99 **/
1010class Statistics extends Base {
1111 protected $ table = 'statistics_shares ' ;
12+ protected $ table_user_stats = 'statistics_users ' ;
1213 private $ getcache = true ;
1314
1415 // Disable fetching values from cache
@@ -18,6 +19,12 @@ public function setGetCache($set=false) {
1819 public function getGetCache () {
1920 return $ this ->getcache ;
2021 }
22+ public function getAllUserMiningStats () {
23+ return $ this ->allUserMiningStats ;
24+ }
25+ public function getUserStatsTableName () {
26+ return $ this ->table_user_stats ;
27+ }
2128
2229 /**
2330 * Get our first block found
@@ -104,7 +111,7 @@ public function getBlocksFound($limit=10) {
104111 b.*,
105112 a.username AS finder,
106113 a.is_anonymous AS is_anonymous,
107- ROUND(difficulty * POW(2, 32 - " . $ this ->coin ->getTargetBits () . "), 0), 4) AS estshares
114+ ROUND(difficulty * POW(2, 32 - " . $ this ->coin ->getTargetBits () . "), 0) AS estshares
108115 FROM " . $ this ->block ->getTableName () . " AS b
109116 LEFT JOIN " . $ this ->user ->getTableName () . " AS a
110117 ON b.account_id = a.id
@@ -254,12 +261,12 @@ public function getCurrentShareRate($interval=180) {
254261 SELECT
255262 (
256263 (
257- SELECT ROUND(COUNT(id ) / ?, 2) AS sharerate
264+ SELECT ROUND(SUM(difficulty ) / ?, 2) AS sharerate
258265 FROM " . $ this ->share ->getTableName () . "
259266 WHERE time > DATE_SUB(now(), INTERVAL ? SECOND)
260267 AND our_result = 'Y'
261268 ) + (
262- SELECT ROUND(COUNT(id ) / ?, 2) AS sharerate
269+ SELECT ROUND(SUM(difficulty ) / ?, 2) AS sharerate
263270 FROM " . $ this ->share ->getArchiveTableName () . "
264271 WHERE time > DATE_SUB(now(), INTERVAL ? SECOND)
265272 AND our_result = 'Y'
@@ -451,16 +458,19 @@ public function getAllUserStats($filter='%',$limit=1,$start=0) {
451458
452459 /**
453460 * Fetch all user hashrates based on shares and archived shares
461+ * Store it in cache, also keep a copy of the data internally to
462+ * return it for further processing
454463 * @return data array Set of all user stats
455464 **/
456- public function getAllUserMiningStats ($ interval =180 ) {
465+ public function fetchAllUserMiningStats ($ interval =180 ) {
457466 $ this ->debug ->append ("STA " . __METHOD__ , 4 );
458467 $ stmt = $ this ->mysqli ->prepare ("
459468 SELECT
460469 a.id AS id,
461470 a.username AS account,
471+ COUNT(DISTINCT t1.username) AS workers,
462472 IFNULL(SUM(t1.difficulty), 0) AS shares,
463- ROUND(COUNT (t1.id ) / ?, 2) AS sharerate,
473+ ROUND(SUM (t1.difficulty ) / ?, 2) AS sharerate,
464474 IFNULL(AVG(IF(difficulty=0, pow(2, ( " . $ this ->config ['difficulty ' ] . " - 16)), difficulty)), 0) AS avgsharediff
465475 FROM (
466476 SELECT
@@ -489,12 +499,45 @@ public function getAllUserMiningStats($interval=180) {
489499 $ aData ['data ' ][$ row ['id ' ]] = $ row ;
490500 $ aData ['data ' ][$ row ['id ' ]]['hashrate ' ] = $ this ->coin ->calcHashrate ($ row ['shares ' ], $ interval );
491501 }
502+ $ this ->allUserMiningStats = $ aData ;
492503 return $ this ->memcache ->setStaticCache (STATISTICS_ALL_USER_HASHRATES , $ aData , 600 );
493504 } else {
494505 return $ this ->sqlError ();
495506 }
496507 }
497508
509+ /**
510+ * Store our gathered data into our statistic table for users
511+ * @param aData array Data created by fetchAllUserMiningStats
512+ * @return bool true or false
513+ **/
514+ public function storeAllUserMiningStatsSnapshot ($ aData ) {
515+ $ this ->debug ->append ("STA " . __METHOD__ , 4 );
516+ if (!isset ($ aData ['data ' ])) return false ;
517+ // initilize
518+ $ timestamp = time (); // Store all entries with the same timestamp to reduce cardinality
519+ $ ok = 0 ;
520+ $ failed = 0 ;
521+ foreach ($ aData ['data ' ] as $ key => $ aUserData ) {
522+ $ stmt = $ this ->mysqli ->prepare ("
523+ INSERT INTO " . $ this ->getUserStatsTableName () . "
524+ ( account_id, hashrate, workers, sharerate, timestamp ) VALUES ( ?, ?, ?, ?, ?) " );
525+ if ($ this ->checkStmt ($ stmt ) && $ stmt ->bind_param ("ididi " , $ aUserData ['id ' ], $ aUserData ['hashrate ' ], $ aUserData ['workers ' ], $ aUserData ['sharerate ' ], $ timestamp ) && $ stmt ->execute () ) {
526+ $ ok ++;
527+ } else {
528+ $ failed ++;
529+ }
530+ }
531+ return array ('ok ' => $ ok , 'failed ' => $ failed );
532+ }
533+
534+ /**
535+ * Fetch unpaid PPS shares for an account
536+ * @param username string Username
537+ * @param account_id int User ID
538+ * @param last_paid_pps_id int Last paid out share by pps_payout cron
539+ * @return data int Sum of unpaid diff1 shares
540+ **/
498541 public function getUserUnpaidPPSShares ($ username , $ account_id =NULL , $ last_paid_pps_id ) {
499542 $ this ->debug ->append ("STA " . __METHOD__ , 4 );
500543 if ($ this ->getGetCache () && $ data = $ this ->memcache ->get (__FUNCTION__ . $ account_id )) return $ data ;
@@ -515,7 +558,7 @@ public function getUserUnpaidPPSShares($username, $account_id=NULL, $last_paid_p
515558 * Get Shares per x interval by user
516559 * @param username string username
517560 * @param $account_id int account id
518- * @return data integer Current Sharerate in shares/s
561+ * @return data integer Current Sharerate in diff1 shares/s
519562 **/
520563 public function getUserMiningStats ($ username , $ account_id =NULL , $ interval =180 ) {
521564 $ this ->debug ->append ("STA " . __METHOD__ , 4 );
@@ -532,7 +575,7 @@ public function getUserMiningStats($username, $account_id=NULL, $interval=180) {
532575 if ($ this ->getGetCache () && $ data = $ this ->memcache ->get (__FUNCTION__ . $ account_id )) return $ data ;
533576 $ stmt = $ this ->mysqli ->prepare ("
534577 SELECT
535- IFNULL(COUNT(* ) / ?, 0) AS sharerate,
578+ IFNULL(SUM(difficulty ) / ?, 0) AS sharerate,
536579 IFNULL(SUM(difficulty), 0) AS shares,
537580 IFNULL(AVG(difficulty), 0) AS avgsharediff
538581 FROM (
@@ -655,78 +698,24 @@ public function getTopContributors($type='shares', $limit=15) {
655698 * @param $account_id int account id
656699 * @return data array NOT FINISHED YET
657700 **/
658- public function getHourlyHashrateByAccount ( $ username , $ account_id = NULL ) {
701+ public function getHourlyMiningStatsByAccount ( $ account_id , $ format = ' array ' , $ days = 1 ) {
659702 $ this ->debug ->append ("STA " . __METHOD__ , 4 );
660703 if ($ data = $ this ->memcache ->get (__FUNCTION__ . $ account_id )) return $ data ;
661704 $ stmt = $ this ->mysqli ->prepare ("
662705 SELECT
663- id,
664- IFNULL(SUM(IF(difficulty=0, pow(2, ( " . $ this ->config ['difficulty ' ] . " - 16)), difficulty)), 0) AS shares,
665- HOUR(time) AS hour
666- FROM " . $ this ->share ->getTableName () . "
667- WHERE time <= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60))
668- AND time >= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60)) - INTERVAL 24 HOUR
669- AND our_result = 'Y'
670- AND username LIKE ?
671- GROUP BY HOUR(time)
672- UNION
673- SELECT
674- share_id,
675- IFNULL(SUM(IF(difficulty=0, pow(2, ( " . $ this ->config ['difficulty ' ] . " - 16)), difficulty)), 0) AS shares,
676- HOUR(time) AS hour
677- FROM " . $ this ->share ->getArchiveTableName () . "
678- WHERE time <= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60))
679- AND time >= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60)) - INTERVAL 24 HOUR
680- AND our_result = 'Y'
681- AND username LIKE ?
682- GROUP BY HOUR(time) " );
683- $ username = $ username . ".% " ;
684- if ($ this ->checkStmt ($ stmt ) && $ stmt ->bind_param ('ss ' , $ username , $ username ) && $ stmt ->execute () && $ result = $ stmt ->get_result ()) {
685- $ iStartHour = date ('G ' );
686- // Initilize array
687- for ($ i = 0 ; $ i < 24 ; $ i ++) $ aData [($ iStartHour + $ i ) % 24 ] = 0 ;
688- // Fill data
689- while ($ row = $ result ->fetch_assoc ()) $ aData [$ row ['hour ' ]] += (int ) $ this ->coin ->calcHashrate ($ row ['shares ' ], 3600 );
690- return $ this ->memcache ->setCache (__FUNCTION__ . $ account_id , $ aData );
691- }
692- return $ this ->sqlError ();
693- }
694-
695- /**
696- * get Hourly hashrate for the pool
697- * @param none
698- * @return data array NOT FINISHED YET
699- **/
700- public function getHourlyHashrateByPool () {
701- $ this ->debug ->append ("STA " . __METHOD__ , 4 );
702- if ($ this ->getGetCache () && $ data = $ this ->memcache ->get (__FUNCTION__ )) return $ data ;
703- $ stmt = $ this ->mysqli ->prepare ("
704- SELECT
705- id,
706- IFNULL(SUM(IF(s.difficulty=0, pow(2, ( " . $ this ->config ['difficulty ' ] . " - 16)), s.difficulty)), 0) AS shares,
707- HOUR(s.time) AS hour
708- FROM " . $ this ->share ->getTableName () . " AS s
709- WHERE time <= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60))
710- AND time >= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60)) - INTERVAL 24 HOUR
711- AND our_result = 'Y'
712- GROUP BY HOUR(time)
713- UNION
714- SELECT
715- share_id,
716- IFNULL(SUM(IF(s.difficulty=0, pow(2, ( " . $ this ->config ['difficulty ' ] . " - 16)), s.difficulty)), 0) AS shares,
717- HOUR(s.time) AS hour
718- FROM " . $ this ->share ->getArchiveTableName () . " AS s
719- WHERE time <= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60))
720- AND time >= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60)) - INTERVAL 24 HOUR
721- AND our_result = 'Y'
722- GROUP BY HOUR(time) " );
723- if ($ this ->checkStmt ($ stmt ) && $ stmt ->execute () && $ result = $ stmt ->get_result ()) {
724- $ iStartHour = date ('G ' );
725- // Initilize array
726- for ($ i = 0 ; $ i < 24 ; $ i ++) $ aData [($ iStartHour + $ i ) % 24 ] = 0 ;
727- // Fill data
728- while ($ row = $ result ->fetch_assoc ()) $ aData [$ row ['hour ' ]] += (int ) $ this ->coin ->calcHashrate ($ row ['shares ' ], 3600 );
729- return $ this ->memcache ->setCache (__FUNCTION__ , $ aData );
706+ timestamp,
707+ FROM_UNIXTIME(timestamp, '%Y-%m-%d %H:%i') AS time,
708+ AVG(hashrate) AS hashrate,
709+ AVG(workers) AS workers,
710+ AVG(sharerate) AS sharerate
711+ FROM " . $ this ->getUserStatsTableName () . "
712+ WHERE FROM_UNIXTIME(timestamp) >= DATE_SUB(NOW(), INTERVAL $ days DAY)
713+ AND account_id = ?
714+ GROUP BY DAY(FROM_UNIXTIME(timestamp)), HOUR(FROM_UNIXTIME(timestamp)) " );
715+ if ($ this ->checkStmt ($ stmt ) && $ stmt ->bind_param ('i ' , $ account_id ) && $ stmt ->execute () && $ result = $ stmt ->get_result ()) {
716+ $ aData = $ result ->fetch_all (MYSQLI_ASSOC );
717+ if ($ format == 'json ' ) $ aData = json_encode ($ aData );
718+ return $ this ->memcache ->setCache (__FUNCTION__ . $ account_id . $ format , $ aData );
730719 }
731720 return $ this ->sqlError ();
732721 }
@@ -914,6 +903,17 @@ public function getCountAllActiveUsers($interval=120) {
914903 return $ this ->memcache ->setCache (__FUNCTION__ , $ result ->fetch_object ()->total );
915904 return $ this ->sqlError ();
916905 }
906+
907+ /**
908+ * Purge older entries from our statistics_users table
909+ **/
910+ public function purgeUserStats ($ days = 1 ) {
911+ // Fallbacks if unset
912+ $ stmt = $ this ->mysqli ->prepare ("DELETE FROM " . $ this ->getUserStatsTableName () . " WHERE FROM_UNIXTIME(timestamp) <= DATE_SUB(NOW(), INTERVAL ? DAY) " );
913+ if ($ this ->checkStmt ($ stmt ) && $ stmt ->bind_param ('i ' , $ days ) && $ stmt ->execute ())
914+ return $ stmt ->affected_rows ;
915+ return $ this ->sqlError ();
916+ }
917917}
918918
919919$ statistics = new Statistics ();
0 commit comments