Browse Source

Modified something about contest

pull/6/head
Menci 8 years ago
parent
commit
f870981d3c
  1. 2
      models/contest.js
  2. 3
      models/contest_player.js
  3. 27
      models/judge_state.js
  4. 21
      modules/contest.js
  5. 6
      modules/problem.js
  6. 24
      modules/submission.js
  7. 3
      static/style.css
  8. 6
      views/contest.ejs
  9. 2
      views/contest_ranklist.ejs
  10. 4
      views/contest_submissions.ejs
  11. 24
      views/submission_content.ejs
  12. 12
      views/submissions_item.ejs
  13. 1
      views/util.ejs

2
models/contest.js

@ -93,7 +93,7 @@ class Contest extends Model {
}
async isAllowedSeeResultBy(user) {
if (this.type === 'acm' || this.type === 'ioi') return true;
if (this.type === 'acm') return true;
return (user && (user.is_admin || this.holder_id === user.id)) || !(await this.isRunning());
}

3
models/contest_player.js

@ -131,6 +131,7 @@ class ContestPlayer extends Model {
this.score_details[judge_state.problem_id].submissions[judge_state.id] = {
judge_id: judge_state.id,
accepted: judge_state.status === 'Accepted',
compiled: judge_state.status !== 'Compile Error',
time: judge_state.submit_time
};
@ -145,7 +146,7 @@ class ContestPlayer extends Model {
this.score_details[judge_state.problem_id].acceptedTime = x.time;
this.score_details[judge_state.problem_id].judge_id = x.judge_id;
break;
} else {
} else if (x.compiled) {
this.score_details[judge_state.problem_id].unacceptedCount++;
}
}

27
models/judge_state.js

@ -99,26 +99,21 @@ class JudgeState extends Model {
if (this.problem_id) this.problem = await Problem.fromID(this.problem_id);
}
async isAllowedSeeResultBy(user) {
async isAllowedVisitBy(user) {
await this.loadRelationships();
if (user && user.id === this.problem.user_id) return true;
else if (this.type === 0) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
else if (this.type === 0 || this.type == 2) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
else if (this.type === 1) {
let contest = await Contest.fromID(this.type_info);
if (await contest.isRunning()) {
return (contest.type === 'acm' || contest.type === 'ioi') || (user && user.is_admin);
} else {
return true;
return user && (user.is_admin || user.id === this.user_id);
}
} else if (this.type === 2) return user && (await user.hasPrivilege('manage_problem'));
}
async isAllowedSeeCodeBy(user) {
await this.loadRelationships();
if (user && user.id === this.problem.user_id) return true;
else if (this.type === 0) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
else if (this.type === 0 || this.type === 2) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
else if (this.type === 1) {
let contest = await Contest.fromID(this.type_info);
if (await contest.isRunning()) {
@ -126,14 +121,14 @@ class JudgeState extends Model {
} else {
return true;
}
} else if (this.type === 2) return user && (await user.hasPrivilege('manage_problem'));
}
}
async isAllowedSeeCaseBy(user) {
await this.loadRelationships();
if (user && user.id === this.problem.user_id) return true;
else if (this.type === 0) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
else if (this.type === 0 || this.type === 2) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
else if (this.type === 1) {
let contest = await Contest.fromID(this.type_info);
if (await contest.isRunning()) {
@ -141,14 +136,14 @@ class JudgeState extends Model {
} else {
return true;
}
} else if (this.type === 2) return user && (await user.hasPrivilege('manage_problem'));
}
}
async isAllowedSeeDataBy(user) {
await this.loadRelationships();
if (user && user.id === this.problem.user_id) return true;
else if (this.type === 0) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
else if (this.type === 0 || this.type === 2) return this.problem.is_public || (user && (await user.hasPrivilege('manage_problem')));
else if (this.type === 1) {
let contest = await Contest.fromID(this.type_info);
if (await contest.isRunning()) {
@ -156,7 +151,7 @@ class JudgeState extends Model {
} else {
return true;
}
} else if (this.type === 2) return true;
}
}
async updateResult(result) {
@ -169,7 +164,7 @@ class JudgeState extends Model {
}
async updateRelatedInfo(newSubmission) {
if (this.type === 0) {
if (this.type === 0 || this.type === 2) {
if (newSubmission) {
await this.loadRelationships();
await this.user.refreshSubmitInfo();
@ -222,7 +217,7 @@ class JudgeState extends Model {
await this.user.save();
}
if (this.type === 0) {
if (this.type === 0 || this.type === 2) {
if (oldStatus === 'Accepted') {
this.problem.ac_num--;
await this.problem.save();

21
modules/contest.js

@ -138,17 +138,12 @@ app.get('/contest/:id', async (req, res) => {
for (let problem of problems) {
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;
if (!contest.ended && !await problem.problem.isAllowedEditBy(res.locals.user) && !['Compile Error', 'Waiting', 'Compiling'].includes(problem.status)) {
problem.status = 'Compiled';
}
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]) {
@ -215,8 +210,8 @@ app.get('/contest/:id/ranklist', async (req, res) => {
try {
let contest_id = parseInt(req.params.id);
let contest = await Contest.fromID(contest_id);
if (!contest) throw new ErrorMessage('无此比赛。');
if (!contest) throw new ErrorMessage('无此比赛。');
if (!await contest.isAllowedSeeResultBy(res.locals.user)) throw new ErrorMessage('您没有权限进行此操作。');
await contest.loadRelationships();
@ -260,6 +255,7 @@ app.get('/contest/:id/submissions', async (req, res) => {
let contest = await Contest.fromID(contest_id);
if (!contest) throw new ErrorMessage('无此比赛。');
if (!await contest.isAllowedSeeResultBy(res.locals.user)) throw new ErrorMessage('您没有权限进行此操作。');
contest.ended = await contest.isEnded();
@ -272,7 +268,7 @@ app.get('/contest/:id/submissions', async (req, res) => {
where.type = 1;
where.type_info = contest_id;
if (contest.ended || contest.type !== 'noi' || (res.locals.user && res.locals.user.is_admin)) {
if (contest.ended || (res.locals.user && res.locals.user.is_admin)) {
if (!((!res.locals.user || !res.locals.user.is_admin) && !contest.ended && contest.type === 'acm')) {
let minScore = parseInt(req.query.min_score);
if (isNaN(minScore)) minScore = 0;
@ -294,12 +290,17 @@ app.get('/contest/:id/submissions', async (req, res) => {
let paginate = syzoj.utils.paginate(await JudgeState.count(where), req.query.page, syzoj.config.page.judge_state);
let judge_state = await JudgeState.query(paginate, where, [['submit_time', 'desc']]);
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 => {
await obj.loadRelationships();
obj.problem_id = problems_id.indexOf(obj.problem_id) + 1;
obj.problem.title = syzoj.utils.removeTitleTag(obj.problem.title);
if (contest.type === 'noi' && !contest.ended && !await obj.problem.isAllowedEditBy(res.locals.user)) {
if (!['Compile Error', 'Waiting', 'Compiling'].includes(obj.status)) {
obj.status = 'Compiled';
}
}
});
res.render('contest_submissions', {

6
modules/problem.js

@ -557,8 +557,6 @@ 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;
@ -572,11 +570,7 @@ app.post('/problem/:id/submit', async (req, res) => {
await waiting_judge.save();
if (redirectToContest) {
res.redirect(syzoj.utils.makeUrl(['contest', contest_id]));
} else {
res.redirect(syzoj.utils.makeUrl(['submission', judge_state.id]));
}
} catch (e) {
syzoj.log(e);
res.render('error', {

24
modules/submission.js

@ -68,7 +68,6 @@ app.get('/submissions', async (req, res) => {
let judge_state = await JudgeState.query(paginate, where, [['submit_time', 'desc']]);
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));
@ -92,7 +91,6 @@ app.get('/submissions/:id/ajax', async (req, res) => {
await judge_state.loadRelationships();
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);
@ -102,6 +100,12 @@ app.get('/submissions/:id/ajax', async (req, res) => {
let problems_id = await contest.getProblems();
judge_state.problem_id = problems_id.indexOf(judge_state.problem_id) + 1;
judge_state.problem.title = syzoj.utils.removeTitleTag(judge_state.problem.title);
if (contest.type === 'noi' && !contest.ended && !await judge_state.problem.isAllowedEditBy(res.locals.user)) {
if (!['Compile Error', 'Waiting', 'Compiling'].includes(judge_state.status)) {
judge_state.status = 'Compiled';
}
}
}
res.render('submissions_item', {
@ -120,6 +124,7 @@ app.get('/submission/:id', async (req, res) => {
try {
let id = parseInt(req.params.id);
let judge = await JudgeState.fromID(id);
if (!judge || !await judge.isAllowedVisitBy(res.locals.user)) throw new ErrorMessage('您没有权限进行此操作。');
let contest;
if (judge.type === 1) contest = await Contest.fromID(judge.type_info);
@ -128,7 +133,6 @@ app.get('/submission/:id', async (req, res) => {
judge.codeLength = judge.code.length;
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.allowedSeeCase = await judge.isAllowedSeeCaseBy(res.locals.user);
judge.allowedSeeData = await judge.isAllowedSeeDataBy(res.locals.user);
@ -138,6 +142,12 @@ app.get('/submission/:id', async (req, res) => {
let problems_id = await contest.getProblems();
judge.problem_id = problems_id.indexOf(judge.problem_id) + 1;
judge.problem.title = syzoj.utils.removeTitleTag(judge.problem.title);
if (contest.type === 'noi' && !contest.ended && !await judge.problem.isAllowedEditBy(res.locals.user)) {
if (!['Compile Error', 'Waiting', 'Compiling'].includes(judge.status)) {
judge.status = 'Compiled';
}
}
}
res.render('submission', {
@ -156,6 +166,7 @@ app.get('/submission/:id/ajax', async (req, res) => {
try {
let id = parseInt(req.params.id);
let judge = await JudgeState.fromID(id);
if (!judge || !await judge.isAllowedVisitBy(res.locals.user)) throw new ErrorMessage('您没有权限进行此操作。');
let contest;
if (judge.type === 1) contest = await Contest.fromID(judge.type_info);
@ -164,7 +175,6 @@ app.get('/submission/:id/ajax', async (req, res) => {
judge.codeLength = judge.code.length;
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.allowedSeeCase = await judge.isAllowedSeeCaseBy(res.locals.user);
judge.allowedSeeData = await judge.isAllowedSeeDataBy(res.locals.user);
@ -174,6 +184,12 @@ app.get('/submission/:id/ajax', async (req, res) => {
let problems_id = await contest.getProblems();
judge.problem_id = problems_id.indexOf(judge.problem_id) + 1;
judge.problem.title = syzoj.utils.removeTitleTag(judge.problem.title);
if (contest.type === 'noi' && !contest.ended && !await judge.problem.isAllowedEditBy(res.locals.user)) {
if (!['Compile Error', 'Waiting', 'Compiling'].includes(judge.status)) {
judge.status = 'Compiled';
}
}
}
res.render('submission_content', {

3
static/style.css

@ -357,6 +357,9 @@ table.center.aligned ul, table.center.aligned ol {
}
*/
:not(.status_detail).status.compiled,
.title:hover .status_detail.status.compiled,
.title.active .status_detail.status.compiled,
:not(.status_detail).status.accepted,
.title:hover .status_detail.status.accepted,
.title.active .status_detail.status.accepted {

6
views/contest.ejs

@ -22,7 +22,7 @@
<div class="bar" style="width: <%= timePercentage %>%;"></div>
</div>
<div class="ui grid">
<% if (contest.allowedEdit || (unveiled && (!contest.running || contest.type !== 'noi'))) { %>
<% if (contest.allowedEdit || (unveiled && (!contest.running || contest.type === 'acm'))) { %>
<div class="row">
<div class="column">
<div class="ui buttons">
@ -66,9 +66,7 @@
<td class="center aligned" style="white-space: nowrap; ">
<% if (problem.judge_id) { %>
<a href="<%= syzoj.utils.makeUrl(['submission', problem.judge_id]) %>">
<% if (problem.status === true) { %>
<i class="black checkmark icon"></i>
<% } else if (typeof problem.status === 'string') { %>
<% if (typeof problem.status === 'string') { %>
<span class="status <%= problem.status.toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(problem.status)] || 'remove' %> icon"></i>
<%= problem.status %>

2
views/contest_ranklist.ejs

@ -87,7 +87,7 @@
<div class="submit_time">
<%= syzoj.utils.formatTime(item.player.score_details[problem.id].acceptedTime - contest.start_time) %>
</div>
<% } else { %>
<% } else if (item.player.score_details[problem.id].unacceptedCount) { %>
<span class="score score_0">
-<%= item.player.score_details[problem.id].unacceptedCount %>
</span>

4
views/contest_submissions.ejs

@ -10,7 +10,7 @@
<label style="font-size: 1.2em; margin-right: 1px; ">提交者:</label>
<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) || !((!user || !user.is_admin) && !contest.ended && contest.type === 'acm')) { %>
<% if ((typeof contest === 'undefined' || !contest) || !((!user || !user.is_admin) && !contest.ended && (contest.type === 'acm' || contest.type === 'noi'))) { %>
<label style="font-size: 1.2em; margin-right: 1px; ">分数:</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>
@ -71,7 +71,7 @@
<th>编号</th>
<th>题目</th>
<th>状态</th>
<% if ((typeof contest === 'undefined' || !contest) || !((!user || !user.is_admin) && !contest.ended && contest.type === 'acm')) { %>
<% if ((typeof contest === 'undefined' || !contest) || !((!user || !user.is_admin) && !contest.ended && (contest.type === 'acm' || contest.type === 'noi'))) { %>
<th>分数</th>
<% } %>
<th>总时间</th>

24
views/submission_content.ejs

@ -2,7 +2,7 @@
// Sanitize judge results for backward compatibility and clarity
if (!judge.result.subtasks) {
judge.result.subtasks = [
{ case_num: judge.result.case_num, status: judge.result.status, score: judge.result.score }
{ case_num: judge.result.case_num, status: judge.status, score: judge.result.score }
];
for (let i = 0; i < judge.result.case_num; ++i) {
judge.result.subtasks[0][i] = judge.result[i];
@ -35,7 +35,7 @@ else problemUrl = syzoj.utils.makeUrl(['problem', judge.problem_id]);
<th>编号</th>
<th>题目名称</th>
<th>状态</th>
<% if ((typeof contest === 'undefined' || !contest) || !((!user || !user.is_admin) && !contest.ended && contest.type === 'acm')) { %>
<% if ((typeof contest === 'undefined' || !contest) || !((!user || !user.is_admin) && !contest.ended && (contest.type === 'acm' || contest.type === 'noi'))) { %>
<th>分数</th>
<% } %>
<th>总时间</th>
@ -49,12 +49,11 @@ else problemUrl = syzoj.utils.makeUrl(['problem', judge.problem_id]);
<tr>
<td>#<%= judge.id %></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) { %>
<td class="status <%= getStatusMeta(judge.result.status).toLowerCase().split(' ').join('_') %>">
<td class="status <%= getStatusMeta(judge.status).toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(judge.status)] || 'remove' %> icon"></i>
<%= judge.result.status %>
<%= judge.status %>
</td>
<% if ((typeof contest === 'undefined' || !contest) || !((!user || !user.is_admin) && !contest.ended && contest.type === 'acm')) { %>
<% if ((typeof contest === 'undefined' || !contest) || !((!user || !user.is_admin) && !contest.ended && (contest.type === 'acm' || contest.type === 'noi'))) { %>
<td class="score score_<%= parseInt(judge.result.score / 10) || 0 %>"><%= judge.result.score %></td>
<% } %>
<td><%= judge.result.total_time %> ms</td>
@ -64,13 +63,6 @@ else problemUrl = syzoj.utils.makeUrl(['problem', judge.problem_id]);
<% } else { %>
<td><%= syzoj.config.languages[judge.language].show %> / 隐藏 %></td>
<% } %>
<% } else { %>
<td>隐藏</td>
<td>隐藏</td>
<td>隐藏</td>
<td>隐藏</td>
<td>隐藏</td>
<% } %>
<td><a href="<%= syzoj.utils.makeUrl(['user', judge.user_id]) %>"><%= judge.user.username %></a><% if (judge.user.nameplate) { %><%- judge.user.nameplate %><% } %></td>
<td><%= syzoj.utils.formatDate(judge.submit_time) %></td>
</tr>
@ -104,13 +96,13 @@ else problemUrl = syzoj.utils.makeUrl(['problem', judge.problem_id]);
});
</script>
<% } %>
<% if (judge.result.compiler_output && judge.result.status === 'Compile Error' && judge.allowedSeeCode) { %>
<% if (judge.result.compiler_output && judge.status === 'Compile Error' && judge.allowedSeeCode) { %>
<h3 class="ui header">编译信息</h3>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%- syzoj.utils.ansiToHTML(judge.result.compiler_output) %></code></pre></div>
<% } else if (judge.result.spj_compiler_output) { %>
<h3 class="ui header">Special Judge 编译信息</h3>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%- syzoj.utils.ansiToHTML(judge.result.spj_compiler_output) %></code></pre></div>
<% } else if (judge.allowedSeeResult && judge.allowedSeeCase && judge.result.subtasks && (judge.result.subtasks.length !== 1 || judge.result.subtasks[0].case_num)) { %>
<% } else if (judge.allowedSeeCase && judge.result.subtasks && (judge.result.subtasks.length !== 1 || judge.result.subtasks[0].case_num)) { %>
<div class="ui styled fluid accordion" id="subtasks_list">
<% let subtask_count = 0; %>
<% for (let subtask_cases of (judge.result.subtasks || [])) { %>
@ -186,7 +178,7 @@ $(function() {
<% if (!isPending(judge.status)) { %><div><div id="stop_ajax"></div><div id="show_rejudge"></div></div><% } %>
<script>
<% if (isPending(judge.status) && judge.allowedSeeResult) { %>
<% if (isPending(judge.status)) { %>
document.addEventListener('mousedown', function (event) {
var list = $('#submission_content').find('div.auto_update_activation');
for (var i = 0; i < list.length; ++i) {

12
views/submissions_item.ejs

@ -10,14 +10,13 @@ else problemUrl = syzoj.utils.makeUrl(['problem', judge.problem_id]);
var e = document.getElementById('text-fit-<%= judge.id %>');
textFit(e, { maxFontSize: 14 });
</script>
<% if (!judge.hidden) { %>
<td><a href="<%= syzoj.utils.makeUrl(['submission', judge.id]) %>">
<span class="status <%= getStatusMeta(judge.status).toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(judge.status)] || 'remove' %> icon"></i>
<%= judge.status %>
</span>
</a></td>
<% if ((typeof contest === 'undefined' || !contest) || !((!user || !user.is_admin) && !contest.ended && contest.type === 'acm')) { %>
<% if ((typeof contest === 'undefined' || !contest) || !((!user || !user.is_admin) && !contest.ended && (contest.type === 'acm' || contest.type === 'noi'))) { %>
<td><a href="<%= syzoj.utils.makeUrl(['submission', judge.id]) %>"><span class="score score_<%= parseInt(judge.result.score / 10) || 0 %>"><%= judge.result.score %></span></a></td>
<% } %>
<td><%= judge.result.total_time %> ms</td>
@ -27,15 +26,6 @@ textFit(e, { maxFontSize: 14 });
<% } else { %>
<td><a href="<%= syzoj.utils.makeUrl(['submission', judge.id]) %>"><%= syzoj.config.languages[judge.language].show %></a> / 隐藏</td>
<% } %>
<% } else { %>
<td>隐藏</td>
<% if ((typeof contest === 'undefined' || !contest) || !((!user || !user.is_admin) && !contest.ended && contest.type === 'acm')) { %>
<td>隐藏</td>
<% } %>
<td>隐藏</td>
<td>隐藏</td>
<td>隐藏</td>
<% } %>
<td><a href="<%= syzoj.utils.makeUrl(['user', judge.user_id]) %>"><%= judge.user.username %></a><% if (judge.user.nameplate) { %><%- judge.user.nameplate %><% } %></td>
<td><%= syzoj.utils.formatDate(judge.submit_time) %>
<% if (isPending(judge.status)) { %>

1
views/util.ejs

@ -29,6 +29,7 @@ this.icon = {
'Running': 'spinner',
'Compiling': 'spinner',
'Compile Error': 'code',
'Compiled': 'checkmark',
'System Error': 'server',
'No Testdata': 'folder open outline',
'Partially Correct': 'minus',

Loading…
Cancel
Save