Compare commits
2 Commits
c22c788cfa
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 9b13c95e8a | |||
| 0e5cac3d4e |
248
web/reinfo.php
248
web/reinfo.php
@@ -102,6 +102,145 @@ function dedup_runtimeinfo($text, &$dedup_count) {
|
||||
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: "a<b" 或 "a>b"(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 = ""; // 折叠后(普通用户看)
|
||||
@@ -120,7 +259,9 @@ if($ok){
|
||||
$rt = pdo_query($sql,$id);
|
||||
$raw_error = "";
|
||||
if(isset($rt[0])){
|
||||
$raw_error = str_replace("\n\r","\n",$rt[0]['error']);
|
||||
$raw_error = $rt[0]['error'];
|
||||
// 统一换行符:先替换 \r\n,再替换单独的 \r
|
||||
$raw_error = str_replace(array("\r\n", "\r"), "\n", $raw_error);
|
||||
}
|
||||
|
||||
// === 阶段 1:基于 solution.result 给"主解释"(永远非空)===
|
||||
@@ -215,111 +356,6 @@ if($ok){
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把 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 每个测试点之间有空行)
|
||||
// 但要避免切分 full mode 里的内容
|
||||
$chunks = preg_split('/\n\s*\n/', $text);
|
||||
foreach ($chunks as $chunk) {
|
||||
$chunk = trim($chunk);
|
||||
if ($chunk === '') continue;
|
||||
|
||||
// full mode: 形如 "========[test1.out]=========" 开头
|
||||
if (preg_match('/^=+\[([^\]]+)\]=+$/m', $chunk, $m_head)) {
|
||||
$name = $m_head[1];
|
||||
// 提取 "------diff out 200 lines-----" 后面的内容
|
||||
if (preg_match('/------diff out[^\n]*-+\n(.*?)\n=+\s*$/s', $chunk, $m_diff)) {
|
||||
$diff_text = trim($m_diff[1]);
|
||||
} else {
|
||||
continue; // 没找到 diff 段,跳过
|
||||
}
|
||||
$lines = parse_diff_side_by_side($diff_text);
|
||||
if (!empty($lines)) {
|
||||
$blocks[] = array(
|
||||
'name' => $name,
|
||||
'expected' => $lines['expected'],
|
||||
'yours' => $lines['yours'],
|
||||
'full_mode' => true,
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// simple mode: 形如 "test1.out\n--\n|Expected|Yours\n|--|--\n|..."
|
||||
if (preg_match('/^([^\n|]+)\n--\n\|Expected\|Yours\n\|--\|--\n(.*)$/s', $chunk, $m)) {
|
||||
$name = trim($m[1]);
|
||||
$table = $m[2];
|
||||
$lines = parse_pipe_diff_table($table);
|
||||
if (!empty($lines)) {
|
||||
$blocks[] = array(
|
||||
'name' => $name,
|
||||
'expected' => $lines['expected'],
|
||||
'yours' => $lines['yours'],
|
||||
'full_mode' => false,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 "|expected|yours\n" 格式的表格
|
||||
* 已知边角:每行以 | 开头和 | 分隔;空字段表示没有该行
|
||||
*/
|
||||
function parse_pipe_diff_table($text) {
|
||||
$expected = array();
|
||||
$yours = array();
|
||||
$lines = explode("\n", $text);
|
||||
foreach ($lines as $line) {
|
||||
if (strlen($line) < 2 || $line[0] !== '|') continue;
|
||||
// 形如 "|a|b" 拆出 a 和 b
|
||||
$rest = substr($line, 1);
|
||||
// 找第一个 |
|
||||
$pos = strpos($rest, '|');
|
||||
if ($pos === false) continue;
|
||||
$left = substr($rest, 0, $pos);
|
||||
$right = substr($rest, $pos + 1);
|
||||
$expected[] = $left;
|
||||
$yours[] = $right;
|
||||
}
|
||||
if (empty($expected)) return array();
|
||||
return array('expected' => $expected, 'yours' => $yours);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 `diff -y` 格式: " < expected > yours"
|
||||
* 中间用 | 或 / 分隔(取决于 GNU diff 版本)
|
||||
*/
|
||||
function parse_diff_side_by_side($text) {
|
||||
$expected = array();
|
||||
$yours = array();
|
||||
$lines = explode("\n", $text);
|
||||
foreach ($lines as $line) {
|
||||
// 找中间的 | 或 / (GNU diff -y 格式)
|
||||
// 形如 " line1 | line2 " 或 " line1 < line2 "
|
||||
if (preg_match('/^(.*?)\s+[<>|]\s+(.*)$/', $line, $m)) {
|
||||
$expected[] = $m[1];
|
||||
$yours[] = $m[2];
|
||||
} elseif (trim($line) === '') {
|
||||
// 空行:两边都空
|
||||
} else {
|
||||
// 单边(一边空):整行属于另一边
|
||||
$expected[] = $line;
|
||||
$yours[] = '';
|
||||
}
|
||||
}
|
||||
if (empty($expected)) return array();
|
||||
return array('expected' => $expected, 'yours' => $yours);
|
||||
}
|
||||
|
||||
// 不是本人的提交,且不是 source_browser
|
||||
else{
|
||||
if($spj[0][0]!=2) $view_errors = $MSG_WARNING_ACCESS_DENIED;
|
||||
|
||||
Reference in New Issue
Block a user