From 3ba95feca6fd906e0557005a55f0124b05b6ba6b Mon Sep 17 00:00:00 2001 From: bLue Date: Sun, 17 Dec 2023 02:20:23 +0800 Subject: [PATCH] feat: display dynamic problem score in competition overview --- src/@types/models.d.ts | 10 ++++ src/common | 2 +- src/pages/competitions/$id/overview.tsx | 69 +++++++++++++++++++++++-- 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/@types/models.d.ts b/src/@types/models.d.ts index 17886fd..35c92a8 100755 --- a/src/@types/models.d.ts +++ b/src/@types/models.d.ts @@ -675,3 +675,13 @@ interface ICompetitionSessionStatus { role: number; }; } + +interface ICompetitionProblemResultStats { + [key: number]: { + accepted: number; + submitted: number; + selfTries: number; + selfAccepted: boolean; + selfAcceptedTime: Date | null; + }; +} diff --git a/src/common b/src/common index 3bf022c..b4b9df0 160000 --- a/src/common +++ b/src/common @@ -1 +1 @@ -Subproject commit 3bf022c32f6a5694025a9397a15815ba94dfb29e +Subproject commit b4b9df0384ba0022ecdbd342949b283619f2b1c5 diff --git a/src/pages/competitions/$id/overview.tsx b/src/pages/competitions/$id/overview.tsx index 654b1aa..8407f05 100644 --- a/src/pages/competitions/$id/overview.tsx +++ b/src/pages/competitions/$id/overview.tsx @@ -28,6 +28,7 @@ import tracker from '@/utils/tracker'; import GeneralFormModal from '@/components/GeneralFormModal'; import Explanation from '@/components/Explanation'; import { getReadableVarScoreExpression } from '@/utils/competition'; +import { compileVarScoreExpression } from '@/common/utils/competition'; export interface Props extends ReduxProps { id: number; @@ -38,7 +39,7 @@ export interface Props extends ReduxProps { problemsLoading: boolean; problems: IFullList; userProblemResultStats: IUserProblemResultStats; - competitionProblemResultStats: IContestProblemResultStats; + competitionProblemResultStats: ICompetitionProblemResultStats; notifications: ICompetitionNotification[]; notificationsLoading: boolean; questions: ICompetitionQuestion[]; @@ -150,6 +151,48 @@ class CompetitionOverview extends React.Component { ]; }; + evalVarScoreExpression = ( + score: number | null, + varScoreExpression: string, + detail: ICompetition, + problemIndex: number, + tries = 0, + acceptedTime?: Date | string, + ): number | null => { + if (typeof score !== 'number') { + return null; + } + if (!varScoreExpression) { + return score; + } + + try { + const currentTime = Date.now() - ((window as any)._t_diff || 0); + const startTime = toLongTs(detail.startAt); + const elapsedMs = (acceptedTime ? toLongTs(acceptedTime) : currentTime) - startTime; + const expression = compileVarScoreExpression(varScoreExpression, { + score, + problemIndex, + elapsedTime: { + h: Math.floor(elapsedMs / 1000 / 60 / 60), + min: Math.floor(elapsedMs / 1000 / 60), + s: Math.floor(elapsedMs / 1000), + }, + tries, + }); + try { + // eslint-disable-next-line no-eval + return eval(expression); + } catch (e) { + console.error('failed to eval var score expression', varScoreExpression, expression, e); + return null; + } + } catch (e) { + console.error('unknown error while evaling var score expression', e); + return null; + } + }; + render() { const { id, @@ -301,11 +344,31 @@ class CompetitionOverview extends React.Component { key="Score" render={(text, record: ICompetitionProblem, index) => (
- {record.score ?? '-'} + + {this.evalVarScoreExpression( + record.score, + record.varScoreExpression, + detail, + index, + competitionProblemResultStats[record.problemId]?.selfTries, + competitionProblemResultStats[record.problemId]?.selfAcceptedTime, + ) ?? '-'} + {typeof record.score === 'number' && (

Base Score: {record.score}

- {!!record.varScoreExpression &&

Score Rule: {getReadableVarScoreExpression(record.varScoreExpression)}

} + {!!record.varScoreExpression && ( +

+ Score Rule:{' '} + {getReadableVarScoreExpression(record.varScoreExpression)} +

+ )}
)}