diff --git a/public/include/autoloader.inc.php b/public/include/autoloader.inc.php
index 35ce807e..d86245fb 100644
--- a/public/include/autoloader.inc.php
+++ b/public/include/autoloader.inc.php
@@ -41,6 +41,7 @@ require_once(CLASS_DIR . '/invitation.class.php');
require_once(CLASS_DIR . '/share.class.php');
require_once(CLASS_DIR . '/worker.class.php');
require_once(CLASS_DIR . '/statistics.class.php');
+require_once(CLASS_DIR . '/roundstats.class.php');
require_once(CLASS_DIR . '/transaction.class.php');
require_once(CLASS_DIR . '/notification.class.php');
require_once(CLASS_DIR . '/news.class.php');
diff --git a/public/include/classes/roundstats.class.php b/public/include/classes/roundstats.class.php
new file mode 100644
index 00000000..d93cca43
--- /dev/null
+++ b/public/include/classes/roundstats.class.php
@@ -0,0 +1,160 @@
+debug = $debug;
+ $this->mysqli = $mysqli;
+ $this->config = $config;
+ $this->debug->append("Instantiated RoundStats class", 2);
+ }
+
+ // get and set methods
+ private function setErrorMessage($msg) {
+ $this->sError = $msg;
+ }
+ public function getError() {
+ return $this->sError;
+ }
+
+ /**
+ * Get next block for round stats
+ **/
+ public function getNextBlock($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 prev block for round stats
+ **/
+ public function getPreviousBlock($iHeight=0) {
+ $stmt = $this->mysqli->prepare("
+ SELECT height
+ FROM $this->tableBlocks
+ WHERE height < ?
+ ORDER BY height DESC
+ 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 details for block height
+ * @param height int Block Height
+ * @return data array Block information from DB
+ **/
+ public function getDetailsForBlockHeight($iHeight=0, $isAdmin=0) {
+ $stmt = $this->mysqli->prepare("
+ SELECT
+ b.id, height, amount, confirmations, difficulty, FROM_UNIXTIME(time) as time, shares,
+ IF(a.is_anonymous, IF( ? , a.username, 'anonymous'), a.username) AS finder
+ 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())
+ return $result->fetch_assoc();
+ return false;
+ }
+
+ /**
+ * Get shares statistics for round block height
+ * @param height int Block Height
+ * @return data array Block information from DB
+ **/
+ public function getRoundStatsForAccounts($iHeight=0, $isAdmin=0) {
+ $stmt = $this->mysqli->prepare("
+ SELECT
+ IF(a.is_anonymous, IF( ? , a.username, 'anonymous'), a.username) AS username,
+ s.valid,
+ s.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 valid DESC
+ ");
+ if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $isAdmin, $iHeight) && $stmt->execute() && $result = $stmt->get_result())
+ return $result->fetch_all(MYSQLI_ASSOC);
+ 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) {
+ $this->debug->append("STA " . __METHOD__, 4);
+ $stmt = $this->mysqli->prepare("
+ SELECT
+ t.id AS id,
+ a.username AS username,
+ 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('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
+ return $result->fetch_all(MYSQLI_ASSOC);
+ $this->debug->append('Unable to fetch transactions');
+ return false;
+ }
+
+ /**
+ * Get transactions for round block height user id
+ * @param height int Block Height
+ * @param id int user id
+ * @return data array Block round transactions for user id
+ **/
+ public function getUserRoundTransactions($iHeight=0, $id=0) {
+ $this->debug->append("STA " . __METHOD__, 4);
+ $stmt = $this->mysqli->prepare("
+ SELECT
+ t.id AS id,
+ a.username AS username,
+ 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 = ? AND a.id = ?
+ ORDER BY id ASC");
+ if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iHeight, $id) && $stmt->execute() && $result = $stmt->get_result())
+ return $result->fetch_all(MYSQLI_ASSOC);
+ $this->debug->append('Unable to fetch transactions');
+ return false;
+ }
+
+ private function checkStmt($bState) {
+ if ($bState ===! true) {
+ $this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
+ $this->setErrorMessage('Internal application Error');
+ return false;
+ }
+ return true;
+ }
+
+}
+
+$roundstats = new RoundStats($debug, $mysqli, $config);
diff --git a/public/include/config/admin_settings.inc.php b/public/include/config/admin_settings.inc.php
index f3b68cd8..3342ef49 100644
--- a/public/include/config/admin_settings.inc.php
+++ b/public/include/config/admin_settings.inc.php
@@ -108,12 +108,19 @@ $aSettings['acl'][] = array(
'tooltip' => 'Make the pool statistics page private (users only) or public.'
);
$aSettings['acl'][] = array(
- 'display' => 'Blcok Statistics', 'type' => 'select',
+ 'display' => 'Block Statistics', 'type' => 'select',
'options' => array( 0 => 'Private', 1 => 'Public'),
'default' => 1,
'name' => 'acl_block_statistics', 'value' => $setting->getValue('acl_block_statistics'),
'tooltip' => 'Make the block statistics page private (users only) or public.'
);
+$aSettings['acl'][] = array(
+ 'display' => 'Round Statistics', 'type' => 'select',
+ 'options' => array( 0 => 'Private', 1 => 'Public'),
+ 'default' => 1,
+ 'name' => 'acl_round_statistics', 'value' => $setting->getValue('acl_round_statistics'),
+ 'tooltip' => 'Make the round statistics page private (users only) or public.'
+);
$aSettings['system'][] = array(
'display' => 'Disable e-mail confirmations', 'type' => 'select',
'options' => array( 0 => 'No', 1 => 'Yes' ),
diff --git a/public/include/pages/statistics/round.inc.php b/public/include/pages/statistics/round.inc.php
new file mode 100644
index 00000000..b6e40a3a
--- /dev/null
+++ b/public/include/pages/statistics/round.inc.php
@@ -0,0 +1,45 @@
+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'];
+ }
+ }
+ echo $iKey;
+ $aDetailsForBlockHeight = $roundstats->getDetailsForBlockHeight($iKey, $user->isAdmin($_SESSION['USERDATA']['id']));
+ $aRoundShareStats = $roundstats->getRoundStatsForAccounts($iKey, $user->isAdmin($_SESSION['USERDATA']['id']));
+
+ if ($user->isAdmin($_SESSION['USERDATA']['id'])) {
+ $aUserRoundTransactions = $roundstats->getAllRoundTransactions($iKey);
+ } else {
+ $aUserRoundTransactions = $roundstats->getUserRoundTransactions($iKey, $_SESSION['USERDATA']['id']);
+ }
+
+ // Propagate content our template
+ $smarty->assign('BLOCKDETAILS', $aDetailsForBlockHeight);
+ $smarty->assign('ROUNDSHARES', $aRoundShareStats);
+ $smarty->assign("ROUNDTRANSACTIONS", $aUserRoundTransactions);
+} else {
+ $debug->append('Using cached page', 3);
+}
+
+if ($setting->getValue('acl_round_statistics')) {
+ $smarty->assign("CONTENT", "default.tpl");
+} else if ($user->isAuthenticated()) {
+ $smarty->assign("CONTENT", "default.tpl");
+}
+?>
diff --git a/public/include/smarty_globals.inc.php b/public/include/smarty_globals.inc.php
index af2805b8..d457ee4e 100644
--- a/public/include/smarty_globals.inc.php
+++ b/public/include/smarty_globals.inc.php
@@ -72,6 +72,7 @@ $setting->getValue('website_chaininfo_url') ? $aGlobal['website']['chaininfo']['
// ACLs
$aGlobal['acl']['pool']['statistics'] = $setting->getValue('acl_pool_statistics');
$aGlobal['acl']['block']['statistics'] = $setting->getValue('acl_block_statistics');
+$aGlobal['acl']['round']['statistics'] = $setting->getValue('acl_round_statistics');
// Special calculations for PPS Values based on reward_type setting and/or available blocks
if ($config['reward_type'] != 'block') {
diff --git a/public/templates/mmcFE/global/navigation.tpl b/public/templates/mmcFE/global/navigation.tpl
index 407f24b0..c7f762e9 100644
--- a/public/templates/mmcFE/global/navigation.tpl
+++ b/public/templates/mmcFE/global/navigation.tpl
@@ -30,6 +30,7 @@
Pool Stats
Block Stats
Hashrate Graphs
+ Round Stats
{else}
@@ -40,6 +41,9 @@
{/if}
{if $GLOBAL.acl.block.statistics}
Block Stats
+ {/if}
+ {if $GLOBAL.acl.round.statistics}
+ Round Stats
{/if}
{/if}
diff --git a/public/templates/mmcFE/statistics/blocks/default.tpl b/public/templates/mmcFE/statistics/blocks/default.tpl
index 6596647f..2bf8e85c 100644
--- a/public/templates/mmcFE/statistics/blocks/default.tpl
+++ b/public/templates/mmcFE/statistics/blocks/default.tpl
@@ -55,11 +55,7 @@ target and network difficulty and assuming a zero variance scenario.
{assign var="totalshares" value=$totalshares+$BLOCKSFOUND[block].shares}
{assign var="count" value=$count+1}
- {if ! $GLOBAL.website.blockexplorer.disabled}
- | {$BLOCKSFOUND[block].height} |
- {else}
- {$BLOCKSFOUND[block].height} |
- {/if}
+ {$BLOCKSFOUND[block].height} |
{if $BLOCKSFOUND[block].confirmations >= $GLOBAL.confirmations}
Confirmed
diff --git a/public/templates/mmcFE/statistics/blocks/small_table.tpl b/public/templates/mmcFE/statistics/blocks/small_table.tpl
index e826fd3a..0c1760ff 100644
--- a/public/templates/mmcFE/statistics/blocks/small_table.tpl
+++ b/public/templates/mmcFE/statistics/blocks/small_table.tpl
@@ -13,11 +13,7 @@
{assign var=rank value=1}
{section block $BLOCKSFOUND}
|
- {if ! $GLOBAL.website.blockexplorer.disabled}
- | {$BLOCKSFOUND[block].height} |
- {else}
- {$BLOCKSFOUND[block].height} |
- {/if}
+ {$BLOCKSFOUND[block].height} |
{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].shares|number_format} |
diff --git a/public/templates/mmcFE/statistics/round/block_stats.tpl b/public/templates/mmcFE/statistics/round/block_stats.tpl
new file mode 100644
index 00000000..75b33950
--- /dev/null
+++ b/public/templates/mmcFE/statistics/round/block_stats.tpl
@@ -0,0 +1,65 @@
+{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 |
+
+
+
+
+ | ID |
+ {$BLOCKDETAILS.id|default:"0"} |
+
+
+ | Height |
+ {if ! $GLOBAL.website.blockexplorer.disabled}
+ {$BLOCKDETAILS.height} |
+ {else}
+ {$BLOCKDETAILS.height} |
+ {/if}
+
+
+ | Amount |
+ {$BLOCKDETAILS.amount|default:"0"} |
+
+
+ | Confirmations |
+ {$BLOCKDETAILS.confirmations|default:"0"} |
+
+
+ | Difficulty |
+ {$BLOCKDETAILS.difficulty|default:"0"} |
+
+
+ | Time |
+ {$BLOCKDETAILS.time|default:"0"} |
+
+
+ | Shares |
+ {$BLOCKDETAILS.shares|default:"0"} |
+
+
+ | Finder |
+ {$BLOCKDETAILS.finder|default:"0"} |
+
+
+ |
+
+ |
+
+
+
+ |
+
+
+ |
+
+
+{include file="global/block_footer.tpl"}
diff --git a/public/templates/mmcFE/statistics/round/default.tpl b/public/templates/mmcFE/statistics/round/default.tpl
new file mode 100644
index 00000000..7098eb06
--- /dev/null
+++ b/public/templates/mmcFE/statistics/round/default.tpl
@@ -0,0 +1,9 @@
+{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"}
+
+{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
new file mode 100644
index 00000000..919aed8e
--- /dev/null
+++ b/public/templates/mmcFE/statistics/round/round_shares.tpl
@@ -0,0 +1,28 @@
+{include file="global/block_header.tpl" ALIGN="left" BLOCK_HEADER="Round Shares" }
+
+
+
+
+ | Rank |
+ User Name |
+ Valid |
+ Invalid |
+ Invalid % |
+
+
+
+{assign var=rank value=1}
+{assign var=listed value=0}
+{section contrib $ROUNDSHARES}
+
+ | {$rank++} |
+ {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"} |
+
+{/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
new file mode 100644
index 00000000..ecb4ea75
--- /dev/null
+++ b/public/templates/mmcFE/statistics/round/round_transactions.tpl
@@ -0,0 +1,24 @@
+{include file="global/block_header.tpl" ALIGN="right" BLOCK_HEADER="Round Transactions"}
+
+
+
+
+ | Tx Id |
+ User Name |
+ Type |
+ Amount |
+
+
+
+{section txs $ROUNDTRANSACTIONS}
+
+ | {$ROUNDTRANSACTIONS[txs].id|default:"0"} |
+ {$ROUNDTRANSACTIONS[txs].username|escape} |
+ {$ROUNDTRANSACTIONS[txs].type|default:""} |
+ {$ROUNDTRANSACTIONS[txs].amount|default:"0"|number_format:"8"} |
+
+{/section}
+
+
+
+{include file="global/block_footer.tpl"}