mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: contest: add ledo contest rule (#481)
This commit is contained in:
1 parent
f27dbb007a
commit
3ee29da3bd
9 files changed
+84
-7
No files matched your search
@@ -30,6 +30,7 @@ __langname: 简体中文
|
|||||||
'Join {0}': '加入 {0}'
|
'Join {0}': '加入 {0}'
|
||||||
'No': 否
|
'No': 否
|
||||||
'Note: Problem title may not be hidden.': 注意:题目标题可能不会被隐藏。
|
'Note: Problem title may not be hidden.': 注意:题目标题可能不会被隐藏。
|
||||||
|
'Original score: {0}': '原得分: {0}'
|
||||||
'Role {1} already exists in domain {0}.': '域 {0} 中已存在角色 {1}。'
|
'Role {1} already exists in domain {0}.': '域 {0} 中已存在角色 {1}。'
|
||||||
'Solved {0} problems, RP: {1} (No. {2})': '解决了 {0} 道题目,RP: {1} (No. {2})'
|
'Solved {0} problems, RP: {1} (No. {2})': '解决了 {0} 道题目,RP: {1} (No. {2})'
|
||||||
'The value `{1}` of {0} already exists.': '{0} 的值 `{1}` 已经存在。'
|
'The value `{1}` of {0} already exists.': '{0} 的值 `{1}` 已经存在。'
|
||||||
|
|||||||
@@ -356,6 +356,76 @@ const ioi = buildContestRule({
|
|||||||
showScoreboard: (tdoc, now) => now > tdoc.beginAt,
|
showScoreboard: (tdoc, now) => now > tdoc.beginAt,
|
||||||
}, oi);
|
}, oi);
|
||||||
|
|
||||||
|
const ledo = buildContestRule({
|
||||||
|
TEXT: 'Ledo',
|
||||||
|
check: () => { },
|
||||||
|
submitAfterAccept: false,
|
||||||
|
showScoreboard: (tdoc, now) => now > tdoc.beginAt,
|
||||||
|
showSelfRecord: () => true,
|
||||||
|
showRecord: (tdoc, now) => now > tdoc.endAt,
|
||||||
|
stat(tdoc, journal) {
|
||||||
|
const ntry = Counter<number>();
|
||||||
|
const detail = {};
|
||||||
|
for (const j of journal.filter((i) => tdoc.pids.includes(i.pid))) {
|
||||||
|
const vaild = ![STATUS.STATUS_COMPILE_ERROR, STATUS.STATUS_FORMAT_ERROR].includes(j.status);
|
||||||
|
if (vaild) ntry[j.pid]++;
|
||||||
|
const penaltyScore = vaild ? Math.round(Math.max(0.7, 0.95 ** (ntry[j.pid] - 1)) * j.score) : 0;
|
||||||
|
if (!detail[j.pid] || detail[j.pid].penaltyScore < penaltyScore) {
|
||||||
|
detail[j.pid] = {
|
||||||
|
...j,
|
||||||
|
penaltyScore,
|
||||||
|
ntry: ntry[j.pid] - 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let score = 0;
|
||||||
|
let originalScore = 0;
|
||||||
|
for (const pid of tdoc.pids) {
|
||||||
|
if (!detail[pid]) continue;
|
||||||
|
score += detail[pid].penaltyScore;
|
||||||
|
originalScore += detail[pid].score;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
score, originalScore, detail,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
async scoreboardRow(isExport, _, tdoc, pdict, udoc, rank, tsdoc, meta) {
|
||||||
|
const tsddict = tsdoc.detail || {};
|
||||||
|
const row: ScoreboardRow = [
|
||||||
|
{ type: 'rank', value: rank.toString() },
|
||||||
|
{ type: 'user', value: udoc.uname, raw: tsdoc.uid },
|
||||||
|
];
|
||||||
|
if (isExport) {
|
||||||
|
row.push({ type: 'email', value: udoc.mail });
|
||||||
|
row.push({ type: 'string', value: udoc.school || '' });
|
||||||
|
row.push({ type: 'string', value: udoc.displayName || '' });
|
||||||
|
row.push({ type: 'string', value: udoc.studentId || '' });
|
||||||
|
}
|
||||||
|
row.push({
|
||||||
|
type: 'total_score',
|
||||||
|
value: tsdoc.score || 0,
|
||||||
|
hover: tsdoc.score !== tsdoc.originalScore ? _('Original score: {0}').format(tsdoc.originalScore) : '',
|
||||||
|
});
|
||||||
|
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) {
|
||||||
|
row.push({
|
||||||
|
type: 'record',
|
||||||
|
value: tsddict[pid]?.penaltyScore || '',
|
||||||
|
hover: tsddict[pid]?.ntry ? `-${tsddict[pid].ntry} (${Math.round(Math.max(0.7, 0.95 ** tsddict[pid].ntry) * 100)}%)` : '',
|
||||||
|
raw: tsddict[pid]?.rid,
|
||||||
|
style: tsddict[pid]?.status === STATUS.STATUS_ACCEPTED && tsddict[pid]?.rid.generationTime === meta?.first?.[pid]
|
||||||
|
? 'background-color: rgb(217, 240, 199);'
|
||||||
|
: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
},
|
||||||
|
}, oi);
|
||||||
|
|
||||||
const homework = buildContestRule({
|
const homework = buildContestRule({
|
||||||
TEXT: 'Assignment',
|
TEXT: 'Assignment',
|
||||||
hidden: true,
|
hidden: true,
|
||||||
@@ -506,7 +576,7 @@ const homework = buildContestRule({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const RULES: ContestRules = {
|
export const RULES: ContestRules = {
|
||||||
acm, oi, homework, ioi,
|
acm, oi, homework, ioi, ledo,
|
||||||
};
|
};
|
||||||
|
|
||||||
function _getStatusJournal(tsdoc) {
|
function _getStatusJournal(tsdoc) {
|
||||||
|
|||||||
@@ -254,5 +254,6 @@ $contest-color = {
|
|||||||
'acm': #6BB67A,
|
'acm': #6BB67A,
|
||||||
'oi': #F5C735,
|
'oi': #F5C735,
|
||||||
'ioi': #2E9AFE,
|
'ioi': #2E9AFE,
|
||||||
|
'ledo': #8076A3,
|
||||||
'homework': #FFCDCD,
|
'homework': #FFCDCD,
|
||||||
}
|
}
|
||||||
@@ -461,6 +461,7 @@ Last Update At: 最后活动时间
|
|||||||
LaTeX Expressions: LaTeX 表达式
|
LaTeX Expressions: LaTeX 表达式
|
||||||
Learn More: 了解更多
|
Learn More: 了解更多
|
||||||
Leave blank to use numeric pid.: 留空来使用数字题号。
|
Leave blank to use numeric pid.: 留空来使用数字题号。
|
||||||
|
Ledo: 乐多
|
||||||
Light: 亮色
|
Light: 亮色
|
||||||
Limit user to finish contest within N hours: 限制用户在N小时内完成比赛
|
Limit user to finish contest within N hours: 限制用户在N小时内完成比赛
|
||||||
Limitations: 限制
|
Limitations: 限制
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<ul class="info">
|
<ul class="info">
|
||||||
<li>
|
<li>
|
||||||
<span class="icon icon-award"></span>
|
<span class="icon icon-award"></span>
|
||||||
{{ _('Rule') }}: {{ model.contest.RULES[tdoc['rule']].TEXT }}
|
{{ _('Rule') }}: {{ _(model.contest.RULES[tdoc['rule']].TEXT) }}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span class="icon icon-calendar"></span>
|
<span class="icon icon-calendar"></span>
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="section__header">
|
<div class="section__header">
|
||||||
<h1 class="section__title">{{ _('All Contests') if not rule else _('All {0} Contests').format(model.contest.RULES[rule].TEXT) }}</h1>
|
<h1 class="section__title">{{ _('All Contests') if not rule else _('All {0} Contests').format(_(model.contest.RULES[rule].TEXT)) }}</h1>
|
||||||
<div class="section__tools">
|
<div class="section__tools">
|
||||||
<form method="get" name="filter-form">
|
<form method="get" name="filter-form">
|
||||||
{{ _('Show') }}:
|
{{ _('Show') }}:
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
<h1 class="contest__title"><a href="{{ url('contest_detail', tid=tdoc.docId) }}" data-emoji-enabled>{{ tdoc.title }}</a></h1>
|
<h1 class="contest__title"><a href="{{ url('contest_detail', tid=tdoc.docId) }}" data-emoji-enabled>{{ tdoc.title }}</a></h1>
|
||||||
<ul class="supplementary list">
|
<ul class="supplementary list">
|
||||||
<li>
|
<li>
|
||||||
<a href="?rule={{ tdoc['rule'] }}" class="contest-type-tag"><span class="icon icon-award"></span>{{ model.contest.RULES[tdoc.rule].TEXT }}</a>
|
<a href="?rule={{ tdoc['rule'] }}" class="contest-type-tag"><span class="icon icon-award"></span>{{ _(model.contest.RULES[tdoc.rule].TEXT) }}</a>
|
||||||
</li>
|
</li>
|
||||||
{% if tdoc.rated %}
|
{% if tdoc.rated %}
|
||||||
<li class="contest-tag-rated"><span class="icon icon-star"></span>Rated</li>
|
<li class="contest-tag-rated"><span class="icon icon-star"></span>Rated</li>
|
||||||
|
|||||||
@@ -102,7 +102,7 @@
|
|||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
{%- else -%}
|
{%- else -%}
|
||||||
{{ column.value|string|nl2br|safe }}
|
<span data-tooltip="{{ column.hover }}">{{ column.value|string|nl2br|safe }}</span>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
</td>
|
</td>
|
||||||
{%- endfor -%}
|
{%- endfor -%}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@
|
|||||||
({{ _('Attended') }})
|
({{ _('Attended') }})
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</dd>
|
</dd>
|
||||||
<dt>{{ _('Rule') }}</dt><dd>{{ model.contest.RULES[tdoc.rule].TEXT }}</dd>
|
<dt>{{ _('Rule') }}</dt><dd>{{ _(model.contest.RULES[tdoc.rule].TEXT) }}</dd>
|
||||||
<dt>{{ _('Problem') }}</dt><dd>{{ tdoc.pids.length }}</dd>
|
<dt>{{ _('Problem') }}</dt><dd>{{ tdoc.pids.length }}</dd>
|
||||||
<dt>{{ _('Start at') }}</dt><dd>{{ contest.render_time(tsdoc.startAt or tdoc.beginAt) }}</dd>
|
<dt>{{ _('Start at') }}</dt><dd>{{ contest.render_time(tsdoc.startAt or tdoc.beginAt) }}</dd>
|
||||||
<dt>{{ _('End at') }}</dt><dd>{{ contest.render_time(tsdoc.endAt or tdoc.endAt) }}</dd>
|
<dt>{{ _('End at') }}</dt><dd>{{ contest.render_time(tsdoc.endAt or tdoc.endAt) }}</dd>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<h1 class="contest__title"><a href="{{ url('contest_detail', tid=tdoc.docId) }}" data-emoji-enabled>{{ tdoc.title }}</a></h1>
|
<h1 class="contest__title"><a href="{{ url('contest_detail', tid=tdoc.docId) }}" data-emoji-enabled>{{ tdoc.title }}</a></h1>
|
||||||
<ul class="supplementary list">
|
<ul class="supplementary list">
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ url('contest_main', query={rule:tdoc.rule}) }}" class="contest-type-tag"><span class="icon icon-award"></span>{{ model.contest.RULES[tdoc.rule].TEXT }}</a>
|
<a href="{{ url('contest_main', query={rule:tdoc.rule}) }}" class="contest-type-tag"><span class="icon icon-award"></span>{{ _(model.contest.RULES[tdoc.rule].TEXT) }}</a>
|
||||||
</li>
|
</li>
|
||||||
{% if tdoc.rated %}
|
{% if tdoc.rated %}
|
||||||
<li class="contest-tag-rated"><span class="icon icon-star"></span>Rated</li>
|
<li class="contest-tag-rated"><span class="icon icon-star"></span>Rated</li>
|
||||||
|
|||||||
@@ -111,6 +111,10 @@
|
|||||||
<p>OI 赛制排名规则为:总分高的排在前面,总分相等则排名相同。</p>
|
<p>OI 赛制排名规则为:总分高的排在前面,总分相等则排名相同。</p>
|
||||||
<p>ACM/ICPC 赛制所有题目递交后立即评测,以是否通过为准。</p>
|
<p>ACM/ICPC 赛制所有题目递交后立即评测,以是否通过为准。</p>
|
||||||
<p>ACM/ICPC 赛制排名规则为:通过题目数多的排在前面,通过题目数相同的做题耗时(含罚时)少的排在前。</p>
|
<p>ACM/ICPC 赛制排名规则为:通过题目数多的排在前面,通过题目数相同的做题耗时(含罚时)少的排在前。</p>
|
||||||
|
<p>{{ _('Ledo') }} 赛制下,选手可以多次提交一道题目,并获得实时评测结果。</p>
|
||||||
|
<p>{{ _('Ledo') }} 赛制下,多次提交会导致选手的得分被扣除,排行榜将显示用户的最高得分。</p>
|
||||||
|
<p>{{ _('Ledo') }} 赛制下,每道题的最终得分为: $s \times \max(0.95^{n}, 0.7)$ 。$s,n$ 分别代表本次得分和本次提交前的尝试次数。</p>
|
||||||
|
<p>{{ _('Ledo') }} 排名规则为:按照如上规则折算后的分数从高到低排名。</p>
|
||||||
<p>时间与空间限制以题目说明为准,默认限制参见<a href="#limits">{{ _('Limitations') }}</a>。</p>
|
<p>时间与空间限制以题目说明为准,默认限制参见<a href="#limits">{{ _('Limitations') }}</a>。</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in new issue
Block a user