diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 2f92b7af9..860d24739 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.26.5", + "version": "2.26.6", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", diff --git a/packages/hydrooj/src/handler/judge.ts b/packages/hydrooj/src/handler/judge.ts index 06a1b42d1..acf128704 100644 --- a/packages/hydrooj/src/handler/judge.ts +++ b/packages/hydrooj/src/handler/judge.ts @@ -39,6 +39,7 @@ async function _postJudge(rdoc: RecordDoc) { record.update(rdoc.domainId, rdoc._id, { effective: true }), problem.edit(pdoc.domainId, pdoc.docId, { difficulty }), problem.inc(pdoc.domainId, pdoc.docId, `stats.${builtin.STATUS_SHORT_TEXTS[rdoc.status]}`, 1), + problem.inc(pdoc.domainId, pdoc.docId, `stats.s${rdoc.score}`, 1), ]); await bus.serial('record/judge', rdoc, updated); } diff --git a/packages/hydrooj/src/script/problemStat.ts b/packages/hydrooj/src/script/problemStat.ts index a912a7336..363b614d0 100644 --- a/packages/hydrooj/src/script/problemStat.ts +++ b/packages/hydrooj/src/script/problemStat.ts @@ -27,7 +27,7 @@ export async function udoc(report) { }, ]; let bulk = db.collection('domain.user').initializeUnorderedBulkOp(); - const cursor = db.collection('record').aggregate(pipeline); + const cursor = db.collection('record').aggregate(pipeline, { allowDiskUse: true }); while (await cursor.hasNext()) { const adoc = await cursor.next() as any; bulk.find({ @@ -58,7 +58,7 @@ export async function psdoc(report) { }, }, ]; - const data = db.collection('record').aggregate(pipeline); + const data = db.collection('record').aggregate(pipeline, { allowDiskUse: true }); while (await data.hasNext()) { const adoc = await data.next() as any; await document.setStatus(adoc._id.domainId, document.TYPE_PROBLEM, adoc._id.pid, adoc._id.uid, { nSubmit: adoc.nSubmit }); @@ -99,29 +99,33 @@ export async function pdoc(report) { }, }, ]; + for (let i = 0; i <= 100; i++) { + pipeline[1].$group[`s${i}`] = { $sum: { $cond: [{ $eq: ['$score', i] }, 1, 0] } }; + pipeline[2].$group[`s${i}`] = { $sum: `$s${i}` }; + } let bulk = db.collection('document').initializeUnorderedBulkOp(); - const data = db.collection('record').aggregate(pipeline); + const data = db.collection('record').aggregate(pipeline, { allowDiskUse: true }); let cnt = 0; while (await data.hasNext()) { const adoc = await data.next() as any; + const $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, + }; + for (let i = 0; i <= 100; i++) if (adoc[`s${i}`]) $set[`stats.s${i}`] = adoc[`s${i}`]; bulk.find({ domainId: adoc._id.domainId, docType: document.TYPE_PROBLEM, docId: adoc._id.pid, - }).updateOne({ - $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, - }, - }); + }).updateOne({ $set }); if (bulk.length > 100) { await bulk.execute(); cnt++; diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 3caf25ec9..e66cc76a5 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.8.19", + "version": "4.8.20", "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 393c86104..36b2b3e4f 100644 --- a/packages/ui-default/pages/problem_detail.page.jsx +++ b/packages/ui-default/pages/problem_detail.page.jsx @@ -9,6 +9,7 @@ import delay from 'vj/utils/delay'; import i18n from 'vj/utils/i18n'; import request from 'vj/utils/request'; import base64 from 'vj/utils/base64'; +import { getScoreColor } from 'vj/../utils/lib/status'; class ProblemPageExtender { constructor() { @@ -251,9 +252,10 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor 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({ + data.pdoc.stats = data.pdoc.stats || {}; + const $status = document.getElementById('submission-status-placeholder'); + const statusChart = echarts.init($status); + statusChart.setOption({ tooltip: { trigger: 'item' }, series: [ { @@ -262,18 +264,33 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor 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' }, + { 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' }, ], }, ], }); + const $score = document.getElementById('submission-score-placeholder'); + const x = Array.from({ length: 101 }, (v, i) => i).filter((i) => data.pdoc.stats[`s${i}`]); + const scoreChart = echarts.init($score); + scoreChart.setOption({ + tooltip: { trigger: 'item' }, + xAxis: { data: x }, + yAxis: {}, + series: [{ + data: x.map((i) => ({ + value: data.pdoc.stats[`s${i}`], + itemStyle: { color: getScoreColor(i) }, + })), + type: 'bar', + }], + }); }); 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 743c5bede..b3e693c90 100644 --- a/packages/ui-default/templates/partials/problem_sidebar_normal.html +++ b/packages/ui-default/templates/partials/problem_sidebar_normal.html @@ -117,7 +117,8 @@

{{ _('Statistics') }}

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