diff --git a/cronjobs/notifications.php b/cronjobs/notifications.php index 8e3ac98a..4166a16e 100755 --- a/cronjobs/notifications.php +++ b/cronjobs/notifications.php @@ -45,7 +45,7 @@ if (empty($aWorkers)) { $aData['subject'] = 'IDLE Worker : ' . $aWorker['username']; $aData['worker'] = $aWorker['username']; $aData['email'] = $user->getUserEmail($aData['username']); - $log->logInfo(" " . $aWorker['username'] . "..."); + $log->logDebug(" " . $aWorker['username'] . "..."); if (!$notification->sendNotification($aWorker['account_id'], 'idle_worker', $aData)) $log->logError(" Failed sending notifications: " . $notification->getError() . "\n"); } @@ -60,15 +60,15 @@ if (!empty($aNotifications)) { foreach ($aNotifications as $aNotification) { $aData = json_decode($aNotification['data'], true); $aWorker = $worker->getWorker($aData['id']); - $log->logInfo(" " . $aWorker['username'] . " ..."); + $log->logDebug(" " . $aWorker['username'] . " ..."); if ($aWorker['hashrate'] > 0) { if ($notification->setInactive($aNotification['id'])) { - $log->logInfo(" updated #" . $aNotification['id'] . " for " . $aWorker['username'] . " as inactive\n"); + $log->logDebug(" updated #" . $aNotification['id'] . " for " . $aWorker['username'] . " as inactive\n"); } else { $log->logInfo(" failed to update #" . $aNotification['id'] . " for " . $aWorker['username'] . "\n"); } } else { - $log->logInfo(" still inactive\n"); + $log->logDebug(" still inactive\n"); } } } else { 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/.htaccess b/public/.htaccess index 1caaddc0..9750f3bb 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -1,3 +1,4 @@ +ErrorDocument 404 /index.php?page=error&action=404 RedirectMatch 404 /templates(/|$) RedirectMatch 404 /include(/|$) RedirectMatch 404 /.git(/|$) diff --git a/public/include/classes/roundstats.class.php b/public/include/classes/roundstats.class.php index 6b187973..45dbb7ea 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,12 @@ 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.id, + a.username, + a.is_anonymous, s.valid, s.invalid FROM $this->tableStats AS s @@ -92,30 +125,76 @@ 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()) { + while ($row = $result->fetch_assoc()) { + $aData[$row['id']] = $row; + } + return $aData; + } + 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.id AS uid, + 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..38f5360a 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 @@ -327,6 +392,24 @@ class Statistics { return false; } + + public function getUserShareDifficulty($account_id, $interval=600) { + $this->debug->append("STA " . __METHOD__, 4); + if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; + $stmt = $this->mysqli->prepare(" + SELECT + IFNULL(AVG(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 0) AS avgsharediff, + COUNT(s.id) AS total + FROM " . $this->share->getTableName() . " AS s JOIN " . $this->user->getTableName() . " AS a + ON a.username = SUBSTRING_INDEX( s.username, '.', 1 ) + WHERE s.time > DATE_SUB(now(), INTERVAL ? SECOND) + AND a.id = ?"); + if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result() ) + return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->avgsharediff); + $this->debug->append("Failed fetching average share dificulty: " . $this->mysqli->error, 3); + return 0; + } + /** * Same as getUserHashrate for Sharerate * @param account_id integer User ID @@ -396,28 +479,32 @@ class Statistics { switch ($type) { case 'shares': if ($data = $this->memcache->get(STATISTICS_ALL_USER_SHARES)) { - // Use global cache to build data - $max = 0; - foreach($data['data'] as $key => $aUser) { - $shares[$key] = $aUser['valid']; - $username[$key] = $aUser['username']; + // Use global cache to build data, if we have any data there + if (!empty($data['data']) && is_array($data['data'])) { + foreach($data['data'] as $key => $aUser) { + $shares[$key] = $aUser['valid']; + $username[$key] = $aUser['username']; + } + array_multisort($shares, SORT_DESC, $username, SORT_ASC, $data['data']); + $count = 0; + foreach ($data['data'] as $key => $aUser) { + if ($count == $limit) break; + $count++; + $data_new[$key]['shares'] = $aUser['valid']; + $data_new[$key]['account'] = $aUser['username']; + $data_new[$key]['donate_percent'] = $aUser['donate_percent']; + $data_new[$key]['is_anonymous'] = $aUser['is_anonymous']; + } + return $data_new; } - array_multisort($shares, SORT_DESC, $username, SORT_ASC, $data['data']); - foreach ($data['data'] as $key => $aUser) { - $data_new[$key]['shares'] = $aUser['valid']; - $data_new[$key]['account'] = $aUser['username']; - $data_new[$key]['donate_percent'] = $aUser['donate_percent']; - $data_new[$key]['is_anonymous'] = $aUser['is_anonymous']; - } - return $data_new; } // No cached data, fallback to SQL and cache in local cache $stmt = $this->mysqli->prepare(" SELECT + a.username AS account, a.donate_percent AS donate_percent, a.is_anonymous AS is_anonymous, - ROUND(IFNULL(SUM(IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS shares, - SUBSTRING_INDEX( s.username, '.', 1 ) AS account + ROUND(IFNULL(SUM(IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS shares FROM " . $this->share->getTableName() . " AS s LEFT JOIN " . $this->user->getTableName() . " AS a ON SUBSTRING_INDEX( s.username, '.', 1 ) = a.username @@ -434,10 +521,10 @@ class Statistics { case 'hashes': $stmt = $this->mysqli->prepare(" SELECT + a.username AS account, a.donate_percent AS donate_percent, a.is_anonymous AS is_anonymous, - IFNULL(ROUND(SUM(t1.difficulty) * 65536/600/1000, 2), 0) AS hashrate, - SUBSTRING_INDEX( t1.username, '.', 1 ) AS account + IFNULL(ROUND(SUM(t1.difficulty) * 65536 / 600 / 1000, 2), 0) AS hashrate FROM ( SELECT IFNULL(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0) AS difficulty, username FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE) AND our_result = 'Y' @@ -536,28 +623,51 @@ class Statistics { /** * get user estimated payouts based on share counts - * @param aRoundShares array Round shares - * @param aUserShares array User shares + * @param value1 mixed Round shares OR share rate + * @param value2 mixed User shares OR share difficulty * @param dDonate double User donation setting * @param bNoFees bool User no-fees option setting * @return aEstimates array User estimations **/ - public function getUserEstimates($aRoundShares, $aUserShares, $dDonate, $bNoFees) { + public function getUserEstimates($value1, $value2, $dDonate, $bNoFees, $ppsvalue=0) { $this->debug->append("STA " . __METHOD__, 4); - // Fetch some user information that we need - if (@$aRoundShares['valid'] > 0 && @$aUserShares['valid'] > 0) { - $aEstimates['block'] = round(( (int)$aUserShares['valid'] / (int)$aRoundShares['valid'] ) * (float)$this->config['reward'], 8); - $bNoFees == 0 ? $aEstimates['fee'] = round(((float)$this->config['fees'] / 100) * (float)$aEstimates['block'], 8) : $aEstimates['fee'] = 0; - $aEstimates['donation'] = round((( (float)$dDonate / 100) * ((float)$aEstimates['block'] - (float)$aEstimates['fee'])), 8); - $aEstimates['payout'] = round((float)$aEstimates['block'] - (float)$aEstimates['donation'] - (float)$aEstimates['fee'], 8); + if ($this->config['payout_system'] != 'pps') { + if (@$value1['valid'] > 0 && @$value2['valid'] > 0) { + $aEstimates['block'] = round(( (int)$value2['valid'] / (int)$value1['valid'] ) * (float)$this->config['reward'], 8); + $bNoFees == 0 ? $aEstimates['fee'] = round(((float)$this->config['fees'] / 100) * (float)$aEstimates['block'], 8) : $aEstimates['fee'] = 0; + $aEstimates['donation'] = round((( (float)$dDonate / 100) * ((float)$aEstimates['block'] - (float)$aEstimates['fee'])), 8); + $aEstimates['payout'] = round((float)$aEstimates['block'] - (float)$aEstimates['donation'] - (float)$aEstimates['fee'], 8); + } else { + $aEstimates['block'] = 0; + $aEstimates['fee'] = 0; + $aEstimates['donation'] = 0; + $aEstimates['payout'] = 0; + } } else { - $aEstimates['block'] = 0; - $aEstimates['fee'] = 0; - $aEstimates['donation'] = 0; - $aEstimates['payout'] = 0; + // Hack so we can use this method for PPS estimates too + if (@$value1 > 0 && @$value2 > 0) { + // Default: No fees applied so multiply by 1 + $fee = 1; + if ($this->config['fees'] > 0) + $bNoFees == 0 ? $fee = round(((float)$this->config['fees'] / 100), 8) : $fee = 1; + $pps = $value1 * $value2 * $ppsvalue; + $hour = 3600; + $aEstimates['hours1'] = $pps * $hour * $fee; + $aEstimates['hours24'] = $pps * 24 * $hour; + $aEstimates['days7'] = $pps * 24 * 7 * $hour; + $aEstimates['days14'] = $pps * 14 * 24 * 7 * $hour; + $aEstimates['days30'] = $pps * 30 * 24 * 7 * $hour; + } else { + $aEstimates['hours1'] = 0; + $aEstimates['hours24'] = 0; + $aEstimates['days7'] = 0; + $aEstimates['days14'] = 0; + $aEstimates['days30'] = 0; + } } return $aEstimates; } } + $statistics = new Statistics($debug, $mysqli, $config, $share, $user, $block, $memcache); diff --git a/public/include/classes/transaction.class.php b/public/include/classes/transaction.class.php index 53d111e3..557ce3e3 100644 --- a/public/include/classes/transaction.class.php +++ b/public/include/classes/transaction.class.php @@ -53,9 +53,16 @@ class Transaction extends Base { * @return data array type and total **/ public function getTransactionSummary($account_id=NULL) { - $sql = "SELECT SUM(t.amount) AS total, t.type AS type FROM $this->table AS t"; + $sql = " + SELECT + SUM(t.amount) AS total, t.type AS type + FROM transactions AS t + LEFT OUTER JOIN blocks AS b + ON b.id = t.block_id + WHERE ( b.confirmations > 0 OR b.id IS NULL ) + "; if (!empty($account_id)) { - $sql .= " WHERE t.account_id = ? "; + $sql .= " AND t.account_id = ? "; $this->addParam('i', $account_id); } $sql .= " GROUP BY t.type"; diff --git a/public/include/classes/worker.class.php b/public/include/classes/worker.class.php index 122d287d..42af02de 100644 --- a/public/include/classes/worker.class.php +++ b/public/include/classes/worker.class.php @@ -136,39 +136,39 @@ class Worker { * @param account_id int User ID * @return mixed array Workers and their settings or false **/ - public function getWorkers($account_id) { + public function getWorkers($account_id, $interval=600) { $this->debug->append("STA " . __METHOD__, 4); $stmt = $this->mysqli->prepare(" SELECT id, username, password, monitor, - ( SELECT COUNT(id) FROM " . $this->share->getTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS count_all, - ( SELECT COUNT(id) FROM " . $this->share->getArchiveTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS count_all_archive, + ( SELECT COUNT(id) FROM " . $this->share->getTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)) AS count_all, + ( SELECT COUNT(id) FROM " . $this->share->getArchiveTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)) AS count_all_archive, ( SELECT - IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536/600/1000), 0), 0) AS hashrate + IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0), 0) AS hashrate FROM " . $this->share->getTableName() . " WHERE username = w.username - AND time > DATE_SUB(now(), INTERVAL 10 MINUTE) + AND time > DATE_SUB(now(), INTERVAL ? SECOND) ) + ( SELECT - IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536/600/1000), 0), 0) AS hashrate + IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0), 0) AS hashrate FROM " . $this->share->getArchiveTableName() . " WHERE username = w.username - AND time > DATE_SUB(now(), INTERVAL 10 MINUTE) + AND time > DATE_SUB(now(), INTERVAL ? SECOND) ) AS hashrate, ( SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all, 2), 0) FROM " . $this->share->getTableName() . " - WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE) + WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND) ) + ( SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all_archive, 2), 0) FROM " . $this->share->getArchiveTableName() . " - WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE) + WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND) ) AS difficulty FROM $this->table AS w WHERE account_id = ?"); - if ($this->checkStmt($stmt) && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result()) + if ($this->checkStmt($stmt) && $stmt->bind_param('iiiiiiiii', $interval, $interval, $interval, $interval, $interval, $interval, $interval, $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result()) return $result->fetch_all(MYSQLI_ASSOC); // Catchall $this->setErrorMessage('Failed to fetch workers for your account'); @@ -183,7 +183,12 @@ class Worker { **/ public function getCountAllActiveWorkers() { $this->debug->append("STA " . __METHOD__, 4); - $stmt = $this->mysqli->prepare("SELECT IFNULL(IF(our_result='Y', COUNT(DISTINCT username), 0), 0) AS total FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)"); + $stmt = $this->mysqli->prepare(" + SELECT COUNT(DISTINCT(username)) AS total + FROM " . $this->share->getTableName() . " + WHERE our_result = 'Y' + AND time > DATE_SUB(now(), INTERVAL 10 MINUTE) + "); if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) return $result->fetch_object()->total; return false; diff --git a/public/include/config/admin_settings.inc.php b/public/include/config/admin_settings.inc.php index e85b9480..b73f6c93 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' => 'statistics_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/api/getdashboarddata.inc.php b/public/include/pages/api/getdashboarddata.inc.php index 732eb65a..4d15763d 100644 --- a/public/include/pages/api/getdashboarddata.inc.php +++ b/public/include/pages/api/getdashboarddata.inc.php @@ -32,23 +32,72 @@ $dPoolHashrate = $statistics->getCurrentHashrate($interval); if ($dPoolHashrate > $dNetworkHashrate) $dNetworkHashrate = $dPoolHashrate; $dPersonalHashrate = $statistics->getUserHashrate($user_id, $interval); $dPersonalSharerate = $statistics->getUserSharerate($user_id, $interval); +$dPersonalShareDifficulty = $statistics->getUserShareDifficulty($user_id, $interval); $statistics->setGetCache(true); // Use caches for this one $aUserRoundShares = $statistics->getUserShares($user_id); $aRoundShares = $statistics->getRoundShares(); -$aEstimates = $statistics->getUserEstimates($aRoundShares, $aUserRoundShares, $user->getUserDonatePercent($user_id), $user->getUserNoFee($user_id)); + +if ($config['payout_system'] != 'pps') { + $aEstimates = $statistics->getUserEstimates($aRoundShares, $aUserRoundShares, $user->getUserDonatePercent($user_id), $user->getUserNoFee($user_id)); +} else { + if ($config['pps']['reward']['type'] == 'blockavg' && $block->getBlockCount() > 0) { + $pps_reward = round($block->getAvgBlockReward($config['pps']['blockavg']['blockcount'])); + } else { + if ($config['pps']['reward']['type'] == 'block') { + if ($aLastBlock = $block->getLast()) { + $pps_reward = $aLastBlock['amount']; + } else { + $pps_reward = $config['pps']['reward']['default']; + } + } else { + $pps_reward = $config['pps']['reward']['default']; + } + } + + $ppsvalue = round($pps_reward / (pow(2,32) * $dDifficulty) * pow(2, $config['pps_target']), 12); + $aEstimates = $statistics->getUserEstimates($dPersonalSharerate, $dPersonalShareDifficulty, $user->getUserDonatePercent($user_id), $user->getUserNoFee($user_id), $ppsvalue); +} + +$iTotalRoundShares = $aRoundShares['valid'] + $aRoundShares['invalid']; +if ($iTotalRoundShares > 0) { + $dUserInvalidPercent = round($aUserRoundShares['invalid'] / $iTotalRoundShares * 100, 2); + $dPoolInvalidPercent = round($aRoundShares['invalid'] / $iTotalRoundShares * 100, 2); +} else { + $dUserInvalidPercent = 0; + $dPoolInvalidPercent = 0; +} // Apply pool modifiers $dPersonalHashrateAdjusted = $dPersonalHashrate * $dPersonalHashrateModifier; $dPoolHashrateAdjusted = $dPoolHashrate * $dPoolHashrateModifier; $dNetworkHashrateAdjusted = $dNetworkHashrate / 1000 * $dNetworkHashrateModifier; +// Worker information +$aWorkers = $worker->getWorkers($user_id, $interval); + +// Coin price +$aPrice = $setting->getValue('price'); + +// Round progress +$iEstShares = round((65536 * $dDifficulty) / pow(2, ($config['difficulty'] - 16))); +$dEstPercent = round(100 / $iEstShares * $aRoundShares['valid'], 2); + // Output JSON format $data = array( 'raw' => array( 'personal' => array( 'hashrate' => $dPersonalHashrate ), 'pool' => array( 'hashrate' => $dPoolHashrate ), 'network' => array( 'hashrate' => $dNetworkHashrate / 1000 ) ), - 'personal' => array ( 'hashrate' => $dPersonalHashrateAdjusted, 'sharerate' => $dPersonalSharerate, 'shares' => array('valid' => $aUserRoundShares['valid'], 'invalid' => $aUserRoundShares['invalid']), 'balance' => $transaction->getBalance($user_id), 'estimates' => $aEstimates), - 'pool' => array( 'hashrate' => $dPoolHashrateAdjusted, 'shares' => $aRoundShares ), + 'personal' => array ( + 'hashrate' => $dPersonalHashrateAdjusted, 'sharerate' => $dPersonalSharerate, 'sharedifficulty' => $dPersonalShareDifficulty, + 'shares' => array('valid' => $aUserRoundShares['valid'], 'invalid' => $aUserRoundShares['invalid'], 'invalid_percent' => $dUserInvalidPercent), + 'balance' => $transaction->getBalance($user_id), 'estimates' => $aEstimates, 'workers' => $aWorkers ), + 'pool' => array( + 'workers' => $worker->getCountAllActiveWorkers(), 'hashrate' => $dPoolHashrateAdjusted, + 'shares' => array( 'valid' => $aRoundShares['valid'], 'invalid' => $aRoundShares['invalid'], 'invalid_percent' => $dPoolInvalidPercent, 'estimated' => $iEstShares, 'progress' => $dEstPercent ), + 'price' => $aPrice, + 'difficulty' => pow(2, $config['difficulty'] - 16), + 'target_bits' => $config['difficulty'] + ), 'network' => array( 'hashrate' => $dNetworkHashrateAdjusted, 'difficulty' => $dDifficulty, 'block' => $iBlock ), ); echo $api->get_json($data); diff --git a/public/include/pages/api/getnavbardata.inc.php b/public/include/pages/api/getnavbardata.inc.php new file mode 100644 index 00000000..38041737 --- /dev/null +++ b/public/include/pages/api/getnavbardata.inc.php @@ -0,0 +1,60 @@ +isActive(); + +// Fetch RPC information +if ($bitcoin->can_connect() === true) { + $dNetworkHashrate = $bitcoin->getnetworkhashps(); + $dDifficulty = $bitcoin->getdifficulty(); + $iBlock = $bitcoin->getblockcount(); +} else { + $dNetworkHashrate = 0; + $dDifficulty = 1; + $iBlock = 0; +} + +// Some settings +if ( ! $interval = $setting->getValue('statistics_ajax_data_interval')) $interval = 300; +if ( ! $dPoolHashrateModifier = $setting->getValue('statistics_pool_hashrate_modifier') ) $dPoolHashrateModifier = 1; +if ( ! $dNetworkHashrateModifier = $setting->getValue('statistics_network_hashrate_modifier') ) $dNetworkHashrateModifier = 1; + +// Fetch raw data +$statistics->setGetCache(false); +$dPoolHashrate = $statistics->getCurrentHashrate($interval); +if ($dPoolHashrate > $dNetworkHashrate) $dNetworkHashrate = $dPoolHashrate; +$statistics->setGetCache(true); + +// Apply pool modifiers +$dPoolHashrateAdjusted = $dPoolHashrate * $dPoolHashrateModifier; +$dNetworkHashrateAdjusted = $dNetworkHashrate / 1000 * $dNetworkHashrateModifier; + +// Use caches for this one +$aRoundShares = $statistics->getRoundShares(); + +$iTotalRoundShares = $aRoundShares['valid'] + $aRoundShares['invalid']; +if ($iTotalRoundShares > 0) { + $dPoolInvalidPercent = round($aRoundShares['invalid'] / $iTotalRoundShares * 100, 2); +} else { + $dUserInvalidPercent = 0; + $dPoolInvalidPercent = 0; +} + +// Round progress +$iEstShares = round((65536 * $dDifficulty) / pow(2, ($config['difficulty'] - 16))); +$dEstPercent = round(100 / $iEstShares * $aRoundShares['valid'], 2); + +// Output JSON format +$data = array( + 'raw' => array( 'workers' => $worker->getCountAllActiveWorkers(), 'pool' => array( 'hashrate' => $dPoolHashrate ) ), + 'pool' => array( 'workers' => $worker->getCountAllActiveWorkers(), 'hashrate' => $dPoolHashrateAdjusted, 'estimated' => $iEstShares, 'progress' => $dEstPercent ), + 'network' => array( 'hashrate' => $dNetworkHashrateAdjusted, 'difficulty' => $dDifficulty, 'block' => $iBlock ), +); +echo $api->get_json($data); + +// Supress master template +$supress_master = 1; +?> diff --git a/public/include/pages/error.inc.php b/public/include/pages/error.inc.php new file mode 100644 index 00000000..aecab054 --- /dev/null +++ b/public/include/pages/error.inc.php @@ -0,0 +1,9 @@ +assign("CONTENT", "default.tpl"); +?> diff --git a/public/include/pages/error/404.inc.php b/public/include/pages/error/404.inc.php new file mode 100644 index 00000000..aecab054 --- /dev/null +++ b/public/include/pages/error/404.inc.php @@ -0,0 +1,9 @@ +assign("CONTENT", "default.tpl"); +?> diff --git a/public/include/pages/statistics/blocks.inc.php b/public/include/pages/statistics/blocks.inc.php index 116d999d..c21a078b 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('statistics_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('statistics_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); + } + } + } +//var_dump($aBlocksFoundData); // 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..4e7288d5 100644 --- a/public/include/pages/statistics/round.inc.php +++ b/public/include/pages/statistics/round.inc.php @@ -6,26 +6,40 @@ 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); + $aUserRoundTransactions = $roundstats->getAllRoundTransactions($iHeight); + + if ($config['payout_system'] == 'pplns') { + $aPPLNSRoundShares = $roundstats->getPPLNSRoundStatsForAccounts($iHeight); + foreach($aPPLNSRoundShares as $aData) { + $iPPLNSShares += $aData['pplns_valid']; + } + $block_avg = $block->getAvgBlockShares($iHeight, $config['pplns']['blockavg']['blockcount']); + $smarty->assign('PPLNSROUNDSHARES', $aPPLNSRoundShares); + $smarty->assign("PPLNSSHARES", $iPPLNSShares); + $smarty->assign("BLOCKAVGCOUNT", $config['pplns']['blockavg']['blockcount']); + $smarty->assign("BLOCKAVERAGE", $block_avg ); } // Propagate content our template diff --git a/public/include/smarty_globals.inc.php b/public/include/smarty_globals.inc.php index 8beb33b0..9bb4ac60 100644 --- a/public/include/smarty_globals.inc.php +++ b/public/include/smarty_globals.inc.php @@ -97,24 +97,6 @@ $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 -if ($config['pps']['reward']['type'] == 'blockavg' && $block->getBlockCount() > 0) { - $pps_reward = round($block->getAvgBlockReward($config['pps']['blockavg']['blockcount'])); -} else { - if ($config['pps']['reward']['type'] == 'block') { - if ($aLastBlock = $block->getLast()) { - $pps_reward = $aLastBlock['amount']; - } else { - $pps_reward = $config['pps']['reward']['default']; - } - } else { - $pps_reward = $config['pps']['reward']['default']; - } -} - -$aGlobal['ppsvalue'] = number_format(round($pps_reward / (pow(2,32) * $dDifficulty) * pow(2, $config['pps_target']), 12) ,12); - // We don't want these session infos cached if (@$_SESSION['USERDATA']['id']) { $aGlobal['userdata'] = $_SESSION['USERDATA']['id'] ? $user->getUserData($_SESSION['USERDATA']['id']) : array(); @@ -126,13 +108,11 @@ if (@$_SESSION['USERDATA']['id']) { $aGlobal['userdata']['sharerate'] = $statistics->getUserSharerate($_SESSION['USERDATA']['id']); switch ($config['payout_system']) { - case 'prop' || 'pplns': + case 'prop': // Some estimations $aEstimates = $statistics->getUserEstimates($aRoundShares, $aGlobal['userdata']['shares'], $aGlobal['userdata']['donate_percent'], $aGlobal['userdata']['no_fees']); - $aGlobal['userdata']['est_block'] = $aEstimates['block']; - $aGlobal['userdata']['est_fee'] = $aEstimates['fee']; - $aGlobal['userdata']['est_donation'] = $aEstimates['donation']; - $aGlobal['userdata']['est_payout'] = $aEstimates['payout']; + $aGlobal['userdata']['estimates'] = $aEstimates; + break; case 'pplns': $aGlobal['pplns']['target'] = $config['pplns']['shares']['default']; if ($aLastBlock = $block->getLast()) { @@ -140,8 +120,29 @@ if (@$_SESSION['USERDATA']['id']) { $aGlobal['pplns']['target'] = $iAvgBlockShares; } } + $aEstimates = $statistics->getUserEstimates($aRoundShares, $aGlobal['userdata']['shares'], $aGlobal['userdata']['donate_percent'], $aGlobal['userdata']['no_fees']); + $aGlobal['userdata']['estimates'] = $aEstimates; break; case 'pps': + // 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 + if ($config['pps']['reward']['type'] == 'blockavg' && $block->getBlockCount() > 0) { + $pps_reward = round($block->getAvgBlockReward($config['pps']['blockavg']['blockcount'])); + } else { + if ($config['pps']['reward']['type'] == 'block') { + if ($aLastBlock = $block->getLast()) { + $pps_reward = $aLastBlock['amount']; + } else { + $pps_reward = $config['pps']['reward']['default']; + } + } else { + $pps_reward = $config['pps']['reward']['default']; + } + } + + $aGlobal['ppsvalue'] = number_format(round($pps_reward / (pow(2,32) * $dDifficulty) * pow(2, $config['pps_target']), 12) ,12); + $aGlobal['userdata']['sharedifficulty'] = $statistics->getUserShareDifficulty($_SESSION['USERDATA']['id']); + $aGlobal['userdata']['estimates'] = $statistics->getUserEstimates($aGlobal['userdata']['sharerate'], $aGlobal['userdata']['sharedifficulty'], $aGlobal['userdata']['donate_percent'], $aGlobal['userdata']['no_fees'], $aGlobal['ppsvalue']); break; } diff --git a/public/index.php b/public/index.php index f8ccb438..db94059e 100644 --- a/public/index.php +++ b/public/index.php @@ -51,7 +51,13 @@ if (is_dir(INCLUDE_DIR . '/pages/')) { } // Set a default action here if no page has been requested -$page = isset($_REQUEST['page']) && isset($arrPages[$_REQUEST['page']]) ? $_REQUEST['page'] : 'home'; +if (isset($_REQUEST['page']) && isset($arrPages[$_REQUEST['page']])) { + $page = $_REQUEST['page']; +} else if (isset($_REQUEST['page']) && ! isset($arrPages[$_REQUEST['page']])) { + $page = 'error'; +} else { + $page = 'home'; +} // Create our pages array from existing files if (is_dir(INCLUDE_DIR . '/pages/' . $page)) { diff --git a/public/site_assets/mpos/css/layout.css b/public/site_assets/mpos/css/layout.css index bb36f42a..e7b06b9d 100644 --- a/public/site_assets/mpos/css/layout.css +++ b/public/site_assets/mpos/css/layout.css @@ -787,7 +787,7 @@ line-height: 150%; #main h4.info { display: block; width: 95%; -margin: 20px 3% 0 3%; +margin: 20px 30px 0 30px; margin-top: 20px; -webkit-border-radius: 5px; -moz-border-radius: 5px; @@ -803,7 +803,7 @@ font-size: 14px;} #main h4.warning { display: block; width: 95%; -margin: 20px 3% 0 3%; +margin: 20px 30px 0 30px; margin-top: 20px; -webkit-border-radius: 5px; -moz-border-radius: 5px; @@ -819,7 +819,7 @@ font-size: 14px;} #main h4.errormsg { display: block; width: 95%; -margin: 20px 3% 0 3%; +margin: 20px 30px 0 30px; margin-top: 20px; -webkit-border-radius: 5px; -moz-border-radius: 5px; @@ -835,7 +835,7 @@ font-size: 14px;} #main h4.success { display: block; width: 95%; -margin: 20px 3% 0 3%; +margin: 20px 30px 0 30px; margin-top: 20px; -webkit-border-radius: 5px; -moz-border-radius: 5px; diff --git a/public/templates/mmcFE/error/404/default.tpl b/public/templates/mmcFE/error/404/default.tpl new file mode 100644 index 00000000..a951eb30 --- /dev/null +++ b/public/templates/mmcFE/error/404/default.tpl @@ -0,0 +1,3 @@ +{include file="global/block_header.tpl" BLOCK_HEADER="{$GLOBAL.website.name}" BLOCK_STYLE="clear:none; margin-left:13px; margin-top:15px;"} +

The page you requested was not found.

+{include file="global/block_footer.tpl"} diff --git a/public/templates/mmcFE/error/default.tpl b/public/templates/mmcFE/error/default.tpl new file mode 100644 index 00000000..a951eb30 --- /dev/null +++ b/public/templates/mmcFE/error/default.tpl @@ -0,0 +1,3 @@ +{include file="global/block_header.tpl" BLOCK_HEADER="{$GLOBAL.website.name}" BLOCK_STYLE="clear:none; margin-left:13px; margin-top:15px;"} +

The page you requested was not found.

+{include file="global/block_footer.tpl"} diff --git a/public/templates/mmcFE/global/login.tpl b/public/templates/mmcFE/global/login.tpl index 363f403e..9df043a0 100644 --- a/public/templates/mmcFE/global/login.tpl +++ b/public/templates/mmcFE/global/login.tpl @@ -1,4 +1,4 @@ -{include file="global/block_header.tpl" BLOCK_HEADER="Login" BLOCK_STYLE="clear:none; margin-left:13px; margin-top:15px;"} +{include file="global/block_header.tpl" BLOCK_HEADER="Login" BLOCK_STYLE="clear:none; margin-left:13px; margin-top:15px;"}

diff --git a/public/templates/mmcFE/global/sidebar_pplns.tpl b/public/templates/mmcFE/global/sidebar_pplns.tpl index 138b40c5..4923519b 100644 --- a/public/templates/mmcFE/global/sidebar_pplns.tpl +++ b/public/templates/mmcFE/global/sidebar_pplns.tpl @@ -53,19 +53,19 @@ Block - {$GLOBAL.userdata.est_block|number_format:"3"} + {$GLOBAL.userdata.estimates.block|number_format:"3"} Fees - {$GLOBAL.userdata.est_fee|number_format:"3"} + {$GLOBAL.userdata.estimates.fee|number_format:"3"} Donation - {$GLOBAL.userdata.est_donation|number_format:"3"} + {$GLOBAL.userdata.estimates.donation|number_format:"3"} Payout - {$GLOBAL.userdata.est_payout|number_format:"3"} + {$GLOBAL.userdata.estimates.payout|number_format:"3"}   {$GLOBAL.config.currency} Account Balance diff --git a/public/templates/mmcFE/global/sidebar_pps.tpl b/public/templates/mmcFE/global/sidebar_pps.tpl index 2759fc27..19535adb 100644 --- a/public/templates/mmcFE/global/sidebar_pps.tpl +++ b/public/templates/mmcFE/global/sidebar_pps.tpl @@ -42,17 +42,25 @@   {$GLOBAL.config.currency} Estimates + + in 1 hour + {$GLOBAL.userdata.estimates.hours1|round:"8"} + in 24 hours - {($GLOBAL.userdata.sharerate * 24 * 60 * 60 * $GLOBAL.ppsvalue)|number_format:"8"} + {$GLOBAL.userdata.estimates.hours24|round:"8"} in 7 days - {($GLOBAL.userdata.sharerate * 7 * 24 * 60 * 60 * $GLOBAL.ppsvalue)|number_format:"8"} + {$GLOBAL.userdata.estimates.days7|round:"8"} in 14 days - {($GLOBAL.userdata.sharerate * 14 * 24 * 60 * 60 * $GLOBAL.ppsvalue)|number_format:"8"} + {$GLOBAL.userdata.estimates.days14|round:"8"} + + + in 30 days + {$GLOBAL.userdata.estimates.days30|round:"8"}   {$GLOBAL.config.currency} Account Balance diff --git a/public/templates/mmcFE/global/sidebar_prop.tpl b/public/templates/mmcFE/global/sidebar_prop.tpl index 8c9d5e0a..d5ec7fc0 100644 --- a/public/templates/mmcFE/global/sidebar_prop.tpl +++ b/public/templates/mmcFE/global/sidebar_prop.tpl @@ -48,19 +48,19 @@ Block - {$GLOBAL.userdata.est_block|number_format:"8"} + {$GLOBAL.userdata.estimates.block|number_format:"8"} Fees - {$GLOBAL.userdata.est_fee|number_format:"8"} + {$GLOBAL.userdata.estimates.fee|number_format:"8"} Donation - {$GLOBAL.userdata.est_donation|number_format:"8"} + {$GLOBAL.userdata.estimates.donation|number_format:"8"} Payout - {$GLOBAL.userdata.est_payout|number_format:"8"} + {$GLOBAL.userdata.estimates.payout|number_format:"8"}   {$GLOBAL.config.currency} Account Balance diff --git a/public/templates/mmcFE/statistics/blocks/default.tpl b/public/templates/mmcFE/statistics/blocks/default.tpl index 5929524d..2d952f86 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} @@ -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/pool/contributors_hashrate.tpl b/public/templates/mmcFE/statistics/pool/contributors_hashrate.tpl index e5c99524..eaa0a3fc 100644 --- a/public/templates/mmcFE/statistics/pool/contributors_hashrate.tpl +++ b/public/templates/mmcFE/statistics/pool/contributors_hashrate.tpl @@ -15,7 +15,7 @@ {assign var=listed value=0} {section contrib $CONTRIBHASHES} {math assign="estday" equation="round(reward / ( diff * pow(2,32) / ( hashrate * 1000 ) / 3600 / 24), 3)" diff=$DIFFICULTY reward=$REWARD hashrate=$CONTRIBHASHES[contrib].hashrate} - + {$rank++} {if $CONTRIBHASHES[contrib].is_anonymous|default:"0" == 1 && $GLOBAL.userdata.is_admin|default:"0" == 0}anonymous{else}{$CONTRIBHASHES[contrib].account|escape}{/if} {($CONTRIBHASHES[contrib].hashrate * $GLOBAL.hashmods.personal)|number_format:"2"} @@ -23,7 +23,7 @@ {if $GLOBAL.config.price.currency}{($estday * $GLOBAL.price)|default:"n/a"|number_format:"2"}{/if} {/section} -{if $listed != 1 && $GLOBAL.userdata.username|default:""} +{if $listed != 1 && $GLOBAL.userdata.username|default:"" && $GLOBAL.userdata.hashrate|default:"0" > 0} {if $GLOBAL.userdata.hashrate > 0}{math assign="myestday" equation="round(reward / ( diff * pow(2,32) / ( hashrate * 1000 ) / 3600 / 24), 3)" diff=$DIFFICULTY reward=$REWARD hashrate=$GLOBAL.userdata.hashrate}{/if} n/a diff --git a/public/templates/mmcFE/statistics/pool/contributors_shares.tpl b/public/templates/mmcFE/statistics/pool/contributors_shares.tpl index e14d3d8e..f6739727 100644 --- a/public/templates/mmcFE/statistics/pool/contributors_shares.tpl +++ b/public/templates/mmcFE/statistics/pool/contributors_shares.tpl @@ -12,13 +12,13 @@ {assign var=rank value=1} {assign var=listed value=0} {section shares $CONTRIBSHARES} - + {$rank++} {if $CONTRIBSHARES[shares].is_anonymous|default:"0" == 1 && $GLOBAL.userdata.is_admin|default:"0" == 0}anonymous{else}{$CONTRIBSHARES[shares].account|escape}{/if} {$CONTRIBSHARES[shares].shares|number_format} {/section} -{if $listed != 1 && $GLOBAL.userdata.username|default:""} +{if $listed != 1 && $GLOBAL.userdata.username|default:"" && $GLOBAL.userdata.shares.valid|default:"0" > 0} n/a {$GLOBAL.userdata.username|escape} 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;"} - {assign var=rank value=1} -{assign var=listed value=0} {section contrib $ROUNDSHARES} - + - + {/section}
+ + + + + + - - - -
+ + + +
- - + - + @@ -26,7 +34,12 @@ - + @@ -38,7 +51,7 @@ - + @@ -47,19 +60,12 @@
NameValueBlock Round Statistics
ID{$BLOCKDETAILS.id|default:"0"}{$BLOCKDETAILS.id|number_format:"0"|default:"0"}
Height
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
Shares{$BLOCKDETAILS.shares|default:"0"}{$BLOCKDETAILS.shares|number_format:"0"|default:"0"}
Finder
- + - +
- - - -
{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;"} +
+
+ +
+ + + + + + +{assign var=percentage value=0} +{assign var=percentage1 value=0} +{assign var=percentage2 value=0} + +
+ + + +
+ + + + + + + + + + + + + + {if ! $GLOBAL.website.blockexplorer.disabled} + + {else} + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Block Round Statistics
ID{$BLOCKDETAILS.id|number_format:"0"|default:"0"}
Height{$BLOCKDETAILS.height}{$BLOCKDETAILS.height}
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"}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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..aa2d87d0 --- /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" } +
+ + + + + + + + + + + +{assign var=rank value=1} +{assign var=listed value=0} +{section contrib $PPLNSROUNDSHARES} + + + + + + + +{/section} + +
RankUser NameValidInvalidInvalid %
{$rank++}{if $PPLNSROUNDSHARES[contrib].is_anonymous|default:"0" == 1 && $GLOBAL.userdata.is_admin|default:"0" == 0}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}
+
+{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..75ee69a7 --- /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"} +
+ + + + + + + + + + + + + +{assign var=percentage1 value=0} +{section txs $ROUNDTRANSACTIONS} + + + + + + + + + {assign var=percentage1 value=0} + +{/section} + +
User NameRound SharesRound %PPLNS SharesPPLNS Round %VarianceAmount
{if $ROUNDTRANSACTIONS[txs].is_anonymous|default:"0" == 1 && $GLOBAL.userdata.is_admin|default:"0" == 0}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"}
+
+{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..7ea0226b 100644 --- a/public/templates/mmcFE/statistics/round/round_shares.tpl +++ b/public/templates/mmcFE/statistics/round/round_shares.tpl @@ -12,17 +12,17 @@
{$rank++} {if $ROUNDSHARES[contrib].is_anonymous|default:"0" == 1 && $GLOBAL.userdata.is_admin|default:"0" == 0}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}
{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..5d7dbfc1 100644 --- a/public/templates/mmcFE/statistics/round/round_transactions.tpl +++ b/public/templates/mmcFE/statistics/round/round_transactions.tpl @@ -3,18 +3,18 @@ - + {section txs $ROUNDTRANSACTIONS} - - - + + + {/section} @@ -22,3 +22,4 @@
Tx Id User Name TypeRound % Amount
{$ROUNDTRANSACTIONS[txs].id|default:"0"}{$ROUNDTRANSACTIONS[txs].username|escape}{if $ROUNDTRANSACTIONS[txs].is_anonymous|default:"0" == 1 && $GLOBAL.userdata.is_admin|default:"0" == 0}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"}
{include file="global/block_footer.tpl"} + diff --git a/public/templates/mobile/error/404/default.tpl b/public/templates/mobile/error/404/default.tpl new file mode 100644 index 00000000..c423d2fa --- /dev/null +++ b/public/templates/mobile/error/404/default.tpl @@ -0,0 +1 @@ +

The page you requested was not found.

diff --git a/public/templates/mobile/error/default.tpl b/public/templates/mobile/error/default.tpl new file mode 100644 index 00000000..c423d2fa --- /dev/null +++ b/public/templates/mobile/error/default.tpl @@ -0,0 +1 @@ +

The page you requested was not found.

diff --git a/public/templates/mobile/global/sidebar_pplns.tpl b/public/templates/mobile/global/sidebar_pplns.tpl index a7c5fa02..7c25728b 100644 --- a/public/templates/mobile/global/sidebar_pplns.tpl +++ b/public/templates/mobile/global/sidebar_pplns.tpl @@ -46,19 +46,19 @@ Block - {$GLOBAL.userdata.est_block|number_format:"3"} + {$GLOBAL.userdata.estimates.block|number_format:"3"} Fees - {$GLOBAL.userdata.est_fee|number_format:"3"} + {$GLOBAL.userdata.estimates.fee|number_format:"3"} Donation - {$GLOBAL.userdata.est_donation|number_format:"3"} + {$GLOBAL.userdata.estimates.donation|number_format:"3"} Payout - {$GLOBAL.userdata.est_payout|number_format:"3"} + {$GLOBAL.userdata.estimates.payout|number_format:"3"}   {$GLOBAL.config.currency} Account Balance diff --git a/public/templates/mobile/global/sidebar_pps.tpl b/public/templates/mobile/global/sidebar_pps.tpl index e76614dc..71ada55c 100644 --- a/public/templates/mobile/global/sidebar_pps.tpl +++ b/public/templates/mobile/global/sidebar_pps.tpl @@ -35,15 +35,15 @@ {$GLOBAL.config.currency} Estimates in 24 hours - {($GLOBAL.userdata.sharerate * 24 * 60 * 60 * $GLOBAL.ppsvalue)|number_format:"8"} + {$GLOBAL.userdata.estimates.hours24} in 7 days - {($GLOBAL.userdata.sharerate * 7 * 24 * 60 * 60 * $GLOBAL.ppsvalue)|number_format:"8"} + {$GLOBAL.userdata.estimates.days7} in 14 days - {($GLOBAL.userdata.sharerate * 14 * 24 * 60 * 60 * $GLOBAL.ppsvalue)|number_format:"8"} + {$GLOBAL.userdata.estimates.days14}   {$GLOBAL.config.currency} Account Balance diff --git a/public/templates/mobile/global/sidebar_prop.tpl b/public/templates/mobile/global/sidebar_prop.tpl index 858740bc..5ab614a2 100644 --- a/public/templates/mobile/global/sidebar_prop.tpl +++ b/public/templates/mobile/global/sidebar_prop.tpl @@ -38,19 +38,19 @@ Block - {$GLOBAL.userdata.est_block|number_format:"8"} + {$GLOBAL.userdata.estimates.block|number_format:"8"} Fees - {$GLOBAL.userdata.est_fee|number_format:"8"} + {$GLOBAL.userdata.estimates.fee|number_format:"8"} Donation - {$GLOBAL.userdata.est_donation|number_format:"8"} + {$GLOBAL.userdata.estimates.donation|number_format:"8"} Payout - {$GLOBAL.userdata.est_payout|number_format:"8"} + {$GLOBAL.userdata.estimates.payout|number_format:"8"}   {$GLOBAL.config.currency} Account Balance diff --git a/public/templates/mobile/statistics/pool/contributors_hashrate.tpl b/public/templates/mobile/statistics/pool/contributors_hashrate.tpl index 2b23089b..9745f831 100644 --- a/public/templates/mobile/statistics/pool/contributors_hashrate.tpl +++ b/public/templates/mobile/statistics/pool/contributors_hashrate.tpl @@ -22,7 +22,7 @@ {($estday * $GLOBAL.price)|default:"n/a"|number_format:"2"} {/section} -{if $listed != 1} +{if $listed != 1 && $GLOBAL.userdata.username|default:"" && $GLOBAL.userdata.hashrate|default:"0" > 0} n/a {$GLOBAL.userdata.username} diff --git a/public/templates/mobile/statistics/pool/contributors_shares.tpl b/public/templates/mobile/statistics/pool/contributors_shares.tpl index 28322823..f7b5ed63 100644 --- a/public/templates/mobile/statistics/pool/contributors_shares.tpl +++ b/public/templates/mobile/statistics/pool/contributors_shares.tpl @@ -17,7 +17,7 @@ {$CONTRIBSHARES[shares].shares|number_format} {/section} -{if $listed != 1} +{if $listed != 1 && $GLOBAL.userdata.username|default:"" && $GLOBAL.userdata.shares|default:"0" > 0} n/a {$GLOBAL.userdata.username} diff --git a/public/templates/mpos/account/notifications/default.tpl b/public/templates/mpos/account/notifications/default.tpl index 3841d679..4d0facc8 100644 --- a/public/templates/mpos/account/notifications/default.tpl +++ b/public/templates/mpos/account/notifications/default.tpl @@ -1,6 +1,6 @@
- - + +
diff --git a/public/templates/mpos/admin/transactions/default.tpl b/public/templates/mpos/admin/transactions/default.tpl index d21f2c57..9a88324f 100644 --- a/public/templates/mpos/admin/transactions/default.tpl +++ b/public/templates/mpos/admin/transactions/default.tpl @@ -55,7 +55,7 @@
- +
diff --git a/public/templates/mpos/admin/user/default.tpl b/public/templates/mpos/admin/user/default.tpl index 3d7e879d..f9d3eec3 100644 --- a/public/templates/mpos/admin/user/default.tpl +++ b/public/templates/mpos/admin/user/default.tpl @@ -98,8 +98,8 @@
diff --git a/public/templates/mpos/statistics/round/round_transactions.tpl b/public/templates/mpos/statistics/round/round_transactions.tpl index 80af70ad..1ab76f97 100644 --- a/public/templates/mpos/statistics/round/round_transactions.tpl +++ b/public/templates/mpos/statistics/round/round_transactions.tpl @@ -3,18 +3,20 @@ - + + {section txs $ROUNDTRANSACTIONS} - - - + + + + {/section} diff --git a/sql/000_base_structure.sql b/sql/000_base_structure.sql index 948fe036..a8108960 100644 --- a/sql/000_base_structure.sql +++ b/sql/000_base_structure.sql @@ -164,6 +164,8 @@ CREATE TABLE IF NOT EXISTS `statistics_shares` ( `block_id` int(10) unsigned NOT NULL, `valid` int(11) NOT NULL, `invalid` int(11) NOT NULL DEFAULT '0', + `pplns_valid` int(11) NOT NULL, + `pplns_invalid` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `account_id` (`account_id`), KEY `block_id` (`block_id`) 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` ;
TX # User Name TypeRound SharesRound % Amount
{$ROUNDTRANSACTIONS[txs].id|default:"0"}{$ROUNDTRANSACTIONS[txs].username|escape}{if $ROUNDTRANSACTIONS[txs].is_anonymous|default:"0" == 1 && $GLOBAL.userdata.is_admin|default:"0" == 0}anonymous{else}{$ROUNDTRANSACTIONS[txs].username|escape}{/if} {$ROUNDTRANSACTIONS[txs].type|default:""}{$ROUNDSHARES[$ROUNDTRANSACTIONS[txs].uid].valid|number_format}{(( 100 / $BLOCKDETAILS.shares) * $ROUNDSHARES[$ROUNDTRANSACTIONS[txs].uid].valid)|default:"0"|number_format:"2"} {$ROUNDTRANSACTIONS[txs].amount|default:"0"|number_format:"8"}