From c00dc85e68263f4d7ae46502d4e20a39ca6a1d91 Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Sun, 5 Feb 2023 14:43:54 +0800 Subject: [PATCH] feat(problem/manage/data): point_score configure --- .../controllers/problem_data_configure.php | 1 - web/app/models/UOJProblemConfigure.php | 74 +++++++++++++++++-- web/js/uoj.js | 62 ++++++++++++++++ 3 files changed, 131 insertions(+), 6 deletions(-) diff --git a/web/app/controllers/problem_data_configure.php b/web/app/controllers/problem_data_configure.php index 934be19..e78f9b2 100644 --- a/web/app/controllers/problem_data_configure.php +++ b/web/app/controllers/problem_data_configure.php @@ -7,7 +7,6 @@ requirePHPLib('data'); UOJProblem::init(UOJRequest::get('id')) || UOJResponse::page404(); UOJProblem::cur()->userCanManage(Auth::user()) || UOJResponse::page403(); -$problem = UOJProblem::info(); $problem_configure = new UOJProblemConfigure(UOJProblem::cur()); $problem_configure->runAtServer(); ?> diff --git a/web/app/models/UOJProblemConfigure.php b/web/app/models/UOJProblemConfigure.php index e99b261..4d61ca1 100644 --- a/web/app/models/UOJProblemConfigure.php +++ b/web/app/models/UOJProblemConfigure.php @@ -34,14 +34,14 @@ class UOJProblemConfigure { 'real-8' => '实数,四舍五入到小数点后 8 位', ]; - private static function getCardHeader($title) { + private static function getCardHeader($title, $body_class = 'vstack gap-3') { return <<
{$title}
-
+
EOD; } @@ -65,6 +65,13 @@ class UOJProblemConfigure { $this->simple_form = new UOJForm('simple'); + $encoded_problem_conf = json_encode($problem_conf->conf, JSON_FORCE_OBJECT); + $this->simple_form->appendHTML(<< + var problem_conf = {$encoded_problem_conf}; + + EOD); + $this->simple_form->appendHTML(static::getCardHeader('基本信息')); $this->addSelect($this->simple_form, 'use_builtin_judger', ['on' => '默认', 'off' => '自定义 Judger'], '测评逻辑', 'on'); $this->addSelect($this->simple_form, 'use_builtin_checker', self::$supported_checkers, '比对函数', 'ncmp'); @@ -74,7 +81,7 @@ class UOJProblemConfigure { $this->simple_form->appendHTML(static::getCardHeader('数据配置')); $this->addNumberInput($this->simple_form, 'n_tests', '数据点个数', 10); $this->addNumberInput($this->simple_form, 'n_ex_tests', '额外数据点个数', 0); - $this->addNumberInput($this->simple_form, 'n_sample_tests', '样例数据点个数', 0); + $this->addNumberInput($this->simple_form, 'n_sample_tests', '样例数据点个数', 0, ['help' => '样例数据点为额外数据点的前 x 个数据点。']); $this->simple_form->appendHTML(static::getCardFooter()); $this->simple_form->appendHTML(static::getCardHeader('文件配置')); @@ -90,6 +97,29 @@ class UOJProblemConfigure { $this->addNumberInput($this->simple_form, 'output_limit', '输出长度限制', 64, ['help' => '单位为 MiB。']); $this->simple_form->appendHTML(static::getCardFooter()); + $this->simple_form->appendHTML(static::getCardHeader('测试点分值', '')); + $this->simple_form->appendHTML(<<
+ EOD); + $this->simple_form->appendHTML(static::getCardFooter()); + $this->simple_form->appendHTML(<< + $(document).ready(function() { + $('#input-n_tests').change(function() { + problem_conf['n_tests'] = $(this).val(); + $('#div-point-score-container').problem_configure_point_scores(problem_conf); + }); + + $('#input-score_type').change(function() { + problem_conf['score_type'] = $(this).val(); + $('.uoj-problem-configure-point-score-input', $('#div-point-score-container')).first().trigger('change'); + }); + + $('#div-point-score-container').problem_configure_point_scores(problem_conf); + }); + + EOD); + $this->simple_form->succ_href = $this->href; $this->simple_form->config['form']['class'] = 'row gy-3 mt-2'; $this->simple_form->config['submit_container']['class'] = 'col-12 text-center mt-3'; @@ -109,6 +139,13 @@ class UOJProblemConfigure { 'select_div_class' => 'col-8', 'default_value' => $this->problem_conf->getVal($key, $default_val), ] + $cfg); + $form->appendHTML(<< + $('#input-{$key}').change(function() { + problem_conf['{$key}'] = $(this).val(); + }); + + EOD); } public function addNumberInput(UOJForm $form, $key, $label, $default_val = '', $cfg = []) { @@ -124,6 +161,13 @@ class UOJProblemConfigure { return validateInt($x) ? '' : '必须为一个整数'; }, ] + $cfg); + $form->appendHTML(<< + $('#input-{$key}').change(function() { + problem_conf['{$key}'] = $(this).val(); + }); + + EOD); } public function addTimeLimitInput(UOJForm $form, $key, $label, $default_val = '', $cfg = []) { @@ -146,6 +190,13 @@ class UOJProblemConfigure { } }, ] + $cfg); + $form->appendHTML(<< + $('#input-{$key}').change(function() { + problem_conf['{$key}'] = $(this).val(); + }); + + EOD); } public function addTextInput(UOJForm $form, $key, $label, $default_val = '', $cfg = []) { @@ -160,6 +211,13 @@ class UOJProblemConfigure { return ctype_graph($x) ? '' : '必须仅包含除空格以外的可见字符'; }, ] + $cfg); + $form->appendHTML(<< + $('#input-{$key}').change(function() { + problem_conf['{$key}'] = $(this).val(); + }); + + EOD); } public function runAtServer() { @@ -168,9 +226,15 @@ class UOJProblemConfigure { public function onUpload(array &$vdata) { $conf = $this->problem_conf->conf; + $conf_keys = $this->conf_keys; + $n_tests = intval(UOJRequest::post('n_tests', 'validateUInt', $this->problem_conf->getVal('n_tests', 10))); - foreach (array_keys($this->conf_keys) as $key) { - $val = UOJRequest::post($key); + for ($i = 1; $i <= $n_tests; $i++) { + $conf_keys["point_score_$i"] = true; + } + + foreach (array_keys($conf_keys) as $key) { + $val = UOJRequest::post($key, 'is_string', ''); if ($key === 'use_builtin_judger') { if ($val === 'off') { unset($conf[$key]); diff --git a/web/js/uoj.js b/web/js/uoj.js index 2d74f7a..f53677c 100644 --- a/web/js/uoj.js +++ b/web/js/uoj.js @@ -1177,6 +1177,68 @@ $.fn.remote_submit_type_group = function(oj, pid, url, submit_type) { }); } +// problem_configure: point scores +$.fn.problem_configure_point_scores = function(problem_conf) { + return $(this).each(function() { + var _this = this; + var n_tests = parseInt(problem_conf['n_tests']); + + $(this).html(''); + + if (isNaN(n_tests) || n_tests <= 0) { + $(this).html('不可用。'); + } + + for (var i = 1; i <= n_tests; i++) { + var input_point_score = $(''); + + if (problem_conf['point_score_' + i]) { + input_point_score.val(problem_conf['point_score_' + i]); + } + + $(this).append( + $('
').append( + $('
') + .append($('
').append('')) + .append($('
').append(input_point_score)) + ) + ); + } + + $('.uoj-problem-configure-point-score-input', this).change(function() { + var full_score = 100; + var rest_tests = parseInt(problem_conf['n_tests'] || '10'); + var score_type = problem_conf['score_type'] || 'int'; + + $('.uoj-problem-configure-point-score-input', _this).each(function() { + var point_score = parseInt($(this).val()); + if (!isNaN(point_score)) { + full_score -= point_score; + rest_tests--; + } + }); + + $('.uoj-problem-configure-point-score-input', _this).each(function() { + if ($(this).val() == '') { + var val = full_score / rest_tests; + + if (score_type == 'int') { + val = Math.floor(val); + } else { + var decimal_places = parseInt(score_type.substring(5)); + + val = val.toFixed(decimal_places); + } + + $(this).attr('placeholder', val); + } + }); + }); + + $('.uoj-problem-configure-point-score-input', this).first().trigger('change'); + }); +}; + // custom test function custom_test_onsubmit(response_text, div_result, url) { if (response_text != '') {