Browse Source

Some UI fixes and improvement

pull/6/head
Menci 6 years ago
parent
commit
488b2d6535
  1. 5
      libs/judger.js
  2. 5
      libs/submissions_process.js
  3. 10
      modules/socketio.js
  4. 7
      modules/submission.js
  5. 1
      modules/user.js
  6. 2
      package.json
  7. 10
      utility.js
  8. 12
      views/status_label.ejs
  9. 18
      views/submission.ejs
  10. 43
      views/submissions_item.ejs

5
libs/judger.js

@ -48,6 +48,11 @@ async function connect () {
judge_state.result = convertedResult.result;
await judge_state.save();
await judge_state.updateRelatedInfo();
} else if(data.type === interface.ProgressReportType.Progress) {
if(!judge_state) return;
judge_state.score = convertedResult.score;
judge_state.total_time = convertedResult.time;
judge_state.max_memory = convertedResult.memory;
} else if(data.type == interface.ProgressReportType.Compiled) {
if(!judge_state) return;
judge_state.compilation = data.progress;

5
libs/submissions_process.js

@ -6,7 +6,7 @@ const getSubmissionInfo = (s, displayConfig) => ({
problemName: s.problem.title,
problemId: s.problem_id,
language: displayConfig.showCode ? ((s.language != null && s.language !== '') ? syzoj.languages[s.language].show : null) : null,
codeSize: displayConfig.showCode ? syzoj.utils.formatSize(s.code_length) : null,
codeSize: displayConfig.showCode ? s.code_length : null,
submitTime: syzoj.utils.formatDate(s.submit_time),
});
@ -18,8 +18,7 @@ const getRoughResult = (x, displayConfig) => {
return {
result: x.status,
time: displayConfig.showUsage ? x.total_time : null,
memory: displayConfig.showUsage ? syzoj.utils.formatSize((x.max_memory * 1024) || 0, 2) : null,
precise_memory: displayConfig.showUsage ? x.max_memory : null,
memory: displayConfig.showUsage ? x.max_memory : null,
score: displayConfig.showScore ? x.score : null
};
}

10
modules/socketio.js

@ -232,6 +232,13 @@ exports.updateCompileStatus = updateCompileStatus;
function updateProgress(taskId, data) {
winston.verbose(`Updating progress for #${taskId}`);
currentJudgeList[taskId] = data;
const finalResult = judgeResult.convertResult(taskId, data);
const roughResult = {
result: "Running",
time: finalResult.time,
memory: finalResult.memory,
score: finalResult.score
};
forAllClients(detailProgressNamespace, taskId, (client) => {
winston.debug(`Pushing progress update to ${client}`);
if (clientDetailProgressList[client] && clientDisplayConfigList[client]) {
@ -242,7 +249,8 @@ function updateProgress(taskId, data) {
taskId: taskId,
from: version,
to: version + 1,
delta: diff.diff(original, updated)
delta: diff.diff(original, updated),
roughResult: roughResult
});
clientDetailProgressList[client].version++;
}

7
modules/submission.js

@ -97,7 +97,10 @@ app.get('/submissions', async (req, res) => {
let paginate = syzoj.utils.paginate(await JudgeState.count(where), req.query.page, syzoj.config.page.judge_state);
let judge_state = await JudgeState.query(paginate, where, [['id', 'desc']], true);
await judge_state.forEachAsync(async obj => obj.loadRelationships());
await judge_state.forEachAsync(async obj => {
await obj.loadRelationships();
obj.code_length = obj.code.length;
})
res.render('submissions', {
// judge_state: judge_state,
@ -147,7 +150,7 @@ app.get('/submission/:id', async (req, res) => {
await judge.loadRelationships();
if (judge.problem.type !== 'submit-answer') {
judge.codeLength = judge.code.length;
judge.code_length = judge.code.length;
let key = syzoj.utils.getFormattedCodeKey(judge.code, judge.language);
if (key) {

1
modules/user.js

@ -187,7 +187,6 @@ app.post('/user/:id/edit', async (req, res) => {
user.information = req.body.information;
user.sex = req.body.sex;
user.public_email = (req.body.public_email === 'on');
console.log(req.body);
user.prefer_formatted_code = (req.body.prefer_formatted_code === 'on');
await user.save();

2
package.json

@ -40,7 +40,7 @@
"gravatar": "^1.8.0",
"javascript-time-ago": "^1.0.30",
"js-yaml": "^3.9.0",
"jsondiffpatch": "0.3.11",
"jsondiffpatch": "0.2.5",
"jsonwebtoken": "^8.4.0",
"katex": "^0.10.0",
"mathjax-node": "^2.1.1",

10
utility.js

@ -92,11 +92,11 @@ module.exports = {
return sgn + util.format('%s:%s:%s', toStringWithPad(x / 3600), toStringWithPad(x / 60 % 60), toStringWithPad(x % 60));
},
formatSize(x, precision) {
let res = filesize(x, { fixed: precision || 1 }).calculate();
if (res.result === parseInt(res.result)) res.fixed = res.result.toString();
if (res.suffix.startsWith('Byte')) res.suffix = 'B';
else res.suffix = res.suffix.replace('iB', '');
return res.fixed + ' ' + res.suffix;
if (typeof x !== 'number') return '0 B';
let unit = 'B', units = ['K', 'M', 'G', 'T'];
for (let i in units) if (x > 1024) x /= 1024, unit = units[i];
var fixed = x === Math.round(x) ? x.toString() : x.toFixed(precision);
return fixed + ' ' + unit;
},
getFormattedCodeKey(code, lang) {
if (syzoj.languages[lang].format) {

12
views/status_label.ejs

@ -10,6 +10,7 @@ const iconList = {
'File Error': 'file outline',
'Waiting': 'hourglass half',
'Running': 'spinner',
'Compiling': 'spinner',
'Compile Error': 'code',
'Submitted': 'checkmark', // NOI contests
'System Error': 'server',
@ -31,10 +32,6 @@ Vue.component('status-label', {
},
colorClass() {
return (this.indetail ? 'status_detail ' : '') + this.status.toLowerCase().split(' ').join('_');
},
outputStatus() {
if (this.status === 'Running' && this.progress) return 'Running ' + this.progress.finished + '/' + this.progress.total;
else return this.status;
}
}
})
@ -42,6 +39,11 @@ Vue.component('status-label', {
<script type="text/x-template" id="statusIconTemplate">
<span class="status" :class="colorClass">
<i class="icon" :class="icon"></i>
{{ outputStatus }}
<template v-if="['Running', 'Waiting'].includes(status) && progress">
<span style="display: inline-block; width: 58px; ">{{ status }}</span>{{ progress.finished }}/{{ progress.total }}
</template>
<template v-else>
{{ status }}
</template>
</span>
</script>

18
views/submission.ejs

@ -47,7 +47,7 @@
</tr>
</thead>
<tbody>
<tr is="submission-item" v-bind:data="roughData" :config="displayConfig" :show-rejudge="showRejudge" :progress="getProgress()"></tr>
<tr is="submission-item" v-bind:data="roughData" :config="displayConfig" :show-rejudge="showRejudge" :progress="getProgress()" :compiling="detailResult && !detailResult.compile"></tr>
</tbody>
</table>
@ -66,7 +66,7 @@
<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" :class="singleSubtask ? 'single-subtask' : '' "v-if="detailResult && detailResult.judge && detailResult.judge.subtasks">
<div class="ui styled fluid accordion" :class="singleSubtask ? 'single-subtask' : '' " 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">
@ -125,7 +125,7 @@
</div>
</div>
<script src="https://cdnjs.loli.net/ajax/libs/vue/2.5.17/vue.min.js"></script>
<script src="https://cdnjs.loli.net/ajax/libs/socket.io/2.1.1/socket.io.js"></script>
<script src="https://cdnjs.loli.net/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
<script src="https://cdnjs.loli.net/ajax/libs/jsondiffpatch/0.2.5/jsondiffpatch.min.js"></script>
<% include submissions_item %>
@ -308,10 +308,12 @@ if (token != null) {
vueApp.detailResult = {};
});
socket.on('update', function (p) {
console.log("Delta: " + JSON.stringify(p));
console.log("Delta: ", p);
if (p.from === currentVersion) {
currentVersion = p.to;
jsondiffpatch.patch(vueApp.detailResult, p.delta);
vueApp.detailResult = JSON.parse(JSON.stringify(vueApp.detailResult));// WTF?
vueApp.roughData.result = p.roughResult;
} else { // Some packets are dropped. Let's reset.
socket.close();
setTimeout(loadSocketIO, 0);
@ -325,18 +327,18 @@ if (token != null) {
socket.close();
});
socket.emit('join', token, function (data) {
console.log("join! " + JSON.stringify(data));
console.log("join! ", data);
if (data && data.ok) {
if (data.finished) {
vueApp.roughData.result = data.roughResult;
vueApp.detailResult = data.result || {
systemMessage: "系统出错,请刷新后重试。"
};
if (!data.result) location.reload(true);
vueApp.detailResult = data.result;
socket.close();
} else {
if (data.running) {
vueApp.roughData.running = true;
vueApp.detailResult = data.current.content;
vueApp.roughData.result = data.roughResult;
currentVersion = data.current.version;
}
}

43
views/submissions_item.ejs

@ -1,37 +1,46 @@
<% include util %>
<% include status_label %>
<script src="https://cdnjs.loli.net/ajax/libs/textfit/2.3.1/textFit.min.js"></script>
<script>
function formatSize(x, precision) {
if (typeof x !== 'number') return '0 B';
var unit = 'B', units = ['K', 'M', 'G', 'T'];
for (var i in units) if (x > 1024) x /= 1024, unit = units[i];
var fixed = x === Math.round(x) ? x.toString() : x.toFixed(precision);
return fixed + ' ' + unit;
}
const submissionUrl = <%- JSON.stringify(displayConfig.inContest ?
syzoj.utils.makeUrl(['contest', 'submission', 'VanDarkholme']) :
syzoj.utils.makeUrl(['submission', 'VanDarkholme'])) %>;
syzoj.utils.makeUrl(['contest', 'submission', '20000528']) :
syzoj.utils.makeUrl(['submission', '20000528'])) %>;
const problemUrl = <%- JSON.stringify(displayConfig.inContest ?
syzoj.utils.makeUrl(['contest', contest.id, 'problem', 'VanDarkholme']) :
syzoj.utils.makeUrl(['problem', 'VanDarkholme'])) %>;
const userUrl = <%- JSON.stringify(syzoj.utils.makeUrl(['user', 'VanDarkholme'])) %>;
syzoj.utils.makeUrl(['contest', contest.id, 'problem', '20000528']) :
syzoj.utils.makeUrl(['problem', '20000528'])) %>;
const userUrl = <%- JSON.stringify(syzoj.utils.makeUrl(['user', '20000528'])) %>;
Vue.component('submission-item', {
template: '#submissionItemTemplate',
props: ['data', 'config', 'showRejudge', 'progress'],
props: ['data', 'config', 'showRejudge', 'progress', 'compiling'],
computed: {
statusString() {
if (this.compiling) return 'Compiling';
const data = this.data;
if (data.result) {
return data.result.result;
} else if (data.running) {
return this.config.showResult ? 'Running' : 'Compiling';
return 'Running';
} else return 'Waiting';
},
submissionLink() {
return submissionUrl.replace('VanDarkholme', this.data.info.submissionId);
return submissionUrl.replace('20000528', this.data.info.submissionId);
},
problemLink() {
return problemUrl.replace('VanDarkholme', this.data.info.problemId);
return problemUrl.replace('20000528', this.data.info.problemId);
},
userLink() {
return userUrl.replace('VanDarkholme', this.data.info.userId);
return userUrl.replace('20000528', this.data.info.userId);
},
scoreClass() {
return "score_" + (parseInt(this.data.result.score / 10) || 0).toString();
@ -71,13 +80,15 @@ Vue.component('submission-item', {
<td v-if="config.showUsage">{{ (data.result.time || 0).toString() + ' ms' }}</td>
<% if (active === 'submissions') { %>
<td v-if="config.showUsage">{{ data.result.memory }}</td>
<td v-if="config.showUsage">{{ formatSize(data.result.memory * 1024, 2) }}</td>
<% } else { %>
<td v-if="config.showUsage">{{ (data.result.precise_memory || 0).toString() + ' K'}}</td>
<td v-if="config.showUsage">{{ (data.result.memory || 0).toString() + ' K'}}</td>
<% } %>
</template> <template v-else>
<td v-if="config.showScore"/> <td v-if="config.showUsage"/> <td v-if="config.showUsage"/>
<td v-if="config.showScore"><a :href="submissionLink"><span class="score score_0">0</span></a></td>
<td v-if="config.showUsage">0 ms</td>
<td v-if="config.showUsage">0 B</td>
</template>
<td v-if="config.showCode">
@ -86,7 +97,7 @@ Vue.component('submission-item', {
<% } else { %>
<span v-if="data.info.language"><b>{{ data.info.language }}</b> / </span>
<% } %>
{{ data.info.codeSize }}
{{ formatSize(data.info.codeSize, 1) }}
</td>
<td><a :href="userLink">{{ data.info.user }}</a></td>
<td>{{ data.info.submitTime }}</td>

Loading…
Cancel
Save