- IOI(OFS)
IOI(OFS)赛制的代码!
- 2024-10-5 22:00:39 @
const ioiObjectiveFirstSubmit = buildContestRule({
TEXT: 'IOI(ObjectiveFirstSubmit)',
submitAfterAccept: false, // 提交之后立即出结果
showScoreboard: (tdoc, now) => now > tdoc.endAt,
showSelfRecord: (tdoc, now) => now > tdoc.endAt,
showRecord: (tdoc, now) => now > tdoc.endAt && !isLocked(tdoc),
// 统计提交情况
stat(tdoc, journal) {
const display: Record<number, OiDetail> = {};
const detail: Record<number, OiDetail> = {};
const accepted: Record<number, boolean> = {};
let score = 0;
const lockAt = isLocked(tdoc) ? tdoc.lockAt : null;
for (const j of journal.filter((i) => tdoc.pids.includes(i.pid))) {
// 跳过已锁定的提交
if (lockAt && j.rid.getTimestamp() > lockAt) continue;
// 记录第一次接受的提交
if (!accepted[j.pid]) {
accepted[j.pid] = true; // 标记为已接受
detail[j.pid] = j; // 记录提交细节
display[j.pid] ||= {};
display[j.pid] = j; // 显示提交的分数
}
}
// 计算总分
for (const i in display) {
score += ((tdoc.score?.[i] || 100) * (display[i].score || 0)) / 100;
}
return { score, detail, display };
},
async scoreboardHeader(config, _, tdoc, pdict) {
const columns: ScoreboardNode[] = [
{ type: 'rank', value: '#' },
{ type: 'user', value: _('User') },
];
if (config.isExport && config.showDisplayName) {
columns.push({ type: 'email', value: _('Email') });
columns.push({ type: 'string', value: _('School') });
columns.push({ type: 'string', value: _('Name') });
columns.push({ type: 'string', value: _('Student ID') });
}
columns.push({ type: 'total_score', value: _('Total Score') });
for (let i = 1; i <= tdoc.pids.length; i++) {
const pid = tdoc.pids[i - 1];
pdict[pid].nAccept = pdict[pid].nSubmit = 0;
if (config.isExport) {
columns.push({
type: 'string',
value: '#{0} {1}'.format(i, pdict[pid].title),
});
} else {
columns.push({
type: 'problem',
value: String.fromCharCode(65 + i - 1),
raw: pid,
});
}
}
return columns;
},
async scoreboardRow(config, _, tdoc, pdict, udoc, rank, tsdoc) {
const row: ScoreboardNode[] = [
{ type: 'rank', value: rank.toString() },
{ type: 'user', value: udoc.uname, raw: tsdoc.uid },
];
if (config.isExport && config.showDisplayName) {
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 });
const tsddict = tsdoc.display || {};
for (const pid of tdoc.pids) {
const doc = tsddict[pid] || {} as Partial<OiDetail>;
const colScore = doc.score ? doc.score : 0;
row.push({
type: 'record',
value: colScore.toString(),
raw: doc.rid,
score: colScore,
});
}
return row;
},
async scoreboard(config, _, tdoc, pdict, cursor) {
const rankedTsdocs = await db.ranked(cursor, (a, b) => b.score - a.score); // 按分数降序排列
const uids = rankedTsdocs.map(([, tsdoc]) => tsdoc.uid);
const udict = await user.getListForRender(tdoc.domainId, uids, config.showDisplayName ? ['displayName'] : []);
const columns = await this.scoreboardHeader(config, _, tdoc, pdict);
const rows: ScoreboardRow[] = [
columns,
...await Promise.all(rankedTsdocs.map(
([rank, tsdoc]) => this.scoreboardRow(
config, _, tdoc, pdict, udict[tsdoc.uid], rank, tsdoc,
),
)),
];
return [rows, udict];
},
async ranked(tdoc, cursor) {
return await db.ranked(cursor, (a, b) => b.score - a.score); // 按分数降序排列
},
applyProjection(tdoc, rdoc) {
if (isDone(tdoc)) return rdoc;
delete rdoc.time;
delete rdoc.memory;
rdoc.testCases = [];
rdoc.judgeTexts = [];
delete rdoc.subtasks;
delete rdoc.score;
return rdoc;
},
});
以下是用HTML写的IOI(OFS)赛制的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IOI Objective First Submit</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.result {
margin-top: 10px;
font-weight: bold;
}
</style>
</head>
<body>
<h1>IOI (Objective First Submit) Code Submission</h1>
<!-- 提交代码的表单 -->
<form id="submitForm">
<label for="participant">Participant Name:</label>
<input type="text" id="participant" required><br><br>
<label for="code">Code Submission:</label><br>
<textarea id="code" rows="10" cols="50" placeholder="Write your code here..." required></textarea><br><br>
<button type="submit">Submit Code</button>
</form>
<!-- 评测结果 -->
<div id="result" class="result"></div>
<script>
// 存储提交状态的哈希表
const submissions = {};
// 评测代码的简单逻辑(检查是否包含 'main' 函数)
function evaluateCode(code) {
return code.includes("main");
}
// 处理表单提交
document.getElementById('submitForm').addEventListener('submit', function(event) {
event.preventDefault();
const participant = document.getElementById('participant').value.trim();
const code = document.getElementById('code').value.trim();
const resultDiv = document.getElementById('result');
// 检查是否已经提交过代码
if (submissions[participant]) {
resultDiv.innerHTML = `Participant <b>${participant}</b> has already submitted code. No further submissions allowed.`;
} else {
// 记录第一次提交
submissions[participant] = true;
// 评测代码
if (evaluateCode(code)) {
resultDiv.innerHTML = `Participant <b>${participant}</b> passed the evaluation!`;
} else {
resultDiv.innerHTML = `Participant <b>${participant}</b> failed the evaluation.`;
}
}
});
</script>
</body>
</html>