judge, problem_settings, problem_upload

This commit is contained in:
masnn committed 2020-04-05 09:02:35 +08:00
1 parent 5b4f5b6520
commit b3024bebb0
45 files changed
+598 -250

No files matched your search

+1 -1
View File
@@ -31,8 +31,8 @@ async function run() {
resolve();
});
});
require('./service/gridfs');
let server = require('./service/server');
require('./handler/ui');
require('./handler/base');
require('./handler/home');
+8 -13
View File
@@ -104,10 +104,17 @@ class ContestNotFoundError extends NotFoundError {
this.params = [cid];
}
}
class ProblemDataNotFoundError extends NotFoundError {
constructor(pid) {
super('Data of problem {0} not found.');
this.params = [pid];
}
}
module.exports = {
BadRequestError, ForbiddenError, NotFoundError,
LoginError, UserAlreadyExistError, InvalidTokenError,
UserNotFoundError, VerifyPasswordError,
UserNotFoundError, VerifyPasswordError, ProblemDataNotFoundError,
OpcountExceededError, PermissionError, NoProblemError,
ValidationError, ProblemNotFoundError, TrainingNotFoundError,
ContestNotFoundError, RecordNotFoundError
@@ -179,18 +186,6 @@ class DocumentNotFoundError(NotFoundError):
return 'Document {2} not found.'
class ProblemDataNotFoundError(NotFoundError):
@property
def message(self):
return 'Data of problem {1} not found.'
class RecordDataNotFoundError(NotFoundError):
@property
def message(self):
return 'Data of record {0} not found.'
class CsrfTokenError(ForbiddenError):
pass
-1
View File
@@ -59,7 +59,6 @@ MIDDLEWARE(async (ctx, next) => {
update_ip: ctx.request.ip,
update_ua: ctx.request.headers['user-agent'] || ''
}, ctx.session));
console.log(ctx.session.sid, ctx.session.uid);
let cookie = { secure: options.session.secure, httponly: true };
if (save) {
cookie.expires = ctx.session.expireAt, cookie.maxAge = expireSeconds;
+47 -2
View File
@@ -14,7 +14,7 @@ GET('/judge/fetch', requirePerm(PERM_JUDGE), async ctx => {
let rid = await queue.get('judge', false);
if (rid) {
let rdoc = await record.get(rid);
let data = {
let task = {
event: 'judge',
rid, type: 0,
pid: rdoc.pid,
@@ -22,12 +22,57 @@ GET('/judge/fetch', requirePerm(PERM_JUDGE), async ctx => {
lang: rdoc.lang,
code: rdoc.code
};
ctx.body = data;
ctx.body = { task };
}
else ctx.body = {};
});
POST('/judge/next', requirePerm(PERM_JUDGE), async ctx => {
console.log(ctx.request.body);
let body = ctx.request.body;
let rdoc = await record.get(body.rid);
let $set = {};
if (body.case) {
rdoc.testCases.push(body.case);
$set.testCases = rdoc.testCases;
}
if (body.judge_text) {
rdoc.judgeTexts.push(body.judge_text);
$set.judgeTexts = rdoc.judgeTexts;
}
if (body.compiler_text) {
rdoc.compilerTexts.push(body.compilerTexts);
$set.compilerTexts = rdoc.compilerTexts;
}
if (body.status) $set.status = body.status;
if (body.score) $set.score = body.score;
if (body.time_ms) $set.time = body.time_ms;
if (body.memory_kb) $set.memory = body.memory_kb;
await record.update(body.rid, $set);
ctx.body = {};
});
POST('/judge/end', requirePerm(PERM_JUDGE), async ctx => {
console.log(ctx.request.body);
let body = ctx.request.body;
let rdoc = await record.get(body.rid);
let $set = {};
if (body.case) {
rdoc.testCases.push(body.case);
$set.testCases = rdoc.testCases;
}
if (body.judge_text) {
rdoc.judgeTexts.push(body.judge_text);
$set.judgeTexts = rdoc.judgeTexts;
}
if (body.compiler_text) {
rdoc.compilerTexts.push(body.compilerTexts);
$set.compilerTexts = rdoc.compilerTexts;
}
if (body.status) $set.status = body.status;
if (body.score) $set.score = body.score;
if (body.time_ms) $set.time = body.time_ms;
if (body.memory_kb) $set.memory = body.memory_kb;
$set.judgeAt = new Date();
$set.judger = ctx.state.user._id;
await record.update(body.rid, $set);
ctx.body = {};
});
+73 -7
View File
@@ -1,29 +1,37 @@
const
fs = require('fs'),
bson = require('bson'),
validator = require('../lib/validator'),
problem = require('../model/problem'),
record = require('../model/record'),
user = require('../model/user'),
system = require('../model/system'),
{ GET, POST } = require('../service/server'),
gridfs = require('../service/gridfs'),
queue = require('../service/queue'),
{ requirePerm } = require('./tools'),
{ NoProblemError } = require('../error'),
{ NoProblemError, ProblemDataNotFoundError, BadRequestError } = require('../error'),
{ constants } = require('../options'),
{
PERM_VIEW_PROBLEM,
PERM_VIEW_PROBLEM_HIDDEN,
PERM_SUBMIT_PROBLEM,
PERM_CREATE_PROBLEM
PERM_CREATE_PROBLEM,
PERM_READ_PROBLEM_DATA,
PERM_EDIT_PROBLEM,
PERM_JUDGE
} = require('../permission');
queue.assert('judge');
GET('/p', requirePerm(PERM_VIEW_PROBLEM), async ctx => {
ctx.templateName = 'problem_main.html';
let q = {},
page = ctx.query.page || 1;
if (ctx.query.category) q.category = ctx.query.category;
if (!ctx.state.user.hasPerm(PERM_VIEW_PROBLEM_HIDDEN)) q.hidden = false;
let pdocs = await problem.getMany(q, { pid: 1 }, page, constants.PROBLEM_PER_PAGE);
ctx.templateName = 'problem_main.html';
ctx.body = { page_name: 'problem_list', page, pdocs, category: '' };
ctx.body = { page, pdocs, category: '' };
});
GET('/problem/random', requirePerm(PERM_VIEW_PROBLEM), async ctx => {
let q = {};
@@ -33,33 +41,89 @@ GET('/problem/random', requirePerm(PERM_VIEW_PROBLEM), async ctx => {
ctx.body = { pid };
});
GET('/p/:pid', requirePerm(PERM_VIEW_PROBLEM), async ctx => {
ctx.templateName = 'problem_detail.html';
let uid = ctx.state.user._id,
pid = ctx.params.pid;
let pdoc = await problem.get({ pid, uid });
if (pdoc.hidden) ctx.checkPerm(PERM_VIEW_PROBLEM_HIDDEN);
let udoc = await user.getById(pdoc.owner);
ctx.templateName = 'problem_detail.html';
ctx.body = { pdoc, udoc, title: pdoc.title };
});
GET('/p/:pid/submit', requirePerm(PERM_SUBMIT_PROBLEM), async ctx => {
ctx.templateName = 'problem_submit.html';
let uid = ctx.state.user._id,
pid = ctx.params.pid;
let pdoc = await problem.get({ pid, uid });
if (pdoc.hidden) ctx.checkPerm(PERM_VIEW_PROBLEM_HIDDEN);
let udoc = await user.getById(pdoc.owner);
ctx.templateName = 'problem_submit.html';
ctx.body = { pdoc, udoc, title: pdoc.title };
});
POST('/p/:pid/submit', requirePerm(PERM_SUBMIT_PROBLEM), async ctx => {
let rid = await record.add({
uid: ctx.state.user._id,
lang: ctx.request.body.language,
lang: ctx.request.body.lang,
code: ctx.request.body.code,
pid: ctx.params.pid
});
await queue.push('judge', rid);
ctx.state.user.nSubmit++;
ctx.body = { rid };
ctx.setRedirect = `/r/${rid}`;
});
GET('/p/:pid/settings', async ctx => {
ctx.templateName = 'problem_settings.html';
let pdoc = await problem.get({ pid: ctx.params.pid, uid: ctx.state.user._id });
if (pdoc.hidden) ctx.checkPerm(PERM_VIEW_PROBLEM_HIDDEN);
ctx.body = { pdoc };
});
POST('/p/:pid/settings', async ctx => {
ctx.templateName = 'problem_settings.html';
// TODO(masnn)
let pdoc = await problem.get({ pid: ctx.params.pid, uid: ctx.state.user._id });
ctx.body = { pdoc };
});
GET('/p/:pid/upload', async ctx => {
ctx.templateName = 'problem_upload.html';
let pdoc = await problem.get({ pid: ctx.params.pid, uid: ctx.state.user._id });
if (pdoc.owner != ctx.state.user._id) ctx.checkPerm(PERM_EDIT_PROBLEM);
let md5;
if (typeof pdoc.data == 'object') {
let files = await gridfs.find({ _id: pdoc.data }).toArray();
md5 = files[0].md5;
}
ctx.body = { pdoc, md5 };
});
POST('/p/:pid/upload', async ctx => {
ctx.templateName = 'problem_upload.html';
if (!ctx.request.files.file) throw new BadRequestError();
let pdoc = await problem.get({ pid: ctx.params.pid, uid: ctx.state.user._id });
if (pdoc.owner != ctx.state.user._id) ctx.checkPerm(PERM_EDIT_PROBLEM);
const r = fs.createReadStream(ctx.request.files.file.path);
let f = gridfs.openUploadStream('data.zip');
await new Promise((resolve, reject) => {
r.pipe(f);
f.once('finish', resolve);
f.once('error', reject);
});
let md5;
if (typeof pdoc.data == 'object') {
let files = await gridfs.find({ _id: pdoc.data }).toArray();
md5 = files[0].md5;
}
pdoc = await problem.edit(ctx.params.pid, { data: f.id });
ctx.body = { pdoc, md5 };
});
GET('/p/:pid/data', async ctx => {
let pdoc = await problem.get({ pid: ctx.params.pid, uid: ctx.state.user._id });
if (!ctx.state.user._id == pdoc.owner) ctx.checkPerm([PERM_READ_PROBLEM_DATA, PERM_JUDGE]);
if (!pdoc.data) throw new ProblemDataNotFoundError(ctx.params.pid);
else if (typeof pdoc.data == 'string') ctx.setRedirect = pdoc.data.split('from:')[1];
ctx.attachment(`${pdoc.title}.zip`);
ctx.body = gridfs.openDownloadStream(pdoc.data);
});
GET('/problem/create', requirePerm(PERM_CREATE_PROBLEM), async ctx => {
ctx.templateName = 'problem_edit.html';
ctx.body = { page_name: 'problem_create' };
});
POST('/problem/create', requirePerm(PERM_CREATE_PROBLEM), async ctx => {
let { title, pid, content, hidden } = ctx.request.body;
@@ -67,8 +131,10 @@ POST('/problem/create', requirePerm(PERM_CREATE_PROBLEM), async ctx => {
pid = pid || await system.incPidCounter();
await problem.add({ title, content, owner: ctx.state.user._id, pid, hidden });
ctx.body = { pid };
ctx.setRedirect = `/p/${pid}/settings`;
});
/*
@app.route('/p/category/{category:[^/]*}/random', 'problem_category_random')
+15 -4
View File
@@ -1,13 +1,16 @@
const
bson = require('bson'),
{ constants } = require('../options'),
{ GET } = require('../service/server'),
{ GET, POST } = require('../service/server'),
{ requirePerm } = require('../handler/tools'),
queue = require('../service/queue'),
record = require('../model/record'),
user = require('../model/user'),
problem = require('../model/problem'),
{ PERM_READ_RECORD_CODE, PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD } = require('../permission');
{ PERM_READ_RECORD_CODE, PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD, PERM_REJUDGE } = require('../permission');
GET('/r', async ctx => {
ctx.templateName = 'record_main.html';
let q = {},
page = ctx.query.page || 1;
let rdocs = await record.getMany(q, { rid: 1 }, page, constants.RECORD_PER_PAGE);
@@ -16,16 +19,24 @@ GET('/r', async ctx => {
udict[rdoc.uid] = await user.getById(rdoc.uid);
pdict[rdoc.pid] = await problem.get({ pid: rdoc.pid, uid: ctx.state.user._id });
}
ctx.templateName = 'record_main.html';
ctx.body = { page, rdocs, pdict, udict };
});
GET('/r/:rid', async ctx => {
ctx.templateName = 'record_detail.html';
let uid = ctx.state.user._id, rid = new bson.ObjectID(ctx.params.rid);
let rdoc = await record.get(rid);
if (rdoc.hidden) ctx.checkPerm(PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
if (rdoc.uid != uid && !ctx.state.user.hasPerm(PERM_READ_RECORD_CODE)) rdoc.code = null;
ctx.body = { rdoc, show_status: true };
});
POST('/r/:rid/rejudge', requirePerm(PERM_REJUDGE), async ctx => {
ctx.templateName = 'record_detail.html';
ctx.body = { rdoc };
let uid = ctx.state.user._id, rid = new bson.ObjectID(ctx.params.rid);
let rdoc = await record.get(rid);
if (rdoc.hidden) ctx.checkPerm(PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
if (rdoc.uid != uid && !ctx.state.user.hasPerm(PERM_READ_RECORD_CODE)) rdoc.code = null;
if (rdoc) await queue.push('judge', rid);
ctx.body = { rdoc, show_status: true };
});
/*
+34 -13
View File
@@ -1,6 +1,5 @@
const
path = require('path'),
md5 = require('blueimp-md5'),
static = require('koa-static'),
nunjucks = require('nunjucks'),
hljs = require('hljs'),
@@ -9,14 +8,9 @@ const
options = require('../options'),
perm = require('../permission'),
builtin = require('../model/builtin'),
md5 = require('../lib/md5'),
{ MIDDLEWARE } = require('../service/server'),
{ NotFoundError } = require('../error'),
MD5_REGEX = /^[0-9a-f]{32}$/;
function getHash(email) {
email = (typeof email === 'string') ? email.trim().toLowerCase() : 'unspecified';
return email.match(MD5_REGEX) ? email : md5(email);
}
{ NotFoundError } = require('../error');
class Markdown extends MarkdownIt {
constructor() {
@@ -35,6 +29,14 @@ class Markdown extends MarkdownIt {
}
}
const md = new Markdown();
function datetime_span(dt, { relative = true } = {}) {
dt = new Date(dt);
return '<span class="time{0}" data-timestamp="{1}">{2}</span>'.format(
relative ? ' relative' : '',
dt.getTime(),
dt.toLocaleString()
);
}
class Nunjucks extends nunjucks.Environment {
constructor() {
super(
@@ -51,12 +53,26 @@ class Nunjucks extends nunjucks.Environment {
return md.render(self);
});
this.addFilter('gravatar_url', function (email, size) {
return `//gravatar.loli.net/avatar/${getHash(email)}?d=mm&s=${size}`;
return `//gravatar.loli.net/avatar/${md5(email.toString().trim().toLowerCase())}?d=mm&s=${size}`;
});
this.addFilter('format_size', function (size, base = 1) {
size *= base;
let unit = 1024;
let unit_names = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
for (let unit_name of unit_names) {
if (size < unit) return '{0} {1}'.format(Math.round(size), unit_name);
size /= unit;
}
return '{0} {1}'.format(Math.round(size * unit), unit_names[unit_names.length - 1]);
});
this.addGlobal('typeof', o => typeof o);
this.addGlobal('console', console);
this.addGlobal('static_url', str => `/${str}`);
this.addGlobal('reverse_url', str => str);
this.addGlobal('datetime_span', datetime_span);
this.addGlobal('perm', perm);
this.addGlobal('builtin', builtin);
this.addGlobal('status', builtin.STATUS);
}
}
const env = new Nunjucks();
@@ -67,6 +83,7 @@ MIDDLEWARE(async (ctx, next) => {
cdn_prefix: '/',
url_prefix: '/'
};
ctx.preferJson = ctx.request.headers['accept'].includes('application/json');
ctx.render = async (name, context) => {
ctx.user = ctx.state.user;
ctx.translate = str => {
@@ -77,7 +94,8 @@ MIDDLEWARE(async (ctx, next) => {
ctx.body = await new Promise((resolve, reject) => {
env.render(name, Object.assign(ctx.state, context, {
handler: ctx,
_: ctx.translate
_: ctx.translate,
user: ctx.state.user
}), (error, res) => {
if (error) reject(error);
else resolve(res);
@@ -89,6 +107,7 @@ MIDDLEWARE(async (ctx, next) => {
try {
await next();
if (ctx.body || ctx.templateName) {
if (ctx.preferJson) return;
if (ctx.query.template || ctx.templateName) {
ctx.body = ctx.body || {};
Object.assign(ctx.body, JSON.parse(ctx.query.data || '{}'));
@@ -99,11 +118,13 @@ MIDDLEWARE(async (ctx, next) => {
}
} else throw new NotFoundError();
} catch (error) {
console.log(error);
if (error.toString().startsWith('NotFoundError')) console.log(error);
if (error.toString().startsWith('Template render error')) throw error;
await ctx.render('error.html', { error });
if (ctx.preferJson) ctx.body = { error };
else await ctx.render('error.html', { error });
}
} catch (error) {
await ctx.render('bsod.html', { error });
if (ctx.preferJson) ctx.body = { error };
else await ctx.render('bsod.html', { error });
}
});
+133
View File
@@ -0,0 +1,133 @@
'use strict';
function safeAdd(x, y) {
var lsw = (x & 0xffff) + (y & 0xffff);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xffff);
}
const bitRotateLeft = (num, cnt) => (num << cnt) | (num >>> (32 - cnt));
const md5cmn = (q, a, b, x, s, t) => safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
const md5ff = (a, b, c, d, x, s, t) => md5cmn((b & c) | (~b & d), a, b, x, s, t);
const md5gg = (a, b, c, d, x, s, t) => md5cmn((b & d) | (c & ~d), a, b, x, s, t);
const md5hh = (a, b, c, d, x, s, t) => md5cmn(b ^ c ^ d, a, b, x, s, t);
const md5ii = (a, b, c, d, x, s, t) => md5cmn(c ^ (b | ~d), a, b, x, s, t);
function binlMD5(x, len) {
x[len >> 5] |= 0x80 << len % 32;
x[(((len + 64) >>> 9) << 4) + 14] = len;
var i;
var olda;
var oldb;
var oldc;
var oldd;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
for (i = 0; i < x.length; i += 16) {
olda = a;
oldb = b;
oldc = c;
oldd = d;
a = md5ff(a, b, c, d, x[i], 7, -680876936);
d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
b = md5gg(b, c, d, a, x[i], 20, -373897302);
a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
d = md5hh(d, a, b, c, x[i], 11, -358537222);
c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
a = md5ii(a, b, c, d, x[i], 6, -198630844);
d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
a = safeAdd(a, olda);
b = safeAdd(b, oldb);
c = safeAdd(c, oldc);
d = safeAdd(d, oldd);
}
return [a, b, c, d];
}
function binl2rstr(input) {
var i;
var output = '';
var length32 = input.length * 32;
for (i = 0; i < length32; i += 8)
output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff);
return output;
}
function rstr2binl(input) {
var i;
var output = [];
output[(input.length >> 2) - 1] = undefined;
for (i = 0; i < output.length; i += 1)
output[i] = 0;
var length8 = input.length * 8;
for (i = 0; i < length8; i += 8)
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32;
return output;
}
const rstrMD5 = s => binl2rstr(binlMD5(rstr2binl(s), s.length * 8));
function rstr2hex(input) {
var hexTab = '0123456789abcdef';
var output = '';
var x;
var i;
for (i = 0; i < input.length; i += 1) {
x = input.charCodeAt(i);
output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f);
}
return output;
}
module.exports = s => rstr2hex(rstrMD5(unescape(encodeURIComponent(s))));
+55 -4
View File
@@ -177,9 +177,9 @@ const FOOTER_EXTRA_HTMLS = [];
const VIEW_LANGS = [
{ code: 'zh-CN', name: 'zh-CN' }
];
const LANGS = [
{ id: 'cc', name: 'cpp' }
];
const LANGS = {
cc: 'cpp'
};
const LANG_TEXTS = {
c: 'C',
cc: 'C++',
@@ -210,7 +210,58 @@ const LANG_HIGHLIGHT_ID = {
go: 'go',
rb: 'ruby',
};
const STATUS = {
STATUS_WAITING: 0,
STATUS_ACCEPTED: 1,
STATUS_WRONG_ANSWER: 2,
STATUS_TIME_LIMIT_EXCEEDED: 3,
STATUS_MEMORY_LIMIT_EXCEEDED: 4,
STATUS_OUTPUT_LIMIT_EXCEEDED: 5,
STATUS_RUNTIME_ERROR: 6,
STATUS_COMPILE_ERROR: 7,
STATUS_SYSTEM_ERROR: 8,
STATUS_CANCELED: 9,
STATUS_ETC: 10,
STATUS_JUDGING: 20,
STATUS_COMPILING: 21,
STATUS_FETCHED: 22,
STATUS_IGNORED: 30
};
const STATUS_TEXTS = {
[STATUS.STATUS_WAITING]: 'Waiting',
[STATUS.STATUS_ACCEPTED]: 'Accepted',
[STATUS.STATUS_WRONG_ANSWER]: 'Wrong Answer',
[STATUS.STATUS_TIME_LIMIT_EXCEEDED]: 'Time Exceeded',
[STATUS.STATUS_MEMORY_LIMIT_EXCEEDED]: 'Memory Exceeded',
[STATUS.STATUS_OUTPUT_LIMIT_EXCEEDED]: 'Output Exceeded',
[STATUS.STATUS_RUNTIME_ERROR]: 'Runtime Error',
[STATUS.STATUS_COMPILE_ERROR]: 'Compile Error',
[STATUS.STATUS_SYSTEM_ERROR]: 'System Error',
[STATUS.STATUS_CANCELED]: 'Cancelled',
[STATUS.STATUS_ETC]: 'Unknown Error',
[STATUS.STATUS_JUDGING]: 'Running',
[STATUS.STATUS_COMPILING]: 'Compiling',
[STATUS.STATUS_FETCHED]: 'Fetched',
[STATUS.STATUS_IGNORED]: 'Ignored',
};
const STATUS_CODES = {
0: 'pending',
1: 'pass',
2: 'fail',
3: 'fail',
4: 'fail',
5: 'fail',
6: 'fail',
7: 'fail',
8: 'fail',
9: 'ignored',
10: 'fail',
20: 'progress',
21: 'progress',
22: 'progress',
30: 'ignored'
};
module.exports = {
BUILTIN_USERS, BUILTIN_ROLES, CATEGORIES, VIEW_LANGS, FOOTER_EXTRA_HTMLS, LANGS,
LANG_TEXTS, LANG_HIGHLIGHT_ID
LANG_TEXTS, LANG_HIGHLIGHT_ID, STATUS, STATUS_TEXTS, STATUS_CODES
};
+7 -4
View File
@@ -1,7 +1,8 @@
const
_ = require('lodash'),
{ ObjectID } = require('bson'),
{ RecordNotFoundError } = require('../error'),
{ STATUS_WAITING } = require('../status'),
{ STATUS_WAITING } = require('../model/builtin').STATUS,
db = require('../service/db.js'),
coll = db.collection('record');
@@ -29,7 +30,8 @@ async function add(data) {
* @returns {import('../interface').Record}
*/
async function get(rid) {
let rdoc = await coll.findOne({ _id: rid });
let _id = new ObjectID(rid);
let rdoc = await coll.findOne({ _id });
if (!rdoc) throw new RecordNotFoundError(rid);
return rdoc;
}
@@ -37,8 +39,9 @@ async function getMany(query, sort, page, limit) {
return await coll.find(query).sort(sort).skip((page - 1) * limit).limit(limit).toArray();
}
async function update(rid, $set) {
await coll.findOneAndUpdate({ _id: rid }, { $set });
let rdoc = await coll.findOne({ _id: rid });
let _id = new ObjectID(rid);
await coll.findOneAndUpdate({ _id }, { $set });
let rdoc = await coll.findOne({ _id });
if (!rdoc) throw new RecordNotFoundError(rid);
return rdoc;
}
-1
View File
@@ -16,7 +16,6 @@ class USER {
this.perm = user.perm;
}
hasPerm(perm) {
console.log('PERM', perm, this.perm);
return this.perm == '-' || (this.perm || '').includes(perm);
}
checkPassword(password) {
+1 -1
View File
@@ -9,7 +9,7 @@ module.exports = {
naccept[j.pid]++;
}
function _time(jdoc) {
let real = jdoc.rid.generation_time - Math.floor(tdoc.begin_at / 1000);
let real = jdoc.rid.generationTime - Math.floor(tdoc.begin_at / 1000);
let penalty = 20 * 60 * naccept[jdoc.pid];
return real + penalty;
}
+1 -1
View File
@@ -12,7 +12,7 @@ module.exports = {
effective[j.pid] = j;
const _time = jdoc => jdoc.rid.generationTime - Math.floor(tdoc.begin_at / 1000);
function _penalty_score(jdoc) {
let exceed_seconds = jdoc.rid.generation_time - Math.floor(tdoc.penalty_since / 1000);
let exceed_seconds = jdoc.rid.generationTime - Math.floor(tdoc.penalty_since / 1000);
if (exceed_seconds < 0) return jdoc.score;
else return 0.5 * jdoc.score;
}
+1
View File
@@ -41,6 +41,7 @@ let permissions = {
PERM_VIEW_TRAINING: 'a',
PERM_CREATE_TRAINING: 'b',
PERM_EDIT_TRAINING: 'c',
PERM_JUDGE: 'd'
};
permissions.PERM_BASIC =
permissions.PERM_VIEW +
+1
View File
@@ -10,6 +10,7 @@ let db = null;
Mongo.MongoClient.connect(mongourl, { useNewUrlParser: true, useUnifiedTopology: true })
.then(Database => {
db = Database.db(options.db.name);
db.Db = Database;
global.bus.emit('connected');
});
+5
View File
@@ -0,0 +1,5 @@
const
{ GridFSBucket } = require('mongodb'),
db = require('./db');
if (!db.s) db.s = {};
module.exports = new GridFSBucket(db);
+6 -1
View File
@@ -12,7 +12,12 @@ let app = new Koa();
let server = http.createServer(app.callback());
app.keys = options.session.keys;
app.use(morgan(':method :url :status :res[content-length] - :response-time ms'));
app.use(Body());
app.use(Body({
multipart: true,
formidable: {
maxFileSize: 256 * 1024 * 1024
}
}));
let router = new Router();
/**
-32
View File
@@ -1,32 +0,0 @@
exports.STATUS_WAITING = 0;
exports.STATUS_ACCEPTED = 1;
exports.STATUS_WRONG_ANSWER = 2;
exports.STATUS_TIME_LIMIT_EXCEEDED = 3;
exports.STATUS_MEMORY_LIMIT_EXCEEDED = 4;
exports.STATUS_OUTPUT_LIMIT_EXCEEDED = 5;
exports.STATUS_RUNTIME_ERROR = 6;
exports.STATUS_COMPILE_ERROR = 7;
exports.STATUS_SYSTEM_ERROR = 8;
exports.STATUS_CANCELED = 9;
exports.STATUS_ETC = 10;
exports.STATUS_JUDGING = 20;
exports.STATUS_COMPILING = 21;
exports.STATUS_FETCHED = 22;
exports.STATUS_IGNORED = 30;
exports.STATUS_TEXTS = {
[exports.STATUS_WAITING]: 'Waiting',
[exports.STATUS_ACCEPTED]: 'Accepted',
[exports.STATUS_WRONG_ANSWER]: 'Wrong Answer',
[exports.STATUS_TIME_LIMIT_EXCEEDED]: 'Time Exceeded',
[exports.STATUS_MEMORY_LIMIT_EXCEEDED]: 'Memory Exceeded',
[exports.STATUS_OUTPUT_LIMIT_EXCEEDED]: 'Output Exceeded',
[exports.STATUS_RUNTIME_ERROR]: 'Runtime Error',
[exports.STATUS_COMPILE_ERROR]: 'Compile Error',
[exports.STATUS_SYSTEM_ERROR]: 'System Error',
[exports.STATUS_CANCELED]: 'Cancelled',
[exports.STATUS_ETC]: 'Unknown Error',
[exports.STATUS_JUDGING]: 'Running',
[exports.STATUS_COMPILING]: 'Compiling',
[exports.STATUS_FETCHED]: 'Fetched',
[exports.STATUS_IGNORED]: 'Ignored',
};