mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-22 14:48:41 +00:00
refactor(web/problem): Codeforces 风格的题目难度评价系统 (#21)
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Co-authored-by: Fengyu Xie <63272948+Ignotus0@users.noreply.github.com> Co-authored-by: Jiaxi Li <91811830+RevolutionBP@users.noreply.github.com> Co-authored-by: Wenkuo Yu <82705676+youwike@users.noreply.github.com> Co-authored-by: Haosen Li <91672298+Johnsonloy@users.noreply.github.com> Co-authored-by: Baoshuo Ren <47095648+renbaoshuo@users.noreply.github.com>
This commit is contained in:
commit
3f2a6feea2
@ -54,7 +54,7 @@ function getProblemTR($info) {
|
||||
)
|
||||
);
|
||||
}
|
||||
$html .= HTML::tag('td', [], UOJProblem::getDifficultyHTML($problem->info['difficulty']));
|
||||
$html .= HTML::tag('td', [], $problem->getDifficultyHTML());
|
||||
$html .= HTML::tag('td', [], ClickZans::getCntBlock($problem->info['zan']));
|
||||
$html .= HTML::tag_end('tr');
|
||||
return $html;
|
||||
@ -66,7 +66,7 @@ $header .= '<th>' . UOJLocale::get('problems::problem') . '</th>';
|
||||
if (isset($_COOKIE['show_submit_mode'])) {
|
||||
$header .= '<th class="text-center" style="width:125px;">' . UOJLocale::get('problems::ac ratio') . '</th>';
|
||||
}
|
||||
$header .= '<th class="text-center" style="width:8em;">' . UOJLocale::get('problems::difficulty') . '</th>';
|
||||
$header .= '<th class="text-center" style="width:4em;">' . UOJLocale::get('problems::difficulty') . '</th>';
|
||||
$header .= '<th class="text-center" style="width:50px;">' . UOJLocale::get('appraisal') . '</th>';
|
||||
$header .= '</tr>';
|
||||
|
||||
|
@ -390,7 +390,7 @@ if (UOJContest::cur()) {
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>难度</span>
|
||||
<span><?= UOJProblem::getDifficultyHTML(UOJProblem::info('difficulty')) ?></span>
|
||||
<span><?= UOJProblem::cur()->getDifficultyHTML() ?></span>
|
||||
</li>
|
||||
<?php if (Auth::check()) : ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
|
@ -553,29 +553,6 @@ $solution_view_type_form->handle = function () {
|
||||
};
|
||||
$solution_view_type_form->submit_button_config['class_str'] = 'btn btn-warning d-block w-100 mt-2';
|
||||
|
||||
$difficulty_form = new UOJBs4Form('difficulty');
|
||||
$difficulty_form->addVInput(
|
||||
'difficulty',
|
||||
'text',
|
||||
'难度系数',
|
||||
$problem_extra_config['difficulty'],
|
||||
function ($str) {
|
||||
if (!is_numeric($str)) {
|
||||
return '难度系数必须是一个数字';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$difficulty_form->handle = function () {
|
||||
global $problem, $problem_extra_config;
|
||||
$config = $problem_extra_config;
|
||||
$config['difficulty'] = $_POST['difficulty'] + 0;
|
||||
$esc_config = DB::escape(json_encode($config));
|
||||
DB::query("update problems set extra_config = '$esc_config' where id = '{$problem['id']}'");
|
||||
};
|
||||
$difficulty_form->submit_button_config['class_str'] = 'btn btn-warning d-block w-100 mt-2';
|
||||
|
||||
if ($problem['hackable']) {
|
||||
$test_std_form = new UOJBs4Form('test_std');
|
||||
$test_std_form->handle = function () use ($problem, $data_disp) {
|
||||
@ -643,7 +620,6 @@ if ($problem['hackable']) {
|
||||
$hackable_form->runAtServer();
|
||||
$view_type_form->runAtServer();
|
||||
$solution_view_type_form->runAtServer();
|
||||
$difficulty_form->runAtServer();
|
||||
$data_form->runAtServer();
|
||||
$clear_data_form->runAtServer();
|
||||
$rejudge_form->runAtServer();
|
||||
@ -803,13 +779,6 @@ $info_form->runAtServer();
|
||||
<div class="mt-2">
|
||||
<button type="button" class="btn d-block w-100 btn-primary" data-bs-toggle="modal" data-bs-target="#ProblemSettingsFileModal">试题配置</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<button id="button-difficulty" type="button" class="btn d-block w-100 btn-primary" onclick="$('#div-difficulty').toggle('fast');">难度系数</button>
|
||||
<div class="mt-2" id="div-difficulty" style="display:none; padding-left:5px; padding-right:5px;">
|
||||
<?php $difficulty_form->printHTML(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
|
@ -128,7 +128,7 @@ function getProblemTR($info) {
|
||||
)
|
||||
);
|
||||
}
|
||||
$html .= HTML::tag('td', [], UOJProblem::getDifficultyHTML($problem->info['difficulty']));
|
||||
$html .= HTML::tag('td', [], $problem->getDifficultyHTML());
|
||||
$html .= HTML::tag('td', [], ClickZans::getCntBlock($problem->info['zan']));
|
||||
$html .= HTML::tag_end('tr');
|
||||
return $html;
|
||||
@ -177,8 +177,12 @@ if (Auth::check() && isset($_GET['my'])) {
|
||||
$cond['problems.uploader'] = Auth::id();
|
||||
}
|
||||
|
||||
if (isset($_GET['difficulty']) && $_GET['difficulty']) {
|
||||
$cond['problems.difficulty'] = $_GET['difficulty'];
|
||||
if (isset($_GET['min_difficulty']) && $_GET['min_difficulty']) {
|
||||
$cond[] = ['problems.difficulty', '>=', $_GET['min_difficulty']];
|
||||
}
|
||||
|
||||
if (isset($_GET['max_difficulty']) && $_GET['max_difficulty']) {
|
||||
$cond[] = ['problems.difficulty', '<=', $_GET['max_difficulty']];
|
||||
}
|
||||
|
||||
if (empty($cond)) {
|
||||
@ -191,7 +195,7 @@ $header .= '<th>' . UOJLocale::get('problems::problem') . '</th>';
|
||||
if (isset($_COOKIE['show_submit_mode'])) {
|
||||
$header .= '<th class="text-center" style="width:125px;">' . UOJLocale::get('problems::ac ratio') . '</th>';
|
||||
}
|
||||
$header .= '<th class="text-center" style="width:8em;">' . UOJLocale::get('problems::difficulty') . '</th>';
|
||||
$header .= '<th class="text-center" style="width:4em;">' . UOJLocale::get('problems::difficulty') . '</th>';
|
||||
$header .= '<th class="text-center" style="width:50px;">' . UOJLocale::get('appraisal') . '</th>';
|
||||
$header .= '</tr>';
|
||||
|
||||
@ -247,8 +251,7 @@ $pag = new Paginator([
|
||||
|
||||
<div class="row">
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
|
||||
<div class="col-md-9">
|
||||
<!-- title -->
|
||||
<div class="d-flex justify-content-between">
|
||||
<h1>
|
||||
@ -335,8 +338,7 @@ $pag = new Paginator([
|
||||
<!-- end left col -->
|
||||
|
||||
<!-- right col -->
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
|
||||
<aside class="col-md-3 mt-3 mt-md-0">
|
||||
<!-- search bar -->
|
||||
<form method="get" class="mb-3" id="form-problem_search">
|
||||
<div class="input-group mb-3">
|
||||
@ -363,15 +365,20 @@ $pag = new Paginator([
|
||||
</div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<label class="col-sm-3 col-form-label" for="input-difficulty">难度</label>
|
||||
<div class="col-sm-9">
|
||||
<select id="input-difficulty" name="difficulty" class="form-select">
|
||||
<option value="">全部</option>
|
||||
<?php foreach (UOJProblem::$difficulty as $opt_name => $opt_value) : ?>
|
||||
<?= HTML::option($opt_name, $opt_value, $opt_name == $_GET['difficulty']) ?>
|
||||
<?php endforeach ?>
|
||||
</select>
|
||||
|
||||
<div class="card mt-3">
|
||||
<div class="card-header fw-bold">
|
||||
题目难度
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="input-group input-group-sm">
|
||||
<input type="text" class="form-control" name="min_difficulty" id="input-min_difficulty" maxlength="4" style="width:4em" placeholder="800" value="<?= HTML::escape($_GET['min_difficulty']) ?>" autocomplete="off" />
|
||||
<span class="input-group-text">~</span>
|
||||
<input type="text" class="form-control" name="max_difficulty" id="input-max_difficulty" maxlength="4" style="width:4em" placeholder="3500" value="<?= HTML::escape($_GET['max_difficulty']) ?>" autocomplete="off" />
|
||||
<button type="submit" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-funnel"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -253,7 +253,7 @@ $pag = new Paginator($pag_config);
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>难度</span>
|
||||
<span><?= UOJProblem::getDifficultyHTML(UOJProblem::info('difficulty')) ?></span>
|
||||
<span><?= UOJProblem::cur()->getDifficultyHTML() ?></span>
|
||||
</li>
|
||||
<?php if (Auth::check()) : ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
|
@ -65,7 +65,7 @@ $problem_editor->runAtServer();
|
||||
|
||||
$difficulty_form = new UOJForm('difficulty');
|
||||
$difficulty_form->addSelect('difficulty', [
|
||||
'options' => UOJProblem::$difficulty,
|
||||
'options' => array_combine(UOJProblem::$difficulty, UOJProblem::$difficulty),
|
||||
'default_value' => UOJProblem::info('difficulty'),
|
||||
]);
|
||||
$difficulty_form->handle = function () {
|
||||
|
@ -325,7 +325,7 @@ $submissions_sort_by_choice = !isset($_COOKIE['submissions-sort-by-code-length']
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>难度</span>
|
||||
<span><?= UOJProblem::getDifficultyHTML(UOJProblem::info('difficulty')) ?></span>
|
||||
<span><?= UOJProblem::cur()->getDifficultyHTML() ?></span>
|
||||
</li>
|
||||
<?php if (Auth::check()) : ?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
|
@ -9,25 +9,45 @@ class UOJProblem {
|
||||
use UOJArticleTrait;
|
||||
|
||||
public static array $difficulty = [
|
||||
-1 => '暂无评定',
|
||||
1 => '入门',
|
||||
2 => '普及-',
|
||||
3 => '普及/提高-',
|
||||
4 => '普及+/提高',
|
||||
6 => '提高+/省选-',
|
||||
8 => '省选/NOI-',
|
||||
10 => 'NOI/NOI+/CTSC',
|
||||
800,
|
||||
1000,
|
||||
1200,
|
||||
1400,
|
||||
1600,
|
||||
1800,
|
||||
1900,
|
||||
2000,
|
||||
2100,
|
||||
2200,
|
||||
2300,
|
||||
2400,
|
||||
2500,
|
||||
2700,
|
||||
2900,
|
||||
3100,
|
||||
3300,
|
||||
3500,
|
||||
];
|
||||
|
||||
public static array $difficulty_color = [
|
||||
-1 => '#bfbfbf',
|
||||
1 => '#fe4c61',
|
||||
2 => '#f39c11',
|
||||
3 => '#ffc116',
|
||||
4 => '#52c41a',
|
||||
6 => '#3498db',
|
||||
8 => '#9d3dcf',
|
||||
10 => '#0e1d69',
|
||||
800 => '#008000',
|
||||
1000 => '#008000',
|
||||
1200 => '#00c0c0',
|
||||
1400 => '#00c0c0',
|
||||
1600 => '#0000ff',
|
||||
1800 => '#0000ff',
|
||||
1900 => '#0000ff',
|
||||
2000 => '#c0c000',
|
||||
2100 => '#c0c000',
|
||||
2200 => '#c0c000',
|
||||
2300 => '#c0c000',
|
||||
2400 => '#ff8000',
|
||||
2500 => '#ff8000',
|
||||
2700 => '#ff8000',
|
||||
2900 => '#ff0000',
|
||||
3100 => '#ff0000',
|
||||
3300 => '#aa0000',
|
||||
3500 => '#aa0000',
|
||||
];
|
||||
|
||||
public static function query($id) {
|
||||
@ -78,14 +98,6 @@ 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;
|
||||
}
|
||||
@ -128,6 +140,14 @@ class UOJProblem {
|
||||
return UOJUser::getLink($this->info['uploader'] ?: "root");
|
||||
}
|
||||
|
||||
public function getDifficultyHTML() {
|
||||
$difficulty = (int)$this->info['difficulty'];
|
||||
$difficulty_text = in_array($difficulty, static::$difficulty) ? $difficulty : '-';
|
||||
$difficulty_color = in_array($difficulty, static::$difficulty) ? static::$difficulty_color[$difficulty] : '#7e7e7e';
|
||||
|
||||
return HTML::tag('span', ['class' => 'uoj-difficulty', 'style' => "color: $difficulty_color"], $difficulty_text);
|
||||
}
|
||||
|
||||
public function findInContests() {
|
||||
$res = DB::selectAll([
|
||||
"select contest_id from contests_problems",
|
||||
|
43
web/app/upgrade/21_problem_difficulty/upgrade.php
Normal file
43
web/app/upgrade/21_problem_difficulty/upgrade.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
return function ($type) {
|
||||
if ($type == 'up') {
|
||||
DB::init();
|
||||
|
||||
$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 = (float)$extra_config['difficulty'];
|
||||
|
||||
$difficulty = (int)(3.0 * $old_difficulty + 5) * 100;
|
||||
$difficulty = (function ($search, $arr) {
|
||||
$closest = null;
|
||||
foreach ($arr as $item) {
|
||||
if ($closest === null || abs($search - $closest) > abs($item - $search)) {
|
||||
$closest = $item;
|
||||
}
|
||||
}
|
||||
return $closest;
|
||||
})($difficulty, UOJProblem::$difficulty);
|
||||
}
|
||||
|
||||
DB::update([
|
||||
"update problems",
|
||||
"set", [
|
||||
"difficulty" => $difficulty,
|
||||
],
|
||||
"where", [
|
||||
"id" => $problem->info['id'],
|
||||
]
|
||||
]);
|
||||
|
||||
echo "Problem: {$problem->info['id']} ({$difficulty})\n";
|
||||
}
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user