let Problem = syzoj.model('problem'); let JudgeState = syzoj.model('judge_state'); let Article = syzoj.model('article'); let Contest = syzoj.model('contest'); let User = syzoj.model('user'); let UserPrivilege = syzoj.model('user_privilege'); const RatingCalculation = syzoj.model('rating_calculation'); const RatingHistory = syzoj.model('rating_history'); let ContestPlayer = syzoj.model('contest_player'); const calcRating = require('../libs/rating'); app.get('/admin/info', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); let allSubmissionsCount = await JudgeState.count(); let todaySubmissionsCount = await JudgeState.count({ submit_time: TypeORM.MoreThanOrEqual(syzoj.utils.getCurrentDate(true)) }); let problemsCount = await Problem.count(); let articlesCount = await Article.count(); let contestsCount = await Contest.count(); let usersCount = await User.count(); res.render('admin_info', { allSubmissionsCount: allSubmissionsCount, todaySubmissionsCount: todaySubmissionsCount, problemsCount: problemsCount, articlesCount: articlesCount, contestsCount: contestsCount, usersCount: usersCount }); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); let configItems = { 'title': { name: '站点标题', type: String }, 'google_analytics': { name: 'Google Analytics', type: String }, '默认参数': null, 'default.problem.time_limit': { name: '时间限制(单位:ms)', type: Number }, 'default.problem.memory_limit': { name: '空间限制(单位:MiB)', type: Number }, '限制': null, 'limit.time_limit': { name: '最大时间限制(单位:ms)', type: Number }, 'limit.memory_limit': { name: '最大空间限制(单位:MiB)', type: Number }, 'limit.data_size': { name: '所有数据包大小(单位:byte)', type: Number }, 'limit.testdata': { name: '测试数据大小(单位:byte)', type: Number }, 'limit.submit_code': { name: '代码长度(单位:byte)', type: Number }, 'limit.submit_answer': { name: '提交答案题目答案大小(单位:byte)', type: Number }, 'limit.custom_test_input': { name: '自定义测试输入文件大小(单位:byte)', type: Number }, 'limit.testdata_filecount': { name: '测试数据文件数量(单位:byte)', type: Number }, '每页显示数量': null, 'page.problem': { name: '题库', type: Number }, 'page.judge_state': { name: '提交记录', type: Number }, 'page.problem_statistics': { name: '题目统计', type: Number }, 'page.ranklist': { name: '排行榜', type: Number }, 'page.discussion': { name: '讨论', type: Number }, 'page.article_comment': { name: '评论', type: Number }, 'page.contest': { name: '比赛', type: Number } }; app.get('/admin/config', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); for (let i in configItems) { if (!configItems[i]) continue; configItems[i].val = eval(`syzoj.config.${i}`); } res.render('admin_config', { items: configItems }); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.post('/admin/config', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); for (let i in configItems) { if (!configItems[i]) continue; if (req.body[i]) { let val; if (configItems[i].type === Boolean) { val = req.body[i] === 'on'; } else if (configItems[i].type === Number) { val = Number(req.body[i]); } else { val = req.body[i]; } let f = new Function('val', `syzoj.config.${i} = val`); f(val); } } await syzoj.utils.saveConfig(); res.redirect(syzoj.utils.makeUrl(['admin', 'config'])); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.get('/admin/privilege', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); let a = await UserPrivilege.find(); let users = {}; for (let p of a) { if (!users[p.user_id]) { users[p.user_id] = { user: await User.findById(p.user_id), privileges: [] }; } users[p.user_id].privileges.push(p.privilege); } res.render('admin_privilege', { users: Object.values(users) }); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.post('/admin/privilege', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); let data = JSON.parse(req.body.data); for (let id in data) { let user = await User.findById(id); if (!user) throw new ErrorMessage(`不存在 ID 为 ${id} 的用户。`); await user.setPrivileges(data[id]); } res.redirect(syzoj.utils.makeUrl(['admin', 'privilege'])); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.get('/admin/rating', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); const contests = await Contest.find({ order: { start_time: 'DESC' } }); const calcs = await RatingCalculation.find({ order: { id: 'DESC' } }); for (const calc of calcs) await calc.loadRelationships(); res.render('admin_rating', { contests: contests, calcs: calcs }); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.post('/admin/rating/add', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); const contest = await Contest.findById(req.body.contest); if (!contest) throw new ErrorMessage('无此比赛'); await contest.loadRelationships(); const newcalc = await RatingCalculation.create(contest.id); await newcalc.save(); if (!contest.ranklist || contest.ranklist.ranklist.player_num <= 1) { throw new ErrorMessage("比赛人数太少。"); } const players = []; for (let i = 1; i <= contest.ranklist.ranklist.player_num; i++) { const user = await User.findById((await ContestPlayer.findById(contest.ranklist.ranklist[i])).user_id); players.push({ user: user, rank: i, currentRating: user.rating }); } const newRating = calcRating(players); for (let i = 0; i < newRating.length; i++) { const user = newRating[i].user; user.rating = newRating[i].currentRating; await user.save(); const newHistory = await RatingHistory.create(newcalc.id, user.id, newRating[i].currentRating, newRating[i].rank); await newHistory.save(); } res.redirect(syzoj.utils.makeUrl(['admin', 'rating'])); } catch (e) { syzoj.log(e); res.render('error', { err: e }); } }); app.post('/admin/rating/delete', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); const calcList = await RatingCalculation.find({ where: { id: TypeORM.MoreThanOrEqual(req.body.calc_id) }, order: { id: 'DESC' } }); if (calcList.length === 0) throw new ErrorMessage('ID 不正确'); for (let i = 0; i < calcList.length; i++) { await calcList[i].delete(); } res.redirect(syzoj.utils.makeUrl(['admin', 'rating'])); } catch (e) { syzoj.log(e); res.render('error', { err: e }); } }); app.get('/admin/other', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); res.render('admin_other'); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.get('/admin/rejudge', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); res.render('admin_rejudge', { form: {}, count: null }); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.post('/admin/other', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); if (req.body.type === 'reset_count') { const problems = await Problem.find(); for (const p of problems) { await p.resetSubmissionCount(); } } else if (req.body.type === 'reset_discussion') { const articles = await Article.find(); for (const a of articles) { await a.resetReplyCountAndTime(); } } else if (req.body.type === 'reset_codelen') { const submissions = await JudgeState.find(); for (const s of submissions) { if (s.type !== 'submit-answer') { s.code_length = Buffer.from(s.code).length; await s.save(); } } } else { throw new ErrorMessage("操作类型不正确"); } res.redirect(syzoj.utils.makeUrl(['admin', 'other'])); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.post('/admin/rejudge', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); let query = JudgeState.createQueryBuilder(); let user = await User.fromName(req.body.submitter || ''); if (user) { query.andWhere('user_id = :user_id', { user_id: user.id }); } else if (req.body.submitter) { query.andWhere('user_id = :user_id', { user_id: 0 }); } let minID = parseInt(req.body.min_id); if (!isNaN(minID)) query.andWhere('id >= :minID', { minID }) let maxID = parseInt(req.body.max_id); if (!isNaN(maxID)) query.andWhere('id <= :maxID', { maxID }) let minScore = parseInt(req.body.min_score); if (!isNaN(minScore)) query.andWhere('score >= :minScore', { minScore }); let maxScore = parseInt(req.body.max_score); if (!isNaN(maxScore)) query.andWhere('score <= :maxScore', { maxScore }); let minTime = syzoj.utils.parseDate(req.body.min_time); if (!isNaN(minTime)) query.andWhere('submit_time >= :minTime', { minTime: parseInt(minTime) }); let maxTime = syzoj.utils.parseDate(req.body.max_time); if (!isNaN(maxTime)) query.andWhere('submit_time <= :maxTime', { maxTime: parseInt(maxTime) }); if (req.body.language) { if (req.body.language === 'submit-answer') { query.andWhere(new TypeORM.Brackets(qb => { qb.orWhere('language = :language', { language: '' }) .orWhere('language IS NULL'); })); } else if (req.body.language === 'non-submit-answer') { query.andWhere('language != :language', { language: '' }) .andWhere('language IS NOT NULL');; } else { query.andWhere('language = :language', { language: req.body.language }); } } if (req.body.status) { query.andWhere('status LIKE :status', { status: req.body.status + '%' }); } if (req.body.problem_id) { query.andWhere('problem_id = :problem_id', { problem_id: parseInt(req.body.problem_id) || 0 }) } let count = await JudgeState.countQuery(query); if (req.body.type === 'rejudge') { let submissions = await JudgeState.queryAll(query); for (let submission of submissions) { await submission.rejudge(); } } res.render('admin_rejudge', { form: req.body, count: count }); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.get('/admin/links', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); res.render('admin_links', { links: syzoj.config.links || [] }); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.post('/admin/links', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); syzoj.config.links = JSON.parse(req.body.data); await syzoj.utils.saveConfig(); res.redirect(syzoj.utils.makeUrl(['admin', 'links'])); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.get('/admin/raw', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); res.render('admin_raw', { data: JSON.stringify(syzoj.config, null, 2) }); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.post('/admin/raw', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); syzoj.config = JSON.parse(req.body.data); await syzoj.utils.saveConfig(); res.redirect(syzoj.utils.makeUrl(['admin', 'raw'])); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.post('/admin/restart', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); syzoj.restart(); res.render('admin_restart', { data: JSON.stringify(syzoj.config, null, 2) }); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } }); app.get('/admin/serviceID', async (req, res) => { try { if (!res.locals.user || !res.locals.user.is_admin) throw new ErrorMessage('您没有权限进行此操作。'); res.send({ serviceID: syzoj.serviceID }); } catch (e) { syzoj.log(e); res.render('error', { err: e }) } });