Browse Source

Add auto refresh for judge state and judge detail

master
Menci 8 years ago
parent
commit
f19c515831
  1. 40
      modules/judge.js
  2. 23
      views/header.ejs
  3. 99
      views/judge_detail.ejs
  4. 119
      views/judge_detail_item.ejs
  5. 24
      views/judge_state.ejs
  6. 36
      views/judge_state_item.ejs
  7. 31
      views/util.ejs

40
modules/judge.js

@ -51,6 +51,25 @@ app.get('/judge_state', async (req, res) => {
}
});
app.get('/judge_state/:id/ajax', async (req, res) => {
try {
let judge_state = await JudgeState.fromID(req.params.id);
if (!judge_state) throw 'No such judge state';
judge_state.hidden = !(await judge_state.isAllowedSeeResultBy(res.locals.user));
judge_state.allowedSeeCode = await judge_state.isAllowedSeeCodeBy(res.locals.user);
res.render('judge_state_item', {
judge: judge_state
});
} catch (e) {
syzoj.log(e);
res.render('error', {
err: e
});
}
});
app.get('/judge_detail/:id', async (req, res) => {
try {
let id = parseInt(req.params.id);
@ -71,3 +90,24 @@ app.get('/judge_detail/:id', async (req, res) => {
});
}
});
app.get('/judge_detail/:id/ajax', async (req, res) => {
try {
let id = parseInt(req.params.id);
let judge = await JudgeState.fromID(id);
judge.code = await syzoj.utils.highlight(judge.code, judge.language);
if (judge.result.compiler_output) judge.result.compiler_output = syzoj.utils.ansiToHTML(judge.result.compiler_output);
judge.allowedSeeResult = await judge.isAllowedSeeResultBy(res.locals.user);
judge.allowedSeeCode = await judge.isAllowedSeeCodeBy(res.locals.user);
res.render('judge_detail_item', {
judge: judge
});
} catch (e) {
syzoj.log(e);
res.render('error', {
err: e
});
}
});

23
views/header.ejs

@ -1,25 +1,4 @@
<%
this.getStatusMeta = (status) => {
if (status.startsWith('Running')) return 'Running';
else return status;
}
this.icon = {
'Accepted': 'checkmark',
'Wrong Answer': 'remove',
'Runtime Error': 'bomb',
'Time Limit Exceeded': 'clock',
'Memory Limit Exceeded': 'disk outline',
'Output Limit Exceeded': 'print',
'File Error': 'file outline',
'Waiting': 'hourglass half',
'Running': 'spinner',
'Compiling': 'spinner',
'Compile Error': 'code',
'System Error': 'server',
'No Testdata': 'folder open outline'
}
%>
<% include util %>
<!DOCTYPE html>
<html>
<head>

99
views/judge_detail.ejs

@ -1,101 +1,4 @@
<% this.title = '评测详细信息' %>
<% include header %>
<div class="padding">
<table class="ui very basic center aligned table">
<thead>
<tr>
<th>编号</th>
<th>题目名称</th>
<th>状态</th>
<th>分数</th>
<th>总时间</th>
<th>内存</th>
<th>提交者</th>
<th>提交时间</th>
</tr>
</thead>
<tbody>
<tr>
<td>#<%= judge.id %></td>
<td><a href="<%= syzoj.utils.makeUrl(['problem', judge.problem_id]) %>">#<%= judge.problem_id %>. <%= judge.problem.title %></a></td>
<% if (judge.allowedSeeResult) { %>
<td class="status <%= getStatusMeta(judge.result.status).toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(judge.status)] || 'remove' %> icon"></i>
<%= judge.result.status %>
</td>
<td class="score score_<%= parseInt(judge.result.score / 10) || 0 %>"><%= judge.result.score %></td>
<td><%= judge.result.total_time %> ms</td>
<td><%= judge.result.max_memory %> KiB</td>
<% } else { %>
<td>隐藏</td>
<td>隐藏</td>
<td>隐藏</td>
<td>隐藏</td>
<% } %>
<td><a href="<%= syzoj.utils.makeUrl(['user', judge.user_id]) %>"><%= judge.user.username %></a><% if (judge.user.nameplate) { %><%- judge.user.nameplate %><% } %></td>
<td><%= syzoj.utils.formatDate(judge.submit_time) %></td>
</tr>
</tbody>
</table>
<% if (judge.allowedSeeCode) { %>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%- judge.code %></code></pre></div>
<% } %>
<% if (judge.result.compiler_output && judge.result.status === 'Compile Error' && judge.allowedSeeCode) { %>
<h3 class="ui header">编译信息</h3>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%- judge.result.compiler_output %></code></pre></div>
<% } else if (judge.allowedSeeResult) { %>
<div class="ui styled fluid accordion">
<% for (let i = 0; i < judge.result.case_num; i++) { %>
<%
let testcase = judge.result[i], pending = false;
if (!testcase) {
pending = true;
if (i == 0 || judge.result[i - 1]) {
testcase = {
status: 'Running'
};
} else {
testcase = {
status: 'Waiting'
};
}
}
%>
<div class="title<% if (pending) { %> pending<% } %>"<% if (pending) { %> style="cursor: auto; "<% } %>>
<div class="ui grid">
<div class="three wide column"><i class="dropdown icon"></i>测试点 #<%= i + 1 %></div>
<div class="four wide column status status_detail <%= getStatusMeta(testcase.status).toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(testcase.status)] || 'remove' %> icon"></i>
<%= testcase.status %></div>
<% if (!pending) { %>
<div class="four wide column">用时:<span style="font-weight: normal; "><%= testcase.time_used %> ms</span></div>
<div class="four wide column">内存:<span style="font-weight: normal; "><%= testcase.memory_used %> KiB</span></div>
<% } %>
</div>
</div>
<% if (!pending) { %>
<div class="content">
<p>
<strong>输入文件</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.input %></code></pre></div>
<strong>期望输出</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.answer %></code></pre></div>
<strong>你的输出</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.user_out %></code></pre></div>
</p>
</div>
<% } %>
<% } %>
</div>
<% } %>
<script>
$(function() {
$('.ui.accordion').accordion({
selector: {
trigger: '.title:not(.pending)'
}
});
});
</script>
<span id="judge_detail_item"><% include judge_detail_item %></span>
<% include footer %>

119
views/judge_detail_item.ejs

@ -0,0 +1,119 @@
<div class="padding">
<table class="ui very basic center aligned table">
<thead>
<tr>
<th>编号</th>
<th>题目名称</th>
<th>状态</th>
<th>分数</th>
<th>总时间</th>
<th>内存</th>
<th>提交者</th>
<th>提交时间</th>
</tr>
</thead>
<tbody>
<tr>
<td>#<%= judge.id %></td>
<td><a href="<%= syzoj.utils.makeUrl(['problem', judge.problem_id]) %>">#<%= judge.problem_id %>. <%= judge.problem.title %></a></td>
<% if (judge.allowedSeeResult) { %>
<td class="status <%= getStatusMeta(judge.result.status).toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(judge.status)] || 'remove' %> icon"></i>
<%= judge.result.status %>
</td>
<td class="score score_<%= parseInt(judge.result.score / 10) || 0 %>"><%= judge.result.score %></td>
<td><%= judge.result.total_time %> ms</td>
<td><%= judge.result.max_memory %> KiB</td>
<% } else { %>
<td>隐藏</td>
<td>隐藏</td>
<td>隐藏</td>
<td>隐藏</td>
<% } %>
<td><a href="<%= syzoj.utils.makeUrl(['user', judge.user_id]) %>"><%= judge.user.username %></a><% if (judge.user.nameplate) { %><%- judge.user.nameplate %><% } %></td>
<td><%= syzoj.utils.formatDate(judge.submit_time) %></td>
</tr>
</tbody>
</table>
<% if (judge.allowedSeeCode) { %>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%- judge.code %></code></pre></div>
<% } %>
<% if (judge.result.compiler_output && judge.result.status === 'Compile Error' && judge.allowedSeeCode) { %>
<h3 class="ui header">编译信息</h3>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%- judge.result.compiler_output %></code></pre></div>
<% } else if (judge.allowedSeeResult) { %>
<div class="ui styled fluid accordion">
<% for (let i = 0; i < judge.result.case_num; i++) { %>
<%
let testcase = judge.result[i], pending = false;
if (!testcase) {
pending = true;
if (i == 0 || judge.result[i - 1]) {
testcase = {
status: 'Running'
};
} else {
testcase = {
status: 'Waiting'
};
}
}
%>
<div class="title<% if (pending) { %> pending<% } %>"<% if (pending) { %> style="cursor: auto; "<% } %>>
<div class="ui grid">
<div class="three wide column"><i class="dropdown icon"></i>测试点 #<%= i + 1 %></div>
<div class="four wide column status status_detail <%= getStatusMeta(testcase.status).toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(testcase.status)] || 'remove' %> icon"></i>
<%= testcase.status %></div>
<% if (!pending) { %>
<div class="four wide column">用时:<span style="font-weight: normal; "><%= testcase.time_used %> ms</span></div>
<div class="four wide column">内存:<span style="font-weight: normal; "><%= testcase.memory_used %> KiB</span></div>
<% } %>
</div>
</div>
<% if (!pending) { %>
<div class="content">
<p>
<strong>输入文件</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.input %></code></pre></div>
<strong>期望输出</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.answer %></code></pre></div>
<strong>你的输出</strong>
<div class="ui existing segment"><pre style="margin-top: 0; margin-bottom: 0; "><code><%= testcase.user_out %></code></pre></div>
</p>
</div>
<% } %>
<% } %>
</div>
<% } %>
</div>
<script>
$(function() {
$('.ui.accordion').accordion({
selector: {
trigger: '.title:not(.pending)'
}
});
});
</script>
<% if (isPending(judge.status)) { %>
<script>
function get_status_from_html(html) {
var x = $.parseHTML(html);
return $(x).find('td.status').text().trim();
}
function update_judge_detail() {
setTimeout(function () {
$.get('/judge_detail/<%= judge.id %>/ajax', function (data) {
var e = $('#judge_detail_item');
if (e.find('td.status').text().trim() != get_status_from_html(data)) e.html(data);
else update_judge_detail();
});
}, 500);
}
update_judge_detail();
</script>
<% } %>

24
views/judge_state.ejs

@ -31,29 +31,7 @@
</thead>
<tbody>
<% for (let judge of judge_state) { %>
<tr>
<td><a href="<%= syzoj.utils.makeUrl(['judge_detail', judge.id]) %>">#<%= judge.id %></a></td>
<td><a href="<%= syzoj.utils.makeUrl(['problem', judge.problem_id]) %>">#<%= judge.problem_id %>. <%= judge.problem.title %></a></td>
<% if (!judge.hidden) { %>
<td><a href="<%= syzoj.utils.makeUrl(['judge_detail', judge.id]) %>">
<span class="status <%= getStatusMeta(judge.status).toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(judge.status)] || 'remove' %> icon"></i>
<%= judge.status %>
</span>
</a></td>
<td><a href="<%= syzoj.utils.makeUrl(['judge_detail', judge.id]) %>"><span class="score score_<%= parseInt(judge.result.score / 10) || 0 %>"><%= judge.result.score %></span></a></td>
<td><%= judge.result.total_time %> ms</td>
<td><%= judge.result.max_memory %> KiB</td>
<% } else { %>
<td>隐藏</td>
<td>隐藏</td>
<td>隐藏</td>
<td>隐藏</td>
<% } %>
<td><a href="<%= syzoj.utils.makeUrl(['user', judge.user_id]) %>"><%= judge.user.username %></a><% if (judge.user.nameplate) { %><%- judge.user.nameplate %><% } %></td>
<td><%= syzoj.utils.formatDate(judge.submit_time) %></td>
<td><a href="<%= syzoj.utils.makeUrl(['judge_detail', judge.id]) %>"><i style="color: #000;" class="code icon"></i></a></td>
</tr>
<tr id="judge_state_<%= judge.id %>"><% include judge_state_item %></tr>
<% } %>
</tbody>
</table>

36
views/judge_state_item.ejs

@ -0,0 +1,36 @@
<% include util %>
<td><a href="<%= syzoj.utils.makeUrl(['judge_detail', judge.id]) %>">#<%= judge.id %></a></td>
<td><a href="<%= syzoj.utils.makeUrl(['problem', judge.problem_id]) %>">#<%= judge.problem_id %>. <%= judge.problem.title %></a></td>
<% if (!judge.hidden) { %>
<td><a href="<%= syzoj.utils.makeUrl(['judge_detail', judge.id]) %>">
<span class="status <%= getStatusMeta(judge.status).toLowerCase().split(' ').join('_') %>">
<i class="<%= icon[getStatusMeta(judge.status)] || 'remove' %> icon"></i>
<%= judge.status %>
</span>
</a></td>
<td><a href="<%= syzoj.utils.makeUrl(['judge_detail', judge.id]) %>"><span class="score score_<%= parseInt(judge.result.score / 10) || 0 %>"><%= judge.result.score %></span></a></td>
<td><%= judge.result.total_time %> ms</td>
<td><%= judge.result.max_memory %> KiB</td>
<% } else { %>
<td>隐藏</td>
<td>隐藏</td>
<td>隐藏</td>
<td>隐藏</td>
<% } %>
<td><a href="<%= syzoj.utils.makeUrl(['user', judge.user_id]) %>"><%= judge.user.username %></a><% if (judge.user.nameplate) { %><%- judge.user.nameplate %><% } %></td>
<td><%= syzoj.utils.formatDate(judge.submit_time) %></td>
<td><a href="<%= syzoj.utils.makeUrl(['judge_detail', judge.id]) %>"><i style="color: #000;" class="code icon"></i></a></td>
<% if (isPending(judge.status)) { %>
<script>
function update_judge_<%= judge.id %>() {
setTimeout(function () {
$.get('/judge_state/<%= judge.id %>/ajax', function (data) {
var e = $('#judge_state_<%= judge.id %>');
if (e.html() != data) e.html(data);
else update_judge_<%= judge.id %>();
});
}, 500);
}
update_judge_<%= judge.id %>();
</script>
<% } %>

31
views/util.ejs

@ -0,0 +1,31 @@
<%
this.getStatusMeta = (status) => {
if (status.startsWith('Running')) return 'Running';
else return status;
}
this.isPending = (status) => {
let pending = [
'Waiting',
'Compiling',
'Running'
];
return pending.includes(this.getStatusMeta(status));
}
this.icon = {
'Accepted': 'checkmark',
'Wrong Answer': 'remove',
'Runtime Error': 'bomb',
'Time Limit Exceeded': 'clock',
'Memory Limit Exceeded': 'disk outline',
'Output Limit Exceeded': 'print',
'File Error': 'file outline',
'Waiting': 'hourglass half',
'Running': 'spinner',
'Compiling': 'spinner',
'Compile Error': 'code',
'System Error': 'server',
'No Testdata': 'folder open outline'
}
%>
Loading…
Cancel
Save