Browse Source

Change problem id in contests to letters, add problem statistics in contest

master
Menci 8 years ago
parent
commit
6b641d613b
  1. 1
      models/contest_ranklist.js
  2. 33
      modules/contest.js
  3. 16
      views/contest.ejs
  4. 13
      views/contest_submissions.ejs
  5. 4
      views/problem.ejs
  6. 2
      views/submission_content.ejs
  7. 2
      views/submissions_item.ejs
  8. 10
      views/util.ejs

1
models/contest_ranklist.js

@ -69,7 +69,6 @@ class ContestRanklist extends Model {
for (let player of players) { for (let player of players) {
player.latest = 0; player.latest = 0;
for (let i in player.score_details) { for (let i in player.score_details) {
console.log(player.score_details);
let judge_state = await JudgeState.fromID(player.score_details[i].judge_id); let judge_state = await JudgeState.fromID(player.score_details[i].judge_id);
player.latest = Math.max(player.latest, judge_state.submit_time); player.latest = Math.max(player.latest, judge_state.submit_time);
} }

33
modules/contest.js

@ -131,7 +131,7 @@ app.get('/contest/:id', async (req, res) => {
}); });
} }
problems = problems.map(x => ({ problem: x, status: null, judge_id: null })); problems = problems.map(x => ({ problem: x, status: null, judge_id: null, statistics: null }));
if (player) { if (player) {
for (let problem of problems) { for (let problem of problems) {
if (contest.type === 'noi') { if (contest.type === 'noi') {
@ -168,9 +168,38 @@ app.get('/contest/:id', async (req, res) => {
} }
} }
let hasStatistics = false;
if (contest.type === 'ioi' || contest.type === 'acm' || (contest.type === 'noi' && (contest.ended || (res.locals.user && res.locals.user.is_admin)))) {
hasStatistics = true;
await contest.loadRelationships();
let players = await contest.ranklist.getPlayers();
for (let problem of problems) {
problem.statistics = { attempt: 0, accepted: 0 };
if (contest.type === 'ioi' || contest.type === 'noi') {
problem.statistics.partially = 0;
}
for (let player of players) {
if (player.score_details[problem.problem.id]) {
problem.statistics.attempt++;
if ((contest.type === 'acm' && player.score_details[problem.problem.id].accepted) || ((contest.type === 'noi' || contest.type === 'ioi') && player.score_details[problem.problem.id].score === 100)) {
problem.statistics.accepted++;
}
if ((contest.type === 'noi' || contest.type === 'ioi') && player.score_details[problem.problem.id].score > 0) {
problem.statistics.partially++;
}
}
}
}
}
res.render('contest', { res.render('contest', {
contest: contest, contest: contest,
problems: problems problems: problems,
hasStatistics: hasStatistics
}); });
} catch (e) { } catch (e) {
syzoj.log(e); syzoj.log(e);

16
views/contest.ejs

@ -49,7 +49,10 @@
<thead> <thead>
<tr> <tr>
<th class="one wide" style="text-align: center">状态</th> <th class="one wide" style="text-align: center">状态</th>
<th class="fourteen wide">题目</th> <th>题目</th>
<% if (hasStatistics) { %>
<th class="one wide center aligned">统计</th>
<% } %>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -89,6 +92,17 @@
<% } %> <% } %>
</td> </td>
<td><a href="<%= syzoj.utils.makeUrl(['contest', contest.id, i]) %>"><%= syzoj.utils.removeTitleTag(problem.problem.title) %></a></td> <td><a href="<%= syzoj.utils.makeUrl(['contest', contest.id, i]) %>"><%= syzoj.utils.removeTitleTag(problem.problem.title) %></a></td>
<% if (hasStatistics) { %>
<td class="center aligned" style="white-space: nowrap; ">
<a href="<%= syzoj.utils.makeUrl(['contest', contest.id, 'submissions'], { problem_id: i, status: 'Accepted' }) %>"><%= problem.statistics.accepted %></a>
/
<a href="<%= syzoj.utils.makeUrl(['contest', contest.id, 'submissions'], { problem_id: i, min_score: 1 }) %>"><%= problem.statistics.partially %></a>
<% if (contest.type === 'noi' || contest.type === 'ioi') { %>
/
<% } %>
<a href="<%= syzoj.utils.makeUrl(['contest', contest.id, 'submissions'], { problem_id: i }) %>"><%= problem.statistics.attempt %></a>
</td>
<% } %>
</tr> </tr>
<% } %> <% } %>
</tbody> </tbody>

13
views/contest_submissions.ejs

@ -2,10 +2,11 @@
<script src="https://cdn.staticfile.org/textfit/2.3.1/textFit.min.js"></script> <script src="https://cdn.staticfile.org/textfit/2.3.1/textFit.min.js"></script>
<% include header %> <% include header %>
<div class="padding"> <div class="padding">
<form action="<%= syzoj.utils.makeUrl(['contest', contest.id, 'submissions']) %>" class="ui mini form" method="get" role="form" id="form"> <form action="<%= syzoj.utils.makeUrl(['contest', contest.id, 'submissions']) %>" class="ui mini form" method="get" role="form" id="form" onsubmit="return checkSubmit()">
<div class="inline fields" style="margin-bottom: 25px; "> <div class="inline fields" style="margin-bottom: 25px; ">
<label style="font-size: 1.2em; margin-right: 3px; ">题目 ID:</label> <label style="font-size: 1.2em; margin-right: 3px; ">题目 ID:</label>
<div class="field"><input name="problem_id" style="width: 50px; " type="text" value="<%= form.problem_id %>"></div> <div class="field"><input id="problem_id" style="width: 50px; " type="text" value="<%= this.alpha(form.problem_id) %>"></div>
<input type="hidden" name="problem_id" id="problem_id_hidden">
<label style="font-size: 1.2em; margin-right: 3px; ">提交者:</label> <label style="font-size: 1.2em; margin-right: 3px; ">提交者:</label>
<div class="field"><input name="submitter" style="width: 100px; " type="text" value="<%= form.submitter %>"></div> <div class="field"><input name="submitter" style="width: 100px; " type="text" value="<%= form.submitter %>"></div>
<% if ((typeof contest === 'undefined' || !contest) || contest.ended || contest.type !== 'noi' || (user && user.is_admin)) { %> <% if ((typeof contest === 'undefined' || !contest) || contest.ended || contest.type !== 'noi' || (user && user.is_admin)) { %>
@ -94,5 +95,13 @@ $(function () {
$('#select_language').dropdown(); $('#select_language').dropdown();
$('#select_status').dropdown(); $('#select_status').dropdown();
}); });
function checkSubmit() {
var x = $('#problem_id').val(), ch = x.charCodeAt(0);
if (x.length === 1 && x >= 'A' && x <= 'Z') $('#problem_id_hidden').val(ch - 'A'.charCodeAt(0) + 1);
else if (x.length === 1 && x >= 'a' && x <= 'a') $('#problem_id_hidden').val(ch - 'a'.charCodeAt(0) + 1);
else $('#problem_id_hidden').val(x);
return true;
}
</script> </script>
<% include footer %> <% include footer %>

4
views/problem.ejs

@ -1,7 +1,7 @@
<% <%
if (typeof contest === 'undefined') contest = null; if (typeof contest === 'undefined') contest = null;
if (contest) { if (contest) {
this.title = syzoj.utils.removeTitleTag(problem.title) + ' - ' + contest.title + ' - 比赛'; this.title = this.alpha(pid) + '. ' + syzoj.utils.removeTitleTag(problem.title) + ' - ' + contest.title + ' - 比赛';
} else { } else {
this.title = problem.title + ' - 题目'; this.title = problem.title + ' - 题目';
} }
@ -22,7 +22,7 @@ if (contest) {
<div class="row"> <div class="row">
<h1 class="ui header"> <h1 class="ui header">
<% if (contest) { %> <% if (contest) { %>
#<%= pid %>. <%= syzoj.utils.removeTitleTag(problem.title) %> <%= this.alpha(pid) %>. <%= syzoj.utils.removeTitleTag(problem.title) %>
<% } else { %> <% } else { %>
#<%= problem.id %>. <%= problem.title %><% if (problem.allowedEdit && !problem.is_public) { %><span class="ui tiny red label">未公开</span><% } %> #<%= problem.id %>. <%= problem.title %><% if (problem.allowedEdit && !problem.is_public) { %><span class="ui tiny red label">未公开</span><% } %>
<% } %> <% } %>

2
views/submission_content.ejs

@ -48,7 +48,7 @@ else problemUrl = syzoj.utils.makeUrl(['problem', judge.problem_id]);
<tbody> <tbody>
<tr> <tr>
<td>#<%= judge.id %></td> <td>#<%= judge.id %></td>
<td><a style="width: 220px; height: 22px; display: block; margin: 0 auto; line-height: 22px; " id="text-fit" href="<%= problemUrl %>">#<%= judge.problem_id %>. <%= judge.problem.title %></a></td> <td><a style="width: 220px; height: 22px; display: block; margin: 0 auto; line-height: 22px; " id="text-fit" href="<%= problemUrl %>"><%= (typeof contest !== 'undefined' && contest) ? this.alpha(judge.problem_id) : ('#' + judge.problem_id) %>. <%= judge.problem.title %></a></td>
<% if (judge.allowedSeeResult) { %> <% if (judge.allowedSeeResult) { %>
<td class="status <%= getStatusMeta(judge.result.status).toLowerCase().split(' ').join('_') %>"> <td class="status <%= getStatusMeta(judge.result.status).toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(judge.status)] || 'remove' %> icon"></i> <i class="<%= icon[getStatusMeta(judge.status)] || 'remove' %> icon"></i>

2
views/submissions_item.ejs

@ -5,7 +5,7 @@ if (typeof contest !== 'undefined' && contest) problemUrl = syzoj.utils.makeUrl(
else problemUrl = syzoj.utils.makeUrl(['problem', judge.problem_id]); else problemUrl = syzoj.utils.makeUrl(['problem', judge.problem_id]);
%> %>
<td><a href="<%= syzoj.utils.makeUrl(['submission', judge.id]) %>">#<%= judge.id %></a></td> <td><a href="<%= syzoj.utils.makeUrl(['submission', judge.id]) %>">#<%= judge.id %></a></td>
<td><a style="width: 220px; height: 22px; display: block; margin: 0 auto; line-height: 22px; " id="text-fit-<%= judge.id %>" href="<%= problemUrl %>">#<%= judge.problem_id %>. <%= judge.problem.title %></a></td> <td><a style="width: 220px; height: 22px; display: block; margin: 0 auto; line-height: 22px; " id="text-fit-<%= judge.id %>" href="<%= problemUrl %>"><%= (typeof contest !== 'undefined' && contest) ? this.alpha(judge.problem_id) : ('#' + judge.problem_id) %>. <%= judge.problem.title %></a></td>
<script> <script>
var e = document.getElementById('text-fit-<%= judge.id %>'); var e = document.getElementById('text-fit-<%= judge.id %>');
textFit(e, { maxFontSize: 14 }); textFit(e, { maxFontSize: 14 });

10
views/util.ejs

@ -2,7 +2,7 @@
this.getStatusMeta = (status) => { this.getStatusMeta = (status) => {
if (status.startsWith('Running')) return 'Running'; if (status.startsWith('Running')) return 'Running';
else return status; else return status;
} };
this.isPending = (status) => { this.isPending = (status) => {
let pending = [ let pending = [
@ -11,7 +11,11 @@ this.isPending = (status) => {
'Running' 'Running'
]; ];
return pending.includes(this.getStatusMeta(status)); return pending.includes(this.getStatusMeta(status));
} };
this.alpha = number => {
if (number && parseInt(number) == number && parseInt(number) > 0) return String.fromCharCode('A'.charCodeAt(0) + parseInt(number) - 1);
};
this.icon = { this.icon = {
'Accepted': 'checkmark', 'Accepted': 'checkmark',
@ -29,5 +33,5 @@ this.icon = {
'No Testdata': 'folder open outline', 'No Testdata': 'folder open outline',
'Partially Correct': 'minus', 'Partially Correct': 'minus',
'Judgement Failed': 'ban' 'Judgement Failed': 'ban'
} };
%> %>

Loading…
Cancel
Save