From 602256c443f5d54054a2c6f05d71e9915eb2d666 Mon Sep 17 00:00:00 2001 From: kanoi Date: Fri, 19 Dec 2014 17:16:33 +1100 Subject: [PATCH] ckdb/php - add user % stats and menus --- pool/db.php | 12 ++ pool/page_api.php | 22 +++- pool/page_percent.php | 174 ++++++++++++++++++++++++++ pool/prime.php | 4 +- src/ckdb.h | 2 +- src/ckdb_cmd.c | 281 ++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 478 insertions(+), 17 deletions(-) create mode 100644 pool/page_percent.php diff --git a/pool/db.php b/pool/db.php index 02028a90..7002d0d5 100644 --- a/pool/db.php +++ b/pool/db.php @@ -234,6 +234,18 @@ function getWorkers($user, $stats = 'Y') return repDecode($rep); } # +function getPercents($user, $stats = 'Y') +{ + if ($user == false) + showIndex(); + $flds = array('username' => $user, 'stats' => $stats, 'percent' => 'Y'); + $msg = msgEncode('workers', 'work', $flds, $user); + $rep = sendsockreply('getPercents', $msg); + if (!$rep) + dbdown(); + return repDecode($rep); +} +# function getPayments($user) { if ($user == false) diff --git a/pool/page_api.php b/pool/page_api.php index 82fbf0a6..234d4235 100644 --- a/pool/page_api.php +++ b/pool/page_api.php @@ -29,8 +29,7 @@ function show_api($info, $page, $menu, $name, $user) no_api($jfu); if (nuem($work)) { - if ($info === NULL) - $info = homeInfo($u); + $info = homeInfo($u); if ($info === false) no_api($jfu); $rep = fldEncode($info, 'lastbc', true); @@ -47,9 +46,26 @@ function show_api($info, $page, $menu, $name, $user) } else { - $ans = getWorkers($u); + $info = homeInfo($u); + if ($info === false) + no_api($jfu); + + $per = false; + if (is_array($info) && isset($info['u_multiaddr'])) + { + $percent = getparam('percent', true); + if (!nuem($percent)) + $per = true; + } + + if ($per === true) + $ans = getPercents($u); + else + $ans = getWorkers($u); + if ($ans === false) no_api($jfu); + $rep = fldEncode($ans, 'rows', true); $rows = $ans['rows']; $flds = explode(',', $ans['flds']); diff --git a/pool/page_percent.php b/pool/page_percent.php new file mode 100644 index 00000000..2cd5b887 --- /dev/null +++ b/pool/page_percent.php @@ -0,0 +1,174 @@ +'; + $pg .= 'Address'; + $pg .= 'Shares'; + $pg .= 'Diff'; + $pg .= 'Invalid'; + $pg .= 'Block %'; + $pg .= 'Hash Rate'; + $pg .= 'Ratio'; + $pg .= 'Addr %'; + $pg .= "\n"; + return $pg; +} +# +function perhashorder($a, $b) +{ + return $b['payratio'] - $a['payratio']; +} +# +function peruser($data, $user, &$offset, &$totshare, &$totdiff, + &$totinvalid, &$totrate, &$blockacc, + &$blockreward, $srt = false) +{ + $ans = getPercents($user); + + $pg = ''; + if ($ans['STATUS'] == 'ok') + { + if (isset($ans['blockacc'])) + $blockacc = $ans['blockacc']; + if (isset($ans['blockreward'])) + $blockreward = $ans['blockreward']; + $all = array(); + $count = $ans['rows']; + for ($i = 0; $i < $count; $i++) + { + $all[] = array('payaddress' => $ans['payaddress:'.$i], + 'payratio' => $ans['payratio:'.$i], + 'paypercent' => $ans['paypercent:'.$i], + 'p_shareacc' => $ans['p_shareacc:'.$i], + 'p_diffacc' => $ans['p_diffacc:'.$i], + 'p_diffinv' => $ans['p_diffinv:'.$i], + 'p_uhr' => $ans['p_hashrate5m:'.$i]); + } + + if ($srt) + usort($all, 'perhashorder'); + + for ($i = 0; $i < $count; $i++) + { + if ((($offset) % 2) == 0) + $row = 'even'; + else + $row = 'odd'; + + $pg .= ""; + $pg .= ''.$all[$i]['payaddress'].''; + + $shareacc = number_format($all[$i]['p_shareacc'], 0); + $totshare += $all[$i]['p_shareacc']; + $diffacc = number_format($all[$i]['p_diffacc'], 0); + $totdiff += $all[$i]['p_diffacc']; + $pg .= "$shareacc"; + $pg .= "$diffacc"; + + $dtot = $all[$i]['p_diffacc'] + $all[$i]['p_diffinv']; + if ($dtot > 0) + $rej = number_format(100.0 * $all[$i]['p_diffinv'] / $dtot, 3); + else + $rej = '0'; + $totinvalid += $all[$i]['p_diffinv']; + + $pg .= "$rej%"; + + if ($blockacc <= 0) + $blkpct = ' '; + else + $blkpct = number_format(100.0 * $all[$i]['p_diffacc'] / $blockacc, 3) . '%'; + + $pg .= "$blkpct"; + + $uhr = $all[$i]['p_uhr']; + if ($uhr == '?') + $uhr = '?GHs'; + else + { + $totrate += $uhr; + $uhr = dsprate($uhr); + } + $pg .= "$uhr"; + + $pg .= ''.$all[$i]['payratio'].''; + $paypct = number_format($all[$i]['paypercent'], 3); + $pg .= "$paypct%"; + + $pg .= "\n"; + + $offset++; + } + } + return $pg; +} +# +function pertotal($offset, $totshare, $totdiff, $totinvalid, $totrate, $blockacc, $blockreward) +{ + $pg = ''; + $totrate = dsprate($totrate); + if (($offset % 2) == 0) + $row = 'even'; + else + $row = 'odd'; + $pg .= "Total:"; + $shareacc = number_format($totshare, 0); + $pg .= "$shareacc"; + $diffacc = number_format($totdiff, 0); + $pg .= "$diffacc"; + $dtot = $totdiff + $totinvalid; + if ($dtot > 0) + $rej = number_format(100.0 * $totinvalid / $dtot, 3); + else + $rej = '0'; + $pg .= "$rej%"; + if ($blockacc <= 0) + $blkpct = ' '; + else + $blkpct = number_format(100.0 * $totdiff / $blockacc, 3) . '%'; + $pg .= "$blkpct"; + $pg .= "$totrate"; + $pg .= "\n"; + return $pg; +} +# +function dopercent($data, $user) +{ + $pg = '

Address Percents

'; + + $pg .= "\n"; + + $totshare = 0; + $totdiff = 0; + $totinvalid = 0; + $totrate = 0; + $offset = 0; + $blockacc = 0; + $blockreward = 0; + + $pg .= pertitle($data, $user); + $pg .= peruser($data, $user, $offset, $totshare, $totdiff, $totinvalid, + $totrate, $blockacc, $blockreward, true); + $pg .= pertotal($offset, $totshare, $totdiff, $totinvalid, $totrate, + $blockacc, $blockreward); + + if ($blockacc > 0 && $blockreward > 0) + { + $btc = btcfmt($totdiff / $blockacc * $blockreward); + $pg .= ''; + } + + $pg .= "
'; + $pg .= "
Payout est if block found at 100%: ~$btc BTC"; + $pg .= '
\n"; + + return $pg; +} +# +function show_percent($info, $page, $menu, $name, $user) +{ + gopage($info, NULL, 'dopercent', $page, $menu, $name, $user); +} +# +?> diff --git a/pool/prime.php b/pool/prime.php index af2bf796..135bea3e 100644 --- a/pool/prime.php +++ b/pool/prime.php @@ -13,8 +13,10 @@ function process($p, $user, $menu) { if (isset($menu['Account'])) $menu['Account']['Addresses'] = 'addrmgt'; + if (isset($menu['Workers'])) + $menu['Workers']['Percents'] = 'percent'; } - if ($user == 'Kano' || $user == 'ckolivas' || $user == 'wvr2' || $user == 'aphorise') + if ($user == 'Kano' || $user == 'ckolivas') { $menu['Admin']['ckp'] = 'ckp'; $menu['Admin']['PPLNS'] = 'pplns'; diff --git a/src/ckdb.h b/src/ckdb.h index 07584c2a..f3a1e885 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.6" -#define CKDB_VERSION DB_VERSION"-0.760" +#define CKDB_VERSION DB_VERSION"-0.770" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 9f3ae8bb..4030804c 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -1141,12 +1141,256 @@ static char *cmd_payments(__maybe_unused PGconn *conn, char *cmd, char *id, return buf; } +static char *cmd_percent(char *cmd, char *id, tv_t *now, USERS *users) +{ + K_ITEM w_look, *w_item, us_look, *us_item, *ws_item; + K_TREE_CTX w_ctx[1], us_ctx[1], pay_ctx[1]; + WORKERS lookworkers, *workers; + WORKERSTATUS *workerstatus; + USERSTATS lookuserstats, *userstats; + char tmp[1024]; + char *buf; + size_t len, off; + int rows; + + K_TREE *userstats_workername_root = new_ktree(); + K_TREE_CTX usw_ctx[1]; + double t_hashrate5m = 0, t_hashrate1hr = 0; + double t_hashrate24hr = 0; + double t_diffacc = 0, t_diffinv = 0; + double t_diffsta = 0, t_diffdup = 0; + double t_diffhi = 0, t_diffrej = 0; + double t_shareacc = 0, t_shareinv = 0; + double t_sharesta = 0, t_sharedup = 0; + double t_sharehi = 0, t_sharerej = 0; + + K_ITEM *pa_item; + PAYMENTADDRESSES *pa; + int64_t paytotal; + double ratio; + + LOGDEBUG("%s(): cmd '%s'", __func__, cmd); + + APPEND_REALLOC_INIT(buf, off, len); + APPEND_REALLOC(buf, off, len, "ok."); + snprintf(tmp, sizeof(tmp), "blockacc=%.1f%c", + pool.diffacc, FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + snprintf(tmp, sizeof(tmp), "blockreward=%"PRId64"%c", + pool.reward, FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + INIT_WORKERS(&w_look); + INIT_USERSTATS(&us_look); + + // Add up all user's worker stats to be divided into payout percentages + lookworkers.userid = users->userid; + lookworkers.workername[0] = '\0'; + lookworkers.expirydate.tv_sec = 0; + lookworkers.expirydate.tv_usec = 0; + w_look.data = (void *)(&lookworkers); + w_item = find_after_in_ktree(workers_root, &w_look, cmp_workers, w_ctx); + DATA_WORKERS_NULL(workers, w_item); + while (w_item && workers->userid == users->userid) { + if (CURRENT(&(workers->expirydate))) { + ws_item = find_workerstatus(users->userid, workers->workername, + __FILE__, __func__, __LINE__); + if (ws_item) { + DATA_WORKERSTATUS(workerstatus, ws_item); + t_diffacc += workerstatus->diffacc; + t_diffinv += workerstatus->diffinv; + t_diffsta += workerstatus->diffsta; + t_diffdup += workerstatus->diffdup; + t_diffhi += workerstatus->diffhi; + t_diffrej += workerstatus->diffrej; + t_shareacc += workerstatus->shareacc; + t_shareinv += workerstatus->shareinv; + t_sharesta += workerstatus->sharesta; + t_sharedup += workerstatus->sharedup; + t_sharehi += workerstatus->sharehi; + t_sharerej += workerstatus->sharerej; + } + + // find last stored userstats record + lookuserstats.userid = users->userid; + lookuserstats.statsdate.tv_sec = date_eot.tv_sec; + lookuserstats.statsdate.tv_usec = date_eot.tv_usec; + // find/cmp doesn't get to here + lookuserstats.poolinstance[0] = '\0'; + lookuserstats.workername[0] = '\0'; + us_look.data = (void *)(&lookuserstats); + K_RLOCK(userstats_free); + us_item = find_before_in_ktree(userstats_root, &us_look, cmp_userstats, us_ctx); + DATA_USERSTATS_NULL(userstats, us_item); + while (us_item && userstats->userid == lookuserstats.userid) { + if (strcmp(userstats->workername, workers->workername) == 0) { + if (tvdiff(now, &(userstats->statsdate)) < USERSTATS_PER_S) { + if (!find_in_ktree(userstats_workername_root, us_item, + cmp_userstats_workername, usw_ctx)) { + t_hashrate5m += userstats->hashrate5m; + t_hashrate1hr += userstats->hashrate1hr; + t_hashrate24hr += userstats->hashrate24hr; + userstats_workername_root = + add_to_ktree(userstats_workername_root, + us_item, + cmp_userstats_workername); + } + } else + break; + + } + us_item = prev_in_ktree(us_ctx); + DATA_USERSTATS_NULL(userstats, us_item); + } + K_RUNLOCK(userstats_free); + } + w_item = next_in_ktree(w_ctx); + DATA_WORKERS_NULL(workers, w_item); + } + + userstats_workername_root = free_ktree(userstats_workername_root, NULL); + + // Calculate total payratio + paytotal = 0; + K_RLOCK(paymentaddresses_free); + pa_item = find_paymentaddresses(users->userid, pay_ctx); + DATA_PAYMENTADDRESSES(pa, pa_item); + while (pa_item && CURRENT(&(pa->expirydate)) && + pa->userid == users->userid) { + paytotal += pa->payratio; + pa_item = prev_in_ktree(pay_ctx); + DATA_PAYMENTADDRESSES_NULL(pa, pa_item); + } + if (paytotal == 0) + paytotal = 1; + + // Divide totals into payout percentages + rows = 0; + pa_item = find_paymentaddresses(users->userid, pay_ctx); + DATA_PAYMENTADDRESSES_NULL(pa, pa_item); + while (pa_item && CURRENT(&(pa->expirydate)) && + pa->userid == users->userid) { + ratio = (double)(pa->payratio) / (double)paytotal; + + snprintf(tmp, sizeof(tmp), "payaddress:%d=%s%c", + rows, pa->payaddress, FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "payratio:%d=%"PRId32"%c", + rows, pa->payratio, FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "paypercent:%d=%.6f%c", + rows, ratio * 100.0, FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_hashrate5m:%d=%.1f%c", rows, + (double)t_hashrate5m * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_hashrate1hr:%d=%.1f%c", rows, + (double)t_hashrate1hr * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_hashrate24hr:%d=%.1f%c", rows, + (double)t_hashrate24hr * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_diffacc:%d=%.1f%c", rows, + (double)t_diffacc * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_diffinv:%d=%.1f%c", rows, + (double)t_diffinv * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_diffsta:%d=%.1f%c", rows, + (double)t_diffsta * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_diffdup:%d=%.1f%c", rows, + (double)t_diffdup * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_diffhi:%d=%.1f%c", rows, + (double)t_diffhi * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_diffrej:%d=%.1f%c", rows, + (double)t_diffrej * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_shareacc:%d=%.1f%c", rows, + (double)t_shareacc * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_shareinv:%d=%.1f%c", rows, + (double)t_shareinv * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_sharesta:%d=%.1f%c", rows, + (double)t_sharesta * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_sharedup:%d=%.1f%c", rows, + (double)t_sharedup * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_sharehi:%d=%.1f%c", rows, + (double)t_sharehi * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "p_sharerej:%d=%.1f%c", rows, + (double)t_sharerej * ratio, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + rows++; + + pa_item = prev_in_ktree(pay_ctx); + DATA_PAYMENTADDRESSES_NULL(pa, pa_item); + } + + snprintf(tmp, sizeof(tmp), + "rows=%d%cflds=%s%c", + rows, FLDSEP, + "payaddress,payratio,paypercent," + "p_hashrate5m,p_hashrate1hr,p_hashrate24hr," + "p_diffacc,p_diffinv," + "p_diffsta,p_diffdup,p_diffhi,p_diffrej," + "p_shareacc,p_shareinv," + "p_sharesta,p_sharedup,p_sharehi,p_sharerej", + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + + snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s", "Percents", FLDSEP, ""); + APPEND_REALLOC(buf, off, len, tmp); + + LOGDEBUG("%s.ok.%s", id, users->username); + return buf; +} + static char *cmd_workers(__maybe_unused PGconn *conn, char *cmd, char *id, - __maybe_unused tv_t *now, __maybe_unused char *by, + tv_t *now, __maybe_unused char *by, __maybe_unused char *code, __maybe_unused char *inet, __maybe_unused tv_t *notcd, K_TREE *trf_root) { - K_ITEM *i_username, *i_stats, w_look, *u_item, *w_item, us_look, *us_item, *ws_item; + K_ITEM *i_username, *i_stats, *i_percent, w_look, *u_item, *w_item; + K_ITEM *ua_item, us_look, *us_item, *ws_item; K_TREE_CTX w_ctx[1], us_ctx[1]; WORKERS lookworkers, *workers; WORKERSTATUS *workerstatus; @@ -1157,7 +1401,7 @@ static char *cmd_workers(__maybe_unused PGconn *conn, char *cmd, char *id, size_t siz = sizeof(reply); char *buf; size_t len, off; - bool stats; + bool stats, percent; int rows; LOGDEBUG("%s(): cmd '%s'", __func__, cmd); @@ -1179,16 +1423,19 @@ static char *cmd_workers(__maybe_unused PGconn *conn, char *cmd, char *id, else stats = (strcasecmp(transfer_data(i_stats), TRUE_STR) == 0); - INIT_WORKERS(&w_look); - INIT_USERSTATS(&us_look); + percent = false; + K_RLOCK(useratts_free); + ua_item = find_useratts(users->userid, USER_MULTI_PAYOUT); + K_RUNLOCK(useratts_free); + if (ua_item) { + i_percent = optional_name(trf_root, "percent", 1, NULL, reply, siz); + if (i_percent) + percent = (strcasecmp(transfer_data(i_stats), TRUE_STR) == 0); + } + + if (percent) + return cmd_percent(cmd, id, now, users); - lookworkers.userid = users->userid; - lookworkers.workername[0] = '\0'; - lookworkers.expirydate.tv_sec = 0; - lookworkers.expirydate.tv_usec = 0; - w_look.data = (void *)(&lookworkers); - w_item = find_after_in_ktree(workers_root, &w_look, cmp_workers, w_ctx); - DATA_WORKERS_NULL(workers, w_item); APPEND_REALLOC_INIT(buf, off, len); APPEND_REALLOC(buf, off, len, "ok."); snprintf(tmp, sizeof(tmp), "blockacc=%.1f%c", @@ -1198,6 +1445,16 @@ static char *cmd_workers(__maybe_unused PGconn *conn, char *cmd, char *id, pool.reward, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); + INIT_WORKERS(&w_look); + INIT_USERSTATS(&us_look); + + lookworkers.userid = users->userid; + lookworkers.workername[0] = '\0'; + lookworkers.expirydate.tv_sec = 0; + lookworkers.expirydate.tv_usec = 0; + w_look.data = (void *)(&lookworkers); + w_item = find_after_in_ktree(workers_root, &w_look, cmp_workers, w_ctx); + DATA_WORKERS_NULL(workers, w_item); rows = 0; while (w_item && workers->userid == users->userid) { if (CURRENT(&(workers->expirydate))) {