From e0b5700cfcdd835fbdc39a50bcb47430b2bece96 Mon Sep 17 00:00:00 2001 From: undefined Date: Sun, 16 May 2021 12:55:03 +0800 Subject: [PATCH] ui: submission status --- packages/hydrooj/package.json | 2 +- packages/hydrooj/src/interface.ts | 1 + packages/hydrooj/src/model/problem.ts | 3 +- packages/hydrooj/src/model/setting.ts | 2 + packages/hydrooj/src/script/problemStat.ts | 64 ++++++++++++++----- packages/ui-default/package.json | 2 +- .../ui-default/pages/problem_detail.page.jsx | 29 ++++++++- .../partials/problem_sidebar_normal.html | 9 ++- 8 files changed, 90 insertions(+), 22 deletions(-) diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 37d5c983c..cb8bbf321 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.26.3", + "version": "2.26.4", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 01a4c6925..1ee53e80c 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -201,6 +201,7 @@ declare module './model/problem' { additional_file: FileInfo[], hidden: boolean, html?: boolean, + stats?: any, difficulty?: number, /** @deprecated */ category?: string[], diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index d629708d9..7d0795217 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -23,7 +23,7 @@ export class ProblemModel { static PROJECTION_LIST: Field[] = [ '_id', 'domainId', 'docType', 'docId', 'pid', 'owner', 'title', 'nSubmit', 'nAccept', 'difficulty', - 'tag', 'hidden', + 'tag', 'hidden', 'stats', ]; static PROJECTION_PUBLIC: Field[] = [ @@ -275,6 +275,7 @@ ProblemModel.extend((docId, pid) => ({ tag: [], data: [], additional_file: [], + stats: {}, hidden: true, config: '', difficulty: 0, diff --git a/packages/hydrooj/src/model/setting.ts b/packages/hydrooj/src/model/setting.ts index 4fefb91ea..92e3ed316 100644 --- a/packages/hydrooj/src/model/setting.ts +++ b/packages/hydrooj/src/model/setting.ts @@ -148,7 +148,9 @@ DomainUserSetting( Setting('setting_storage', 'nLike', 0, 'number', 'nLike', null, FLAG_HIDDEN | FLAG_DISABLED), Setting('setting_storage', 'rp', 1500, 'number', 'RP', null, FLAG_HIDDEN | FLAG_DISABLED), Setting('setting_storage', 'rpdelta', 0, 'number', 'RP.delta', null, FLAG_HIDDEN | FLAG_DISABLED), + Setting('setting_storage', 'rank', 0, 'number', 'Rank', null, FLAG_DISABLED | FLAG_HIDDEN), Setting('setting_storage', 'level', 0, 'number', 'level', null, FLAG_HIDDEN | FLAG_DISABLED), + Setting('setting_storage', 'ratingHistory', [], 'text', 'Rating History', null, FLAG_DISABLED | FLAG_HIDDEN), ); SystemSetting( diff --git a/packages/hydrooj/src/script/problemStat.ts b/packages/hydrooj/src/script/problemStat.ts index 216d7aae3..a912a7336 100644 --- a/packages/hydrooj/src/script/problemStat.ts +++ b/packages/hydrooj/src/script/problemStat.ts @@ -5,18 +5,17 @@ import * as document from '../model/document'; export const description = 'Recalculates nSubmit and nAccept in problem status.'; -export async function udoc() { +const sumStatus = (status) => ({ $sum: { $cond: [{ $eq: ['$status', status] }, 1, 0] } }); + +export async function udoc(report) { + report({ message: 'Udoc' }); const pipeline = [ { $match: { hidden: false, type: { $ne: 'run' } } }, { $group: { _id: { domainId: '$domainId', pid: '$pid', uid: '$uid' }, nSubmit: { $sum: 1 }, - nAccept: { - $sum: { - $cond: [{ $eq: ['$status', STATUS.STATUS_ACCEPTED] }, 1, 0], - }, - }, + nAccept: sumStatus(STATUS.STATUS_ACCEPTED), }, }, { @@ -48,7 +47,8 @@ export async function udoc() { if (bulk.length) await bulk.execute(); } -export async function psdoc() { +export async function psdoc(report) { + report({ message: 'Psdoc' }); const pipeline = [ { $match: { hidden: false, type: { $ne: 'run' } } }, { @@ -65,18 +65,22 @@ export async function psdoc() { } } -export async function pdoc() { +export async function pdoc(report) { + report({ message: 'Pdoc' }); const pipeline = [ { $match: { hidden: false, type: { $ne: 'run' }, effective: true } }, { $group: { _id: { domainId: '$domainId', pid: '$pid', uid: '$uid' }, nSubmit: { $sum: 1 }, - nAccept: { - $sum: { - $cond: [{ $eq: ['$status', STATUS.STATUS_ACCEPTED] }, 1, 0], - }, - }, + nAccept: sumStatus(STATUS.STATUS_ACCEPTED), + WA: sumStatus(STATUS.STATUS_WRONG_ANSWER), + TLE: sumStatus(STATUS.STATUS_TIME_LIMIT_EXCEEDED), + MLE: sumStatus(STATUS.STATUS_MEMORY_LIMIT_EXCEEDED), + RE: sumStatus(STATUS.STATUS_RUNTIME_ERROR), + SE: sumStatus(STATUS.STATUS_SYSTEM_ERROR), + IGN: sumStatus(STATUS.STATUS_CANCELED), + CE: sumStatus(STATUS.STATUS_COMPILE_ERROR), }, }, { @@ -84,11 +88,20 @@ export async function pdoc() { _id: { domainId: '$_id.domainId', pid: '$_id.pid' }, nSubmit: { $sum: '$nSubmit' }, nAccept: { $sum: { $min: ['$nAccept', 1] } }, + AC: { $sum: '$nAccept' }, + WA: { $sum: '$WA' }, + TLE: { $sum: '$TLE' }, + MLE: { $sum: '$MLE' }, + RE: { $sum: '$RE' }, + SE: { $sum: '$SE' }, + IGN: { $sum: '$IGN' }, + CE: { $sum: '$CE' }, }, }, ]; let bulk = db.collection('document').initializeUnorderedBulkOp(); const data = db.collection('record').aggregate(pipeline); + let cnt = 0; while (await data.hasNext()) { const adoc = await data.next() as any; bulk.find({ @@ -99,20 +112,37 @@ export async function pdoc() { $set: { nSubmit: adoc.nSubmit, nAccept: adoc.nAccept, + 'stats.AC': adoc.AC, + 'stats.WA': adoc.WA, + 'stats.TLE': adoc.TLE, + 'stats.MLE': adoc.MLE, + 'stats.RE': adoc.RE, + 'stats.SE': adoc.SE, + 'stats.IGN': adoc.IGN, + 'stats.CE': adoc.CE, }, }); if (bulk.length > 100) { await bulk.execute(); - bulk = db.collection('domain.user').initializeUnorderedBulkOp(); + cnt++; + report({ message: `${cnt * 100} pdocs updated` }); + bulk = db.collection('document').initializeUnorderedBulkOp(); } } if (bulk.length) await bulk.execute(); } -export async function run() { - return await Promise.all([udoc(), pdoc(), psdoc()]); +export async function run(arg, report) { + if (arg.pdoc === undefined || arg.pdoc) await pdoc(report); + if (arg.udoc === undefined || arg.udoc) await udoc(report); + if (arg.psdoc === undefined || arg.psdoc) await psdoc(report); + return true; } -export const validate = {}; +export const validate = { + udoc: 'boolean?', + pdoc: 'boolean?', + psdoc: 'boolean?', +}; global.Hydro.script.problemStat = { run, description, validate }; diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 8d21377dd..a0185fed1 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.8.16", + "version": "4.8.17", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/pages/problem_detail.page.jsx b/packages/ui-default/pages/problem_detail.page.jsx index 06b0b2031..393c86104 100644 --- a/packages/ui-default/pages/problem_detail.page.jsx +++ b/packages/ui-default/pages/problem_detail.page.jsx @@ -1,4 +1,5 @@ import yaml from 'js-yaml'; +import * as echarts from 'echarts'; import { NamedPage } from 'vj/misc/Page'; import Navigation from 'vj/components/navigation'; import Notification from 'vj/components/notification/index'; @@ -105,7 +106,7 @@ class ProblemPageExtender { } } -const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homework_detail_problem'], () => { +const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homework_detail_problem'], async (pagename) => { let reactLoaded = false; let renderReact = null; let unmountReact = null; @@ -247,6 +248,32 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor }); $('[name="problem-sidebar__send-to"]').on('click', handleClickCopyProblem); loadSubjective(); + + if (pagename === 'contest_detail_problem') return; + const data = await request.get(''); + const $dom = document.getElementById('submission-detail-placeholder'); + const chart = echarts.init($dom); + chart.setOption({ + tooltip: { trigger: 'item' }, + series: [ + { + name: 'Submissions', + type: 'pie', + radius: [10, 70], + roseType: 'radius', + data: [ + { value: data.pdoc.stats?.TLE, name: 'TLE' }, + { value: data.pdoc.stats?.AC, name: 'AC' }, + { value: data.pdoc.stats?.MLE, name: 'MLE' }, + { value: data.pdoc.stats?.WA, name: 'WA' }, + { value: data.pdoc.stats?.RE, name: 'RE' }, + { value: data.pdoc.stats?.CE, name: 'CE' }, + { value: data.pdoc.stats?.SE, name: 'SE' }, + { value: data.pdoc.stats?.IGN, name: 'IGN' }, + ], + }, + ], + }); }); export default page; diff --git a/packages/ui-default/templates/partials/problem_sidebar_normal.html b/packages/ui-default/templates/partials/problem_sidebar_normal.html index f05fae301..743c5bede 100644 --- a/packages/ui-default/templates/partials/problem_sidebar_normal.html +++ b/packages/ui-default/templates/partials/problem_sidebar_normal.html @@ -105,13 +105,20 @@ -{% if pagename != 'problem_detail' %} +{% if page_name != 'problem_detail' %}

{{ _('Information') }}

{% include "partials/problem-sidebar-information.html" %}
+{% else %} +
+
+

{{ _('Statistics') }}

+
+
+
{% endif %} {% if page_name == 'problem_detail' and (tdocs or ctdocs) %}