321 lines
12 KiB
PHP
321 lines
12 KiB
PHP
<?php $show_title=$id." - $MSG_ERROR_INFO - $OJ_NAME"; ?>
|
|
<?php include("template/$OJ_TEMPLATE/header.php");?>
|
|
|
|
<script src="include/vditor-adapter.js"></script>
|
|
<script src="template/<?php echo $OJ_TEMPLATE?>/js/textFit.min.js"></script>
|
|
<style>
|
|
.single-subtask {
|
|
box-shadow: none !important;
|
|
}
|
|
|
|
.single-subtask > .title {
|
|
display: none;
|
|
}
|
|
|
|
.single-subtask > .content {
|
|
padding: 0 !important;
|
|
}
|
|
|
|
.accordion > .content > .accordion {
|
|
margin-top: 0;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.accordion > .content > .accordion > .content {
|
|
margin-top: 0;
|
|
margin-bottom: 14px;
|
|
}
|
|
|
|
.accordion > .content > .accordion > .content > :last-child {
|
|
margin-bottom: -10px !important;
|
|
}
|
|
</style>
|
|
|
|
<div class="padding">
|
|
<div style="margin-top: 0px; margin-bottom: 14px; " v-if="content != null && content !== ''">
|
|
<p class="transition visible">
|
|
<strong ><?php echo "$MSG_ERROR_INFO";?> </strong>
|
|
</p>
|
|
<div class="ui existing segment">
|
|
<div v-if="escape" style="margin-top: 0; margin-bottom: 0; " id="errtxt">
|
|
<pre><?php
|
|
echo $view_reinfo
|
|
?></pre>
|
|
<h2></h2>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 0px; margin-bottom: 14px; " v-if="content != null && content !== ''">
|
|
<p class="transition visible">
|
|
<strong ><?php echo "$MSG_INFO_EXPLAINATION";?></strong>
|
|
</p>
|
|
<div class="ui existing segment">
|
|
<pre v-if="escape" style="margin-top: 0; margin-bottom: 0; "><code><div id='errexp'></div></code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
var pats=new Array();
|
|
var exps=new Array();
|
|
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 ?>";
|
|
|
|
function explain(){
|
|
var errmsg = $("#errtxt").text();
|
|
var expmsg = "";
|
|
for(var i=0; i<pats.length; i++){
|
|
var pat = pats[i];
|
|
var exp = exps[i];
|
|
var ret = pat.exec(errmsg);
|
|
if(ret){
|
|
expmsg += ret+" : "+exp+"<br><hr />";
|
|
}
|
|
}
|
|
document.getElementById("errexp").innerHTML=expmsg;
|
|
}
|
|
explain();
|
|
</script>
|
|
|
|
<?php if(isset($OJ_MARKDOWN)&&$OJ_MARKDOWN){ ?>
|
|
<script>
|
|
$(document).ready(function(){
|
|
HustOJVditor.renderMarkdownBlocks('#errtxt', {
|
|
getSource: function (element) {
|
|
var pre = element.querySelector ? element.querySelector('pre') : null;
|
|
return pre ? pre.textContent : element.textContent || '';
|
|
}
|
|
}).then(function () {
|
|
for(let i=1;i<10;i++){
|
|
$(".language-input"+i).parent().before("<div><?php echo $MSG_Input?>"+i+":</div>");
|
|
$(".language-output"+i).parent().before("<div><?php echo $MSG_Output?>"+i+":</div>");
|
|
}
|
|
|
|
|
|
$("#errtxt table").addClass("ui mini-table cell striped");
|
|
$("#errtxt table tr:odd td").css({
|
|
"border": "1px solid grey",
|
|
"text-align": "center",
|
|
"width": "200px",
|
|
"background-color": "#8521d022",
|
|
"height": "30px"
|
|
});
|
|
$("#errtxt table tr:even td").css({
|
|
"border": "1px solid grey",
|
|
"text-align": "center",
|
|
"width": "200px",
|
|
"background-color": "#2185d022",
|
|
"height": "30px"
|
|
});
|
|
$("#errtxt table th").css({
|
|
"border": "1px solid grey",
|
|
"width": "200px",
|
|
"height": "30px",
|
|
"background-color": "#2185d088",
|
|
"text-align": "center"
|
|
});
|
|
<?php
|
|
if(isset($OJ_DOWNLOAD)&&$OJ_DOWNLOAD){
|
|
if(isset($OJ_DL_1ST_WA_ONLY) && $OJ_DL_1ST_WA_ONLY){
|
|
?>
|
|
let down=$($("#errtxt").find("h2")[0]);
|
|
let filename=down.text();
|
|
down.html("<a href='download.php?sid=<?php echo $id?>&name=" + filename+ "'>" + filename+ "</a>");
|
|
<?php
|
|
}else{
|
|
?>
|
|
$("#errtxt").find("h2").each(function(){
|
|
let down=$(this);
|
|
let filename=down.text();
|
|
console.log(filename);
|
|
down.html("<a href='download.php?sid=<?php echo $id?>&name=" + filename+ "'>" + filename+ "</a>");
|
|
});
|
|
|
|
<?php
|
|
}
|
|
}
|
|
?>
|
|
$("th").each(function(){
|
|
let html=$(this).html();
|
|
html=html.replace("Expected","<?php echo $MSG_EXPECTED ?>");
|
|
html=html.replace("Yours","<?php echo $MSG_YOURS ?>");
|
|
html=html.replace("filename","<?php echo $MSG_FILENAME ?>");
|
|
html=html.replace("size","<?php echo $MSG_SIZE ?>");
|
|
html=html.replace("result","<?php echo $MSG_RESULT ?>");
|
|
html=html.replace("memory","<?php echo $MSG_MEMORY?>");
|
|
html=html.replace("time","<?php echo $MSG_TIME ?>");
|
|
$(this).html(html);
|
|
|
|
});
|
|
}).catch(function (error) {
|
|
console.error('Failed to render reinfo markdown.', error);
|
|
});
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
<?php } ?>
|
|
|
|
<?php if(isset($OJ_LLM_ENABLED) && $OJ_LLM_ENABLED){ ?>
|
|
<div style="margin-top: 20px; margin-bottom: 14px; ">
|
|
<div class="ui styled fluid accordion" id="llm-review-accordion">
|
|
<div class="title" style="font-size: 1.1em; font-weight: bold; ">
|
|
<i class="dropdown icon"></i> 🤖 AI 点评
|
|
</div>
|
|
<div class="content">
|
|
<div id="llm-review-area">
|
|
<button class="ui labeled icon blue button" id="llm-review-btn" onclick="fetchLLMReview()">
|
|
<i class="magic icon"></i> 获取 AI 点评
|
|
</button>
|
|
<div id="llm-review-loading" style="display:none; margin-top: 15px; ">
|
|
<div class="ui active centered inline text loader">AI 正在分析你的代码,请稍候...</div>
|
|
</div>
|
|
<div id="llm-review-result" style="display:none; margin-top: 15px; ">
|
|
<div class="ui existing segment" id="llm-review-content"></div>
|
|
</div>
|
|
<div id="llm-review-error" style="display:none; margin-top: 15px; ">
|
|
<div class="ui negative message">
|
|
<p id="llm-review-error-msg"></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
$(document).ready(function(){
|
|
$('#llm-review-accordion').accordion();
|
|
});
|
|
|
|
function fetchLLMReview(){
|
|
var btn = $('#llm-review-btn');
|
|
btn.prop('disabled', true).addClass('loading');
|
|
$('#llm-review-loading').show();
|
|
$('#llm-review-error').hide();
|
|
$('#llm-review-result').hide();
|
|
|
|
var fullText = "";
|
|
var container = document.getElementById('llm-review-content');
|
|
var resultDiv = document.getElementById('llm-review-result');
|
|
var reader = null;
|
|
var decoder = new TextDecoder();
|
|
|
|
// 解析 SSE 事件
|
|
var sseBuffer = "";
|
|
function processSSE(text) {
|
|
sseBuffer += text;
|
|
var lines = sseBuffer.split('\n');
|
|
sseBuffer = lines.pop(); // 保留未完成的行
|
|
|
|
var currentEvent = "";
|
|
for (var i = 0; i < lines.length; i++) {
|
|
var line = lines[i];
|
|
if (line.indexOf('event: ') === 0) {
|
|
currentEvent = line.substring(7);
|
|
} else if (line.indexOf('data: ') === 0) {
|
|
var dataStr = line.substring(6);
|
|
try {
|
|
var data = JSON.parse(dataStr);
|
|
if (currentEvent === 'chunk') {
|
|
fullText += data.text;
|
|
container.textContent = fullText;
|
|
resultDiv.style.display = 'block';
|
|
} else if (currentEvent === 'cached') {
|
|
fullText = data.text;
|
|
container.textContent = fullText;
|
|
resultDiv.style.display = 'block';
|
|
} else if (currentEvent === 'done') {
|
|
finishReview();
|
|
} else if (currentEvent === 'error') {
|
|
showError(data.message || '未知错误');
|
|
}
|
|
} catch(e) {}
|
|
currentEvent = "";
|
|
}
|
|
}
|
|
}
|
|
|
|
function finishReview() {
|
|
btn.removeClass('loading').hide();
|
|
document.getElementById('llm-review-loading').style.display = 'none';
|
|
resultDiv.style.display = 'block';
|
|
// 渲染 Markdown
|
|
if (fullText && typeof HustOJVditor !== 'undefined' && HustOJVditor.renderMarkdownBlocks) {
|
|
HustOJVditor.renderMarkdownBlocks('#llm-review-content', { useTextContent: true });
|
|
}
|
|
}
|
|
|
|
function showError(msg) {
|
|
btn.removeClass('loading').prop('disabled', false);
|
|
document.getElementById('llm-review-loading').style.display = 'none';
|
|
document.getElementById('llm-review-error-msg').textContent = msg;
|
|
document.getElementById('llm-review-error').style.display = 'block';
|
|
}
|
|
|
|
if (typeof fetch === 'undefined') {
|
|
showError('浏览器不支持,请升级浏览器');
|
|
return;
|
|
}
|
|
|
|
fetch('llm-review.php?sid=<?php echo intval($id); ?>')
|
|
.then(function(response) {
|
|
if (!response.ok) {
|
|
return response.text().then(function(text) {
|
|
try {
|
|
var d = JSON.parse(text);
|
|
showError(d.error || '请求失败 (HTTP ' + response.status + ')');
|
|
} catch(e) {
|
|
showError('请求失败 (HTTP ' + response.status + ')');
|
|
}
|
|
});
|
|
}
|
|
reader = response.body.getReader();
|
|
function read() {
|
|
reader.read().then(function(result) {
|
|
if (result.done) {
|
|
if (fullText) finishReview();
|
|
return;
|
|
}
|
|
var text = decoder.decode(result.value, { stream: true });
|
|
processSSE(text);
|
|
read();
|
|
}).catch(function(err) {
|
|
if (fullText) {
|
|
finishReview();
|
|
} else {
|
|
showError('读取响应失败: ' + err.message);
|
|
}
|
|
});
|
|
}
|
|
read();
|
|
})
|
|
.catch(function(err) {
|
|
showError('网络请求失败: ' + err.message);
|
|
});
|
|
}
|
|
</script>
|
|
<?php } ?>
|
|
|
|
<?php include("template/$OJ_TEMPLATE/footer.php");?>
|