Browse Source

Implement judge status tracking

master
hewenyang 7 years ago
parent
commit
9eeb1fde5d
  1. 6
      app.js
  2. 32
      libs/judger.js
  3. 2
      libs/winston.js
  4. 298
      modules/socketio.js
  5. 324
      package-lock.json
  6. 2
      package.json
  7. 2
      views/submission.ejs

6
app.js

@ -39,12 +39,16 @@ global.syzoj = {
console.log(obj); console.log(obj);
}, },
async run() { async run() {
let winstonLib = require('./libs/winston');
winstonLib.configureWinston(true);
let Express = require('express'); let Express = require('express');
global.app = Express(); global.app = Express();
syzoj.production = app.get('env') === 'production'; syzoj.production = app.get('env') === 'production';
app.listen(parseInt(syzoj.config.port), syzoj.config.hostname, () => { app.server = require('http').createServer(app);
app.server.listen(parseInt(syzoj.config.port), syzoj.config.hostname, () => {
this.log(`SYZOJ is listening on ${syzoj.config.hostname}:${parseInt(syzoj.config.port)}...`); this.log(`SYZOJ is listening on ${syzoj.config.hostname}:${parseInt(syzoj.config.port)}...`);
}); });

32
libs/judger.js

@ -49,10 +49,12 @@ async function connect () {
judge_state.result = convertedResult.result; judge_state.result = convertedResult.result;
await judge_state.save(); await judge_state.save();
await judge_state.updateRelatedInfo(); await judge_state.updateRelatedInfo();
} else { } else if(data.type == interface.ProgressReportType.Compiled) {
if(!judge_state) return; if(!judge_state) return;
judge_state.compilation = data.progress; judge_state.compilation = data.progress;
await judge_state.save(); await judge_state.save();
} else {
winston.error("Unsupported result type: " + data.type);
} }
})(msg).then(async() => { })(msg).then(async() => {
amqpConsumeChannel.ack(msg) amqpConsumeChannel.ack(msg)
@ -61,6 +63,34 @@ async function connect () {
amqpConsumeChannel.nack(msg, false, false); amqpConsumeChannel.nack(msg, false, false);
}); });
}); });
socketio = require('../modules/socketio');
const progressChannel = await amqpConnection.createChannel();
const queueName = (await progressChannel.assertQueue('', { exclusive: true })).queue;
await progressChannel.bindQueue(queueName, 'progress', '');
await progressChannel.consume(queueName, (msg) => {
const data = msgPack.decode(msg.content);
winston.verbose(`Got result from progress exchange, id: ${data.taskId}`);
(async (result) => {
if (result.type === interface.ProgressReportType.Started) {
socketio.createTask(result.taskId);
} else if (result.type === interface.ProgressReportType.Compiled) {
socketio.updateCompileStatus(result.taskId, result.progress);
} else if (result.type === interface.ProgressReportType.Progress) {
socketio.updateProgress(result.taskId, result.progress);
} else if (result.type === interface.ProgressReportType.Finished) {
socketio.updateResult(result.taskId, result.progress);
} else if (result.type === interface.ProgressReportType.Reported) {
socketio.cleanupProgress(result.taskId);
}
})(data).then(async() => {
progressChannel.ack(msg)
}, async(err) => {
winston.error('Error handling progress', err);
progressChannel.nack(msg, false, false);
});
});
winston.debug('Created progress exchange queue', queueName);
amqpConnection.on('error', (err) => { amqpConnection.on('error', (err) => {
winston.error('RabbitMQ connection failure: ${err.toString()}'); winston.error('RabbitMQ connection failure: ${err.toString()}');
amqpConnection.close(); amqpConnection.close();

2
modules/winston.js → libs/winston.js

@ -20,4 +20,4 @@ function configureWinston(verbose) {
} }
} }
configureWinston(false); module.exports.configureWinston = configureWinston;

298
modules/socketio.js

@ -0,0 +1,298 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const socketio = require("socket.io");
const diff = require("jsondiffpatch");
const jwt = require("jsonwebtoken");
const winston = require("winston");
const judgeResult_1 = require("../libs/judgeResult");
const interfaces_1 = require("../libs/judger_interfaces");
let ioInstance;
let detailProgressNamespace;
let roughProgressNamespace;
let compileProgressNamespace;
const currentJudgeList = {};
const finishedJudgeList = {};
const compiledList = [];
const clientDetailProgressList = {};
const clientDisplayConfigList = {};
function processOverallResult(source, config) {
if (source == null)
return null;
if (source.error != null) {
return {
error: source.error,
systemMessage: source.systemMessage
};
}
return {
compile: source.compile,
judge: config.showDetailResult ? (source.judge && {
subtasks: source.judge.subtasks && source.judge.subtasks.map(st => ({
score: st.score,
cases: st.cases.map(cs => ({
status: cs.status,
result: cs.result && {
type: cs.result.type,
time: config.showUsage ? cs.result.time : undefined,
memory: config.showUsage ? cs.result.memory : undefined,
scoringRate: cs.result.scoringRate,
systemMessage: cs.result.systemMessage,
input: config.showTestdata ? cs.result.input : undefined,
output: config.showTestdata ? cs.result.output : undefined,
userOutput: config.showTestdata ? cs.result.userOutput : undefined,
userError: config.showTestdata ? cs.result.userError : undefined,
spjMessage: config.showTestdata ? cs.result.spjMessage : undefined,
}
}))
}))
}) : null
};
}
function getCompileStatus(status) {
if (["System Error", "Compile Error", "No Testdata"].includes(status)) {
return status;
}
else {
return "Submitted";
}
}
function processRoughResult(source, config) {
const result = config.showResult ?
source.result :
getCompileStatus(source.result);
return {
result: result,
time: config.showUsage ? source.time : null,
memory: config.showUsage ? source.memory : null,
score: config.showScore ? source.score : null
};
}
function forAllClients(ns, taskId, exec) {
ns.in(taskId.toString()).clients((err, clients) => {
if (!err) {
clients.forEach(client => {
exec(client);
});
}
else {
winston.warn(`Error while listing socketio clients in ${taskId}`, err);
}
});
}
function initializeSocketIO(s) {
ioInstance = socketio(s);
const initializeNamespace = (name, exec) => {
winston.debug('initializing socketIO', name);
const newNamespace = ioInstance.of('/' + name);
newNamespace.on('connection', (socket) => {
socket.on('disconnect', () => {
winston.info(`Client ${socket.id} disconnected.`);
delete clientDisplayConfigList[socket.id];
if (clientDetailProgressList[socket.id]) {
delete clientDetailProgressList[socket.id];
}
});
socket.on('join', (reqJwt, cb) => {
winston.info(`Client ${socket.id} connected.`);
let req;
try {
req = jwt.verify(reqJwt, syzoj.config.judge_token);
if (req.type !== name) {
throw new Error("Request type in token mismatch.");
}
clientDisplayConfigList[socket.id] = req.displayConfig;
const taskId = req.taskId;
winston.verbose(`A client trying to join ${name} namespace for ${taskId}.`);
socket.join(taskId.toString());
exec(req, socket).then(x => cb(x), err => cb({ ok: false, message: err.toString() }));
}
catch (err) {
winston.info('Error while joining.');
cb({
ok: false,
message: err.toString()
});
return;
}
});
});
return newNamespace;
};
detailProgressNamespace = initializeNamespace('detail', async (req, socket) => {
const taskId = req.taskId;
if (finishedJudgeList[taskId]) {
winston.debug(`Judge task #${taskId} has been finished, ${JSON.stringify(currentJudgeList[taskId])}`);
return {
ok: true,
running: false,
finished: true,
result: processOverallResult(currentJudgeList[taskId], clientDisplayConfigList[socket.id]),
roughResult: processRoughResult(finishedJudgeList[taskId], clientDisplayConfigList[socket.id])
};
}
else {
winston.debug(`Judge task #${taskId} has not been finished`);
if (currentJudgeList[taskId]) {
clientDetailProgressList[socket.id] = {
version: 0,
content: processOverallResult(currentJudgeList[taskId], clientDisplayConfigList[socket.id])
};
return {
ok: true,
finished: false,
running: true,
current: clientDetailProgressList[socket.id]
};
}
else {
return {
ok: true,
finished: false,
running: false
};
}
}
});
roughProgressNamespace = initializeNamespace('rough', async (req, socket) => {
const taskId = req.taskId;
if (finishedJudgeList[taskId]) {
return {
ok: true,
running: false,
finished: true,
result: processRoughResult(finishedJudgeList[taskId], clientDisplayConfigList[socket.id])
};
}
else if (currentJudgeList[taskId]) {
return {
ok: true,
running: true,
finished: false
};
}
else {
return {
ok: true,
running: false,
finished: false
};
}
});
compileProgressNamespace = initializeNamespace('compile', async (req, socket) => {
const taskId = req.taskId;
if (compiledList[taskId]) {
return {
ok: true,
running: false,
finished: true,
result: compiledList[taskId]
};
}
else if (currentJudgeList[taskId]) {
return {
ok: true,
running: true,
finished: false
};
}
else {
return {
ok: true,
running: false,
finished: false
};
}
});
}
exports.initializeSocketIO = initializeSocketIO;
function createTask(taskId) {
winston.debug(`Judge task #${taskId} has started`);
currentJudgeList[taskId] = {};
finishedJudgeList[taskId] = null;
forAllClients(detailProgressNamespace, taskId, (clientId) => {
clientDetailProgressList[clientId] = {
version: 0,
content: {}
};
});
roughProgressNamespace.to(taskId.toString()).emit("start", { taskId: taskId });
detailProgressNamespace.to(taskId.toString()).emit("start", { taskId: taskId });
compileProgressNamespace.to(taskId.toString()).emit("start", { taskId: taskId });
}
exports.createTask = createTask;
function updateCompileStatus(taskId, result) {
winston.debug(`Updating compilation status for #${taskId}`);
compiledList[taskId] = { result: result.status === interfaces_1.TaskStatus.Done ? 'Submitted' : 'Compile Error' };
compileProgressNamespace.to(taskId.toString()).emit('finish', {
taskId: taskId,
result: compiledList[taskId]
});
}
exports.updateCompileStatus = updateCompileStatus;
function updateProgress(taskId, data) {
winston.verbose(`Updating progress for #${taskId}`);
currentJudgeList[taskId] = data;
forAllClients(detailProgressNamespace, taskId, (client) => {
winston.debug(`Pushing progress update to ${client}`);
if (clientDetailProgressList[client] && clientDisplayConfigList[client]) {
const original = clientDetailProgressList[client].content;
const updated = processOverallResult(currentJudgeList[taskId], clientDisplayConfigList[client]);
const version = clientDetailProgressList[client].version;
detailProgressNamespace.sockets[client].emit('update', {
taskId: taskId,
from: version,
to: version + 1,
delta: diff.diff(original, updated)
});
clientDetailProgressList[client].version++;
}
});
}
exports.updateProgress = updateProgress;
function updateResult(taskId, data) {
currentJudgeList[taskId] = data;
if (compiledList[taskId] == null) {
if (data.error != null) {
compiledList[taskId] = { result: "System Error" };
compileProgressNamespace.to(taskId.toString()).emit('finish', {
taskId: taskId,
result: compiledList[taskId]
});
}
}
const finalResult = judgeResult_1.convertResult(taskId, data);
const roughResult = {
result: finalResult.statusString,
time: finalResult.time,
memory: finalResult.memory,
score: finalResult.score
};
finishedJudgeList[taskId] = roughResult;
forAllClients(roughProgressNamespace, taskId, (client) => {
winston.debug(`Pushing rough result to ${client}`);
roughProgressNamespace.sockets[client].emit('finish', {
taskId: taskId,
result: processRoughResult(finishedJudgeList[taskId], clientDisplayConfigList[client])
});
});
forAllClients(detailProgressNamespace, taskId, (client) => {
if (clientDisplayConfigList[client]) {
winston.debug(`Pushing detail result to ${client}`);
detailProgressNamespace.sockets[client].emit('finish', {
taskId: taskId,
result: processOverallResult(currentJudgeList[taskId], clientDisplayConfigList[client]),
roughResult: processRoughResult(finishedJudgeList[taskId], clientDisplayConfigList[client])
});
delete clientDetailProgressList[client];
}
});
}
exports.updateResult = updateResult;
function cleanupProgress(taskId) {
setTimeout(() => { delete currentJudgeList[taskId]; }, 10000);
}
exports.cleanupProgress = cleanupProgress;
//# sourceMappingURL=socketio.js.map
initializeSocketIO(app.server);

324
package-lock.json generated

@ -51,6 +51,11 @@
"resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz",
"integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=" "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y="
}, },
"after": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
"integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
},
"ajv": { "ajv": {
"version": "4.11.8", "version": "4.11.8",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
@ -106,6 +111,11 @@
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
}, },
"ansi-styles": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz",
"integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94="
},
"ansi-to-html": { "ansi-to-html": {
"version": "0.4.2", "version": "0.4.2",
"resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.4.2.tgz", "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.4.2.tgz",
@ -164,6 +174,11 @@
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz",
"integrity": "sha1-X8w3OSB3VyPP1k1lxkvvU7+eum0=" "integrity": "sha1-X8w3OSB3VyPP1k1lxkvvU7+eum0="
}, },
"arraybuffer.slice": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
"integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog=="
},
"asn1": { "asn1": {
"version": "0.2.3", "version": "0.2.3",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
@ -179,6 +194,11 @@
"resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz",
"integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k="
}, },
"async-limiter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
},
"async-lock": { "async-lock": {
"version": "0.3.10", "version": "0.3.10",
"resolved": "https://registry.npmjs.org/async-lock/-/async-lock-0.3.10.tgz", "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-0.3.10.tgz",
@ -202,6 +222,11 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4="
}, },
"backo2": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
},
"bagpipe": { "bagpipe": {
"version": "0.3.5", "version": "0.3.5",
"resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz", "resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz",
@ -212,11 +237,21 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
}, },
"base64-arraybuffer": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
"integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg="
},
"base64-js": { "base64-js": {
"version": "0.0.8", "version": "0.0.8",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
"integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=" "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg="
}, },
"base64id": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
"integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY="
},
"base64url": { "base64url": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz",
@ -231,6 +266,14 @@
"tweetnacl": "0.14.5" "tweetnacl": "0.14.5"
} }
}, },
"better-assert": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
"integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
"requires": {
"callsite": "1.0.0"
}
},
"bignumber.js": { "bignumber.js": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-3.1.2.tgz", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-3.1.2.tgz",
@ -252,6 +295,11 @@
"readable-stream": "2.3.3" "readable-stream": "2.3.3"
} }
}, },
"blob": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
"integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE="
},
"block-stream": { "block-stream": {
"version": "0.0.9", "version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@ -406,6 +454,11 @@
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz",
"integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=" "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk="
}, },
"callsite": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
"integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA="
},
"camelcase": { "camelcase": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
@ -430,6 +483,33 @@
"tunnel-agent": "0.4.3" "tunnel-agent": "0.4.3"
} }
}, },
"chalk": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz",
"integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=",
"requires": {
"ansi-styles": "1.1.0",
"escape-string-regexp": "1.0.5",
"has-ansi": "0.1.0",
"strip-ansi": "0.3.0",
"supports-color": "0.2.0"
},
"dependencies": {
"ansi-regex": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz",
"integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk="
},
"strip-ansi": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz",
"integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=",
"requires": {
"ansi-regex": "0.2.1"
}
}
}
},
"cheerio": { "cheerio": {
"version": "1.0.0-rc.2", "version": "1.0.0-rc.2",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz",
@ -494,6 +574,21 @@
"graceful-readlink": "1.0.1" "graceful-readlink": "1.0.1"
} }
}, },
"component-bind": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
"integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E="
},
"component-emitter": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
},
"component-inherit": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
"integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM="
},
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -958,6 +1053,70 @@
"once": "1.4.0" "once": "1.4.0"
} }
}, },
"engine.io": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.4.tgz",
"integrity": "sha1-PQIRtwpVLOhB/8fahiezAamkFi4=",
"requires": {
"accepts": "1.3.3",
"base64id": "1.0.0",
"cookie": "0.3.1",
"debug": "2.6.9",
"engine.io-parser": "2.1.2",
"uws": "0.14.5",
"ws": "3.3.3"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
}
}
},
"engine.io-client": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.4.tgz",
"integrity": "sha1-T88TcLRxY70s6b4nM5ckMDUNTqE=",
"requires": {
"component-emitter": "1.2.1",
"component-inherit": "0.0.3",
"debug": "2.6.9",
"engine.io-parser": "2.1.2",
"has-cors": "1.1.0",
"indexof": "0.0.1",
"parseqs": "0.0.5",
"parseuri": "0.0.5",
"ws": "3.3.3",
"xmlhttprequest-ssl": "1.5.5",
"yeast": "0.1.2"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
}
}
},
"engine.io-parser": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz",
"integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==",
"requires": {
"after": "0.8.2",
"arraybuffer.slice": "0.0.7",
"base64-arraybuffer": "0.1.5",
"blob": "0.0.4",
"has-binary2": "1.0.2"
}
},
"entities": { "entities": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
@ -1354,6 +1513,41 @@
"har-schema": "1.0.5" "har-schema": "1.0.5"
} }
}, },
"has-ansi": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz",
"integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=",
"requires": {
"ansi-regex": "0.2.1"
},
"dependencies": {
"ansi-regex": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz",
"integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk="
}
}
},
"has-binary2": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz",
"integrity": "sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=",
"requires": {
"isarray": "2.0.1"
},
"dependencies": {
"isarray": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
}
}
},
"has-cors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
"integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
},
"has-unicode": { "has-unicode": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
@ -1442,6 +1636,11 @@
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
}, },
"indexof": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
"integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
},
"inflection": { "inflection": {
"version": "1.12.0", "version": "1.12.0",
"resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz",
@ -1641,6 +1840,14 @@
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
}, },
"jsondiffpatch": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.2.4.tgz",
"integrity": "sha1-1LbFOz/H2htLkcHCrsi5MrdRHVw=",
"requires": {
"chalk": "0.5.1"
}
},
"jsonfile": { "jsonfile": {
"version": "2.4.0", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
@ -2191,6 +2398,11 @@
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
}, },
"object-component": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
"integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE="
},
"object-keys": { "object-keys": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
@ -2273,6 +2485,22 @@
"@types/node": "6.0.83" "@types/node": "6.0.83"
} }
}, },
"parseqs": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
"integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
"requires": {
"better-assert": "1.0.2"
}
},
"parseuri": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
"integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
"requires": {
"better-assert": "1.0.2"
}
},
"parseurl": { "parseurl": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz",
@ -2864,6 +3092,61 @@
"hoek": "2.16.3" "hoek": "2.16.3"
} }
}, },
"socket.io": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz",
"integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=",
"requires": {
"debug": "2.6.7",
"engine.io": "3.1.4",
"socket.io-adapter": "1.1.1",
"socket.io-client": "2.0.4",
"socket.io-parser": "3.1.2"
}
},
"socket.io-adapter": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz",
"integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs="
},
"socket.io-client": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz",
"integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=",
"requires": {
"backo2": "1.0.2",
"base64-arraybuffer": "0.1.5",
"component-bind": "1.0.0",
"component-emitter": "1.2.1",
"debug": "2.6.7",
"engine.io-client": "3.1.4",
"has-cors": "1.1.0",
"indexof": "0.0.1",
"object-component": "0.0.3",
"parseqs": "0.0.5",
"parseuri": "0.0.5",
"socket.io-parser": "3.1.2",
"to-array": "0.1.4"
}
},
"socket.io-parser": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.2.tgz",
"integrity": "sha1-28IoIVH8T6675Aru3Ady66YZ9/I=",
"requires": {
"component-emitter": "1.2.1",
"debug": "2.6.7",
"has-binary2": "1.0.2",
"isarray": "2.0.1"
},
"dependencies": {
"isarray": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
}
}
},
"source-map": { "source-map": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
@ -3023,6 +3306,11 @@
"escape-string-regexp": "1.0.5" "escape-string-regexp": "1.0.5"
} }
}, },
"supports-color": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz",
"integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo="
},
"symbol-tree": { "symbol-tree": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
@ -3167,6 +3455,11 @@
"tmp": "0.0.31" "tmp": "0.0.31"
} }
}, },
"to-array": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
"integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA="
},
"topo": { "topo": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz",
@ -3257,6 +3550,11 @@
"random-bytes": "1.0.0" "random-bytes": "1.0.0"
} }
}, },
"ultron": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
"integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
},
"unbzip2-stream": { "unbzip2-stream": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.4.tgz", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.4.tgz",
@ -3304,6 +3602,12 @@
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
"integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g=="
}, },
"uws": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/uws/-/uws-0.14.5.tgz",
"integrity": "sha1-Z6rzPEaypYel9mZtAPdpEyjxSdw=",
"optional": true
},
"validate-npm-package-license": { "validate-npm-package-license": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
@ -3467,6 +3771,16 @@
"slide": "1.1.6" "slide": "1.1.6"
} }
}, },
"ws": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
"integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
"requires": {
"async-limiter": "1.0.0",
"safe-buffer": "5.1.1",
"ultron": "1.1.1"
}
},
"xml-mapping": { "xml-mapping": {
"version": "1.7.1", "version": "1.7.1",
"resolved": "https://registry.npmjs.org/xml-mapping/-/xml-mapping-1.7.1.tgz", "resolved": "https://registry.npmjs.org/xml-mapping/-/xml-mapping-1.7.1.tgz",
@ -3498,6 +3812,11 @@
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz",
"integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk="
}, },
"xmlhttprequest-ssl": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
"integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4="
},
"xpath": { "xpath": {
"version": "0.0.24", "version": "0.0.24",
"resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.24.tgz", "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.24.tgz",
@ -3575,6 +3894,11 @@
"buffer-crc32": "0.2.13", "buffer-crc32": "0.2.13",
"fd-slicer": "1.0.1" "fd-slicer": "1.0.1"
} }
},
"yeast": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
"integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
} }
} }
} }

2
package.json

@ -40,6 +40,7 @@
"fs-extra": "^4.0.1", "fs-extra": "^4.0.1",
"gravatar": "^1.5.2", "gravatar": "^1.5.2",
"js-yaml": "^3.9.0", "js-yaml": "^3.9.0",
"jsondiffpatch": "0.2.4",
"jsonwebtoken": "^7.4.3", "jsonwebtoken": "^7.4.3",
"moemark-renderer": "^1.2.6", "moemark-renderer": "^1.2.6",
"moment": "^2.15.0", "moment": "^2.15.0",
@ -55,6 +56,7 @@
"sendmail": "^1.1.1", "sendmail": "^1.1.1",
"sequelize": "^3.24.3", "sequelize": "^3.24.3",
"session-file-store": "^1.0.0", "session-file-store": "^1.0.0",
"socket.io": "^2.0.3",
"sqlite3": "^3.1.4", "sqlite3": "^3.1.4",
"syzoj-divine": "^1.0.2", "syzoj-divine": "^1.0.2",
"tmp-promise": "^1.0.3", "tmp-promise": "^1.0.3",

2
views/submission.ejs

@ -108,7 +108,7 @@ Vue.component("code-box", {
template: "#codeBoxTemplate", template: "#codeBoxTemplate",
props: ['title', 'content', 'escape'], props: ['title', 'content', 'escape'],
}); });
const socketUrl = <%- syzoj.utils.judgeServer('detail') %>; const socketUrl = "/detail";
const displayConfig = <%- JSON.stringify(displayConfig) %>; const displayConfig = <%- JSON.stringify(displayConfig) %>;
const token = <%- JSON.stringify(socketToken) %>; const token = <%- JSON.stringify(socketToken) %>;

Loading…
Cancel
Save