Browse Source

Add support for ACM and IOI contest

pull/6/head
Menci 7 years ago
parent
commit
24bacde025
  1. 8
      models/contest.js
  2. 93
      models/contest_player.js
  3. 48
      models/contest_ranklist.js
  4. 17
      models/judge_state.js
  5. 36
      modules/contest.js
  6. 6
      modules/problem.js
  7. 4
      modules/submission.js
  8. 27
      views/contest.ejs
  9. 21
      views/contest_edit.ejs
  10. 106
      views/contest_ranklist.ejs
  11. 2
      views/contest_submissions.ejs
  12. 3
      views/header.ejs
  13. 58
      views/submission_content.ejs

8
models/contest.js

@ -40,6 +40,8 @@ let model = db.define('contest', {
key: 'id'
}
},
// type: noi, ioi, acm
type: { type: Sequelize.STRING(10) },
information: { type: Sequelize.TEXT },
problems: { type: Sequelize.TEXT },
@ -71,6 +73,7 @@ class Contest extends Model {
title: '',
problems: '',
information: '',
type: 'noi',
start_time: 0,
end_time: 0,
holder: 0,
@ -88,6 +91,7 @@ class Contest extends Model {
}
async isAllowedSeeResultBy(user) {
if (this.type === 'acm' || this.type === 'ioi') return true;
return (user && (user.is_admin || this.holder_id === user.id)) || !(await this.isRunning());
}
@ -111,6 +115,8 @@ class Contest extends Model {
}
async newSubmission(judge_state) {
if (judge_state.pending) return;
let problems = await this.getProblems();
if (!problems.includes(judge_state.problem_id)) throw new ErrorMessage('当前比赛中无此题目。');
@ -130,7 +136,7 @@ class Contest extends Model {
await player.save();
await this.loadRelationships();
await this.ranklist.updatePlayer(player);
await this.ranklist.updatePlayer(this, player);
await this.ranklist.save();
}

93
models/contest_player.js

@ -24,7 +24,6 @@ let db = syzoj.db;
let User = syzoj.model('user');
let Problem = syzoj.model('problem');
let Contest = syzoj.model('contest');
let model = db.define('contest_player', {
id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
@ -64,18 +63,96 @@ class ContestPlayer extends Model {
}
async loadRelationships() {
let Contest = syzoj.model('contest');
this.user = await User.fromID(this.user_id);
this.contest = await Contest.fromID(this.contest_id);
}
async updateScore(judge_state) {
this.score_details[judge_state.problem_id] = {
score: judge_state.score,
judge_id: judge_state.id
};
this.score = 0;
for (let x in this.score_details) {
this.score += this.score_details[x].score;
await this.loadRelationships();
if (this.contest.type === 'ioi') {
if (!this.score_details[judge_state.problem_id]) {
this.score_details[judge_state.problem_id] = {
score: judge_state.score,
judge_id: judge_state.id,
submissions: {}
};
}
this.score_details[judge_state.problem_id].submissions[judge_state.id] = {
judge_id: judge_state.id,
score: judge_state.score,
time: judge_state.submit_time
};
let arr = Object.values(this.score_details[judge_state.problem_id].submissions);
arr.sort((a, b) => a.time - b.time);
let maxScoreSubmission = null;
for (let x of arr) {
if (!maxScoreSubmission || x.score >= maxScoreSubmission.score && maxScoreSubmission.score < 100) {
maxScoreSubmission = x;
}
}
this.score_details[judge_state.problem_id].judge_id = maxScoreSubmission.judge_id;
this.score_details[judge_state.problem_id].score = maxScoreSubmission.score;
this.score_details[judge_state.problem_id].time = maxScoreSubmission.time;
this.score = 0;
for (let x in this.score_details) {
this.score += this.score_details[x].score;
}
} else if (this.contest.type === 'noi') {
this.score_details[judge_state.problem_id] = {
score: judge_state.score,
judge_id: judge_state.id
};
this.score = 0;
for (let x in this.score_details) {
this.score += this.score_details[x].score;
}
} else if (this.contest.type === 'acm') {
if (!this.score_details[judge_state.problem_id]) {
this.score_details[judge_state.problem_id] = {
accepted: false,
unacceptedCount: 0,
acceptedTime: 0,
judge_id: 0,
submissions: {}
};
}
this.score_details[judge_state.problem_id].submissions[judge_state.id] = {
judge_id: judge_state.id,
accepted: judge_state.status === 'Accepted',
time: judge_state.submit_time
};
let arr = Object.values(this.score_details[judge_state.problem_id].submissions);
arr.sort((a, b) => a.time - b.time);
this.score_details[judge_state.problem_id].unacceptedCount = 0;
this.score_details[judge_state.problem_id].judge_id = 0;
for (let x of arr) {
if (x.accepted) {
this.score_details[judge_state.problem_id].accepted = true;
this.score_details[judge_state.problem_id].acceptedTime = x.time;
this.score_details[judge_state.problem_id].judge_id = x.judge_id;
break;
} else {
this.score_details[judge_state.problem_id].unacceptedCount++;
}
}
if (!this.score_details[judge_state.problem_id].accepted) {
this.score_details[judge_state.problem_id].judge_id = arr[arr.length - 1].judge_id;
}
this.score = 0;
for (let x in this.score_details) {
if (this.score_details[x].accepted) this.score++;
}
}
}

48
models/contest_ranklist.js

@ -50,7 +50,7 @@ class ContestRanklist extends Model {
return a;
}
async updatePlayer(player) {
async updatePlayer(contest, player) {
let players = await this.getPlayers(), newPlayer = true;
for (let x of players) {
if (x.user_id === player.user_id) {
@ -65,21 +65,41 @@ class ContestRanklist extends Model {
let JudgeState = syzoj.model('judge_state');
for (let player of players) {
player.latest = 0;
for (let i in player.score_details) {
let judge_state = await JudgeState.fromID(player.score_details[i].judge_id);
player.latest = Math.max(player.latest, judge_state.submit_time);
if (contest.type === 'noi' || contest.type === 'ioi') {
for (let player of players) {
player.latest = 0;
for (let i in player.score_details) {
console.log(player.score_details);
let judge_state = await JudgeState.fromID(player.score_details[i].judge_id);
player.latest = Math.max(player.latest, judge_state.submit_time);
}
}
players.sort((a, b) => {
if (a.score > b.score) return -1;
if (b.score > a.score) return 1;
if (a.latest < b.latest) return -1;
if (a.latest > b.latest) return 1;
return 0;
});
} else {
for (let player of players) {
player.timeSum = 0;
for (let i in player.score_details) {
if (player.score_details[i].accepted) {
player.timeSum += (player.score_details[i].acceptedTime - contest.start_time) + (player.score_details[i].unacceptedCount * 20 * 60);
}
}
}
}
players.sort((a, b) => {
if (a.score > b.score) return -1;
if (b.score > a.score) return 1;
if (a.latest < b.latest) return -1;
if (a.latest > b.latest) return 1;
return 0;
});
players.sort((a, b) => {
if (a.score > b.score) return -1;
if (b.score > a.score) return 1;
if (a.timeSum < b.timeSum) return -1;
if (a.timeSum > b.timeSum) return 1;
return 0;
});
}
this.ranklist = { player_num: players.length };
for (let i = 0; i < players.length; i++) this.ranklist[i + 1] = players[i].id;

17
models/judge_state.js

@ -107,7 +107,7 @@ class JudgeState extends Model {
else if (this.type === 1) {
let contest = await Contest.fromID(this.type_info);
if (await contest.isRunning()) {
return false;
return contest.type === 'acm' || contest.type === 'ioi';
} else {
return true;
}
@ -129,6 +129,21 @@ class JudgeState extends Model {
} else if (this.type === 2) return false;
}
async isAllowedSeeDataBy(user) {
await this.loadRelationships();
if (user && (await user.hasPrivilege('manage_problem') || user.id === this.problem.user_id)) return true;
else if (this.type === 0) return this.problem.is_public;
else if (this.type === 1) {
let contest = await Contest.fromID(this.type_info);
if (await contest.isRunning()) {
return false;
} else {
return true;
}
} else if (this.type === 2) return true;
}
async updateResult(result) {
this.score = result.score;
this.pending = result.pending;

36
modules/contest.js

@ -91,6 +91,8 @@ app.post('/contest/:id/edit', async (req, res) => {
contest.title = req.body.title;
if (!Array.isArray(req.body.problems)) req.body.problems = [req.body.problems];
contest.problems = req.body.problems.join('|');
if (!['noi', 'ioi', 'acm'].includes(req.body.type)) throw new ErrorMessage('无效的赛制。');
contest.type = req.body.type;
contest.information = req.body.information;
contest.start_time = syzoj.utils.parseDate(req.body.start_time);
contest.end_time = syzoj.utils.parseDate(req.body.end_time);
@ -132,17 +134,35 @@ app.get('/contest/:id', async (req, res) => {
problems = problems.map(x => ({ problem: x, status: null, judge_id: null }));
if (player) {
for (let problem of problems) {
if (player.score_details[problem.problem.id]) {
if (await contest.isRunning()) {
problem.status = true;
if (contest.type === 'noi') {
if (player.score_details[problem.problem.id]) {
if (await contest.isRunning()) {
problem.status = true;
} else {
let judge_state = await JudgeState.fromID(player.score_details[problem.problem.id].judge_id);
problem.status = judge_state.status;
}
problem.judge_id = player.score_details[problem.problem.id].judge_id;
} else {
if (contest.isRunning()) {
problem.status = false;
}
}
} else if (contest.type === 'ioi') {
if (player.score_details[problem.problem.id]) {
let judge_state = await JudgeState.fromID(player.score_details[problem.problem.id].judge_id);
problem.status = judge_state.status;
problem.judge_id = player.score_details[problem.problem.id].judge_id;
}
problem.judge_id = player.score_details[problem.problem.id].judge_id;
} else {
if (contest.isRunning()) {
problem.status = false;
} else if (contest.type === 'acm') {
if (player.score_details[problem.problem.id]) {
problem.status = {
accepted: player.score_details[problem.problem.id].accepted,
unacceptedCount: player.score_details[problem.problem.id].unacceptedCount
};
problem.judge_id = player.score_details[problem.problem.id].judge_id;
} else {
problem.status = null;
}
}
}
@ -221,7 +241,7 @@ app.get('/contest/:id/submissions', async (req, res) => {
where.type = 1;
where.type_info = contest_id;
if (contest.ended || (res.locals.user && res.locals.user.is_admin)) {
if (contest.ended || contest.type !== 'noi' || (res.locals.user && res.locals.user.is_admin)) {
let minScore = parseInt(req.query.min_score);
if (isNaN(minScore)) minScore = 0;
let maxScore = parseInt(req.query.max_score);

6
modules/problem.js

@ -489,7 +489,7 @@ app.post('/problem/:id/submit', async (req, res) => {
problem_id: req.params.id
});
let contest_id = parseInt(req.query.contest_id);
let contest_id = parseInt(req.query.contest_id), redirectToContest = false;
if (contest_id) {
let contest = await Contest.fromID(contest_id);
if (!contest) throw new ErrorMessage('无此比赛。');
@ -500,6 +500,8 @@ app.post('/problem/:id/submit', async (req, res) => {
judge_state.type_info = contest_id;
await judge_state.save();
if (contest.type === 'noi') redirectToContest = true;
} else {
if (!await problem.isAllowedUseBy(res.locals.user)) throw new ErrorMessage('您没有权限进行此操作。');
judge_state.type = problem.is_public ? 0 : 2;
@ -513,7 +515,7 @@ app.post('/problem/:id/submit', async (req, res) => {
await waiting_judge.save();
if (contest_id) {
if (redirectToContest) {
res.redirect(syzoj.utils.makeUrl(['contest', contest_id]));
} else {
res.redirect(syzoj.utils.makeUrl(['submission', judge_state.id]));

4
modules/submission.js

@ -54,6 +54,7 @@ app.get('/submissions', async (req, res) => {
await judge_state.forEachAsync(async obj => obj.loadRelationships());
await judge_state.forEachAsync(async obj => obj.hidden = !(await obj.isAllowedSeeResultBy(res.locals.user)));
await judge_state.forEachAsync(async obj => obj.allowedSeeCode = await obj.isAllowedSeeCodeBy(res.locals.user));
await judge_state.forEachAsync(async obj => obj.allowedSeeData = await obj.isAllowedSeeDataBy(res.locals.user));
res.render('submissions', {
judge_state: judge_state,
@ -77,6 +78,7 @@ app.get('/submissions/:id/ajax', async (req, res) => {
judge_state.hidden = !(await judge_state.isAllowedSeeResultBy(res.locals.user));
judge_state.allowedSeeCode = await judge_state.isAllowedSeeCodeBy(res.locals.user);
judge_state.allowedSeeData = await judge_state.isAllowedSeeDataBy(res.locals.user);
res.render('submissions_item', {
judge: judge_state
@ -103,6 +105,7 @@ app.get('/submission/:id', async (req, res) => {
judge.code = await syzoj.utils.highlight(judge.code, syzoj.config.languages[judge.language].highlight);
judge.allowedSeeResult = await judge.isAllowedSeeResultBy(res.locals.user);
judge.allowedSeeCode = await judge.isAllowedSeeCodeBy(res.locals.user);
judge.allowedSeeData = await judge.isAllowedSeeDataBy(res.locals.user);
judge.allowedRejudge = await judge.problem.isAllowedEditBy(res.locals.user);
if (contest) {
@ -137,6 +140,7 @@ app.get('/submission/:id/ajax', async (req, res) => {
judge.code = await syzoj.utils.highlight(judge.code, syzoj.config.languages[judge.language].highlight);
judge.allowedSeeResult = await judge.isAllowedSeeResultBy(res.locals.user);
judge.allowedSeeCode = await judge.isAllowedSeeCodeBy(res.locals.user);
judge.allowedSeeData = await judge.isAllowedSeeDataBy(res.locals.user);
judge.allowedRejudge = await judge.problem.isAllowedEditBy(res.locals.user);
if (contest) {

27
views/contest.ejs

@ -4,6 +4,7 @@
.ui.label.pointing.below.right::before { left: 88%; }
.ui.label.pointing.below.left { margin-bottom: 0; }
.ui.label.pointing.below.right { margin-bottom: 0; float: right; }
#back_to_contest { display: none; }
</style>
<% include header %>
<div class="padding">
@ -20,7 +21,7 @@
<div class="bar" style="width: <%= timePercentage %>%;"></div>
</div>
<div class="ui grid">
<% if (contest.allowedEdit || (unveiled && !contest.running)) { %>
<% if (contest.allowedEdit || (unveiled && (!contest.running || contest.type !== 'noi'))) { %>
<div class="row">
<div class="column">
<div class="ui buttons">
@ -49,7 +50,6 @@
<tr>
<th class="one wide" style="text-align: center">状态</th>
<th class="fourteen wide">题目</th>
<th class="one wide" style="text-align: center">代码</th>
</tr>
</thead>
<tbody>
@ -64,20 +64,31 @@
<a href="<%= syzoj.utils.makeUrl(['submission', problem.judge_id]) %>">
<% if (problem.status === true) { %>
<i class="black checkmark icon"></i>
<% } else if (problem.status !== false) { %>
<% } else if (typeof problem.status === 'string') { %>
<span class="status <%= problem.status.toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(problem.status)] || 'remove' %> icon"></i>
<%= problem.status %>
</span>
<% } else if (typeof problem.status === 'object') { %>
<% if (problem.status.accepted) { %>
<span class="score score_10">
<% if (problem.status.unacceptedCount === 0) { %>
+
<% } else { %>
+<%= problem.status.unacceptedCount %>
<% } %>
</span>
<% } else { %>
<span class="score score_0">
<% if (problem.status.unacceptedCount !== 0) { %>
-<%= problem.status.unacceptedCount %>
<% } %>
</span>
<% } %>
<% } %>
<% } %>
</td>
<td><a href="<%= syzoj.utils.makeUrl(['contest', contest.id, i]) %>"><%= syzoj.utils.removeTitleTag(problem.problem.title) %></a></td>
<td class="center aligned">
<% if (problem.judge_id) { %>
<a href="<%= syzoj.utils.makeUrl(['submission', problem.judge_id]) %>"><i style="color: #000;" class="code icon"></i></a>
<% } %>
</td>
</tr>
<% } %>
</tbody>

21
views/contest_edit.ejs

@ -14,6 +14,27 @@
<% } %>
</select>
</div>
<div class="inline fields">
<label>赛制</label>
<div class="field">
<div class="ui radio checkbox">
<input type="radio" name="type" id="type-noi" value="noi"<% if (contest.type === 'noi') { %> checked="checked"<% } %>>
<label for="type-noi">NOI</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox">
<input type="radio" name="type" id="type-ioi" value="ioi"<% if (contest.type === 'ioi') { %> checked="checked"<% } %>>
<label for="type-ioi">IOI</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox">
<input type="radio" name="type" id="type-acm" value="acm"<% if (contest.type === 'acm') { %> checked="checked"<% } %>>
<label for="type-acm">ACM</label>
</div>
</div>
</div>
<div class="field">
<label>比赛介绍</label>
<textarea class="" rows="5" id="doc-ta-1" name="information" class="font-content"><%= contest.information %></textarea>

106
views/contest_ranklist.ejs

@ -4,6 +4,7 @@
.submit_time {
font-size: 0.8em;
margin-top: 5px;
color: #000;
}
</style>
<div class="padding">
@ -12,12 +13,20 @@
<tr>
<th>#</th>
<th>用户名</th>
<% for (let problem of problems) { %>
<th><a href="<%= syzoj.utils.makeUrl(['problem', problem.id]) %>">
<%= syzoj.utils.removeTitleTag(problem.title) %>
</a></th>
<% if (contest.type === 'acm') { %>
<th>通过数量</th>
<th>罚时</th>
<% } %>
<% for (let i = 0; i < problems.length; i++) { %>
<th>
<a href="<%= syzoj.utils.makeUrl(['contest', contest.id, i + 1]) %>">
<%= syzoj.utils.removeTitleTag(problems[i].title) %>
</a>
</th>
<% } %>
<% if (contest.type === 'noi' || contest.type === 'ioi') { %>
<th>总分</th>
<% } %>
<th>总分</th>
</tr>
</thead>
<tbody>
@ -25,7 +34,7 @@
let i = 0;
for (let item of ranklist) {
i++
let latest = contest.start_time;
let latest = contest.start_time, timeSum = 0, unacceptedCount = 0;
%>
<tr>
<td>
@ -42,30 +51,73 @@
</div>
</td>
<td><a href="<%= syzoj.utils.makeUrl(['user', item.user.id]) %>"><%= item.user.username %></a><% if (item.user.nameplate) { %><%- item.user.nameplate %><% } %></td>
<%
if (contest.type === 'acm') {
for (let problem of problems) {
if (item.player.score_details[problem.id] && item.player.score_details[problem.id].accepted) {
timeSum += (item.player.score_details[problem.id].acceptedTime - contest.start_time) + (item.player.score_details[problem.id].unacceptedCount * 20 * 60);
unacceptedCount += item.player.score_details[problem.id].unacceptedCount;
}
}
%>
<td>
<span class="score score_<%= parseInt((item.player.score / ranklist[0].player.score * 10) || 0) %>">
<%= item.player.score %>
</span>
</td>
<td>
<%= syzoj.utils.formatTime(timeSum) %>
</td>
<% } %>
<% for (let problem of problems) { %>
<% if (item.player.score_details[problem.id]) { %>
<td><a href="<%= syzoj.utils.makeUrl(['submission', item.player.score_details[problem.id].judge_id]) %>">
<span class="score score_<%= parseInt((item.player.score_details[problem.id].score / 10) || 0) %>">
<%= item.player.score_details[problem.id].score %>
</span>
</a>
<div class="submit_time">
<%= syzoj.utils.formatTime(item.player.score_details[problem.id].judge_state.submit_time - contest.start_time) %>
<% latest = Math.max(latest, item.player.score_details[problem.id].judge_state.submit_time) %>
</div>
</td>
<% } else { %>
<td></td>
<% if (!item.player.score_details[problem.id]) { %>
<td></td>
<% } else if (contest.type === 'acm') { %>
<td>
<a href="<%= syzoj.utils.makeUrl(['submission', item.player.score_details[problem.id].judge_id]) %>">
<% if (item.player.score_details[problem.id].accepted) { %>
<span class="score score_10">
<% if (item.player.score_details[problem.id].unacceptedCount) { %>
+<%= item.player.score_details[problem.id].unacceptedCount %>
<% } else { %>
+
<% } %>
</span>
<div class="submit_time">
<%= syzoj.utils.formatTime(item.player.score_details[problem.id].acceptedTime - contest.start_time) %>
</div>
<% } else { %>
<span class="score score_0">
-<%= item.player.score_details[problem.id].unacceptedCount %>
</span>
<% } %>
</a>
</td>
<% } else if (contest.type === 'noi' || contest.type === 'ioi') { %>
<td>
<a href="<%= syzoj.utils.makeUrl(['submission', item.player.score_details[problem.id].judge_id]) %>">
<span class="score score_<%= parseInt((item.player.score_details[problem.id].score / 10) || 0) %>">
<%= item.player.score_details[problem.id].score %>
</span>
</a>
<div class="submit_time">
<%= syzoj.utils.formatTime(item.player.score_details[problem.id].judge_state.submit_time - contest.start_time) %>
<% latest = Math.max(latest, item.player.score_details[problem.id].judge_state.submit_time) %>
</div>
</td>
<% } %>
<% } %>
<% if (contest.type === 'noi' || contest.type === 'ioi') { %>
<td>
<span class="score score_<%= parseInt((item.player.score / ranklist[0].player.score * 10) || 0) %>">
<%= item.player.score %>
</span>
<div class="submit_time">
<%= syzoj.utils.formatTime(latest - contest.start_time) %>
</div>
</td>
<% } %>
<td>
<span class="score score_<%= parseInt((item.player.score / ranklist[0].player.score * 10) || 0) %>">
<%= item.player.score %>
</span>
<div class="submit_time">
<%= syzoj.utils.formatTime(latest - contest.start_time) %>
</div>
</td>
</tr>
<% } %>
</tbody>

2
views/contest_submissions.ejs

@ -7,7 +7,7 @@
<div class="field"><input name="problem_id" style="width: 50px; " type="text" value="<%= form.problem_id %>"></div>
<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>
<% if (contest.ended || (user && user.is_admin)) { %>
<% if (contest.ended || contest.type !== 'noi' || (user && user.is_admin)) { %>
<label style="font-size: 1.2em; margin-right: 3px; ">分数:</label>
<div class="field" style="padding-right: 6px; "><input name="min_score" style="width: 45px; " type="text" value="<%= form.min_score || 0 %>"></div>
<label style="font-size: 1.2em; margin-right: 7px; ">~</label>

3
views/header.ejs

@ -24,6 +24,9 @@
<a class="item<% if (active.startsWith('ranklist')) { %> active<% } %>" href="/ranklist"><i class="signal icon"></i> 排名</a>
<a class="item<% if (active.startsWith('discussion') || active.startsWith('article')) { %> active<% } %>" href="/discussion"><i class="comments icon"></i> 讨论</a>
<a class="item<% if (active.startsWith('help')) { %> active<% } %>" href="/help"><i class="help circle icon"></i> 帮助</a>
<% if (typeof contest !== 'undefined' && contest && contest.id) { %>
<a id="back_to_contest" class="item" href="<%= syzoj.utils.makeUrl(['contest', contest.id]) %>"><i class="arrow left icon"></i> 返回比赛</a>
<% } %>
<div class="right menu">
<% if (user) { %>
<a href="<%= syzoj.utils.makeUrl(['user', user.id]) %>" style="color: inherit; ">

58
views/submission_content.ejs

@ -126,37 +126,37 @@ else problemUrl = syzoj.utils.makeUrl(['problem', judge.problem_id]);
<div class="accordion" style="margin-top: 0; ">
<% } %>
<% for (let i = 0; i < subtask_cases.case_num; i++) { %>
<% let testcase = subtask_cases[i]; %>
<div class="title<% if (testcase.pending) { %> pending<% } %> auto_update"<% if (testcase.pending) { %> style="cursor: auto; "<% } %>>
<div class="ui grid">
<div class="three wide column"><i class="dropdown icon"></i>测试点 #<%= i + 1 %></div>
<div class="four wide column status status_detail <%= getStatusMeta(testcase.status).toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(testcase.status)] || 'remove' %> icon"></i>
<%= testcase.status %></div>
<% if (!testcase.pending) { %>
<% if (!testcase.score) testcase.score = testcase.status === 'Accepted' ? 100 : 0; %>
<div class="three wide column">得分:<span style="font-weight: normal; "><%= parseFloat(testcase.score.toFixed(2)).toString() %></span></div>
<div class="three wide column">用时:<span style="font-weight: normal; "><%= testcase.time_used %> ms</span></div>
<div class="three wide column">内存:<span style="font-weight: normal; "><%= testcase.memory_used %> KiB</span></div>
<% let testcase = subtask_cases[i]; %>
<div class="title<% if (testcase.pending || !judge.allowedSeeData) { %> pending<% } %> auto_update"<% if (testcase.pending || !judge.allowedSeeData) { %> style="cursor: auto; "<% } %>>
<div class="ui grid">
<div class="three wide column"><i class="dropdown icon"></i>测试点 #<%= i + 1 %></div>
<div class="four wide column status status_detail <%= getStatusMeta(testcase.status).toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(testcase.status)] || 'remove' %> icon"></i>
<%= testcase.status %></div>
<% if (!testcase.pending) { %>
<% if (!testcase.score) testcase.score = testcase.status === 'Accepted' ? 100 : 0; %>
<div class="three wide column">得分:<span style="font-weight: normal; "><%= parseFloat(testcase.score.toFixed(2)).toString() %></span></div>
<div class="three wide column">用时:<span style="font-weight: normal; "><%= testcase.time_used %> ms</span></div>
<div class="three wide column">内存:<span style="font-weight: normal; "><%= testcase.memory_used %> KiB</span></div>
<% } %>
</div>
</div>
<div class="content auto_update">
<% if (!testcase.pending && judge.allowedSeeData) { %>
<p>
<strong>输入文件</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.input %></code></pre></div>
<strong>期望输出</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.answer %></code></pre></div>
<strong>你的输出</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.user_out %></code></pre></div>
<% if (testcase.spj_message) { %>
<strong>Special Judge 信息</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.spj_message %></code></pre></div>
<% } %>
</p>
<% } %>
</div>
</div>
<div class="content auto_update">
<% if (!testcase.pending) { %>
<p>
<strong>输入文件</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.input %></code></pre></div>
<strong>期望输出</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.answer %></code></pre></div>
<strong>你的输出</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.user_out %></code></pre></div>
<% if (testcase.spj_message) { %>
<strong>Special Judge 信息</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.spj_message %></code></pre></div>
<% } %>
</p>
<% } %>
</div>
<% } %>
<% if (judge.result.subtasks.length !== 1) { %>
</div></div>

Loading…
Cancel
Save