算法评测平台前端。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

413 lines
15 KiB

let Classify = syzoj.model('classify');
let JudgeState = syzoj.model('judge_state');
let Problem = syzoj.model('problem');
let CToP = syzoj.model('classify_to_problem');
let Article = syzoj.model('article');
let User = syzoj.model('user');
let UToP = syzoj.model('user_to_practice');
app.get('/practice', async (req, res) => {
if (!res.locals.user) {
res.render('error', {
err: new ErrorMessage('请先登录。')
});
} else {
async function getUserInfo(userId) {
let userQuery = await User.createQueryBuilder();
const currentUserInfo = await userQuery.where("id = :id", { id: userId }).getOne();
return currentUserInfo.current_p_id;
}
try {
let classifyQuery = Classify.createQueryBuilder();
let utopQuery = UToP.createQueryBuilder();
let result = await Classify.queryAll(classifyQuery);
let userQuery = await User.createQueryBuilder();
const userId = res.locals.user.id;
let currentPId = await getUserInfo(userId);
const unFinishedIdArray = [];
if (!currentPId) {
// 用户第一次进入练习板块
await userQuery.update(User).set({current_p_id: 1}).where("id = :id", { id:userId }).execute();
currentPId = 1;
await result.forEachAsync(async resultItem => {
const c_id = resultItem.id;
let utopInfo = await utopQuery.where('c_id=:c_id',{c_id}).andWhere('u_id=:u_id',{u_id:userId}).andWhere("is_finished=1").getMany();
resultItem.ac_num = utopInfo.length || 0;
});
} else {
await result.forEachAsync(async resultItem => {
const c_id = resultItem.id;
let utopInfo = await utopQuery.where('c_id=:c_id',{c_id}).andWhere('u_id=:u_id',{u_id:userId}).andWhere("is_finished=1").getMany();
let ctopQuery = CToP.createQueryBuilder();
const classifyProblems = await ctopQuery.where("c_id = :id", { id:resultItem.id }).getMany();
const classifyProblemsArr = classifyProblems.map(item => item.p_id);
const utopInfoArr = utopInfo.map(item => item.p_id);
const restArr = classifyProblemsArr.filter(item => !utopInfoArr.includes(item));
// 当前阶段里已经练习的题目的数量
const currentPassProblemNum = classifyProblemsArr.filter(item => utopInfoArr.includes(item));
resultItem.ac_num = currentPassProblemNum.length || 0;
if (restArr.length === 0) {
currentPId = resultItem.order + 1
await userQuery.update(User).set({current_p_id: currentPId}).where("id = :id", { id:userId }).execute();
} else {
unFinishedIdArray.push(resultItem.order);
}
});
}
if (unFinishedIdArray.length !== 0) {
const minOrder = Math.min.apply(null,unFinishedIdArray);
currentPId = minOrder;
await userQuery.update(User).set({current_p_id: minOrder}).where("id = :id", { id:userId }).execute();
}
result.sort(function(a,b) {
return a.order - b.order;
});
result.forEach(function(item) {
if (item.order <= currentPId) {
item.href = `/practice/classify/${item.id}`;
}
item.isNow = item.order === currentPId;
});
res.render('practice', {
user:res.locals.user,
result
})
} catch (e) {
syzoj.log(e);
res.render('error', {
err: e
});
}
}
});
app.get('/practice/classify/:cid/problem/:pid', async (req, res) => {
try {
let id = parseInt(req.params.pid);
let cid = parseInt(req.params.cid);
let problem = await Problem.findById(id);
if (!problem) throw new ErrorMessage('无此题目。');
if (!await problem.isAllowedUseBy(res.locals.user)) {
throw new ErrorMessage('您没有权限进行此操作。');
}
problem.allowedEdit = await problem.isAllowedEditBy(res.locals.user);
problem.allowedManage = await problem.isAllowedManageBy(res.locals.user);
if (problem.is_public || problem.allowedEdit) {
await syzoj.utils.markdown(problem, ['description', 'input_format', 'output_format', 'example', 'limit_and_hint']);
} else {
throw new ErrorMessage('您没有权限进行此操作。');
}
let state = await problem.getJudgeState(res.locals.user, false);
problem.tags = await problem.getTags();
await problem.loadRelationships();
let testcases = await syzoj.utils.parseTestdata(problem.getTestdataPath(), problem.type === 'submit-answer');
let discussionCount = await Article.count({ problem_id: id });
res.render('practice_problem', {
problem: problem,
state: state,
lastLanguage: res.locals.user ? await res.locals.user.getLastSubmitLanguage() : null,
testcases: testcases,
discussionCount: discussionCount,
pid: id,
cid
});
} catch (e) {
syzoj.log(e);
res.render('error', {
err: e
});
}
});
app.get('/practice/classify/:id', async (req, res) => {
try {
const c_id = parseInt(req.params.id);
const u_id = res.locals.user.id;
let ctopQuery = CToP.createQueryBuilder();
let query = await Problem.createQueryBuilder();
let utopQuery = UToP.createQueryBuilder();
let problemArray = await ctopQuery.where("c_id = :id", { id:c_id }).getMany();
let utopResult = await utopQuery.where("c_id = :c_id", { c_id }).andWhere("u_id=:u_id", {u_id}).getMany();
let problems = await problemArray.mapAsync(async problemArrayInfo => query.where('id=:id', {id: problemArrayInfo.p_id}).getOne());
problems.forEach(function(problemItem) {
const obj = utopResult.find(function(item){return parseInt(item.p_id) === parseInt(problemItem.id)});
problemItem.href = `/practice/classify/${c_id}/problem/${problemItem.id}`;
if (obj) {
problemItem.statusStr = obj.is_practice && obj.is_finished ? '已练习且已通过' : '已练习但未通过';
} else {
problemItem.statusStr = '尚未练习'
}
});
problems.sort(function(a, b){
return a.id - b.id;
})
res.render('practice_classify', {
user:res.locals.user,
problems
})
} catch (e) {
syzoj.log(e);
res.render('error', {
err: e
});
}
});
app.get('/api/practice/classify/:id', async (req, res) => {
try {
let id = parseInt(req.params.id);
let query = await Classify.createQueryBuilder();
let classifyInfo = await query.where('id=:id',{id}).getOne();
let problem = await CToP.queryBy({c_id: id});
res.send({ classifyInfo, problem:problem.map(function(item){return item.p_id}) });
} catch(e) {
res.send({ error_code: e.errno, error_msg: '失败' });
}
});
app.get('/api/pass/:cid/:pid/:sid',async (req, res) => {
try {
const c_id = parseInt(req.params.cid);
const p_id = parseInt(req.params.pid);
const u_id = res.locals.user.id;
const s_id = parseInt(req.params.sid);
let utopQuery = UToP.createQueryBuilder();
let query = Classify.createQueryBuilder();
let userQuery = User.createQueryBuilder();
let judgeStateQuery = JudgeState.createQueryBuilder();
let classify = await Classify.queryAll(query);
classify.sort(function(a,b) {
return a.order - b.order;
});
let utopResult = await utopQuery.where("c_id = :c_id", { c_id }).andWhere("u_id=:u_id", {u_id}).andWhere("p_id=:p_id", {p_id}).getOne();
// 查询到结果了
if (utopResult ) {
// mock答题通过了
await utopQuery.update(UToP).set({is_finished: 1, practice_num: utopResult.practice_num + 1}).where("c_id = :c_id", { c_id }).andWhere("u_id=:u_id", {u_id}).andWhere("p_id=:p_id", {p_id}).execute();
// 说明两个题都练习过了
} else {
let utop = await UToP.create({
u_id,
c_id,
p_id,
s_id,
is_practice: 1,
is_finished: 1,
practice_num: 1
});
await utop.save();
}
let newutopQuery = UToP.createQueryBuilder();
let userACArray = await newutopQuery.select("p_id").where('u_id=:u_id',{u_id}).andWhere("is_finished=1").getRawMany();
if (syzoj.config.practice_rating) {
const scoreArray = await judgeStateQuery.select("score").addSelect("problem_id").where("user_id=:u_id",{u_id}).andWhere("type=2").andWhere("score>=100").getRawMany();
let newScore = 0;
if (scoreArray && scoreArray.length !== 0) {
let num = 0;
for(let i=0;i<userACArray.length;i++){
const problem_id = userACArray[i].p_id;
const item = scoreArray.find(item => item.problem_id === problem_id)
num+=parseInt(item.score);
}
newScore = num - userACArray.length * 100;
}
const originRating = syzoj.config.default.user.rating;
const newRating = originRating + newScore;
await userQuery.update(User).set({rating: newRating}).where('id=:u_id',{u_id}).execute();
res.send({newRating: newRating});
}
} catch(e) {
console.log(e);
res.send({ error_code: e.errno, error_msg: '练习失败,请稍后重试' });
}
});
app.get('/api/nopass/:cid/:pid/:sid',async (req, res) => {
try {
const c_id = parseInt(req.params.cid);
const p_id = parseInt(req.params.pid);
const u_id = res.locals.user.id;
const s_id = parseInt(req.params.sid);
let utopQuery = UToP.createQueryBuilder();
let query = Classify.createQueryBuilder();
let utopResult = await utopQuery.where("c_id = :c_id", { c_id }).andWhere("u_id=:u_id", {u_id}).andWhere("p_id=:p_id", {p_id}).getOne();
// 查询到结果了
if (utopResult) {
// mock答题通过了
await utopQuery.update(UToP).set({is_practice:1, is_finished: 0, practice_num: utopResult.practice_num + 1}).where("c_id = :c_id", { c_id }).andWhere("u_id=:u_id", {u_id}).andWhere("p_id=:p_id", {p_id}).execute();
// 说明两个题都练习过了
} else {
let utop = await UToP.create({
u_id,
c_id,
p_id,
s_id,
is_practice: 1,
practice_num: 1,
is_finished: 0
});
await utop.save();
}
res.send();
} catch(e) {
res.send({ error_code: e.errno, error_msg: '练习失败,请稍后重试' });
}
});
app.put('/api/practice/classify/update/:id', async (req, res) => {
try {
let id = parseInt(req.params.id);
let u_id = parseInt(res.locals.user.id);
let utopQuery = UToP.createQueryBuilder();
let classifyQuery = await Classify.createQueryBuilder();
let ctopQuery = await CToP.createQueryBuilder();
const {name, intro, problemIdArray, order} = req.body;
let classifyInfo = await classifyQuery.where('id=:id',{id}).getOne();
// 新增题
if (problemIdArray.length > classifyInfo.problem_num) {
/*
* 把当前练习的阶段设置为新增题的阶段,因为新增题后,当前阶段的题目就没答完。
* */
}
// 删除题
if (problemIdArray.length < classifyInfo.problem_num) {
// 1。找出两个数组的差异
function findDifference(source, target){
const parseIntTarget = target.map(function(item){
return parseInt(item);
})
return source.filter(function(item){
return !parseIntTarget.includes(item);
})
}
let ctopInfo = await ctopQuery.where('c_id=:id',{id}).getMany();
const targetArray = ctopInfo.map(function(ctopInfoItem){
return ctopInfoItem.p_id;
})
// 2.从utop表里清除被删除题目的练习记录
const differenceArray = findDifference(targetArray, problemIdArray);
differenceArray.forEachAsync(async differenceItem => {
await utopQuery.delete().from(UToP).where("c_id = :id", { id }).andWhere("u_id=:u_id",{u_id}).andWhere("p_id=:p_id",{p_id:differenceItem}).execute();
})
}
let updateClassifyInfo = await classifyQuery.update(Classify).set({name, intro, order, problem_num: problemIdArray.length}).where("id = :id", { id }).execute();
await ctopQuery.delete().from(CToP).where("c_id = :id", { id }).execute();
problemIdArray.forEach(async function (item) {
let ctop = await CToP.create({
c_id: id,
p_id: item
});
await ctop.save();
})
res.send({ updateClassifyInfo });
} catch(e) {
res.send({ error_code: e.errno, error_msg: '失败' });
}
});
app.get('/api/pagination/allproblem', async (req, res) => {
try {
let query = await Problem.createQueryBuilder();
let problemInfo = await query.select('id').addSelect('title').getRawMany();
res.send({ problemInfo});
} catch(e) {
res.send({ error_code: e.errno, error_msg: '失败' });
}
});
app.get('/api/pagination', async (req, res) => {
let pagesize = parseInt(req.query.pagesize);
let page = parseInt(req.query.page);
try {
let query = await Problem.createQueryBuilder();
let problemInfo = await query.limit(pagesize).offset(pagesize*page).getMany();
res.send({ problemInfo});
} catch(e) {
res.send({ error_code: e.errno, error_msg: '失败' });
}
});
app.get('/api/getProblem/:id', async (req, res) => {
let id = parseInt(req.params.id);
try {
let query = await Problem.createQueryBuilder();
let problemInfo = await query.where('id=:id', {id}).getOne()
res.send({ problemInfo});
} catch(e) {
res.send({ error_code: e.errno, error_msg: '失败' });
}
});
app.get('/api/practice/all', async (req, res) => {
try {
let classifyQuery = Classify.createQueryBuilder();
let ctopQuery = CToP.createQueryBuilder();
let result = await Classify.queryAll(classifyQuery);
result.sort(function(a,b) {
return a.order - b.order;
})
let problem = await CToP.queryAll(ctopQuery);
res.send({ result, problem});
} catch(e) {
res.send({ error_code: e.errno, error_msg: '失败' });
}
});
app.get('/api/admin/practice/all', async (req, res) => {
try {
let classifyQuery = Classify.createQueryBuilder();
let result = await Classify.queryAll(classifyQuery);
res.send({ result });
} catch(e) {
res.send({ error_code: e.errno, error_msg: '失败' });
}
});
app.post('/api/practice/create', async (req, res) => {
try {
const {name, intro, problemIdArray, order} = req.body;
let classify = await Classify.create({
name,
intro,
order,
problem_num: problemIdArray.length || 0,
updateTime: parseInt((new Date()).getTime() / 1000, 10),
createTime: parseInt((new Date()).getTime() / 1000)
});
await classify.save();
let query = Classify.createQueryBuilder();
let recordArray = await Classify.queryAll(query);
let lastRecordId = recordArray[recordArray.length - 1].id;
problemIdArray.forEach(async function (item) {
let ctop = await CToP.create({
c_id: lastRecordId,
p_id: item
})
await ctop.save();
})
res.send();
} catch(e) {
res.send({ error_code: e.errno, error_msg: '创建失败' });
}
});
app.get('/api/problem/all', async (req, res) => {
try {
let query = Problem.createQueryBuilder();
let result = await Problem.querySomeColumn(query);
res.send({ result });
} catch(e) {
res.send({ error_code: e.errno, error_msg: '失败' });
}
});