mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-08 14:48:41 +00:00
feat(problem/manage/data): subtasks configure
This commit is contained in:
parent
b3113238a2
commit
6c24bd9bf6
@ -37,7 +37,7 @@ class UOJProblemConfigure {
|
|||||||
private static function getCardHeader($title, $body_class = 'vstack gap-3') {
|
private static function getCardHeader($title, $body_class = 'vstack gap-3') {
|
||||||
return <<<EOD
|
return <<<EOD
|
||||||
<div class="col-12 col-md-6">
|
<div class="col-12 col-md-6">
|
||||||
<div class="card">
|
<div class="card h-100 overflow-hidden">
|
||||||
<div class="card-header fw-bold">
|
<div class="card-header fw-bold">
|
||||||
{$title}
|
{$title}
|
||||||
</div>
|
</div>
|
||||||
@ -99,10 +99,11 @@ class UOJProblemConfigure {
|
|||||||
|
|
||||||
$this->simple_form->appendHTML(static::getCardHeader('测试点分值', ''));
|
$this->simple_form->appendHTML(static::getCardHeader('测试点分值', ''));
|
||||||
$this->simple_form->appendHTML(<<<EOD
|
$this->simple_form->appendHTML(<<<EOD
|
||||||
<details>
|
<details id="div-point-score-container-outer">
|
||||||
<summary>展开/收起全部</summary>
|
<summary>展开/收起全部</summary>
|
||||||
<div id="div-point-score-container" class="row g-3 mt-0"></div>
|
<div id="div-point-score-container" class="row g-3 mt-0"></div>
|
||||||
</details>
|
</details>
|
||||||
|
<div id="div-point-score-unavailable" style="display: none;">在启用 Subtask 时「测试点分值」不可用。</div>
|
||||||
EOD);
|
EOD);
|
||||||
$this->simple_form->appendHTML(static::getCardFooter());
|
$this->simple_form->appendHTML(static::getCardFooter());
|
||||||
$this->simple_form->appendHTML(<<<EOD
|
$this->simple_form->appendHTML(<<<EOD
|
||||||
@ -123,6 +124,58 @@ class UOJProblemConfigure {
|
|||||||
</script>
|
</script>
|
||||||
EOD);
|
EOD);
|
||||||
|
|
||||||
|
$this->simple_form->appendHTML(static::getCardHeader('Subtask 配置', 'p-0'));
|
||||||
|
$this->simple_form->appendHTML(<<<EOD
|
||||||
|
<div class="form-check form-switch m-3">
|
||||||
|
<input class="form-check-input" type="checkbox" role="switch" id="input-enable_subtasks">
|
||||||
|
<label class="form-check-label" for="input-enable_subtasks">启用 Subtask</label>
|
||||||
|
</div>
|
||||||
|
<div id="div-subtasks-container"></div>
|
||||||
|
EOD);
|
||||||
|
$this->simple_form->appendHTML(static::getCardFooter());
|
||||||
|
$this->simple_form->appendHTML(<<<EOD
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#input-enable_subtasks').change(function() {
|
||||||
|
if (this.checked) {
|
||||||
|
$('#div-point-score-container-outer').hide();
|
||||||
|
$('#div-point-score-unavailable').show();
|
||||||
|
$('#div-subtasks-container').problem_configure_subtasks(problem_conf);
|
||||||
|
} else {
|
||||||
|
$('#div-point-score-container-outer').show();
|
||||||
|
$('#div-point-score-unavailable').hide();
|
||||||
|
$('#div-subtasks-container').empty();
|
||||||
|
$('.uoj-problem-configure-point-score-input').val('');
|
||||||
|
|
||||||
|
var subtask_keys = Object.keys(problem_conf).filter(function(key) {
|
||||||
|
return /^subtask_/.test(key);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < subtask_keys.length; ++i) {
|
||||||
|
problem_conf[subtask_keys[i]] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
problem_conf['n_subtasks'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#problem-conf-preview').problem_conf_preview(problem_conf);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (problem_conf['n_subtasks']) {
|
||||||
|
$('#input-enable_subtasks').prop('checked', true).trigger('change');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
EOD);
|
||||||
|
|
||||||
|
$this->simple_form->appendHTML(<<<EOD
|
||||||
|
<script>
|
||||||
|
$(document).on("keydown", "form", function(event) {
|
||||||
|
return event.key != "Enter";
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
EOD);
|
||||||
|
|
||||||
$this->simple_form->succ_href = $this->href;
|
$this->simple_form->succ_href = $this->href;
|
||||||
$this->simple_form->config['form']['class'] = 'row gy-3';
|
$this->simple_form->config['form']['class'] = 'row gy-3';
|
||||||
$this->simple_form->config['submit_container']['class'] = 'col-12 text-center mt-3';
|
$this->simple_form->config['submit_container']['class'] = 'col-12 text-center mt-3';
|
||||||
@ -137,7 +190,7 @@ class UOJProblemConfigure {
|
|||||||
$form->addSelect($key, [
|
$form->addSelect($key, [
|
||||||
'options' => $options,
|
'options' => $options,
|
||||||
'label' => $label,
|
'label' => $label,
|
||||||
'div_class' => 'row',
|
'div_class' => 'row gx-2',
|
||||||
'label_class' => 'col-form-label col-4',
|
'label_class' => 'col-form-label col-4',
|
||||||
'select_div_class' => 'col-8',
|
'select_div_class' => 'col-8',
|
||||||
'default_value' => $this->problem_conf->getVal($key, $default_val),
|
'default_value' => $this->problem_conf->getVal($key, $default_val),
|
||||||
@ -157,7 +210,7 @@ class UOJProblemConfigure {
|
|||||||
$form->addInput($key, [
|
$form->addInput($key, [
|
||||||
'type' => 'number',
|
'type' => 'number',
|
||||||
'label' => $label,
|
'label' => $label,
|
||||||
'div_class' => 'row',
|
'div_class' => 'row gx-2',
|
||||||
'label_class' => 'col-form-label col-4',
|
'label_class' => 'col-form-label col-4',
|
||||||
'input_div_class' => 'col-8',
|
'input_div_class' => 'col-8',
|
||||||
'default_value' => $this->problem_conf->getVal($key, $default_val),
|
'default_value' => $this->problem_conf->getVal($key, $default_val),
|
||||||
@ -181,7 +234,7 @@ class UOJProblemConfigure {
|
|||||||
'type' => 'number',
|
'type' => 'number',
|
||||||
'label' => $label,
|
'label' => $label,
|
||||||
'input_attrs' => ['step' => 0.001],
|
'input_attrs' => ['step' => 0.001],
|
||||||
'div_class' => 'row',
|
'div_class' => 'row gx-2',
|
||||||
'label_class' => 'col-form-label col-4',
|
'label_class' => 'col-form-label col-4',
|
||||||
'input_div_class' => 'col-8',
|
'input_div_class' => 'col-8',
|
||||||
'default_value' => $this->problem_conf->getVal($key, $default_val),
|
'default_value' => $this->problem_conf->getVal($key, $default_val),
|
||||||
@ -209,7 +262,7 @@ class UOJProblemConfigure {
|
|||||||
$this->conf_keys[$key] = true;
|
$this->conf_keys[$key] = true;
|
||||||
$form->addInput($key, [
|
$form->addInput($key, [
|
||||||
'label' => $label,
|
'label' => $label,
|
||||||
'div_class' => 'row',
|
'div_class' => 'row gx-2',
|
||||||
'label_class' => 'col-form-label col-4',
|
'label_class' => 'col-form-label col-4',
|
||||||
'input_div_class' => 'col-8',
|
'input_div_class' => 'col-8',
|
||||||
'default_value' => $this->problem_conf->getVal($key, $default_val),
|
'default_value' => $this->problem_conf->getVal($key, $default_val),
|
||||||
@ -235,11 +288,33 @@ class UOJProblemConfigure {
|
|||||||
$conf = $this->problem_conf->conf;
|
$conf = $this->problem_conf->conf;
|
||||||
$conf_keys = $this->conf_keys;
|
$conf_keys = $this->conf_keys;
|
||||||
$n_tests = intval(UOJRequest::post('n_tests', 'validateUInt', $this->problem_conf->getVal('n_tests', 10)));
|
$n_tests = intval(UOJRequest::post('n_tests', 'validateUInt', $this->problem_conf->getVal('n_tests', 10)));
|
||||||
|
$n_subtasks = intval(UOJRequest::post('n_subtasks', 'validateUInt', $this->problem_conf->getVal('n_subtasks', 0)));
|
||||||
|
|
||||||
for ($i = 1; $i <= $n_tests; $i++) {
|
for ($i = 1; $i <= $n_tests; $i++) {
|
||||||
$conf_keys["point_score_$i"] = true;
|
$conf_keys["point_score_$i"] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$conf_keys['n_subtasks'] = true;
|
||||||
|
for ($i = 1; $i <= $n_subtasks; $i++) {
|
||||||
|
$conf_keys["subtask_type_$i"] = true;
|
||||||
|
$conf_keys["subtask_score_$i"] = true;
|
||||||
|
$conf_keys["subtask_end_$i"] = true;
|
||||||
|
$conf_keys["subtask_used_time_type_$i"] = true;
|
||||||
|
|
||||||
|
// $conf_keys["subtask_dependence_$i"] = true;
|
||||||
|
|
||||||
|
// $subtask_dependence_str = UOJRequest::post("subtask_dependence_$i", 'is_string', '');
|
||||||
|
|
||||||
|
// if ($subtask_dependence_str == 'many') {
|
||||||
|
// $subtask_dependence_cnt = 0;
|
||||||
|
|
||||||
|
// while (UOJRequest::post("subtask_dependence_{$i}_{$subtask_dependence_cnt}", 'is_string', '') != '') {
|
||||||
|
// $subtask_dependence_cnt++;
|
||||||
|
// $conf_keys["subtask_dependence_{$i}_{$subtask_dependence_cnt}"] = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
foreach (array_keys($conf_keys) as $key) {
|
foreach (array_keys($conf_keys) as $key) {
|
||||||
$val = UOJRequest::post($key, 'is_string', '');
|
$val = UOJRequest::post($key, 'is_string', '');
|
||||||
if ($key === 'use_builtin_judger') {
|
if ($key === 'use_builtin_judger') {
|
||||||
|
148
web/js/uoj.js
148
web/js/uoj.js
@ -1212,10 +1212,12 @@ $.fn.problem_configure_point_scores = function(problem_conf) {
|
|||||||
var _this = this;
|
var _this = this;
|
||||||
var n_tests = parseInt(problem_conf['n_tests']);
|
var n_tests = parseInt(problem_conf['n_tests']);
|
||||||
|
|
||||||
$(this).html('');
|
$(this).empty();
|
||||||
|
|
||||||
if (isNaN(n_tests) || n_tests <= 0) {
|
if (isNaN(n_tests) || n_tests <= 0) {
|
||||||
$(this).html('不可用。');
|
$(this).html('不可用。');
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 1; i <= n_tests; i++) {
|
for (var i = 1; i <= n_tests; i++) {
|
||||||
@ -1275,6 +1277,150 @@ $.fn.problem_configure_point_scores = function(problem_conf) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// problem_configure: subtasks
|
||||||
|
$.fn.problem_configure_subtasks = function(problem_conf) {
|
||||||
|
return $(this).each(function() {
|
||||||
|
var _this = this;
|
||||||
|
var n_subtasks = parseInt(problem_conf['n_subtasks'] || '0');
|
||||||
|
|
||||||
|
$(this).empty();
|
||||||
|
|
||||||
|
if (isNaN(n_subtasks)) {
|
||||||
|
$(this).html('不可用。');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var input_n_subtasks = $('<input class="form-control" type="number" name="n_subtasks" id="input-n_subtasks" />');
|
||||||
|
var div_subtasks = $('<div class="list-group list-group-flush border-top" />');
|
||||||
|
|
||||||
|
if (n_subtasks) {
|
||||||
|
input_n_subtasks.val(n_subtasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(this).append(
|
||||||
|
$('<div class="m-3" />').append(
|
||||||
|
$('<div class="row" />').append(
|
||||||
|
$('<div class="col-4" />').append('<label for="input-n_subtasks" class="col-form-label">子任务数</label>')
|
||||||
|
).append(
|
||||||
|
$('<div class="col-8" />').append(input_n_subtasks)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).append(div_subtasks);
|
||||||
|
|
||||||
|
input_n_subtasks.change(function() {
|
||||||
|
div_subtasks.empty();
|
||||||
|
|
||||||
|
var n_subtasks = parseInt(input_n_subtasks.val() || '0');
|
||||||
|
problem_conf['n_subtasks'] = input_n_subtasks.val();
|
||||||
|
|
||||||
|
for (var i = 1; i <= n_subtasks; i++) {
|
||||||
|
var input_subtask_type = $('<select class="form-select form-select-sm" name="subtask_type_' + i + '" id="input-subtask_type_' + i + '" />');
|
||||||
|
var input_subtask_end = $('<input class="form-control form-control-sm uoj-problem-configure-subtask-end-input" type="number" name="subtask_end_' + i + '" id="input-subtask_end_' + i + '" />');
|
||||||
|
var input_subtask_score = $('<input class="form-control form-control-sm uoj-problem-configure-subtask-score-input" type="number" name="subtask_score_' + i + '" id="input-subtask_score_' + i + '" />');
|
||||||
|
var input_subtask_used_time_type = $('<select class="form-select form-select-sm" name="subtask_used_time_type_' + i + '" id="input-subtask_used_time_type_' + i + '" />');
|
||||||
|
|
||||||
|
input_subtask_type
|
||||||
|
.append($('<option value="packed" />').text('错一个就零分'))
|
||||||
|
.append($('<option value="min" />').text('得分取所有测试点中的最小值'));
|
||||||
|
input_subtask_used_time_type
|
||||||
|
.append($('<option value="sum" />').text('全部相加'))
|
||||||
|
.append($('<option value="max" />').text('取所有测试点中的最大值'));
|
||||||
|
|
||||||
|
(function(i) {
|
||||||
|
input_subtask_type.change(function() {
|
||||||
|
problem_conf['subtask_type_' + i] = $(this).val();
|
||||||
|
$('#problem-conf-preview').problem_conf_preview(problem_conf);
|
||||||
|
});
|
||||||
|
|
||||||
|
input_subtask_end.change(function() {
|
||||||
|
problem_conf['subtask_end_' + i] = $(this).val();
|
||||||
|
$('#problem-conf-preview').problem_conf_preview(problem_conf);
|
||||||
|
})
|
||||||
|
|
||||||
|
input_subtask_score.change(function() {
|
||||||
|
problem_conf['subtask_score_' + i] = $(this).val();
|
||||||
|
$('#problem-conf-preview').problem_conf_preview(problem_conf);
|
||||||
|
});
|
||||||
|
|
||||||
|
input_subtask_used_time_type.change(function() {
|
||||||
|
problem_conf['subtask_used_time_type_' + i] = $(this).val();
|
||||||
|
$('#problem-conf-preview').problem_conf_preview(problem_conf);
|
||||||
|
});
|
||||||
|
})(i);
|
||||||
|
|
||||||
|
div_subtasks.append(
|
||||||
|
$('<div class="list-group-item" />').append(
|
||||||
|
$('<div class="fw-bold" />').text('Subtask #' + i)
|
||||||
|
).append(
|
||||||
|
$('<div />').append(
|
||||||
|
$('<div class="row mt-2" />').append(
|
||||||
|
$('<div class="col-sm-6" />').append('<label for="input-subtask_type_' + i + '" class="col-form-label col-form-label-sm">评分类型</label>')
|
||||||
|
).append(
|
||||||
|
$('<div class="col-sm-6" />').append(input_subtask_type)
|
||||||
|
)
|
||||||
|
).append(
|
||||||
|
$('<div class="row mt-2" />').append(
|
||||||
|
$('<div class="col-sm-6" />').append('<label for="input-subtask_end_' + i + '" class="col-form-label col-form-label-sm">最后一个测试点的编号</label>')
|
||||||
|
).append(
|
||||||
|
$('<div class="col-sm-6" />').append(input_subtask_end)
|
||||||
|
)
|
||||||
|
).append(
|
||||||
|
$('<div class="row mt-2" />').append(
|
||||||
|
$('<div class="col-sm-6" />').append('<label for="input-subtask_score_' + i + '" class="col-form-label col-form-label-sm">分数</label>')
|
||||||
|
).append(
|
||||||
|
$('<div class="col-sm-6" />').append(input_subtask_score)
|
||||||
|
)
|
||||||
|
).append(
|
||||||
|
$('<div class="row mt-2" />').append(
|
||||||
|
$('<div class="col-sm-6" />').append('<label for="input-subtask_used_time_type_' + i + '" class="col-form-label col-form-label-sm">程序用时统计方式</label>')
|
||||||
|
).append(
|
||||||
|
$('<div class="col-sm-6" />').append(input_subtask_used_time_type)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.uoj-problem-configure-subtask-score-input', _this).change(function() {
|
||||||
|
var full_score = 100;
|
||||||
|
var rest_subtasks = parseInt(problem_conf['n_subtasks'] || '10');
|
||||||
|
var score_type = problem_conf['score_type'] || 'int';
|
||||||
|
|
||||||
|
$('.uoj-problem-configure-subtask-score-input', _this).each(function() {
|
||||||
|
var subtask_score = parseInt($(this).val());
|
||||||
|
|
||||||
|
if (!isNaN(subtask_score)) {
|
||||||
|
full_score -= subtask_score;
|
||||||
|
rest_subtasks--;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.uoj-problem-configure-subtask-score-input', _this).each(function() {
|
||||||
|
if ($(this).val() == '') {
|
||||||
|
var val = full_score / rest_subtasks;
|
||||||
|
|
||||||
|
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-subtask-score-input', _this).first().trigger('change');
|
||||||
|
$('#problem-conf-preview').problem_conf_preview(problem_conf);
|
||||||
|
});
|
||||||
|
|
||||||
|
input_n_subtasks.trigger('change');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// custom test
|
// custom test
|
||||||
function custom_test_onsubmit(response_text, div_result, url) {
|
function custom_test_onsubmit(response_text, div_result, url) {
|
||||||
if (response_text != '') {
|
if (response_text != '') {
|
||||||
|
Loading…
Reference in New Issue
Block a user