mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-22 14:08:42 +00:00
refactor(web/contest): contest manage v2 and contest confirmation
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
71901efa5f
commit
1227acf47a
@ -16,7 +16,23 @@
|
||||
$time_form = new UOJForm('time');
|
||||
$time_form->addVInput(
|
||||
'name', 'text', '比赛标题', 'New Contest',
|
||||
function($str) {
|
||||
function($name, &$vdata) {
|
||||
if ($name == '') {
|
||||
return '标题不能为空';
|
||||
}
|
||||
|
||||
if (strlen($name) > 100) {
|
||||
return '标题过长';
|
||||
}
|
||||
|
||||
$name = HTML::escape($name);
|
||||
|
||||
if ($name === '') {
|
||||
return '无效编码';
|
||||
}
|
||||
|
||||
$vdata['name'] = $name;
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
@ -35,23 +51,25 @@
|
||||
);
|
||||
$time_form->addVInput(
|
||||
'last_min', 'text', '时长(单位:分钟)', 180,
|
||||
function($str) {
|
||||
return !validateUInt($str) ? '必须为一个整数' : '';
|
||||
function($str, &$vdata) {
|
||||
if (!validateUInt($str)) {
|
||||
return '必须为一个整数';
|
||||
}
|
||||
|
||||
$vdata['last_min'] = $str;
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$time_form->handle = function(&$vdata) {
|
||||
$start_time_str = $vdata['start_time']->format('Y-m-d H:i:s');
|
||||
|
||||
$purifier = HTML::purifier_inline();
|
||||
$esc_name = DB::escape($vdata['name']);
|
||||
$esc_last_min = DB::escape($vdata['last_min']);
|
||||
|
||||
$esc_name = $_POST['name'];
|
||||
$esc_name = $purifier->purify($esc_name);
|
||||
$esc_name = DB::escape($esc_name);
|
||||
|
||||
DB::query("insert into contests (name, start_time, last_min, status) values ('$esc_name', '$start_time_str', ${_POST['last_min']}, 'unfinished')");
|
||||
DB::query("insert into contests (name, start_time, last_min, status) values ('$esc_name', '$start_time_str', $esc_last_min, 'unfinished')");
|
||||
};
|
||||
$time_form->succ_href="/contests";
|
||||
$time_form->succ_href = "/contests";
|
||||
$time_form->runAtServer();
|
||||
?>
|
||||
<?php echoUOJPageHeader('添加比赛') ?>
|
||||
|
77
web/app/controllers/contest_confirmation.php
Normal file
77
web/app/controllers/contest_confirmation.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
|
||||
if (!validateUInt($_GET['id']) || !($contest = queryContest($_GET['id']))) {
|
||||
become404Page();
|
||||
}
|
||||
|
||||
genMoreContestInfo($contest);
|
||||
|
||||
if (!Auth::check()) {
|
||||
redirectToLogin();
|
||||
} elseif (!hasRegistered($myUser, $contest)) {
|
||||
redirectTo("/contest/{$contest['id']}/register");
|
||||
} elseif ($contest['cur_progress'] < CONTEST_IN_PROGRESS) {
|
||||
redirectTo('/contests');
|
||||
} elseif (hasParticipated($myUser, $contest) || $contest['cur_progress'] > CONTEST_IN_PROGRESS) {
|
||||
redirectTo("/contest/{$contest['id']}");
|
||||
}
|
||||
|
||||
$confirm_form = new UOJForm('confirm');
|
||||
$confirm_form->submit_button_config['class_str'] = 'btn btn-primary';
|
||||
$confirm_form->submit_button_config['margin_class'] = 'mt-3';
|
||||
$confirm_form->submit_button_config['text'] = '我已核对信息,确认参加比赛';
|
||||
$confirm_form->handle = function() use ($myUser, $contest) {
|
||||
DB::update("update contests_registrants set has_participated = 1 where username = '{$myUser['username']}' and contest_id = {$contest['id']}");
|
||||
};
|
||||
$confirm_form->succ_href = "/contest/{$contest['id']}";
|
||||
$confirm_form->runAtServer();
|
||||
?>
|
||||
|
||||
<?php echoUOJPageHeader('确认参赛 - ' . HTML::stripTags($contest['name'])) ?>
|
||||
|
||||
<div class="card mw-100 mx-auto" style="width:800px">
|
||||
<div class="card-body">
|
||||
<h1 class="h2 card-title text-center mb-3">确认参赛</h1>
|
||||
|
||||
<p class="card-text text-center">您即将参加比赛 “<b><?= $contest['name'] ?></b>”,请在正式参赛前仔细核对以下比赛信息:</p>
|
||||
|
||||
<div class="table-responsive mx-auto" style="width:500px">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40%"></th>
|
||||
<th style="width:60%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center">比赛名称</td>
|
||||
<td><?= $contest['name'] ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">参赛选手</td>
|
||||
<td><?= getUserLink($myUser['username']) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">开始时间</td>
|
||||
<td><?= $contest['start_time_str'] ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">结束时间</td>
|
||||
<td><?= $contest['end_time_str'] ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">比赛赛制</td>
|
||||
<td><?= $contest['extra_config']['contest_type'] ?: 'OI' ?></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php $confirm_form->printHTML() ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
@ -12,21 +12,32 @@
|
||||
}
|
||||
genMoreContestInfo($contest);
|
||||
|
||||
if (!hasContestPermission(Auth::user(), $contest)) {
|
||||
if (!hasContestPermission($myUser, $contest)) {
|
||||
if ($contest['cur_progress'] == CONTEST_NOT_STARTED) {
|
||||
header("Location: /contest/{$contest['id']}/register");
|
||||
die();
|
||||
redirectTo("/contest/{$contest['id']}/register");
|
||||
} elseif ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {
|
||||
if ($myUser == null || !hasRegistered(Auth::user(), $contest)) {
|
||||
becomeMsgPage("<h1>比赛正在进行中</h1><p>很遗憾,您尚未报名。比赛结束后再来看吧~</p>");
|
||||
if (Auth::check()) {
|
||||
if (!hasParticipated($myUser, $contest)) {
|
||||
redirectTo("/contest/{$contest['id']}/confirm");
|
||||
}
|
||||
} else {
|
||||
redirectToLogin();
|
||||
}
|
||||
} else {
|
||||
if (!isNormalUser($myUser)) {
|
||||
if (!hasRegistered($myUser, $contest) && !isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {
|
||||
if (hasRegistered($myUser, $contest)) {
|
||||
if (!hasParticipated($myUser, $contest)) {
|
||||
redirectTo("/contest/{$contest['id']}/confirm");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isset($_GET['tab'])) {
|
||||
$cur_tab = $_GET['tab'];
|
||||
} else {
|
||||
|
@ -2,7 +2,8 @@
|
||||
if (!Auth::check()) {
|
||||
redirectToLogin();
|
||||
}
|
||||
|
||||
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
|
||||
if (!validateUInt($_GET['id']) || !($contest = queryContest($_GET['id']))) {
|
||||
@ -10,298 +11,672 @@
|
||||
}
|
||||
genMoreContestInfo($contest);
|
||||
|
||||
if (!isSuperUser($myUser)) {
|
||||
if (!hasContestPermission($myUser, $contest)) {
|
||||
become403Page();
|
||||
}
|
||||
|
||||
$time_form = new UOJForm('time');
|
||||
$time_form->addInput(
|
||||
'name', 'text', '比赛标题', $contest['name'],
|
||||
function($str) {
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$time_form->addInput(
|
||||
'start_time', 'text', '开始时间', $contest['start_time_str'],
|
||||
function($str, &$vdata) {
|
||||
try {
|
||||
$vdata['start_time'] = new DateTime($str);
|
||||
} catch (Exception $e) {
|
||||
return '无效时间格式';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$time_form->addInput(
|
||||
'last_min', 'text', '时长(单位:分钟)', $contest['last_min'],
|
||||
function($str) {
|
||||
return !validateUInt($str) ? '必须为一个整数' : '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$time_form->handle = function(&$vdata) {
|
||||
global $contest;
|
||||
$start_time_str = $vdata['start_time']->format('Y-m-d H:i:s');
|
||||
|
||||
$purifier = HTML::purifier_inline();
|
||||
|
||||
$esc_name = $_POST['name'];
|
||||
$esc_name = $purifier->purify($esc_name);
|
||||
$esc_name = DB::escape($esc_name);
|
||||
|
||||
DB::update("update contests set start_time = '$start_time_str', last_min = {$_POST['last_min']}, name = '$esc_name' where id = {$contest['id']}");
|
||||
};
|
||||
|
||||
$managers_form = newAddDelCmdForm('managers',
|
||||
function($username) {
|
||||
if (!validateUsername($username) || !queryUser($username)) {
|
||||
return "不存在名为{$username}的用户";
|
||||
}
|
||||
return '';
|
||||
},
|
||||
function($type, $username) {
|
||||
global $contest;
|
||||
|
||||
if ($type == '+') {
|
||||
DB::query("insert into contests_permissions (contest_id, username) values (${contest['id']}, '$username')");
|
||||
} elseif ($type == '-') {
|
||||
DB::query("delete from contests_permissions where contest_id = ${contest['id']} and username = '$username'");
|
||||
}
|
||||
}
|
||||
);
|
||||
if (isset($_GET['tab'])) {
|
||||
$cur_tab = $_GET['tab'];
|
||||
} else {
|
||||
$cur_tab = 'profile';
|
||||
}
|
||||
|
||||
$tabs_info = [
|
||||
'profile' => [
|
||||
'name' => '基本信息',
|
||||
'url' => "/contest/{$contest['id']}/manage/profile",
|
||||
],
|
||||
'problems' => [
|
||||
'name' => '试题',
|
||||
'url' => "/contest/{$contest['id']}/manage/problems",
|
||||
],
|
||||
'managers' => [
|
||||
'name' => '管理者',
|
||||
'url' => "/contest/{$contest['id']}/manage/managers",
|
||||
],
|
||||
'others' => [
|
||||
'name' => '其他',
|
||||
'url' => "/contest/{$contest['id']}/manage/others",
|
||||
],
|
||||
];
|
||||
|
||||
$problems_form = newAddDelCmdForm('problems',
|
||||
function($cmd) {
|
||||
if (!preg_match('/^(\d+)\s*(\[\S+\])?$/', $cmd, $matches)) {
|
||||
return "无效题号";
|
||||
}
|
||||
$problem_id = $matches[1];
|
||||
if (!validateUInt($problem_id) || !($problem = queryProblemBrief($problem_id))) {
|
||||
return "不存在题号为{$problem_id}的题";
|
||||
}
|
||||
if (!hasProblemPermission(Auth::user(), $problem)) {
|
||||
return "无权添加题号为{$problem_id}的题";
|
||||
}
|
||||
return '';
|
||||
},
|
||||
function($type, $cmd) {
|
||||
global $contest;
|
||||
|
||||
if (!preg_match('/^(\d+)\s*(\[\S+\])?$/', $cmd, $matches)) {
|
||||
return "无效题号";
|
||||
}
|
||||
|
||||
$problem_id = $matches[1];
|
||||
|
||||
if ($type == '+') {
|
||||
$dfn = DB::selectFirst("select max(dfn) from contests_problems where contest_id = {$contest['id']}")['max(dfn)'] + 1;
|
||||
DB::insert("insert into contests_problems (contest_id, problem_id, dfn) values ({$contest['id']}, '$problem_id', $dfn)");
|
||||
} elseif ($type == '-') {
|
||||
DB::delete("delete from contests_problems where contest_id = {$contest['id']} and problem_id = '$problem_id'");
|
||||
}
|
||||
|
||||
if (isset($matches[2])) {
|
||||
switch ($matches[2]) {
|
||||
case '[sample]':
|
||||
unset($contest['extra_config']["problem_$problem_id"]);
|
||||
break;
|
||||
case '[full]':
|
||||
$contest['extra_config']["problem_$problem_id"] = 'full';
|
||||
break;
|
||||
case '[no-details]':
|
||||
$contest['extra_config']["problem_$problem_id"] = 'no-details';
|
||||
break;
|
||||
if (!isset($tabs_info[$cur_tab])) {
|
||||
become404Page();
|
||||
}
|
||||
|
||||
if ($cur_tab == 'profile') {
|
||||
$profile_form = new UOJForm('time');
|
||||
$profile_form->addVInput(
|
||||
'name', 'text', '比赛标题', $contest['name'],
|
||||
function($name, &$vdata) {
|
||||
if ($name == '') {
|
||||
return '标题不能为空';
|
||||
}
|
||||
|
||||
if (strlen($name) > 100) {
|
||||
return '标题过长';
|
||||
}
|
||||
$esc_extra_config = json_encode($contest['extra_config']);
|
||||
$esc_extra_config = DB::escape($esc_extra_config);
|
||||
DB::update("update contests set extra_config = '$esc_extra_config' where id = {$contest['id']}");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (isSuperUser($myUser)) {
|
||||
$version_form = new UOJForm('version');
|
||||
$version_form->addInput('standings_version', 'text', '排名版本', $contest['extra_config']['standings_version'],
|
||||
function ($x) {
|
||||
if (!validateUInt($x) || $x < 1 || $x > 2) {
|
||||
return '不是合法的版本号';
|
||||
$name = HTML::escape($name);
|
||||
|
||||
if ($name === '') {
|
||||
return '无效编码';
|
||||
}
|
||||
|
||||
$vdata['name'] = $name;
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$profile_form->addVInput(
|
||||
'start_time', 'text', '开始时间', $contest['start_time_str'],
|
||||
function($str, &$vdata) {
|
||||
try {
|
||||
$vdata['start_time'] = new DateTime($str);
|
||||
} catch (Exception $e) {
|
||||
return '无效时间格式';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$version_form->handle = function() {
|
||||
global $contest;
|
||||
$profile_form->addVInput(
|
||||
'last_min', 'text', '时长(单位:分钟)', $contest['last_min'],
|
||||
function($str, &$vdata) {
|
||||
if (!validateUInt($str)) {
|
||||
return '必须为一个整数';
|
||||
}
|
||||
|
||||
$vdata['last_min'] = $str;
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$profile_form->handle = function(&$vdata) use ($contest) {
|
||||
$start_time_str = $vdata['start_time']->format('Y-m-d H:i:s');
|
||||
$esc_name = DB::escape($vdata['name']);
|
||||
$esc_last_min = DB::escape($vdata['last_min']);
|
||||
|
||||
DB::update("update contests set start_time = '$start_time_str', last_min = {$_POST['last_min']}, name = '$esc_name' where id = {$contest['id']}");
|
||||
|
||||
dieWithJsonData(['status' => 'success', 'message' => '修改成功']);
|
||||
};
|
||||
$profile_form->setAjaxSubmit(<<<EOD
|
||||
function(res) {
|
||||
if (res.status === 'success') {
|
||||
$('#result-alert')
|
||||
.html('比赛信息修改成功!')
|
||||
.addClass('alert-success')
|
||||
.removeClass('alert-danger')
|
||||
.show();
|
||||
} else {
|
||||
$('#result-alert')
|
||||
.html('比赛信息修改失败。' + (res.message || ''))
|
||||
.removeClass('alert-success')
|
||||
.addClass('alert-danger')
|
||||
.show();
|
||||
}
|
||||
|
||||
$(window).scrollTop(0);
|
||||
}
|
||||
EOD);
|
||||
$profile_form->runAtServer();
|
||||
} elseif ($cur_tab == 'problems') {
|
||||
if (isset($_POST['submit-remove_problem']) && $_POST['submit-remove_problem'] == 'remove_problem') {
|
||||
$problem_id = $_POST['problem_id'];
|
||||
|
||||
if (!validateUInt($problem_id)) {
|
||||
dieWithAlert('无效的题目 ID。');
|
||||
}
|
||||
|
||||
if (!queryProblemBrief($problem_id)) {
|
||||
dieWithAlert('题目不存在。');
|
||||
}
|
||||
|
||||
if (!DB::selectFirst("SELECT * FROM contests_problems WHERE contest_id = {$contest['id']} AND problem_id = $problem_id")) {
|
||||
dieWithAlert('题目不在比赛中。');
|
||||
}
|
||||
|
||||
DB::delete("DELETE FROM contests_problems WHERE contest_id = {$contest['id']} AND problem_id = $problem_id");
|
||||
|
||||
unset($contest['extra_config']["problem_$problem_id"]);
|
||||
$esc_extra_config = DB::escape(json_encode($contest['extra_config']));
|
||||
DB::update("UPDATE `contests` SET extra_config = '$esc_extra_config' WHERE id = {$contest['id']}");
|
||||
|
||||
dieWithAlert('移除成功!');
|
||||
}
|
||||
|
||||
$add_problem_form = new UOJForm('add_problem');
|
||||
$add_problem_form->addVInput('problem_id', 'text', '题目 ID', '',
|
||||
function($problem_id, &$vdata) {
|
||||
if (!validateUInt($problem_id)) {
|
||||
return '无效的题目 ID。';
|
||||
}
|
||||
|
||||
$problem = queryProblemBrief($problem_id);
|
||||
if (!$problem) {
|
||||
return '题目不存在。';
|
||||
}
|
||||
|
||||
if (!hasProblemPermission(Auth::user(), $problem)) {
|
||||
return "无权添加题目 #$problem_id。";
|
||||
}
|
||||
|
||||
$vdata['problem_id'] = $problem_id;
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$add_problem_form->addVSelect('judge_config', [
|
||||
'sample' => '只测样例',
|
||||
'no-details' => '测试全部数据,但不显示测试点详情',
|
||||
'full' => '测试全部数据',
|
||||
], '评测设置', 'sample');
|
||||
$add_problem_form->handle = function(&$vdata) use ($contest) {
|
||||
$dfn = DB::selectFirst("SELECT max(dfn) FROM contests_problems WHERE contest_id = {$contest['id']}")['max(dfn)'] + 1;
|
||||
DB::insert("INSERT INTO `contests_problems` (contest_id, problem_id, dfn) VALUES ({$contest['id']}, '{$vdata['problem_id']}', $dfn)");
|
||||
|
||||
if ($_POST['judge_config'] != 'sample') {
|
||||
$contest['extra_config']["problem_$problem_id"] = $_POST['judge_config'];
|
||||
$esc_extra_config = DB::escape(json_encode($contest['extra_config']));
|
||||
DB::update("UPDATE `contests` SET extra_config = '$esc_extra_config' WHERE id = {$contest['id']}");
|
||||
}
|
||||
|
||||
dieWithJsonData(['status' => 'success', 'message' => "题目 #{$vdata['problem_id']} 添加成功!"]);
|
||||
};
|
||||
$add_problem_form->submit_button_config['text'] = '添加';
|
||||
$add_problem_form->submit_button_config['margin_class'] = 'mt-3';
|
||||
$add_problem_form->setAjaxSubmit(<<<EOD
|
||||
function(res) {
|
||||
if (res.status === 'success') {
|
||||
$('#result-alert')
|
||||
.html('添加成功!' + (res.message || ''))
|
||||
.addClass('alert-success')
|
||||
.removeClass('alert-danger')
|
||||
.show();
|
||||
} else {
|
||||
$('#result-alert')
|
||||
.html('添加失败。' + (res.message || ''))
|
||||
.removeClass('alert-success')
|
||||
.addClass('alert-danger')
|
||||
.show();
|
||||
}
|
||||
|
||||
$(window).scrollTop(0);
|
||||
}
|
||||
EOD);
|
||||
$add_problem_form->runAtServer();
|
||||
} elseif ($cur_tab == 'managers') {
|
||||
if (isset($_POST['submit-remove_manager']) && $_POST['submit-remove_manager'] == 'remove_manager') {
|
||||
$username = $_POST['username'];
|
||||
|
||||
if (!validateUsername($username)) {
|
||||
dieWithAlert('用户名不合法。');
|
||||
}
|
||||
|
||||
if (!queryUser($username)) {
|
||||
dieWithAlert('用户不存在。');
|
||||
}
|
||||
|
||||
if (!DB::selectFirst("SELECT * FROM contests_permissions WHERE contest_id = {$contest['id']} AND username = '$username'")) {
|
||||
dieWithAlert('用户不是这场比赛的管理员。');
|
||||
}
|
||||
|
||||
DB::delete("DELETE FROM `contests_permissions` WHERE contest_id = ${contest['id']} AND username = '$username'");
|
||||
dieWithAlert('移除成功!');
|
||||
}
|
||||
|
||||
$add_manager_form = new UOJForm('add_manager');
|
||||
$add_manager_form->addVInput('username', 'text', '用户名', '',
|
||||
function($username, &$vdata) {
|
||||
if (!validateUsername($username)) {
|
||||
return '用户名不合法';
|
||||
}
|
||||
|
||||
if (!queryUser($username)) {
|
||||
return '用户不存在';
|
||||
}
|
||||
|
||||
if (DB::selectFirst("SELECT * FROM contests_permissions WHERE contest_id = {$contest['id']} AND username = '$username'")) {
|
||||
return '用户已经是这场比赛的管理员';
|
||||
}
|
||||
|
||||
$vdata['username'] = $username;
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$add_manager_form->handle = function(&$vdata) use ($contest) {
|
||||
DB::query("INSERT INTO `contests_permissions` (contest_id, username) VALUES (${contest['id']}, '{$vdata['username']}')");
|
||||
|
||||
dieWithJsonData(['status' => 'success', 'message' => '已将用户名为 ' . $vdata['username'] . ' 的用户设置为本场比赛的管理者。']);
|
||||
};
|
||||
$add_manager_form->submit_button_config['text'] = '添加';
|
||||
$add_manager_form->submit_button_config['margin_class'] = 'mt-3';
|
||||
$add_manager_form->setAjaxSubmit(<<<EOD
|
||||
function(res) {
|
||||
if (res.status === 'success') {
|
||||
$('#result-alert')
|
||||
.html('添加成功!' + (res.message || ''))
|
||||
.addClass('alert-success')
|
||||
.removeClass('alert-danger')
|
||||
.show();
|
||||
} else {
|
||||
$('#result-alert')
|
||||
.html('添加失败。' + (res.message || ''))
|
||||
.removeClass('alert-success')
|
||||
.addClass('alert-danger')
|
||||
.show();
|
||||
}
|
||||
|
||||
$(window).scrollTop(0);
|
||||
}
|
||||
EOD);
|
||||
$add_manager_form->runAtServer();
|
||||
} elseif ($cur_tab == 'others') {
|
||||
$version_form = new UOJForm('version');
|
||||
$version_form->addVSelect('standings_version', [
|
||||
'1' => '1',
|
||||
'2' => '2',
|
||||
], '比赛排名版本', $contest['extra_config']['standings_version']);
|
||||
$version_form->handle = function() use ($contest) {
|
||||
$contest['extra_config']['standings_version'] = $_POST['standings_version'];
|
||||
$esc_extra_config = json_encode($contest['extra_config']);
|
||||
$esc_extra_config = DB::escape($esc_extra_config);
|
||||
DB::update("update contests set extra_config = '$esc_extra_config' where id = {$contest['id']}");
|
||||
DB::update("UPDATE contests SET extra_config = '$esc_extra_config' WHERE id = {$contest['id']}");
|
||||
|
||||
dieWithJsonData(['status' => 'success', 'message' => '修改成功']);
|
||||
};
|
||||
$version_form->setAjaxSubmit(<<<EOD
|
||||
function(res) {
|
||||
if (res.status === 'success') {
|
||||
$('#version-result-alert')
|
||||
.html('修改成功!')
|
||||
.addClass('alert-success')
|
||||
.removeClass('alert-danger')
|
||||
.show();
|
||||
} else {
|
||||
$('#version-result-alert')
|
||||
.html('修改失败。' + (res.message || ''))
|
||||
.removeClass('alert-success')
|
||||
.addClass('alert-danger')
|
||||
.show();
|
||||
}
|
||||
|
||||
$(window).scrollTop(0);
|
||||
}
|
||||
EOD);
|
||||
$version_form->runAtServer();
|
||||
|
||||
$contest_type_form = new UOJForm('contest_type');
|
||||
$contest_type_form->addInput('contest_type', 'text', '赛制', $contest['extra_config']['contest_type'],
|
||||
function ($x) {
|
||||
if ($x != 'OI' && $x != 'ACM' && $x != 'IOI') {
|
||||
return '不是合法的赛制名';
|
||||
$contest_type_form->addVSelect('contest_type', [
|
||||
'OI' => 'OI',
|
||||
'IOI' => 'IOI'
|
||||
], '比赛类型', $contest['extra_config']['contest_type']);
|
||||
$contest_type_form->handle = function() use ($contest) {
|
||||
$contest['extra_config']['contest_type'] = $_POST['contest_type'];
|
||||
$esc_extra_config = json_encode($contest['extra_config']);
|
||||
$esc_extra_config = DB::escape($esc_extra_config);
|
||||
DB::update("UPDATE contests set extra_config = '$esc_extra_config' where id = {$contest['id']}");
|
||||
|
||||
dieWithJsonData(['status' => 'success', 'message' => '修改成功']);
|
||||
};
|
||||
$contest_type_form->setAjaxSubmit(<<<EOD
|
||||
function(res) {
|
||||
if (res.status === 'success') {
|
||||
$('#type-result-alert')
|
||||
.html('修改成功!')
|
||||
.addClass('alert-success')
|
||||
.removeClass('alert-danger')
|
||||
.show();
|
||||
} else {
|
||||
$('#type-result-alert')
|
||||
.html('修改失败。' + (res.message || ''))
|
||||
.removeClass('alert-success')
|
||||
.addClass('alert-danger')
|
||||
.show();
|
||||
}
|
||||
|
||||
$(window).scrollTop(0);
|
||||
}
|
||||
EOD);
|
||||
$contest_type_form->runAtServer();
|
||||
|
||||
$blog_link_contests = new UOJForm('blog_link_contests');
|
||||
$blog_link_contests->addVInput('blog_id', 'text', '博客 ID', '',
|
||||
function ($blog_id, &$vdata) {
|
||||
if (!validateUInt($blog_id)) {
|
||||
return 'ID 不合法';
|
||||
}
|
||||
|
||||
if (!queryBlog($blog_id)) {
|
||||
return '博客不存在';
|
||||
}
|
||||
|
||||
$vdata['blog_id'] = $blog_id;
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$contest_type_form->handle = function() {
|
||||
global $contest;
|
||||
$contest['extra_config']['contest_type'] = $_POST['contest_type'];
|
||||
$esc_extra_config = json_encode($contest['extra_config']);
|
||||
$esc_extra_config = DB::escape($esc_extra_config);
|
||||
DB::update("update contests set extra_config = '$esc_extra_config' where id = {$contest['id']}");
|
||||
};
|
||||
$contest_type_form->runAtServer();
|
||||
}
|
||||
|
||||
$time_form->runAtServer();
|
||||
$managers_form->runAtServer();
|
||||
$problems_form->runAtServer();
|
||||
$blog_link_contests->addVInput('title', 'text', '名称', '',
|
||||
function($title, &$vdata) {
|
||||
if ($title == '') {
|
||||
return '名称不能为空';
|
||||
}
|
||||
|
||||
if (strlen($title) > 40) {
|
||||
return '名称过长';
|
||||
}
|
||||
|
||||
$blog_link_contests = new UOJForm('blog_link_contests');
|
||||
$blog_link_contests->addInput('blog_link_contests__blog_id', 'text', '博客ID', '',
|
||||
function ($x) {
|
||||
if (!validateUInt($x)) {
|
||||
return 'ID不合法';
|
||||
}
|
||||
if (!queryBlog($x)) {
|
||||
return '博客不存在';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$blog_link_contests->addInput('blog_link_contests__title', 'text', '标题', '',
|
||||
function ($x) {
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$options = array(
|
||||
'add' => '添加',
|
||||
'del' => '删除'
|
||||
);
|
||||
$blog_link_contests->addSelect('blog_link_contests__op-type', $options, '操作类型', '');
|
||||
$blog_link_contests->handle = function() {
|
||||
global $contest;
|
||||
$title = HTML::escape($title);
|
||||
if ($title === '') {
|
||||
return '无效编码';
|
||||
}
|
||||
|
||||
$blog_id = $_POST['blog_link_contests__blog_id'];
|
||||
$contest_id = $contest['id'];
|
||||
$str = DB::selectFirst("select * from contests where id='${contest_id}'");
|
||||
$all_config = json_decode($str['extra_config'], true);
|
||||
$config = $all_config['links'];
|
||||
$vdata['title'] = $title;
|
||||
|
||||
$n = count($config);
|
||||
|
||||
if ($_POST['blog_link_contests__op-type'] == 'add') {
|
||||
$row = array();
|
||||
$row[0] = $_POST['blog_link_contests__title'];
|
||||
$row[1] = $blog_id;
|
||||
$config[$n] = $row;
|
||||
}
|
||||
if ($_POST['blog_link_contests__op-type'] == 'del') {
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
if ($config[$i][1] == $blog_id) {
|
||||
$config[$i] = $config[$n - 1];
|
||||
unset($config[$n - 1]);
|
||||
break;
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$blog_link_contests->addVSelect('op_type', [
|
||||
'add' => '添加',
|
||||
'del' => '移除',
|
||||
], '操作类型', '');
|
||||
$blog_link_contests->handle = function($vdata) use ($contest) {
|
||||
if ($_POST['op_type'] == 'add') {
|
||||
if (!isset($contest['extra_config']['links'])) {
|
||||
$contest['extra_config']['links'] = [];
|
||||
}
|
||||
|
||||
$contest['extra_config']['links'][] = [$vdata['title'], $vdata['blog_id']];
|
||||
} elseif ($_POST['op_type'] == 'del') {
|
||||
$n = count($contest['extra_config']['links']);
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
if ($contest['extra_config']['links'][$i][1] == $vdata['blog_id']) {
|
||||
$contest['extra_config']['links'][$i] = $contest['extra_config']['links'][$n - 1];
|
||||
unset($contest['extra_config']['links'][$n - 1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!count($contest['extra_config']['links'])) {
|
||||
unset($contest['extra_config']['links']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$esc_extra_config = json_encode($contest['extra_config']);
|
||||
$esc_extra_config = DB::escape($esc_extra_config);
|
||||
DB::update("UPDATE contests set extra_config = '$esc_extra_config' where id = {$contest['id']}");
|
||||
|
||||
$all_config['links'] = $config;
|
||||
$str = json_encode($all_config);
|
||||
$str = DB::escape($str);
|
||||
DB::query("update contests set extra_config='${str}' where id='${contest_id}'");
|
||||
};
|
||||
$blog_link_contests->runAtServer();
|
||||
|
||||
?>
|
||||
<?php echoUOJPageHeader(HTML::stripTags($contest['name']) . ' - 比赛管理') ?>
|
||||
<h1 class="page-header" align="center"><?=$contest['name']?> 管理</h1>
|
||||
<ul class="nav nav-tabs mb-3" role="tablist">
|
||||
<li class="nav-item"><a class="nav-link active" href="#tab-time" role="tab" data-toggle="tab">比赛时间</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#tab-managers" role="tab" data-toggle="tab">管理者</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#tab-problems" role="tab" data-toggle="tab">试题</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#tab-blogs" role="tab" data-toggle="tab">比赛资料</a></li>
|
||||
<?php if (isSuperUser($myUser)): ?>
|
||||
<li class="nav-item"><a class="nav-link" href="#tab-others" role="tab" data-toggle="tab">其它</a></li>
|
||||
<?php endif ?>
|
||||
<li class="nav-item"><a class="nav-link" href="/contest/<?=$contest['id']?>" role="tab">返回</a></li>
|
||||
</ul>
|
||||
<div class="tab-content top-buffer-sm">
|
||||
<div class="tab-pane active" id="tab-time">
|
||||
<?php $time_form->printHTML(); ?>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="tab-managers">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>用户名</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$row_id = 0;
|
||||
$result = DB::query("select username from contests_permissions where contest_id = {$contest['id']}");
|
||||
while ($row = DB::fetch($result, MYSQLI_ASSOC)) {
|
||||
$row_id++;
|
||||
echo '<tr>', '<td>', $row_id, '</td>', '<td>', getUserLink($row['username']), '</td>', '</tr>';
|
||||
dieWithJsonData(['status' => 'success', 'message' => '修改成功']);
|
||||
};
|
||||
$blog_link_contests->setAjaxSubmit(<<<EOD
|
||||
function(res) {
|
||||
if (res.status === 'success') {
|
||||
$('#blogs-result-alert')
|
||||
.html('操作成功!')
|
||||
.addClass('alert-success')
|
||||
.removeClass('alert-danger')
|
||||
.show();
|
||||
} else {
|
||||
$('#blogs-result-alert')
|
||||
.html('操作失败。' + (res.message || ''))
|
||||
.removeClass('alert-success')
|
||||
.addClass('alert-danger')
|
||||
.show();
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="text-center">命令格式:命令一行一个,+mike表示把mike加入管理者,-mike表示把mike从管理者中移除</p>
|
||||
<?php $managers_form->printHTML(); ?>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="tab-problems">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>试题名</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$result = DB::query("select problem_id from contests_problems where contest_id = ${contest['id']} order by dfn, problem_id");
|
||||
while ($row = DB::fetch($result, MYSQLI_ASSOC)) {
|
||||
$problem = queryProblemBrief($row['problem_id']);
|
||||
$problem_config_str = isset($contest['extra_config']["problem_{$problem['id']}"]) ? $contest['extra_config']["problem_{$problem['id']}"] : 'sample';
|
||||
echo '<tr>', '<td>', $problem['id'], '</td>', '<td>', getProblemLink($problem), ' ', "[$problem_config_str]", '</td>', '</tr>';
|
||||
|
||||
$(window).scrollTop(0);
|
||||
}
|
||||
EOD);
|
||||
$blog_link_contests->runAtServer();
|
||||
}
|
||||
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="text-center">命令格式:命令一行一个,+233表示把题号为233的试题加入比赛,-233表示把题号为233的试题从比赛中移除</p>
|
||||
<?php $problems_form->printHTML(); ?>
|
||||
<?php echoUOJPageHeader(HTML::stripTags('比赛管理 - ' . $contest['name'])) ?>
|
||||
<h1 class="h2">
|
||||
<?= $contest['name'] ?>
|
||||
<small class="fs-5">(ID: <?= $contest['id'] ?>)</small>
|
||||
管理
|
||||
</h1>
|
||||
|
||||
<div class="row mt-4">
|
||||
<!-- left col -->
|
||||
<div class="col-md-3">
|
||||
|
||||
<?= HTML::navListGroup($tabs_info, $cur_tab) ?>
|
||||
|
||||
<a
|
||||
class="btn btn-light d-block mt-2 w-100 text-start text-primary"
|
||||
style="--bs-btn-hover-bg: #d3d4d570; --bs-btn-hover-border-color: transparent;"
|
||||
href="<?= HTML::url("/contest/{$contest['id']}") ?>">
|
||||
<i class="bi bi-arrow-left"></i> 返回
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<!-- end left col -->
|
||||
|
||||
<!-- right col -->
|
||||
<div class="col-md-9">
|
||||
|
||||
<?php if ($cur_tab == 'profile'): ?>
|
||||
<div class="card mt-3 mt-md-0">
|
||||
<div class="card-body">
|
||||
<div id="result-alert" class="alert" role="alert" style="display: none"></div>
|
||||
<div class="row row-cols-1 row-cols-md-2">
|
||||
<div class="col">
|
||||
<?php $profile_form->printHTML(); ?>
|
||||
</div>
|
||||
<div class="col mt-3 mt-md-0">
|
||||
<h5>注意事项</h5>
|
||||
<ul class="mb-0">
|
||||
<li>请为选手预留合理的做题时间。一般而言,CSP 和 NOIP 的比赛时长为 4 小时,省选 / NOI 的比赛时长为 5 小时。</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="tab-blogs">
|
||||
<?php $blog_link_contests->printHTML(); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php elseif ($cur_tab == 'problems'): ?>
|
||||
<div class="card mt-3 mt-md-0">
|
||||
<div class="card-header">
|
||||
<ul class="nav nav-tabs card-header-tabs" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#problems" data-bs-toggle="tab" data-bs-target="#problems">题目列表</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#add-problem" data-bs-toggle="tab" data-bs-target="#add-problem">添加题目</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<?php if (isSuperUser($myUser)): ?>
|
||||
<div class="tab-pane" id="tab-others">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 top-buffer-sm">
|
||||
<h3>版本控制</h3>
|
||||
<?php $version_form->printHTML(); ?>
|
||||
</div>
|
||||
<div class="col-sm-12 top-buffer-sm">
|
||||
<h3>赛制</h3>
|
||||
<?php $contest_type_form->printHTML(); ?>
|
||||
<div class="card-body tab-content">
|
||||
<div class="tab-pane active" id="problems">
|
||||
<?php
|
||||
echoLongTable(
|
||||
['*'],
|
||||
'contests_problems',
|
||||
"contest_id = '{$contest['id']}'",
|
||||
'ORDER BY dfn, problem_id',
|
||||
<<<EOD
|
||||
<tr>
|
||||
<th style="width:3em">ID</th>
|
||||
<th>标题</th>
|
||||
<th style="width:8em">评测设置</th>
|
||||
<th style="width:6em">操作</th>
|
||||
</tr>
|
||||
EOD,
|
||||
function($row) {
|
||||
$problem = queryProblemBrief($row['problem_id']);
|
||||
echo '<tr>';
|
||||
echo '<td>', $row['problem_id'], '</td>';
|
||||
echo '<td>', getProblemLink($problem), '</td>';
|
||||
echo '<td>', isset($contest['extra_config']["problem_{$problem['id']}"]) ? $contest['extra_config']["problem_{$problem['id']}"] : 'sample', '</td>';
|
||||
echo '<td>';
|
||||
echo '<form class="d-inline-block" method="POST" target="_self" onsubmit=\'return confirm("你确定要将题目 #', $problem['id'], ' 从比赛中移除吗?")\'>';
|
||||
echo '<input type="hidden" name="_token" value="', crsf_token(),'">';
|
||||
echo '<input type="hidden" name="problem_id" value="', $problem['id'], '">';
|
||||
echo '<button type="submit" class="btn btn-link text-danger text-decoration-none p-0" name="submit-remove_problem" value="remove_problem">移除</button>';
|
||||
echo '</form>';
|
||||
echo '</td>';
|
||||
echo '</tr>';
|
||||
},
|
||||
[
|
||||
'echo_full' => true,
|
||||
'div_classes' => ['table-responsive'],
|
||||
'table_classes' => ['table', 'align-middle'],
|
||||
]
|
||||
)
|
||||
?>
|
||||
</div>
|
||||
<div class="tab-pane" id="add-problem">
|
||||
<div id="result-alert" class="alert" role="alert" style="display: none"></div>
|
||||
<div class="row row-cols-1 row-cols-md-2">
|
||||
<div class="col">
|
||||
<?php $add_problem_form->printHTML() ?>
|
||||
</div>
|
||||
<div class="col">
|
||||
<h5>注意事项</h5>
|
||||
<ul class="mt-0">
|
||||
<li>推荐在比赛结束前将题目设置为隐藏。</li>
|
||||
<li>对于「评测设置」选项,一般情况下保持默认(即只测样例)即可。</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php elseif ($cur_tab == 'managers'): ?>
|
||||
<div class="card mt-3 mt-md-0">
|
||||
<div class="card-header">
|
||||
<ul class="nav nav-tabs card-header-tabs" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#managers" data-bs-toggle="tab" data-bs-target="#managers">管理者列表</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#add-manager" data-bs-toggle="tab" data-bs-target="#add-manager">添加管理者</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-body tab-content">
|
||||
<div class="tab-pane active" id="managers">
|
||||
<?php
|
||||
echoLongTable(
|
||||
['*'],
|
||||
'contests_permissions',
|
||||
"contest_id = {$contest['id']}",
|
||||
'ORDER BY username',
|
||||
<<<EOD
|
||||
<tr>
|
||||
<th>用户名</th>
|
||||
<th style="width:6em">操作</th>
|
||||
</tr>
|
||||
EOD,
|
||||
function ($row) {
|
||||
echo '<tr>';
|
||||
echo '<td>', getUserLink($row['username']), '</td>';
|
||||
echo '<td>';
|
||||
echo '<form method="POST" target="_self" class="d-inline-block" onsubmit=\'return confirm("你确定要将 ', $row['username'], ' 从比赛管理员列表中移除吗?")\'>';
|
||||
echo '<input type="hidden" name="_token" value="', crsf_token(), '">';
|
||||
echo '<input type="hidden" name="username" value="', $row['username'], '">';
|
||||
echo '<button type="submit" class="btn btn-link text-danger text-decoration-none p-0" name="submit-remove_manager" value="remove_manager">移除</button>';
|
||||
echo '</form>';
|
||||
echo '</td>';
|
||||
echo '</tr>';
|
||||
},
|
||||
[
|
||||
'echo_full' => true,
|
||||
'div_classes' => ['table-responsive'],
|
||||
'table_classes' => ['table'],
|
||||
]
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<div class="tab-pane" id="add-manager">
|
||||
<div id="result-alert" class="alert" role="alert" style="display: none"></div>
|
||||
<div class="row row-cols-1 row-cols-md-2">
|
||||
<div class="col">
|
||||
<?php $add_manager_form->printHTML(); ?>
|
||||
</div>
|
||||
<div class="col mt-3 mt-md-0">
|
||||
<h5>注意事项</h5>
|
||||
<ul class="mb-0">
|
||||
<li>添加管理者前请确认用户名是否正确以免带来不必要的麻烦。</li>
|
||||
<li>比赛管理者如果报名了比赛仍可以正常参赛,但不报名比赛也可以查看并管理本场比赛。</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php elseif ($cur_tab == 'others'): ?>
|
||||
<div class="card mt-3 mt-md-0">
|
||||
<div class="card-header">
|
||||
<ul class="nav nav-tabs card-header-tabs" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#type" data-bs-toggle="tab" data-bs-target="#type">赛制管理</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#standings-version" data-bs-toggle="tab" data-bs-target="#standings-version">排名版本</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#blogs" data-bs-toggle="tab" data-bs-target="#blogs">比赛资料</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-body tab-content">
|
||||
<div class="tab-pane active" id="type">
|
||||
<div id="type-result-alert" class="alert" role="alert" style="display: none"></div>
|
||||
<div class="row row-cols-1 row-cols-md-2">
|
||||
<div class="col">
|
||||
<?php $contest_type_form->printHTML(); ?>
|
||||
</div>
|
||||
<div class="col mt-3 mt-md-0">
|
||||
<h5>注意事项</h5>
|
||||
<ul class="mb-0">
|
||||
<li>目前 S2OJ 支持 OI 和 IOI 赛制。</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="standings-version">
|
||||
<div id="version-result-alert" class="alert" role="alert" style="display: none"></div>
|
||||
<div class="row row-cols-1 row-cols-md-2">
|
||||
<div class="col">
|
||||
<?php $version_form->printHTML(); ?>
|
||||
</div>
|
||||
<div class="col mt-3 mt-md-0">
|
||||
<h5>注意事项</h5>
|
||||
<ul class="mb-0">
|
||||
<li>正常情况下无需调整此项设置。</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="blogs">
|
||||
<div id="blogs-result-alert" class="alert" role="alert" style="display: none"></div>
|
||||
<div class="row row-cols-1 row-cols-md-2">
|
||||
<div class="col">
|
||||
<?php $blog_link_contests->printHTML(); ?>
|
||||
</div>
|
||||
<div class="col mt-3 mt-md-0">
|
||||
<h5>注意事项</h5>
|
||||
<ul class="mb-0">
|
||||
<li>添加比赛资料前请确认博客是否处于公开状态。</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<!-- end right col -->
|
||||
</div>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -183,7 +183,7 @@
|
||||
<?php if ($iHasRegistered): ?>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<a style="color:green">已报名</a>
|
||||
<a class="text-decoration-none text-success">已报名</a>
|
||||
</div>
|
||||
<div class="col-6 text-end">
|
||||
<?php $unregister_form->printHTML(); ?>
|
||||
@ -199,16 +199,6 @@
|
||||
$header_row = '<tr><th>#</th><th>'.UOJLocale::get('username').'</th>';
|
||||
if ($show_ip) {
|
||||
$header_row .= '<th>remote_addr</th><th>http_x_forwarded_for</th>';
|
||||
|
||||
$ip_owner = array();
|
||||
$forwarded_ip_owner = array();
|
||||
$has_participated = array();
|
||||
foreach (DB::selectAll("select * from contests_registrants where contest_id = {$contest['id']} order by username desc") as $reg) {
|
||||
$user = queryUser($reg['username']);
|
||||
$ip_owner[$user['remote_addr']] = $reg['username'];
|
||||
$forwarded_ip_owner[$user['http_x_forwarded_for']] = $reg['username'];
|
||||
$has_participated[$reg['username']] = $reg['has_participated'];
|
||||
}
|
||||
}
|
||||
if ($has_contest_permission) {
|
||||
$header_row .= '<th>是否参赛</th>';
|
||||
@ -221,18 +211,10 @@
|
||||
"contest_id = {$contest['id']}",
|
||||
'order by username desc',
|
||||
$header_row,
|
||||
function($contestant, $num) use ($myUser, $has_contest_permission, $show_ip, $ip_owner, $has_participated) {
|
||||
function($contestant, $num) use ($myUser, $has_contest_permission, $show_ip, $has_participated) {
|
||||
$user = queryUser($contestant['username']);
|
||||
|
||||
if (!$show_ip) {
|
||||
echo '<tr>';
|
||||
} else {
|
||||
if ($ip_owner[$user['remote_addr']] != $user['username'] || $forwarded_ip_owner[$user['http_x_forwarded_for']] != $user['username']) {
|
||||
echo '<tr class="table-danger">';
|
||||
} else {
|
||||
echo '<tr>';
|
||||
}
|
||||
}
|
||||
echo '<tr>';
|
||||
echo '<td>'.$num.'</td>';
|
||||
echo '<td>'.getUserLink($contestant['username']).'</td>';
|
||||
if ($show_ip) {
|
||||
|
@ -1,42 +1,73 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
|
||||
if (!validateUInt($_GET['id']) || !($contest = queryContest($_GET['id']))) {
|
||||
become404Page();
|
||||
}
|
||||
|
||||
|
||||
genMoreContestInfo($contest);
|
||||
|
||||
if (!Auth::check()) {
|
||||
redirectToLogin();
|
||||
} elseif (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
} elseif (hasRegistered($myUser, $contest) || $contest['cur_progress'] != CONTEST_NOT_STARTED) {
|
||||
redirectTo('/contests');
|
||||
} elseif (hasRegistered($myUser, $contest)) {
|
||||
if ($contest['cur_progress'] < CONTEST_IN_PROGRESS) {
|
||||
redirectTo('/contests');
|
||||
} elseif ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {
|
||||
redirectTo("/contest/{$contest['id']}/confirm");
|
||||
} else {
|
||||
redirectTo("/contest/{$contest['id']}");
|
||||
}
|
||||
} elseif ($contest['cur_progress'] > CONTEST_IN_PROGRESS) {
|
||||
redirectTo("/contest/{$contest['id']}");
|
||||
}
|
||||
|
||||
$register_form = new UOJForm('register');
|
||||
$register_form->handle = function() {
|
||||
global $myUser, $contest;
|
||||
$register_form->handle = function() use ($myUser, $contest) {
|
||||
DB::query("replace into contests_registrants (username, contest_id, has_participated) values ('{$myUser['username']}', {$contest['id']}, 0)");
|
||||
|
||||
updateContestPlayerNum($contest);
|
||||
};
|
||||
$register_form->submit_button_config['class_str'] = 'btn btn-primary';
|
||||
$register_form->submit_button_config['text'] = '报名比赛';
|
||||
$register_form->succ_href = "/contests";
|
||||
$register_form->submit_button_config['text'] = '我已阅读规则,确认报名比赛';
|
||||
|
||||
if ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {
|
||||
$register_form->succ_href = "/contest/{$contest['id']}/confirm";
|
||||
} else {
|
||||
$register_form->succ_href = "/contests";
|
||||
}
|
||||
|
||||
$register_form->runAtServer();
|
||||
?>
|
||||
<?php echoUOJPageHeader(HTML::stripTags($contest['name']) . ' - 报名') ?>
|
||||
<h1 class="page-header">比赛规则</h1>
|
||||
<ul>
|
||||
<li>比赛报名后不算正式参赛,报名后进了比赛页面也不算参赛,<strong>看了题目才算正式参赛</strong>。</li>
|
||||
<li>比赛中途可以提交,若同一题有多次提交按<strong>最后一次不是 Compile Error 的提交</strong>算成绩。(其实UOJ会自动无视你所有 Compile Error 的提交)</li>
|
||||
<li>比赛中途提交后,可以看到<strong>测样例</strong>的结果。(若为提交答案题则对于每个测试点,该测试点有分则该测试点为满分)</li>
|
||||
<li>比赛结束后会进行最终测试,最终测试后的排名为最终排名。</li>
|
||||
<li>比赛排名按分数为第一关键字,完成题目的总时间为第二关键字。完成题目的总时间等于完成每道题所花时间之和(无视掉爆零的题目)。</li>
|
||||
<li>请遵守比赛规则,一位选手在一场比赛内不得报名多个账号,选手之间不能交流或者抄袭代码,如果被检测到将以 0 分处理或者封禁。</li>
|
||||
</ul>
|
||||
<?php $register_form->printHTML(); ?>
|
||||
<?php echoUOJPageHeader('报名 - ' . HTML::stripTags($contest['name'])) ?>
|
||||
|
||||
<div class="card mw-100 mx-auto" style="width:800px">
|
||||
<div class="card-body">
|
||||
<h1 class="h2 card-title text-center mb-3">比赛规则</h1>
|
||||
|
||||
<p class="card-text">您即将报名比赛 “<b><?= $contest['name'] ?></b>”,请在报名前仔细阅读以下比赛规则:</p>
|
||||
|
||||
<ul>
|
||||
<?php if ($contest['cur_progress'] == CONTEST_IN_PROGRESS): ?>
|
||||
<li class="text-danger">本场比赛正在进行中,将于 <b><?= $contest['end_time_str'] ?></b> 结束。</li>
|
||||
<?php else: ?>
|
||||
<li>本场比赛将于 <b><?= $contest['start_time_str'] ?></b> 开始,并于 <b><?= $contest['end_time_str'] ?></b> 结束。</li>
|
||||
<?php endif ?>
|
||||
<li>比赛开始后点击 “<b>确认参赛</b>” 按钮才会被视为正式参赛,未正式参赛的选手不会显示在排行榜上。</li>
|
||||
<?php if (!isset($contest['extra_config']['contest_type']) || $contest['extra_config']['contest_type'] == 'OI'): ?>
|
||||
<li>本场比赛为 OI 赛制。比赛中途可以提交代码,但 <b>只显示测样例的结果</b>。</li>
|
||||
<?php elseif ($contest['extra_config']['contest_type'] == 'IOI'): ?>
|
||||
<li>本场比赛为 IOI 赛制。比赛时的提交会测试题目的全部数据,但无法查看数据点详情。</li>
|
||||
<?php endif ?>
|
||||
<li>若选手在比赛中多次提交了同一题,则最后按照 <b>最后一次不是 Compile Error 的提交</b> 计算排行。</li>
|
||||
<li>比赛结束后会进行最终测试,最终测试后的排名为最终排名。</li>
|
||||
<li>比赛排名按分数为第一关键字,完成题目的总时间为第二关键字。完成题目的总时间等于完成每道题所花时间之和(无视掉爆零的题目)。</li>
|
||||
<li>请遵守比赛规则,一位选手在一场比赛内不得报名多个账号,选手之间不能交流或者抄袭代码,如果被检测到将以 0 分处理或者封禁。</li>
|
||||
</ul>
|
||||
|
||||
<?php $register_form->printHTML() ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -24,18 +24,22 @@ EOD;
|
||||
$rest_second = $cur_rest_second;
|
||||
}
|
||||
if ($myUser != null && hasRegistered($myUser, $contest)) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:green">'.UOJLocale::get('contests::registered').'</a></sup>';
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:green">'.UOJLocale::get('contests::registered').'</a></sup>';
|
||||
} else {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:red" href="/contest/'.$contest['id'].'/register">'.UOJLocale::get('contests::register').'</a></sup>';
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:red" href="/contest/'.$contest['id'].'/register">'.UOJLocale::get('contests::register').'</a></sup>';
|
||||
}
|
||||
} elseif ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:blue" href="/contest/'.$contest['id'].'">'.UOJLocale::get('contests::in progress').'</a></sup>';
|
||||
if (hasRegistered($myUser, $contest)) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:blue" href="/contest/'.$contest['id'].'">'.UOJLocale::get('contests::in progress').'</a></sup>';
|
||||
} else {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:blue" href="/contest/'.$contest['id'].'/register">'.UOJLocale::get('contests::in progress').'</a></sup>';
|
||||
}
|
||||
} elseif ($contest['cur_progress'] == CONTEST_PENDING_FINAL_TEST) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:blue" href="/contest/'.$contest['id'].'">'.UOJLocale::get('contests::pending final test').'</a></sup>';
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:blue" href="/contest/'.$contest['id'].'">'.UOJLocale::get('contests::pending final test').'</a></sup>';
|
||||
} elseif ($contest['cur_progress'] == CONTEST_TESTING) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:blue" href="/contest/'.$contest['id'].'">'.UOJLocale::get('contests::final testing').'</a></sup>';
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:blue" href="/contest/'.$contest['id'].'">'.UOJLocale::get('contests::final testing').'</a></sup>';
|
||||
} elseif ($contest['cur_progress'] == CONTEST_FINISHED) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:grey" href="/contest/'.$contest['id'].'/standings">'.UOJLocale::get('contests::ended').'</a></sup>';
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:grey" href="/contest/'.$contest['id'].'/standings">'.UOJLocale::get('contests::ended').'</a></sup>';
|
||||
}
|
||||
|
||||
$last_hour = round($contest['last_min'] / 60, 2);
|
||||
|
@ -407,7 +407,7 @@ EOD,
|
||||
echo '<tr>';
|
||||
|
||||
echo '<td class="text-center">', $row['id'], '</td>';
|
||||
echo '<td>', '<a class="text-decoration-none" href="', HTML::url('/problem/' . $row['id']),'">', $row['title'], '</a>';
|
||||
echo '<td>', getProblemLink($row);
|
||||
if ($row['is_hidden']) {
|
||||
echo ' <span class="badge text-bg-danger"><i class="bi bi-eye-slash-fill"></i> ', UOJLocale::get('hidden'), '</span> ';
|
||||
}
|
||||
|
@ -33,19 +33,31 @@
|
||||
if ($contest['cur_progress'] == CONTEST_NOT_STARTED) {
|
||||
become404Page();
|
||||
} elseif ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {
|
||||
if ($myUser == null || !hasRegistered($myUser, $contest)) {
|
||||
becomeMsgPage("<h1>比赛正在进行中</h1><p>很遗憾,您尚未报名。比赛结束后再来看吧~</p>");
|
||||
if (Auth::check()) {
|
||||
if (hasParticipated($myUser, $contest)) {
|
||||
$is_in_contest = true;
|
||||
} else {
|
||||
redirectTo("/contest/{$contest['id']}/confirm");
|
||||
}
|
||||
} else {
|
||||
$is_in_contest = true;
|
||||
DB::update("update contests_registrants set has_participated = 1 where username = '{$myUser['username']}' and contest_id = {$contest['id']}");
|
||||
redirectToLogin();
|
||||
}
|
||||
} else {
|
||||
$ban_in_contest = !isProblemVisibleToUser($problem, $myUser);
|
||||
|
||||
if (!hasRegistered($myUser, $contest) && !isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {
|
||||
$is_in_contest = true;
|
||||
DB::update("update contests_registrants set has_participated = 1 where username = '{$myUser['username']}' and contest_id = {$contest['id']}");
|
||||
if (hasRegistered($myUser, $contest)) {
|
||||
if (hasParticipated($myUser, $contest)) {
|
||||
$is_in_contest = true;
|
||||
} else {
|
||||
redirectTo("/contest/{$contest['id']}/confirm");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -10,6 +10,7 @@ function genMoreContestInfo(&$contest) {
|
||||
$contest['start_time'] = new DateTime($contest['start_time']);
|
||||
$contest['end_time'] = clone $contest['start_time'];
|
||||
$contest['end_time']->add(new DateInterval("PT${contest['last_min']}M"));
|
||||
$contest['end_time_str'] = $contest['end_time']->format('Y-m-d H:i:s');
|
||||
|
||||
if ($contest['status'] == 'unfinished') {
|
||||
if (UOJTime::$time_now < $contest['start_time']) {
|
||||
|
@ -31,7 +31,8 @@ Route::group([
|
||||
Route::any('/contest/{id}', '/contest_inside.php');
|
||||
Route::any('/contest/{id}/registrants', '/contest_members.php');
|
||||
Route::any('/contest/{id}/register', '/contest_registration.php');
|
||||
Route::any('/contest/{id}/manage', '/contest_manage.php');
|
||||
Route::any('/contest/{id}/confirm', '/contest_confirmation.php');
|
||||
Route::any('/contest/{id}/manage(?:/{tab})?', '/contest_manage.php');
|
||||
Route::any('/contest/{id}/submissions', '/contest_inside.php?tab=submissions');
|
||||
Route::any('/contest/{id}/standings', '/contest_inside.php?tab=standings');
|
||||
Route::any('/contest/{id}/after_contest_standings', '/contest_inside.php?tab=after_contest_standings');
|
||||
|
@ -1144,7 +1144,7 @@ function showStandings(config) {
|
||||
var col_tr = '<tr>';
|
||||
col_tr += '<td>' + row[3] + '</td>';
|
||||
col_tr += '<td>' + getUserLink(row[2][0], row[2][1]) + '</td>';
|
||||
col_tr += '<td>' + '<div><span class="uoj-score" data-max="' + problems.length * 100 + '" style="color:' + getColOfScore(row[0] / problems.length) + '">' + row[0] + '</span></div>' + '<div>' + (row[1] == 0 ? '(未提交)' : getPenaltyTimeStr(row[1])) + '</div></td>';
|
||||
col_tr += '<td>' + '<div><span class="uoj-score" data-max="' + problems.length * 100 + '" style="color:' + getColOfScore(row[0] / problems.length) + '">' + row[0] + '</span></div>' + '<div>' + getPenaltyTimeStr(row[1]) + '</div></td>';
|
||||
for (var i = 0; i < problems.length; i++) {
|
||||
col_tr += '<td' + (show_self_reviews ? ' style="vertical-align: text-top"' : '') + '>';
|
||||
col = score[row[2][0]][i];
|
||||
|
Loading…
Reference in New Issue
Block a user