mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-23 07:18:41 +00:00
feat: allow empty input_pre and output_pre
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
04ab18076b
commit
a6d9222aea
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user