Browse Source

Merge pull request #32 from hewenyang/merge_frontend

Merge judge-v3 frontend code into syzoj
master
Menci 6 years ago committed by GitHub
parent
commit
7eb3b66ebe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      app.js
  2. 2
      config-example.json
  3. 78
      libs/judgeResult.js
  4. 115
      libs/judger.js
  5. 53
      libs/judger_interfaces.js
  6. 23
      libs/winston.js
  7. 49
      modules/api_v2.js
  8. 298
      modules/socketio.js
  9. 1764
      package-lock.json
  10. 5
      package.json
  11. 2
      views/submission.ejs
  12. 2
      views/submissions.ejs

6
app.js

@ -44,8 +44,11 @@ global.syzoj = {
global.app = Express();
syzoj.production = app.get('env') === 'production';
let winstonLib = require('./libs/winston');
winstonLib.configureWinston(!syzoj.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)}...`);
});
@ -83,6 +86,7 @@ global.syzoj = {
app.use(csurf({ cookie: true }));
await this.connectDatabase();
await this.lib('judger').connect();
this.loadModules();
},
async connectDatabase() {

2
config-example.json

@ -166,7 +166,7 @@
}
],
"session_secret": "233",
"judge_server_addr": "http://127.0.0.1:5284",
"rabbitMQ": "amqp://localhost/",
"judge_token": "233",
"email_jwt_secret": "test"
}

78
libs/judgeResult.js

@ -0,0 +1,78 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const _ = require("lodash");
const winston = require("winston");
const interfaces = require("./judger_interfaces");
const compileError = "Compile Error", systemError = "System Error", testdataError = "No Testdata";
exports.statusToString = {};
exports.statusToString[interfaces.TestcaseResultType.Accepted] = "Accepted";
exports.statusToString[interfaces.TestcaseResultType.WrongAnswer] = "Wrong Answer";
exports.statusToString[interfaces.TestcaseResultType.PartiallyCorrect] = "Partially Correct";
exports.statusToString[interfaces.TestcaseResultType.MemoryLimitExceeded] = "Memory Limit Exceeded";
exports.statusToString[interfaces.TestcaseResultType.TimeLimitExceeded] = "Time Limit Exceeded";
exports.statusToString[interfaces.TestcaseResultType.OutputLimitExceeded] = "Output Limit Exceeded";
exports.statusToString[interfaces.TestcaseResultType.RuntimeError] = "Runtime Error";
exports.statusToString[interfaces.TestcaseResultType.FileError] = "File Error";
exports.statusToString[interfaces.TestcaseResultType.JudgementFailed] = "Judgement Failed";
exports.statusToString[interfaces.TestcaseResultType.InvalidInteraction] = "Invalid Interaction";
function firstNonAC(t) {
if (t.every(v => v === interfaces.TestcaseResultType.Accepted)) {
return interfaces.TestcaseResultType.Accepted;
}
else {
return t.find(r => r !== interfaces.TestcaseResultType.Accepted);
}
}
exports.firstNonAC = firstNonAC;
function convertResult(taskId, source) {
winston.debug(`Converting result for ${taskId}`, source);
let time = null, memory = null, score = null, done = true, statusString = null;
if (source.compile && source.compile.status === interfaces.TaskStatus.Failed) {
statusString = compileError;
}
else if (source.error != null) {
done = false;
if (source.error === interfaces.ErrorType.TestDataError) {
statusString = testdataError;
}
else {
statusString = systemError;
}
}
else if (source.judge != null && source.judge.subtasks != null) {
const forEveryTestcase = function (map, reduce) {
const list = source.judge.subtasks.map(s => reduce(s.cases.filter(c => c.result != null).map(c => map(c.result))));
if (list.every(x => x == null))
return null;
else
return reduce(list);
};
time = forEveryTestcase(c => (c.time ? c.time : 0), _.sum);
memory = forEveryTestcase(c => (c.memory ? c.memory : 0), _.max);
if (source.judge.subtasks.some(s => s.cases.some(c => c.status === interfaces.TaskStatus.Failed))) {
winston.debug(`Some subtasks failed, returning system error`);
statusString = systemError;
}
else {
score = _.sum(source.judge.subtasks.map(s => s.score));
const finalResult = forEveryTestcase(c => c.type, firstNonAC);
statusString = exports.statusToString[finalResult];
}
}
else {
statusString = systemError;
}
const result = {
taskId: taskId,
time: time,
memory: memory,
score: score,
statusNumber: done ? interfaces.TaskStatus.Done : interfaces.TaskStatus.Failed,
statusString: statusString,
result: source
};
winston.debug(`Result for ${taskId}`, result);
return result;
}
exports.convertResult = convertResult;
//# sourceMappingURL=judgeResult.js.map

115
libs/judger.js

@ -2,14 +2,110 @@ const enums = require('./enums'),
rp = require('request-promise'),
url = require('url');
const amqp = require('amqplib');
const util = require('util');
const winston = require('winston');
const msgPack = require('msgpack-lite');
const interface = require('./judger_interfaces');
const judgeResult = require('./judgeResult');
let amqpConnection;
let amqpSendChannel;
let amqpConsumeChannel;
async function connect () {
amqpConnection = await amqp.connect(syzoj.config.rabbitMQ);
amqpSendChannel = await amqpConnection.createChannel();
await amqpSendChannel.assertQueue('judge', {
maxPriority: 5,
durable: true
});
await amqpSendChannel.assertQueue('result', {
durable: true
});
await amqpSendChannel.assertExchange('progress', 'fanout', {
durable: false
});
amqpConsumeChannel = await amqpConnection.createChannel();
amqpConsumeChannel.prefetch(1);
amqpConsumeChannel.consume('result', async (msg) => {
(async(msg) => {
const data = msgPack.decode(msg.content);
winston.verbose('Received report for task ' + data.taskId);
let JudgeState = syzoj.model('judge_state');
let judge_state = await JudgeState.findOne({ where: { task_id: data.taskId } });
if(data.type === interface.ProgressReportType.Finished) {
const convertedResult = judgeResult.convertResult(data.taskId, data.progress);
winston.verbose('Reporting report finished: ' + data.taskId);
const payload = msgPack.encode({ type: interface.ProgressReportType.Reported, taskId: data.taskId });
amqpSendChannel.publish('progress', '', payload);
if(!judge_state) return;
judge_state.score = convertedResult.score;
judge_state.pending = false;
judge_state.status = convertedResult.statusString;
judge_state.total_time = convertedResult.time;
judge_state.max_memory = convertedResult.memory;
judge_state.result = convertedResult.result;
await judge_state.save();
await judge_state.updateRelatedInfo();
} else if(data.type == interface.ProgressReportType.Compiled) {
if(!judge_state) return;
judge_state.compilation = data.progress;
await judge_state.save();
} else {
winston.error("Unsupported result type: " + data.type);
}
})(msg).then(async() => {
amqpConsumeChannel.ack(msg)
}, async(err) => {
winston.error('Error handling report', err);
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) => {
winston.error('RabbitMQ connection failure: ${err.toString()}');
amqpConnection.close();
process.exit(1);
});
}
module.exports.connect = connect;
module.exports.judge = async function (judge_state, problem, priority) {
let type, param, extraFile = null;
let type, param, extraData = null;
switch (problem.type) {
case 'submit-answer':
type = enums.ProblemType.AnswerSubmission;
param = null;
extraFile = 'static/uploads/answer/' + judge_state.code;
let fs = Promise.promisifyAll(require('fs-extra'));
extraData = await fs.readFileAsync(syzoj.model('file').resolvePath('answer', judge_state.code));
break;
case 'interaction':
type = enums.ProblemType.Interaction;
@ -33,24 +129,13 @@ module.exports.judge = async function (judge_state, problem, priority) {
break;
}
const req = {
content: {
const content = {
taskId: judge_state.task_id,
testData: problem.id.toString(),
type: type,
priority: priority,
param: param
},
extraFileLocation: extraFile
};
await rp(url.resolve(syzoj.config.judge_server_addr, "/daemon/task"), {
method: 'PUT',
body: req,
headers: {
Token: syzoj.config.judge_token
},
json: true,
simple: true
});
amqpSendChannel.sendToQueue('judge', msgPack.encode({ content: content, extraData: extraData }), { priority: priority });
}

53
libs/judger_interfaces.js

@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var RPCTaskType;
(function (RPCTaskType) {
RPCTaskType[RPCTaskType["Compile"] = 1] = "Compile";
RPCTaskType[RPCTaskType["RunStandard"] = 2] = "RunStandard";
RPCTaskType[RPCTaskType["RunSubmitAnswer"] = 3] = "RunSubmitAnswer";
RPCTaskType[RPCTaskType["RunInteraction"] = 4] = "RunInteraction";
})(RPCTaskType = exports.RPCTaskType || (exports.RPCTaskType = {}));
;
var ErrorType;
(function (ErrorType) {
ErrorType[ErrorType["SystemError"] = 0] = "SystemError";
ErrorType[ErrorType["TestDataError"] = 1] = "TestDataError";
})(ErrorType = exports.ErrorType || (exports.ErrorType = {}));
var 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 = exports.TaskStatus || (exports.TaskStatus = {}));
var 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 = exports.TestcaseResultType || (exports.TestcaseResultType = {}));
var RPCReplyType;
(function (RPCReplyType) {
RPCReplyType[RPCReplyType["Started"] = 1] = "Started";
RPCReplyType[RPCReplyType["Finished"] = 2] = "Finished";
RPCReplyType[RPCReplyType["Error"] = 3] = "Error";
})(RPCReplyType = exports.RPCReplyType || (exports.RPCReplyType = {}));
var ProgressReportType;
(function (ProgressReportType) {
ProgressReportType[ProgressReportType["Started"] = 1] = "Started";
ProgressReportType[ProgressReportType["Compiled"] = 2] = "Compiled";
ProgressReportType[ProgressReportType["Progress"] = 3] = "Progress";
ProgressReportType[ProgressReportType["Finished"] = 4] = "Finished";
ProgressReportType[ProgressReportType["Reported"] = 5] = "Reported";
})(ProgressReportType = exports.ProgressReportType || (exports.ProgressReportType = {}));
exports.redisBinarySuffix = '-bin';
exports.redisMetadataSuffix = '-meta';
//# sourceMappingURL=interfaces.js.map

23
libs/winston.js

@ -0,0 +1,23 @@
const winston = require('winston');
const _ = require('lodash');
const util = require('util');
function formatter(args) {
var msg = args.level + ' - ' + args.message + (_.isEmpty(args.meta) ? '' : (' - ' + util.inspect(args.meta)));
return msg;
}
function configureWinston(verbose) {
winston.configure({
transports: [
new (winston.transports.Console)({ formatter: formatter })
]
});
if (verbose) {
winston.level = 'debug';
} else {
winston.level = 'info';
}
}
module.exports.configureWinston = configureWinston;

49
modules/api_v2.js

@ -111,52 +111,3 @@ app.apiRouter.post('/api/v2/markdown', async (req, res) => {
res.send(e);
}
});
app.apiRouter.post('/api/v2/judge/compiled', async (req, res) => {
try {
if (req.get('Token') !== syzoj.config.judge_token) return res.status(403).send({ err: 'Incorrect token' });
let data = req.body;
let JudgeState = syzoj.model('judge_state');
let judge_state = await JudgeState.findOne({ where: { task_id: req.body.taskId } });
if (!judge_state) {
res.send({ return: 1 }); // The task might have been rejudging.
return;
}
judge_state.compilation = req.body.result;
await judge_state.save();
res.send({ return: 0 });
} catch (e) {
syzoj.log(e);
res.status(500).send(e);
}
});
app.apiRouter.post('/api/v2/judge/finished', async (req, res) => {
try {
if (req.get('Token') !== syzoj.config.judge_token) return res.status(403).send({ err: 'Incorrect token' });
let data = req.body;
let JudgeState = syzoj.model('judge_state');
let judge_state = await JudgeState.findOne({ where: { task_id: req.body.taskId } });
if (!judge_state) {
res.send({ return: 1 }); // The task might have been rejudging.
return;
}
// await judge_state.updateResult(JSON.parse(req.body));
judge_state.score = data.score;
judge_state.pending = false;
judge_state.status = data.statusString;
judge_state.total_time = data.time;
judge_state.max_memory = data.memory;
judge_state.result = data.result;
await judge_state.save();
await judge_state.updateRelatedInfo();
res.send({ return: 0 });
} catch (e) {
syzoj.log(e);
res.status(500).send(e);
}
});

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 = require("../libs/judgeResult");
const interfaces = 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.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.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);

1764
package-lock.json generated

File diff suppressed because it is too large Load Diff

5
package.json

@ -23,6 +23,7 @@
},
"homepage": "https://github.com/syzoj/syzoj#readme",
"dependencies": {
"amqplib": "^0.5.2",
"ansi-to-html": "^0.4.2",
"async-lock": "^0.3.9",
"body-parser": "^1.15.2",
@ -39,9 +40,11 @@
"fs-extra": "^4.0.1",
"gravatar": "^1.5.2",
"js-yaml": "^3.9.0",
"jsondiffpatch": "0.2.4",
"jsonwebtoken": "^7.4.3",
"moemark-renderer": "^1.2.6",
"moment": "^2.15.0",
"msgpack-lite": "^0.1.26",
"multer": "^1.2.0",
"mysql": "^2.11.1",
"node-7z": "^0.4.0",
@ -53,10 +56,12 @@
"sendmail": "^1.1.1",
"sequelize": "^3.24.3",
"session-file-store": "^1.0.0",
"socket.io": "^2.0.3",
"sqlite3": "^3.1.4",
"syzoj-divine": "^1.0.2",
"tmp-promise": "^1.0.3",
"waliyun": "^3.1.1",
"winston": "^2.3.1",
"xss": "^0.3.3"
}
}

2
views/submission.ejs

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

2
views/submissions.ejs

@ -114,7 +114,7 @@ $(function () {
$('#select_status').dropdown();
});
const itemList = <%- JSON.stringify(items) %>;
const socketUrl = <%- syzoj.utils.judgeServer(pushType) %>;
const socketUrl = "/rough";
const displayConfig = <%- JSON.stringify(displayConfig) %>;
const vueApp = new Vue({

Loading…
Cancel
Save