mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-23 10:38:42 +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;
|
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 ====================== */
|
/*========================== random ====================== */
|
||||||
|
|
||||||
inline string gen_token() {
|
inline string gen_token() {
|
||||||
@ -679,14 +717,22 @@ void print_config() {
|
|||||||
}
|
}
|
||||||
void load_config(const string &filename) {
|
void load_config(const string &filename) {
|
||||||
ifstream fin(filename.c_str());
|
ifstream fin(filename.c_str());
|
||||||
|
|
||||||
if (!fin) {
|
if (!fin) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
string key;
|
|
||||||
string val;
|
string key, val;
|
||||||
while (fin >> key >> val) {
|
|
||||||
config[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) {
|
string conf_str(const string &key, int num, const string &val) {
|
||||||
ostringstream sout;
|
ostringstream sout;
|
||||||
@ -759,7 +805,7 @@ string conf_input_file_name(int num) {
|
|||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
name << "ex_";
|
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();
|
return name.str();
|
||||||
}
|
}
|
||||||
string conf_output_file_name(int num) {
|
string conf_output_file_name(int num) {
|
||||||
@ -768,7 +814,7 @@ string conf_output_file_name(int num) {
|
|||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
name << "ex_";
|
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();
|
return name.str();
|
||||||
}
|
}
|
||||||
runp::limits_t conf_run_limit(string pre, const int &num, const runp::limits_t &val) {
|
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();
|
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 ====================== */
|
/*========================== random ====================== */
|
||||||
|
|
||||||
inline string gen_token() {
|
inline string gen_token() {
|
||||||
@ -463,13 +501,22 @@ void print_config() {
|
|||||||
}
|
}
|
||||||
void load_config(const string &filename) {
|
void load_config(const string &filename) {
|
||||||
ifstream fin(filename.c_str());
|
ifstream fin(filename.c_str());
|
||||||
|
|
||||||
if (!fin) {
|
if (!fin) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string key, val;
|
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) {
|
string conf_str(const string &key, int num, const string &val) {
|
||||||
ostringstream sout;
|
ostringstream sout;
|
||||||
@ -535,7 +582,7 @@ string conf_input_file_name(int num) {
|
|||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
name << "ex_";
|
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();
|
return name.str();
|
||||||
}
|
}
|
||||||
string conf_output_file_name(int num) {
|
string conf_output_file_name(int num) {
|
||||||
@ -543,7 +590,7 @@ string conf_output_file_name(int num) {
|
|||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
name << "ex_";
|
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();
|
return name.str();
|
||||||
}
|
}
|
||||||
runp::limits_t conf_run_limit(string pre, const int &num, const runp::limits_t &val) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
function updateBestACSubmissions($username, $problem_id) {
|
||||||
|
@ -1,65 +1,81 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class StrictFileReader {
|
class StrictFileReader {
|
||||||
private $f;
|
private $f;
|
||||||
private $buf = '', $off = 0;
|
private $buf = '', $off = 0;
|
||||||
|
|
||||||
public function __construct($file_name) {
|
public function __construct($file_name) {
|
||||||
$this->f = fopen($file_name, 'r');
|
$this->f = fopen($file_name, 'r');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function failed() {
|
public function failed() {
|
||||||
return $this->f === false;
|
return $this->f === false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readChar() {
|
public function readChar() {
|
||||||
if (isset($this->buf[$this->off])) {
|
if (isset($this->buf[$this->off])) {
|
||||||
return $this->buf[$this->off++];
|
return $this->buf[$this->off++];
|
||||||
}
|
}
|
||||||
return fgetc($this->f);
|
return fgetc($this->f);
|
||||||
}
|
}
|
||||||
public function unreadChar($c) {
|
public function unreadChar($c) {
|
||||||
$this->buf .= $c;
|
$this->buf .= $c;
|
||||||
if ($this->off > 1000) {
|
if ($this->off > 1000) {
|
||||||
$this->buf = substr($this->buf, $this->off);
|
$this->buf = substr($this->buf, $this->off);
|
||||||
$this->off = 0;
|
$this->off = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function readString() {
|
public function readString() {
|
||||||
$str = '';
|
$str = '';
|
||||||
while (true) {
|
while (true) {
|
||||||
$c = $this->readChar();
|
$c = $this->readChar();
|
||||||
if ($c === false) {
|
if ($c === false) {
|
||||||
break;
|
break;
|
||||||
} elseif ($c === " " || $c === "\n" || $c === "\r") {
|
} elseif ($c === " " || $c === "\n" || $c === "\r") {
|
||||||
$this->unreadChar($c);
|
$this->unreadChar($c);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
$str .= $c;
|
$str .= $c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $str;
|
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 eof() {
|
public function readLine() {
|
||||||
return feof($this->f);
|
$str = '';
|
||||||
}
|
while (true) {
|
||||||
|
$c = $this->readChar();
|
||||||
|
if ($c === false) {
|
||||||
|
break;
|
||||||
|
} elseif ($c === "\n") {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
$str .= $c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
|
|
||||||
public function close() {
|
public function ignoreWhite() {
|
||||||
fclose($this->f);
|
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 = [];
|
$conf = [];
|
||||||
|
|
||||||
while (!$reader->eof()) {
|
while (!$reader->eof()) {
|
||||||
$reader->ignoreWhite();
|
$reader->ignoreWhite();
|
||||||
$key = $reader->readString();
|
|
||||||
if ($key === '') {
|
$line = $reader->readLine();
|
||||||
break;
|
$line = explode(' ', $line);
|
||||||
}
|
|
||||||
$reader->ignoreWhite();
|
$key = array_shift($line);
|
||||||
$val = $reader->readString();
|
|
||||||
if ($val === '') {
|
if (!$key) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($conf[$key])) {
|
if (isset($conf[$key])) {
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
$conf[$key] = $val;
|
|
||||||
|
$conf[$key] = trim(implode(' ', $line));
|
||||||
}
|
}
|
||||||
|
|
||||||
$reader->close();
|
$reader->close();
|
||||||
|
|
||||||
return new UOJProblemConf($conf);
|
return new UOJProblemConf($conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,9 +41,11 @@ class UOJProblemConf {
|
|||||||
|
|
||||||
public function putToFile($file_name) {
|
public function putToFile($file_name) {
|
||||||
$f = fopen($file_name, 'w');
|
$f = fopen($file_name, 'w');
|
||||||
|
|
||||||
foreach ($this->conf as $key => $val) {
|
foreach ($this->conf as $key => $val) {
|
||||||
fwrite($f, "{$key} {$val}\n");
|
fwrite($f, "{$key} {$val}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose($f);
|
fclose($f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,15 +61,16 @@ class UOJProblemConf {
|
|||||||
return $this->conf[$key];
|
return $this->conf[$key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $default_val;
|
return $default_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getInputFileName($num) {
|
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) {
|
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) {
|
public function getExtraInputFileName($num) {
|
||||||
|
@ -85,10 +85,10 @@ class UOJProblemConfigure {
|
|||||||
$this->simple_form->appendHTML(static::getCardFooter());
|
$this->simple_form->appendHTML(static::getCardFooter());
|
||||||
|
|
||||||
$this->simple_form->appendHTML(static::getCardHeader('文件配置'));
|
$this->simple_form->appendHTML(static::getCardHeader('文件配置'));
|
||||||
$this->addTextInput($this->simple_form, 'input_pre', '输入文件名称', '');
|
$this->addTextInput($this->simple_form, 'input_pre', '输入文件名称', '', ['validator_php' => fn ($x) => '']);
|
||||||
$this->addTextInput($this->simple_form, 'input_suf', '输入文件后缀', '');
|
$this->addTextInput($this->simple_form, 'input_suf', '输入文件后缀', 'in', ['validator_php' => fn ($x) => '']);
|
||||||
$this->addTextInput($this->simple_form, 'output_pre', '输出文件名称', '');
|
$this->addTextInput($this->simple_form, 'output_pre', '输出文件名称', '', ['validator_php' => fn ($x) => '']);
|
||||||
$this->addTextInput($this->simple_form, 'output_suf', '输出文件后缀', '');
|
$this->addTextInput($this->simple_form, 'output_suf', '输出文件后缀', 'out', ['validator_php' => fn ($x) => '']);
|
||||||
$this->simple_form->appendHTML(static::getCardFooter());
|
$this->simple_form->appendHTML(static::getCardFooter());
|
||||||
|
|
||||||
$this->simple_form->appendHTML(static::getCardHeader('运行时限制'));
|
$this->simple_form->appendHTML(static::getCardHeader('运行时限制'));
|
||||||
@ -227,7 +227,7 @@ class UOJProblemConfigure {
|
|||||||
|
|
||||||
public function addNumberInput(UOJForm $form, $key, $label, $default_val = '', $cfg = []) {
|
public function addNumberInput(UOJForm $form, $key, $label, $default_val = '', $cfg = []) {
|
||||||
$this->conf_keys[$key] = true;
|
$this->conf_keys[$key] = true;
|
||||||
$form->addInput($key, [
|
$form->addInput($key, $cfg + [
|
||||||
'type' => 'number',
|
'type' => 'number',
|
||||||
'label' => $label,
|
'label' => $label,
|
||||||
'div_class' => 'row gx-2',
|
'div_class' => 'row gx-2',
|
||||||
@ -237,7 +237,7 @@ class UOJProblemConfigure {
|
|||||||
'validator_php' => function ($x) {
|
'validator_php' => function ($x) {
|
||||||
return validateInt($x) ? '' : '必须为一个整数';
|
return validateInt($x) ? '' : '必须为一个整数';
|
||||||
},
|
},
|
||||||
] + $cfg);
|
]);
|
||||||
$form->appendHTML(<<<EOD
|
$form->appendHTML(<<<EOD
|
||||||
<script>
|
<script>
|
||||||
$('#input-{$key}').change(function() {
|
$('#input-{$key}').change(function() {
|
||||||
@ -250,7 +250,7 @@ class UOJProblemConfigure {
|
|||||||
|
|
||||||
public function addTimeLimitInput(UOJForm $form, $key, $label, $default_val = '', $cfg = []) {
|
public function addTimeLimitInput(UOJForm $form, $key, $label, $default_val = '', $cfg = []) {
|
||||||
$this->conf_keys[$key] = true;
|
$this->conf_keys[$key] = true;
|
||||||
$form->addInput($key, [
|
$form->addInput($key, $cfg + [
|
||||||
'type' => 'number',
|
'type' => 'number',
|
||||||
'label' => $label,
|
'label' => $label,
|
||||||
'input_attrs' => ['step' => 0.001],
|
'input_attrs' => ['step' => 0.001],
|
||||||
@ -267,7 +267,7 @@ class UOJProblemConfigure {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
] + $cfg);
|
]);
|
||||||
$form->appendHTML(<<<EOD
|
$form->appendHTML(<<<EOD
|
||||||
<script>
|
<script>
|
||||||
$('#input-{$key}').change(function() {
|
$('#input-{$key}').change(function() {
|
||||||
@ -280,7 +280,7 @@ class UOJProblemConfigure {
|
|||||||
|
|
||||||
public function addTextInput(UOJForm $form, $key, $label, $default_val = '', $cfg = []) {
|
public function addTextInput(UOJForm $form, $key, $label, $default_val = '', $cfg = []) {
|
||||||
$this->conf_keys[$key] = true;
|
$this->conf_keys[$key] = true;
|
||||||
$form->addInput($key, [
|
$form->addInput($key, $cfg + [
|
||||||
'label' => $label,
|
'label' => $label,
|
||||||
'div_class' => 'row gx-2',
|
'div_class' => 'row gx-2',
|
||||||
'label_class' => 'col-form-label col-4',
|
'label_class' => 'col-form-label col-4',
|
||||||
@ -289,7 +289,7 @@ class UOJProblemConfigure {
|
|||||||
'validator_php' => function ($x) {
|
'validator_php' => function ($x) {
|
||||||
return ctype_graph($x) ? '' : '必须仅包含除空格以外的可见字符';
|
return ctype_graph($x) ? '' : '必须仅包含除空格以外的可见字符';
|
||||||
},
|
},
|
||||||
] + $cfg);
|
]);
|
||||||
$form->appendHTML(<<<EOD
|
$form->appendHTML(<<<EOD
|
||||||
<script>
|
<script>
|
||||||
$('#input-{$key}').change(function() {
|
$('#input-{$key}').change(function() {
|
||||||
|
Loading…
Reference in New Issue
Block a user