创新实训(八)——题目相关的逻辑处理解释

news/2024/9/23 0:43:36

题目部分

题目是整个OJ系统的练习基础,无论是平时学生的练习还是比赛时的准备用题,题目系统在OJ中都是至关重要的。在controllers文件夹下,负责题目部分的代码文件分别为:problem_set.php,problem.php,problem_statistics.php,problem_data_manage.php,problem_statement_manage.php,problem_managers_manage.php。以下是具体的详细内容

题目列表

problem_set.php中,文件主要用于管理和展示题目列表。以下是代码的详细解释:

1. 引入库

requirePHPLib('form');
requirePHPLib('judger');
requirePHPLib('data');

这些函数用于引入需要的库文件,分别用于表单处理、评测系统和数据操作。

2. 新增题目按钮

if (isSuperUser($myUser)) {$new_problem_form = new UOJForm('new_problem');$new_problem_form->handle = function() {DB::query("insert into problems (title, is_hidden, submission_requirement) values ('New Problem', 1, '{}')");$id = DB::insert_id();DB::query("insert into problems_contents (id, statement, statement_md) values ($id, '', '')");dataNewProblem($id);};$new_problem_form->submit_button_config['align'] = 'right';$new_problem_form->submit_button_config['class_str'] = 'btn btn-primary';$new_problem_form->submit_button_config['text'] = UOJLocale::get('problems::add new');$new_problem_form->submit_button_config['smart_confirm'] = '';$new_problem_form->runAtServer();
}
  • 检查当前用户是否是超级用户,如果是,则显示一个用于新增题目的表单。
  • 当表单提交时,插入一条新题目记录到problems表,并获取新题目的ID。
  • 插入一条空的题目内容记录到problems_contents表。
  • 表单按钮的样式和文本配置。

3. 打印每个题目

function echoProblem($problem) {global $myUser;if (isProblemVisibleToUser($problem, $myUser)) {echo '<tr class="text-center">';if ($problem['submission_id']) {echo '<td class="success">';} else {echo '<td>';}echo '#', $problem['id'], '</td>';echo '<td class="text-left">';if ($problem['is_hidden']) {echo ' <span class="text-danger">[隐藏]</span> ';}echo '<a href="/problem/', $problem['id'], '">', $problem['title'], '</a>';if (isset($_COOKIE['show_tags_mode'])) {foreach (queryProblemTags($problem['id']) as $tag) {echo '<a class="uoj-problem-tag">', '<span class="badge badge-pill badge-secondary">', HTML::escape($tag), '</span>', '</a>';}}echo '</td>';if (isset($_COOKIE['show_submit_mode'])) {$perc = $problem['submit_num'] > 0 ? round(100 * $problem['ac_num'] / $problem['submit_num']) : 0;echo <<<EOD<td><a href="/submissions?problem_id={$problem['id']}&min_score=100&max_score=100">&times;{$problem['ac_num']}</a></td><td><a href="/submissions?problem_id={$problem['id']}">&times;{$problem['submit_num']}</a></td><td><div class="progress bot-buffer-no"><div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="$perc" aria-valuemin="0" aria-valuemax="100" style="width: $perc%; min-width: 20px;">{$perc}%</div></div></td>
EOD;}echo '<td class="text-left">', getClickZanBlock('P', $problem['id'], $problem['zan']), '</td>';echo '</tr>';}
}
  • echoProblem函数用于输出每个题目的HTML。
  • 判断题目是否对当前用户可见,如果可见,则输出题目的ID、标题、标签、提交统计和点赞数。

4. 构建查询条件

$cond = array();
$search_tag = null;
$cur_tab = isset($_GET['tab']) ? $_GET['tab'] : 'all';
if ($cur_tab == 'template') {$search_tag = "模板题";
}
if (isset($_GET['tag'])) {$search_tag = $_GET['tag'];
}
if ($search_tag) {$cond[] = "'".DB::escape($search_tag)."' in (select tag from problems_tags where problems_tags.problem_id = problems.id)";
}
if (isset($_GET["search"])) { $cond[]="title like '%".DB::escape($_GET["search"])."%' or id like '%".DB::escape($_GET["search"])."%'";
}
if ($cond) {$cond = join($cond, ' and ');
} else {$cond = '1';
}
  • 根据URL参数构建查询条件,用于筛选题目列表。

5. 定义表头

$header = '<tr>';
$header .= '<th class="text-center" style="width:5em;">ID</th>';
$header .= '<th>'.UOJLocale::get('problems::problem').'</th>';
if (isset($_COOKIE['show_submit_mode'])) {$header .= '<th class="text-center" style="width:5em;">'.UOJLocale::get('problems::ac').'</th>';$header .= '<th class="text-center" style="width:5em;">'.UOJLocale::get('problems::submit').'</th>';$header .= '<th class="text-center" style="width:150px;">'.UOJLocale::get('problems::ac ratio').'</th>';
}
$header .= '<th class="text-center" style="width:180px;">'.UOJLocale::get('appraisal').'</th>';
$header .= '</tr>';
  • 定义题目列表的表头,根据用户的显示设置调整显示内容。

6. 定义分页器和表格样式

$pag_config = array('page_len' => 100);
$pag_config['col_names'] = array('*');
$pag_config['table_name'] = "problems left join best_ac_submissions on best_ac_submissions.submitter = '{$myUser['username']}' and problems.id = best_ac_submissions.problem_id";
$pag_config['cond'] = $cond;
$pag_config['tail'] = "order by id asc";
$pag = new Paginator($pag_config);$div_classes = array('table-responsive');
$table_classes = array('table', 'table-bordered', 'table-hover', 'table-striped');
  • 设置分页器的配置,包括每页显示的题目数量、查询的表名和条件等。

7. 输出HTML内容

<?php echoUOJPageHeader(UOJLocale::get('problems')) ?>
<div class="row"><div class="col-sm-4"><?= HTML::tablist($tabs_info, $cur_tab, 'nav-pills') ?></div><div class="col-sm-4 order-sm-9 checkbox text-right"><label class="checkbox-inline" for="input-show_tags_mode"><input type="checkbox" id="input-show_tags_mode" <?= isset($_COOKIE['show_tags_mode']) ? 'checked="checked" ': ''?>/> <?= UOJLocale::get('problems::show tags') ?></label><label class="checkbox-inline" for="input-show_submit_mode"><input type="checkbox" id="input-show_submit_mode" <?= isset($_COOKIE['show_submit_mode']) ? 'checked="checked" ': ''?>/> <?= UOJLocale::get('problems::show statistics') ?></label></div><div class="col-sm-4 order-sm-5"><?php echo $pag->pagination(); ?></div>
</div>
<div class="top-buffer-sm"></div>
<script type="text/javascript">
$('#input-show_tags_mode').click(function() {if (this.checked) {$.cookie('show_tags_mode', '', {path: '/problems'});} else {$.removeCookie('show_tags_mode', {path: '/problems'});}location.reload();
});
$('#input-show_submit_mode').click(function() {if (this.checked) {$.cookie('show_submit_mode', '', {path: '/problems'});} else {$.removeCookie('show_submit_mode', {path: '/problems'});}location.reload();
});
</script>
<?phpecho '<div class="', join($div_classes, ' '), '">';echo '<table class="', join($table_classes, ' '), '">';echo '<thead>';echo $header;echo '</thead>';echo '<tbody>';foreach ($pag->get() as $idx => $row) {echoProblem($row);echo "\n";}if ($pag->isEmpty()) {echo '<tr><td class="text-center" colspan="233">'.UOJLocale::get('none').'</td></tr>';}echo '</tbody>';echo '</table>';echo '</div>';if (isSuperUser($myUser)) {$new_problem_form->printHTML();}echo $pag->pagination();
?>
<?php echoUOJPageFooter() ?>
  • 输出页面头部、标签栏、分页导航、题目列表表格和底部。
  • 使用JavaScript控制标签和统计信息的显示。

题目页面与提交

题目页面与提交页面下主要有”描述“、”提交“和”管理“(此功能只有管理员才能看到)功能。

当然,下面是对这段PHP代码的详细解释:

引入必要的PHP库

requirePHPLib('form');
requirePHPLib('judger');
  • requirePHPLib('form'):引入处理表单的库。
  • requirePHPLib('judger'):引入处理评测的库。

验证题目ID并查询题目信息

if (!validateUInt($_GET['id']) || !($problem = queryProblemBrief($_GET['id']))) {become404Page();
}
$problem_content = queryProblemContent($problem['id']);
  • 验证 id 是否为正整数,且查询题目的简要信息。
  • 如果题目不存在或ID无效,返回404页面。
  • 查询题目详细内容。

处理竞赛相关信息

$contest = validateUInt($_GET['contest_id']) ? queryContest($_GET['contest_id']) : null;
if ($contest != null) {genMoreContestInfo($contest);$problem_rank = queryContestProblemRank($contest, $problem);if ($problem_rank == null) {become404Page();} else {$problem_letter = chr(ord('A') + $problem_rank - 1);}
}
  • 验证 contest_id 是否为正整数,且查询竞赛信息。
  • 如果竞赛存在,生成更多竞赛信息并查询题目在竞赛中的排名。
  • 如果题目不在竞赛中,返回404页面。
  • 计算题目在竞赛中的字母标识。

检查用户权限和题目可见性

$is_in_contest = false;
$ban_in_contest = false;
if ($contest != null) {if (!hasContestPermission($myUser, $contest)) {if ($contest['cur_progress'] == CONTEST_NOT_STARTED) {become404Page();} elseif ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {if ($myUser == null || !hasRegistered($myUser, $contest)) {becomeMsgPage("<h1>比赛正在进行中</h1><p>很遗憾,您尚未报名。比赛结束后再来看吧~</p>");} else {$is_in_contest = true;DB::update("update contests_registrants set has_participated = 1 where username = '{$myUser['username']}' and contest_id = {$contest['id']}");}} else {$ban_in_contest = !isProblemVisibleToUser($problem, $myUser);}}
} else {if (!isProblemVisibleToUser($problem, $myUser)) {become404Page();}
}
  • 初始化 is_in_contestban_in_contestfalse
  • 如果竞赛存在且用户无权限:
    • 竞赛未开始,返回404页面。
    • 竞赛进行中,且用户未登录或未报名,显示比赛进行中的提示信息。
    • 如果用户已报名,设置 is_in_contesttrue 并更新数据库。
    • 竞赛已结束,检查题目是否对用户可见,设置 ban_in_contest
  • 如果没有竞赛,检查题目是否对用户可见,不可见则返回404页面。

获取提交需求和额外配置

$submission_requirement = json_decode($problem['submission_requirement'], true);
$problem_extra_config = getProblemExtraConfig($problem);
$custom_test_requirement = getProblemCustomTestRequirement($problem);
  • 解析题目的提交需求和自定义测试需求。
  • 获取题目的额外配置。

处理自定义测试状态请求

if ($custom_test_requirement && $_GET['get'] == 'custom-test-status-details' && Auth::check()) {if ($custom_test_submission == null) {echo json_encode(null);} else if ($custom_test_submission['status'] != 'Judged') {echo json_encode(array('judged' => false,'html' => getSubmissionStatusDetails($custom_test_submission)));} else {ob_start();$styler = new CustomTestSubmissionDetailsStyler();if (!hasViewPermission($problem_extra_config['view_details_type'], $myUser, $problem, $submission)) {$styler->fade_all_details = true;}echoJudgementDetails($custom_test_submission_result['details'], $styler, 'custom_test_details');$result = ob_get_contents();ob_end_clean();echo json_encode(array('judged' => true,'html' => getSubmissionStatusDetails($custom_test_submission),'result' => $result));}die();
}
  • 如果有自定义测试需求,并且GET请求参数 getcustom-test-status-details 且用户已登录:
    • 如果没有自定义测试提交记录,返回 null
    • 如果提交记录的状态不是 Judged,返回评测状态详情。
    • 否则,获取评测详情并返回评测结果。

检查是否可以使用ZIP上传

$can_use_zip_upload = true;
foreach ($submission_requirement as $req) {if ($req['type'] == 'source code') {$can_use_zip_upload = false;}
}
  • 检查提交需求中是否包含源代码,如果包含则不允许使用ZIP上传。

处理ZIP文件上传

function handleUpload($zip_file_name, $content, $tot_size) {global $problem, $contest, $myUser, $is_in_contest;$content['config'][] = array('problem_id', $problem['id']);if ($is_in_contest && $contest['extra_config']["contest_type"] != 'IOI' && !isset($contest['extra_config']["problem_{$problem['id']}"])) {$content['final_test_config'] = $content['config'];$content['config'][] = array('test_sample_only', 'on');}$esc_content = DB::escape(json_encode($content));$language = '/';foreach ($content['config'] as $row) {if (strEndWith($row[0], '_language')) {$language = $row[1];break;}}if ($language != '/') {Cookie::set('uoj_preferred_language', $language, time() + 60 * 60 * 24 * 365, '/');}$esc_language = DB::escape($language);$result = array();$result['status'] = "Waiting";$result_json = json_encode($result);if ($is_in_contest) {DB::query("insert into submissions (problem_id, contest_id, submit_time, submitter, content, language, tot_size, status, result, is_hidden) values (${problem['id']}, ${contest['id']}, now(), '${myUser['username']}', '$esc_content', '$esc_language', $tot_size, '${result['status']}', '$result_json', 0)");} else {DB::query("insert into submissions (problem_id, submit_time, submitter, content, language, tot_size, status, result, is_hidden) values (${problem['id']}, now(), '${myUser['username']}', '$esc_content', '$esc_language', $tot_size, '${result['status']}', '$result_json', {$problem['is_hidden']})");}
}
  • 处理ZIP文件上传:
    • 根据上传内容配置更新提交记录。
    • 处理语言设置并存储。
    • 将提交记录插入数据库。

处理自定义测试上传

function handleCustomTestUpload($zip_file_name, $content, $tot_size) {global $problem, $contest, $myUser;$content['config'][] = array('problem_id', $problem['id']);$content['config'][] = array('custom_test', 'on');$esc_content = DB::escape(json_encode($content));$language = '/';foreach ($content['config'] as $row) {if (strEndWith($row[0], '_language')) {$language = $row[1];break;}}if ($language != '/') {Cookie::set('uoj_preferred_language', $language, time() + 60 * 60 * 24 * 365, '/');}$esc_language = DB::escape($language);$result = array();$result['status'] = "Waiting";$result_json = json_encode($result);DB::insert("insert into custom_test_submissions (problem_id, submit_time, submitter, content, status, result) values ({$problem['id']}, now(), '{$myUser['username']}', '$esc_content', '{$result['status']}', '$result_json')");
}
  • 类似ZIP文件上传的处理方式,处理自定义测试上传并插入数据库。

创建并处理表单

if ($can_use_zip_upload) {$zip_answer_form = newZipSubmissionForm('zip_answer',$submission_requirement,'uojRandAvaiableSubmissionFileName','handleUpload');$zip_answer_form->runAtServer();
}$answer_form = newSubmissionForm('answer',$submission_requirement,'handleUpload');
$answer_form->runAtServer();if ($custom_test_requirement) {$custom_test_form = newSubmissionForm('custom_test',$custom_test_requirement,'handleCustomTestUpload');$custom_test_form->runAtServer();
}
  • 根据题目的提交需求,创建并处理不同类型的表单:
    • 如果允许ZIP上传,创建ZIP提交表单。
    • 创建普通提交表单。
    • 如果有自定义测试需求,创建自定义测试表单。

管理员题目描述处理

这段代码实现了一个问题管理页面,允许具有相应权限的用户编辑问题的内容、标签和可见性

引入必要的库

requirePHPLib('form');

这行代码引入了form库,提供表单处理功能。

验证和获取问题信息

if (!validateUInt($_GET['id']) || !($problem = queryProblemBrief($_GET['id']))) {become404Page();
}
  • validateUInt($_GET['id']):验证GET参数id是否为无符号整数。
  • queryProblemBrief($_GET['id']):查询问题简要信息。如果问题不存在或验证失败,调用become404Page(),返回404页面。
if (!hasProblemPermission($myUser, $problem)) {become403Page();
}
  • hasProblemPermission($myUser, $problem):检查当前用户是否有权限管理这个问题。如果没有权限,调用become403Page(),返回403页面。

获取问题详细内容和标签

$problem_content = queryProblemContent($problem['id']);
$problem_tags = queryProblemTags($problem['id']);
  • queryProblemContent($problem['id']):获取问题的详细内容。
  • queryProblemTags($problem['id']):获取问题的标签。

初始化编辑器

$problem_editor = new UOJBlogEditor();
$problem_editor->name = 'problem';
$problem_editor->blog_url = "/problem/{$problem['id']}";
$problem_editor->cur_data = array('title' => $problem['title'],'content_md' => $problem_content['statement_md'],'content' => $problem_content['statement'],'tags' => $problem_tags,'is_hidden' => $problem['is_hidden']
);
$problem_editor->label_text = array_merge($problem_editor->label_text, array('view blog' => '查看题目','blog visibility' => '题目可见性'
));
  • 创建一个新的UOJBlogEditor实例用于编辑问题内容。
  • 设置编辑器名称、URL和当前数据(标题、内容、标签和可见性)。
  • 更新编辑器的标签文本(如“查看题目”和“题目可见性”)。

定义保存操作

$problem_editor->save = function($data) {global $problem, $problem_tags;DB::update("update problems set title = '".DB::escape($data['title'])."' where id = {$problem['id']}");DB::update("update problems_contents set statement = '".DB::escape($data['content'])."', statement_md = '".DB::escape($data['content_md'])."' where id = {$problem['id']}");if ($data['tags'] !== $problem_tags) {DB::delete("delete from problems_tags where problem_id = {$problem['id']}");foreach ($data['tags'] as $tag) {DB::insert("insert into problems_tags (problem_id, tag) values ({$problem['id']}, '".DB::escape($tag)."')");}}if ($data['is_hidden'] != $problem['is_hidden'] ) {DB::update("update problems set is_hidden = {$data['is_hidden']} where id = {$problem['id']}");DB::update("update submissions set is_hidden = {$data['is_hidden']} where problem_id = {$problem['id']}");DB::update("update hacks set is_hidden = {$data['is_hidden']} where problem_id = {$problem['id']}");}
};
  • 定义save函数以处理编辑器保存操作。
  • 更新问题标题和内容(包括Markdown格式和HTML格式)。
  • 如果标签发生变化,删除旧标签并插入新标签。
  • 如果可见性发生变化,更新问题、提交的可见性。

题目数据管理

problem_data_manage.php中,包含着对于一道题目数据上传的逻辑操作。这里截取部分重要代码进行解释

数据上传代码

<div class="modal fade" id="UploadDataModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h4 class="modal-title" id="myModalLabel">上传数据</h4><button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button></div><div class="modal-body"><form action="" method="post" enctype="multipart/form-data" role="form"><div class="form-group"><label for="exampleInputFile">上传zip文件</label><input type="file" name="problem_data_file" id="problem_data_file"><p class="help-block">说明:请将所有数据放置于压缩包根目录内。若压缩包内仅存在文件夹而不存在文件,则会将这些一级子文件夹下的内容移动到根目录下,然后这些一级子文件夹删除;若这些子文件夹内存在同名文件,则会发生随机替换,仅保留一个副本。</p></div><input type="hidden" name="problem_data_file_submit" value="submit"></div><div class="modal-footer"><button type="submit" class="btn btn-success">上传</button></form><button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button></div></div></div></div>
  • 用户可以点击上传数据按钮,弹出此模态框。
  • 用户可以选择一个ZIP文件,并点击模态框底部的上传按钮来提交选择的文件。
  • 提交表单时,数据将被提交到当前页面(action=""表示当前页面),并使用POST方法传输数据。
  • 上传的ZIP文件将会作为名为 problem_data_file 的文件上传字段提交。
  • 提交完成后,可以点击模态框右上角的关闭按钮或底部的关闭按钮来关闭模态框。

在线显示测试数据

这段代码定义了一个名为 getDataDisplayer() 的函数,它根据问题的配置信息动态生成并返回一个 DataDisplayer 对象,用于显示不同类型的数据文件和信息。让我们逐步解释其功能和实现细节:

1. 全局变量声明:

global $data_dir;
global $problem;
  • 这些变量包含了数据目录路径 $data_dir 和与问题相关的信息 $problem

2. 获取允许显示的文件列表:

$allow_files = array_flip(array_filter(scandir($data_dir), function($x){return $x !== '.' && $x !== '..';}));
  • 使用 scandir($data_dir) 获取 $data_dir 目录下的所有文件和目录。
  • 使用 array_filter 过滤掉当前目录 ('.') 和上级目录 ('..')。
  • 使用 array_flip 将文件名作为键,便于后续快速查找文件是否存在。

3. 定义获取文件显示函数的匿名函数:

$getDisplaySrcFunc = function($name) use($allow_files) {return function() use($name, $allow_files) {$src_name = $name . '.cpp';if (isset($allow_files[$src_name])) {echoFilePre($src_name);} else {echoFileNotFound($src_name);}if (isset($allow_files[$name])) {echoFilePre($name);} else {echoFileNotFound($name);}};
};
  • $getDisplaySrcFunc 是一个匿名函数,接受一个文件名 $name,返回一个函数。
  • 返回的函数根据 $name$name . '.cpp'$allow_files 中查找文件是否存在,存在则调用 echoFilePre($file_name) 显示文件预览,否则调用 echoFileNotFound($file_name) 显示文件未找到的信息。

4. 读取问题的配置文件 problem.conf:

$problem_conf = getUOJConf("$data_dir/problem.conf");
if ($problem_conf === -1) {// 处理无法读取问题配置文件的情况
}
if ($problem_conf === -2) {// 处理问题配置文件格式错误的情况
}
  • 使用 getUOJConf("$data_dir/problem.conf") 函数读取问题的配置文件内容。
  • 根据返回值 -1-2 处理无法读取或格式错误的情况,分别显示相应的错误信息。

5. 根据配置文件中的信息设置显示器和处理器:

  • 根据 use_builtin_judger 的设置和其他配置信息动态生成 DataDisplayer 对象,并设置相应的数据显示和处理方法。
// 处理使用内置判题器的情况
if ($problem_conf['use_builtin_judger'] == 'on') {// 设置显示器用于显示测试数据和额外测试数据// 设置显示器用于显示checker等其他类型数据// 根据hackable属性设置显示器用于显示standard和validator// 根据interaction_mode设置显示器用于显示interactor
}

题目数据统计

在单个题目的主页面的右上角中,有一个“统计”按钮。点击按钮即可显示当前题目的相关数据信息。下面列举一些重要逻辑代码:

题目数据相关信息的处理

	// 分数分布数据的获取function scoreDistributionData() {$data = array();$result = DB::select("select score, count(*) from submissions where problem_id = {$_GET['id']} and score is not null group by score");$is_res_empty = true;$has_score_0 = false;$has_score_100 = false;while ($row = DB::fetch($result, MYSQLI_NUM)) {if ($row[0] == 0) {$has_score_0 = true;} else if ($row[0] == 100) {$has_score_100 = true;}$score = $row[0] * 100;$data[] = array('score' => $score, 'count' => $row[1]);}if (!$has_score_0) {array_unshift($data, array('score' => 0, 'count' => 0));}if (!$has_score_100) {$data[] = array('score' => 10000, 'count' => 0);}return $data;}// 分数分布数据的预处理$data = scoreDistributionData();$pre_data = $data;$suf_data = $data;for ($i = 0; $i < count($data); $i++) {$data[$i]['score'] /= 100;}for ($i = 1; $i < count($data); $i++) {$pre_data[$i]['count'] += $pre_data[$i - 1]['count'];}for ($i = count($data) - 1; $i > 0; $i--) {$suf_data[$i - 1]['count'] += $suf_data[$i]['count'];}// 提交排序选择的处理$submissions_sort_by_choice = !isset($_COOKIE['submissions-sort-by-code-length']) ? 'time' : 'tot_size';
  • 从数据库中查询特定问题 (problem_id = $_GET['id']) 的提交数据,并统计每个分数的提交次数。
  • 如果没有分数为0或100的记录,手动添加这些分数和对应的次数。
  • 返回一个数组 $data,包含分数和对应的提交次数。
  • 使用 scoreDistributionData() 函数获取分数分布数据并存储在 $data 数组中。
  • 复制 $data$pre_data$suf_data,用于预处理。
  • $data 数组中的每个分数除以100,以得到真实的分数值。
  • $pre_data 数组中每个元素的 count 属性表示该分数及之前所有分数的累计提交次数。
  • $suf_data 数组中每个元素的 count 属性表示该分数及之后所有分数的累计提交次数。
  • 检查是否设置了名为 submissions-sort-by-code-length 的 Cookie。
  • 如果未设置该 Cookie,将 $submissions_sort_by_choice 设置为 'time',表示按时间排序。
  • 如果设置了该 Cookie,将 $submissions_sort_by_choice 设置为 'tot_size',表示按代码长度排序。

使用Morris数据可视化

代码使用了 Morris.js 库来生成一个折线图,并对数据进行了一些配置和处理。

new Morris.Line({element: 'score-distribution-chart-suf', // 图表要渲染的元素的 IDdata: <?= json_encode($suf_data) ?>, // 图表使用的数据,使用 PHP 的 json_encode 将 PHP 数组转换为 JavaScript 对象xkey: 'score', // X 轴上的数据字段ykeys: ['count'], // Y 轴上的数据字段labels: ['number'], // 数据字段的标签,用于图例和提示信息lineColors: function(row, sidx, type) { // 定义折线的颜色if (type == 'line') {return '#0b62a4'; // 折线颜色}return getColOfScore(row.src.score / 100); // 如果有其他类型的数据,使用自定义函数获取颜色},xLabelFormat: function(x) { // 定义 X 轴标签的格式化函数return (x.getTime() / 100).toString(); // 将时间转换为指定格式的字符串},hoverCallback: function(index, options, content, row) { // 定义鼠标悬停提示信息的回调函数var scr = row.score / 100; // 获取分数,并转换为实际的分数值return '<div class="morris-hover-row-label">' + 'score: &ge;' + scr + '</div>' + // 返回自定义的悬停提示信息的 HTML'<div class="morris-hover-point">' + '<a href="/submissions?problem_id=' + <?= $problem['id'] ?> + '&amp;min_score=' + scr + '">' + 'number: ' + row.count + '</a>' + '</div>';},resize: true // 是否支持自动调整大小
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/46910.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

创新实训(10)- 大模型服务进一步完善邮件服务

之前为应付中期检查简单接入了一个基础服务,并未对 prompt 词等做太深入的细分,为了实现更人性化的效果,我对大模型的服务进行了更进一步的完善 首先是前端的效果: 超级用户端:一般用户端:三个按钮分别对应 AI 整理格式,AI 基础纠错,AI 结合题目和代码详细检查错误。 前…

多面体

这个triangles的八个数组什么意思看不懂啊

模拟集成电路设计系列博客——7.3.1 并联比较型ADC基本介绍

7.3.1 并联比较型ADC基本介绍 并联比较型ADC(后续都称作Flash ADC)是实现超高速转换器的标准方式。Flash ADC的输入信号被并行的馈入\(2^N\)个比较器中,如下图所示:每个比较器被连接到电阻串的节点上。任何连接到电阻串节点的比较器,如果\(V_{ri}\)大于\(V_{in}\)有着1的输…

创新实训(7)- 大模型服务进一步完善

之前为应付中期检查简单接入了一个基础服务,并未对 prompt 词等做太深入的细分,为了实现更人性化的效果,我对大模型的服务进行了更进一步的完善 首先是前端的效果: 超级用户端:一般用户端:三个按钮分别对应 AI 整理格式,AI 基础纠错,AI 结合题目和代码详细检查错误。 前…

[模式识别复习笔记] 第9章 神经网络及BP算法

1. 基本概念 1.1 神经元 神经网络是很多的 神经元 模型按照一定的层次结构连接起来所构成的。1.2 激活函数\(\text{ReLU}\) 函数:修正线性单元ReLU,是一种人工神经网络中常用的激活函数。 \[\text{ReLU}(x) = \max(0, x) \] \(\text{sgn}\) 阶跃函数:它将输入值映射为 \(0\…

[Java基础]String

String 常量池/运行时常量池 java类编译之后生成的.class文件包含三部分信息, 类的基本信息,常量池,方法的定义 通过javap -v xxxx.class命令可以看到 Constant pool:#1 = Methodref #2.#3 // java/lang/Object."<init>":()V#2 = Class …

VScode配置C语言开发环境

可以总结为两步 1.本地安装和配置编译器 2.VScode上安装C/C++扩展 最后直接运行即可安装和配置编译器 Windows系统可以使用mingw64,发布网址在这里https://sourceforge.net/projects/mingw-w64/files/这是压缩包格式,可以自由选择目录解压,比如我把mingw64放在D盘根目录在命…

MySQL8-中文参考-四十-

MySQL8 中文参考(四十)原文:docs.oracle.com/javase/tutorial/reallybigindex.html原文:dev.mysql.com/doc/refman/8.0/en/mysql-cluster-system-definition.html25.4.3.8 定义系统 [system] 部分用于适用于整个集群的参数。 Name 系统参数用于 MySQL Enterprise Monitor;…