3) return true; // 如果希望能让任何人都查看对比和RE,放开行首注释,并设定$OJ_SHOW_DIFF=true; // return true; $n = strlen($str2); $str = str_split($str2); $m = 1; for($i=0; $i<$n; $i++){ if(is_numeric($str[$i])) $m++; } return $n/$m>3; } if(!isset($_SESSION[$OJ_NAME.'_'.'user_id'])){ $view_errors = $MSG_WARNING_ACCESS_DENIED ; require("template/".$OJ_TEMPLATE."/error.php"); exit(0); } $ok = false; $id = strval(intval($_GET['sid'])); $sql = "SELECT * FROM `solution` WHERE `solution_id`=?"; $result = pdo_query($sql,$id); $row = $result[0]; $lang = $row['language']; $contest_id = intval($row['contest_id']); $isRE = $row['result']==10; $isAC = $row['result']==4 ; $mark=$row['pass_rate']*100; if($isAC) $mark=100; if((isset($_SESSION[$OJ_NAME.'_'.'user_id']) && $row && ($row['user_id']==$_SESSION[$OJ_NAME.'_'.'user_id']))||isset($_SESSION[$OJ_NAME.'_'.'source_browser'])) { $ok = true; } $spj=pdo_query("select spj from problem where problem_id=?",$row['problem_id']); if(!empty($spj)&&$spj[0][0]==2 && $OJ_HIDE_RIGHT_ANSWER && !isset($_SESSION[$OJ_NAME.'_'.'source_browser']) ){ $view_errors = "

$MSG_MARK:$mark


"; $ok = false; } /** * 把 N 个相同测试点的 RE 折叠为 "1.in~5.in: Aborted (共 5 个测试点)" */ function dedup_runtimeinfo($text, &$dedup_count) { $lines = explode("\n", $text); $buckets = array(); // reason => [testcase, ...] $other = array(); foreach ($lines as $line) { $line = trim($line); if ($line === "") continue; // 形如 "data/1001/1.in:Aborted" 或 "1.in: Segmentation fault" if (preg_match('/^(?:data\/\d+\/)?([^\s:]+(?:[.:][^\s:]+)*?):\s*(.+)$/', $line, $m)) { $tc = $m[1]; $reason = trim($m[2]); $buckets[$reason][] = $tc; } else { $other[] = $line; } } $out = array(); foreach ($other as $o) $out[] = $o; foreach ($buckets as $reason => $tcs) { $count = count($tcs); if ($count == 1) { $out[] = $tcs[0] . ": " . $reason; } else { $first = $tcs[0]; $last = $tcs[$count - 1]; $range = ($first === $last) ? $first : ($first . "~" . $last); $out[] = $range . ": " . $reason . " (共 " . $count . " 个测试点)"; $dedup_count += ($count - 1); } } return implode("\n", $out); } /** * 把 runtimeinfo.error 解析为结构化的 diff blocks * 返回 [['name' => 'test1.out', 'expected' => [...], 'yours' => [...], 'full_mode' => bool], ...] * 解析失败返回空数组 */ function parse_diff_blocks($text) { $blocks = array(); if (empty($text)) return $blocks; // 先按 "\n\n" 切分(simple mode 每个测试点之间有空行) $chunks = preg_split('/\n\s*\n/', $text); foreach ($chunks as $chunk) { $chunk = trim($chunk); if ($chunk === '') continue; // 格式 1: 整段就是一个 =====[name]===== 块(包含表头+数据+结尾 ====) // 形如 "========[test1.out]========\nExpected | Yours\nFail | Fall\n==============================" if (preg_match('/^=+\[([^\]]+)\]\=+(.+?)\n=+\s*$/s', $chunk, $m)) { $name = trim($m[1]); $body = $m[2]; // body 形如 "\nExpected | Yours\nFail | Fall" // 去掉首尾的换行符 $body = trim($body, "\n\r"); $lines_in_body = explode("\n", $body); $expected = array(); $yours = array(); $found_header = false; foreach ($lines_in_body as $bl) { $bl = rtrim($bl); if ($bl === '') continue; // 跳过表头 if (!$found_header && preg_match('/^Expected.*\|.*Yours/i', $bl)) { $found_header = true; continue; } if (!$found_header && (preg_match('/^\|?--\s*\|/', $bl) || trim($bl) === '--')) { continue; } $parsed = parse_one_diff_line($bl); if ($parsed !== null) { $expected[] = $parsed[0]; $yours[] = $parsed[1]; $found_header = true; } else { $expected[] = $bl; $yours[] = ''; $found_header = true; } } if (!empty($expected)) { $blocks[] = array( 'name' => $name, 'expected' => $expected, 'yours' => $yours, 'full_mode' => true, ); } continue; } // 格式 2: simple mode "test1.out\n--\n|Expected|Yours\n|--|--\n|row1|row2" if (preg_match('/^([^\n=|]+)\n--\n([\s\S]+)$/', $chunk, $m)) { $name = trim($m[1]); $body = $m[2]; $lines_in_body = explode("\n", $body); $expected = array(); $yours = array(); $found_header = false; foreach ($lines_in_body as $bl) { $bl = rtrim($bl); if ($bl === '') continue; if (!$found_header && preg_match('/Expected.*\|.*Yours/i', $bl)) { $found_header = true; continue; } if (!$found_header && (preg_match('/^\|?--\s*\|/', $bl) || trim($bl) === '--')) { continue; } $parsed = parse_one_diff_line($bl); if ($parsed !== null) { $expected[] = $parsed[0]; $yours[] = $parsed[1]; $found_header = true; } else { $expected[] = $bl; $yours[] = ''; $found_header = true; } } if (!empty($expected)) { $blocks[] = array( 'name' => $name, 'expected' => $expected, 'yours' => $yours, 'full_mode' => false, ); } } } return $blocks; } /** * 解析单行 "expected | yours" 格式 * 支持 "|a|b"、"a | b"、"a|b" 等 * 返回 [left, right] 或 null(无法解析) */ function parse_one_diff_line($line) { $line = rtrim($line); if ($line === '') return null; // 格式 A: "|a|b" (首尾带 |) if ($line[0] === '|') { $rest = substr($line, 1); $pos = strpos($rest, '|'); if ($pos !== false) { return array(substr($rest, 0, $pos), substr($rest, $pos + 1)); } } // 格式 B: "a | b" 或 "a | b"(带空格的 markdown 风格) // 注意:可能行内有空格,所以用 " | " 或 " | " 等宽松匹配 if (preg_match('/^(.*?)\s+\|\s+(.*)$/', $line, $m)) { // 确保左右两边都非空 $left = trim($m[1]); $right = trim($m[2]); if ($left !== '' || $right !== '') { return array($left, $right); } } // 格式 C: "ab"(diff -y 风格) if (preg_match('/^(.*?)\s+([<>])\s+(.*)$/', $line, $m)) { return array($m[1], $m[3]); } return null; } $view_reinfo = ""; $view_reinfo_raw = ""; // 原始(管理员/有权限者看) $view_reinfo_summary = ""; // 折叠后(普通用户看) $view_reinfo_dedup_count = 0; // 折叠掉的测试点数 $verdict_color_class = "blue"; // semantic ui color: green/red/orange/yellow/grey $result_icon = "info circle"; $verdict_tip = ""; if($ok){ if($row['user_id']!=$_SESSION[$OJ_NAME.'_'.'user_id']){ $view_mail_link= "Mail the auther"; } $sql = "SELECT `error` FROM `runtimeinfo` WHERE `solution_id`=?"; $rt = pdo_query($sql,$id); $raw_error = ""; if(isset($rt[0])){ $raw_error = $rt[0]['error']; // 统一换行符:先替换 \r\n,再替换单独的 \r $raw_error = str_replace(array("\r\n", "\r"), "\n", $raw_error); } // === 阶段 1:基于 solution.result 给"主解释"(永远非空)=== $result_code = intval($row['result']); $is_admin_session = isset($_SESSION[$OJ_NAME."_administrator"]); $is_source_browser = isset($_SESSION[$OJ_NAME.'_'.'source_browser']); // 颜色 + 图标 switch ($result_code) { case 4: $verdict_color_class = "green"; $result_icon = "check circle"; break; case 5: // PE case 6: $verdict_color_class = "red"; $result_icon = "times circle"; break; case 7: // TLE case 8: // MLE case 9: $verdict_color_class = "yellow";$result_icon = "hourglass end"; break; case 10: $verdict_color_class = "red"; $result_icon = "bug"; break; case 11: $verdict_color_class = "grey"; $result_icon = "code"; break; case 13: $verdict_color_class = "blue"; $result_icon = "play circle"; break; default: $verdict_color_class = "blue"; $result_icon = "info circle"; } // 友好提示:仅保留标题性文字,具体修复建议交给 AI 点评 switch ($result_code) { case 4: // AC $verdict_tip = "本次提交通过了所有测试点"; break; case 5: // PE $verdict_tip = "输出与预期基本一致但格式不符(Presentation Error)"; break; case 6: // WA $verdict_tip = "输出与预期不符(Wrong Answer)"; break; case 7: // TLE $verdict_tip = $MSG_HINT_TLE; break; case 8: // MLE $verdict_tip = $MSG_HINT_MLE; break; case 9: // OLE $verdict_tip = $MSG_HINT_OLE; break; case 10: // RE $verdict_tip = "程序运行中发生错误(Runtime Error)"; break; case 11: // CE $verdict_tip = "编译错误(Compile Error)。请查看编译信息页。"; break; case 13: // TR (test run) $verdict_tip = "测试运行完成(Test Run)"; break; default: $verdict_tip = "正在评判,请稍候刷新"; } // === 阶段 3:原始错误处理(syscall 提示 vs 占位符修复)=== $view_reinfo_raw = $raw_error; if (trim($raw_error) === "") { // TLE/MLE/OLE 时 runtimeinfo 通常为空 $view_reinfo_summary = ""; } else { // 含 "PASS" 不再显示 "error3" 占位 // 含 "php" 不再显示 "error2" 占位(用 generic 提示) if (strpos($raw_error, "php") !== false) { $view_reinfo_summary = $MSG_RUNTIME_GENERIC_ERROR; $view_reinfo_raw = $raw_error; // 管理员仍能看 } // 含 "judge/" 区分:是否是 syscall 错误 elseif (strpos($raw_error, "judge/") !== false && strpos($raw_error, "CALLID") === false && strpos($raw_error, "Forbidden system call") === false) { $view_reinfo_summary = "潜在的数组或指针越界,请检查代码。"; } // 默认:原文 + 去重 else { $view_reinfo_summary = $raw_error; // 多测试点去重:按 "infile: error" 模式分组 $view_reinfo_summary = dedup_runtimeinfo($view_reinfo_summary, $view_reinfo_dedup_count); } } $view_reinfo = $view_reinfo_summary; // 尝试解析为结构化的 diff 数据(用于 WA/PE/AC 时的对比展示) $diff_blocks = parse_diff_blocks($raw_error); // 管理员或 source_browser 永远看完整原文 $show_raw = $is_admin_session || $is_source_browser; if ($show_raw) { $view_reinfo = $view_reinfo_raw; } else { $view_reinfo = $view_reinfo_summary; } } // 不是本人的提交,且不是 source_browser else{ if($spj[0][0]!=2) $view_errors = $MSG_WARNING_ACCESS_DENIED; require("template/".$OJ_TEMPLATE."/error.php"); exit(0); } /////////////////////////Template if(!isset($_SESSION[$OJ_NAME.'_'.'source_browser']) && $OJ_SHOW_DIFF==false){ $view_errors = $MSG_WARNING_ACCESS_DENIED; require("template/".$OJ_TEMPLATE."/error.php"); exit(0); } else{ require("template/".$OJ_TEMPLATE."/reinfo.php"); } /////////////////////////Common foot if(file_exists('./include/cache_end.php')){ require_once('./include/cache_end.php'); } ?>