From dbdc49e73aba0384466ed6569e0ad79ac3544060 Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Sun, 4 Dec 2022 17:27:16 +0800 Subject: [PATCH] refactor(web/problem): problem difficulty --- db/app_uoj233.sql | 9 +- web/app/controllers/problem_set.php | 4 +- .../controllers/problem_statement_manage.php | 27 +++++- web/app/models/UOJForm.php | 54 +++++++++++ web/app/models/UOJProblem.php | 30 ++++++ web/app/upgrade/20_problem_difficulty/up.sql | 2 + .../upgrade/20_problem_difficulty/upgrade.php | 91 +++++++++++++++++++ web/css/uoj-bs5.css | 5 +- 8 files changed, 213 insertions(+), 9 deletions(-) create mode 100644 web/app/upgrade/20_problem_difficulty/up.sql create mode 100644 web/app/upgrade/20_problem_difficulty/upgrade.php diff --git a/db/app_uoj233.sql b/db/app_uoj233.sql index 9706a68..4dd2aa8 100644 --- a/db/app_uoj233.sql +++ b/db/app_uoj233.sql @@ -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`), diff --git a/web/app/controllers/problem_set.php b/web/app/controllers/problem_set.php index 0de0224..2cbd656 100644 --- a/web/app/controllers/problem_set.php +++ b/web/app/controllers/problem_set.php @@ -116,7 +116,7 @@ function getProblemTR($info) { $html .= ''; } 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'); @@ -179,7 +179,7 @@ if (isset($_COOKIE['show_submit_mode'])) { $header .= '' . UOJLocale::get('problems::ac ratio') . ''; } if (isset($_COOKIE['show_difficulty'])) { - $header .= '' . UOJLocale::get('problems::difficulty') . ''; + $header .= '' . UOJLocale::get('problems::difficulty') . ''; } $header .= '' . UOJLocale::get('appraisal') . ''; $header .= ''; diff --git a/web/app/controllers/problem_statement_manage.php b/web/app/controllers/problem_statement_manage.php index a8cbd01..3abf647 100644 --- a/web/app/controllers/problem_statement_manage.php +++ b/web/app/controllers/problem_statement_manage.php @@ -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(); ?> @@ -153,7 +171,14 @@ $problem_editor->runAtServer(); - +
+
+ 题目难度 +
+
+ printHTML() ?> +
+
diff --git a/web/app/models/UOJForm.php b/web/app/models/UOJForm.php index e41d51b..de75caa 100644 --- a/web/app/models/UOJForm.php +++ b/web/app/models/UOJForm.php @@ -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(), diff --git a/web/app/models/UOJProblem.php b/web/app/models/UOJProblem.php index e5d2dec..2dfaa02 100644 --- a/web/app/models/UOJProblem.php +++ b/web/app/models/UOJProblem.php @@ -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; } diff --git a/web/app/upgrade/20_problem_difficulty/up.sql b/web/app/upgrade/20_problem_difficulty/up.sql new file mode 100644 index 0000000..5cd8680 --- /dev/null +++ b/web/app/upgrade/20_problem_difficulty/up.sql @@ -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; diff --git a/web/app/upgrade/20_problem_difficulty/upgrade.php b/web/app/upgrade/20_problem_difficulty/upgrade.php new file mode 100644 index 0000000..ab1635c --- /dev/null +++ b/web/app/upgrade/20_problem_difficulty/upgrade.php @@ -0,0 +1,91 @@ + "{$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']}"; + } + } +}; diff --git a/web/css/uoj-bs5.css b/web/css/uoj-bs5.css index dab351d..6d35ca9 100644 --- a/web/css/uoj-bs5.css +++ b/web/css/uoj-bs5.css @@ -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,