From 6ddaa8cf0cb2ce7536d8288138676b04cf9ee24d Mon Sep 17 00:00:00 2001 From: undefined Date: Tue, 15 Nov 2022 17:32:52 +0800 Subject: [PATCH] core&ui: optimize scoreboard nAccept and nSubmit calculation --- packages/hydrooj/src/handler/contest.ts | 6 +-- packages/hydrooj/src/interface.ts | 2 - packages/hydrooj/src/model/contest.ts | 27 +++++++--- .../pages/contest_scoreboard.page.styl | 4 ++ .../pages/homework_scoreboard.page.styl | 4 ++ .../templates/contest_scoreboard.html | 53 ++++++++++++------- 6 files changed, 63 insertions(+), 33 deletions(-) diff --git a/packages/hydrooj/src/handler/contest.ts b/packages/hydrooj/src/handler/contest.ts index 17144e2aa..9f46f0f08 100644 --- a/packages/hydrooj/src/handler/contest.ts +++ b/packages/hydrooj/src/handler/contest.ts @@ -236,11 +236,7 @@ export class ContestScoreboardHandler extends ContestDetailBaseHandler { await this.exportScoreboard(domainId, tid, ext); return; } - const pdict = await problem.getList(domainId, this.tdoc.pids, true, undefined, false, [ - // Problem statistics display is allowed as we can view submission info in scoreboard. - ...problem.PROJECTION_CONTEST_LIST, 'nSubmit', 'nAccept', - ]); - const [, rows, udict] = await contest.getScoreboard.call(this, domainId, tid, false); + const [, rows, udict, pdict] = await contest.getScoreboard.call(this, domainId, tid, false); this.response.template = 'contest_scoreboard.html'; // eslint-disable-next-line @typescript-eslint/naming-convention const page_name = this.tdoc.rule === 'homework' diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 6a3ead8eb..5e5c548a3 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -352,8 +352,6 @@ export interface Tdoc; - nAccept?: Record; // For contest lockAt?: Date; diff --git a/packages/hydrooj/src/model/contest.ts b/packages/hydrooj/src/model/contest.ts index e3196f8ea..d8207b5a6 100644 --- a/packages/hydrooj/src/model/contest.ts +++ b/packages/hydrooj/src/model/contest.ts @@ -96,6 +96,7 @@ const acm = buildContestRule({ columns.push({ type: 'solved', value: `${_('Solved')}\n${_('Total Time')}` }); for (let i = 1; i <= tdoc.pids.length; i++) { const pid = tdoc.pids[i - 1]; + pdict[pid].nAccept = pdict[pid].nSubmit = 0; if (isExport) { columns.push( { @@ -134,6 +135,11 @@ const acm = buildContestRule({ value: `${tsdoc.accept || 0}\n${formatSeconds(tsdoc.time || 0.0, false)}`, hover: formatSeconds(tsdoc.time || 0.0), }); + for (const s of tsdoc.journal || []) { + if (!pdict[s.pid]) continue; + pdict[s.pid].nSubmit++; + if (s.status === STATUS.STATUS_ACCEPTED) pdict[s.pid].nAccept++; + } for (const pid of tdoc.pids) { const doc = tsddict[pid] || {} as Partial; const accept = doc.status === STATUS.STATUS_ACCEPTED; @@ -231,6 +237,8 @@ const oi = buildContestRule({ } columns.push({ type: 'total_score', value: _('Total Score') }); for (let i = 1; i <= tdoc.pids.length; i++) { + const pid = tdoc.pids[i - 1]; + pdict[pid].nAccept = pdict[pid].nSubmit = 0; if (isExport) { columns.push({ type: 'string', @@ -259,6 +267,11 @@ const oi = buildContestRule({ row.push({ type: 'string', value: udoc.studentId || '' }); } row.push({ type: 'total_score', value: tsdoc.score || 0 }); + for (const s of tsdoc.journal || []) { + if (!pdict[s.pid]) continue; + pdict[s.pid].nSubmit++; + if (s.status === STATUS.STATUS_ACCEPTED) pdict[s.pid].nAccept++; + } for (const pid of tdoc.pids) { const index = `${tsdoc.uid}/${tdoc.domainId}/${pid}`; // eslint-disable-next-line @typescript-eslint/no-use-before-define @@ -395,6 +408,7 @@ const homework = buildContestRule({ columns.push({ type: 'time', value: _('Total Time') }); for (let i = 1; i <= tdoc.pids.length; i++) { const pid = tdoc.pids[i - 1]; + pdict[pid].nAccept = pdict[pid].nSubmit = 0; if (isExport) { columns.push( { @@ -438,6 +452,11 @@ const homework = buildContestRule({ row.push({ type: 'string', value: tsdoc.score || 0 }); } row.push({ type: 'time', value: formatSeconds(tsdoc.time || 0, false), raw: tsdoc.time }); + for (const s of tsdoc.journal || []) { + if (!pdict[s.pid]) continue; + pdict[s.pid].nSubmit++; + if (s.status === STATUS.STATUS_ACCEPTED) pdict[s.pid].nAccept++; + } for (const pid of tdoc.pids) { const rid = tsddict[pid]?.rid; const colScore = tsddict[pid]?.penaltyScore ?? ''; @@ -536,11 +555,7 @@ export async function getRelated(domainId: string, pid: number, rule?: string) { } export async function getStatus(domainId: string, tid: ObjectID, uid: number) { - const [tdoc, status] = await Promise.all([ - get(domainId, tid), - document.getStatus(domainId, document.TYPE_CONTEST, tid, uid), - ]); - return status; + return await document.getStatus(domainId, document.TYPE_CONTEST, tid, uid); } async function _updateStatus(tdoc: Tdoc<30>, uid: number, rid: ObjectID, pid: number, status: STATUS, score: number) { @@ -702,7 +717,7 @@ export async function getScoreboard( const tdoc = await get(domainId, tid); if (!canShowScoreboard.call(this, tdoc)) throw new ContestScoreboardHiddenError(tid); const tsdocsCursor = getMultiStatus(domainId, { docId: tid }).sort(RULES[tdoc.rule].statusSort); - const pdict = await problem.getList(domainId, tdoc.pids, true); + const pdict = await problem.getList(domainId, tdoc.pids, true, problem.PROJECTION_CONTEST_DETAIL); const [rows, udict] = await RULES[tdoc.rule].scoreboard( isExport, this.translate.bind(this), tdoc, pdict, tsdocsCursor, diff --git a/packages/ui-default/pages/contest_scoreboard.page.styl b/packages/ui-default/pages/contest_scoreboard.page.styl index 609d58262..a867dc06b 100644 --- a/packages/ui-default/pages/contest_scoreboard.page.styl +++ b/packages/ui-default/pages/contest_scoreboard.page.styl @@ -1,4 +1,8 @@ .page--contest_scoreboard + .main + .row + max-width: 100vw !important; + .col--rank width: rem(60px) text-align: center diff --git a/packages/ui-default/pages/homework_scoreboard.page.styl b/packages/ui-default/pages/homework_scoreboard.page.styl index def0f5c4e..ff1064a34 100644 --- a/packages/ui-default/pages/homework_scoreboard.page.styl +++ b/packages/ui-default/pages/homework_scoreboard.page.styl @@ -1,4 +1,8 @@ .page--homework_scoreboard + .main + .row + max-width: 100vw !important; + .col--rank width: rem(60px) text-align: center diff --git a/packages/ui-default/templates/contest_scoreboard.html b/packages/ui-default/templates/contest_scoreboard.html index 9dc79707f..1d5a65f28 100644 --- a/packages/ui-default/templates/contest_scoreboard.html +++ b/packages/ui-default/templates/contest_scoreboard.html @@ -2,6 +2,18 @@ {% extends "layout/basic.html" %} {{ set(UiContext, 'tdoc', tdoc) }} {% set type = 'homework' if tdoc.rule == 'homework' else 'contest' %} + +{% macro renderRecord(cell, canView) %} + + {%- if cell.status == status.STATUS_JUDGING -%} + ? + {%- else -%} + {%- set _color = utils.status.getScoreColor(cell.score|default(cell.value)) -%} + {{ cell.value|string|nl2br|safe }} + {%- endif -%} + +{% endmacro %} + {% block content %}
@@ -12,7 +24,7 @@ {{ _('Export as CSV') }} - {% if model.contest.isEnded(tdoc) and tdoc.lockAt and handler.user.own(tdoc) and not tdoc.unlocked %} + {% if model.contest.isDone(tdoc) and tdoc.lockAt and handler.user.own(tdoc) and not tdoc.unlocked %}
- {% elif model.contest.isEnded(tdoc) and tdoc.lockAt and not tdoc.unlocked %} + {% elif model.contest.isDone(tdoc) and tdoc.lockAt and not tdoc.unlocked %}
{{ _('Please wait until contest host unlock the scoreboard.') }} @@ -45,48 +57,49 @@ {%- for column in rows[0] -%} - {% if column.type == 'problem' and column.raw %} + {%- if column.type == 'problem' and column.raw -%} - {{ column.value }}
{{ pdict[column.raw].nAccept }}/{{ pdict[column.raw].nSubmit }} + {{ column.value }}
{{ pdict[column.raw].nAccept|default(0) }}/{{ pdict[column.raw].nSubmit|default(0) }}
- {% else %} + {%- else -%} {{ column.value|string|nl2br|safe }} - {% endif %} + {%- endif -%} {%- endfor -%} - {% set canViewAll = handler.user.own(tdoc) or model.contest.canShowRecord.call(handler, tdoc) %} - {%- for row in rows -%}{% if loop.index0 > 0 %} + {%- set canViewAll = handler.user.own(tdoc) or model.contest.canShowRecord.call(handler, tdoc) -%} + {%- for row in rows -%}{%- if loop.index0 > 0 -%} {%- for column in row -%} - {% if column.type == 'user' %} - {% set canView = canViewAll or handler.user._id == column.raw %} + {%- if column.type == 'user' -%} + {%- set canView = canViewAll or handler.user._id == column.raw -%} {{ user.render_inline(udict[column.raw], badge=false) }} - {% elif column.type == 'record' and column.raw %} + {%- elif column.type == 'record' and column.raw -%} {{ column.value|string|nl2br|safe }} - {% elif column.type == 'records' %} + {%- elif column.type == 'records' -%} {%- for record in column.raw -%} - {% if loop.index0 %}/{% endif %} - {% if record.raw %} + {%- if loop.index0 -%}/{%- endif -%} + {%- if record.raw -%} - {{ record.value|string|nl2br|safe }} + {%- set _color = utils.status.getScoreColor(record.score|default(record.value)) -%} + {{ record.value|string|nl2br|safe }} - {% else %} + {%- else -%} {{ record.value|string|nl2br|safe }} - {% endif %} + {%- endif -%} {%- endfor -%} - {% else %} + {%- else -%} {{ column.value|string|nl2br|safe }} - {% endif %} + {%- endif -%} {%- endfor -%} - {% endif %}{%- endfor -%} + {%- endif -%}{%- endfor -%}