Compare commits

...

2 Commits

Author SHA1 Message Date
a6d9222aea
feat: allow empty input_pre and output_pre
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-28 21:08:20 +08:00
04ab18076b
chore(submission): disable hack for remote submissions 2023-03-28 21:05:39 +08:00
8 changed files with 210 additions and 89 deletions

View File

@ -50,6 +50,44 @@ inline string htmlspecialchars(const string &s) {
return r;
}
// trim from start (in place)
inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}
// trim from end (in place)
inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (in place)
inline void trim(std::string &s) {
rtrim(s);
ltrim(s);
}
// trim from start (copying)
inline std::string ltrim_copy(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
inline std::string rtrim_copy(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
inline std::string trim_copy(std::string s) {
trim(s);
return s;
}
/*========================== random ====================== */
inline string gen_token() {
@ -679,14 +717,22 @@ void print_config() {
}
void load_config(const string &filename) {
ifstream fin(filename.c_str());
if (!fin) {
return;
}
string key;
string val;
while (fin >> key >> val) {
config[key] = val;
string key, val;
// the first token of a line is key, the rest is value
while (fin >> key) {
getline(fin, val);
config[key] = trim_copy(val);
}
// while (fin >> key >> val) {
// config[key] = val;
// }
}
string conf_str(const string &key, int num, const string &val) {
ostringstream sout;
@ -759,7 +805,7 @@ string conf_input_file_name(int num) {
if (num < 0) {
name << "ex_";
}
name << conf_str("input_pre", "input") << abs(num) << "." << conf_str("input_suf", "txt");
name << conf_str("input_pre", "") << abs(num) << "." << conf_str("input_suf", "in");
return name.str();
}
string conf_output_file_name(int num) {
@ -768,7 +814,7 @@ string conf_output_file_name(int num) {
if (num < 0) {
name << "ex_";
}
name << conf_str("output_pre", "output") << abs(num) << "." << conf_str("output_suf", "txt");
name << conf_str("output_pre", "") << abs(num) << "." << conf_str("output_suf", "out");
return name.str();
}
runp::limits_t conf_run_limit(string pre, const int &num, const runp::limits_t &val) {

View File

@ -59,6 +59,44 @@ inline string list_to_string(const T &list) {
return sout.str();
}
// trim from start (in place)
inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}
// trim from end (in place)
inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (in place)
inline void trim(std::string &s) {
rtrim(s);
ltrim(s);
}
// trim from start (copying)
inline std::string ltrim_copy(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
inline std::string rtrim_copy(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
inline std::string trim_copy(std::string s) {
trim(s);
return s;
}
/*========================== random ====================== */
inline string gen_token() {
@ -463,13 +501,22 @@ void print_config() {
}
void load_config(const string &filename) {
ifstream fin(filename.c_str());
if (!fin) {
return;
}
string key, val;
while (fin >> key >> val) {
uconfig[key] = val;
// the first token of a line is key, the rest is value
while (fin >> key) {
getline(fin, val);
uconfig[key] = trim_copy(val);
}
// while (fin >> key >> val) {
// uconfig[key] = val;
// }
}
string conf_str(const string &key, int num, const string &val) {
ostringstream sout;
@ -535,7 +582,7 @@ string conf_input_file_name(int num) {
if (num < 0) {
name << "ex_";
}
name << conf_str("input_pre", "input") << abs(num) << "." << conf_str("input_suf", "txt");
name << conf_str("input_pre", "") << abs(num) << "." << conf_str("input_suf", "in");
return name.str();
}
string conf_output_file_name(int num) {
@ -543,7 +590,7 @@ string conf_output_file_name(int num) {
if (num < 0) {
name << "ex_";
}
name << conf_str("output_pre", "output") << abs(num) << "." << conf_str("output_suf", "txt");
name << conf_str("output_pre", "") << abs(num) << "." << conf_str("output_suf", "out");
return name.str();
}
runp::limits_t conf_run_limit(string pre, const int &num, const runp::limits_t &val) {

View File

@ -109,6 +109,7 @@ function handleUpload($zip_file_name, $content, $tot_size) {
if (UOJProblem::info('type') == 'remote') {
$submit_type = in_array($_POST['answer_remote_submit_type'], $remote_provider['submit_type']) ? $_POST['answer_remote_submit_type'] : $remote_provider['submit_type'][0];
$content['remote_judge'] = true;
$content['config'][] = ['remote_submit_type', $submit_type];
if ($submit_type != 'bot') {

View File

@ -67,16 +67,16 @@ function getUOJConfVal($conf, $key, $default_val) {
}
function getUOJProblemInputFileName($problem_conf, $num) {
return getUOJConfVal($problem_conf, 'input_pre', 'input') . $num . '.' . getUOJConfVal($problem_conf, 'input_suf', 'txt');
return getUOJConfVal($problem_conf, 'input_pre', '') . $num . '.' . getUOJConfVal($problem_conf, 'input_suf', 'in');
}
function getUOJProblemOutputFileName($problem_conf, $num) {
return getUOJConfVal($problem_conf, 'output_pre', 'output') . $num . '.' . getUOJConfVal($problem_conf, 'output_suf', 'txt');
return getUOJConfVal($problem_conf, 'output_pre', '') . $num . '.' . getUOJConfVal($problem_conf, 'output_suf', 'out');
}
function getUOJProblemExtraInputFileName($problem_conf, $num) {
return 'ex_' . getUOJConfVal($problem_conf, 'input_pre', 'input') . $num . '.' . getUOJConfVal($problem_conf, 'input_suf', 'txt');
return 'ex_' . getUOJConfVal($problem_conf, 'input_pre', '') . $num . '.' . getUOJConfVal($problem_conf, 'input_suf', 'in');
}
function getUOJProblemExtraOutputFileName($problem_conf, $num) {
return 'ex_' . getUOJConfVal($problem_conf, 'output_pre', 'output') . $num . '.' . getUOJConfVal($problem_conf, 'output_suf', 'txt');
return 'ex_' . getUOJConfVal($problem_conf, 'output_pre', '') . $num . '.' . getUOJConfVal($problem_conf, 'output_suf', 'out');
}
function updateBestACSubmissions($username, $problem_id) {

View File

@ -1,65 +1,81 @@
<?php
class StrictFileReader {
private $f;
private $buf = '', $off = 0;
private $f;
private $buf = '', $off = 0;
public function __construct($file_name) {
$this->f = fopen($file_name, 'r');
}
public function __construct($file_name) {
$this->f = fopen($file_name, 'r');
}
public function failed() {
return $this->f === false;
}
public function failed() {
return $this->f === false;
}
public function readChar() {
if (isset($this->buf[$this->off])) {
return $this->buf[$this->off++];
}
return fgetc($this->f);
}
public function unreadChar($c) {
$this->buf .= $c;
if ($this->off > 1000) {
$this->buf = substr($this->buf, $this->off);
$this->off = 0;
}
}
public function readChar() {
if (isset($this->buf[$this->off])) {
return $this->buf[$this->off++];
}
return fgetc($this->f);
}
public function unreadChar($c) {
$this->buf .= $c;
if ($this->off > 1000) {
$this->buf = substr($this->buf, $this->off);
$this->off = 0;
}
}
public function readString() {
$str = '';
while (true) {
$c = $this->readChar();
if ($c === false) {
break;
} elseif ($c === " " || $c === "\n" || $c === "\r") {
$this->unreadChar($c);
break;
} else {
$str .= $c;
}
}
return $str;
}
public function ignoreWhite() {
while (true) {
$c = $this->readChar();
if ($c === false) {
break;
} elseif ($c === " " || $c === "\n" || $c === "\r") {
continue;
} else {
$this->unreadChar($c);
break;
}
}
}
public function readString() {
$str = '';
while (true) {
$c = $this->readChar();
if ($c === false) {
break;
} elseif ($c === " " || $c === "\n" || $c === "\r") {
$this->unreadChar($c);
break;
} else {
$str .= $c;
}
}
return $str;
}
public function eof() {
return feof($this->f);
}
public function readLine() {
$str = '';
while (true) {
$c = $this->readChar();
if ($c === false) {
break;
} elseif ($c === "\n") {
break;
} else {
$str .= $c;
}
}
return $str;
}
public function close() {
fclose($this->f);
}
public function ignoreWhite() {
while (true) {
$c = $this->readChar();
if ($c === false) {
break;
} elseif ($c === " " || $c === "\n" || $c === "\r") {
continue;
} else {
$this->unreadChar($c);
break;
}
}
}
public function eof() {
return feof($this->f);
}
public function close() {
fclose($this->f);
}
}

View File

@ -10,24 +10,28 @@ class UOJProblemConf {
}
$conf = [];
while (!$reader->eof()) {
$reader->ignoreWhite();
$key = $reader->readString();
if ($key === '') {
break;
}
$reader->ignoreWhite();
$val = $reader->readString();
if ($val === '') {
$line = $reader->readLine();
$line = explode(' ', $line);
$key = array_shift($line);
if (!$key) {
break;
}
if (isset($conf[$key])) {
return -2;
}
$conf[$key] = $val;
$conf[$key] = trim(implode(' ', $line));
}
$reader->close();
return new UOJProblemConf($conf);
}
@ -37,9 +41,11 @@ class UOJProblemConf {
public function putToFile($file_name) {
$f = fopen($file_name, 'w');
foreach ($this->conf as $key => $val) {
fwrite($f, "{$key} {$val}\n");
}
fclose($f);
}
@ -55,15 +61,16 @@ class UOJProblemConf {
return $this->conf[$key];
}
}
return $default_val;
}
public function getInputFileName($num) {
return $this->getVal('input_pre', 'input') . $num . '.' . $this->getVal('input_suf', 'txt');
return $this->getVal('input_pre', '') . $num . '.' . $this->getVal('input_suf', 'txt');
}
public function getOutputFileName($num) {
return $this->getVal('output_pre', 'output') . $num . '.' . $this->getVal('output_suf', 'txt');
return $this->getVal('output_pre', '') . $num . '.' . $this->getVal('output_suf', 'txt');
}
public function getExtraInputFileName($num) {

View File

@ -85,10 +85,10 @@ class UOJProblemConfigure {
$this->simple_form->appendHTML(static::getCardFooter());
$this->simple_form->appendHTML(static::getCardHeader('文件配置'));
$this->addTextInput($this->simple_form, 'input_pre', '输入文件名称', '');
$this->addTextInput($this->simple_form, 'input_suf', '输入文件后缀', '');
$this->addTextInput($this->simple_form, 'output_pre', '输出文件名称', '');
$this->addTextInput($this->simple_form, 'output_suf', '输出文件后缀', '');
$this->addTextInput($this->simple_form, 'input_pre', '输入文件名称', '', ['validator_php' => fn ($x) => '']);
$this->addTextInput($this->simple_form, 'input_suf', '输入文件后缀', 'in', ['validator_php' => fn ($x) => '']);
$this->addTextInput($this->simple_form, 'output_pre', '输出文件名称', '', ['validator_php' => fn ($x) => '']);
$this->addTextInput($this->simple_form, 'output_suf', '输出文件后缀', 'out', ['validator_php' => fn ($x) => '']);
$this->simple_form->appendHTML(static::getCardFooter());
$this->simple_form->appendHTML(static::getCardHeader('运行时限制'));
@ -227,7 +227,7 @@ class UOJProblemConfigure {
public function addNumberInput(UOJForm $form, $key, $label, $default_val = '', $cfg = []) {
$this->conf_keys[$key] = true;
$form->addInput($key, [
$form->addInput($key, $cfg + [
'type' => 'number',
'label' => $label,
'div_class' => 'row gx-2',
@ -237,7 +237,7 @@ class UOJProblemConfigure {
'validator_php' => function ($x) {
return validateInt($x) ? '' : '必须为一个整数';
},
] + $cfg);
]);
$form->appendHTML(<<<EOD
<script>
$('#input-{$key}').change(function() {
@ -250,7 +250,7 @@ class UOJProblemConfigure {
public function addTimeLimitInput(UOJForm $form, $key, $label, $default_val = '', $cfg = []) {
$this->conf_keys[$key] = true;
$form->addInput($key, [
$form->addInput($key, $cfg + [
'type' => 'number',
'label' => $label,
'input_attrs' => ['step' => 0.001],
@ -267,7 +267,7 @@ class UOJProblemConfigure {
return '';
}
},
] + $cfg);
]);
$form->appendHTML(<<<EOD
<script>
$('#input-{$key}').change(function() {
@ -280,7 +280,7 @@ class UOJProblemConfigure {
public function addTextInput(UOJForm $form, $key, $label, $default_val = '', $cfg = []) {
$this->conf_keys[$key] = true;
$form->addInput($key, [
$form->addInput($key, $cfg + [
'label' => $label,
'div_class' => 'row gx-2',
'label_class' => 'col-form-label col-4',
@ -289,7 +289,7 @@ class UOJProblemConfigure {
'validator_php' => function ($x) {
return ctype_graph($x) ? '' : '必须仅包含除空格以外的可见字符';
},
] + $cfg);
]);
$form->appendHTML(<<<EOD
<script>
$('#input-{$key}').change(function() {

View File

@ -480,6 +480,10 @@ class UOJSubmission {
}
public function preHackCheck(array $user = null) {
if ($this->getContent('remote_judge')) {
return false;
}
return $this->info['score'] == 100 && $this->problem->preHackCheck($user);
}