diff --git a/cronjobs/pplns_payout.php b/cronjobs/pplns_payout.php
index 39ea294a..15e8d6b4 100755
--- a/cronjobs/pplns_payout.php
+++ b/cronjobs/pplns_payout.php
@@ -46,7 +46,9 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
// We support some dynamic share targets but fall back to our fixed value
// Re-calculate after each run due to re-targets in this loop
if ($config['pplns']['shares']['type'] == 'blockavg' && $block->getBlockCount() > 0) {
- $pplns_target = round($block->getAvgBlockShares($aBlock['height'], $config['pplns']['blockavg']['blockcount']));
+ $pplns_target = round($block->getAvgBlockShares($aBlock['height'], $config['pplns']['blockavg']['blockcount']));
+ } else if ($config['pplns']['shares']['type'] == 'dynamic' && $block->getBlockCount() > 0) {
+ $pplns_target = round($block->getAvgBlockShares($aBlock['height'], $config['pplns']['blockavg']['blockcount']) * (100 - $config['pplns']['dynamic']['percent'])/100 + $aBlock['shares'] * $config['pplns']['dynamic']['percent']/100);
} else {
$pplns_target = $config['pplns']['shares']['default'];
}
@@ -66,6 +68,8 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
$config['reward_type'] == 'block' ? $dReward = $aBlock['amount'] : $dReward = $config['reward'];
$aRoundAccountShares = $share->getSharesForAccounts($iPreviousShareId, $aBlock['share_id']);
+ $log->logInfo('Shares: ' . $iRoundShares . "\t" . 'Height: ' . $aBlock['height'] . ' Amount: ' . $aBlock['amount'] . "\t" . 'Found by ID: ' . $aBlock['account_id']);
+
if ($iRoundShares >= $pplns_target) {
$log->logDebug("Matching or exceeding PPLNS target of $pplns_target with $iRoundShares");
$iMinimumShareId = $share->getMinimumShareId($pplns_target, $aBlock['share_id']);
@@ -81,7 +85,7 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
foreach($aAccountShares as $key => $aData) {
$iNewRoundShares += $aData['valid'];
}
- $log->logInfo('Adjusting round target to PPLNS target ' . $iNewRoundShares);
+ $log->logInfo('Adjusting round to PPLNS target of ' . $pplns_target . ' shares used ' . $iNewRoundShares);
$iRoundShares = $iNewRoundShares;
} else {
$log->logDebug("Not able to match PPLNS target of $pplns_target with $iRoundShares");
@@ -114,6 +118,24 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
$aAccountShares[$key]['invalid'] += $aArchiveShares[$aData['username']]['invalid'];
}
}
+ // reverse payout
+ if ($config['pplns']['reverse_payout']) {
+ $aSharesData = NULL;
+ foreach($aAccountShares as $key => $aData) {
+ $aSharesData[$aData['username']] = $aData;
+ }
+ // Add users from archive not in current round
+ foreach($aArchiveShares as $key => $aArchData) {
+ if (!array_key_exists($aArchData['account'], $aSharesData)) {
+ $log->logDebug('Adding user ' . $aArchData['account'] . ' to round shares');
+ $log->logDebug(' valid : ' . $aArchData['valid']);
+ $log->logDebug(' invalid : ' . $aArchData['invalid']);
+ $aArchData['username'] = $aArchData['account'];
+ $aSharesData[$aArchData['account']] = $aArchData;
+ }
+ }
+ $aAccountShares = $aSharesData;
+ }
}
// We tried to fill up to PPLNS target, now we need to check the actual shares to properly payout users
foreach($aAccountShares as $key => $aData) {
@@ -162,6 +184,19 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
$log->logError('Failed to update share statistics for ' . $aData['username']);
}
+ // Add PPLNS share statistics
+ foreach ($aAccountShares as $key => $aRoundData) {
+ if ($aRoundData['username'] == $aData['username']){
+ if (@$statistics->getIdShareStatistics($aRoundData, $aBlock['id'])){
+ if (!$statistics->updatePPLNSShareStatistics($aRoundData, $aBlock['id']))
+ $log->logError('Failed to update pplns statistics for ' . $aData['username']);
+ } else {
+ if (!$statistics->insertPPLNSShareStatistics($aRoundData, $aBlock['id']))
+ $log->logError('Failed to insert pplns statistics for ' . $aData['username']);
+ }
+ }
+ }
+
// Add new credit transaction
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit', $aBlock['id']))
$log->logFatal('Failed to insert new Credit transaction to database for ' . $aData['username']);
diff --git a/public/include/classes/roundstats.class.php b/public/include/classes/roundstats.class.php
index 6b187973..1f5ab765 100644
--- a/public/include/classes/roundstats.class.php
+++ b/public/include/classes/roundstats.class.php
@@ -56,20 +56,51 @@ class RoundStats {
return false;
}
+ /**
+ * search for block height
+ **/
+ public function searchForBlockHeight($iHeight=0) {
+ $stmt = $this->mysqli->prepare("
+ SELECT height
+ FROM $this->tableBlocks
+ WHERE height >= ?
+ ORDER BY height ASC
+ LIMIT 1");
+ if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
+ return $result->fetch_object()->height;
+ return false;
+ }
+
+ /**
+ * get next block for stats paging
+ **/
+ public function getNextBlockForStats($iHeight=0, $limit=10) {
+ $stmt = $this->mysqli->prepare("
+ SELECT MAX(x.height) AS height
+ FROM (SELECT height FROM $this->tableBlocks
+ WHERE height >= ?
+ ORDER BY height ASC LIMIT ?) AS x");
+ if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $iHeight, $limit) && $stmt->execute() && $result = $stmt->get_result())
+ return $result->fetch_object()->height;
+ return false;
+ }
+
/**
* Get details for block height
* @param height int Block Height
* @return data array Block information from DB
**/
- public function getDetailsForBlockHeight($iHeight=0, $isAdmin=0) {
+ public function getDetailsForBlockHeight($iHeight=0) {
$stmt = $this->mysqli->prepare("
SELECT
b.id, height, blockhash, amount, confirmations, difficulty, FROM_UNIXTIME(time) as time, shares,
- IF(a.is_anonymous, IF( ? , a.username, 'anonymous'), a.username) AS finder
+ IF(a.is_anonymous, 'anonymous', a.username) AS finder,
+ ROUND((difficulty * 65535) / POW(2, (" . $this->config['difficulty'] . " -16)), 0) AS estshares,
+ (time - (SELECT time FROM $this->tableBlocks WHERE height < ? ORDER BY height DESC LIMIT 1)) AS round_time
FROM $this->tableBlocks as b
LEFT JOIN $this->tableUsers AS a ON b.account_id = a.id
WHERE b.height = ? LIMIT 1");
- if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $isAdmin, $iHeight) && $stmt->execute() && $result = $stmt->get_result())
+ if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iHeight, $iHeight) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_assoc();
return false;
}
@@ -79,10 +110,11 @@ class RoundStats {
* @param height int Block Height
* @return data array Block information from DB
**/
- public function getRoundStatsForAccounts($iHeight=0, $isAdmin=0) {
+ public function getRoundStatsForAccounts($iHeight=0) {
$stmt = $this->mysqli->prepare("
SELECT
- IF(a.is_anonymous, IF( ? , a.username, 'anonymous'), a.username) AS username,
+ a.username,
+ a.is_anonymous,
s.valid,
s.invalid
FROM $this->tableStats AS s
@@ -92,30 +124,71 @@ class RoundStats {
GROUP BY username ASC
ORDER BY valid DESC
");
- if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $isAdmin, $iHeight) && $stmt->execute() && $result = $stmt->get_result())
+ if ($this->checkStmt($stmt) && $stmt->bind_param('i',$iHeight) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
return false;
}
+ /**
+ * Get pplns statistics for round block height
+ * @param height int Block Height
+ * @return data array Block information from DB
+ **/
+ public function getPPLNSRoundStatsForAccounts($iHeight=0) {
+ $stmt = $this->mysqli->prepare("
+ SELECT
+ a.username,
+ a.is_anonymous,
+ s.pplns_valid,
+ s.pplns_invalid
+ FROM $this->tableStats AS s
+ LEFT JOIN $this->tableBlocks AS b ON s.block_id = b.id
+ LEFT JOIN $this->tableUsers AS a ON a.id = s.account_id
+ WHERE b.height = ?
+ GROUP BY username ASC
+ ORDER BY pplns_valid DESC
+ ");
+ if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
+ return $result->fetch_all(MYSQLI_ASSOC);
+ return false;
+ }
+
+ /**
+ * Get total valid pplns shares for block height
+ **/
+ public function getPPLNSRoundShares($iHeight=0) {
+ $stmt = $this->mysqli->prepare("
+ SELECT
+ SUM(s.pplns_valid) AS pplns_valid
+ FROM $this->tableStats AS s
+ LEFT JOIN $this->tableBlocks AS b ON s.block_id = b.id
+ WHERE b.height = ?
+ ");
+ if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
+ return $result->fetch_object()->pplns_valid;
+ return false;
+ }
+
/**
* Get all transactions for round block height for admin
* @param height int Block Height
* @return data array Block round transactions
**/
- public function getAllRoundTransactions($iHeight=0, $admin) {
+ public function getAllRoundTransactions($iHeight=0) {
$this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare("
SELECT
t.id AS id,
- IF(a.is_anonymous, IF( ? , a.username, 'anonymous'), a.username) AS username,
+ a.username AS username,
+ a.is_anonymous,
t.type AS type,
t.amount AS amount
FROM $this->tableTrans AS t
LEFT JOIN $this->tableBlocks AS b ON t.block_id = b.id
LEFT JOIN $this->tableUsers AS a ON t.account_id = a.id
- WHERE b.height = ?
- ORDER BY id ASC");
- if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $admin, $iHeight) && $stmt->execute() && $result = $stmt->get_result())
+ WHERE b.height = ? AND t.type = 'Credit'
+ ORDER BY amount DESC");
+ if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
$this->debug->append('Unable to fetch transactions');
return false;
diff --git a/public/include/classes/statistics.class.php b/public/include/classes/statistics.class.php
index 8fd80aa9..3f608701 100644
--- a/public/include/classes/statistics.class.php
+++ b/public/include/classes/statistics.class.php
@@ -77,6 +77,32 @@ class Statistics {
return false;
}
+ /**
+ * Get our last $limit blocks found by height
+ * @param limit int Last limit blocks
+ * @return array
+ **/
+ public function getBlocksFoundHeight($iHeight=0, $limit=10) {
+ $this->debug->append("STA " . __METHOD__, 4);
+ if ($data = $this->memcache->get(__FUNCTION__ . $iHeight . $limit)) return $data;
+ $stmt = $this->mysqli->prepare("
+ SELECT
+ b.*,
+ a.username AS finder,
+ a.is_anonymous AS is_anonymous,
+ ROUND((difficulty * 65535) / POW(2, (" . $this->config['difficulty'] . " -16)), 0) AS estshares
+ FROM " . $this->block->getTableName() . " AS b
+ LEFT JOIN " . $this->user->getTableName() . " AS a
+ ON b.account_id = a.id
+ WHERE b.height <= ?
+ ORDER BY height DESC LIMIT ?");
+ if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $iHeight, $limit) && $stmt->execute() && $result = $stmt->get_result())
+ return $this->memcache->setCache(__FUNCTION__ . $iHeight . $limit, $result->fetch_all(MYSQLI_ASSOC), 5);
+ // Catchall
+ $this->debug->append("Failed to find blocks:" . $this->mysqli->error);
+ return false;
+ }
+
/**
* Currently the only function writing to the database
* Stored per block user statistics of valid and invalid shares
@@ -93,6 +119,44 @@ class Statistics {
return false;
}
+ /**
+ * update user statistics of valid and invalid pplns shares
+ **/
+ public function updatePPLNSShareStatistics($aStats, $iBlockId) {
+ $this->debug->append("STA " . __METHOD__, 4);
+ $stmt = $this->mysqli->prepare("
+ UPDATE $this->table SET pplns_valid = ?, pplns_invalid = ? WHERE account_id = ? AND block_id = ?");
+ if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $aStats['valid'], $aStats['invalid'], $aStats['id'], $iBlockId) && $stmt->execute()) return true;
+ // Catchall
+ $this->debug->append("Failed to update pplns share stats: " . $this->mysqli->error);
+ return false;
+ }
+
+ /**
+ * insert user statistics of valid and invalid pplns shares "rbpplns"
+ **/
+ public function insertPPLNSShareStatistics($aStats, $iBlockId) {
+ $this->debug->append("STA " . __METHOD__, 4);
+ $stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, valid, invalid, pplns_valid, pplns_invalid, block_id) VALUES (?, 0, 0, ?, ?, ?)");
+ if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $aStats['id'], $aStats['valid'], $aStats['invalid'], $iBlockId) && $stmt->execute()) return true;
+ // Catchall
+ $this->debug->append("Failed to insert pplns share stats: " . $this->mysqli->error);
+ return false;
+ }
+
+ /**
+ * Fetch the share ID from stats for rbpplns
+ **/
+ function getIdShareStatistics($aStats, $iBlockId) {
+ $stmt = $this->mysqli->prepare("
+ SELECT id AS id FROM $this->table
+ WHERE account_id = ? AND block_id = ?
+ ");
+ if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $aStats['id'], $iBlockId) && $stmt->execute() && $result = $stmt->get_result())
+ return $result->fetch_object()->id;
+ return false;
+ }
+
/**
* Get our current pool hashrate for the past 10 minutes across both
* shares and shares_archive table
@@ -196,7 +260,6 @@ class Statistics {
$data['share_id'] = 0;
$data['data'] = array();
}
- $data['last_update'] = time();
$stmt = $this->mysqli->prepare("
SELECT
ROUND(IFNULL(SUM(IF(our_result='Y', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS valid,
@@ -246,12 +309,14 @@ class Statistics {
if ($data = $this->memcache->get(STATISTICS_ALL_USER_SHARES)) {
if (array_key_exists($account_id, $data['data']))
return $data['data'][$account_id];
+ // We have no cached value, we return defaults
+ return array('valid' => 0, 'invalid' => 0, 'donate_percent' => 0, 'is_anonymous' => 0);
}
- // if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
+ if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
$stmt = $this->mysqli->prepare("
SELECT
- ROUND(IFNULL(SUM(IF(our_result='Y', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0), 0) AS valid,
- ROUND(IFNULL(SUM(IF(our_result='N', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0), 0) AS invalid
+ ROUND(IFNULL(SUM(IF(our_result='Y', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS valid,
+ ROUND(IFNULL(SUM(IF(our_result='N', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS invalid
FROM " . $this->share->getTableName() . " AS s,
" . $this->user->getTableName() . " AS u
WHERE
diff --git a/public/include/config/admin_settings.inc.php b/public/include/config/admin_settings.inc.php
index e85b9480..c56bf623 100644
--- a/public/include/config/admin_settings.inc.php
+++ b/public/include/config/admin_settings.inc.php
@@ -123,6 +123,13 @@ $aSettings['statistics'][] = array(
'name' => 'statistics_block_count', 'value' => $setting->getValue('statistics_block_count'),
'tooltip' => 'Blocks to fetch for the block statistics page.'
);
+$aSettings['statistics'][] = array(
+ 'display' => 'Show block average', 'type' => 'select',
+ 'options' => array( 0 => 'No', 1 => 'Yes' ),
+ 'default' => 0,
+ 'name' => 'show_block_average', 'value' => $setting->getValue('show_block_average'),
+ 'tooltip' => 'Show block average in block statistics page.'
+);
$aSettings['statistics'][] = array(
'display' => 'Pool Hashrate Modifier', 'type' => 'select',
'options' => array( '1' => 'KH/s', '0.001' => 'MH/s', '0.000001' => 'GH/s' ),
@@ -165,13 +172,6 @@ $aSettings['acl'][] = array(
'name' => 'acl_round_statistics', 'value' => $setting->getValue('acl_round_statistics'),
'tooltip' => 'Make the round statistics page private (users only) or public.'
);
-$aSettings['acl'][] = array(
- 'display' => 'Round Transactions', 'type' => 'select',
- 'options' => array( 0 => 'Admins', 1 => 'Public'),
- 'default' => 0,
- 'name' => 'acl_round_transactions', 'value' => $setting->getValue('acl_round_transactions'),
- 'tooltip' => 'Display all transactions regardless of admin status.'
-);
$aSettings['system'][] = array(
'display' => 'Disable e-mail confirmations', 'type' => 'select',
'options' => array( 0 => 'No', 1 => 'Yes' ),
diff --git a/public/include/config/global.inc.dist.php b/public/include/config/global.inc.dist.php
index 941f57b0..b9cfda0d 100644
--- a/public/include/config/global.inc.dist.php
+++ b/public/include/config/global.inc.dist.php
@@ -231,9 +231,20 @@ $config['fees'] = 0;
* type = `blockavg`
* blockcount = 10
**/
+/**
+ * $config['pplns']['shares']['type'] = 'dynamic';
+ * Dynamic target adjustment allows the blockavg target to adjust faster to share counts
+ * while still tracking round share averages by using a percentage of the current round shares
+ * to alter the pplns blockavg target this is useful with the nature of many alt coins low and fast
+ * adjusting difficulties and quick round times
+ * reverse_payout is useful to even out payouts for fast round times when even steady miners
+ * are missing share submissions for the current round
+**/
$config['pplns']['shares']['default'] = 4000000;
$config['pplns']['shares']['type'] = 'blockavg';
$config['pplns']['blockavg']['blockcount'] = 10;
+$config['pplns']['reverse_payout'] = false; // add user shares from archive even if user not in current round
+$config['pplns']['dynamic']['percent'] = 30; // percentage of round shares factored into block average when using dynamic type
// Pool target difficulty as set in pushpoold configuration file
// Please also read this for stratum: https://github.com/TheSerapher/php-mpos/wiki/FAQ
diff --git a/public/include/pages/statistics/blocks.inc.php b/public/include/pages/statistics/blocks.inc.php
index 116d999d..ce3667cb 100644
--- a/public/include/pages/statistics/blocks.inc.php
+++ b/public/include/pages/statistics/blocks.inc.php
@@ -8,11 +8,71 @@ if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
$debug->append('No cached version available, fetching from backend', 3);
// Grab the last blocks found
$setting->getValue('statistics_block_count') ? $iLimit = $setting->getValue('statistics_block_count') : $iLimit = 20;
- $aBlocksFoundData = $statistics->getBlocksFound($iLimit);
+ if (@$_REQUEST['limit'] && !empty($_REQUEST['limit']) && is_numeric($_REQUEST['limit'])) {
+ $iLimit = $_REQUEST['limit'];
+ if ( $iLimit > 40 )
+ $iLimit = 40;
+ }
+
+ $iHeight = 0;
+ if (@$_REQUEST['next'] && !empty($_REQUEST['height']) && is_numeric($_REQUEST['height'])) {
+ $iHeight = @$roundstats->getNextBlockForStats($_REQUEST['height'], $iLimit);
+ if (!$iHeight) {
+ $iBlock = $block->getLast();
+ $iHeight = $iBlock['height'];
+ }
+ } else if (@$_REQUEST['prev'] && !empty($_REQUEST['height']) && is_numeric($_REQUEST['height'])) {
+ $iHeight = $_REQUEST['height'];
+ } else if (empty($_REQUEST['height'])) {
+ $aBlock = $block->getLast();
+ $iHeight = $aBlock['height'];
+ }
+
+ $test = false;
+ if (@$_REQUEST['test'] && $user->isAdmin($_SESSION['USERDATA']['id'])) {
+ $test = true;
+ $count = 10;
+ $percent = 30;
+ if (@$_REQUEST['count'] && is_numeric($_REQUEST['count']))
+ $count = $_REQUEST['count'];
+ if (@$_REQUEST['percent'] && is_numeric($_REQUEST['percent']))
+ $percent = $_REQUEST['percent'];
+ }
+
+ $aBlocksFoundData = $statistics->getBlocksFoundHeight($iHeight, $iLimit);
+ $use_average = false;
+ if ($config['payout_system'] == 'pplns') {
+ foreach($aBlocksFoundData as $key => $aData) {
+ $aBlocksFoundData[$key]['pplns_shares'] = $roundstats->getPPLNSRoundShares($aData['height']);
+ if ($setting->getValue('show_block_average') && !$test) {
+ $aBlocksFoundData[$key]['block_avg'] = round($block->getAvgBlockShares($aData['height'], $config['pplns']['blockavg']['blockcount']));
+ $use_average = true;
+ }
+ }
+ } else if ($config['payout_system'] == 'prop' || $config['payout_system'] == 'pps') {
+ if ($setting->getValue('show_block_average') && !$test) {
+ foreach($aBlocksFoundData as $key => $aData) {
+ $aBlocksFoundData[$key]['block_avg'] = round($block->getAvgBlockShares($aData['height'], $config['pplns']['blockavg']['blockcount']));
+ $use_average = true;
+ }
+ }
+ }
+ // show test data in graph
+ if ($test) {
+ $use_average = true;
+ foreach($aBlocksFoundData as $key => $aData) {
+ if ($_REQUEST['test'] == 1) {
+ $aBlocksFoundData[$key]['block_avg'] = round($block->getAvgBlockShares($aData['height'], $count));
+ } else if ($_REQUEST['test'] == 2) {
+ $aBlocksFoundData[$key]['block_avg'] = round($block->getAvgBlockShares($aData['height'], $count) * (100 - $percent) / 100 + $aData['shares'] * $percent / 100);
+ }
+ }
+ }
// Propagate content our template
$smarty->assign("BLOCKSFOUND", $aBlocksFoundData);
$smarty->assign("BLOCKLIMIT", $iLimit);
+ $smarty->assign("USEBLOCKAVERAGE", $use_average);
} else {
$debug->append('Using cached page', 3);
}
diff --git a/public/include/pages/statistics/round.inc.php b/public/include/pages/statistics/round.inc.php
index 4c37f749..bcc53ebe 100644
--- a/public/include/pages/statistics/round.inc.php
+++ b/public/include/pages/statistics/round.inc.php
@@ -6,32 +6,57 @@ if (!defined('SECURITY')) die('Hacking attempt');
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
$debug->append('No cached version available, fetching from backend', 3);
- if (@$_REQUEST['next'] && !empty($_REQUEST['height'])) {
- $iKey = $roundstats->getNextBlock($_REQUEST['height']);
- } else if (@$_REQUEST['prev'] && !empty($_REQUEST['height'])) {
- $iKey = $roundstats->getPreviousBlock($_REQUEST['height']);
- } else {
-
- if (empty($_REQUEST['height'])) {
- $iBlock = $block->getLast();
- $iKey = $iBlock['height'];
- } else {
- $iKey = $_REQUEST['height'];
- }
+ if (@$_REQUEST['search']) {
+ $_REQUEST['height'] = $roundstats->searchForBlockHeight($_REQUEST['search']);
}
- $aDetailsForBlockHeight = $roundstats->getDetailsForBlockHeight($iKey, $user->isAdmin(@$_SESSION['USERDATA']['id']));
- $aRoundShareStats = $roundstats->getRoundStatsForAccounts($iKey, $user->isAdmin(@$_SESSION['USERDATA']['id']));
-
- if ($user->isAdmin(@$_SESSION['USERDATA']['id']) || $setting->getValue('acl_round_transactions')) {
- $aUserRoundTransactions = $roundstats->getAllRoundTransactions($iKey, @$_SESSION['USERDATA']['id']);
+ if (@$_REQUEST['next'] && !empty($_REQUEST['height'])) {
+ $iHeight = @$roundstats->getNextBlock($_REQUEST['height']);
+ if (!$iHeight) {
+ $iBlock = $block->getLast();
+ $iHeight = $iBlock['height'];
+ }
+ } else if (@$_REQUEST['prev'] && !empty($_REQUEST['height'])) {
+ $iHeight = $roundstats->getPreviousBlock($_REQUEST['height']);
+ } else if (empty($_REQUEST['height'])) {
+ $iBlock = $block->getLast();
+ $iHeight = $iBlock['height'];
} else {
- $aUserRoundTransactions = $roundstats->getUserRoundTransactions($iKey, @$_SESSION['USERDATA']['id']);
+ $iHeight = $_REQUEST['height'];
+ }
+ $_REQUEST['height'] = $iHeight;
+
+ $iPPLNSShares = 0;
+ $aDetailsForBlockHeight = $roundstats->getDetailsForBlockHeight($iHeight);
+ $aRoundShareStats = $roundstats->getRoundStatsForAccounts($iHeight);
+
+ if ($config['payout_system'] == 'pplns') {
+ $aUserRoundTransactions = $roundstats->getAllRoundTransactions($iHeight);
+ foreach($aRoundShareStats as $key => $aData) {
+ $aSharesData[$aData['username']] = $aData;
+ }
+ $aPPLNSRoundShares = $roundstats->getPPLNSRoundStatsForAccounts($iHeight);
+ foreach($aPPLNSRoundShares as $key => $aData) {
+ $iPPLNSShares += $aData['pplns_valid'];
+ }
+ $block_avg = $block->getAvgBlockShares($iHeight, $config['pplns']['blockavg']['blockcount']);
+ } else if ($config['payout_system'] == 'prop') {
+ $aUserRoundTransactions = $roundstats->getAllRoundTransactions($iHeight);
}
// Propagate content our template
$smarty->assign('BLOCKDETAILS', $aDetailsForBlockHeight);
$smarty->assign('ROUNDSHARES', $aRoundShareStats);
- $smarty->assign("ROUNDTRANSACTIONS", $aUserRoundTransactions);
+
+ if ($config['payout_system'] == 'pplns') {
+ $smarty->assign('SHARESDATA', $aSharesData);
+ $smarty->assign('PPLNSROUNDSHARES', $aPPLNSRoundShares);
+ $smarty->assign("PPLNSSHARES", $iPPLNSShares);
+ $smarty->assign("BLOCKAVGCOUNT", $config['pplns']['blockavg']['blockcount']);
+ $smarty->assign("BLOCKAVERAGE", $block_avg );
+ $smarty->assign("ROUNDTRANSACTIONS", $aUserRoundTransactions);
+ } else if ($config['payout_system'] == 'prop') {
+ $smarty->assign("ROUNDTRANSACTIONS", $aUserRoundTransactions);
+ }
} else {
$debug->append('Using cached page', 3);
}
diff --git a/public/templates/mmcFE/statistics/blocks/default.tpl b/public/templates/mmcFE/statistics/blocks/default.tpl
index 5929524d..1ab96c10 100644
--- a/public/templates/mmcFE/statistics/blocks/default.tpl
+++ b/public/templates/mmcFE/statistics/blocks/default.tpl
@@ -21,13 +21,38 @@
{$BLOCKSFOUND[block].shares}
{/section}
+ {if $GLOBAL.config.payout_system == 'pplns'}
+ PPLNS
+{section block $BLOCKSFOUND step=-1}
+ {$BLOCKSFOUND[block].pplns_shares}
+{/section}
+ {/if}
+ {if $USEBLOCKAVERAGE}
+ Average
+{section block $BLOCKSFOUND step=-1}
+ {$BLOCKSFOUND[block].block_avg}
+{/section}
+ {/if}
The graph above illustrates N shares to find a block vs. E Shares expected to find a block based on
target and network difficulty and assuming a zero variance scenario.
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{include file="global/block_footer.tpl"}
{include file="global/block_header.tpl" BLOCK_HEADER="Last $BLOCKLIMIT Blocks Found" BLOCK_STYLE="clear:none;"}
@@ -42,6 +67,7 @@ target and network difficulty and assuming a zero variance scenario.
Difficulty
Amount
Expected Shares
+ {if $GLOBAL.config.payout_system == 'pplns'}PPLNS Shares {/if}
Actual Shares
Percentage
@@ -51,9 +77,11 @@ target and network difficulty and assuming a zero variance scenario.
{assign var=totalexpectedshares value=0}
{assign var=totalshares value=0}
{assign var=totalpercentage value=0}
+{assign var=pplnsshares value=0}
{section block $BLOCKSFOUND}
{assign var="totalshares" value=$totalshares+$BLOCKSFOUND[block].shares}
{assign var="count" value=$count+1}
+ {if $GLOBAL.config.payout_system == 'pplns'}{assign var="pplnsshares" value=$pplnsshares+$BLOCKSFOUND[block].pplns_shares}{/if}
{$BLOCKSFOUND[block].height}
@@ -62,7 +90,7 @@ target and network difficulty and assuming a zero variance scenario.
{else if $BLOCKSFOUND[block].confirmations == -1}
Orphan
{else}{$GLOBAL.confirmations - $BLOCKSFOUND[block].confirmations} left{/if}
- {if $BLOCKSFOUND[block].is_anonymous|default:"0" == 1 && $GLOBAL.userdata.is_admin|default:"0" == 0}anonymous{else}{$BLOCKSFOUND[block].finder|default:"unknown"|escape}{/if}
+ {if $BLOCKSFOUND[block].is_anonymous|default:"0" == 1}anonymous{else}{$BLOCKSFOUND[block].finder|default:"unknown"|escape}{/if}
{$BLOCKSFOUND[block].time|date_format:"%d/%m %H:%M:%S"}
{$BLOCKSFOUND[block].difficulty|number_format:"8"}
{$BLOCKSFOUND[block].amount|number_format:"2"}
@@ -70,6 +98,7 @@ target and network difficulty and assuming a zero variance scenario.
{$BLOCKSFOUND[block].estshares|number_format}
{assign var="totalexpectedshares" value=$totalexpectedshares+$BLOCKSFOUND[block].estshares}
+ {if $GLOBAL.config.payout_system == 'pplns'}{$BLOCKSFOUND[block].pplns_shares|number_format} {/if}
{$BLOCKSFOUND[block].shares|number_format}
{math assign="percentage" equation="shares / estshares * 100" shares=$BLOCKSFOUND[block].shares estshares=$BLOCKSFOUND[block].estshares}
@@ -82,6 +111,7 @@ target and network difficulty and assuming a zero variance scenario.
Totals
{$totalexpectedshares|number_format}
+ {if $GLOBAL.config.payout_system == 'pplns'}{$pplnsshares|number_format} {/if}
{$totalshares|number_format}
{($totalpercentage / $count)|number_format:"2"}
diff --git a/public/templates/mmcFE/statistics/round/block_stats.tpl b/public/templates/mmcFE/statistics/round/block_stats.tpl
index 75b33950..dbd37bae 100644
--- a/public/templates/mmcFE/statistics/round/block_stats.tpl
+++ b/public/templates/mmcFE/statistics/round/block_stats.tpl
@@ -1,16 +1,24 @@
{include file="global/block_header.tpl" ALIGN="left" BLOCK_STYLE="width: 100%" BLOCK_HEADER="Block Stats" STYLE="padding-left:5px;padding-right:5px;"}
-
+
+
+
+
+
+
+
+
+
+
- Name
- Value
+ Block Round Statistics
ID
- {$BLOCKDETAILS.id|default:"0"}
+ {$BLOCKDETAILS.id|number_format:"0"|default:"0"}
Height
@@ -26,7 +34,12 @@
Confirmations
- {$BLOCKDETAILS.confirmations|default:"0"}
+ {if $BLOCKDETAILS.confirmations >= $GLOBAL.confirmations}
+ Confirmed
+ {else if $BLOCKDETAILS.confirmations == -1}
+ Orphan
+ {else if $BLOCKDETAILS.confirmations == 0}0
+ {else}{($GLOBAL.confirmations - $BLOCKDETAILS.confirmations)|default:"0"} left{/if}
Difficulty
@@ -38,7 +51,7 @@
Shares
- {$BLOCKDETAILS.shares|default:"0"}
+ {$BLOCKDETAILS.shares|number_format:"0"|default:"0"}
Finder
@@ -47,19 +60,12 @@
-
-
-
-
-
-
-
-
-
{include file="global/block_footer.tpl"}
+
diff --git a/public/templates/mmcFE/statistics/round/default.tpl b/public/templates/mmcFE/statistics/round/default.tpl
index 7098eb06..c233a827 100644
--- a/public/templates/mmcFE/statistics/round/default.tpl
+++ b/public/templates/mmcFE/statistics/round/default.tpl
@@ -1,9 +1,14 @@
{include file="global/block_header.tpl" BLOCK_HEADER="Round Statistics" BLOCK_STYLE="clear:none;"}
-{include file="statistics/round/block_stats.tpl"}
-
-{include file="statistics/round/round_transactions.tpl"}
-
-{include file="statistics/round/round_shares.tpl"}
+{if $GLOBAL.config.payout_system == 'pplns'}
+ {include file="statistics/round/pplns_block_stats.tpl"}
+ {include file="statistics/round/round_shares.tpl"}
+ {include file="statistics/round/pplns_round_shares.tpl"}
+ {include file="statistics/round/pplns_transactions.tpl"}
+{else}
+ {include file="statistics/round/block_stats.tpl"}
+ {include file="statistics/round/round_shares.tpl"}
+ {include file="statistics/round/round_transactions.tpl"}
+{/if}
{include file="global/block_footer.tpl"}
diff --git a/public/templates/mmcFE/statistics/round/pplns_block_stats.tpl b/public/templates/mmcFE/statistics/round/pplns_block_stats.tpl
new file mode 100644
index 00000000..f23facb3
--- /dev/null
+++ b/public/templates/mmcFE/statistics/round/pplns_block_stats.tpl
@@ -0,0 +1,118 @@
+{include file="global/block_header.tpl" ALIGN="left" BLOCK_STYLE="width: 100%" BLOCK_HEADER="Block Stats" STYLE="padding-left:5px;padding-right:5px;"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Block Round Statistics
+
+
+
+
+ ID
+ {$BLOCKDETAILS.id|number_format:"0"|default:"0"}
+
+
+ Height
+ {if ! $GLOBAL.website.blockexplorer.disabled}
+ {$BLOCKDETAILS.height}
+ {else}
+ {$BLOCKDETAILS.height}
+ {/if}
+
+
+ Amount
+ {$BLOCKDETAILS.amount|default:"0"}
+
+
+ Confirmations
+ {if $BLOCKDETAILS.confirmations >= $GLOBAL.confirmations}
+ Confirmed
+ {else if $BLOCKDETAILS.confirmations == -1}
+ Orphan
+ {else if $BLOCKDETAILS.confirmations == 0}0
+ {else}{($GLOBAL.confirmations - $BLOCKDETAILS.confirmations)|default:"0"} left{/if}
+
+
+
+ Difficulty
+ {$BLOCKDETAILS.difficulty|default:"0"}
+
+
+ Time
+ {$BLOCKDETAILS.time|default:"0"}
+
+
+ Shares
+ {$BLOCKDETAILS.shares|number_format:"0"|default:"0"}
+
+
+ Finder
+ {$BLOCKDETAILS.finder|default:"0"}
+
+
+
+{assign var=percentage value=0}
+{assign var=percentage1 value=0}
+{assign var=percentage2 value=0}
+
+
+
+ PPLNS Round Statistics
+
+
+
+
+ PPLNS Shares
+ {$PPLNSSHARES|number_format:"0"|default:"0"}
+
+
+ Estimated Shares
+ {$BLOCKDETAILS.estshares|number_format|default:"0"}
+
+
+ Target Variance
+ {if $PPLNSSHARES > 0}{math assign="percentage" equation=(($BLOCKDETAILS.estshares / $PPLNSSHARES) * 100)}{/if}{$percentage|number_format:"2"} %
+
+
+ Block Average
+ {$BLOCKAVERAGE|number_format:"0"|default:"0"}
+
+
+ Average Efficiency
+ {if $BLOCKAVERAGE > 0 && $BLOCKDETAILS.estshares > 0}{math assign="percentage2" equation=(($BLOCKDETAILS.estshares / $BLOCKAVERAGE) * 100)}{/if}{$percentage2|number_format:"2"} %
+
+
+ Target Rounds
+ {$BLOCKAVGCOUNT|number_format:"0"|default:"0"}
+
+
+ Seconds This Round
+ {$BLOCKDETAILS.round_time|number_format:"0"|default:"0"}
+
+
+ Round Variance
+ {if $PPLNSSHARES > 0}{math assign="percentage1" equation=(($BLOCKDETAILS.shares / $PPLNSSHARES) * 100)}{/if}{$percentage1|number_format:"2"} %
+
+
+
+
+{include file="global/block_footer.tpl"}
+
diff --git a/public/templates/mmcFE/statistics/round/pplns_round_shares.tpl b/public/templates/mmcFE/statistics/round/pplns_round_shares.tpl
new file mode 100644
index 00000000..52c47f9c
--- /dev/null
+++ b/public/templates/mmcFE/statistics/round/pplns_round_shares.tpl
@@ -0,0 +1,29 @@
+{include file="global/block_header.tpl" ALIGN="right" BLOCK_HEADER="PPLNS Round Shares" }
+
+
+
+
+ Rank
+ User Name
+ Valid
+ Invalid
+ Invalid %
+
+
+
+{assign var=rank value=1}
+{assign var=listed value=0}
+{section contrib $PPLNSROUNDSHARES}
+
+ {$rank++}
+ {if $PPLNSROUNDSHARES[contrib].is_anonymous|default:"0" == 1}anonymous{else}{$PPLNSROUNDSHARES[contrib].username|escape}{/if}
+ {$PPLNSROUNDSHARES[contrib].pplns_valid|number_format}
+ {$PPLNSROUNDSHARES[contrib].pplns_invalid|number_format}
+ {if $PPLNSROUNDSHARES[contrib].pplns_invalid > 0 && $PPLNSROUNDSHARES[contrib].pplns_valid > 0}{($PPLNSROUNDSHARES[contrib].pplns_invalid / $PPLNSROUNDSHARES[contrib].pplns_valid * 100)|number_format:"2"|default:"0"}{else}0.00{/if}
+
+{/section}
+
+
+
+{include file="global/block_footer.tpl"}
+
diff --git a/public/templates/mmcFE/statistics/round/pplns_transactions.tpl b/public/templates/mmcFE/statistics/round/pplns_transactions.tpl
new file mode 100644
index 00000000..4052a24b
--- /dev/null
+++ b/public/templates/mmcFE/statistics/round/pplns_transactions.tpl
@@ -0,0 +1,34 @@
+{include file="global/block_header.tpl" ALIGN="left" BLOCK_STYLE="width: 100%" BLOCK_HEADER="Round Transactions"}
+
+
+
+
+ User Name
+ Round Shares
+ Round %
+ PPLNS Shares
+ PPLNS Round %
+ Variance
+ Amount
+
+
+
+{assign var=percentage1 value=0}
+{section txs $ROUNDTRANSACTIONS}
+
+ {if $ROUNDTRANSACTIONS[txs].is_anonymous|default:"0" == 1}anonymous{else}{$ROUNDTRANSACTIONS[txs].username|escape}{/if}
+ {$SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid|number_format}
+ {if $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid > 0 }{(( 100 / $BLOCKDETAILS.shares) * $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid)|number_format:"2"}{else}0.00{/if}
+ {$PPLNSROUNDSHARES[txs].pplns_valid|number_format|default:"0"}
+ {if $PPLNSROUNDSHARES[txs].pplns_valid > 0 }{(( 100 / $PPLNSSHARES) * $PPLNSROUNDSHARES[txs].pplns_valid)|number_format:"2"|default:"0"}{else}0{/if}
+ {if $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid > 0 && $PPLNSROUNDSHARES[txs].pplns_valid > 0}{math assign="percentage1" equation=(100 / ((( 100 / $BLOCKDETAILS.shares) * $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid) / (( 100 / $PPLNSSHARES) * $PPLNSROUNDSHARES[txs].pplns_valid)))}{else if $PPLNSROUNDSHARES[txs].pplns_valid == 0}{assign var=percentage1 value=0}{else}{assign var=percentage1 value=100}{/if}
+ {$percentage1|number_format:"2"}
+ {$ROUNDTRANSACTIONS[txs].amount|default:"0"|number_format:"8"}
+ {assign var=percentage1 value=0}
+
+{/section}
+
+
+
+{include file="global/block_footer.tpl"}
+
diff --git a/public/templates/mmcFE/statistics/round/round_shares.tpl b/public/templates/mmcFE/statistics/round/round_shares.tpl
index fa09ca0a..63a03a89 100644
--- a/public/templates/mmcFE/statistics/round/round_shares.tpl
+++ b/public/templates/mmcFE/statistics/round/round_shares.tpl
@@ -12,17 +12,17 @@
{assign var=rank value=1}
-{assign var=listed value=0}
{section contrib $ROUNDSHARES}
-
+
{$rank++}
- {if $ROUNDSHARES[contrib].is_anonymous|default:"0" == 1 && $GLOBAL.userdata.is_admin|default:"0" == 0}anonymous{else}{$ROUNDSHARES[contrib].username|escape}{/if}
+ {if $ROUNDSHARES[contrib].is_anonymous|default:"0" == 1}anonymous{else}{$ROUNDSHARES[contrib].username|escape}{/if}
{$ROUNDSHARES[contrib].valid|number_format}
{$ROUNDSHARES[contrib].invalid|number_format}
- {($ROUNDSHARES[contrib].invalid / $ROUNDSHARES[contrib].valid * 100)|number_format:"2"}
+ {if $ROUNDSHARES[contrib].invalid > 0 }{($ROUNDSHARES[contrib].invalid / $ROUNDSHARES[contrib].valid * 100)|number_format:"2"|default:"0"}{else}0.00{/if}
{/section}
{include file="global/block_footer.tpl"}
+
diff --git a/public/templates/mmcFE/statistics/round/round_transactions.tpl b/public/templates/mmcFE/statistics/round/round_transactions.tpl
index ecb4ea75..39f47697 100644
--- a/public/templates/mmcFE/statistics/round/round_transactions.tpl
+++ b/public/templates/mmcFE/statistics/round/round_transactions.tpl
@@ -3,18 +3,18 @@
- Tx Id
User Name
Type
+ Round %
Amount
{section txs $ROUNDTRANSACTIONS}
-
- {$ROUNDTRANSACTIONS[txs].id|default:"0"}
- {$ROUNDTRANSACTIONS[txs].username|escape}
+
+ {if $ROUNDTRANSACTIONS[txs].is_anonymous|default:"0" == 1}anonymous{else}{$ROUNDTRANSACTIONS[txs].username|escape}{/if}
{$ROUNDTRANSACTIONS[txs].type|default:""}
+ {(( 100 / $BLOCKDETAILS.shares) * $ROUNDSHARES[txs].valid)|number_format:"2"}
{$ROUNDTRANSACTIONS[txs].amount|default:"0"|number_format:"8"}
{/section}
@@ -22,3 +22,4 @@
{include file="global/block_footer.tpl"}
+
diff --git a/public/templates/mpos/statistics/blocks/default.tpl b/public/templates/mpos/statistics/blocks/default.tpl
index 02bcaf21..eb87227b 100644
--- a/public/templates/mpos/statistics/blocks/default.tpl
+++ b/public/templates/mpos/statistics/blocks/default.tpl
@@ -22,6 +22,30 @@
{$BLOCKSFOUND[block].shares}
{/section}
+ {if $GLOBAL.config.payout_system == 'pplns'}
+ PPLNS
+{section block $BLOCKSFOUND step=-1}
+ {$BLOCKSFOUND[block].pplns_shares}
+{/section}
+ {/if}
+ {if $USEBLOCKAVERAGE}
+ Average
+{section block $BLOCKSFOUND step=-1}
+ {$BLOCKSFOUND[block].block_avg}
+{/section}
+ {/if}
+
+
+
@@ -44,6 +68,7 @@
Difficulty
Amount
Expected Shares
+{if $GLOBAL.config.payout_system == 'pplns'}PPLNS Shares {/if}
Actual Shares
Percentage
@@ -53,9 +78,11 @@
{assign var=totalexpectedshares value=0}
{assign var=totalshares value=0}
{assign var=totalpercentage value=0}
+{assign var=pplnsshares value=0}
{section block $BLOCKSFOUND}
{assign var="totalshares" value=$totalshares+$BLOCKSFOUND[block].shares}
{assign var="count" value=$count+1}
+ {if $GLOBAL.config.payout_system == 'pplns'}{assign var="pplnsshares" value=$pplnsshares+$BLOCKSFOUND[block].pplns_shares}{/if}
{if ! $GLOBAL.website.blockexplorer.disabled}
{$BLOCKSFOUND[block].height}
@@ -71,7 +98,7 @@
{$GLOBAL.confirmations - $BLOCKSFOUND[block].confirmations} left
{/if}
- {if $BLOCKSFOUND[block].is_anonymous|default:"0" == 1 && $GLOBAL.userdata.is_admin|default:"0" == 0}anonymous{else}{$BLOCKSFOUND[block].finder|default:"unknown"|escape}{/if}
+ {if $BLOCKSFOUND[block].is_anonymous|default:"0" == 1}anonymous{else}{$BLOCKSFOUND[block].finder|default:"unknown"|escape}{/if}
{$BLOCKSFOUND[block].time|date_format:"%d/%m %H:%M:%S"}
{$BLOCKSFOUND[block].difficulty|number_format:"2"}
{$BLOCKSFOUND[block].amount|number_format:"2"}
@@ -80,6 +107,7 @@
{assign var="totalexpectedshares" value=$totalexpectedshares+$estshares}
{$estshares|number_format}
+{if $GLOBAL.config.payout_system == 'pplns'}{$BLOCKSFOUND[block].pplns_shares|number_format} {/if}
{$BLOCKSFOUND[block].shares|number_format}
{math assign="percentage" equation="shares / estshares * 100" shares=$BLOCKSFOUND[block].shares estshares=$estshares}
@@ -91,8 +119,9 @@
Totals
{$totalexpectedshares|number_format}
+ {if $GLOBAL.config.payout_system == 'pplns'}{$pplnsshares|number_format} {/if}
{$totalshares|number_format}
- {if $count > 0}{($totalpercentage / $count)|number_format:"2"} {else}0{/if}
+ {if $count > 0}{($totalshares / $totalexpectedshares * 100)|number_format:"2"} {else}0{/if}
diff --git a/public/templates/mpos/statistics/round/block_stats.tpl b/public/templates/mpos/statistics/round/block_stats.tpl
index c6f21d25..c4c4c0d8 100644
--- a/public/templates/mpos/statistics/round/block_stats.tpl
+++ b/public/templates/mpos/statistics/round/block_stats.tpl
@@ -3,46 +3,39 @@
-
+
-
+
ID
- {$BLOCKDETAILS.id|default:"0"}
-
-
+ {$BLOCKDETAILS.id|number_format:"0"|default:"0"}
Height
{if ! $GLOBAL.website.blockexplorer.disabled}
- {$BLOCKDETAILS.height}
+ {$BLOCKDETAILS.height|number_format:"0"|default:"0"}
{else}
- {$BLOCKDETAILS.height}
+ {$BLOCKDETAILS.height|number_format:"0"|default:"0"}
{/if}
-
-
Amount
- {$BLOCKDETAILS.amount|default:"0"}
+ {$BLOCKDETAILS.amount|number_format|default:"0"}
+ Confirmations
+ {if $BLOCKDETAILS.confirmations >= $GLOBAL.confirmations}
+ Confirmed
+ {else if $BLOCKDETAILS.confirmations == -1}
+ Orphan
+ {else if $BLOCKDETAILS.confirmations == 0}0
+ {else}{($GLOBAL.confirmations - $BLOCKDETAILS.confirmations)|default:"0"} left{/if}
- Confirmations
- {$BLOCKDETAILS.confirmations|default:"0"}
-
-
Difficulty
{$BLOCKDETAILS.difficulty|default:"0"}
-
-
Time
{$BLOCKDETAILS.time|default:"0"}
-
-
Shares
- {$BLOCKDETAILS.shares|default:"0"}
-
-
+ {$BLOCKDETAILS.shares|number_format:"0"|default:"0"}
Finder
{$BLOCKDETAILS.finder|default:"0"}
@@ -50,10 +43,10 @@
-
diff --git a/public/templates/mpos/statistics/round/default.tpl b/public/templates/mpos/statistics/round/default.tpl
index d1379d61..ede8e0de 100644
--- a/public/templates/mpos/statistics/round/default.tpl
+++ b/public/templates/mpos/statistics/round/default.tpl
@@ -1,3 +1,13 @@
-{include file="statistics/round/block_stats.tpl"}
-{include file="statistics/round/round_transactions.tpl"}
-{include file="statistics/round/round_shares.tpl"}
+{if $GLOBAL.config.payout_system == 'pplns'}
+ {include file="statistics/round/pplns_block_stats.tpl"}
+ {include file="statistics/round/pplns_transactions.tpl"}
+ {include file="statistics/round/round_shares.tpl"}
+ {include file="statistics/round/pplns_round_shares.tpl"}
+{else if $GLOBAL.config.payout_system == 'prop'}
+ {include file="statistics/round/block_stats.tpl"}
+ {include file="statistics/round/round_shares.tpl"}
+ {include file="statistics/round/round_transactions.tpl"}
+{else}
+ {include file="statistics/round/block_stats.tpl"}
+ {include file="statistics/round/round_shares.tpl"}
+{/if}
diff --git a/public/templates/mpos/statistics/round/pplns_block_stats.tpl b/public/templates/mpos/statistics/round/pplns_block_stats.tpl
new file mode 100644
index 00000000..d330b7fe
--- /dev/null
+++ b/public/templates/mpos/statistics/round/pplns_block_stats.tpl
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+ Block Statistics
+ PPLNS Round Statistics
+
+
+
+ ID
+ {$BLOCKDETAILS.id|number_format:"0"|default:"0"}
+ PPLNS Shares
+ {$PPLNSSHARES|number_format:"0"|default:"0"}
+
+
+ Height
+ {if ! $GLOBAL.website.blockexplorer.disabled}
+ {$BLOCKDETAILS.height|number_format:"0"|default:"0"}
+ {else}
+ {$BLOCKDETAILS.height|number_format:"0"|default:"0"}
+ {/if}
+ Estimated Shares
+ {$BLOCKDETAILS.estshares|number_format|default:"0"}
+
+
+ Amount
+ {$BLOCKDETAILS.amount|default:"0"}
+ Target Variance
+{assign var=percentage value=0}
+{assign var=percentage1 value=0}
+{assign var=percentage2 value=0}
+ {if $PPLNSSHARES > 0}{math assign="percentage" equation=(($BLOCKDETAILS.estshares / $PPLNSSHARES) * 100)}{/if}{$percentage|number_format:"2"} %
+
+
+ Confirmations
+ {if $BLOCKDETAILS.confirmations >= $GLOBAL.confirmations}
+ Confirmed
+ {else if $BLOCKDETAILS.confirmations == -1}
+ Orphan
+ {else if $BLOCKDETAILS.confirmations == 0}0
+ {else}{($GLOBAL.confirmations - $BLOCKDETAILS.confirmations)|default:"0"} left{/if}
+ Block Average
+ {$BLOCKAVERAGE|number_format:"0"|default:"0"}
+
+
+ Difficulty
+ {$BLOCKDETAILS.difficulty|default:"0"}
+ Average Efficiency
+ {if $BLOCKAVERAGE > 0 && $BLOCKDETAILS.estshares > 0}{math assign="percentage2" equation=(($BLOCKDETAILS.estshares / $BLOCKAVERAGE) * 100)}{/if}{$percentage2|number_format:"2"} %
+
+
+ Time
+ {$BLOCKDETAILS.time|default:"0"}
+ Target Rounds
+ {$BLOCKAVGCOUNT|number_format:"0"|default:"0"}
+
+
+ Shares
+ {$BLOCKDETAILS.shares|number_format:"0"|default:"0"}
+ Seconds This Round
+ {$BLOCKDETAILS.round_time|number_format:"0"|default:"0"}
+
+
+ Finder
+ {$BLOCKDETAILS.finder|default:"0"}
+ Round Variance
+ {if $PPLNSSHARES > 0}{math assign="percentage1" equation=(($BLOCKDETAILS.shares / $PPLNSSHARES) * 100)}{/if}{$percentage1|number_format:"2"} %
+
+
+
+
+
diff --git a/public/templates/mpos/statistics/round/pplns_block_stats_small.tpl b/public/templates/mpos/statistics/round/pplns_block_stats_small.tpl
new file mode 100644
index 00000000..0a55b816
--- /dev/null
+++ b/public/templates/mpos/statistics/round/pplns_block_stats_small.tpl
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+ Block Statistics
+ PPLNS Round Statistics
+
+
+
+ ID
+ {$BLOCKDETAILS.id|number_format:"0"|default:"0"}
+ Height
+ {if ! $GLOBAL.website.blockexplorer.disabled}
+ {$BLOCKDETAILS.height|number_format:"0"|default:"0"}
+ {else}
+ {$BLOCKDETAILS.height|number_format:"0"|default:"0"}
+ {/if}
+ PPLNS Shares
+ {$PPLNSSHARES|number_format:"0"|default:"0"}
+ Estimated Shares
+ {$BLOCKDETAILS.estshares|number_format|default:"0"}
+
+
+ Amount
+ {$BLOCKDETAILS.amount|default:"0"}
+ Confirmations
+ {if $BLOCKDETAILS.confirmations >= $GLOBAL.confirmations}
+ Confirmed
+ {else if $BLOCKDETAILS.confirmations == -1}
+ Orphan
+ {else if $BLOCKDETAILS.confirmations == 0}0
+ {else}{($GLOBAL.confirmations - $BLOCKDETAILS.confirmations)|default:"0"} left{/if}
+ Block Average
+ {$BLOCKAVERAGE|number_format:"0"|default:"0"}
+ Average Efficiency
+ {math assign="percentage2" equation=(($BLOCKDETAILS.estshares / $BLOCKAVERAGE) * 100)}{$percentage2|number_format:"2"} %
+
+
+ Difficulty
+ {$BLOCKDETAILS.difficulty|default:"0"}
+ Time
+ {$BLOCKDETAILS.time|default:"0"}
+ Target Rounds
+ {$BLOCKAVGCOUNT|number_format:"0"|default:"0"}
+ Target Variance
+ {math assign="percentage" equation=(($BLOCKDETAILS.estshares / $PPLNSSHARES) * 100)}{$percentage|number_format:"2"} %
+
+
+ Shares
+ {$BLOCKDETAILS.shares|number_format:"0"|default:"0"}
+ Finder
+ {$BLOCKDETAILS.finder|default:"0"}
+ Seconds This Round
+ {$BLOCKDETAILS.round_time|number_format:"0"|default:"0"}
+ Round Variance
+ {math assign="percentage1" equation=(($BLOCKDETAILS.shares / $PPLNSSHARES) * 100)}{$percentage1|number_format:"2"} %
+
+
+
+
+
diff --git a/public/templates/mpos/statistics/round/pplns_round_shares.tpl b/public/templates/mpos/statistics/round/pplns_round_shares.tpl
new file mode 100644
index 00000000..5f299f78
--- /dev/null
+++ b/public/templates/mpos/statistics/round/pplns_round_shares.tpl
@@ -0,0 +1,26 @@
+
+
+
+
+
+ Rank
+ User Name
+ Valid
+ Invalid
+ Invalid %
+
+
+
+{assign var=rank value=1}
+{section contrib $PPLNSROUNDSHARES}
+
+ {$rank++}
+ {if $PPLNSROUNDSHARES[contrib].is_anonymous|default:"0" == 1}anonymous{else}{$PPLNSROUNDSHARES[contrib].username|escape}{/if}
+ {$PPLNSROUNDSHARES[contrib].pplns_valid|number_format}
+ {$PPLNSROUNDSHARES[contrib].pplns_invalid|number_format}
+ {if $PPLNSROUNDSHARES[contrib].pplns_invalid > 0 && $PPLNSROUNDSHARES[contrib].pplns_valid > 0}{($PPLNSROUNDSHARES[contrib].pplns_invalid / $PPLNSROUNDSHARES[contrib].pplns_valid * 100)|number_format:"2"|default:"0"}{else}0.00{/if}
+
+{/section}
+
+
+
diff --git a/public/templates/mpos/statistics/round/pplns_transactions.tpl b/public/templates/mpos/statistics/round/pplns_transactions.tpl
new file mode 100644
index 00000000..4541d45f
--- /dev/null
+++ b/public/templates/mpos/statistics/round/pplns_transactions.tpl
@@ -0,0 +1,32 @@
+
+
+
+
+
+ User Name
+ Round Shares
+ Round %
+ PPLNS Shares
+ PPLNS Round %
+ Variance
+ Amount
+
+
+
+{assign var=percentage1 value=0}
+{section txs $ROUNDTRANSACTIONS}
+
+ {if $ROUNDTRANSACTIONS[txs].is_anonymous|default:"0" == 1}anonymous{else}{$ROUNDTRANSACTIONS[txs].username|escape}{/if}
+ {$SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid|number_format}
+ {if $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid > 0 }{(( 100 / $BLOCKDETAILS.shares) * $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid)|number_format:"2"}{else}0.00{/if}
+ {$PPLNSROUNDSHARES[txs].pplns_valid|number_format|default:"0"}
+ {if $PPLNSROUNDSHARES[txs].pplns_valid > 0 }{(( 100 / $PPLNSSHARES) * $PPLNSROUNDSHARES[txs].pplns_valid)|number_format:"2"|default:"0"}{else}0{/if}
+ {if $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid > 0 && $PPLNSROUNDSHARES[txs].pplns_valid > 0}{math assign="percentage1" equation=(100 / ((( 100 / $BLOCKDETAILS.shares) * $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid) / (( 100 / $PPLNSSHARES) * $PPLNSROUNDSHARES[txs].pplns_valid)))}{else if $PPLNSROUNDSHARES[txs].pplns_valid == 0}{assign var=percentage1 value=0}{else}{assign var=percentage1 value=100}{/if}
+ {$percentage1|number_format:"2"}
+ {$ROUNDTRANSACTIONS[txs].amount|default:"0"|number_format:"8"}
+ {assign var=percentage1 value=0}
+
+{/section}
+
+
+
diff --git a/public/templates/mpos/statistics/round/pplns_transactions_small.tpl b/public/templates/mpos/statistics/round/pplns_transactions_small.tpl
new file mode 100644
index 00000000..998f0eab
--- /dev/null
+++ b/public/templates/mpos/statistics/round/pplns_transactions_small.tpl
@@ -0,0 +1,39 @@
+
+
+
+
+
+ User Name
+ Round Valid
+ Invalid
+ Invalid %
+ Round %
+ PPLNS Valid
+ Invalid
+ Invalid %
+ PPLNS Round %
+ Variance
+ Amount
+
+
+
+{section txs $ROUNDTRANSACTIONS}
+
+ {if $ROUNDTRANSACTIONS[txs].is_anonymous|default:"0" == 1}anonymous{else}{$ROUNDTRANSACTIONS[txs].username|escape}{/if}
+ {$SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid|number_format}
+ {$SHARESDATA[$ROUNDTRANSACTIONS[txs].username].invalid|number_format}
+ {if $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].invalid > 0 }{($SHARESDATA[$ROUNDTRANSACTIONS[txs].username].invalid / $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid * 100)|number_format:"2"|default:"0"}{else}0.00{/if}
+ {if $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid > 0 }{(( 100 / $BLOCKDETAILS.shares) * $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid)|number_format:"2"}{else}0.00{/if}
+ {$PPLNSROUNDSHARES[txs].pplns_valid|number_format}
+ {$PPLNSROUNDSHARES[txs].pplns_invalid|number_format}
+ {if $PPLNSROUNDSHARES[txs].pplns_invalid > 0 }{($PPLNSROUNDSHARES[txs].pplns_invalid / $PPLNSROUNDSHARES[txs].pplns_valid * 100)|number_format:"2"|default:"0"}{else}0.00{/if}
+ {(( 100 / $PPLNSSHARES) * $PPLNSROUNDSHARES[txs].pplns_valid)|number_format:"2"}
+ {if $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid > 0 }{math assign="percentage1" equation=(100 / ((( 100 / $BLOCKDETAILS.shares) * $SHARESDATA[$ROUNDTRANSACTIONS[txs].username].valid) / (( 100 / $PPLNSSHARES) * $PPLNSROUNDSHARES[txs].pplns_valid)))}{else if $PPLNSROUNDSHARES[txs].pplns_valid == 0}{assign var=percentage1 value=0}{else}{assign var=percentage1 value=100}{/if}
+ {$percentage1|number_format:"2"}
+ {$ROUNDTRANSACTIONS[txs].amount|default:"0"|number_format:"8"}
+ {assign var=percentage1 value=0}
+
+{/section}
+
+
+
diff --git a/public/templates/mpos/statistics/round/round_shares.tpl b/public/templates/mpos/statistics/round/round_shares.tpl
index ec52a5b0..9753c234 100644
--- a/public/templates/mpos/statistics/round/round_shares.tpl
+++ b/public/templates/mpos/statistics/round/round_shares.tpl
@@ -19,7 +19,7 @@
{if $ROUNDSHARES[contrib].is_anonymous|default:"0" == 1}anonymous{else}{$ROUNDSHARES[contrib].username|escape}{/if}
{$ROUNDSHARES[contrib].valid|number_format}
{$ROUNDSHARES[contrib].invalid|number_format}
- {($ROUNDSHARES[contrib].invalid / $ROUNDSHARES[contrib].valid * 100)|number_format:"2"}
+ {if $ROUNDSHARES[contrib].invalid > 0 }{($ROUNDSHARES[contrib].invalid / $ROUNDSHARES[contrib].valid * 100)|number_format:"2"|default:"0"}{else}0.00{/if}
{/section}
diff --git a/public/templates/mpos/statistics/round/round_transactions.tpl b/public/templates/mpos/statistics/round/round_transactions.tpl
index 80af70ad..3a917ebd 100644
--- a/public/templates/mpos/statistics/round/round_transactions.tpl
+++ b/public/templates/mpos/statistics/round/round_transactions.tpl
@@ -3,18 +3,18 @@
- TX #
User Name
Type
+ Round %
Amount
{section txs $ROUNDTRANSACTIONS}
-
- {$ROUNDTRANSACTIONS[txs].id|default:"0"}
- {$ROUNDTRANSACTIONS[txs].username|escape}
+
+ {if $ROUNDTRANSACTIONS[txs].is_anonymous|default:"0" == 1}anonymous{else}{$ROUNDTRANSACTIONS[txs].username|escape}{/if}
{$ROUNDTRANSACTIONS[txs].type|default:""}
+ {(( 100 / $BLOCKDETAILS.shares) * $ROUNDSHARES[txs].valid)|default:"0"|number_format:"2"}
{$ROUNDTRANSACTIONS[txs].amount|default:"0"|number_format:"8"}
{/section}
diff --git a/sql/001_pplns_statistics.sql b/sql/001_pplns_statistics.sql
new file mode 100644
index 00000000..95ec5247
--- /dev/null
+++ b/sql/001_pplns_statistics.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `statistics_shares` ADD `pplns_valid` int(11) NOT NULL AFTER `invalid` ;
+ALTER TABLE `statistics_shares` ADD `pplns_invalid` int(11) NOT NULL DEFAULT 0 AFTER `pplns_valid` ;