feat(*): remove rating

This commit is contained in:
Baoshuo Ren 2022-03-17 11:02:44 +08:00
parent dcea523cfc
commit 2f4ed55d9d
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
32 changed files with 29 additions and 614 deletions

View File

@ -291,7 +291,6 @@ UNLOCK TABLES;
/*!40101 SET character_set_client = utf8mb4 */; /*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `contests_registrants` ( CREATE TABLE `contests_registrants` (
`username` varchar(20) NOT NULL, `username` varchar(20) NOT NULL,
`user_rating` int(11) NOT NULL,
`contest_id` int(11) NOT NULL, `contest_id` int(11) NOT NULL,
`has_participated` tinyint(1) NOT NULL, `has_participated` tinyint(1) NOT NULL,
`rank` int(11) NOT NULL, `rank` int(11) NOT NULL,
@ -622,7 +621,6 @@ CREATE TABLE `user_info` (
`email` varchar(50) NOT NULL, `email` varchar(50) NOT NULL,
`password` char(32) NOT NULL, `password` char(32) NOT NULL,
`svn_password` char(10) NOT NULL, `svn_password` char(10) NOT NULL,
`rating` int(11) NOT NULL DEFAULT '1500',
`qq` bigint(20) NOT NULL, `qq` bigint(20) NOT NULL,
`sex` char(1) NOT NULL DEFAULT 'U', `sex` char(1) NOT NULL DEFAULT 'U',
`ac_num` int(11) NOT NULL, `ac_num` int(11) NOT NULL,
@ -632,7 +630,6 @@ CREATE TABLE `user_info` (
`remember_token` char(60) NOT NULL, `remember_token` char(60) NOT NULL,
`motto` varchar(200) NOT NULL, `motto` varchar(200) NOT NULL,
PRIMARY KEY (`username`), PRIMARY KEY (`username`),
KEY `rating` (`rating`,`username`),
KEY `ac_num` (`ac_num`,`username`) KEY `ac_num` (`ac_num`,`username`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
/*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET character_set_client = @saved_cs_client */;

View File

@ -120,35 +120,11 @@
global $contest; global $contest;
$contest_data = queryContestData($contest); $contest_data = queryContestData($contest);
calcStandings($contest, $contest_data, $score, $standings, true); calcStandings($contest, $contest_data, $score, $standings, true);
if (!isset($contest['extra_config']['unrated'])) {
$rating_k = isset($contest['extra_config']['rating_k']) ? $contest['extra_config']['rating_k'] : 400;
$ratings = calcRating($standings, $rating_k);
} else {
$ratings = array();
for ($i = 0; $i < count($standings); $i++) {
$ratings[$i] = $standings[$i][2][1];
}
}
for ($i = 0; $i < count($standings); $i++) { for ($i = 0; $i < count($standings); $i++) {
$user = queryUser($standings[$i][2][0]); $user = queryUser($standings[$i][2][0]);
$change = $ratings[$i] - $user['rating'];
$user_link = getUserLink($user['username']); $user_link = getUserLink($user['username']);
if ($change != 0) {
$tail = '<strong style="color:red">' . ($change > 0 ? '+' : '') . $change . '</strong>';
$content = <<<EOD
<p>${user_link} 您好:</p>
<p class="indent2">您在 <a href="/contest/{$contest['id']}">{$contest['name']}</a> 这场比赛后的Rating变化为${tail}当前Rating为 <strong style="color:red">{$ratings[$i]}</strong></p>
EOD;
} else {
$content = <<<EOD
<p>${user_link} 您好:</p>
<p class="indent2">您在 <a href="/contest/{$contest['id']}">{$contest['name']}</a> 这场比赛后Rating没有变化。当前Rating为 <strong style="color:red">{$ratings[$i]}</strong></p>
EOD;
}
sendSystemMsg($user['username'], 'Rating变化通知', $content);
DB::query("update user_info set rating = {$ratings[$i]} where username = '{$standings[$i][2][0]}'");
DB::query("update contests_registrants set rank = {$standings[$i][3]} where contest_id = {$contest['id']} and username = '{$standings[$i][2][0]}'"); DB::query("update contests_registrants set rank = {$standings[$i][3]} where contest_id = {$contest['id']} and username = '{$standings[$i][2][0]}'");
} }
DB::query("update contests set status = 'finished' where id = {$contest['id']}"); DB::query("update contests set status = 'finished' where id = {$contest['id']}");

View File

@ -116,43 +116,6 @@
); );
if (isSuperUser($myUser)) { if (isSuperUser($myUser)) {
$rating_k_form = new UOJForm('rating_k');
$rating_k_form->addInput('rating_k', 'text', 'rating 变化上限', isset($contest['extra_config']['rating_k']) ? $contest['extra_config']['rating_k'] : 400,
function ($x) {
if (!validateUInt($x) || $x < 1 || $x > 1000) {
return '不合法的上限';
}
return '';
},
null
);
$rating_k_form->handle = function() {
global $contest;
$contest['extra_config']['rating_k'] = $_POST['rating_k'];
$esc_extra_config = json_encode($contest['extra_config']);
$esc_extra_config = DB::escape($esc_extra_config);
DB::update("update contests set extra_config = '$esc_extra_config' where id = {$contest['id']}");
};
$rating_k_form->runAtServer();
$rated_form = new UOJForm('rated');
$rated_form->handle = function() {
global $contest;
if (isset($contest['extra_config']['unrated'])) {
unset($contest['extra_config']['unrated']);
} else {
$contest['extra_config']['unrated'] = '';
}
$esc_extra_config = json_encode($contest['extra_config']);
$esc_extra_config = DB::escape($esc_extra_config);
DB::update("update contests set extra_config = '$esc_extra_config' where id = {$contest['id']}");
};
$rated_form->submit_button_config['class_str'] = 'btn btn-warning btn-block';
$rated_form->submit_button_config['text'] = isset($contest['extra_config']['unrated']) ? '设置比赛为rated' : '设置比赛为unrated';
$rated_form->submit_button_config['smart_confirm'] = '';
$rated_form->runAtServer();
$version_form = new UOJForm('version'); $version_form = new UOJForm('version');
$version_form->addInput('standings_version', 'text', '排名版本', $contest['extra_config']['standings_version'], $version_form->addInput('standings_version', 'text', '排名版本', $contest['extra_config']['standings_version'],
function ($x) { function ($x) {
@ -260,16 +223,6 @@
<?php if (isSuperUser($myUser)): ?> <?php if (isSuperUser($myUser)): ?>
<div class="tab-pane" id="tab-others"> <div class="tab-pane" id="tab-others">
<div class="row"> <div class="row">
<div class="col-sm-12">
<h3>Rating控制</h3>
<div class="row">
<div class="col-sm-3">
<?php $rated_form->printHTML(); ?>
</div>
</div>
<div class="top-buffer-sm"></div>
<?php $rating_k_form->printHTML(); ?>
</div>
<div class="col-sm-12 top-buffer-sm"> <div class="col-sm-12 top-buffer-sm">
<h3>版本控制</h3> <h3>版本控制</h3>
<?php $version_form->printHTML(); ?> <?php $version_form->printHTML(); ?>

View File

@ -25,23 +25,6 @@
$unregister_form->runAtServer(); $unregister_form->runAtServer();
} }
if ($has_contest_permission) {
$pre_rating_form = new UOJForm('pre_rating');
$pre_rating_form->handle = function() {
global $contest;
foreach (DB::selectAll("select * from contests_registrants where contest_id = {$contest['id']}") as $reg) {
$user = queryUser($reg['username']);
DB::update("update contests_registrants set user_rating = {$user['rating']} where contest_id = {$contest['id']} and username = '{$user['username']}'");
}
};
$pre_rating_form->submit_button_config['align'] = 'right';
$pre_rating_form->submit_button_config['class_str'] = 'btn btn-warning';
$pre_rating_form->submit_button_config['text'] = '重新计算参赛前的 rating';
$pre_rating_form->submit_button_config['smart_confirm'] = '';
$pre_rating_form->runAtServer();
}
} }
?> ?>
<?php echoUOJPageHeader(HTML::stripTags($contest['name']) . ' - ' . UOJLocale::get('contests::contest registrants')) ?> <?php echoUOJPageHeader(HTML::stripTags($contest['name']) . ' - ' . UOJLocale::get('contests::contest registrants')) ?>
@ -61,25 +44,25 @@
<?php <?php
if ($show_ip) { if ($show_ip) {
$header_row = '<tr><th>#</th><th>'.UOJLocale::get('username').'</th><th>remote_addr</th><th>rating</th></tr>'; $header_row = '<tr><th>#</th><th>'.UOJLocale::get('username').'</th><th>remote_addr</th></tr>';
$ip_owner = array(); $ip_owner = array();
foreach (DB::selectAll("select * from contests_registrants where contest_id = {$contest['id']} order by user_rating asc") as $reg) { foreach (DB::selectAll("select * from contests_registrants where contest_id = {$contest['id']} order by username desc") as $reg) {
$user = queryUser($reg['username']); $user = queryUser($reg['username']);
$ip_owner[$user['remote_addr']] = $reg['username']; $ip_owner[$user['remote_addr']] = $reg['username'];
} }
} else { } else {
$header_row = '<tr><th>#</th><th>'.UOJLocale::get('username').'</th><th>rating</th></tr>'; $header_row = '<tr><th>#</th><th>'.UOJLocale::get('username').'</th></tr>';
} }
echoLongTable(array('*'), 'contests_registrants', "contest_id = {$contest['id']}", 'order by user_rating desc', echoLongTable(array('*'), 'contests_registrants', "contest_id = {$contest['id']}", 'order by username desc',
$header_row, $header_row,
function($contest, $num) { function($contest, $num) {
global $myUser; global $myUser;
global $show_ip, $ip_owner; global $show_ip, $ip_owner;
$user = queryUser($contest['username']); $user = queryUser($contest['username']);
$user_link = getUserLink($contest['username'], $contest['user_rating']); $user_link = getUserLink($contest['username']);
if (!$show_ip) { if (!$show_ip) {
echo '<tr>'; echo '<tr>';
} else { } else {
@ -94,17 +77,11 @@
if ($show_ip) { if ($show_ip) {
echo '<td>'.$user['remote_addr'].'</td>'; echo '<td>'.$user['remote_addr'].'</td>';
} }
echo '<td>'.$contest['user_rating'].'</td>';
echo '</tr>'; echo '</tr>';
}, },
array('page_len' => 100, array('page_len' => 100,
'get_row_index' => '', 'get_row_index' => '',
'print_after_table' => function() { 'print_after_table' => function() {}
global $pre_rating_form;
if (isset($pre_rating_form)) {
$pre_rating_form->printHTML();
}
}
) )
); );
?> ?>

View File

@ -14,7 +14,7 @@
$register_form = new UOJForm('register'); $register_form = new UOJForm('register');
$register_form->handle = function() { $register_form->handle = function() {
global $myUser, $contest; global $myUser, $contest;
DB::query("insert into contests_registrants (username, user_rating, contest_id, has_participated) values ('{$myUser['username']}', {$myUser['rating']}, {$contest['id']}, 0)"); DB::query("insert into contests_registrants (username, contest_id, has_participated) values ('{$myUser['username']}', {$contest['id']}, 0)");
updateContestPlayerNum($contest); updateContestPlayerNum($contest);
}; };
$register_form->submit_button_config['class_str'] = 'btn btn-primary'; $register_form->submit_button_config['class_str'] = 'btn btn-primary';
@ -26,7 +26,7 @@
<?php echoUOJPageHeader(HTML::stripTags($contest['name']) . ' - 报名') ?> <?php echoUOJPageHeader(HTML::stripTags($contest['name']) . ' - 报名') ?>
<h1 class="page-header">比赛规则</h1> <h1 class="page-header">比赛规则</h1>
<ul> <ul>
<li>比赛报名后不算正式参赛,报名后进了比赛页面也不算参赛,<strong>看了题目才算正式参赛</strong>如果未正式参赛则不算rating。</li> <li>比赛报名后不算正式参赛,报名后进了比赛页面也不算参赛,<strong>看了题目才算正式参赛</strong></li>
<li>比赛中途可以提交,若同一题有多次提交按<strong>最后一次不是Compile Error的提交</strong>算成绩。其实UOJ会自动无视你所有Compile Error的提交当作没看见</li> <li>比赛中途可以提交,若同一题有多次提交按<strong>最后一次不是Compile Error的提交</strong>算成绩。其实UOJ会自动无视你所有Compile Error的提交当作没看见</li>
<li>比赛中途提交后,可以看到<strong>测样例</strong>的结果。(若为提交答案题则对于每个测试点,该测试点有分则该测试点为满分)</li> <li>比赛中途提交后,可以看到<strong>测样例</strong>的结果。(若为提交答案题则对于每个测试点,该测试点有分则该测试点为满分)</li>
<li>比赛结束后会进行最终测试,最终测试后的排名为最终排名。</li> <li>比赛结束后会进行最终测试,最终测试后的排名为最终排名。</li>

View File

@ -43,13 +43,4 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="col-sm-12 mt-4">
<h3><?= UOJLocale::get('top rated') ?></h3>
<?php echoRanklist(array('echo_full' => '', 'top10' => '')) ?>
<div class="text-center">
<a href="/ranklist"><?= UOJLocale::get('view all') ?></a>
</div>
</div>
</div>
<?php echoUOJPageFooter() ?> <?php echoUOJPageFooter() ?>

View File

@ -1,9 +1,5 @@
<?php <?php
if (isset($_GET['type']) && $_GET['type'] == 'rating') {
$config = array('page_len' => 100);
} else {
become404Page(); become404Page();
}
?> ?>
<?php echoUOJPageHeader('比赛排行榜') ?> <?php echoUOJPageHeader('比赛排行榜') ?>
<?php echoRanklist($config) ?> <?php echoRanklist($config) ?>

View File

@ -154,9 +154,6 @@
$asrc = HTML::avatar_addr($poster, 80); $asrc = HTML::avatar_addr($poster, 80);
$replies = DB::selectAll("select id, poster, content, post_time from blogs_comments where reply_id = {$comment['id']} order by id"); $replies = DB::selectAll("select id, poster, content, post_time from blogs_comments where reply_id = {$comment['id']} order by id");
foreach ($replies as $idx => $reply) {
$replies[$idx]['poster_rating'] = queryUser($reply['poster'])['rating'];
}
$replies_json = json_encode($replies); $replies_json = json_encode($replies);
?> ?>
<div id="comment-<?= $comment['id'] ?>" class="list-group-item"> <div id="comment-<?= $comment['id'] ?>" class="list-group-item">

View File

@ -1,7 +1,5 @@
<?php <?php
$username = $_GET['username']; $username = $_GET['username'];
requireLib('flot');
?> ?>
<?php if (validateUsername($username) && ($user = queryUser($username))): ?> <?php if (validateUsername($username) && ($user = queryUser($username))): ?>
<?php echoUOJPageHeader($user['username'] . ' - ' . UOJLocale::get('user profile')) ?> <?php echoUOJPageHeader($user['username'] . ' - ' . UOJLocale::get('user profile')) ?>
@ -30,12 +28,8 @@
<img class="media-object img-thumbnail d-block mx-auto" alt="<?= $user['username'] ?> Avatar" src="<?= HTML::avatar_addr($user, 256) ?>" /> <img class="media-object img-thumbnail d-block mx-auto" alt="<?= $user['username'] ?> Avatar" src="<?= HTML::avatar_addr($user, 256) ?>" />
</div> </div>
<div class="col-md-8 order-md-1"> <div class="col-md-8 order-md-1">
<h2><span class="uoj-honor" data-rating="<?= $user['rating'] ?>"><?= $user['username'] ?></span> <span><strong style="<?= $col_sex ?>"><?= $esc_sex ?></strong></span></h2> <h2><span class="uoj-honor"><?= $user['username'] ?></span> <span><strong style="<?= $col_sex ?>"><?= $esc_sex ?></strong></span></h2>
<div class="list-group"> <div class="list-group">
<div class="list-group-item">
<h4 class="list-group-item-heading"><?= UOJLocale::get('rating') ?></h4>
<p class="list-group-item-text"><strong style="color:red"><?= $user['rating'] ?></strong></p>
</div>
<div class="list-group-item"> <div class="list-group-item">
<h4 class="list-group-item-heading"><?= UOJLocale::get('email') ?></h4> <h4 class="list-group-item-heading"><?= UOJLocale::get('email') ?></h4>
<p class="list-group-item-text"><?= $esc_email ?></p> <p class="list-group-item-text"><?= $esc_email ?></p>
@ -77,10 +71,6 @@
<div class="top-buffer-lg"></div> <div class="top-buffer-lg"></div>
<div class="list-group"> <div class="list-group">
<div class="list-group-item">
<h4 class="list-group-item-heading"><?= UOJLocale::get('rating changes') ?></h4>
<div class="list-group-item-text" id="rating-plot" style="height:500px;"></div>
</div>
<div class="list-group-item"> <div class="list-group-item">
<?php <?php
$ac_problems = DB::selectAll("select problem_id from best_ac_submissions where submitter = '{$user['username']}'"); $ac_problems = DB::selectAll("select problem_id from best_ac_submissions where submitter = '{$user['username']}'");
@ -100,147 +90,6 @@
</div> </div>
</div> </div>
</div> </div>
<script type="text/javascript">
var rating_data = [[
<?php
$user_rating_min = $user_rating_max = 1500;
$result = DB::query("select contest_id, `rank`, user_rating from contests_registrants where username = '{$user['username']}' and has_participated = 1 order by contest_id");
$is_first_row = true;
$last_rating = 1500;
while ($row = DB::fetch($result)) {
$contest = queryContest($row['contest_id']);
$rating_delta = $row['user_rating'] - $last_rating;
if (!$is_first_row) {
echo "[$last_contest_time, {$row['user_rating']}, $last_contest_id, $last_contest_name, $last_rank, $rating_delta],";
} else {
$is_first_row = false;
}
$contest_start_time = new DateTime($contest['start_time']);
$last_contest_time = ($contest_start_time->getTimestamp() + $contest_start_time->getOffset()) * 1000;
$last_contest_name = json_encode($contest['name']);
$last_contest_id = $contest['id'];
$last_rank = $row['rank'];
$last_rating = $row['user_rating'];
if ($row['user_rating'] < $user_rating_min) {
$user_rating_min = $row['user_rating'];
}
if ($row['user_rating'] > $user_rating_max) {
$user_rating_max = $row['user_rating'];
}
}
if ($is_first_row) {
$time_now_stamp = (UOJTime::$time_now->getTimestamp() + UOJTime::$time_now->getOffset()) * 1000;
echo "[{$time_now_stamp}, {$user['rating']}, 0]";
} else {
$rating_delta = $user['rating'] - $last_rating;
echo "[$last_contest_time, {$user['rating']}, $last_contest_id, $last_contest_name, $last_rank, $rating_delta]";
}
if ($user['rating'] < $user_rating_min) {
$user_rating_min = $user['rating'];
}
if ($user['rating'] > $user_rating_max) {
$user_rating_max = $user['rating'];
}
$user_rating_min -= 400;
$user_rating_max += 400;
?>
]];
var rating_plot = $.plot($("#rating-plot"), [{
color: "#3850eb",
label: "<?= $user['username'] ?>",
data: rating_data[0]
}], {
series: {
lines: {
show: true
},
points: {
show: true
}
},
xaxis: {
mode: "time"
},
yaxis: {
min: <?= $user_rating_min ?>,
max: <?= $user_rating_max ?>
},
legend: {
labelFormatter: function(username) {
return getUserLink(username, <?= $user['rating'] ?>, false);
}
},
grid: {
clickable: true,
hoverable: true
},
hooks: {
drawBackground: [
function(plot, ctx) {
var plotOffset = plot.getPlotOffset();
for (var y = 0; y < plot.height(); y++) {
var rating = <?= $user_rating_max ?> - <?= $user_rating_max - $user_rating_min ?> * y / plot.height();
ctx.fillStyle = getColOfRating(rating);
ctx.fillRect(plotOffset.left, plotOffset.top + y, plot.width(), Math.min(5, plot.height() - y));
}
}
]
}
});
function showTooltip(x, y, contents) {
$('<div id="rating-tooltip">' + contents + '</div>').css({
position: 'absolute',
display: 'none',
top: y - 20,
left: x + 10,
border: '1px solid #fdd',
padding: '2px',
'font-size' : '11px',
'background-color': '#fee',
opacity: 0.80
}).appendTo("body").fadeIn(200);
}
var prev = -1;
function onHoverRating(event, pos, item) {
if (prev != item.dataIndex) {
$("#rating-tooltip").remove();
var params = rating_data[item.seriesIndex][item.dataIndex];
var total = params[1];
var contestId = params[2];
if (contestId != 0) {
var change = params[5] > 0 ? "+" + params[5] : params[5];
var contestName = params[3];
var rank = params[4];
var html = "= " + total + " (" + change + "), <br/>"
+ "Rank: " + rank + "<br/>"
+ '<a href="' + '/contest/' + contestId + '">' + contestName + '</a>';
} else {
var html = "= " + total + "<br/>"
+ "Unrated";
}
showTooltip(item.pageX, item.pageY, html);
prev = item.dataIndex;
}
}
$("#rating-plot").bind("plothover", function (event, pos, item) {
if (item) {
onHoverRating(event, pos, item);
}
});
$("#rating-plot").bind("plotclick", function (event, pos, item) {
if (item && prev == -1) {
onHoverRating(event, pos, item);
} else {
$("#rating-tooltip").fadeOut(200);
prev = -1;
}
});
</script>
<?php else: ?> <?php else: ?>
<?php echoUOJPageHeader('不存在该用户' . ' - 用户信息') ?> <?php echoUOJPageHeader('不存在该用户' . ' - 用户信息') ?>
<div class="card border-danger"> <div class="card border-danger">

View File

@ -5,99 +5,6 @@ define("CONTEST_PENDING_FINAL_TEST", 2);
define("CONTEST_TESTING", 10); define("CONTEST_TESTING", 10);
define("CONTEST_FINISHED", 20); define("CONTEST_FINISHED", 20);
function calcRating($standings, $K = 400) {
$DELTA = 500;
$n = count($standings);
$rating = array();
for ($i = 0; $i < $n; ++$i) {
$rating[$i] = $standings[$i][2][1];
}
$rank = array();
$foot = array();
for ($i = 0; $i < $n; ) {
$j = $i;
while ($j + 1 < $n && $standings[$j + 1][3] == $standings[$j][3]) {
++$j;
}
$our_rk = 0.5 * (($i + 1) + ($j + 1));
while ($i <= $j) {
$rank[$i] = $our_rk;
$foot[$i] = $n - $rank[$i];
$i++;
}
}
$weight = array();
for ($i = 0; $i < $n; ++$i) {
$weight[$i] = pow(7, $rating[$i] / $DELTA);
}
$exp = array_fill(0, $n, 0);
for ($i = 0; $i < $n; ++$i) {
for ($j = 0; $j < $n; ++$j) {
if ($j != $i) {
$exp[$i] += $weight[$i] / ($weight[$i] + $weight[$j]);
}
}
}
$new_rating = array();
for ($i = 0; $i < $n; $i++) {
$new_rating[$i] = $rating[$i];
$new_rating[$i] += ceil($K * ($foot[$i] - $exp[$i]) / ($n - 1));
}
for ($i = $n - 1; $i >= 0; $i--) {
if ($i + 1 < $n && $standings[$i][3] != $standings[$i + 1][3]) {
break;
}
if ($new_rating[$i] > $rating[$i]) {
$new_rating[$i] = $rating[$i];
}
}
for ($i = 0; $i < $n; $i++) {
if ($new_rating[$i] < 0) {
$new_rating[$i] = 0;
}
}
return $new_rating;
}
function calcRatingSelfTest() {
$tests = [
[[1500, 1], [1500, 1]],
[[1500, 1], [1600, 1]],
[[1500, 1], [1600, 2], [1600, 2]],
[[1500, 1], [200, 2], [100, 2]],
[[1500, 1], [100, 2], [200, 2]],
[[1500, 1], [100, 2], [200, 3]],
[[1500, 1], [200, 2], [100, 3]],
[[1500, 1], [3000, 2], [1500, 3]],
[[1500, 1], [3000, 2], [1500, 3], [1500, 3]],
[[1500, 1], [1500, 2], [1500, 3], [3000, 4]],
[[1500, 1], [1500, 2], [10, 3], [1, 4]]
];
foreach ($tests as $test_num => $test) {
print "test #{$test_num}\n";
$standings = array();
$n = count($test);
for ($i = 0; $i < $n; $i++) {
$standings[] = [0, 0, [(string)$i, $test[$i][0]], $test[$i][1]];
}
$new_rating = calcRating($standings);
for ($i = 0; $i < $n; $i++) {
printf("%3d: %4d -> %4d delta: %+4d\n", $test[$i][1], $test[$i][0], $new_rating[$i], $new_rating[$i] - $test[$i][0]);
}
print "\n";
}
}
function genMoreContestInfo(&$contest) { function genMoreContestInfo(&$contest) {
$contest['start_time_str'] = $contest['start_time']; $contest['start_time_str'] = $contest['start_time'];
$contest['start_time'] = new DateTime($contest['start_time']); $contest['start_time'] = new DateTime($contest['start_time']);
@ -130,7 +37,7 @@ function updateContestPlayerNum($contest) {
// problems: pos => id // problems: pos => id
// data : id, submit_time, submitter, problem_pos, score // data : id, submit_time, submitter, problem_pos, score
// people : username, user_rating // people : username
function queryContestData($contest, $config = array()) { function queryContestData($contest, $config = array()) {
mergeConfig($config, [ mergeConfig($config, [
'pre_final' => false 'pre_final' => false
@ -175,9 +82,8 @@ function queryContestData($contest, $config = array()) {
} }
$people = []; $people = [];
$result = DB::query("select username, user_rating from contests_registrants where contest_id = {$contest['id']} and has_participated = 1"); $result = DB::query("select username from contests_registrants where contest_id = {$contest['id']} and has_participated = 1");
while ($row = DB::fetch($result, MYSQLI_NUM)) { while ($row = DB::fetch($result, MYSQLI_NUM)) {
$row[1] = (int)$row[1];
$people[] = $row; $people[] = $row;
} }
@ -202,7 +108,7 @@ function calcStandings($contest, $contest_data, &$score, &$standings, $update_co
$score[$submission[2]][$submission[3]] = array($submission[4], $penalty, $submission[0]); $score[$submission[2]][$submission[3]] = array($submission[4], $penalty, $submission[0]);
} }
// standings: rank => score, penalty, [username, user_rating], virtual_rank // standings: rank => score, penalty, [username], virtual_rank
$standings = array(); $standings = array();
foreach ($contest_data['people'] as $person) { foreach ($contest_data['people'] as $person) {
$cur = array(0, 0, $person); $cur = array(0, 0, $person);

View File

@ -11,7 +11,7 @@ function uojHandleAtSign($str, $uri) {
return $matches[0]; return $matches[0];
} else { } else {
$referrers[$user['username']] = ''; $referrers[$user['username']] = '';
return '<span class="uoj-username" data-rating="'.$user['rating'].'">@'.$user['username'].'</span>'; return '<span class="uoj-username">@'.$user['username'].'</span>';
} }
} }
}, $str); }, $str);
@ -74,12 +74,9 @@ function become403Page() {
becomeMsgPage('<div class="text-center"><div style="font-size:233px">403</div><p>禁止入内! T_T</p></div>', '403'); becomeMsgPage('<div class="text-center"><div style="font-size:233px">403</div><p>禁止入内! T_T</p></div>', '403');
} }
function getUserLink($username, $rating = null) { function getUserLink($username) {
if (validateUsername($username) && ($user = queryUser($username))) { if (validateUsername($username) && ($user = queryUser($username))) {
if ($rating == null) { return '<span class="uoj-username">'.$username.'</span>';
$rating = $user['rating'];
}
return '<span class="uoj-username" data-rating="'.$rating.'">'.$username.'</span>';
} else { } else {
$esc_username = HTML::escape($username); $esc_username = HTML::escape($username);
return '<span>'.$esc_username.'</span>'; return '<span>'.$esc_username.'</span>';
@ -1030,44 +1027,3 @@ function echoUOJPageHeader($page_title, $extra_config = array()) {
function echoUOJPageFooter($config = array()) { function echoUOJPageFooter($config = array()) {
uojIncludeView('page-footer', $config); uojIncludeView('page-footer', $config);
} }
function echoRanklist($config = array()) {
$header_row = '';
$header_row .= '<tr>';
$header_row .= '<th style="width: 5em;">#</th>';
$header_row .= '<th style="width: 14em;">'.UOJLocale::get('username').'</th>';
$header_row .= '<th style="width: 50em;">'.UOJLocale::get('motto').'</th>';
$header_row .= '<th style="width: 5em;">'.UOJLocale::get('rating').'</th>';
$header_row .= '</tr>';
$users = array();
$print_row = function($user, $now_cnt) use (&$users) {
if (!$users) {
$rank = DB::selectCount("select count(*) from user_info where rating > {$user['rating']}") + 1;
} elseif ($user['rating'] == $users[count($users) - 1]['rating']) {
$rank = $users[count($users) - 1]['rank'];
} else {
$rank = $now_cnt;
}
$user['rank'] = $rank;
echo '<tr>';
echo '<td>' . $user['rank'] . '</td>';
echo '<td>' . getUserLink($user['username']) . '</td>';
echo '<td>' . HTML::escape($user['motto']) . '</td>';
echo '<td>' . $user['rating'] . '</td>';
echo '</tr>';
$users[] = $user;
};
$col_names = array('username', 'rating', 'motto');
$tail = 'order by rating desc, username asc';
if (isset($config['top10'])) {
$tail .= ' limit 10';
}
$config['get_row_index'] = '';
echoLongTable($col_names, 'user_info', '1', $tail, $header_row, $print_row, $config);
}

View File

@ -17,7 +17,6 @@ return [
'all the announcements' => 'All the Announcements……', 'all the announcements' => 'All the Announcements……',
'help' => 'Help', 'help' => 'Help',
'search' => 'Search', 'search' => 'Search',
'top rated' => 'Top rated',
'username' => 'Username', 'username' => 'Username',
'password' => 'Password', 'password' => 'Password',
'new password' => 'New password', 'new password' => 'New password',
@ -26,7 +25,6 @@ return [
'QQ' => 'QQ', 'QQ' => 'QQ',
'sex' => 'Sex', 'sex' => 'Sex',
'motto' => 'Motto', 'motto' => 'Motto',
'rating' => 'Rating',
'view all' => 'View all', 'view all' => 'View all',
'appraisal' => 'Appraisal', 'appraisal' => 'Appraisal',
'submit' => 'Submit', 'submit' => 'Submit',
@ -46,7 +44,6 @@ return [
'visit his blog' => function($name) { 'visit his blog' => function($name) {
return "Visit $name's blog"; return "Visit $name's blog";
}, },
'rating changes' => 'Rating changes',
'accepted problems' => 'Accepted problems', 'accepted problems' => 'Accepted problems',
'n problems in total' => function($n) { 'n problems in total' => function($n) {
return "$n ".($n <= 1 ? 'problem' : 'problems'); return "$n ".($n <= 1 ? 'problem' : 'problems');

View File

@ -17,7 +17,6 @@ return [
'all the announcements' => '所有公告……', 'all the announcements' => '所有公告……',
'help' => '帮助', 'help' => '帮助',
'search' => '搜索', 'search' => '搜索',
'top rated' => '比赛排行榜',
'username' => '用户名', 'username' => '用户名',
'password' => '密码', 'password' => '密码',
'new password' => '新密码', 'new password' => '新密码',
@ -26,7 +25,6 @@ return [
'QQ' => 'QQ', 'QQ' => 'QQ',
'sex' => '性别', 'sex' => '性别',
'motto' => '格言', 'motto' => '格言',
'rating' => 'Rating',
'view all' => '查看全部', 'view all' => '查看全部',
'appraisal' => '评价', 'appraisal' => '评价',
'submit' => '提交', 'submit' => '提交',
@ -46,7 +44,6 @@ return [
'visit his blog' => function($name) { 'visit his blog' => function($name) {
return "访问 $name 的博客"; return "访问 $name 的博客";
}, },
'rating changes' => 'Rating 变化',
'accepted problems' => 'AC 过的题目', 'accepted problems' => 'AC 过的题目',
'n problems in total' => function($n) { 'n problems in total' => function($n) {
return "$n 道题"; return "$n 道题";

View File

@ -152,7 +152,6 @@ class HTML {
//$config->set('HTML.Doctype', 'HTML 4.01 Transitional'); //$config->set('HTML.Doctype', 'HTML 4.01 Transitional');
$config->set('Cache.DefinitionImpl', null); $config->set('Cache.DefinitionImpl', null);
$def = $config->getHTMLDefinition(true); $def = $config->getHTMLDefinition(true);
$def->addAttribute('span', 'data-rating', 'Number');
$def->addElement('section', 'Block', 'Flow', 'Common'); $def->addElement('section', 'Block', 'Flow', 'Common');
$def->addElement('nav', 'Block', 'Flow', 'Common'); $def->addElement('nav', 'Block', 'Flow', 'Common');

View File

@ -48,7 +48,6 @@ Route::group([
Route::any('/announcements', '/announcements.php'); Route::any('/announcements', '/announcements.php');
Route::any('/faq', '/faq.php'); Route::any('/faq', '/faq.php');
Route::any('/ranklist', '/ranklist.php?type=rating');
Route::any('/captcha', '/captcha.php'); Route::any('/captcha', '/captcha.php');
Route::any('/login', '/login.php'); Route::any('/login', '/login.php');

View File

@ -166,16 +166,6 @@
<?= HTML::js_src('/js/jquery.hotkeys.js') ?> <?= HTML::js_src('/js/jquery.hotkeys.js') ?>
<?php endif ?> <?php endif ?>
<?php if (isset($REQUIRE_LIB['flot'])): ?>
<!-- flot -->
<?= HTML::js_src('/js/jquery.flot.min.js') ?>
<?= HTML::js_src('/js/jquery.flot.time.min.js') ?>
<?= HTML::js_src('/js/jquery.flot.resize.min.js') ?>
<?php
$REQUIRE_LIB['colorhelpers'] = "";
?>
<?php endif ?>
<?php if (isset($REQUIRE_LIB['colorhelpers'])): ?> <?php if (isset($REQUIRE_LIB['colorhelpers'])): ?>
<!-- colorhelpers --> <!-- colorhelpers -->
<?= HTML::js_src('/js/jquery.colorhelpers.min.js') ?> <?= HTML::js_src('/js/jquery.colorhelpers.min.js') ?>
@ -242,7 +232,7 @@
<?php if (Auth::check()): ?> <?php if (Auth::check()): ?>
<li class="nav-item dropdown"> <li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown"> <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown">
<span class="uoj-username" data-rating="<?= Auth::user()['rating'] ?>" data-link="0"><?= Auth::id() ?></span> <?= $new_msg_tot_html ?> <span class="uoj-username" data-link="0"><?= Auth::id() ?></span> <?= $new_msg_tot_html ?>
</a> </a>
<ul class="dropdown-menu" role="menu"> <ul class="dropdown-menu" role="menu">
<li role="presentation"><a class="dropdown-item" href="<?= HTML::url('/user/profile/' . Auth::id()) ?>"><?= UOJLocale::get('my profile') ?></a></li> <li role="presentation"><a class="dropdown-item" href="<?= HTML::url('/user/profile/' . Auth::id()) ?>"><?= UOJLocale::get('my profile') ?></a></li>

View File

@ -1,7 +0,0 @@
/* Javascript plotting library for jQuery, version 0.8.3.
Copyright (c) 2007-2014 IOLA and Ole Laursen.
Licensed under the MIT license.
*/
(function($){var options={canvas:true};var render,getTextInfo,addText;var hasOwnProperty=Object.prototype.hasOwnProperty;function init(plot,classes){var Canvas=classes.Canvas;if(render==null){getTextInfo=Canvas.prototype.getTextInfo,addText=Canvas.prototype.addText,render=Canvas.prototype.render}Canvas.prototype.render=function(){if(!plot.getOptions().canvas){return render.call(this)}var context=this.context,cache=this._textCache;context.save();context.textBaseline="middle";for(var layerKey in cache){if(hasOwnProperty.call(cache,layerKey)){var layerCache=cache[layerKey];for(var styleKey in layerCache){if(hasOwnProperty.call(layerCache,styleKey)){var styleCache=layerCache[styleKey],updateStyles=true;for(var key in styleCache){if(hasOwnProperty.call(styleCache,key)){var info=styleCache[key],positions=info.positions,lines=info.lines;if(updateStyles){context.fillStyle=info.font.color;context.font=info.font.definition;updateStyles=false}for(var i=0,position;position=positions[i];i++){if(position.active){for(var j=0,line;line=position.lines[j];j++){context.fillText(lines[j].text,line[0],line[1])}}else{positions.splice(i--,1)}}if(positions.length==0){delete styleCache[key]}}}}}}}context.restore()};Canvas.prototype.getTextInfo=function(layer,text,font,angle,width){if(!plot.getOptions().canvas){return getTextInfo.call(this,layer,text,font,angle,width)}var textStyle,layerCache,styleCache,info;text=""+text;if(typeof font==="object"){textStyle=font.style+" "+font.variant+" "+font.weight+" "+font.size+"px "+font.family}else{textStyle=font}layerCache=this._textCache[layer];if(layerCache==null){layerCache=this._textCache[layer]={}}styleCache=layerCache[textStyle];if(styleCache==null){styleCache=layerCache[textStyle]={}}info=styleCache[text];if(info==null){var context=this.context;if(typeof font!=="object"){var element=$("<div>&nbsp;</div>").css("position","absolute").addClass(typeof font==="string"?font:null).appendTo(this.getTextLayer(layer));font={lineHeight:element.height(),style:element.css("font-style"),variant:element.css("font-variant"),weight:element.css("font-weight"),family:element.css("font-family"),color:element.css("color")};font.size=element.css("line-height",1).height();element.remove()}textStyle=font.style+" "+font.variant+" "+font.weight+" "+font.size+"px "+font.family;info=styleCache[text]={width:0,height:0,positions:[],lines:[],font:{definition:textStyle,color:font.color}};context.save();context.font=textStyle;var lines=(text+"").replace(/<br ?\/?>|\r\n|\r/g,"\n").split("\n");for(var i=0;i<lines.length;++i){var lineText=lines[i],measured=context.measureText(lineText);info.width=Math.max(measured.width,info.width);info.height+=font.lineHeight;info.lines.push({text:lineText,width:measured.width,height:font.lineHeight})}context.restore()}return info};Canvas.prototype.addText=function(layer,x,y,text,font,angle,width,halign,valign){if(!plot.getOptions().canvas){return addText.call(this,layer,x,y,text,font,angle,width,halign,valign)}var info=this.getTextInfo(layer,text,font,angle,width),positions=info.positions,lines=info.lines;y+=info.height/lines.length/2;if(valign=="middle"){y=Math.round(y-info.height/2)}else if(valign=="bottom"){y=Math.round(y-info.height)}else{y=Math.round(y)}if(!!(window.opera&&window.opera.version().split(".")[0]<12)){y-=2}for(var i=0,position;position=positions[i];i++){if(position.x==x&&position.y==y){position.active=true;return}}position={active:true,lines:[],x:x,y:y};positions.push(position);for(var i=0,line;line=lines[i];i++){if(halign=="center"){position.lines.push([Math.round(x-line.width/2),y])}else if(halign=="right"){position.lines.push([Math.round(x-line.width),y])}else{position.lines.push([Math.round(x),y])}y+=line.height}}}$.plot.plugins.push({init:init,options:options,name:"canvas",version:"1.0"})})(jQuery);

View File

@ -1,7 +0,0 @@
/* Javascript plotting library for jQuery, version 0.8.3.
Copyright (c) 2007-2014 IOLA and Ole Laursen.
Licensed under the MIT license.
*/
(function($){var options={xaxis:{categories:null},yaxis:{categories:null}};function processRawData(plot,series,data,datapoints){var xCategories=series.xaxis.options.mode=="categories",yCategories=series.yaxis.options.mode=="categories";if(!(xCategories||yCategories))return;var format=datapoints.format;if(!format){var s=series;format=[];format.push({x:true,number:true,required:true});format.push({y:true,number:true,required:true});if(s.bars.show||s.lines.show&&s.lines.fill){var autoscale=!!(s.bars.show&&s.bars.zero||s.lines.show&&s.lines.zero);format.push({y:true,number:true,required:false,defaultValue:0,autoscale:autoscale});if(s.bars.horizontal){delete format[format.length-1].y;format[format.length-1].x=true}}datapoints.format=format}for(var m=0;m<format.length;++m){if(format[m].x&&xCategories)format[m].number=false;if(format[m].y&&yCategories)format[m].number=false}}function getNextIndex(categories){var index=-1;for(var v in categories)if(categories[v]>index)index=categories[v];return index+1}function categoriesTickGenerator(axis){var res=[];for(var label in axis.categories){var v=axis.categories[label];if(v>=axis.min&&v<=axis.max)res.push([v,label])}res.sort(function(a,b){return a[0]-b[0]});return res}function setupCategoriesForAxis(series,axis,datapoints){if(series[axis].options.mode!="categories")return;if(!series[axis].categories){var c={},o=series[axis].options.categories||{};if($.isArray(o)){for(var i=0;i<o.length;++i)c[o[i]]=i}else{for(var v in o)c[v]=o[v]}series[axis].categories=c}if(!series[axis].options.ticks)series[axis].options.ticks=categoriesTickGenerator;transformPointsOnAxis(datapoints,axis,series[axis].categories)}function transformPointsOnAxis(datapoints,axis,categories){var points=datapoints.points,ps=datapoints.pointsize,format=datapoints.format,formatColumn=axis.charAt(0),index=getNextIndex(categories);for(var i=0;i<points.length;i+=ps){if(points[i]==null)continue;for(var m=0;m<ps;++m){var val=points[i+m];if(val==null||!format[m][formatColumn])continue;if(!(val in categories)){categories[val]=index;++index}points[i+m]=categories[val]}}}function processDatapoints(plot,series,datapoints){setupCategoriesForAxis(series,"xaxis",datapoints);setupCategoriesForAxis(series,"yaxis",datapoints)}function init(plot){plot.hooks.processRawData.push(processRawData);plot.hooks.processDatapoints.push(processDatapoints)}$.plot.plugins.push({init:init,options:options,name:"categories",version:"1.0"})})(jQuery);

View File

@ -1,7 +0,0 @@
/* Javascript plotting library for jQuery, version 0.8.3.
Copyright (c) 2007-2014 IOLA and Ole Laursen.
Licensed under the MIT license.
*/
(function($){var options={crosshair:{mode:null,color:"rgba(170, 0, 0, 0.80)",lineWidth:1}};function init(plot){var crosshair={x:-1,y:-1,locked:false};plot.setCrosshair=function setCrosshair(pos){if(!pos)crosshair.x=-1;else{var o=plot.p2c(pos);crosshair.x=Math.max(0,Math.min(o.left,plot.width()));crosshair.y=Math.max(0,Math.min(o.top,plot.height()))}plot.triggerRedrawOverlay()};plot.clearCrosshair=plot.setCrosshair;plot.lockCrosshair=function lockCrosshair(pos){if(pos)plot.setCrosshair(pos);crosshair.locked=true};plot.unlockCrosshair=function unlockCrosshair(){crosshair.locked=false};function onMouseOut(e){if(crosshair.locked)return;if(crosshair.x!=-1){crosshair.x=-1;plot.triggerRedrawOverlay()}}function onMouseMove(e){if(crosshair.locked)return;if(plot.getSelection&&plot.getSelection()){crosshair.x=-1;return}var offset=plot.offset();crosshair.x=Math.max(0,Math.min(e.pageX-offset.left,plot.width()));crosshair.y=Math.max(0,Math.min(e.pageY-offset.top,plot.height()));plot.triggerRedrawOverlay()}plot.hooks.bindEvents.push(function(plot,eventHolder){if(!plot.getOptions().crosshair.mode)return;eventHolder.mouseout(onMouseOut);eventHolder.mousemove(onMouseMove)});plot.hooks.drawOverlay.push(function(plot,ctx){var c=plot.getOptions().crosshair;if(!c.mode)return;var plotOffset=plot.getPlotOffset();ctx.save();ctx.translate(plotOffset.left,plotOffset.top);if(crosshair.x!=-1){var adj=plot.getOptions().crosshair.lineWidth%2?.5:0;ctx.strokeStyle=c.color;ctx.lineWidth=c.lineWidth;ctx.lineJoin="round";ctx.beginPath();if(c.mode.indexOf("x")!=-1){var drawX=Math.floor(crosshair.x)+adj;ctx.moveTo(drawX,0);ctx.lineTo(drawX,plot.height())}if(c.mode.indexOf("y")!=-1){var drawY=Math.floor(crosshair.y)+adj;ctx.moveTo(0,drawY);ctx.lineTo(plot.width(),drawY)}ctx.stroke()}ctx.restore()});plot.hooks.shutdown.push(function(plot,eventHolder){eventHolder.unbind("mouseout",onMouseOut);eventHolder.unbind("mousemove",onMouseMove)})}$.plot.plugins.push({init:init,options:options,name:"crosshair",version:"1.0"})})(jQuery);

File diff suppressed because one or more lines are too long

View File

@ -1,7 +0,0 @@
/* Javascript plotting library for jQuery, version 0.8.3.
Copyright (c) 2007-2014 IOLA and Ole Laursen.
Licensed under the MIT license.
*/
(function($){var options={series:{fillBetween:null}};function init(plot){function findBottomSeries(s,allseries){var i;for(i=0;i<allseries.length;++i){if(allseries[i].id===s.fillBetween){return allseries[i]}}if(typeof s.fillBetween==="number"){if(s.fillBetween<0||s.fillBetween>=allseries.length){return null}return allseries[s.fillBetween]}return null}function computeFillBottoms(plot,s,datapoints){if(s.fillBetween==null){return}var other=findBottomSeries(s,plot.getData());if(!other){return}var ps=datapoints.pointsize,points=datapoints.points,otherps=other.datapoints.pointsize,otherpoints=other.datapoints.points,newpoints=[],px,py,intery,qx,qy,bottom,withlines=s.lines.show,withbottom=ps>2&&datapoints.format[2].y,withsteps=withlines&&s.lines.steps,fromgap=true,i=0,j=0,l,m;while(true){if(i>=points.length){break}l=newpoints.length;if(points[i]==null){for(m=0;m<ps;++m){newpoints.push(points[i+m])}i+=ps}else if(j>=otherpoints.length){if(!withlines){for(m=0;m<ps;++m){newpoints.push(points[i+m])}}i+=ps}else if(otherpoints[j]==null){for(m=0;m<ps;++m){newpoints.push(null)}fromgap=true;j+=otherps}else{px=points[i];py=points[i+1];qx=otherpoints[j];qy=otherpoints[j+1];bottom=0;if(px===qx){for(m=0;m<ps;++m){newpoints.push(points[i+m])}bottom=qy;i+=ps;j+=otherps}else if(px>qx){if(withlines&&i>0&&points[i-ps]!=null){intery=py+(points[i-ps+1]-py)*(qx-px)/(points[i-ps]-px);newpoints.push(qx);newpoints.push(intery);for(m=2;m<ps;++m){newpoints.push(points[i+m])}bottom=qy}j+=otherps}else{if(fromgap&&withlines){i+=ps;continue}for(m=0;m<ps;++m){newpoints.push(points[i+m])}if(withlines&&j>0&&otherpoints[j-otherps]!=null){bottom=qy+(otherpoints[j-otherps+1]-qy)*(px-qx)/(otherpoints[j-otherps]-qx)}i+=ps}fromgap=false;if(l!==newpoints.length&&withbottom){newpoints[l+2]=bottom}}if(withsteps&&l!==newpoints.length&&l>0&&newpoints[l]!==null&&newpoints[l]!==newpoints[l-ps]&&newpoints[l+1]!==newpoints[l-ps+1]){for(m=0;m<ps;++m){newpoints[l+ps+m]=newpoints[l+m]}newpoints[l+1]=newpoints[l-ps+1]}}datapoints.points=newpoints}plot.hooks.processDatapoints.push(computeFillBottoms)}$.plot.plugins.push({init:init,options:options,name:"fillbetween",version:"1.0"})})(jQuery);

View File

@ -1,7 +0,0 @@
/* Javascript plotting library for jQuery, version 0.8.3.
Copyright (c) 2007-2014 IOLA and Ole Laursen.
Licensed under the MIT license.
*/
(function($){var options={series:{images:{show:false,alpha:1,anchor:"corner"}}};$.plot.image={};$.plot.image.loadDataImages=function(series,options,callback){var urls=[],points=[];var defaultShow=options.series.images.show;$.each(series,function(i,s){if(!(defaultShow||s.images.show))return;if(s.data)s=s.data;$.each(s,function(i,p){if(typeof p[0]=="string"){urls.push(p[0]);points.push(p)}})});$.plot.image.load(urls,function(loadedImages){$.each(points,function(i,p){var url=p[0];if(loadedImages[url])p[0]=loadedImages[url]});callback()})};$.plot.image.load=function(urls,callback){var missing=urls.length,loaded={};if(missing==0)callback({});$.each(urls,function(i,url){var handler=function(){--missing;loaded[url]=this;if(missing==0)callback(loaded)};$("<img />").load(handler).error(handler).attr("src",url)})};function drawSeries(plot,ctx,series){var plotOffset=plot.getPlotOffset();if(!series.images||!series.images.show)return;var points=series.datapoints.points,ps=series.datapoints.pointsize;for(var i=0;i<points.length;i+=ps){var img=points[i],x1=points[i+1],y1=points[i+2],x2=points[i+3],y2=points[i+4],xaxis=series.xaxis,yaxis=series.yaxis,tmp;if(!img||img.width<=0||img.height<=0)continue;if(x1>x2){tmp=x2;x2=x1;x1=tmp}if(y1>y2){tmp=y2;y2=y1;y1=tmp}if(series.images.anchor=="center"){tmp=.5*(x2-x1)/(img.width-1);x1-=tmp;x2+=tmp;tmp=.5*(y2-y1)/(img.height-1);y1-=tmp;y2+=tmp}if(x1==x2||y1==y2||x1>=xaxis.max||x2<=xaxis.min||y1>=yaxis.max||y2<=yaxis.min)continue;var sx1=0,sy1=0,sx2=img.width,sy2=img.height;if(x1<xaxis.min){sx1+=(sx2-sx1)*(xaxis.min-x1)/(x2-x1);x1=xaxis.min}if(x2>xaxis.max){sx2+=(sx2-sx1)*(xaxis.max-x2)/(x2-x1);x2=xaxis.max}if(y1<yaxis.min){sy2+=(sy1-sy2)*(yaxis.min-y1)/(y2-y1);y1=yaxis.min}if(y2>yaxis.max){sy1+=(sy1-sy2)*(yaxis.max-y2)/(y2-y1);y2=yaxis.max}x1=xaxis.p2c(x1);x2=xaxis.p2c(x2);y1=yaxis.p2c(y1);y2=yaxis.p2c(y2);if(x1>x2){tmp=x2;x2=x1;x1=tmp}if(y1>y2){tmp=y2;y2=y1;y1=tmp}tmp=ctx.globalAlpha;ctx.globalAlpha*=series.images.alpha;ctx.drawImage(img,sx1,sy1,sx2-sx1,sy2-sy1,x1+plotOffset.left,y1+plotOffset.top,x2-x1,y2-y1);ctx.globalAlpha=tmp}}function processRawData(plot,series,data,datapoints){if(!series.images.show)return;datapoints.format=[{required:true},{x:true,number:true,required:true},{y:true,number:true,required:true},{x:true,number:true,required:true},{y:true,number:true,required:true}]}function init(plot){plot.hooks.processRawData.push(processRawData);plot.hooks.drawSeries.push(drawSeries)}$.plot.plugins.push({init:init,options:options,name:"image",version:"1.1"})})(jQuery);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +0,0 @@
/* Javascript plotting library for jQuery, version 0.8.3.
Copyright (c) 2007-2014 IOLA and Ole Laursen.
Licensed under the MIT license.
*/
(function($,e,t){"$:nomunge";var i=[],n=$.resize=$.extend($.resize,{}),a,r=false,s="setTimeout",u="resize",m=u+"-special-event",o="pendingDelay",l="activeDelay",f="throttleWindow";n[o]=200;n[l]=20;n[f]=true;$.event.special[u]={setup:function(){if(!n[f]&&this[s]){return false}var e=$(this);i.push(this);e.data(m,{w:e.width(),h:e.height()});if(i.length===1){a=t;h()}},teardown:function(){if(!n[f]&&this[s]){return false}var e=$(this);for(var t=i.length-1;t>=0;t--){if(i[t]==this){i.splice(t,1);break}}e.removeData(m);if(!i.length){if(r){cancelAnimationFrame(a)}else{clearTimeout(a)}a=null}},add:function(e){if(!n[f]&&this[s]){return false}var i;function a(e,n,a){var r=$(this),s=r.data(m)||{};s.w=n!==t?n:r.width();s.h=a!==t?a:r.height();i.apply(this,arguments)}if($.isFunction(e)){i=e;return a}else{i=e.handler;e.handler=a}}};function h(t){if(r===true){r=t||1}for(var s=i.length-1;s>=0;s--){var l=$(i[s]);if(l[0]==e||l.is(":visible")){var f=l.width(),c=l.height(),d=l.data(m);if(d&&(f!==d.w||c!==d.h)){l.trigger(u,[d.w=f,d.h=c]);r=t||true}}else{d=l.data(m);d.w=0;d.h=0}}if(a!==null){if(r&&(t==null||t-r<1e3)){a=e.requestAnimationFrame(h)}else{a=setTimeout(h,n[o]);r=false}}}if(!e.requestAnimationFrame){e.requestAnimationFrame=function(){return e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame||e.msRequestAnimationFrame||function(t,i){return e.setTimeout(function(){t((new Date).getTime())},n[l])}}()}if(!e.cancelAnimationFrame){e.cancelAnimationFrame=function(){return e.webkitCancelRequestAnimationFrame||e.mozCancelRequestAnimationFrame||e.oCancelRequestAnimationFrame||e.msCancelRequestAnimationFrame||clearTimeout}()}})(jQuery,this);(function($){var options={};function init(plot){function onResize(){var placeholder=plot.getPlaceholder();if(placeholder.width()==0||placeholder.height()==0)return;plot.resize();plot.setupGrid();plot.draw()}function bindEvents(plot,eventHolder){plot.getPlaceholder().resize(onResize)}function shutdown(plot,eventHolder){plot.getPlaceholder().unbind("resize",onResize)}plot.hooks.bindEvents.push(bindEvents);plot.hooks.shutdown.push(shutdown)}$.plot.plugins.push({init:init,options:options,name:"resize",version:"1.0"})})(jQuery);

File diff suppressed because one or more lines are too long

View File

@ -1,7 +0,0 @@
/* Javascript plotting library for jQuery, version 0.8.3.
Copyright (c) 2007-2014 IOLA and Ole Laursen.
Licensed under the MIT license.
*/
(function($){var options={series:{stack:null}};function init(plot){function findMatchingSeries(s,allseries){var res=null;for(var i=0;i<allseries.length;++i){if(s==allseries[i])break;if(allseries[i].stack==s.stack)res=allseries[i]}return res}function stackData(plot,s,datapoints){if(s.stack==null||s.stack===false)return;var other=findMatchingSeries(s,plot.getData());if(!other)return;var ps=datapoints.pointsize,points=datapoints.points,otherps=other.datapoints.pointsize,otherpoints=other.datapoints.points,newpoints=[],px,py,intery,qx,qy,bottom,withlines=s.lines.show,horizontal=s.bars.horizontal,withbottom=ps>2&&(horizontal?datapoints.format[2].x:datapoints.format[2].y),withsteps=withlines&&s.lines.steps,fromgap=true,keyOffset=horizontal?1:0,accumulateOffset=horizontal?0:1,i=0,j=0,l,m;while(true){if(i>=points.length)break;l=newpoints.length;if(points[i]==null){for(m=0;m<ps;++m)newpoints.push(points[i+m]);i+=ps}else if(j>=otherpoints.length){if(!withlines){for(m=0;m<ps;++m)newpoints.push(points[i+m])}i+=ps}else if(otherpoints[j]==null){for(m=0;m<ps;++m)newpoints.push(null);fromgap=true;j+=otherps}else{px=points[i+keyOffset];py=points[i+accumulateOffset];qx=otherpoints[j+keyOffset];qy=otherpoints[j+accumulateOffset];bottom=0;if(px==qx){for(m=0;m<ps;++m)newpoints.push(points[i+m]);newpoints[l+accumulateOffset]+=qy;bottom=qy;i+=ps;j+=otherps}else if(px>qx){if(withlines&&i>0&&points[i-ps]!=null){intery=py+(points[i-ps+accumulateOffset]-py)*(qx-px)/(points[i-ps+keyOffset]-px);newpoints.push(qx);newpoints.push(intery+qy);for(m=2;m<ps;++m)newpoints.push(points[i+m]);bottom=qy}j+=otherps}else{if(fromgap&&withlines){i+=ps;continue}for(m=0;m<ps;++m)newpoints.push(points[i+m]);if(withlines&&j>0&&otherpoints[j-otherps]!=null)bottom=qy+(otherpoints[j-otherps+accumulateOffset]-qy)*(px-qx)/(otherpoints[j-otherps+keyOffset]-qx);newpoints[l+accumulateOffset]+=bottom;i+=ps}fromgap=false;if(l!=newpoints.length&&withbottom)newpoints[l+2]+=bottom}if(withsteps&&l!=newpoints.length&&l>0&&newpoints[l]!=null&&newpoints[l]!=newpoints[l-ps]&&newpoints[l+1]!=newpoints[l-ps+1]){for(m=0;m<ps;++m)newpoints[l+ps+m]=newpoints[l+m];newpoints[l+1]=newpoints[l-ps+1]}}datapoints.points=newpoints}plot.hooks.processDatapoints.push(stackData)}$.plot.plugins.push({init:init,options:options,name:"stack",version:"1.2"})})(jQuery);

View File

@ -1,7 +0,0 @@
/* Javascript plotting library for jQuery, version 0.8.3.
Copyright (c) 2007-2014 IOLA and Ole Laursen.
Licensed under the MIT license.
*/
(function($){function processRawData(plot,series,datapoints){var handlers={square:function(ctx,x,y,radius,shadow){var size=radius*Math.sqrt(Math.PI)/2;ctx.rect(x-size,y-size,size+size,size+size)},diamond:function(ctx,x,y,radius,shadow){var size=radius*Math.sqrt(Math.PI/2);ctx.moveTo(x-size,y);ctx.lineTo(x,y-size);ctx.lineTo(x+size,y);ctx.lineTo(x,y+size);ctx.lineTo(x-size,y)},triangle:function(ctx,x,y,radius,shadow){var size=radius*Math.sqrt(2*Math.PI/Math.sin(Math.PI/3));var height=size*Math.sin(Math.PI/3);ctx.moveTo(x-size/2,y+height/2);ctx.lineTo(x+size/2,y+height/2);if(!shadow){ctx.lineTo(x,y-height/2);ctx.lineTo(x-size/2,y+height/2)}},cross:function(ctx,x,y,radius,shadow){var size=radius*Math.sqrt(Math.PI)/2;ctx.moveTo(x-size,y-size);ctx.lineTo(x+size,y+size);ctx.moveTo(x-size,y+size);ctx.lineTo(x+size,y-size)}};var s=series.points.symbol;if(handlers[s])series.points.symbol=handlers[s]}function init(plot){plot.hooks.processDatapoints.push(processRawData)}$.plot.plugins.push({init:init,name:"symbols",version:"1.0"})})(jQuery);

View File

@ -1,7 +0,0 @@
/* Javascript plotting library for jQuery, version 0.8.3.
Copyright (c) 2007-2014 IOLA and Ole Laursen.
Licensed under the MIT license.
*/
(function($){var options={series:{threshold:null}};function init(plot){function thresholdData(plot,s,datapoints,below,color){var ps=datapoints.pointsize,i,x,y,p,prevp,thresholded=$.extend({},s);thresholded.datapoints={points:[],pointsize:ps,format:datapoints.format};thresholded.label=null;thresholded.color=color;thresholded.threshold=null;thresholded.originSeries=s;thresholded.data=[];var origpoints=datapoints.points,addCrossingPoints=s.lines.show;var threspoints=[];var newpoints=[];var m;for(i=0;i<origpoints.length;i+=ps){x=origpoints[i];y=origpoints[i+1];prevp=p;if(y<below)p=threspoints;else p=newpoints;if(addCrossingPoints&&prevp!=p&&x!=null&&i>0&&origpoints[i-ps]!=null){var interx=x+(below-y)*(x-origpoints[i-ps])/(y-origpoints[i-ps+1]);prevp.push(interx);prevp.push(below);for(m=2;m<ps;++m)prevp.push(origpoints[i+m]);p.push(null);p.push(null);for(m=2;m<ps;++m)p.push(origpoints[i+m]);p.push(interx);p.push(below);for(m=2;m<ps;++m)p.push(origpoints[i+m])}p.push(x);p.push(y);for(m=2;m<ps;++m)p.push(origpoints[i+m])}datapoints.points=newpoints;thresholded.datapoints.points=threspoints;if(thresholded.datapoints.points.length>0){var origIndex=$.inArray(s,plot.getData());plot.getData().splice(origIndex+1,0,thresholded)}}function processThresholds(plot,s,datapoints){if(!s.threshold)return;if(s.threshold instanceof Array){s.threshold.sort(function(a,b){return a.below-b.below});$(s.threshold).each(function(i,th){thresholdData(plot,s,datapoints,th.below,th.color)})}else{thresholdData(plot,s,datapoints,s.threshold.below,s.threshold.color)}}plot.hooks.processDatapoints.push(processThresholds)}$.plot.plugins.push({init:init,options:options,name:"threshold",version:"1.2"})})(jQuery);

File diff suppressed because one or more lines are too long

View File

@ -108,18 +108,6 @@ function htmlspecialchars(str)
return s; return s;
} }
function getColOfRating(rating) {
if (rating < 1500) {
var H = 300 - (1500 - 850) * 300 / 1650, S = 30 + (1500 - 850) * 70 / 1650, V = 50 + (1500 - 850) * 50 / 1650;
if (rating < 300) rating = 300;
var k = (rating - 300) / 1200;
return ColorConverter.toStr(ColorConverter.toRGB(new HSV(H + (300 - H) * (1 - k), 30 + (S - 30) * k, 50 + (V - 50) * k)));
}
if (rating > 2500) {
rating = 2500;
}
return ColorConverter.toStr(ColorConverter.toRGB(new HSV(300 - (rating - 850) * 300 / 1650, 30 + (rating - 850) * 70 / 1650, 50 + (rating - 850) * 50 / 1650)));
}
function getColOfScore(score) { function getColOfScore(score) {
if (score == 0) { if (score == 0) {
return ColorConverter.toStr(ColorConverter.toRGB(new HSV(0, 100, 80))); return ColorConverter.toStr(ColorConverter.toRGB(new HSV(0, 100, 80)));
@ -130,82 +118,36 @@ function getColOfScore(score) {
} }
} }
function getUserLink(username, rating, addSymbol) { function getUserLink(username) {
if (!username) { if (!username) {
return ''; return '';
} }
if (addSymbol == undefined) {
addSymbol = true;
}
var text = username; var text = username;
if (username.charAt(0) == '@') { if (username.charAt(0) == '@') {
username = username.substr(1); username = username.substr(1);
} }
if (addSymbol) { return '<a class="uoj-username" href="' + uojHome + '/user/profile/' + username + '">' + text + '</a>';
if (rating >= 2500) {
text += '<sup>';
for (var i = 2500; i <= rating; i += 200) {
text += "&alefsym;"
} }
text += "</sup>"; function getUserSpan(username) {
}
}
return '<a class="uoj-username" href="' + uojHome + '/user/profile/' + username + '" style="color:' + getColOfRating(rating) + '">' + text + '</a>';
}
function getUserSpan(username, rating, addSymbol) {
if (!username) { if (!username) {
return ''; return '';
} }
if (addSymbol == undefined) {
addSymbol = true;
}
var text = username; var text = username;
if (username.charAt(0) == '@') { if (username.charAt(0) == '@') {
username = username.substr(1); username = username.substr(1);
} }
if (addSymbol) { return '<span class="uoj-username">' + text + '</span>';
if (rating >= 2500) {
text += '<sup>';
for (var i = 2500; i <= rating; i += 200) {
text += "&alefsym;"
}
text += "</sup>";
}
}
return '<span class="uoj-username" style="color:' + getColOfRating(rating) + '">' + text + '</span>';
} }
function replaceWithHighlightUsername() { function replaceWithHighlightUsername() {
var username = $(this).text(); var username = $(this).text();
var rating = $(this).data("rating");
if (isNaN(rating)) {
return;
}
if ($(this).data("link") != 0) { if ($(this).data("link") != 0) {
$(this).replaceWith(getUserLink(username, rating)); $(this).replaceWith(getUserLink(username));
} else { } else {
$(this).replaceWith(getUserSpan(username, rating)); $(this).replaceWith(getUserSpan(username));
} }
} }
$.fn.uoj_honor = function() {
return this.each(function() {
var honor = $(this).text();
var rating = $(this).data("rating");
if (isNaN(rating)) {
return;
}
if (rating >= 2500) {
honor += '<sup>';
for (var i = 2500; i <= rating; i += 200) {
honor += "&alefsym;"
}
honor += "</sup>";
}
$(this).css("color", getColOfRating(rating)).html(honor);
});
}
function showErrorHelp(name, err) { function showErrorHelp(name, err) {
if (err) { if (err) {
$('#div-' + name).addClass('has-error'); $('#div-' + name).addClass('has-error');
@ -422,7 +364,6 @@ $(document).ready(function() {
$.fn.uoj_highlight = function() { $.fn.uoj_highlight = function() {
return $(this).each(function() { return $(this).each(function() {
$(this).find("span.uoj-username").each(replaceWithHighlightUsername); $(this).find("span.uoj-username").each(replaceWithHighlightUsername);
$(this).find(".uoj-honor").uoj_honor();
$(this).find(".uoj-score").each(function() { $(this).find(".uoj-score").each(function() {
var score = parseInt($(this).text()); var score = parseInt($(this).text());
var maxscore = parseInt($(this).data('max')); var maxscore = parseInt($(this).data('max'));
@ -1069,7 +1010,7 @@ function showCommentReplies(id, replies) {
function(reply) { function(reply) {
return $('<tr id="' + 'comment-' + reply.id + '" />').append( return $('<tr id="' + 'comment-' + reply.id + '" />').append(
$('<td />').append( $('<td />').append(
$('<div class="comtbox6">' + getUserLink(reply.poster, reply.poster_rating) + '' + reply.content + '</div>') $('<div class="comtbox6">' + getUserLink(reply.poster) + '' + reply.content + '</div>')
).append( ).append(
$('<ul class="text-right list-inline bot-buffer-no" />').append( $('<ul class="text-right list-inline bot-buffer-no" />').append(
'<li>' + '<small class="text-muted">' + reply.post_time + '</small>' + '</li>' '<li>' + '<small class="text-muted">' + reply.post_time + '</small>' + '</li>'
@ -1107,7 +1048,7 @@ function showStandings() {
function(row) { function(row) {
var col_tr = '<tr>'; var col_tr = '<tr>';
col_tr += '<td>' + row[3] + '</td>'; col_tr += '<td>' + row[3] + '</td>';
col_tr += '<td>' + getUserLink(row[2][0], row[2][1]) + '</td>'; col_tr += '<td>' + getUserLink(row[2][0]) + '</td>';
col_tr += '<td>' + '<div><span class="uoj-score" data-max="' + problems.length * 100 + '" style="color:' + getColOfScore(row[0] / problems.length) + '">' + row[0] + '</span></div>' + '<div>' + getPenaltyTimeStr(row[1]) + '</div></td>'; col_tr += '<td>' + '<div><span class="uoj-score" data-max="' + problems.length * 100 + '" style="color:' + getColOfScore(row[0] / problems.length) + '">' + row[0] + '</span></div>' + '<div>' + getPenaltyTimeStr(row[1]) + '</div></td>';
for (var i = 0; i < problems.length; i++) { for (var i = 0; i < problems.length; i++) {
col_tr += '<td>'; col_tr += '<td>';