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();
-
+
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,