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']);
$problem_id = intval($row['problem_id']);
$problem_num = intval($row['num']);
$view_resubmit_url = "submitpage.php?id=".$problem_id."&sid=".intval($id);
$view_problem_url = "problem.php?id=".$problem_id;
if($contest_id > 0){
$view_resubmit_url = "submitpage.php?cid=".$contest_id."&pid=".$problem_num."&sid=".intval($id);
$view_problem_url = "problem.php?cid=".$contest_id."&pid=".$problem_num;
}
$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 && (strval($row['user_id'])===strval($_SESSION[$OJ_NAME.'_'.'user_id'])))||isset($_SESSION[$OJ_NAME.'_'.'source_browser']))
{
$ok = true;
}
// Compile Error has its own page with compiler diagnostics and source-line
// annotations. Redirect after the ownership check so submit-page polling and
// status-page clicks end up on the same safe CE view.
if ($ok && intval($row['result']) === 11) {
header("Location: ceinfo.php?sid=" . intval($id));
exit(0);
}
$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) {
if (trim($chunk) === '') continue;
$chunk = trim($chunk, "\r\n");
// 格式 1: 整段就是一个 =====[name]===== 块(包含表头+数据+结尾 ====)
// 形如 "========[test1.out]========\nExpected | Yours\nFail | Fall\n=============================="
if (preg_match('/^=+\[([^\]]+)\]\=+(.+?)\n=+\s*$/s', $chunk, $m)) {
$name = trim($m[1]);
$body = $m[2];
if (llm_guidance_testcase_base($name) === null) continue;
// OJ_FULL_DIFF also contains hidden test input. It is never interpreted
// as an Expected/Yours block; normal users fall back to focused guidance.
if (llm_guidance_has_full_diff_sections($chunk)) continue;
// body 形如 "\nExpected | Yours\nFail | Fall"
// 去掉首尾的换行符
$body = trim($body, "\n\r");
$rows = llm_guidance_parse_diff_rows($body);
$expected = $rows['expected'];
$yours = $rows['yours'];
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];
if (llm_guidance_testcase_base($name) === null) continue;
$rows = llm_guidance_parse_diff_rows($body);
$expected = $rows['expected'];
$yours = $rows['yours'];
if (!empty($expected)) {
$blocks[] = array(
'name' => $name,
'expected' => $expected,
'yours' => $yours,
'full_mode' => false,
);
}
}
}
return $blocks;
}
$is_compile_error = intval($row['result']) == 11;
$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(strval($row['user_id'])!==strval($_SESSION[$OJ_NAME.'_'.'user_id'])){
$view_mail_link= "Mail the auther";
}
$sql = $is_compile_error
? "SELECT `error` FROM `compileinfo` WHERE `solution_id`=?"
: "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 = "";
} elseif ($is_compile_error) {
$view_reinfo_summary = $raw_error;
} 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;
$show_raw = $is_admin_session || $is_source_browser;
$unsafe_full_diff = llm_guidance_has_full_diff_sections($raw_error);
// 尝试解析为结构化的 diff 数据(用于高完成度 WA/PE 的对比展示)。
// Full diff 同时携带隐藏输入,普通页面不解析也不回显。
$diff_blocks = $unsafe_full_diff ? array() : parse_diff_blocks($raw_error);
// 完成度只使用学生自己的源码和判题统计;不查询参考答案。
$source_result = pdo_query("SELECT `source` FROM `source_code_user` WHERE `solution_id`=?", $id);
$student_source = (!empty($source_result) && $source_result !== -1)
? $source_result[0]['source']
: "";
$llm_guidance = llm_guidance_assess($student_source, $result_code, floatval($row['pass_rate']));
$llm_guidance = llm_guidance_refine_with_output_attempt(
$llm_guidance,
$result_code,
llm_guidance_output_attempt($unsafe_full_diff ? '' : $raw_error)
);
if ($llm_guidance['show_output_diff'] && empty($diff_blocks)) {
$llm_guidance['mode'] = 'focused_hint';
$llm_guidance['show_output_diff'] = false;
}
$llm_guidance_auto_fetch = true;
// 管理员或 source_browser 永远看完整原文。普通学生的 WA/PE
// 只看经过策略授权的结构化 diff,不再从原始折叠区旁路读取。
if (!$show_raw && ($result_code === 5 || $result_code === 6)) {
if ($llm_guidance['show_output_diff'] && !empty($diff_blocks)) {
$view_reinfo_summary = "已在下方显示本次错误测试点的结构化输出差异。";
} else {
// 低/中完成度不能通过重复白卷提交套取隐藏测试点答案。
$diff_blocks = array();
$view_reinfo_summary = "当前提交完成度不足,暂不显示隐藏测试点的期望输出。请先补齐程序,再重新提交。";
}
}
if ($show_raw) {
$view_reinfo = $view_reinfo_raw;
} else {
$view_reinfo = $view_reinfo_summary;
}
$llm_guidance_has_output_diff = !empty($diff_blocks);
$is_owner_session = isset($_SESSION[$OJ_NAME.'_'.'user_id'])
&& strval($row['user_id']) === strval($_SESSION[$OJ_NAME.'_'.'user_id']);
$download_hidden_spj = !empty($spj)
&& intval($spj[0][0]) === 2
&& !empty($OJ_HIDE_RIGHT_ANSWER);
$download_diff_enabled = !isset($OJ_SHOW_DIFF) || $OJ_SHOW_DIFF;
$llm_guidance_download_allowed = $is_admin_session
|| ($is_owner_session
&& $download_diff_enabled
&& !$download_hidden_spj
&& !$unsafe_full_diff
&& !empty($llm_guidance['show_output_diff']));
}
// 不是本人的提交,且不是 source_browser
else{
if($spj[0][0]!=2) $view_errors = $MSG_WARNING_ACCESS_DENIED;
require("template/".$OJ_TEMPLATE."/error.php");
exit(0);
}
/////////////////////////Template
if(!$is_compile_error && !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');
}
?>