From 1c60e467a7b38af39b039348d371a54c856cb38f Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 28 Sep 2014 08:11:51 -0700 Subject: [PATCH] web: add page (per_app_list.php) to show top users/teams by app Notes: - it's per app, not per sub-project; that would have been harder - it only shows the top 20 Also: shuffle code to reduce recursive includes. --- html/inc/boinc_db.inc | 14 ++++ html/inc/db.inc | 32 ++++----- html/inc/db_conn.inc | 17 ----- html/inc/team.inc | 8 ++- html/user/per_app_list.php | 129 +++++++++++++++++++++++++++++++++++++ html/user/stats.php | 11 +++- 6 files changed, 175 insertions(+), 36 deletions(-) create mode 100644 html/user/per_app_list.php diff --git a/html/inc/boinc_db.inc b/html/inc/boinc_db.inc index 51146d89d0..cb00a2547c 100644 --- a/html/inc/boinc_db.inc +++ b/html/inc/boinc_db.inc @@ -684,4 +684,18 @@ class BoincCreditTeam { } } +// DEPRECATED: use BoincDb::escape_string where possible +// +// apply this to any user-supplied strings used in queries +// +function boinc_real_escape_string($x) { + if (version_compare(phpversion(),"4.3.0")>=0) { + return BoincDb::escape_string($x); + } else { + $x = str_replace("'", "\'", $x); + $x = str_replace("\"", "\\\"", $x); + return $x; + } +} + ?> diff --git a/html/inc/db.inc b/html/inc/db.inc index e239d4aabe..533ad16d65 100644 --- a/html/inc/db.inc +++ b/html/inc/db.inc @@ -16,8 +16,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see . -require_once('../inc/util.inc'); -require_once('../inc/boinc_db.inc'); +require_once('../project/project.inc'); // database-related functions. // Presentation code (HTML) shouldn't be here @@ -25,6 +24,21 @@ require_once('../inc/boinc_db.inc'); // DEPRECATED; use boinc_db.inc instead. // TODO: replace calls to these functions +// use mysqli if available, +// but let projects not use it if they want +// (by define('NO_MYSQLI', true) in project.inc) +// +if (defined('NO_MYSQLI') && NO_MYSQLI) { + define("MYSQLI", false); +} else { + if (class_exists("mysqli")) { + define("MYSQLI", true); + $mysqli = null; + } else { + define("MYSQLI", false); + } +} + if (MYSQLI) { function _mysql_connect($host, $user, $pass, $dbname) { global $mysqli; @@ -170,20 +184,6 @@ function db_init_aux($try_replica=false) { return 0; } -// DEPRECATED: use BoincDb::escape_string where possible -// -// apply this to any user-supplied strings used in queries -// -function boinc_real_escape_string($x) { - if (version_compare(phpversion(),"4.3.0")>=0) { - return BoincDb::escape_string($x); - } else { - $x = str_replace("'", "\'", $x); - $x = str_replace("\"", "\\\"", $x); - return $x; - } -} - // escape a string for MySQL "like" // function escape_pattern($str) { diff --git a/html/inc/db_conn.inc b/html/inc/db_conn.inc index 6e4ef49a3f..da9092dd50 100644 --- a/html/inc/db_conn.inc +++ b/html/inc/db_conn.inc @@ -16,23 +16,6 @@ // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see . -require_once("../project/project.inc"); - -// use mysqli if available, -// but let projects not use it if they want -// (by define('NO_MYSQLI', true) in project.inc) -// -if (defined('NO_MYSQLI') && NO_MYSQLI) { - define("MYSQLI", false); -} else { - if (class_exists("mysqli")) { - define("MYSQLI", true); - $mysqli = null; - } else { - define("MYSQLI", false); - } -} - // represents a connection to a database. // Intended to be subclassed (e.g., BoincDb, BossaDb) // diff --git a/html/inc/team.inc b/html/inc/team.inc index ce45b1c01f..e0db7e5caa 100644 --- a/html/inc/team.inc +++ b/html/inc/team.inc @@ -383,14 +383,18 @@ function team_table_start($sort_by, $type_url) { "; } +function team_links($team) { + $b = badges_string(false, $team, BADGE_HEIGHT_MEDIUM); + return "id>$team->name $b"; +} + function show_team_row($team, $i) { $team_expavg_credit = format_credit_large($team->expavg_credit); $team_total_credit = format_credit_large($team->total_credit); $j = $i % 2; - $b = badges_string(false, $team, BADGE_HEIGHT_MEDIUM); echo" $i - id>$team->name $b + ".team_links($team)." ".$team->nusers." $team_expavg_credit $team_total_credit diff --git a/html/user/per_app_list.php b/html/user/per_app_list.php new file mode 100644 index 0000000000..c5afb5fe73 --- /dev/null +++ b/html/user/per_app_list.php @@ -0,0 +1,129 @@ +. + +// show top users or teams, ordered by per-app credit +// +// URL args: +// is_team: if nonzero, show teams +// appid: ID of app for sorting; default is first app returned by enum +// is_total: if nonzero, sort by total credit + +require_once("../inc/util.inc"); + +// return a column title (Average or Total), +// hyperlinked if this is not the current sort column +// +function col_title($is_team, $app, $appid, $is_total, $i) { + $x = $i?"Total":"Average"; + if ($app->id == $appid && ($is_total?$i:!$i)) { + return $x; + } else { + return "id&is_team=$is_team&is_total=$i>$x"; + } +} + +// print a row of app names, +// under each of which are columns for Average and Total +// +function show_header($is_team, $apps, $appid, $is_total) { + echo " "; + foreach ($apps as $app) { + echo "$app->name\n"; + } + echo ""; + + echo ""; + echo "RankName\n"; + foreach ($apps as $app) { + for ($i=0; $i<2; $i++) { + $x = col_title($is_team, $app, $appid, $is_total, $i); + echo "$x\n"; + } + } + echo ""; + +} + +// show a user or team, with their credit for each app +// +function show_row($item, $apps, $is_team, $i) { + $j = $i % 2; + if ($is_team) { + $team = BoincTeam::lookup_id($item->teamid); + if (!$team) return; + $x = "".team_links($team)."\n"; + } else { + $user = BoincUser::lookup_id($item->userid); + if (!$user) return; + $x= "".user_links($user, BADGE_HEIGHT_MEDIUM)."\n"; + } + echo ""; + echo "$i\n"; + echo $x; + + foreach ($apps as $app) { + if ($app->id == $item->appid) { + $c = $item; + } else { + if ($is_team) { + $c = BoincCreditTeam::lookup("teamid=$item->teamid and appid=$app->id"); + } else { + $c = BoincCreditUser::lookup("userid=$item->userid and appid=$app->id"); + } + if (!$c) { + $c = new StdClass; + $c->expavg = 0; + $c->total = 0; + } + } + echo "".format_credit($c->expavg)."".format_credit_large($c->total)."\n"; + } + echo "\n"; +} + +function show_list($is_team, $appid, $is_total) { + $x = $is_team?"teams":"participants"; + page_head("Top $x by application"); + $apps = BoincApp::enum("deprecated=0"); + if (!$appid) { + $appid = $apps[0]->id; + } + start_table(); + show_header($is_team, $apps, $appid, $is_total); + $x = $is_total?"total":"expavg"; + if ($is_team) { + $items = BoincCreditTeam::enum("appid=$appid order by $x desc"); + } else { + $items = BoincCreditUser::enum("appid=$appid order by $x desc"); + } + $i = 0; + foreach ($items as $item) { + show_row($item, $apps, $is_team, $i); + $i++; + } + end_table(); + page_tail(); +} + +$is_team = get_int('is_team', true); +$appid = get_int('appid', true); +$is_total = get_int('is_total', true); + +show_list($is_team, $appid, $is_total); + +?> diff --git a/html/user/stats.php b/html/user/stats.php index 5177966377..62fbd2f4fe 100644 --- a/html/user/stats.php +++ b/html/user/stats.php @@ -22,20 +22,29 @@ page_head(tra('Statistics and leaderboards')); check_get_args(array()); +$credit_by_app = parse_bool(get_config(), "credit_by_app"); + start_table(); echo " " . tra("Statistics for %1",PROJECT).":