mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
修复参加比赛的错误
This commit is contained in:
1 parent
32ad47e031
commit
f40e4e2c74
10 files changed
+62
-38
No files matched your search
+7
-7
@@ -92,6 +92,12 @@ class ContestNotAttendedError extends ForbiddenError {
|
||||
this.params = [tid];
|
||||
}
|
||||
}
|
||||
class ContestAlreadyAttendedError extends ForbiddenError {
|
||||
constructor(tid, uid) {
|
||||
super('You\'ve already attended this contest.');
|
||||
this.params = [tid, uid];
|
||||
}
|
||||
}
|
||||
class ContestNotLiveError extends ForbiddenError {
|
||||
constructor(tid) {
|
||||
super('This contest is not live.');
|
||||
@@ -148,7 +154,7 @@ module.exports = {
|
||||
ValidationError, ProblemNotFoundError, TrainingNotFoundError,
|
||||
ContestNotFoundError, RecordNotFoundError, SolutionNotFoundError,
|
||||
AlreadyVotedError, ContestNotAttendedError, ContestNotLiveError,
|
||||
ContestScoreboardHiddenError
|
||||
ContestScoreboardHiddenError, ContestAlreadyAttendedError
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -278,12 +284,6 @@ class InvalidJoinInvitationCodeError(ForbiddenError):
|
||||
return 'The invitation code you provided is invalid.'
|
||||
|
||||
|
||||
class ContestAlreadyAttendedError(ForbiddenError):
|
||||
@property
|
||||
def message(self):
|
||||
return "You've already attended this contest."
|
||||
|
||||
|
||||
class HomeworkScoreboardHiddenError(ForbiddenError):
|
||||
@property
|
||||
def message(self):
|
||||
|
||||
+11
-10
@@ -14,10 +14,10 @@ const
|
||||
|
||||
class ContestHandler extends Handler {
|
||||
canViewHiddenScoreboard() {
|
||||
return this.hasPerm(PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
|
||||
return this.user.hasPerm(PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
|
||||
}
|
||||
canShowRecord(tdoc, allowPermOverride = true) {
|
||||
if (contest.RULES[tdoc.rule].showRecordFunc(tdoc, new Date())) return true;
|
||||
if (contest.RULES[tdoc.rule].showRecord(tdoc, new Date())) return true;
|
||||
if (allowPermOverride && this.canViewHiddenScoreboard(tdoc)) return true;
|
||||
return false;
|
||||
}
|
||||
@@ -27,14 +27,15 @@ class ContestHandler extends Handler {
|
||||
return false;
|
||||
}
|
||||
async getScoreboard(tid, isExport = false) {
|
||||
let [tdoc, tsdocs] = await contest.getAndListStatus(tid);
|
||||
let tdoc = await contest.get(tid);
|
||||
if (!this.canShowScoreboard(tdoc)) throw new ContestScoreboardHiddenError(tid);
|
||||
let tsdocs = await contest.getMultiStatus(tid).sort(contest.RULES[tdoc.rule].statusSort).toArray();
|
||||
let uids = [];
|
||||
for (let tsdoc of tsdocs) uids.push(tsdoc.uid);
|
||||
let [udict, pdict] = await Promise.all([user.getList(uids), problem.getList(tdoc['pids'])]);
|
||||
let ranked_tsdocs = contest.RULES[tdoc.rule].rank(tsdocs);
|
||||
let rows = contest.RULES[tdoc.rule].scoreboard(isExport, this.translate, tdoc, ranked_tsdocs, udict, pdict);
|
||||
return tdoc, rows, udict;
|
||||
let rows = contest.RULES[tdoc.rule].scoreboard(isExport, str => str ? str.toString().translate(this.user.language) : '', tdoc, ranked_tsdocs, udict, pdict);
|
||||
return [tdoc, rows, udict];
|
||||
}
|
||||
async verifyProblems(pids) {
|
||||
console.log(pids);
|
||||
@@ -61,17 +62,17 @@ class ContestListHandler extends ContestHandler {
|
||||
this.response.template = 'contest_main.html';
|
||||
let tdocs, qs, tpcount;
|
||||
if (!rule) {
|
||||
tdocs = contest.getMulti();
|
||||
tdocs = contest.getMulti().sort({ beginAt: -1 });
|
||||
qs = '';
|
||||
} else {
|
||||
if (!contest.CONTEST_RULES.includes(rule)) throw new ValidationError('rule');
|
||||
tdocs = contest.getMulti({ rule });
|
||||
tdocs = contest.getMulti({ rule }).sort({ beginAt: -1 });
|
||||
qs = 'rule={0}'.format(rule);
|
||||
}
|
||||
[tdocs, tpcount] = await paginate(tdocs, page, constants.CONTEST_PER_PAGE);
|
||||
let tids = [];
|
||||
for (let tdoc of tdocs) tids.push(tdoc._id);
|
||||
let tsdict = await contest.getListStatus(this.uid, tids);
|
||||
let tsdict = await contest.getListStatus(this.user._id, tids);
|
||||
this.response.body = {
|
||||
page, tpcount, qs, rule, tdocs, tsdict
|
||||
};
|
||||
@@ -84,7 +85,7 @@ class ContestDetailHandler extends ContestHandler {
|
||||
async get({ page = 1 }) {
|
||||
this.response.template = 'contest_detail.html';
|
||||
let [tsdoc, pdict] = await Promise.all([
|
||||
contest.getStatus(this.tdoc._id, this.uid),
|
||||
contest.getStatus(this.tdoc._id, this.user._id),
|
||||
problem.getList(this.tdoc.pids)
|
||||
]);
|
||||
let psdict = {}, rdict = {}, attended;
|
||||
@@ -111,7 +112,7 @@ class ContestDetailHandler extends ContestHandler {
|
||||
}
|
||||
async post_attend() {
|
||||
if (contest.is_done(this.tdoc)) throw new ContestNotLiveError(this.tdoc._id);
|
||||
await contest.attend(this.tdoc._id, this.uid);
|
||||
await contest.attend(this.tdoc._id, this.user._id);
|
||||
this.back();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ exports.datetime_span = function (dt, relative = true, format = '%Y-%m-%d %H:%M:
|
||||
dt.format(format)
|
||||
);
|
||||
};
|
||||
exports.nl2br = function (self) {
|
||||
return self.replace(/\n/gm, '<br>');
|
||||
};
|
||||
exports.paginate = function* (page, num_pages) {
|
||||
let radius = 2, first, last;
|
||||
if (page > 1) {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
module.exports = function* ranked(diter, equ = (a, b) => a == b) {
|
||||
let last_doc = null;
|
||||
let r = 0, count = 0;
|
||||
for (let doc of diter) {
|
||||
count++;
|
||||
if (count == 1 || !equ(last_doc, doc))
|
||||
r = count;
|
||||
last_doc = doc;
|
||||
yield [r, doc];
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
const
|
||||
validator = require('../lib/validator'),
|
||||
{ ValidationError, ContestNotFoundError } = require('../error'),
|
||||
{ ValidationError, ContestNotFoundError, ContestAlreadyAttendedError } = require('../error'),
|
||||
db = require('../service/db.js'),
|
||||
coll = db.collection('contest'),
|
||||
coll_status = db.collection('contest.status');
|
||||
@@ -56,7 +56,7 @@ async function getListStatus(uid, tids) {
|
||||
}
|
||||
async function attend(tid, uid) {
|
||||
try {
|
||||
await coll_status.insertOne({ tid, uid });
|
||||
await coll_status.insertOne({ tid, uid, attend: 1 });
|
||||
} catch (e) {
|
||||
throw new ContestAlreadyAttendedError(tid, uid);
|
||||
}
|
||||
@@ -70,10 +70,10 @@ function is_new(tdoc, days = 1) {
|
||||
function is_upcoming(tdoc, days = 1) {
|
||||
let now = new Date().getTime();
|
||||
let readyAt = tdoc.beginAt.getTime();
|
||||
return (now > readyAt + days * 24 * 3600 * 1000 && now < tdoc.beginAt);
|
||||
return (now > readyAt - days * 24 * 3600 * 1000 && now < tdoc.beginAt);
|
||||
}
|
||||
function is_not_started(tdoc) {
|
||||
return new Date() < tdoc.beginAt;
|
||||
return (new Date()) < tdoc.beginAt;
|
||||
}
|
||||
function is_ongoing(tdoc) {
|
||||
let now = new Date();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
module.exports = {
|
||||
TEXT: 'ACM/ICPC',
|
||||
check: () => { },
|
||||
showScoreboard: () => true,
|
||||
showRecord: (tdoc, now) => now > tdoc.endAt,
|
||||
stat: (tdoc, journal) => {
|
||||
let naccept = {}, effective = {}, detail = [], accept = 0, time = 0;
|
||||
for (let j in journal) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
const ranked = require('../../lib/rank');
|
||||
|
||||
module.exports = {
|
||||
TEXT: 'OI',
|
||||
check: () => { },
|
||||
@@ -10,10 +12,13 @@ module.exports = {
|
||||
}
|
||||
return { score, detail };
|
||||
},
|
||||
showScoreboard(tdoc,now){
|
||||
return now>tdoc.endAt;
|
||||
showScoreboard(tdoc, now) {
|
||||
return now > tdoc.endAt;
|
||||
},
|
||||
scoreboard(is_export, _, tdoc, ranked_tsdocs, udict, dudict, pdict) {
|
||||
showRecord(tdoc, now) {
|
||||
return now > tdoc.endAt;
|
||||
},
|
||||
scoreboard(is_export, _, tdoc, ranked_tsdocs, udict, pdict) {
|
||||
let columns = [
|
||||
{ type: 'rank', value: _('Rank') },
|
||||
{ type: 'user', value: _('User') },
|
||||
@@ -49,5 +54,6 @@ module.exports = {
|
||||
rows.push(row);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
},
|
||||
rank: tdocs => ranked(tdocs, (a, b) => a.score == b.score)
|
||||
};
|
||||
@@ -252,7 +252,7 @@ class ConnectionHandler {
|
||||
return new Promise((resolve, reject) => {
|
||||
template.render(name, Object.assign(context, {
|
||||
handler: this,
|
||||
_: this.translate,
|
||||
_: str => str ? str.toString().translate(this.user.language) : '',
|
||||
user: this.user
|
||||
}), (error, res) => {
|
||||
console.timeEnd(name);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{% set page_name = "contest_scoreboard" %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row"><div class="medium-12 columns">
|
||||
@@ -21,25 +22,25 @@
|
||||
<tr>
|
||||
{%- for column in rows[0] -%}
|
||||
<th class="col--{{ column['type'] }}">
|
||||
{% if column['type'] == 'problem_detail' %}
|
||||
<a href="{{ reverse_url('contest_detail_problem' if tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST else 'homework_detail_problem', tid=tdoc['doc_id'], pid=column['raw']['doc_id']) }}" data-tooltip="{{ column['raw']['title'] }}">{{ column['value'] }}</a>
|
||||
{% if column.type == 'problem_detail' %}
|
||||
<a href="{{ reverse_url('contest_detail_problem' , tid=tdoc._id, pid=column.raw._id) }}" data-tooltip="{{ column['raw']['title'] }}">{{ column['value'] }}</a>
|
||||
{% else %}
|
||||
{{ column['value'] }}
|
||||
{{ column.value }}
|
||||
{% endif %}
|
||||
</th>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for row in rows[1:] -%}
|
||||
{%- for i, row in rows -%}{% if i>0 %}
|
||||
<tr>
|
||||
{%- for column in row -%}
|
||||
<td class="col--{{ rows[0][loop.index0]['type'] }}">
|
||||
{% if column['type'] == 'user' %}
|
||||
{{ user.render_inline(column['raw'], badge=false) }}
|
||||
{% elif column['type'] == 'record' %}
|
||||
{% if column['raw'] %}
|
||||
<a href="{{ reverse_url('record_detail', rid=column['raw']) }}">{{ column['value']|nl2br }}</a>
|
||||
{% if column.type == 'user' %}
|
||||
{{ user.render_inline(column.raw, badge=false) }}
|
||||
{% elif column.type == 'record' %}
|
||||
{% if column.raw %}
|
||||
<a href="/r/{{ column.raw }}">{{ column.value|nl2br }}</a>
|
||||
{% else %}
|
||||
{{ column['value']|nl2br }}
|
||||
{% endif %}
|
||||
@@ -49,7 +50,7 @@
|
||||
</td>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
{% endif %}{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -43,11 +43,11 @@
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if handler.can_show_scoreboard(tdoc, False) %}
|
||||
{% if handler.canShowScoreboard(tdoc, False) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('homework_scoreboard', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-statistics"></span> {{ _('Scoreboard') }}
|
||||
</a></li>
|
||||
{% elif handler.can_view_hidden_scoreboard(tdoc) %}
|
||||
{% elif handler.canViewHiddenScoreboard(tdoc) %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('homework_scoreboard', tid=tdoc['doc_id']) }}">
|
||||
<span class="icon icon-statistics"></span> {{ _('Scoreboard (Hidden)') }}
|
||||
</a></li>
|
||||
|
||||
Reference in new issue
Block a user