2016-07-18 16:39:37 +00:00
|
|
|
|
<?php
|
2022-11-06 02:26:21 +00:00
|
|
|
|
if (!Auth::check()) {
|
|
|
|
|
redirectToLogin();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
requireLib('bootstrap5');
|
|
|
|
|
requirePHPLib('form');
|
|
|
|
|
requirePHPLib('judger');
|
|
|
|
|
requirePHPLib('data');
|
|
|
|
|
|
|
|
|
|
UOJProblem::init(UOJRequest::get('id')) || UOJResponse::page404();
|
|
|
|
|
UOJProblem::cur()->userCanManage(Auth::user()) || UOJResponse::page403();
|
2023-01-19 08:06:42 +00:00
|
|
|
|
UOJProblem::info('type') === 'local' || UOJResponse::page404();
|
2023-02-02 06:25:39 +00:00
|
|
|
|
|
|
|
|
|
$tabs_info = [
|
|
|
|
|
'statement' => [
|
|
|
|
|
'name' => '题面',
|
|
|
|
|
'url' => UOJProblem::cur()->getUri('/manage/statement'),
|
|
|
|
|
],
|
|
|
|
|
'permissions' => [
|
|
|
|
|
'name' => '权限',
|
|
|
|
|
'url' => UOJProblem::cur()->getUri('/manage/permissions'),
|
|
|
|
|
],
|
|
|
|
|
'data' => [
|
|
|
|
|
'name' => '数据',
|
|
|
|
|
'url' => UOJProblem::cur()->getUri('/manage/data'),
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$problem = UOJProblem::info();
|
|
|
|
|
$problem_extra_config = UOJProblem::cur()->getExtraConfig();
|
|
|
|
|
|
2023-01-17 07:40:32 +00:00
|
|
|
|
$data_dir = "/var/uoj_data/{$problem['id']}";
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
|
|
|
|
function echoFileNotFound($file_name) {
|
|
|
|
|
echo '<h5>', htmlspecialchars($file_name), '</h5>';
|
|
|
|
|
echo '<div class="small text-danger"> ', '文件未找到', '</div>';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function echoFilePre($file_name) {
|
|
|
|
|
global $data_dir;
|
|
|
|
|
$file_full_name = $data_dir . '/' . $file_name;
|
|
|
|
|
|
|
|
|
|
$finfo = finfo_open(FILEINFO_MIME);
|
|
|
|
|
$mimetype = finfo_file($finfo, $file_full_name);
|
|
|
|
|
if ($mimetype === false) {
|
|
|
|
|
echoFileNotFound($file_name);
|
|
|
|
|
return;
|
2022-03-17 04:00:03 +00:00
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
finfo_close($finfo);
|
2022-04-03 10:18:17 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
echo '<h5 class="mb-1">', htmlspecialchars($file_name), '</h5>';
|
|
|
|
|
echo '<div class="text-muted small mb-1 font-monospace">', $mimetype, '</div>';
|
|
|
|
|
echo '<pre class="bg-light rounded uoj-pre">', "\n";
|
2022-04-03 10:18:17 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$output_limit = 1000;
|
|
|
|
|
if (strStartWith($mimetype, 'text/')) {
|
|
|
|
|
echo htmlspecialchars(uojFilePreview($file_full_name, $output_limit));
|
|
|
|
|
} else {
|
|
|
|
|
echo htmlspecialchars(uojFilePreview($file_full_name, $output_limit, 'binary'));
|
2016-07-18 16:39:37 +00:00
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
echo "\n</pre>";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 上传数据
|
|
|
|
|
if ($_POST['problem_data_file_submit'] == 'submit') {
|
|
|
|
|
if ($_FILES["problem_data_file"]["error"] > 0) {
|
|
|
|
|
$errmsg = "Error: " . $_FILES["problem_data_file"]["error"];
|
|
|
|
|
becomeMsgPage('<div>' . $errmsg . '</div><a href="/problem/' . $problem['id'] . '/manage/data">返回</a>');
|
|
|
|
|
} else {
|
|
|
|
|
$zip_mime_types = array('application/zip', 'application/x-zip', 'application/x-zip-compressed');
|
|
|
|
|
if (in_array($_FILES["problem_data_file"]["type"], $zip_mime_types) || $_FILES["problem_data_file"]["type"] == 'application/octet-stream' && substr($_FILES["problem_data_file"]["name"], -4) == '.zip') {
|
|
|
|
|
$up_filename = "/tmp/" . rand(0, 100000000) . "data.zip";
|
|
|
|
|
move_uploaded_file($_FILES["problem_data_file"]["tmp_name"], $up_filename);
|
|
|
|
|
$zip = new ZipArchive;
|
|
|
|
|
if ($zip->open($up_filename) === TRUE) {
|
|
|
|
|
$zip->extractTo("/var/uoj_data/upload/{$problem['id']}");
|
|
|
|
|
$zip->close();
|
2022-11-09 13:37:37 +00:00
|
|
|
|
exec("cd /var/uoj_data/upload/{$problem['id']}; if [ -z \"`find . -maxdepth 1 -type f`\" ]; then for sub_dir in `find -maxdepth 1 -type d ! -name .`; do mv -f \$sub_dir/* . && rm -rf \$sub_dir; done; fi");
|
2022-11-06 02:26:21 +00:00
|
|
|
|
echo "<script>alert('上传成功!')</script>";
|
|
|
|
|
} else {
|
|
|
|
|
$errmsg = "解压失败!";
|
|
|
|
|
becomeMsgPage('<div>' . $errmsg . '</div><a href="/problem/' . $problem['id'] . '/manage/data">返回</a>');
|
|
|
|
|
}
|
|
|
|
|
unlink($up_filename);
|
|
|
|
|
} else {
|
|
|
|
|
$errmsg = "请上传zip格式!";
|
|
|
|
|
becomeMsgPage('<div>' . $errmsg . '</div><a href="/problem/' . $problem['id'] . '/manage/data">返回</a>');
|
|
|
|
|
}
|
2016-07-18 16:39:37 +00:00
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$info_form = new UOJForm('info');
|
2022-11-11 23:10:34 +00:00
|
|
|
|
$attachment_url = UOJProblem::cur()->getAttachmentUri();
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$info_form->appendHTML(<<<EOD
|
2022-09-20 05:10:25 +00:00
|
|
|
|
<div class="form-group row">
|
|
|
|
|
<label class="col-sm-3 control-label">problem_{$problem['id']}_attachment.zip</label>
|
|
|
|
|
<div class="col-sm-9">
|
|
|
|
|
<div class="form-control-static">
|
2022-10-18 06:47:03 +00:00
|
|
|
|
<a class="text-decoration-none" href="$attachment_url">$attachment_url</a>
|
2022-09-20 05:10:25 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-02-01 11:36:27 +00:00
|
|
|
|
EOD);
|
2022-11-11 23:10:34 +00:00
|
|
|
|
$download_url = UOJProblem::cur()->getMainDataUri();
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$info_form->appendHTML(<<<EOD
|
2019-09-10 02:15:20 +00:00
|
|
|
|
<div class="form-group row">
|
2016-07-18 16:39:37 +00:00
|
|
|
|
<label class="col-sm-3 control-label">problem_{$problem['id']}.zip</label>
|
|
|
|
|
<div class="col-sm-9">
|
|
|
|
|
<div class="form-control-static">
|
2022-10-18 06:47:03 +00:00
|
|
|
|
<a class="text-decoration-none" href="$download_url">$download_url</a>
|
2016-07-18 16:39:37 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-02-01 11:36:27 +00:00
|
|
|
|
EOD);
|
|
|
|
|
$info_form->appendHTML(<<<EOD
|
2019-09-10 02:15:20 +00:00
|
|
|
|
<div class="form-group row">
|
2016-07-18 16:39:37 +00:00
|
|
|
|
<label class="col-sm-3 control-label">testlib.h</label>
|
|
|
|
|
<div class="col-sm-9">
|
|
|
|
|
<div class="form-control-static">
|
2023-02-01 11:36:27 +00:00
|
|
|
|
<a class="text-decoration-none" href="/download/testlib.h">下载</a>
|
2016-07-18 16:39:37 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-02-01 11:36:27 +00:00
|
|
|
|
EOD);
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$esc_submission_requirement = HTML::escape(json_encode(json_decode($problem['submission_requirement']), JSON_PRETTY_PRINT));
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$info_form->appendHTML(<<<EOD
|
2019-09-10 02:15:20 +00:00
|
|
|
|
<div class="form-group row">
|
2016-07-18 16:39:37 +00:00
|
|
|
|
<label class="col-sm-3 control-label">提交文件配置</label>
|
|
|
|
|
<div class="col-sm-9">
|
2023-02-01 11:36:27 +00:00
|
|
|
|
<pre class="uoj-pre bg-light rounded">
|
2016-07-18 16:39:37 +00:00
|
|
|
|
$esc_submission_requirement
|
|
|
|
|
</pre>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-02-01 11:36:27 +00:00
|
|
|
|
EOD);
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$esc_extra_config = HTML::escape(json_encode(json_decode($problem['extra_config']), JSON_PRETTY_PRINT));
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$info_form->appendHTML(<<<EOD
|
2019-09-10 02:15:20 +00:00
|
|
|
|
<div class="form-group row">
|
2016-07-18 16:39:37 +00:00
|
|
|
|
<label class="col-sm-3 control-label">其它配置</label>
|
|
|
|
|
<div class="col-sm-9">
|
2023-02-01 11:36:27 +00:00
|
|
|
|
<pre class="uoj-pre bg-light rounded">
|
2016-07-18 16:39:37 +00:00
|
|
|
|
$esc_extra_config
|
|
|
|
|
</pre>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-02-01 11:36:27 +00:00
|
|
|
|
EOD);
|
2022-11-11 23:10:34 +00:00
|
|
|
|
if (isSuperUser(Auth::user())) {
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$info_form->addTextArea('submission_requirement', [
|
|
|
|
|
'label' => '提交文件配置',
|
|
|
|
|
'input_class' => 'form-control font-monospace',
|
|
|
|
|
'default_value' => $problem['submission_requirement'],
|
|
|
|
|
'validator_php' => function ($submission_requirement, &$vdata) {
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$submission_requirement = json_decode($submission_requirement, true);
|
|
|
|
|
if ($submission_requirement === null) {
|
|
|
|
|
return '不是合法的JSON';
|
|
|
|
|
}
|
|
|
|
|
$vdata['submission_requirement'] = json_encode($submission_requirement);
|
|
|
|
|
},
|
2023-02-01 11:36:27 +00:00
|
|
|
|
]);
|
|
|
|
|
$info_form->addTextArea('extra_config', [
|
|
|
|
|
'label' => '其他配置',
|
|
|
|
|
'input_class' => 'form-control font-monospace',
|
|
|
|
|
'default_value' => $problem['extra_config'],
|
|
|
|
|
'validator_php' => function ($extra_config, &$vdata) {
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$extra_config = json_decode($extra_config, true);
|
|
|
|
|
if ($extra_config === null) {
|
|
|
|
|
return '不是合法的JSON';
|
|
|
|
|
}
|
|
|
|
|
$vdata['extra_config'] = json_encode($extra_config);
|
|
|
|
|
},
|
2023-02-01 11:36:27 +00:00
|
|
|
|
]);
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$info_form->handle = function (&$vdata) use ($problem) {
|
|
|
|
|
DB::update([
|
|
|
|
|
"update problems",
|
|
|
|
|
"set", [
|
|
|
|
|
"submission_requirement" => $vdata['submission_requirement'],
|
2023-02-01 11:36:27 +00:00
|
|
|
|
"extra_config" => $vdata['extra_config'],
|
|
|
|
|
], "where", [
|
|
|
|
|
"id" => $problem['id'],
|
|
|
|
|
]
|
2022-11-06 02:26:21 +00:00
|
|
|
|
]);
|
|
|
|
|
};
|
|
|
|
|
} else {
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$info_form->config['no_submit'] = true;
|
2022-11-06 02:26:21 +00:00
|
|
|
|
}
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$info_form->runAtServer();
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
function displayProblemConf(UOJProblemDataDisplayer $self) {
|
|
|
|
|
global $info_form;
|
|
|
|
|
$info_form->printHTML();
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
echo '<hr class="my-3">';
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$self->echoProblemConfTable();
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$self->echoFilePre('problem.conf');
|
|
|
|
|
}
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
function addTestsTab(UOJProblemDataDisplayer $disp, UOJProblemConf $problem_conf) {
|
|
|
|
|
$n_tests = $problem_conf->getVal('n_tests', 10);
|
2022-11-06 02:26:21 +00:00
|
|
|
|
if (!validateUInt($n_tests)) {
|
|
|
|
|
$disp->setProblemConfRowStatus('n_tests', 'danger');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$inputs = [];
|
|
|
|
|
$outputs = [];
|
|
|
|
|
for ($num = 1; $num <= $n_tests; $num++) {
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$inputs[$num] = $problem_conf->getInputFileName($num);
|
|
|
|
|
$outputs[$num] = $problem_conf->getOutputFileName($num);
|
2022-11-06 02:26:21 +00:00
|
|
|
|
unset($disp->rest_data_files[$inputs[$num]]);
|
|
|
|
|
unset($disp->rest_data_files[$outputs[$num]]);
|
|
|
|
|
}
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$disp->addTab('tests', function ($self) use ($inputs, $outputs, $n_tests) {
|
|
|
|
|
for ($num = 1; $num <= $n_tests; $num++) {
|
|
|
|
|
echo '<div class="row">';
|
|
|
|
|
echo '<div class="col-md-6">';
|
|
|
|
|
$self->echoFilePre($inputs[$num]);
|
|
|
|
|
echo '</div>';
|
|
|
|
|
echo '<div class="col-md-6">';
|
|
|
|
|
$self->echoFilePre($outputs[$num]);
|
|
|
|
|
echo '</div>';
|
|
|
|
|
echo '</div>';
|
2016-07-18 16:39:37 +00:00
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
function addExTestsTab(UOJProblemDataDisplayer $disp, UOJProblemConf $problem_conf) {
|
|
|
|
|
$has_extra_tests = $problem_conf->getNonTraditionalJudgeType() != 'submit_answer';
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
|
|
|
|
if (!$has_extra_tests) {
|
|
|
|
|
return false;
|
2016-07-18 16:39:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$n_ex_tests = $problem_conf->getVal('n_ex_tests', 0);
|
2022-11-06 02:26:21 +00:00
|
|
|
|
if (!validateUInt($n_ex_tests)) {
|
|
|
|
|
$disp->setProblemConfRowStatus('n_ex_tests', 'danger');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2022-10-18 06:47:03 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
if ($n_ex_tests == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$inputs = [];
|
|
|
|
|
$outputs = [];
|
|
|
|
|
for ($num = 1; $num <= $n_ex_tests; $num++) {
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$inputs[$num] = $problem_conf->getExtraInputFileName($num);
|
|
|
|
|
$outputs[$num] = $problem_conf->getExtraOutputFileName($num);
|
2022-11-06 02:26:21 +00:00
|
|
|
|
unset($disp->rest_data_files[$inputs[$num]]);
|
|
|
|
|
unset($disp->rest_data_files[$outputs[$num]]);
|
|
|
|
|
}
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$disp->addTab('extra tests', function ($self) use ($inputs, $outputs, $n_ex_tests) {
|
|
|
|
|
for ($num = 1; $num <= $n_ex_tests; $num++) {
|
|
|
|
|
echo '<div class="row">';
|
|
|
|
|
echo '<div class="col-md-6">';
|
|
|
|
|
$self->echoFilePre($inputs[$num]);
|
|
|
|
|
echo '</div>';
|
|
|
|
|
echo '<div class="col-md-6">';
|
|
|
|
|
$self->echoFilePre($outputs[$num]);
|
|
|
|
|
echo '</div>';
|
|
|
|
|
echo '</div>';
|
2016-07-18 16:39:37 +00:00
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function addSrcTab(UOJProblemDataDisplayer $disp, $tab_name, string $name) {
|
|
|
|
|
$src = UOJLang::findSourceCode($name, '', [$disp, 'isFile']);
|
|
|
|
|
if ($src !== false) {
|
|
|
|
|
unset($disp->rest_data_files[$src['path']]);
|
|
|
|
|
}
|
|
|
|
|
unset($disp->rest_data_files[$name]);
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$disp->addTab($tab_name, function ($self) use ($name, $src) {
|
|
|
|
|
if ($src !== false) {
|
|
|
|
|
$self->echoFilePre($src['path']);
|
2016-07-18 16:39:37 +00:00
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$self->echoFilePre($name);
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
function getDataDisplayer() {
|
|
|
|
|
$disp = new UOJProblemDataDisplayer(UOJProblem::cur());
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$problem_conf = UOJProblem::cur()->getProblemConf();
|
2022-11-06 02:26:21 +00:00
|
|
|
|
if ($problem_conf === -1) {
|
|
|
|
|
return $disp->addTab('problem.conf', function ($self) {
|
|
|
|
|
global $info_form;
|
|
|
|
|
|
|
|
|
|
$info_form->printHTML();
|
|
|
|
|
|
|
|
|
|
echo '<hr class="my-3">';
|
|
|
|
|
|
|
|
|
|
$self->echoFileNotFound('problem.conf');
|
|
|
|
|
});
|
|
|
|
|
} elseif ($problem_conf === -2) {
|
|
|
|
|
return $disp->addTab('problem.conf', function ($self) {
|
|
|
|
|
global $info_form;
|
|
|
|
|
|
|
|
|
|
$info_form->printHTML();
|
|
|
|
|
|
|
|
|
|
echo '<hr class="my-3">';
|
|
|
|
|
|
|
|
|
|
echo '<div class="fw-bold text-danger">problem.conf 文件格式有误</div>';
|
|
|
|
|
$self->echoFilePre('problem.conf');
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$disp->setProblemConf($problem_conf->conf);
|
2022-11-06 02:26:21 +00:00
|
|
|
|
unset($disp->rest_data_files['problem.conf']);
|
|
|
|
|
unset($disp->rest_data_files['download.zip']);
|
|
|
|
|
$disp->addTab('problem.conf', 'displayProblemConf');
|
|
|
|
|
addTestsTab($disp, $problem_conf);
|
|
|
|
|
addExTestsTab($disp, $problem_conf);
|
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$judger_name = $problem_conf->getVal('use_builtin_judger', null);
|
2022-11-06 02:26:21 +00:00
|
|
|
|
if ($judger_name === null) {
|
|
|
|
|
return $disp;
|
|
|
|
|
} elseif ($judger_name === 'on') {
|
2023-02-01 11:36:27 +00:00
|
|
|
|
if ($problem_conf->isOn('interaction_mode')) {
|
2022-11-06 02:26:21 +00:00
|
|
|
|
if (isset($problem_conf['use_builtin_checker'])) {
|
|
|
|
|
$disp->addTab('checker', function ($self) {
|
|
|
|
|
echo '<h4>use builtin checker : ', $self->problem_conf['use_builtin_checker']['val'], '</h4>';
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
addSrcTab($disp, 'checker', 'chk');
|
2018-07-09 02:40:30 +00:00
|
|
|
|
}
|
2016-07-18 16:39:37 +00:00
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
if (UOJProblem::info('hackable')) {
|
|
|
|
|
addSrcTab($disp, 'standard', 'std');
|
|
|
|
|
addSrcTab($disp, 'validator', 'val');
|
|
|
|
|
}
|
2023-02-01 11:36:27 +00:00
|
|
|
|
if (isset($problem_conf->conf['interaction_mode'])) {
|
2022-11-06 02:26:21 +00:00
|
|
|
|
addSrcTab($disp, 'interactor', 'interactor');
|
|
|
|
|
}
|
|
|
|
|
return $disp;
|
|
|
|
|
} else {
|
|
|
|
|
return $disp->setProblemConfRowStatus('use_builtin_judger', 'danger');
|
2016-07-18 16:39:37 +00:00
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
}
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$data_disp = getDataDisplayer();
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
if (isset($_GET['display_file'])) {
|
|
|
|
|
if (!isset($_GET['file_name'])) {
|
|
|
|
|
echoFileNotFound('');
|
|
|
|
|
} else {
|
|
|
|
|
$data_disp->displayFile($_GET['file_name']);
|
|
|
|
|
}
|
|
|
|
|
die();
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$hackable_form = new UOJForm('hackable');
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$hackable_form->handle = function () use ($problem) {
|
|
|
|
|
$problem['hackable'] = !$problem['hackable'];
|
|
|
|
|
$ret = dataSyncProblemData($problem);
|
|
|
|
|
if ($ret) {
|
|
|
|
|
becomeMsgPage('<div>' . $ret . '</div><a href="/problem/' . $problem['id'] . '/manage/data">返回</a>');
|
2016-07-18 16:39:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$hackable = $problem['hackable'] ? 1 : 0;
|
|
|
|
|
DB::update([
|
|
|
|
|
"update problems",
|
|
|
|
|
"set", ["hackable" => $hackable],
|
|
|
|
|
"where", ["id" => $problem['id']]
|
|
|
|
|
]);
|
|
|
|
|
};
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$hackable_form->config['submit_container']['class'] = '';
|
|
|
|
|
$hackable_form->config['submit_button']['class'] = 'btn btn-warning d-block w-100';
|
|
|
|
|
$hackable_form->config['submit_button']['text'] = $problem['hackable'] ? '禁用 Hack 功能' : '启用 Hack 功能';
|
|
|
|
|
$hackable_form->config['confirm']['smart'] = true;
|
|
|
|
|
$hackable_form->runAtServer();
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$data_form = new UOJForm('data');
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$data_form->handle = function () use ($problem) {
|
|
|
|
|
set_time_limit(60 * 5);
|
|
|
|
|
$ret = dataSyncProblemData($problem, Auth::user());
|
|
|
|
|
if ($ret) {
|
|
|
|
|
becomeMsgPage('<div>' . $ret . '</div><a href="/problem/' . $problem['id'] . '/manage/data">返回</a>');
|
|
|
|
|
}
|
|
|
|
|
};
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$data_form->config['submit_container']['class'] = '';
|
|
|
|
|
$data_form->config['submit_button']['class'] = 'btn btn-danger d-block w-100';
|
|
|
|
|
$data_form->config['submit_button']['text'] = '检验配置并同步数据';
|
|
|
|
|
$data_form->config['confirm']['smart'] = true;
|
|
|
|
|
$data_form->runAtServer();
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$clear_data_form = new UOJForm('clear_data');
|
|
|
|
|
$clear_data_form->handle = function () use ($problem) {
|
2022-11-06 02:26:21 +00:00
|
|
|
|
dataClearProblemData($problem);
|
|
|
|
|
};
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$clear_data_form->config['submit_container']['class'] = '';
|
|
|
|
|
$clear_data_form->config['submit_button']['class'] = 'btn btn-danger d-block w-100';
|
|
|
|
|
$clear_data_form->config['submit_button']['text'] = '清空题目数据';
|
|
|
|
|
$clear_data_form->config['confirm']['smart'] = true;
|
|
|
|
|
$clear_data_form->runAtServer();
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$rejudge_form = new UOJForm('rejudge');
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$rejudge_form->handle = function () {
|
|
|
|
|
UOJSubmission::rejudgeProblem(UOJProblem::cur());
|
|
|
|
|
};
|
|
|
|
|
$rejudge_form->succ_href = "/submissions?problem_id={$problem['id']}";
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$rejudge_form->config['submit_container']['class'] = '';
|
|
|
|
|
$rejudge_form->config['submit_button']['class'] = 'btn btn-danger d-block w-100';
|
|
|
|
|
$rejudge_form->config['submit_button']['text'] = '重测该题';
|
|
|
|
|
$rejudge_form->config['confirm']['smart'] = true;
|
|
|
|
|
$rejudge_form->runAtServer();
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$rejudgege97_form = new UOJForm('rejudgege97');
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$rejudgege97_form->handle = function () {
|
|
|
|
|
UOJSubmission::rejudgeProblemGe97(UOJProblem::cur());
|
|
|
|
|
};
|
|
|
|
|
$rejudgege97_form->succ_href = "/submissions?problem_id={$problem['id']}";
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$rejudgege97_form->config['submit_container']['class'] = '';
|
|
|
|
|
$rejudgege97_form->config['submit_button']['class'] = 'btn btn-danger d-block w-100';
|
|
|
|
|
$rejudgege97_form->config['submit_button']['text'] = '重测 >=97 的程序';
|
|
|
|
|
$rejudgege97_form->config['confirm']['smart'] = true;
|
|
|
|
|
$rejudgege97_form->runAtServer();
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
|
|
|
|
if ($problem['hackable']) {
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$test_std_form = new UOJForm('test_std');
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$test_std_form->handle = function () use ($problem, $data_disp) {
|
|
|
|
|
$user_std = UOJUser::query('std');
|
|
|
|
|
if (!$user_std) {
|
|
|
|
|
UOJResponse::message('Please create an user named "std"');
|
2016-07-18 16:39:37 +00:00
|
|
|
|
}
|
2022-09-29 01:27:11 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$requirement = json_decode($problem['submission_requirement'], true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$src_std = UOJLang::findSourceCode('std', '', [$data_disp, 'isFile']);
|
|
|
|
|
if ($src_std === false) {
|
2023-02-01 11:36:27 +00:00
|
|
|
|
UOJResponse::message('未找到 std!');
|
2022-11-06 02:26:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$zip_file_name = FS::randomAvailableSubmissionFileName();
|
|
|
|
|
$zip_file = new ZipArchive();
|
|
|
|
|
if ($zip_file->open(UOJContext::storagePath() . $zip_file_name, ZipArchive::CREATE) !== true) {
|
|
|
|
|
UOJResponse::message('提交失败');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$content = [];
|
|
|
|
|
$content['file_name'] = $zip_file_name;
|
|
|
|
|
$content['config'] = [];
|
|
|
|
|
$tot_size = 0;
|
|
|
|
|
foreach ($requirement as $req) {
|
|
|
|
|
if ($req['type'] == "source code") {
|
|
|
|
|
$content['config'][] = ["{$req['name']}_language", $src_std['lang']];
|
|
|
|
|
if ($zip_file->addFromString($req['file_name'], $data_disp->getFile($src_std['path'])) === false) {
|
|
|
|
|
$zip_file->close();
|
|
|
|
|
unlink(UOJContext::storagePath() . $zip_file_name);
|
|
|
|
|
UOJResponse::message('提交失败');
|
2016-07-18 16:39:37 +00:00
|
|
|
|
}
|
|
|
|
|
$tot_size += $zip_file->statName($req['file_name'])['size'];
|
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$zip_file->close();
|
|
|
|
|
|
|
|
|
|
$content['config'][] = ['validate_input_before_test', 'on'];
|
|
|
|
|
$content['config'][] = ['problem_id', $problem['id']];
|
|
|
|
|
$esc_content = json_encode($content);
|
|
|
|
|
|
|
|
|
|
$result = [];
|
|
|
|
|
$result['status'] = "Waiting";
|
|
|
|
|
$result_json = json_encode($result);
|
|
|
|
|
$is_hidden = $problem['is_hidden'] ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
DB::insert([
|
|
|
|
|
"insert into submissions",
|
|
|
|
|
"(problem_id, submit_time, submitter, content, language, tot_size, status, result, is_hidden)",
|
|
|
|
|
"values", DB::tuple([
|
|
|
|
|
$problem['id'], DB::now(), $user_std['username'], $esc_content,
|
|
|
|
|
$src_std['lang'], $tot_size, $result['status'], $result_json, $is_hidden
|
|
|
|
|
])
|
|
|
|
|
]);
|
|
|
|
|
};
|
|
|
|
|
$test_std_form->succ_href = "/submissions?problem_id={$problem['id']}";
|
2023-02-01 11:36:27 +00:00
|
|
|
|
$test_std_form->config['submit_container']['class'] = '';
|
|
|
|
|
$test_std_form->config['submit_button']['class'] = 'btn btn-warning d-block w-100';
|
|
|
|
|
$test_std_form->config['submit_button']['text'] = '检验数据正确性';
|
2022-11-06 02:26:21 +00:00
|
|
|
|
$test_std_form->runAtServer();
|
|
|
|
|
}
|
|
|
|
|
?>
|
2022-10-18 06:47:03 +00:00
|
|
|
|
|
2023-02-01 11:36:27 +00:00
|
|
|
|
<?php echoUOJPageHeader('数据管理 - ' . UOJProblem::cur()->getTitle(['with' => 'id'])) ?>
|
2016-07-18 16:39:37 +00:00
|
|
|
|
|
|
|
|
|
<div class="row">
|
2022-11-06 02:26:21 +00:00
|
|
|
|
<!-- left col -->
|
|
|
|
|
<div class="col-12 col-lg-9">
|
|
|
|
|
<h1>
|
2023-02-01 11:36:27 +00:00
|
|
|
|
<?= UOJProblem::cur()->getTitle(['with' => 'id']) ?> 管理
|
2022-11-06 02:26:21 +00:00
|
|
|
|
</h1>
|
|
|
|
|
|
2023-02-02 06:25:39 +00:00
|
|
|
|
<div class="my-3">
|
|
|
|
|
<?= HTML::tablist($tabs_info, 'data', 'nav-pills') ?>
|
|
|
|
|
</div>
|
2022-10-18 06:47:03 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
<div class="card">
|
|
|
|
|
<div class="card-header" id="div-file_list">
|
|
|
|
|
<ul class="nav nav-tabs card-header-tabs">
|
|
|
|
|
<?php $data_disp->echoAllTabs('problem.conf'); ?>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="card-body" id="div-file_content">
|
|
|
|
|
<?php $data_disp->displayFile('problem.conf'); ?>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
|
|
|
curFileName = '';
|
|
|
|
|
$('#div-file_list a').click(function(e) {
|
|
|
|
|
$('#div-file_content').html('<h3>Loading...</h3>');
|
|
|
|
|
$(this).tab('show');
|
|
|
|
|
|
|
|
|
|
var fileName = $(this).text();
|
|
|
|
|
curFileName = fileName;
|
|
|
|
|
$.get('/problem/<?= $problem['id'] ?>/manage/data', {
|
|
|
|
|
display_file: '',
|
|
|
|
|
file_name: fileName
|
|
|
|
|
},
|
|
|
|
|
function(data) {
|
|
|
|
|
if (curFileName != fileName) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
$('#div-file_content').html(data);
|
|
|
|
|
},
|
|
|
|
|
'html'
|
|
|
|
|
);
|
|
|
|
|
return false;
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
</div>
|
2022-10-18 06:47:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
<!-- right col -->
|
|
|
|
|
<aside class="col-12 col-lg-3 mt-3 mt-lg-0 d-flex flex-column">
|
|
|
|
|
<div class="card card-default mt-3 mt-lg-0 mb-2 order-2 order-lg-1">
|
|
|
|
|
<ul class="nav nav-pills nav-fill flex-column" role="tablist">
|
|
|
|
|
<li class="nav-item text-start">
|
|
|
|
|
<a href="/problem/<?= $problem['id'] ?>" class="nav-link" role="tab">
|
|
|
|
|
<i class="bi bi-journal-text"></i>
|
|
|
|
|
<?= UOJLocale::get('problems::statement') ?>
|
|
|
|
|
</a>
|
|
|
|
|
</li>
|
2022-12-06 06:51:09 +00:00
|
|
|
|
<li class="nav-item text-start">
|
|
|
|
|
<a href="/problem/<?= UOJProblem::info('id') ?>#submit" class="nav-link" role="tab">
|
|
|
|
|
<i class="bi bi-upload"></i>
|
|
|
|
|
<?= UOJLocale::get('problems::submit') ?>
|
|
|
|
|
</a>
|
|
|
|
|
</li>
|
2022-11-06 02:26:21 +00:00
|
|
|
|
<li class="nav-item text-start">
|
|
|
|
|
<a href="/problem/<?= $problem['id'] ?>/solutions" class="nav-link" role="tab">
|
|
|
|
|
<i class="bi bi-journal-bookmark"></i>
|
|
|
|
|
<?= UOJLocale::get('problems::solutions') ?>
|
|
|
|
|
</a>
|
|
|
|
|
</li>
|
2022-11-23 08:31:37 +00:00
|
|
|
|
<li class="nav-item text-start">
|
|
|
|
|
<a class="nav-link" href="/submissions?problem_id=<?= UOJProblem::info('id') ?>">
|
|
|
|
|
<i class="bi bi-list-ul"></i>
|
|
|
|
|
<?= UOJLocale::get('submissions') ?>
|
|
|
|
|
</a>
|
|
|
|
|
</li>
|
2022-11-06 02:26:21 +00:00
|
|
|
|
<li class="nav-item text-start">
|
|
|
|
|
<a class="nav-link" href="/problem/<?= $problem['id'] ?>/statistics">
|
|
|
|
|
<i class="bi bi-graph-up"></i>
|
|
|
|
|
<?= UOJLocale::get('problems::statistics') ?>
|
|
|
|
|
</a>
|
|
|
|
|
</li>
|
|
|
|
|
<li class="nav-item text-start">
|
|
|
|
|
<a class="nav-link active" href="#" role="tab">
|
|
|
|
|
<i class="bi bi-sliders"></i>
|
|
|
|
|
<?= UOJLocale::get('problems::manage') ?>
|
|
|
|
|
</a>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
2018-07-09 02:40:30 +00:00
|
|
|
|
</div>
|
2017-11-25 04:00:00 +00:00
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
|
<div class="order-1 order-lg-2">
|
|
|
|
|
<div>
|
2022-12-06 08:35:00 +00:00
|
|
|
|
<div class="mb-2">
|
|
|
|
|
<?php if ($problem['hackable']) : ?>
|
|
|
|
|
<i class="bi bi-check-lg text-success"></i> Hack 功能已启用
|
|
|
|
|
<?php else : ?>
|
|
|
|
|
<i class="bi bi-x-lg text-danger"></i> Hack 功能已禁用
|
|
|
|
|
<?php endif ?>
|
|
|
|
|
</div>
|
2022-11-06 02:26:21 +00:00
|
|
|
|
<?php $hackable_form->printHTML() ?>
|
|
|
|
|
</div>
|
|
|
|
|
<?php if ($problem['hackable']) : ?>
|
|
|
|
|
<div class="mt-2">
|
|
|
|
|
<?php $test_std_form->printHTML() ?>
|
|
|
|
|
</div>
|
|
|
|
|
<?php endif ?>
|
|
|
|
|
<div class="mt-2">
|
|
|
|
|
<?php $data_form->printHTML(); ?>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="mt-2">
|
|
|
|
|
<?php $clear_data_form->printHTML(); ?>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="mt-2">
|
|
|
|
|
<?php $rejudge_form->printHTML(); ?>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="mt-2">
|
|
|
|
|
<?php $rejudgege97_form->printHTML(); ?>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="mt-2">
|
|
|
|
|
<button type="button" class="btn d-block w-100 btn-primary" data-bs-toggle="modal" data-bs-target="#UploadDataModal">上传数据</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="mt-2">
|
2023-02-05 10:55:09 +00:00
|
|
|
|
<a role="button" class="btn d-block w-100 btn-primary" href="<?= UOJProblem::cur()->getUri('/manage/data/configure') ?>">数据配置</a>
|
2022-11-06 02:26:21 +00:00
|
|
|
|
</div>
|
2022-09-29 02:10:24 +00:00
|
|
|
|
</div>
|
2022-11-06 02:26:21 +00:00
|
|
|
|
</aside>
|
2017-11-25 04:00:00 +00:00
|
|
|
|
|
2022-10-18 06:47:03 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="modal fade" id="UploadDataModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
|
|
|
|
<div class="modal-dialog">
|
2022-10-19 03:57:27 +00:00
|
|
|
|
<div class="modal-content">
|
|
|
|
|
<div class="modal-header">
|
|
|
|
|
<h4 class="modal-title" id="myModalLabel">上传数据</h4>
|
|
|
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
|
|
|
</div>
|
|
|
|
|
<form action="" method="post" enctype="multipart/form-data" role="form">
|
2022-10-18 06:47:03 +00:00
|
|
|
|
<div class="modal-body">
|
2022-10-19 03:57:27 +00:00
|
|
|
|
<label class="form-label" for="problem_data_file">上传 zip 文件</label>
|
|
|
|
|
<input class="form-control" type="file" name="problem_data_file" id="problem_data_file" accept=".zip">
|
|
|
|
|
|
|
|
|
|
<p class="form-text">
|
|
|
|
|
说明:请将所有数据放置于压缩包根目录内。若压缩包内仅存在文件夹而不存在文件,则会将这些一级子文件夹下的内容移动到根目录下,然后这些一级子文件夹删除;若这些子文件夹内存在同名文件,则会发生随机替换,仅保留一个副本。
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<!-- hidden input for server-side check -->
|
|
|
|
|
<input type="hidden" name="problem_data_file_submit" value="submit">
|
2022-10-18 06:47:03 +00:00
|
|
|
|
</div>
|
|
|
|
|
<div class="modal-footer">
|
|
|
|
|
<button type="submit" class="btn btn-success">上传</button>
|
|
|
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
|
|
|
|
|
</div>
|
2022-10-19 03:57:27 +00:00
|
|
|
|
</form>
|
|
|
|
|
</div>
|
2017-11-25 04:00:00 +00:00
|
|
|
|
</div>
|
2022-10-18 06:47:03 +00:00
|
|
|
|
</div>
|
2017-11-25 04:00:00 +00:00
|
|
|
|
|
2016-07-18 16:39:37 +00:00
|
|
|
|
<?php echoUOJPageFooter() ?>
|