♻️ refactor(reinfo): 简化判错提示并新增自动刷新
- 移除 PHP 中冗余的 verdict_hints 数组及其填充逻辑 - 移除模板中 friendly-explain 区与 errexp-list 错误模式匹配脚本(28 条规则) - 标题提示简化为单行 verdict-tip,详细的修复建议交由 AI 点评 - 调整页面顺序:AI 点评区提前,原始错误折叠下移 - 新增判题中自动刷新状态指示:轮询 status-ajax.php,完成后自动 reload,并加入后台标签暂停与退避策略
This commit is contained in:
@@ -109,7 +109,6 @@ $view_reinfo_dedup_count = 0; // 折叠掉的测试点数
|
|||||||
$verdict_color_class = "blue"; // semantic ui color: green/red/orange/yellow/grey
|
$verdict_color_class = "blue"; // semantic ui color: green/red/orange/yellow/grey
|
||||||
$result_icon = "info circle";
|
$result_icon = "info circle";
|
||||||
$verdict_tip = "";
|
$verdict_tip = "";
|
||||||
$verdict_hints = array();
|
|
||||||
|
|
||||||
if($ok){
|
if($ok){
|
||||||
|
|
||||||
@@ -143,75 +142,39 @@ if($ok){
|
|||||||
default: $verdict_color_class = "blue"; $result_icon = "info circle";
|
default: $verdict_color_class = "blue"; $result_icon = "info circle";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 友好提示
|
// 友好提示:仅保留标题性文字,具体修复建议交给 AI 点评
|
||||||
switch ($result_code) {
|
switch ($result_code) {
|
||||||
case 4: // AC
|
case 4: // AC
|
||||||
$verdict_tip = "本次提交通过了所有测试点";
|
$verdict_tip = "本次提交通过了所有测试点";
|
||||||
$verdict_hints[] = "注意时间/内存是否接近限制,考虑是否有更优的算法";
|
|
||||||
$verdict_hints[] = "可以继续挑战更高难度或查看其他人的标程";
|
|
||||||
break;
|
break;
|
||||||
case 5: // PE
|
case 5: // PE
|
||||||
$verdict_tip = "输出与预期基本一致但格式不符(Presentation Error)";
|
$verdict_tip = "输出与预期基本一致但格式不符(Presentation Error)";
|
||||||
$verdict_hints[] = "对照样例:每行末尾是否多/少换行";
|
|
||||||
$verdict_hints[] = "检查空格、大小写、标点符号";
|
|
||||||
$verdict_hints[] = "PE 通常是细微的格式问题,请逐字符对比";
|
|
||||||
break;
|
break;
|
||||||
case 6: // WA
|
case 6: // WA
|
||||||
$verdict_tip = "输出与预期不符(Wrong Answer)";
|
$verdict_tip = "输出与预期不符(Wrong Answer)";
|
||||||
$verdict_hints[] = "对照样例手动模拟程序执行过程";
|
|
||||||
$verdict_hints[] = "检查边界条件:n=0、n=1、极值、空输入";
|
|
||||||
$verdict_hints[] = "注意 long long 溢出、int 范围";
|
|
||||||
break;
|
break;
|
||||||
case 7: // TLE
|
case 7: // TLE
|
||||||
$verdict_tip = $MSG_HINT_TLE;
|
$verdict_tip = $MSG_HINT_TLE;
|
||||||
$verdict_hints[] = "检查是否有死循环(循环变量未更新)";
|
|
||||||
$verdict_hints[] = "优化算法复杂度(如 O(n²) → O(n log n))";
|
|
||||||
$verdict_hints[] = "递归层数过深?改为迭代或加深栈";
|
|
||||||
break;
|
break;
|
||||||
case 8: // MLE
|
case 8: // MLE
|
||||||
$verdict_tip = $MSG_HINT_MLE;
|
$verdict_tip = $MSG_HINT_MLE;
|
||||||
$verdict_hints[] = "大数组开在函数内(栈)?改为全局或 new";
|
|
||||||
$verdict_hints[] = "Java: 减小内存使用或调整 JVM 参数";
|
|
||||||
$verdict_hints[] = "递归太深未释放,考虑显式清理";
|
|
||||||
break;
|
break;
|
||||||
case 9: // OLE
|
case 9: // OLE
|
||||||
$verdict_tip = $MSG_HINT_OLE;
|
$verdict_tip = $MSG_HINT_OLE;
|
||||||
$verdict_hints[] = "是否有死循环输出";
|
|
||||||
$verdict_hints[] = "调试用的 print/cout 是否忘记删除";
|
|
||||||
break;
|
break;
|
||||||
case 10: // RE
|
case 10: // RE
|
||||||
$verdict_tip = "程序运行中发生错误(Runtime Error)";
|
$verdict_tip = "程序运行中发生错误(Runtime Error)";
|
||||||
$verdict_hints[] = "数组下标是否越界(i<n 还是 i<=n)";
|
|
||||||
$verdict_hints[] = "除以零、空指针、栈溢出";
|
|
||||||
$verdict_hints[] = "递归爆栈:转迭代或加尾递归";
|
|
||||||
break;
|
break;
|
||||||
case 11: // CE
|
case 11: // CE
|
||||||
$verdict_tip = "编译错误(Compile Error)。请查看编译信息页。";
|
$verdict_tip = "编译错误(Compile Error)。请查看编译信息页。";
|
||||||
break;
|
break;
|
||||||
case 13: // TR (test run)
|
case 13: // TR (test run)
|
||||||
$verdict_tip = "测试运行完成(Test Run)";
|
$verdict_tip = "测试运行完成(Test Run)";
|
||||||
$verdict_hints[] = "你输入的测试数据已与程序输出对比";
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$verdict_tip = "正在评判,请稍候刷新";
|
$verdict_tip = "正在评判,请稍候刷新";
|
||||||
}
|
}
|
||||||
|
|
||||||
// === 阶段 2:syscall vs 真正越界 的区分 ===
|
|
||||||
if ($result_code === 10) {
|
|
||||||
if (preg_match('/Forbidden system call.*CALLID:(\d+)/', $raw_error, $m)) {
|
|
||||||
$callid = $m[1];
|
|
||||||
$verdict_hints[] = sprintf("系统调用 ID=%d 被判题器禁止,常见于直接操作文件/网络/进程", $callid);
|
|
||||||
}
|
|
||||||
// Java / Python / Go 的细化提示
|
|
||||||
if (preg_match('/java\.lang\.(\w+Exception|\w+Error)/', $raw_error, $m2)) {
|
|
||||||
$verdict_hints[] = "Java 异常类型:" . $m2[1];
|
|
||||||
} elseif (preg_match('/Traceback \(most recent call last\)/', $raw_error)) {
|
|
||||||
$verdict_hints[] = "Python 抛出异常,下方 traceback 从下往上读就是异常源头";
|
|
||||||
} elseif (preg_match('/panic:.*?(index out of range|invalid memory address|nil pointer)/i', $raw_error)) {
|
|
||||||
$verdict_hints[] = "Go 运行时报错:通常是越界访问或 nil 指针";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// === 阶段 3:原始错误处理(syscall 提示 vs 占位符修复)===
|
// === 阶段 3:原始错误处理(syscall 提示 vs 占位符修复)===
|
||||||
$view_reinfo_raw = $raw_error;
|
$view_reinfo_raw = $raw_error;
|
||||||
if (trim($raw_error) === "") {
|
if (trim($raw_error) === "") {
|
||||||
|
|||||||
@@ -51,25 +51,14 @@
|
|||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#friendly-explain {
|
#verdict-tip {
|
||||||
margin-bottom: 18px;
|
margin-bottom: 18px;
|
||||||
}
|
|
||||||
#friendly-explain .verdict-tip {
|
|
||||||
font-size: 1.05em;
|
font-size: 1.05em;
|
||||||
margin-bottom: 12px;
|
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
background: rgba(33,150,243,0.08);
|
background: rgba(33,150,243,0.08);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
border-left: 3px solid #2185d0;
|
border-left: 3px solid #2185d0;
|
||||||
}
|
}
|
||||||
#friendly-explain .verdict-hints {
|
|
||||||
margin: 0;
|
|
||||||
padding-left: 22px;
|
|
||||||
}
|
|
||||||
#friendly-explain .verdict-hints li {
|
|
||||||
margin-bottom: 6px;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
#raw-info-accordion {
|
#raw-info-accordion {
|
||||||
margin-bottom: 18px;
|
margin-bottom: 18px;
|
||||||
@@ -116,21 +105,19 @@
|
|||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 错误解释列表(由 JS explain() 填充) */
|
/* 错误解释列表(由 JS explain() 填充) - 已弃用,由 AI 点评替代 */
|
||||||
#errexp-list {
|
|
||||||
list-style: disc;
|
/* 自动刷新状态 */
|
||||||
padding-left: 22px;
|
i.icon.spinning {
|
||||||
margin: 0;
|
animation: spin 1.2s linear infinite;
|
||||||
}
|
}
|
||||||
#errexp-list li {
|
@keyframes spin {
|
||||||
margin-bottom: 6px;
|
from { transform: rotate(0deg); }
|
||||||
line-height: 1.5;
|
to { transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
#errexp-list li code {
|
#auto-refresh-status {
|
||||||
background: rgba(0,0,0,0.05);
|
color: #2185d0;
|
||||||
padding: 1px 4px;
|
font-weight: 600;
|
||||||
border-radius: 3px;
|
|
||||||
font-size: 0.9em;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@@ -155,65 +142,22 @@
|
|||||||
<span class="stat"><i class="microchip icon"></i><?php echo $verdict_memory ?> KB</span>
|
<span class="stat"><i class="microchip icon"></i><?php echo $verdict_memory ?> KB</span>
|
||||||
<span class="stat"><i class="clock icon"></i><?php echo $verdict_time ?> ms</span>
|
<span class="stat"><i class="clock icon"></i><?php echo $verdict_time ?> ms</span>
|
||||||
<span class="stat"><i class="code icon"></i><?php echo htmlspecialchars($verdict_lang, ENT_QUOTES, 'UTF-8') ?></span>
|
<span class="stat"><i class="code icon"></i><?php echo htmlspecialchars($verdict_lang, ENT_QUOTES, 'UTF-8') ?></span>
|
||||||
|
<span class="stat" id="auto-refresh-status" style="display:none;">
|
||||||
|
<i class="refresh icon spinning"></i> <span id="auto-refresh-text"></span>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 2. 友好解释区(永远非空) -->
|
<!-- 2. 判题结果标题提示(仅一句话,具体修复建议交给 AI) -->
|
||||||
<div class="ui message" id="friendly-explain">
|
<div class="ui info message" id="verdict-tip">
|
||||||
<div class="header">
|
<i class="info circle icon"></i>
|
||||||
<i class="lightbulb outline icon"></i>
|
<?php echo isset($verdict_tip) ? htmlspecialchars($verdict_tip, ENT_QUOTES, 'UTF-8') : ''; ?>
|
||||||
<?php echo isset($MSG_FRIENDLY_EXPLAIN) ? $MSG_FRIENDLY_EXPLAIN : '错误解释'; ?>
|
|
||||||
</div>
|
|
||||||
<div class="verdict-tip">
|
|
||||||
<i class="info circle icon"></i>
|
|
||||||
<?php echo isset($verdict_tip) ? htmlspecialchars($verdict_tip, ENT_QUOTES, 'UTF-8') : ''; ?>
|
|
||||||
</div>
|
|
||||||
<?php if (!empty($verdict_hints) && is_array($verdict_hints)): ?>
|
|
||||||
<ul class="verdict-hints">
|
|
||||||
<?php foreach ($verdict_hints as $h): ?>
|
|
||||||
<li><?php echo htmlspecialchars($h, ENT_QUOTES, 'UTF-8'); ?></li>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</ul>
|
|
||||||
<?php endif; ?>
|
|
||||||
<!-- JS explain() 也会把 pats[] 匹配到的具体错误模式追加在这里 -->
|
|
||||||
<ul id="errexp-list"></ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 3. 原始错误折叠(默认收起) -->
|
|
||||||
<div class="ui styled accordion" id="raw-info-accordion">
|
|
||||||
<div class="title">
|
|
||||||
<i class="dropdown icon"></i>
|
|
||||||
<?php echo isset($MSG_RAW_ERROR) ? $MSG_RAW_ERROR : '查看原始错误信息'; ?>
|
|
||||||
<?php if (!empty($view_reinfo_dedup_count)): ?>
|
|
||||||
<span class="ui tiny teal label dedup-label">
|
|
||||||
<?php echo sprintf(isset($MSG_DEDUP_HINT) ? $MSG_DEDUP_HINT : '已折叠 %d 个相同测试点', intval($view_reinfo_dedup_count)); ?>
|
|
||||||
</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if (trim($view_reinfo) === ''): ?>
|
|
||||||
<span class="dedup-label empty-notice">(无)</span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<div class="content">
|
|
||||||
<?php if (trim($view_reinfo) === ''): ?>
|
|
||||||
<p class="empty-notice">当前判题结果没有原始错误信息(如 TLE/MLE 通常不会写 runtimeinfo)。</p>
|
|
||||||
<?php else: ?>
|
|
||||||
<pre id="errtxt"><?php
|
|
||||||
// 普通用户:折叠后;管理员/源浏览者:原文
|
|
||||||
if (isset($is_admin_session) && $is_admin_session) {
|
|
||||||
echo htmlspecialchars($view_reinfo_raw, ENT_QUOTES, 'UTF-8');
|
|
||||||
} elseif (isset($is_source_browser) && $is_source_browser) {
|
|
||||||
echo htmlspecialchars($view_reinfo_raw, ENT_QUOTES, 'UTF-8');
|
|
||||||
} else {
|
|
||||||
echo htmlspecialchars($view_reinfo, ENT_QUOTES, 'UTF-8');
|
|
||||||
}
|
|
||||||
?></pre>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 4. AI 点评区(直接显示按钮,不再折叠) -->
|
<!-- 3. AI 点评区(直接显示按钮,提到原始错误上面) -->
|
||||||
<?php if (isset($OJ_LLM_ENABLED) && $OJ_LLM_ENABLED) { ?>
|
<?php if (isset($OJ_LLM_ENABLED) && $OJ_LLM_ENABLED) { ?>
|
||||||
<div class="ui raised segment" id="llm-section">
|
<div class="ui raised segment" id="llm-section">
|
||||||
<h3 class="ui header">
|
<h3 class="ui header">
|
||||||
@@ -347,6 +291,38 @@
|
|||||||
</script>
|
</script>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
|
<!-- 4. 原始错误折叠(默认收起) -->
|
||||||
|
<div class="ui styled accordion" id="raw-info-accordion">
|
||||||
|
<div class="title">
|
||||||
|
<i class="dropdown icon"></i>
|
||||||
|
<?php echo isset($MSG_RAW_ERROR) ? $MSG_RAW_ERROR : '查看原始错误信息'; ?>
|
||||||
|
<?php if (!empty($view_reinfo_dedup_count)): ?>
|
||||||
|
<span class="ui tiny teal label dedup-label">
|
||||||
|
<?php echo sprintf(isset($MSG_DEDUP_HINT) ? $MSG_DEDUP_HINT : '已折叠 %d 个相同测试点', intval($view_reinfo_dedup_count)); ?>
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (trim($view_reinfo) === ''): ?>
|
||||||
|
<span class="dedup-label empty-notice">(无)</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<?php if (trim($view_reinfo) === ''): ?>
|
||||||
|
<p class="empty-notice">当前判题结果没有原始错误信息(如 TLE/MLE 通常不会写 runtimeinfo)。</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<pre id="errtxt"><?php
|
||||||
|
// 普通用户:折叠后;管理员/源浏览者:原文
|
||||||
|
if (isset($is_admin_session) && $is_admin_session) {
|
||||||
|
echo htmlspecialchars($view_reinfo_raw, ENT_QUOTES, 'UTF-8');
|
||||||
|
} elseif (isset($is_source_browser) && $is_source_browser) {
|
||||||
|
echo htmlspecialchars($view_reinfo_raw, ENT_QUOTES, 'UTF-8');
|
||||||
|
} else {
|
||||||
|
echo htmlspecialchars($view_reinfo, ENT_QUOTES, 'UTF-8');
|
||||||
|
}
|
||||||
|
?></pre>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 5. 快捷操作区 -->
|
<!-- 5. 快捷操作区 -->
|
||||||
<div class="quick-actions">
|
<div class="quick-actions">
|
||||||
<div class="ui horizontal divider">
|
<div class="ui horizontal divider">
|
||||||
@@ -372,122 +348,6 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 错误模式 → 解释(pats[]/exps[],共 28 条) -->
|
|
||||||
<script>
|
|
||||||
var pats = new Array();
|
|
||||||
var exps = new Array();
|
|
||||||
var patsSeen = {}; // 防止"段错误"和"stack smashing"双重提示
|
|
||||||
|
|
||||||
// === 原有 11 条 ===
|
|
||||||
pats[0]=/A Not allowed system call.* /;
|
|
||||||
exps[0]="<?php echo $MSG_A_NOT_ALLOWED_SYSTEM_CALL ?>";
|
|
||||||
pats[1]=/Segmentation fault/;
|
|
||||||
exps[1]="<?php echo $MSG_SEGMETATION_FAULT ?>";
|
|
||||||
pats[2]=/Floating point exception/;
|
|
||||||
exps[2]="<?php echo $MSG_FLOATING_POINT_EXCEPTION ?>";
|
|
||||||
pats[3]=/buffer overflow detected/;
|
|
||||||
exps[3]="<?php echo $MSG_BUFFER_OVERFLOW_DETECTED ?>";
|
|
||||||
pats[4]=/Killed/;
|
|
||||||
exps[4]="<?php echo $MSG_PROCESS_KILLED ?>";
|
|
||||||
pats[5]=/Alarm clock/;
|
|
||||||
exps[5]="<?php echo $MSG_ALARM_CLOCK ?>";
|
|
||||||
pats[6]=/CALLID:20/;
|
|
||||||
exps[6]="<?php echo $MSG_CALLID_20 ?>";
|
|
||||||
pats[7]=/ArrayIndexOutOfBoundsException/;
|
|
||||||
exps[7]="<?php echo $MSG_ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION ?>";
|
|
||||||
pats[8]=/StringIndexOutOfBoundsException/;
|
|
||||||
exps[8]="<?php echo $MSG_STRING_INDEX_OUT_OF_BOUNDS_EXCEPTION ?>";
|
|
||||||
pats[9]=/Binary files/;
|
|
||||||
exps[9]="<?php echo $MSG_WRONG_OUTPUT_TYPE_EXCEPTION ?>";
|
|
||||||
pats[10]=/non-zero return/;
|
|
||||||
exps[10]="<?php echo $MSG_NON_ZERO_RETURN ?>";
|
|
||||||
|
|
||||||
// === 新增 17 条(覆盖 glibc / Java / Python / Go) ===
|
|
||||||
pats[11]=/stack smashing detected/;
|
|
||||||
exps[11]="<?php echo $MSG_STACK_SMASHING_DETECTED ?>";
|
|
||||||
// 同时标 pats[3] 已被覆盖(避免重复)
|
|
||||||
pats[12]=/terminate called after throwing/;
|
|
||||||
exps[12]="<?php echo $MSG_TERMINATE_CALLED ?>";
|
|
||||||
pats[13]=/NullPointerException/;
|
|
||||||
exps[13]="<?php echo $MSG_NULL_POINTER_EXCEPTION ?>";
|
|
||||||
pats[14]=/NumberFormatException/;
|
|
||||||
exps[14]="<?php echo $MSG_NUMBER_FORMAT_EXCEPTION ?>";
|
|
||||||
pats[15]=/ClassCastException/;
|
|
||||||
exps[15]="<?php echo $MSG_CLASS_CAST_EXCEPTION ?>";
|
|
||||||
pats[16]=/NegativeArraySizeException/;
|
|
||||||
exps[16]="<?php echo $MSG_NEGATIVE_ARRAY_SIZE_EXCEPTION ?>";
|
|
||||||
pats[17]=/Traceback \(most recent call last\)/;
|
|
||||||
exps[17]="<?php echo $MSG_PYTHON_TRACEBACK ?>";
|
|
||||||
pats[18]=/RecursionError/;
|
|
||||||
exps[18]="<?php echo $MSG_PYTHON_RECURSION_ERROR ?>";
|
|
||||||
pats[19]=/IndentationError/;
|
|
||||||
exps[19]="<?php echo $MSG_PYTHON_INDENTATION_ERROR ?>";
|
|
||||||
pats[20]=/ZeroDivisionError/;
|
|
||||||
exps[20]="<?php echo $MSG_PYTHON_ZERO_DIVISION ?>";
|
|
||||||
pats[21]=/NameError:/;
|
|
||||||
exps[21]="<?php echo $MSG_PYTHON_NAME_ERROR ?>";
|
|
||||||
pats[22]=/panic:.*runtime error/;
|
|
||||||
exps[22]="<?php echo $MSG_GO_PANIC ?>";
|
|
||||||
pats[23]=/Aborted \(core dumped\)/;
|
|
||||||
exps[23]="<?php echo $MSG_ABORTED_CORE_DUMPED ?>";
|
|
||||||
pats[24]=/CALLID:(\d+)/;
|
|
||||||
exps[24]="使用了非法的系统调用(syscall),请检查是否访问了文件、网络、进程等受限资源。";
|
|
||||||
pats[25]=/StackOverflowError/;
|
|
||||||
exps[25]="<?php echo $MSG_STACK_OVERFLOW_ERROR ?? '栈溢出(StackOverflowError)。通常是递归层数过深或局部大数组占用过多栈空间。' ?>";
|
|
||||||
pats[26]=/class not found|Could not find or load main class/;
|
|
||||||
exps[26]="Java 类未找到。检查 public class 名称是否与文件名一致,是否有 package 声明。";
|
|
||||||
pats[27]=/no test data/;
|
|
||||||
exps[27]="没有找到测试数据,请联系管理员检查题目数据。";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 把匹配到的错误模式追加到 <ul id="errexp-list">
|
|
||||||
* 同一类错误(内存类/异常类/系统调用类)只显示一次
|
|
||||||
*/
|
|
||||||
function explain(){
|
|
||||||
var errmsg = $("#errtxt").text();
|
|
||||||
if (!errmsg || errmsg.trim() === '') return;
|
|
||||||
|
|
||||||
// 同族分组
|
|
||||||
var familyMap = {
|
|
||||||
'mem': [1, 3, 11, 25], // 段错误 / 缓冲溢出 / stack smashing / 栈溢出
|
|
||||||
'sysc': [0, 6, 24], // 系统调用
|
|
||||||
'time': [4, 5], // 时间/Killed
|
|
||||||
'arith':[2, 20], // 除零
|
|
||||||
'jexc': [7, 8, 13, 14, 15, 16, 25], // Java 异常
|
|
||||||
'pyexc':[17, 18, 19, 20, 21], // Python
|
|
||||||
'goexc':[22], // Go
|
|
||||||
};
|
|
||||||
|
|
||||||
var shownFamilies = {};
|
|
||||||
var shown = {};
|
|
||||||
var items = [];
|
|
||||||
|
|
||||||
for (var i = 0; i < pats.length; i++) {
|
|
||||||
if (!pats[i] || shown[i]) continue;
|
|
||||||
var ret = pats[i].exec(errmsg);
|
|
||||||
if (!ret) continue;
|
|
||||||
|
|
||||||
// 检查是否已被同族其它规则覆盖
|
|
||||||
var family = null;
|
|
||||||
for (var f in familyMap) {
|
|
||||||
if (familyMap[f].indexOf(i) >= 0) { family = f; break; }
|
|
||||||
}
|
|
||||||
if (family && shownFamilies[family]) continue;
|
|
||||||
if (family) shownFamilies[family] = true;
|
|
||||||
shown[i] = true;
|
|
||||||
|
|
||||||
items.push("<li><code>" + ret[0] + "</code> → " + exps[i] + "</li>");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (items.length > 0) {
|
|
||||||
$("#errexp-list").html(items.join(""));
|
|
||||||
} else {
|
|
||||||
$("#errexp-list").html("<li class='empty-notice'>未匹配到具体错误模式,请参考原始错误信息或 AI 点评。</li>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
explain();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<?php if(isset($OJ_MARKDOWN) && $OJ_MARKDOWN){ ?>
|
<?php if(isset($OJ_MARKDOWN) && $OJ_MARKDOWN){ ?>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
@@ -587,4 +447,96 @@
|
|||||||
</script>
|
</script>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
|
<!-- 自动刷新:判题中(result < 4 或 > 14)时定时拉取最新状态 -->
|
||||||
|
<?php
|
||||||
|
$result_code_js = isset($row['result']) ? intval($row['result']) : 4;
|
||||||
|
$sid_js = isset($id) ? intval($id) : 0;
|
||||||
|
// 0=Pending, 1=Pending Rejudging, 2=Compiling, 3=Running/Judging, 14=Manual, 15=Submitting, 16/17=Remote
|
||||||
|
$is_pending = ($result_code_js < 4) || ($result_code_js > 14);
|
||||||
|
?>
|
||||||
|
<?php if ($sid_js > 0 && $is_pending): ?>
|
||||||
|
<script>
|
||||||
|
(function(){
|
||||||
|
var sid = <?php echo $sid_js ?>;
|
||||||
|
var currentResult = <?php echo $result_code_js ?>;
|
||||||
|
var interval = 1500; // 初始 1.5s
|
||||||
|
var maxInterval = 8000; // 最长 8s
|
||||||
|
var countdown = 0;
|
||||||
|
var stopped = false;
|
||||||
|
|
||||||
|
function showStatus(text){
|
||||||
|
var el = document.getElementById('auto-refresh-status');
|
||||||
|
var t = document.getElementById('auto-refresh-text');
|
||||||
|
if (el && t) {
|
||||||
|
el.style.display = '';
|
||||||
|
t.textContent = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideStatus(){
|
||||||
|
var el = document.getElementById('auto-refresh-status');
|
||||||
|
if (el) el.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function tick(){
|
||||||
|
if (stopped) return;
|
||||||
|
countdown--;
|
||||||
|
if (countdown > 0) {
|
||||||
|
showStatus('将在 ' + countdown + ' 秒后自动刷新');
|
||||||
|
setTimeout(tick, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fetch('status-ajax.php?solution_id=' + sid + '&t=json', {credentials: 'same-origin'})
|
||||||
|
.then(function(r){ return r.json(); })
|
||||||
|
.then(function(data){
|
||||||
|
if (!data || typeof data.result === 'undefined') {
|
||||||
|
// 解析失败,下次重试
|
||||||
|
interval = Math.min(interval * 1.5, maxInterval);
|
||||||
|
countdown = Math.ceil(interval / 1000);
|
||||||
|
tick();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var newResult = parseInt(data.result);
|
||||||
|
if (newResult >= 4 && newResult <= 14) {
|
||||||
|
// 判题完成,刷新页面拿到完整错误信息
|
||||||
|
showStatus('判题完成,正在刷新...');
|
||||||
|
setTimeout(function(){ location.reload(); }, 400);
|
||||||
|
stopped = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 仍在评判中
|
||||||
|
interval = Math.min(interval * 1.3, maxInterval);
|
||||||
|
countdown = Math.ceil(interval / 1000);
|
||||||
|
showStatus('判题中,将在 ' + countdown + ' 秒后再次查询');
|
||||||
|
setTimeout(tick, 1000);
|
||||||
|
})
|
||||||
|
.catch(function(err){
|
||||||
|
// 网络错误,重试
|
||||||
|
console.warn('auto refresh failed:', err);
|
||||||
|
interval = Math.min(interval * 1.5, maxInterval);
|
||||||
|
countdown = Math.ceil(interval / 1000);
|
||||||
|
showStatus('查询失败,' + countdown + ' 秒后重试');
|
||||||
|
setTimeout(tick, 1000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户切到后台标签时停止轮询,避免无意义请求
|
||||||
|
document.addEventListener('visibilitychange', function(){
|
||||||
|
if (document.hidden) {
|
||||||
|
stopped = true;
|
||||||
|
hideStatus();
|
||||||
|
} else if (!stopped) {
|
||||||
|
countdown = 0;
|
||||||
|
tick();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 启动
|
||||||
|
countdown = Math.ceil(interval / 1000);
|
||||||
|
showStatus('判题中,将在 ' + countdown + ' 秒后自动刷新');
|
||||||
|
setTimeout(tick, 1000);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php include("template/$OJ_TEMPLATE/footer.php");?>
|
<?php include("template/$OJ_TEMPLATE/footer.php");?>
|
||||||
|
|||||||
Reference in New Issue
Block a user