diff --git a/POOLS.md b/POOLS.md
index 42ffd0b4..723c3e53 100644
--- a/POOLS.md
+++ b/POOLS.md
@@ -111,3 +111,9 @@ Small Time Miners are running various stratum only pools for different coins.
| http://ftc.nut2pools.com | Feathercoin | 45-50Mhs | 25 workers | New style, PPLNS |
| http://wdc.nut2pools.com | Worldcoin | 3.5 Mhs | 3 workers | New style, PPLNS |
| http://pxc.nut2pools.com | Phenixcoin | 0 | 0 | New style | PPLNS |
+
+### Dids
+
+| Pool URL | Coin | Avg. Hashrate | Avg. Active Workers | Notes |
+| -------- | ---- | ------------: | ------------------: | ----- |
+| http://poolmine.it | Litecoin | 0.23 MHash | 5 | PPLNS, Custom Template |
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..8af22cbf
--- /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, blockhash, 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/classes/user.class.php b/public/include/classes/user.class.php
index e012505a..dc0c71b7 100644
--- a/public/include/classes/user.class.php
+++ b/public/include/classes/user.class.php
@@ -201,7 +201,6 @@ class User {
return $result->fetch_all(MYSQLI_ASSOC);
}
$this->debug->append("Unable to fetch users with AP set");
- echo $this->mysqli->error;
return false;
}
diff --git a/public/include/config/admin_settings.inc.php b/public/include/config/admin_settings.inc.php
index f3b68cd8..69b55e75 100644
--- a/public/include/config/admin_settings.inc.php
+++ b/public/include/config/admin_settings.inc.php
@@ -77,6 +77,7 @@ $aSettings['website'][] = array(
$aSettings['website'][] = array(
'display' => 'Disable Blockexplorer', 'type' => 'select',
'options' => array( 0 => 'No', 1 => 'Yes' ),
+ 'default' => 0,
'name' => 'website_blockexplorer_disabled', 'value' => $setting->getValue('website_blockexplorer_disabled'),
'tooltip' => 'Enabled or disable the blockexplorer URL feature. Will remove any links using the blockexplorer URL.'
);
@@ -90,6 +91,7 @@ $aSettings['website'][] = array(
$aSettings['website'][] = array(
'display' => 'Disable Chaininfo', 'type' => 'select',
'options' => array( 0 => 'No', 1 => 'Yes' ),
+ 'default' => 0,
'name' => 'website_chaininfo_disabled', 'value' => $setting->getValue('website_chaininfo_disabled'),
'tooltip' => 'Enabled or disable the chainfo URL feature. Will remove any links using the chaininfo URL.'
);
@@ -108,12 +110,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..869dbb72
--- /dev/null
+++ b/public/include/pages/statistics/round.inc.php
@@ -0,0 +1,44 @@
+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'];
+ }
+ }
+ $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/account/edit/default.tpl b/public/templates/mmcFE/account/edit/default.tpl
index 0a3e523d..e548da34 100644
--- a/public/templates/mmcFE/account/edit/default.tpl
+++ b/public/templates/mmcFE/account/edit/default.tpl
@@ -6,7 +6,7 @@
Username: {$GLOBAL.userdata.username|escape}
User Id: {$GLOBAL.userdata.id}
- {if !$GLOBAL.config.website.api.disabled}API Key: {$GLOBAL.userdata.api_key} {/if}
+ {if !$GLOBAL.website.api.disabled}API Key: {$GLOBAL.userdata.api_key} {/if}
E-Mail:
Payment Address:
Donation %: [donation amount in percent (example: 0.5)]
diff --git a/public/templates/mmcFE/account/qrcode/default.tpl b/public/templates/mmcFE/account/qrcode/default.tpl
index 2656314e..c185a4b4 100644
--- a/public/templates/mmcFE/account/qrcode/default.tpl
+++ b/public/templates/mmcFE/account/qrcode/default.tpl
@@ -1,4 +1,4 @@
-{if !$GLOBAL.config.website.api.disabled}
+{if !$GLOBAL.website.api.disabled}
{include file="global/block_header.tpl" BLOCK_HEADER="API String"}
This code will allow you to import the full API string into your mobile application.
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..596ccfe9 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
@@ -83,12 +79,14 @@ target and network difficulty and assuming a zero variance scenario.
{/section}
+ {if $count > 0}
Totals
{$totalexpectedshares|number_format}
{$totalshares|number_format}
{($totalpercentage / $count)|number_format:"2"}
+ {/if}
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/default.tpl b/public/templates/mmcFE/statistics/default.tpl
index 59603d94..5fa45522 100644
--- a/public/templates/mmcFE/statistics/default.tpl
+++ b/public/templates/mmcFE/statistics/default.tpl
@@ -19,5 +19,5 @@
-{if !$GLOBAL.config.website.api.disabled}These stats are also available in JSON format HERE {/if}
+{if !$GLOBAL.website.api.disabled}These stats are also available in JSON format HERE {/if}
{include file="global/block_footer.tpl"}
diff --git a/public/templates/mmcFE/statistics/pool/authenticated.tpl b/public/templates/mmcFE/statistics/pool/authenticated.tpl
index 6189ef78..b19848db 100644
--- a/public/templates/mmcFE/statistics/pool/authenticated.tpl
+++ b/public/templates/mmcFE/statistics/pool/authenticated.tpl
@@ -32,7 +32,7 @@
{/if}
- {if $GLOBAL.website.blockexplorer.url}{$LASTBLOCK|default:"0"} {else}{$LASTBLOCK|default:"0"}{/if}
+ {if $GLOBAL.website.blockexplorer.url}{$LASTBLOCK|default:"0"} {else}{$LASTBLOCK|default:"0"}{/if}
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"}