diff --git a/models/contest.js b/models/contest.js index 3309dc1..e59eb01 100644 --- a/models/contest.js +++ b/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()); } diff --git a/models/contest_player.js b/models/contest_player.js index 3999b36..c64659a 100644 --- a/models/contest_player.js +++ b/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++; } } diff --git a/models/judge_state.js b/models/judge_state.js index 5e1b123..28f6cc1 100644 --- a/models/judge_state.js +++ b/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; - } - } else if (this.type === 2) return user && (await user.hasPrivilege('manage_problem')); + return user && (user.is_admin || user.id === this.user_id); + } } 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(); diff --git a/modules/contest.js b/modules/contest.js index cf24d52..1454fcf 100644 --- a/modules/contest.js +++ b/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; + 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', { diff --git a/modules/problem.js b/modules/problem.js index b823406..7144b30 100644 --- a/modules/problem.js +++ b/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])); - } + res.redirect(syzoj.utils.makeUrl(['submission', judge_state.id])); } catch (e) { syzoj.log(e); res.render('error', { diff --git a/modules/submission.js b/modules/submission.js index 3499a15..ffb1bea 100644 --- a/modules/submission.js +++ b/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', { diff --git a/static/style.css b/static/style.css index 2280ab0..944b0c5 100644 --- a/static/style.css +++ b/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 { diff --git a/views/contest.ejs b/views/contest.ejs index 3360235..303acdd 100644 --- a/views/contest.ejs +++ b/views/contest.ejs @@ -22,7 +22,7 @@