diff --git a/framework/eslint-config/package.json b/framework/eslint-config/package.json index 68eb61c9f..3cfeaa496 100644 --- a/framework/eslint-config/package.json +++ b/framework/eslint-config/package.json @@ -6,9 +6,9 @@ "repository": "https://github.com/hydro-dev/Hydro", "dependencies": { "@antfu/eslint-config": "^6.2.0", - "@eslint-react/eslint-plugin": "^2.3.9", - "@typescript-eslint/eslint-plugin": "^8.48.0", - "@typescript-eslint/parser": "^8.48.0", + "@eslint-react/eslint-plugin": "^2.3.11", + "@typescript-eslint/eslint-plugin": "^8.48.1", + "@typescript-eslint/parser": "^8.48.1", "eslint-plugin-de-morgan": "^2.0.0", "eslint-plugin-github": "^6.0.0", "eslint-plugin-react-hooks": "^7.0.1", diff --git a/package.json b/package.json index de4044032..aa80e7d2e 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "mongodb-memory-server": "10.3.0", "nyc": "^17.1.0", "ora": "^9.0.0", - "oxlint": "^1.30.0", + "oxlint": "^1.31.0", "package-json": "^10.0.1", "semver": "^7.7.3", "simple-git": "^3.30.0", diff --git a/packages/scoreboard-xcpcio/index.ts b/packages/scoreboard-xcpcio/index.ts index d8d693c50..38566504f 100644 --- a/packages/scoreboard-xcpcio/index.ts +++ b/packages/scoreboard-xcpcio/index.ts @@ -97,22 +97,17 @@ const PublishConfig = Schema.object({ publishToken: Schema.string().required(), publishPath: Schema.string().required(), publishEndpoint: Schema.string().default('https://scoreboard.hydrooj.com/_publish'), - medals: Schema.object({ - gold: Schema.number().required(), - silver: Schema.number().required(), - bronze: Schema.number().required(), - }), + preset: Schema.union(['ICPC', 'CCPC']).default('ICPC'), banner: Schema.string().default(''), badge: Schema.boolean().default(false), - override: Schema.any().default({}).description('Scoreboard contest override'), }); export const Config = Schema.object({ cacheTTL: Schema.number().default(0).description('Cache TTL in milliseconds'), cacheSize: Schema.number().default(100).description('Cache size'), asDefault: Schema.boolean().default(false).description('As default scoreboard'), override: Schema.any().default({}).description('Scoreboard contest override'), - publish: Schema.array(PublishConfig).description('Scoreboard publish config'), -}); + publish: Schema.array(PublishConfig).role('table').description('Scoreboard publish config'), +}).description('XCPCIO Scoreboard Config'); export async function apply(ctx: Context, config: ReturnType) { const lru = new LRUCache>>({ @@ -184,9 +179,7 @@ export async function apply(ctx: Context, config: ReturnType) { incorrect: true, pending: true, }, - medal: { - official: cfg.medals, - }, + medal: (cfg.preset || 'ICPC').toLowerCase(), balloon_color: tdoc.balloon ? tdoc.pids.filter((i) => tdoc.balloon[i]).map((i) => ({ color: '#000', @@ -194,9 +187,9 @@ export async function apply(ctx: Context, config: ReturnType) { })) : [], logo: { - preset: 'ICPC', + preset: cfg.preset || 'ICPC', }, - ...(cfg.banner ? { banner: { url: 'banner.jpg' } } : {}), + ...(cfg.banner ? { banner: { url: cfg.banner } } : {}), options: { submission_timestamp_unit: 'millisecond', }, @@ -238,7 +231,7 @@ export async function apply(ctx: Context, config: ReturnType) { json: Types.Boolean, realtime: Types.Boolean, badge: Types.Boolean, - banner: Types.Boolean, + banner: Types.String, gold: Schema.transform(Schema.union([Schema.string(), Schema.number().step(1).min(0)]), (v) => +v).default(0), silver: Schema.transform(Schema.union([Schema.string(), Schema.number().step(1).min(0)]), (v) => +v).default(0), bronze: Schema.transform(Schema.union([Schema.string(), Schema.number().step(1).min(0)]), (v) => +v).default(0), @@ -262,6 +255,7 @@ export async function apply(ctx: Context, config: ReturnType) { js: indexJs, css: indexCss, realtime, + refreshInterval: ContestModel.isOngoing(tdoc) ? 30000 : 0, tdoc: this.tdoc, }; } diff --git a/packages/ui-default/locales/zh.yaml b/packages/ui-default/locales/zh.yaml index f1ed0074c..21b638056 100644 --- a/packages/ui-default/locales/zh.yaml +++ b/packages/ui-default/locales/zh.yaml @@ -413,6 +413,7 @@ First of Problem: 题目一血 fontFamily: 字体 Footer: 页脚 Footnote: 脚注 +For better problem version management and validation, we suggest using Polyhedron to prepare problems.: 为了更好的题目版本管理和检查,我们推荐使用 Polyhedron 来准备算法竞赛题目。 Forgot Password and/or Username: 忘记密码和/或用户名 Forgot password or username?: 忘记密码或者用户名? Formula blocks: 公式区块 @@ -640,6 +641,7 @@ Only A-Z, a-z, 0-9 and _ are accepted: 只接受 A-Z, a-z, 0-9 和 _ Oops, there are no results.: 呀,没有结果。 Oops!: Oops! Open in Problem Set: 在题库中打开 +Open Polyhedron: 打开 Polyhedron Open Scratchpad: 进入在线编程模式 Open Since: 开始时间 Open Source: 开源 @@ -693,6 +695,7 @@ Please select at least one role to perform this operation.: 请选择至少一 Please select at least one user to perform this operation.: 请选择至少一个用户来进行操作。 Please set the balloon color for each problem first.: 请先为每道题设置气球颜色。 Please wait until contest host unfreeze the scoreboard.: 请等待比赛主办方解除封榜。 +Polyhedron supports managing problem version history, testing solutions, checking time limits, composing contest statements, cooperation and much more.: Polyhedron 支持题目版本管理,代码测试,时限检验,制作比赛题面,多人协作等等功能。 Preference Settings: 偏好设置 preferredPrefix_hint: 此选项用于重排题号。例如,若题目包中所给的题号分别是 P1001, P1002, P1003,而此选项填写了 T,则导入后三道题的题号分别为 T1001, T1002 和 T1003。 Preparing Upload...: 准备上传... @@ -742,6 +745,7 @@ problem.stats.sort.date: 提交时间 problem.stats.sort.length: 代码长度 problem.stats.sort.memory: 内存占用 problem.stats.sort.time: 运行时间 +Problems created in polyhedron can be directly imported into any Hydro based online judge system.: Polyhedron 中的题目可以直接导入任何基于 Hydro 的在线测评系统。 Problems Sets: 题库 Problems: 题目 Processing...: 处理中... diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index bfd113048..855b67365 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -23,7 +23,7 @@ "@mantine/core": "^8.3.9", "@mantine/hooks": "^8.3.9", "@mantine/notifications": "^8.3.9", - "@sentry/browser": "^10.27.0", + "@sentry/browser": "^10.28.0", "@sentry/webpack-plugin": "^4.6.1", "@simplewebauthn/browser": "13.2.2", "@svgr/webpack": "^8.1.0", diff --git a/packages/ui-default/pages/problem_edit.page.js b/packages/ui-default/pages/problem_edit.page.jsx similarity index 86% rename from packages/ui-default/pages/problem_edit.page.js rename to packages/ui-default/pages/problem_edit.page.jsx index a273f324c..154697881 100644 --- a/packages/ui-default/pages/problem_edit.page.js +++ b/packages/ui-default/pages/problem_edit.page.jsx @@ -1,11 +1,12 @@ import $ from 'jquery'; import _ from 'lodash'; +import ReactDOM from 'react-dom/client'; import { confirm } from 'vj/components/dialog'; import Dropdown from 'vj/components/dropdown/Dropdown'; import Editor from 'vj/components/editor/index'; import Notification from 'vj/components/notification'; import { NamedPage } from 'vj/misc/Page'; -import { i18n, request } from 'vj/utils'; +import { i18n, request, tpl } from 'vj/utils'; const categories = {}; const dirtyCategories = []; @@ -210,4 +211,19 @@ export default new NamedPage(['problem_create', 'problem_edit'], () => { ev.preventDefault(); } }); + + if (localStorage.getItem('polyhedron-hint') === 'dismiss') return; + $(tpl`
`).prependTo('.medium-9.columns .section__body'); + const root = ReactDOM.createRoot(document.querySelector('[name="hint"]')); + function ignore() { + root.unmount(); + localStorage.setItem('polyhedron-hint', 'dismiss'); + } + /* eslint-disable max-len */ + root.render(
+

{i18n('For better problem version management and validation, we suggest using Polyhedron to prepare problems.')}

+

{i18n('Polyhedron supports managing problem version history, testing solutions, checking time limits, composing contest statements, cooperation and much more.')}

+

{i18n('Problems created in polyhedron can be directly imported into any Hydro based online judge system.')}

+ {i18n('Open Polyhedron')} / root.unmount()}>{i18n('Dismiss')} / {i18n("Don't show again")} +
); }); diff --git a/packages/ui-default/templates/wiki_help.html b/packages/ui-default/templates/wiki_help.html index 418898d28..7d8a75ba2 100644 --- a/packages/ui-default/templates/wiki_help.html +++ b/packages/ui-default/templates/wiki_help.html @@ -99,17 +99,22 @@

{{ _('Contest') }}

-

按照赛制不同,有不同的递交、排名规则。 +

按照赛制不同,有不同的递交、排名规则。

+

在 IOI,XCPC,{{ _('Ledo') }},IOI(Strict) 赛制下,选手可以多次提交一道题目,并获得实时评测结果。

+

在 IOI,XCPC,{{ _('Ledo') }} 赛制下,选手可以在比赛时看到排行榜。

+

OI 赛制所有题目均以最后一次递交为准,特别地,请避免编译错误。

OI 赛制排名规则为:总分高的排在前面,总分相等则排名相同。

-

ACM/ICPC 赛制所有题目递交后立即评测,以是否通过为准。

-

ACM/ICPC 赛制排名规则为:通过题目数多的排在前面,通过题目数相同的做题耗时(含罚时)少的排在前。

-

{{ _('Ledo') }} 赛制下,选手可以多次提交一道题目,并获得实时评测结果。

+ +

XCPC 赛制中,每次错误提交会给题目增加 20 分钟的罚时。

+

XCPC 赛制排名规则为:通过题目数多的排在前面,通过题目数相同的做题耗时(含罚时)少的排在前。

+

{{ _('Ledo') }} 赛制下,多次提交会导致选手的得分被扣除,排行榜将显示用户的最高得分。

{{ _('Ledo') }} 赛制下,每道题的最终得分为: $s \times \max(0.95^{n}, 0.7)$ 。$s,n$ 分别代表本次得分和本次提交前的尝试次数。

{{ _('Ledo') }} 排名规则为:按照如上规则折算后的分数从高到低排名。

-

{{ _('IOI(Strict)') }} 赛制下,不同于IOI赛制,排行榜将被关闭至比赛结束。

+

{{ _('IOI(Strict)') }} 赛制下,每道题的排行榜得分将为用户每个子任务在所有提交中的最大得分的和。

+

时间与空间限制以题目说明为准,默认限制参见{{ _('Limitations') }}。