mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-25 22:38:40 +00:00
refactor(web/problem): problem difficulty (#20)
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:
commit
6d0a665d8e
@ -617,10 +617,11 @@ CREATE TABLE `problems` (
|
||||
`is_hidden` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`submission_requirement` mediumtext COLLATE utf8mb4_unicode_ci,
|
||||
`hackable` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`extra_config` varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '{"view_content_type":"ALL","view_details_type":"ALL"}',
|
||||
`zan` int(11) NOT NULL DEFAULT '0',
|
||||
`ac_num` int(11) NOT NULL DEFAULT '0',
|
||||
`submit_num` int(11) NOT NULL DEFAULT '0',
|
||||
`extra_config` json NOT NULL,
|
||||
`zan` int NOT NULL DEFAULT '0',
|
||||
`ac_num` int NOT NULL DEFAULT '0',
|
||||
`submit_num` int NOT NULL DEFAULT '0',
|
||||
`difficulty` int NOT NULL DEFAULT '-1',
|
||||
`assigned_to_judger` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'any',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `assigned_to_judger` (`assigned_to_judger`),
|
||||
|
@ -250,8 +250,6 @@ if (UOJContest::cur()) {
|
||||
时间限制: <?= $time_limit ? "$time_limit s" : "N/A" ?>
|
||||
 
|
||||
空间限制: <?= $memory_limit ? "$memory_limit MB" : "N/A" ?>
|
||||
 
|
||||
上传者: <?= UOJProblem::cur()->getUploaderLink() ?>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
@ -381,9 +379,46 @@ if (UOJContest::cur()) {
|
||||
</li>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
<div class="card-footer bg-transparent">
|
||||
评价:<?= UOJProblem::cur()->getZanBlock() ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 题目信息卡片 -->
|
||||
<div class="card mb-2">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>上传者</span>
|
||||
<span><?= UOJProblem::cur()->getUploaderLink() ?></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>难度</span>
|
||||
<span><?= UOJProblem::getDifficultyHTML(UOJProblem::info('difficulty')) ?></span>
|
||||
</li>
|
||||
<?php if (Auth::check()) : ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>历史分数</span>
|
||||
<?php $his_score = DB::selectSingle(["select max(score)", "from submissions", "where", ["problem_id" => UOJProblem::info('id'), "submitter" => Auth::id()]]) ?>
|
||||
|
||||
<a class="<?= is_null($his_score) ? '' : 'uoj-score' ?>" href="<?= HTML::url('/submissions', ['params' => ['problem_id' => UOJProblem::info('id'), 'submitter' => Auth::id()]]) ?>">
|
||||
<?= is_null($his_score) ? '无' : $his_score ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>标签</span>
|
||||
<span>
|
||||
<?php foreach (UOJProblem::cur()->queryTags() as $tag) : ?>
|
||||
<a class="uoj-problem-tag">
|
||||
<span class="badge bg-secondary">
|
||||
<?= HTML::escape($tag) ?>
|
||||
</span>
|
||||
</a>
|
||||
<?php endforeach ?>
|
||||
</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>评价</span>
|
||||
<span><?= UOJProblem::cur()->getZanBlock() ?></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- 附件 -->
|
||||
@ -411,6 +446,7 @@ if (UOJContest::cur()) {
|
||||
if (UOJContest::cur() && UOJContest::cur()->progress() <= CONTEST_IN_PROGRESS) {
|
||||
$sidebar_config['upcoming_contests_hidden'] = '';
|
||||
}
|
||||
|
||||
uojIncludeView('sidebar', $sidebar_config);
|
||||
?>
|
||||
</aside>
|
||||
|
@ -656,7 +656,6 @@ $info_form->runAtServer();
|
||||
<div class="row">
|
||||
<!-- left col -->
|
||||
<div class="col-12 col-lg-9">
|
||||
|
||||
<h1>
|
||||
#<?= $problem['id'] ?>. <?= $problem['title'] ?> 管理
|
||||
</h1>
|
||||
|
@ -129,7 +129,7 @@ function getProblemTR($info) {
|
||||
);
|
||||
}
|
||||
if (isset($_COOKIE['show_difficulty'])) {
|
||||
$html .= HTML::tag('td', [], $problem->getExtraConfig('difficulty'));
|
||||
$html .= HTML::tag('td', [], UOJProblem::getDifficultyHTML($problem->info['difficulty']));
|
||||
}
|
||||
$html .= HTML::tag('td', [], ClickZans::getCntBlock($problem->info['zan']));
|
||||
$html .= HTML::tag_end('tr');
|
||||
@ -190,7 +190,7 @@ if (isset($_COOKIE['show_submit_mode'])) {
|
||||
$header .= '<th class="text-center" style="width:125px;">' . UOJLocale::get('problems::ac ratio') . '</th>';
|
||||
}
|
||||
if (isset($_COOKIE['show_difficulty'])) {
|
||||
$header .= '<th class="text-center" style="width:3em;">' . UOJLocale::get('problems::difficulty') . '</th>';
|
||||
$header .= '<th class="text-center" style="width:8em;">' . UOJLocale::get('problems::difficulty') . '</th>';
|
||||
}
|
||||
$header .= '<th class="text-center" style="width:50px;">' . UOJLocale::get('appraisal') . '</th>';
|
||||
$header .= '</tr>';
|
||||
|
@ -206,6 +206,7 @@ $pag = new Paginator($pag_config);
|
||||
|
||||
<!-- right col -->
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<!-- 题目导航 -->
|
||||
<div class="card card-default mb-2">
|
||||
<ul class="nav nav-pills nav-fill flex-column" role="tablist">
|
||||
<li class="nav-item text-start">
|
||||
@ -241,9 +242,46 @@ $pag = new Paginator($pag_config);
|
||||
</li>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
<div class="card-footer bg-transparent">
|
||||
评价:<?= UOJProblem::cur()->getZanBlock() ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 题目信息卡片 -->
|
||||
<div class="card mb-2">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>上传者</span>
|
||||
<span><?= UOJProblem::cur()->getUploaderLink() ?></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>难度</span>
|
||||
<span><?= UOJProblem::getDifficultyHTML(UOJProblem::info('difficulty')) ?></span>
|
||||
</li>
|
||||
<?php if (Auth::check()) : ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>历史分数</span>
|
||||
<?php $his_score = DB::selectSingle(["select max(score)", "from submissions", "where", ["problem_id" => UOJProblem::info('id'), "submitter" => Auth::id()]]) ?>
|
||||
|
||||
<a class="<?= is_null($his_score) ? '' : 'uoj-score' ?>" href="<?= HTML::url('/submissions', ['params' => ['problem_id' => UOJProblem::info('id'), 'submitter' => Auth::id()]]) ?>">
|
||||
<?= is_null($his_score) ? '无' : $his_score ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>标签</span>
|
||||
<span>
|
||||
<?php foreach (UOJProblem::cur()->queryTags() as $tag) : ?>
|
||||
<a class="uoj-problem-tag">
|
||||
<span class="badge bg-secondary">
|
||||
<?= HTML::escape($tag) ?>
|
||||
</span>
|
||||
</a>
|
||||
<?php endforeach ?>
|
||||
</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>评价</span>
|
||||
<span><?= UOJProblem::cur()->getZanBlock() ?></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card card-default mb-2">
|
||||
|
@ -62,6 +62,24 @@ $problem_editor->save = function ($data) {
|
||||
};
|
||||
|
||||
$problem_editor->runAtServer();
|
||||
|
||||
$difficulty_form = new UOJForm('difficulty');
|
||||
$difficulty_form->addSelect('difficulty', [
|
||||
'options' => UOJProblem::$difficulty,
|
||||
'default_value' => UOJProblem::info('difficulty'),
|
||||
]);
|
||||
$difficulty_form->handle = function () {
|
||||
DB::update([
|
||||
"update problems",
|
||||
"set", [
|
||||
"difficulty" => $_POST['difficulty'],
|
||||
],
|
||||
"where", [
|
||||
"id" => UOJProblem::info('id'),
|
||||
],
|
||||
]);
|
||||
};
|
||||
$difficulty_form->runAtServer();
|
||||
?>
|
||||
|
||||
<?php echoUOJPageHeader('题面编辑 - ' . HTML::stripTags(UOJProblem::info('title'))) ?>
|
||||
@ -153,7 +171,14 @@ $problem_editor->runAtServer();
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php uojIncludeView('sidebar') ?>
|
||||
<div class="card mt-3">
|
||||
<div class="card-header fw-bold">
|
||||
题目难度
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php $difficulty_form->printHTML() ?>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
|
@ -314,9 +314,46 @@ $submissions_sort_by_choice = !isset($_COOKIE['submissions-sort-by-code-length']
|
||||
</li>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
<div class="card-footer bg-transparent">
|
||||
评价:<?= UOJProblem::cur()->getZanBlock() ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 题目信息卡片 -->
|
||||
<div class="card mb-2">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>上传者</span>
|
||||
<span><?= UOJProblem::cur()->getUploaderLink() ?></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>难度</span>
|
||||
<span><?= UOJProblem::getDifficultyHTML(UOJProblem::info('difficulty')) ?></span>
|
||||
</li>
|
||||
<?php if (Auth::check()) : ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>历史分数</span>
|
||||
<?php $his_score = DB::selectSingle(["select max(score)", "from submissions", "where", ["problem_id" => UOJProblem::info('id'), "submitter" => Auth::id()]]) ?>
|
||||
|
||||
<a class="<?= is_null($his_score) ? '' : 'uoj-score' ?>" href="<?= HTML::url('/submissions', ['params' => ['problem_id' => UOJProblem::info('id'), 'submitter' => Auth::id()]]) ?>">
|
||||
<?= is_null($his_score) ? '无' : $his_score ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>标签</span>
|
||||
<span>
|
||||
<?php foreach (UOJProblem::cur()->queryTags() as $tag) : ?>
|
||||
<a class="uoj-problem-tag">
|
||||
<span class="badge bg-secondary">
|
||||
<?= HTML::escape($tag) ?>
|
||||
</span>
|
||||
</a>
|
||||
<?php endforeach ?>
|
||||
</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>评价</span>
|
||||
<span><?= UOJProblem::cur()->getZanBlock() ?></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<?php uojIncludeView('sidebar') ?>
|
||||
|
@ -158,6 +158,60 @@ class UOJForm {
|
||||
$this->addNoVal($name, $html);
|
||||
}
|
||||
|
||||
public function addSelect($name, $config) {
|
||||
$config += [
|
||||
'div_class' => '',
|
||||
'select_class' => 'form-select',
|
||||
'options' => [],
|
||||
'default_value' => '',
|
||||
'label' => '',
|
||||
'label_class' => 'form-check-label',
|
||||
'help' => '',
|
||||
'help_class' => 'form-text',
|
||||
'disabled' => false,
|
||||
];
|
||||
|
||||
$html = '';
|
||||
$html .= HTML::tag_begin('div', ['id' => "div-$name", 'class' => $config['div_class']]);
|
||||
|
||||
// Label
|
||||
if ($config['label']) {
|
||||
$html .= HTML::tag('label', [
|
||||
'class' => $config['label_class'],
|
||||
'for' => "input-$name",
|
||||
], $config['label']);
|
||||
}
|
||||
|
||||
// Select
|
||||
$html .= HTML::tag_begin('select', ['id' => "input-$name", 'name' => $name, 'class' => $config['select_class']]);
|
||||
|
||||
foreach ($config['options'] as $opt_name => $opt_label) {
|
||||
if ($opt_name == $config['default_value']) {
|
||||
$html .= HTML::tag('option', ['value' => $opt_name, 'selected' => 'selected'], $opt_label);
|
||||
} else {
|
||||
$html .= HTML::tag('option', ['value' => $opt_name], $opt_label);
|
||||
}
|
||||
}
|
||||
|
||||
$html .= HTML::tag_end('select');
|
||||
|
||||
// Help text
|
||||
if ($config['help']) {
|
||||
$html .= HTML::tag('div', ['class' => $config['help_class']], $config['help']);
|
||||
}
|
||||
|
||||
$html .= HTML::tag_end('div');
|
||||
|
||||
$this->add(
|
||||
$name,
|
||||
$html,
|
||||
function ($opt) use ($config) {
|
||||
return isset($config['options'][$opt]) ? '' : "无效选项";
|
||||
},
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
public function printHTML() {
|
||||
echo HTML::tag_begin('form', [
|
||||
'action' => UOJContext::requestURI(),
|
||||
|
@ -8,6 +8,28 @@ class UOJProblem {
|
||||
use UOJDataTrait;
|
||||
use UOJArticleTrait;
|
||||
|
||||
public static array $difficulty = [
|
||||
-1 => '暂无评定',
|
||||
1 => '入门',
|
||||
2 => '普及-',
|
||||
3 => '普及/提高-',
|
||||
4 => '普及+/提高',
|
||||
6 => '提高+/省选-',
|
||||
8 => '省选/NOI-',
|
||||
10 => 'NOI/NOI+/CTSC',
|
||||
];
|
||||
|
||||
public static array $difficulty_color = [
|
||||
-1 => '#bfbfbf',
|
||||
1 => '#fe4c61',
|
||||
2 => '#f39c11',
|
||||
3 => '#ffc116',
|
||||
4 => '#52c41a',
|
||||
6 => '#3498db',
|
||||
8 => '#9d3dcf',
|
||||
10 => '#0e1d69',
|
||||
];
|
||||
|
||||
public static function query($id) {
|
||||
if (!isset($id) || !validateUInt($id)) {
|
||||
return null;
|
||||
@ -56,6 +78,14 @@ class UOJProblem {
|
||||
return isSuperUser($user) || UOJUser::checkPermission($user, 'problems.create');
|
||||
}
|
||||
|
||||
public static function getDifficultyHTML($difficulty = -1) {
|
||||
$difficulty = (int)$difficulty;
|
||||
$difficulty_text = self::$difficulty[$difficulty] ?: self::$difficulty[-1];
|
||||
$difficulty_color = self::$difficulty_color[$difficulty] ?: self::$difficulty_color[-1];
|
||||
|
||||
return HTML::tag('span', ['class' => 'uoj-difficulty', 'style' => "color: $difficulty_color"], $difficulty_text);
|
||||
}
|
||||
|
||||
public function __construct($info) {
|
||||
$this->info = $info;
|
||||
}
|
||||
|
2
web/app/upgrade/20_problem_difficulty/up.sql
Normal file
2
web/app/upgrade/20_problem_difficulty/up.sql
Normal file
@ -0,0 +1,2 @@
|
||||
ALTER TABLE `problems` ADD `difficulty` int NOT NULL DEFAULT '-1' AFTER `submit_num`;
|
||||
ALTER TABLE `problems` MODIFY `extra_config` json NOT NULL;
|
91
web/app/upgrade/20_problem_difficulty/upgrade.php
Normal file
91
web/app/upgrade/20_problem_difficulty/upgrade.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
return function ($type) {
|
||||
if ($type == 'up_after_sql') {
|
||||
DB::init();
|
||||
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
for ($j = 0; $j < 10; $j++) {
|
||||
echo "Tag: {$i}.{$j}\n";
|
||||
|
||||
$tag_info = DB::selectAll([
|
||||
"select *",
|
||||
"from problems_tags",
|
||||
"where", [
|
||||
"tag" => "{$i}.{$j}",
|
||||
]
|
||||
]);
|
||||
|
||||
foreach ($tag_info as $tag) {
|
||||
DB::delete([
|
||||
"delete from problems_tags",
|
||||
"where", [
|
||||
"id" => $tag['id'],
|
||||
],
|
||||
]);
|
||||
|
||||
$problem = UOJProblem::query($tag['problem_id']);
|
||||
$extra_config = $problem->getExtraConfig();
|
||||
|
||||
$extra_config['difficulty'] = doubleval("{$i}.{$j}");
|
||||
|
||||
DB::update([
|
||||
"update problems",
|
||||
"set", [
|
||||
"extra_config" => json_encode($extra_config),
|
||||
],
|
||||
"where", [
|
||||
"id" => $problem->info['id'],
|
||||
],
|
||||
]);
|
||||
|
||||
echo "{$problem->info['id']}: {$extra_config['difficulty']}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
echo "Tag: DONE";
|
||||
|
||||
$problems = DB::selectAll("select * from problems");
|
||||
|
||||
foreach ($problems as $info) {
|
||||
$problem = new UOJProblem($info);
|
||||
|
||||
$difficulty = -1;
|
||||
$extra_config = $problem->getExtraConfig();
|
||||
|
||||
if (isset($extra_config['difficulty'])) {
|
||||
$old_difficulty = $extra_config['difficulty'];
|
||||
|
||||
if (0 <= $old_difficulty && $old_difficulty < 2) {
|
||||
$difficulty = 1;
|
||||
} else if (2 <= $old_difficulty && $old_difficulty < 3) {
|
||||
$difficulty = 2;
|
||||
} else if (3 <= $old_difficulty && $old_difficulty < 4) {
|
||||
$difficulty = 2;
|
||||
} else if (4 <= $old_difficulty && $old_difficulty < 5) {
|
||||
$difficulty = 4;
|
||||
} else if (5 <= $old_difficulty && $old_difficulty < 6) {
|
||||
$difficulty = 6;
|
||||
} else if (6 <= $old_difficulty && $old_difficulty < 8) {
|
||||
$difficulty = 8;
|
||||
} else if (8 <= $old_difficulty) {
|
||||
$difficulty = 10;
|
||||
}
|
||||
}
|
||||
|
||||
DB::update([
|
||||
"update problems",
|
||||
"set", [
|
||||
"difficulty" => $difficulty,
|
||||
],
|
||||
"where", [
|
||||
"id" => $problem->info['id'],
|
||||
]
|
||||
]);
|
||||
|
||||
echo "Problem: {$problem->info['id']}";
|
||||
}
|
||||
}
|
||||
};
|
@ -82,8 +82,9 @@ h6,
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: right;
|
||||
.uoj-difficulty {
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.uoj-table > tbody > tr:last-child,
|
||||
|
Loading…
Reference in New Issue
Block a user