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/block.class.php b/public/include/classes/block.class.php
index fb5e8dc4..3f88887d 100644
--- a/public/include/classes/block.class.php
+++ b/public/include/classes/block.class.php
@@ -133,9 +133,8 @@ class Block {
* @param confirmations int Required confirmations to consider block confirmed
* @return data array Array with database fields as keys
**/
- public function getAllUnconfirmed() {
+ public function getAllUnconfirmed($confirmations=120) {
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE confirmations < ? AND confirmations > -1");
- empty($this->config['network_confirmations']) ? $confirmations = 120 : $confirmations = $this->config['network_confirmations'];
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $confirmations) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
return false;
diff --git a/public/include/classes/notification.class.php b/public/include/classes/notification.class.php
index 08f3d3f5..ac61d105 100644
--- a/public/include/classes/notification.class.php
+++ b/public/include/classes/notification.class.php
@@ -164,9 +164,13 @@ class Notification extends Mail {
if ($stmt && $stmt->bind_param('si', $strType, $account_id) && $stmt->execute() && $stmt->bind_result($id) && $stmt->fetch()) {
if ($stmt->close() && $this->sendMail('notifications/' . $strType, $aMailData) && $this->addNotification($account_id, $strType, $aMailData)) {
return true;
+ } else {
+ $this->setErrorMessage('SendMail call failed: ' . $this->mail->getError());
+ return false;
}
} else {
$this->setErrorMessage('User disabled ' . $strType . ' notifications');
+ return false;
}
$this->setErrorMessage('Error sending mail notification');
return false;
@@ -178,5 +182,5 @@ $notification->setDebug($debug);
$notification->setMysql($mysqli);
$notification->setSmarty($smarty);
$notification->setConfig($config);
-
+$notification->setSetting($setting);
?>
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/config/global.inc.dist.php b/public/include/config/global.inc.dist.php
index 82ea1b5a..39335c08 100644
--- a/public/include/config/global.inc.dist.php
+++ b/public/include/config/global.inc.dist.php
@@ -11,6 +11,9 @@ define('CLASS_DIR', INCLUDE_DIR . '/classes');
// Our pages directory which takes care of
define('PAGES_DIR', INCLUDE_DIR . '/pages');
+// Our theme folder holding all themes
+define('THEME_DIR', BASEPATH . 'templates');
+
// Set debugging level for our debug class
define('DEBUG', 0);
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 01cc6e5b..f19ff9c7 100644
--- a/public/include/smarty_globals.inc.php
+++ b/public/include/smarty_globals.inc.php
@@ -74,6 +74,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');
// We support some dynamic reward targets but fall back to our fixed value
// Special calculations for PPS Values based on reward_type setting and/or available blocks
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 7ebb4e47..83de463e 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"}