mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-19 17:38:19 +08:00
judge, problem_settings, problem_upload
This commit is contained in:
1 parent
5b4f5b6520
commit
b3024bebb0
45 files changed
+598
-250
No files matched your search
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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 = {};
|
||||
});
|
||||
@@ -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
@@ -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
@@ -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 });
|
||||
}
|
||||
});
|
||||
@@ -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
@@ -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
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 +
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
const
|
||||
{ GridFSBucket } = require('mongodb'),
|
||||
db = require('./db');
|
||||
if (!db.s) db.s = {};
|
||||
module.exports = new GridFSBucket(db);
|
||||
@@ -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();
|
||||
|
||||
/**
|
||||
|
||||
@@ -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',
|
||||
};
|
||||
Reference in new issue
Block a user