<% this.title = '提交记录 #' + info.submissionId %> <% include util %> <% include header %> <script src="/textFit.js"></script> <span id="submission_content"> <div class="padding" id="vueApp"> <table class="ui very basic center aligned table" id="status_table"> <thead> <tr> <th>编号</th> <th>题目</th> <th>状态</th> <th v-if="displayConfig.showScore">分数</th> <th v-if="displayConfig.showUsage">总时间</th> <th v-if="displayConfig.showUsage">内存</th> <th v-if="displayConfig.showCode">代码 / 答案文件</th> <th>提交者</th> <th>提交时间</th> <th v-if="showRejudge">重新评测</th> </tr> </thead> <tbody> <tr is="submission-item" v-bind:data="roughData" :config="displayConfig" :show-rejudge="showRejudge"></tr> </tbody> </table> <code-box :escape="false" v-bind:content="code"></code-box> <code-box v-if="detailResult && detailResult.compile" :escape="false" title="编译信息" v-bind:content="detailResult.compile.message"></code-box> <code-box v-if="detailResult" title="系统信息" :escape="true" v-bind:content="detailResult.systemMessage"></code-box> <div class="ui styled fluid accordion" v-if="detailResult && detailResult.judge && detailResult.judge.subtasks"> <template v-for="subtask, $index in detailResult.judge.subtasks"> <div class="title" :class="singleSubtask ? 'active' : ''"> <div class="ui grid"> <div class="three wide column"> <i class="dropdown icon"></i> 子任务 #{{ $index + 1 }} </div> <div class="four wide column"> <status-label :status="getSubtaskResult(subtask)"></status-label> </div> <div class="three wide column" v-if="subtask.score != null">得分 <span style="font-weight: normal; ">{{ Math.trunc(subtask.score) }}</span> </div> </div> </div> <div class="content" :class="singleSubtask ? 'active' : ''"> <div class="accordion"> <template v-for="curCase, $caseIndex in subtask.cases"> <div class="title"> <div class="ui grid"> <div class="three wide column"> <i class="dropdown icon"></i> 测试点 #{{ $caseIndex + 1 }} </div> <div class="four wide column"> <status-label :status="getTestcaseStatus(curCase)"></status-label> </div> <template v-if="checkTestcaseOK(curCase)"> <div class="three wide column">得分率 <span style="font-weight: normal; ">{{ Math.trunc(curCase.result.scoringRate * 100) }}</span> </div> <div class="three wide column" v-if="curCase.result.time != null && curCase.result.time !== NaN">用时 <span style="font-weight: normal; ">{{ curCase.result.time }} ms</span> </div> <div class="three wide column" v-if="curCase.result.memory != null && curCase.result.memory !== NaN">内存 <span style="font-weight: normal; ">{{ curCase.result.memory }} KiB</span> </div> </template> </div> </div> <div class="content"> <template v-if="checkTestcaseOK(curCase)"> <code-box v-if="curCase.result.input" :title="'输入文件('+ curCase.result.input.name +')'" :content="curCase.result.input.content"></code-box> <code-box v-if="curCase.result.output" :title="'答案文件('+ curCase.result.output.name +')'" :content="curCase.result.output.content"></code-box> <code-box title="用户输出" :content="curCase.result.userOutput"></code-box> <code-box title="标准错误流" :content="curCase.result.userError"></code-box> <code-box title="Special Judge 信息" :content="curCase.result.spjMessage"></code-box> <code-box title="系统信息" :content="curCase.result.systemMessage"></code-box> </template> <code-box title="错误信息" :content="curCase.errorMessage"></code-box> </div> </template> </div> </div> </template> </div> </div> <script src="//cdn.bootcss.com/vue/2.4.2/vue.js"></script> <script src="//cdn.bootcss.com/socket.io/2.0.3/socket.io.js"></script> <script src="//cdn.bootcss.com/jsondiffpatch/0.2.4/jsondiffpatch.js"></script> <% include submissions_item %> <script type="text/x-template" id="codeBoxTemplate"> <div style="" v-if="content != null && content !== ''"> <div></div> <h3 v-if="title" class="ui header">{{ title }}</h3> <div class="ui existing segment"> <pre v-if="escape" style="margin-top: 0; margin-bottom: 0; "><code>{{ content }}</code></pre> <pre v-if="!escape" style="margin-top: 0; margin-bottom: 0; "><code v-html="content"></code></pre> </div> </div> </script> <script> Vue.component("code-box", { template: "#codeBoxTemplate", props: ['title', 'content', 'escape'], }); const socketUrl = <%- syzoj.utils.judgeServer('detail') %>; const displayConfig = <%- JSON.stringify(displayConfig) %>; const token = <%- JSON.stringify(socketToken) %>; const TestcaseResultType = {}; (function (TestcaseResultType) { TestcaseResultType[TestcaseResultType["Accepted"] = 1] = "Accepted"; TestcaseResultType[TestcaseResultType["WrongAnswer"] = 2] = "WrongAnswer"; TestcaseResultType[TestcaseResultType["PartiallyCorrect"] = 3] = "PartiallyCorrect"; TestcaseResultType[TestcaseResultType["MemoryLimitExceeded"] = 4] = "MemoryLimitExceeded"; TestcaseResultType[TestcaseResultType["TimeLimitExceeded"] = 5] = "TimeLimitExceeded"; TestcaseResultType[TestcaseResultType["OutputLimitExceeded"] = 6] = "OutputLimitExceeded"; TestcaseResultType[TestcaseResultType["FileError"] = 7] = "FileError"; TestcaseResultType[TestcaseResultType["RuntimeError"] = 8] = "RuntimeError"; TestcaseResultType[TestcaseResultType["JudgementFailed"] = 9] = "JudgementFailed"; TestcaseResultType[TestcaseResultType["InvalidInteraction"] = 10] = "InvalidInteraction"; })(TestcaseResultType); const statusToString = {}; statusToString[TestcaseResultType.Accepted] = "Accepted"; statusToString[TestcaseResultType.WrongAnswer] = "Wrong Answer"; statusToString[TestcaseResultType.PartiallyCorrect] = "Partially Correct"; statusToString[TestcaseResultType.MemoryLimitExceeded] = "Memory Limit Exceeded"; statusToString[TestcaseResultType.TimeLimitExceeded] = "Time Limit Exceeded"; statusToString[TestcaseResultType.OutputLimitExceeded] = "Output Limit Exceeded"; statusToString[TestcaseResultType.RuntimeError] = "Runtime Error"; statusToString[TestcaseResultType.FileError] = "File Error"; statusToString[TestcaseResultType.JudgementFailed] = "Judgement Failed"; statusToString[TestcaseResultType.InvalidInteraction] = "Invalid Interaction"; const TaskStatus = {}; (function (TaskStatus) { TaskStatus[TaskStatus["Waiting"] = 0] = "Waiting"; TaskStatus[TaskStatus["Running"] = 1] = "Running"; TaskStatus[TaskStatus["Done"] = 2] = "Done"; TaskStatus[TaskStatus["Failed"] = 3] = "Failed"; TaskStatus[TaskStatus["Skipped"] = 4] = "Skipped"; })(TaskStatus); const vueApp = new Vue({ el: '#vueApp', data: { roughData: { info: <%- JSON.stringify(info) %>, result: <%- JSON.stringify(roughResult) %>, running: false, displayConfig: displayConfig }, code: <%- JSON.stringify(code) %>, detailResult: <%- JSON.stringify(detailResult) %>, displayConfig: displayConfig, }, computed: { singleSubtask() { return this.detailResult.judge.subtasks.length === 1; }, showRejudge() { return this.displayConfig.showRejudge && (!this.roughData.running); } }, methods: { getStatusString(statusCode) { return statusToString[statusCode]; }, firstNonAC(t) { if (t.every(v => v === TestcaseResultType.Accepted)) { return TestcaseResultType.Accepted; } else { return t.find(r => r !== TestcaseResultType.Accepted); } }, getSubtaskResult(t) { if (t.cases.some(c => c.status === TaskStatus.Running)) { return "Running"; } else if (t.cases.some(c => c.status === TaskStatus.Waiting)) { return "Waiting"; } else if (t.cases.every(c => c.status === TaskStatus.Done || c.status === TaskStatus.Skipped)) { return this.getStatusString(this.firstNonAC(t.cases.filter(c => c.result).map(c => c.result.type))); } else { return "System Error"; } }, getTestcaseStatus(c) { if (c.status === TaskStatus.Done) { return this.getStatusString(c.result.type); } else if (c.status === TaskStatus.Waiting) { return "Waiting"; } else if (c.status === TaskStatus.Running) { return "Running"; } else if (c.status === TaskStatus.Skipped) { return "Skipped"; } else { return "System Error"; } }, checkTestcaseOK(c) { return c.status === TaskStatus.Done; } }, mounted() { $(document).ready(() => $('.ui.accordion').accordion()); }, updated() { $('.ui.accordion').accordion("refresh"); } }); if (token != null) { const loadSocketIO = function () { let currentVersion = 0; const socket = io(socketUrl); socket.on('connect', () => { socket.on('start', () => { vueApp.roughData.running = true; console.log("Judge start!"); vueApp.detailResult = {}; }); socket.on('update', (p) => { console.log("Delta: " + JSON.stringify(p)); if (p.from === currentVersion) { currentVersion = p.to; jsondiffpatch.patch(vueApp.detailResult, p.delta); } else { // Some packets are dropped. Let's reset. socket.close(); setTimeout(loadSocketIO, 0); } }); socket.on('finish', (p) => { console.log("Judge finished"); vueApp.roughData.running = false; vueApp.roughData.result = p.roughResult; vueApp.detailResult = p.result; socket.close(); }); socket.emit('join', token, (data) => { console.log("join! " + JSON.stringify(data)); if (data && data.ok) { if (data.finished) { vueApp.roughData.result = data.roughResult; vueApp.detailResult = data.result || { systemMessage: "系统出错,请刷新后重试。" }; socket.close(); } else { if (data.running) { vueApp.roughData.running = true; vueApp.detailResult = data.current.content; currentVersion = data.current.version; } } } else { alert("ERROR: " + JSON.stringify(data)); } }); }); }; loadSocketIO(); } </script> </span> <% include footer %>