mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: contest(OI): 订正模式
This commit is contained in:
1 parent
e70beab967
commit
15827eeabb
7 files changed
+65
-31
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.26.14",
|
"version": "2.26.15",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "dist/loader.js",
|
"main": "dist/loader.js",
|
||||||
"typings": "dist/loader.d.ts",
|
"typings": "dist/loader.d.ts",
|
||||||
|
|||||||
@@ -269,9 +269,10 @@ export interface RecordDoc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ScoreboardNode {
|
export interface ScoreboardNode {
|
||||||
type: string,
|
type: string;
|
||||||
value: string,
|
value: string;
|
||||||
raw?: any,
|
raw?: any;
|
||||||
|
score?: number;
|
||||||
}
|
}
|
||||||
export type ScoreboardRow = ScoreboardNode[] & { raw?: any };
|
export type ScoreboardRow = ScoreboardNode[] & { raw?: any };
|
||||||
|
|
||||||
|
|||||||
@@ -110,21 +110,10 @@ const acm: ContestRule = {
|
|||||||
}
|
}
|
||||||
for (const pid of tdoc.pids) {
|
for (const pid of tdoc.pids) {
|
||||||
const doc = tsddict[pid] || {};
|
const doc = tsddict[pid] || {};
|
||||||
let rid;
|
const rid = doc.accept ? doc.rid : null;
|
||||||
let colAccepted;
|
const colAccepted = `${doc.accept ? `${_('Accepted')} ` : ''}${doc.naccept ? ` (-${doc.naccept})` : ''}`;
|
||||||
let colTime;
|
const colTime = doc.accept ? doc.time : '-';
|
||||||
let colTimeStr;
|
const colTimeStr = doc.accept ? misc.formatSeconds(colTime) : '-';
|
||||||
if (doc.accept) {
|
|
||||||
rid = doc.rid;
|
|
||||||
colAccepted = `${_('Accepted')} ${doc.naccept ? ` (-${doc.naccept})` : ''}`;
|
|
||||||
colTime = doc.time;
|
|
||||||
colTimeStr = misc.formatSeconds(colTime);
|
|
||||||
} else {
|
|
||||||
rid = null;
|
|
||||||
colAccepted = doc.naccept ? `(-${doc.naccept})` : '-';
|
|
||||||
colTime = '-';
|
|
||||||
colTimeStr = '';
|
|
||||||
}
|
|
||||||
if (isExport) {
|
if (isExport) {
|
||||||
row.push({ type: 'string', value: colAccepted });
|
row.push({ type: 'string', value: colAccepted });
|
||||||
row.push({ type: 'string', value: colTime });
|
row.push({ type: 'string', value: colTime });
|
||||||
@@ -132,7 +121,8 @@ const acm: ContestRule = {
|
|||||||
} else {
|
} else {
|
||||||
row.push({
|
row.push({
|
||||||
type: 'record',
|
type: 'record',
|
||||||
value: '{0}<br>{1}'.format(colAccepted, colTimeStr),
|
score: doc.accept ? 100 : 0,
|
||||||
|
value: '{0}\n{1}'.format(colAccepted, colTimeStr),
|
||||||
raw: rid,
|
raw: rid,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -185,6 +175,19 @@ const oi: ContestRule = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const psdict = {};
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||||
|
if (isDone(tdoc)) {
|
||||||
|
const psdocs = await problem.getMultiStatus(tdoc.domainId, {
|
||||||
|
$or: rankedTsdocs.map(([, i]) => ({
|
||||||
|
uid: i.uid,
|
||||||
|
docId: { $in: tdoc.pids },
|
||||||
|
})),
|
||||||
|
}).toArray();
|
||||||
|
for (const psdoc of psdocs) {
|
||||||
|
psdict[`${psdoc.uid}/${psdoc.docId}`] = psdoc;
|
||||||
|
}
|
||||||
|
}
|
||||||
const rows = [columns];
|
const rows = [columns];
|
||||||
for (const [rank, tsdoc] of rankedTsdocs) {
|
for (const [rank, tsdoc] of rankedTsdocs) {
|
||||||
const tsddict = {};
|
const tsddict = {};
|
||||||
@@ -198,11 +201,29 @@ const oi: ContestRule = {
|
|||||||
{ type: 'string', value: tsdoc.score || 0 },
|
{ type: 'string', value: tsdoc.score || 0 },
|
||||||
);
|
);
|
||||||
for (const pid of tdoc.pids) {
|
for (const pid of tdoc.pids) {
|
||||||
row.push({
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||||
type: 'record',
|
if (isDone(tdoc)) {
|
||||||
value: tsddict[pid]?.score ?? '-',
|
row.push({
|
||||||
raw: tsddict[pid]?.rid || null,
|
type: 'records',
|
||||||
});
|
value: '',
|
||||||
|
raw: [
|
||||||
|
{
|
||||||
|
value: tsddict[pid]?.score ?? '-',
|
||||||
|
raw: tsddict[pid]?.rid || null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: psdict[`${tsdoc.uid}/${pid}`]?.score ?? '-',
|
||||||
|
raw: psdict[`${tsdoc.uid}/${pid}`]?.rid ?? null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
row.push({
|
||||||
|
type: 'record',
|
||||||
|
value: tsddict[pid]?.score ?? '-',
|
||||||
|
raw: tsddict[pid]?.rid || null,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rows.push(row);
|
rows.push(row);
|
||||||
}
|
}
|
||||||
@@ -313,13 +334,13 @@ const homework: ContestRule = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const rows = [columns];
|
const rows: ScoreboardRow[] = [columns];
|
||||||
for (const [rank, tsdoc] of rankedTsdocs) {
|
for (const [rank, tsdoc] of rankedTsdocs) {
|
||||||
const tsddict = {};
|
const tsddict = {};
|
||||||
for (const item of tsdoc.detail || []) {
|
for (const item of tsdoc.detail || []) {
|
||||||
tsddict[item.pid] = item;
|
tsddict[item.pid] = item;
|
||||||
}
|
}
|
||||||
const row = [
|
const row: ScoreboardRow = [
|
||||||
{ type: 'string', value: rank },
|
{ type: 'string', value: rank },
|
||||||
{
|
{
|
||||||
type: 'user',
|
type: 'user',
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ class Nunjucks extends nunjucks.Environment {
|
|||||||
this.addFilter('base64_encode', (s) => Buffer.from(s).toString('base64'));
|
this.addFilter('base64_encode', (s) => Buffer.from(s).toString('base64'));
|
||||||
this.addFilter('base64_decode', (s) => Buffer.from(s, 'base64').toString());
|
this.addFilter('base64_decode', (s) => Buffer.from(s, 'base64').toString());
|
||||||
this.addFilter('bitand', (self, val) => self & val);
|
this.addFilter('bitand', (self, val) => self & val);
|
||||||
|
this.addFilter('replaceBr', (self) => self.toString().replace(/\n/g, '<br>'));
|
||||||
this.addFilter('toString', (self) => (typeof self === 'string' ? self : JSON.stringify(self, replacer)));
|
this.addFilter('toString', (self) => (typeof self === 'string' ? self : JSON.stringify(self, replacer)));
|
||||||
this.addFilter('content', (content, language, html) => {
|
this.addFilter('content', (content, language, html) => {
|
||||||
let s = '';
|
let s = '';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hydrooj/ui-default",
|
"name": "@hydrooj/ui-default",
|
||||||
"version": "4.8.29",
|
"version": "4.8.30",
|
||||||
"author": "undefined <i@undefined.moe>",
|
"author": "undefined <i@undefined.moe>",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "hydro.js",
|
"main": "hydro.js",
|
||||||
|
|||||||
@@ -41,10 +41,21 @@
|
|||||||
{{ user.render_inline(udict[column.raw], badge=false) }}
|
{{ user.render_inline(udict[column.raw], badge=false) }}
|
||||||
{% elif column.type == 'record' and column.raw %}
|
{% elif column.type == 'record' and column.raw %}
|
||||||
<a href="{{ url('record_detail', rid=column.raw) }}">
|
<a href="{{ url('record_detail', rid=column.raw) }}">
|
||||||
<span style="font-weight:bold;color:{{ utils.status.getScoreColor(column.value) }}">{{ column.value|safe }}</span>
|
<span style="font-weight:bold;color:{{ utils.status.getScoreColor(column.score|default(column.value)) }}">{{ column.value|replaceBr|safe }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
{% elif column.type == 'records' %}
|
||||||
|
{%- for record in column.raw -%}
|
||||||
|
{% if loop.index0 %}/{% endif %}
|
||||||
|
{% if record.raw %}
|
||||||
|
<a href="{{ url('record_detail', rid=record.raw) }}">
|
||||||
|
<span style="font-weight:bold;color:{{ utils.status.getScoreColor(record.score|default(record.value)) }}">{{ record.value|replaceBr|safe }}</span>
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
{{ record.value|replaceBr|safe }}
|
||||||
|
{% endif %}
|
||||||
|
{%- endfor -%}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ column.value|safe }}
|
{{ column.value|replaceBr|safe }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ function _digit2(number: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function formatSeconds(_seconds = '0') {
|
export function formatSeconds(_seconds = '0') {
|
||||||
const seconds = parseInt(_seconds, 10);
|
const seconds = +_seconds;
|
||||||
return '{0}:{1}:{2}'.format(
|
return '{0}:{1}:{2}'.format(
|
||||||
_digit2(Math.floor(seconds / 3600)),
|
_digit2(Math.floor(seconds / 3600)),
|
||||||
_digit2(Math.floor((seconds % 3600) / 60)),
|
_digit2(Math.floor((seconds % 3600) / 60)),
|
||||||
|
|||||||
Reference in new issue
Block a user