mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
Contest rule: ACM/ICPC
This commit is contained in:
1 parent
d1ec9064fc
commit
e06283c0cc
43 files changed
+158
-891
No files matched your search
+31
-24
@@ -4,36 +4,42 @@ module.exports = {
|
||||
showScoreboard: () => true,
|
||||
showRecord: (tdoc, now) => now > tdoc.endAt,
|
||||
stat: (tdoc, journal) => {
|
||||
const naccept = {}; const effective = {}; const detail = []; let accept = 0; let time = 0;
|
||||
const naccept = {};
|
||||
const effective = {};
|
||||
const detail = [];
|
||||
let accept = 0;
|
||||
let time = 0;
|
||||
for (const j in journal) {
|
||||
if (tdoc.pids.includes(j.pid) && !(effective.includes(j.pid) && effective[j.pid].accept)) { effective[j.pid] = j; }
|
||||
if (!j.accept) { naccept[j.pid]++; }
|
||||
if (tdoc.pids.includes(j.pid)
|
||||
&& !(effective.includes(j.pid) && effective[j.pid].accept)) {
|
||||
effective[j.pid] = j;
|
||||
}
|
||||
if (!j.accept) naccept[j.pid]++;
|
||||
}
|
||||
function _time(jdoc) {
|
||||
const real = jdoc.rid.generationTime - Math.floor(tdoc.begin_at / 1000);
|
||||
const penalty = 20 * 60 * naccept[jdoc.pid];
|
||||
return real + penalty;
|
||||
}
|
||||
for (const j of effective) { detail.push({ ...j, naccept: naccept[j.pid], time: _time(j) }); }
|
||||
for (const j of effective) detail.push({ ...j, naccept: naccept[j.pid], time: _time(j) });
|
||||
for (const d of detail) {
|
||||
accept += d.accept;
|
||||
if (d.accept) time += d.time;
|
||||
}
|
||||
return { accept, time, detail };
|
||||
},
|
||||
scoreboard(is_export, _, tdoc, ranked_tsdocs, udict, dudict, pdict) {
|
||||
scoreboard(isExport, _, tdoc, rankedTsdocs, udict, pdict) {
|
||||
const columns = [
|
||||
{ type: 'rank', value: _('Rank') },
|
||||
{ type: 'user', value: _('User') },
|
||||
{ type: 'display_name', value: _('Display Name') },
|
||||
{ type: 'solved_problems', value: _('Solved Problems') },
|
||||
];
|
||||
if (is_export) {
|
||||
if (isExport) {
|
||||
columns.push({ type: 'total_time', value: _('Total Time (Seconds)') });
|
||||
columns.push({ type: 'total_time_str', value: _('Total Time') });
|
||||
}
|
||||
for (const i in tdoc.pids) {
|
||||
if (is_export) {
|
||||
if (isExport) {
|
||||
columns.push({
|
||||
type: 'problem_flag',
|
||||
value: '#{0} {1}'.format(i + 1, pdict[tdoc.pids[i]].title),
|
||||
@@ -55,44 +61,45 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
const rows = [columns];
|
||||
for (const [rank, tsdoc] of ranked_tsdocs) {
|
||||
for (const [rank, tsdoc] of rankedTsdocs) {
|
||||
const tsddict = {};
|
||||
if (tdoc.detail) { for (const item of tsdoc.detail) tsddict[item.pid] = item; }
|
||||
const row = [];
|
||||
row.push(
|
||||
{ type: 'string', value: rank },
|
||||
{ type: 'user', value: udict[tsdoc.uid].uname, raw: udict[tsdoc.uid] },
|
||||
{ type: 'display_name', value: (dudict[tsdoc.uid] || {}).display_name || '' },
|
||||
{ type: 'string', value: tsdoc.accept || 0 },
|
||||
);
|
||||
if (is_export) {
|
||||
if (isExport) {
|
||||
row.push(
|
||||
{ type: 'string', value: tsdoc.time || 0.0 },
|
||||
{ type: 'string', value: tsdoc.time || 0.0 },
|
||||
);
|
||||
}
|
||||
for (const pid of tdoc.pids) {
|
||||
let rdoc; let col_accepted; let col_time; let
|
||||
col_time_str;
|
||||
let rdoc;
|
||||
let colAccepted;
|
||||
let colTime;
|
||||
let colTimeStr;
|
||||
if ((tsddict[pid] || {}).accept) {
|
||||
rdoc = tsddict[pid].rid;
|
||||
col_accepted = _('Accepted');
|
||||
col_time = tsddict[pid].time;
|
||||
col_time_str = col_time;
|
||||
colAccepted = _('Accepted');
|
||||
colTime = tsddict[pid].time;
|
||||
colTimeStr = colTime;
|
||||
} else {
|
||||
rdoc = null;
|
||||
col_accepted = '-';
|
||||
col_time = '-';
|
||||
col_time_str = '-';
|
||||
colAccepted = '-';
|
||||
colTime = '-';
|
||||
colTimeStr = '-';
|
||||
}
|
||||
if (is_export) {
|
||||
row.push({ type: 'string', value: col_accepted });
|
||||
row.push({ type: 'string', value: col_time });
|
||||
row.push({ type: 'string', value: col_time_str });
|
||||
if (isExport) {
|
||||
row.push({ type: 'string', value: colAccepted });
|
||||
row.push({ type: 'string', value: colTime });
|
||||
row.push({ type: 'string', value: colTimeStr });
|
||||
} else {
|
||||
row.push({
|
||||
type: 'record',
|
||||
value: '{0}\n{1}'.format(col_accepted, col_time_str),
|
||||
value: '{0}\n{1}'.format(colAccepted, colTimeStr),
|
||||
raw: rdoc,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,45 +1,40 @@
|
||||
const { ValidationError } = require('../../error');
|
||||
|
||||
module.exports = {
|
||||
TEXT: 'Assignment',
|
||||
check(data) {
|
||||
if (!data.penalty_since) throw new ValidationError('penalty_since');
|
||||
if (data.penalty_since < data.begin_at) throw new ValidationError('penalty_since', 'begin_at');
|
||||
if (data.penalty_since > data.end_at) throw new ValidationError('penalty_since', 'end_at');
|
||||
},
|
||||
check() {},
|
||||
stat(tdoc, journal) {
|
||||
const effective = {};
|
||||
const detail = [];
|
||||
let score = 0;
|
||||
let penalty_score = 0;
|
||||
let time = 0;
|
||||
for (const j in journal) { if (tdoc.pids.includes(j.pid) && !(effective.includes(j.pid) && effective[j.pid].accept)) effective[j.pid] = j; }
|
||||
const _time = (jdoc) => jdoc.rid.generationTime - Math.floor(tdoc.begin_at / 1000);
|
||||
function _penalty_score(jdoc) {
|
||||
const exceed_seconds = jdoc.rid.generationTime - Math.floor(tdoc.penalty_since / 1000);
|
||||
if (exceed_seconds < 0) return jdoc.score;
|
||||
return 0.5 * jdoc.score;
|
||||
for (const j in journal) {
|
||||
if (tdoc.pids.includes(j.pid)
|
||||
&& !(effective.includes(j.pid) && effective[j.pid].accept)) {
|
||||
effective[j.pid] = j;
|
||||
}
|
||||
}
|
||||
const _time = (jdoc) => jdoc.rid.generationTime - Math.floor(tdoc.beginAt / 1000);
|
||||
for (const j in effective) {
|
||||
detail.push({ ...effective[j], penalty_score: _penalty_score(effective[j]), time: _time(effective[j]) });
|
||||
detail.push({
|
||||
...effective[j],
|
||||
time: _time(effective[j]),
|
||||
});
|
||||
}
|
||||
for (const d of detail) {
|
||||
score += d.score;
|
||||
penalty_score += d.penalty_score;
|
||||
time += d.time;
|
||||
}
|
||||
return {
|
||||
score, penalty_score, time, detail,
|
||||
score, time, detail,
|
||||
};
|
||||
},
|
||||
scoreboard(is_export, _, tdoc, ranked_tsdocs, udict, dudict, pdict) {
|
||||
scoreboard(isExport, _, tdoc, rankedTsdocs, udict, pdict) {
|
||||
const columns = [
|
||||
{ type: 'rank', value: _('Rank') },
|
||||
{ type: 'user', value: _('User') },
|
||||
{ type: 'display_name', value: _('Display Name') },
|
||||
{ type: 'total_score', value: _('Score') },
|
||||
];
|
||||
if (is_export) {
|
||||
if (isExport) {
|
||||
columns.push(
|
||||
{ type: 'total_original_score', value: _('Original Score') },
|
||||
{ type: 'total_time', value: _('Total Time (Seconds)') },
|
||||
@@ -47,7 +42,7 @@ module.exports = {
|
||||
}
|
||||
columns.push({ type: 'total_time_str', value: _('Total Time') });
|
||||
for (const i in tdoc.pids) {
|
||||
if (is_export) {
|
||||
if (isExport) {
|
||||
columns.push(
|
||||
{ type: 'problem_score', value: '#{0} {1}'.format(i + 1, pdict[tdoc.pids[i]].title) },
|
||||
{ type: 'problem_original_score', value: '#{0} {1}'.format(i + 1, _('Original Score')) },
|
||||
@@ -57,16 +52,15 @@ module.exports = {
|
||||
} else columns.push({ type: 'problem_detail', value: '#{0}'.format(i + 1), raw: pdict[tdoc.pids[i]] });
|
||||
}
|
||||
const rows = [columns];
|
||||
for (const [rank, tsdoc] in ranked_tsdocs) {
|
||||
for (const [rank, tsdoc] in rankedTsdocs) {
|
||||
const tsddict = {};
|
||||
if (tsdoc.detail) { for (const item of tsdoc.detail) tsddict[item.pid] = item; }
|
||||
const row = [
|
||||
{ type: 'string', value: rank },
|
||||
{ type: 'user', value: udict[tsdoc.uid].uname, raw: udict[tsdoc.uid] },
|
||||
{ type: 'display_name', value: (dudict[tsdoc.uid] || {}).display_name || '' },
|
||||
{ type: 'string', value: tsdoc.penalty_score || 0 },
|
||||
];
|
||||
if (is_export) {
|
||||
if (isExport) {
|
||||
row.push(
|
||||
{ type: 'string', value: tsdoc.score || 0 },
|
||||
{ type: 'string', value: tsdoc.time || 0.0 },
|
||||
@@ -75,21 +69,21 @@ module.exports = {
|
||||
row.push({ type: 'string', value: tsdoc.time || 0 });
|
||||
for (const pid of tdoc.pids) {
|
||||
const rdoc = (tsddict[pid] || {}).rid || null;
|
||||
const col_score = (tsddict[pid] || {}).penalty_score || '-';
|
||||
const col_original_score = (tsddict[pid] || {}).score || '-';
|
||||
const col_time = (tsddict[pid] || {}).time || '-';
|
||||
const col_time_str = col_time != '-' ? col_time : '-';
|
||||
if (is_export) {
|
||||
const colScore = (tsddict[pid] || {}).penalty_score || '-';
|
||||
const colOriginalScore = (tsddict[pid] || {}).score || '-';
|
||||
const colTime = (tsddict[pid] || {}).time || '-';
|
||||
const colTimeStr = colTime !== '-' ? colTime : '-';
|
||||
if (isExport) {
|
||||
row.push(
|
||||
{ type: 'string', value: col_score },
|
||||
{ type: 'string', value: col_original_score },
|
||||
{ type: 'string', value: col_time },
|
||||
{ type: 'string', value: col_time_str },
|
||||
{ type: 'string', value: colScore },
|
||||
{ type: 'string', value: colOriginalScore },
|
||||
{ type: 'string', value: colTime },
|
||||
{ type: 'string', value: colTimeStr },
|
||||
);
|
||||
} else {
|
||||
row.push({
|
||||
type: 'record',
|
||||
value: '{0} / {1}\n{2}'.format(col_score, col_original_score, col_time_str),
|
||||
value: '{0} / {1}\n{2}'.format(colScore, colOriginalScore, colTimeStr),
|
||||
raw: rdoc,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user