Files
bd-contest/app/service/Exam.js
2026-06-04 10:39:14 +08:00

243 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
const Service = require('../core/base_service');
const { Op } = require('sequelize');
const fileName = "Exam";
class ExamService extends Service {
// 学生获取历史消息
async getHistoryMsg(uid, body) {
const { ctx } = this;
try {
let { offset, limit, searchOptions, sortOptions } = body;
offset = (offset - 1) * limit;
let attributes = ['id', 'card_id', 'encode_type', 'msg_data', 'created_at'],
where = { user_uid: uid }, order = [], dbOptions, joinSubstring = [],
substring = ['card_id', 'msg_data'], key = ['encode_type'], between = ['created_at'];
attributes.forEach(element => {
if (searchOptions[element]) {
if (searchOptions[element] == '*空') {
if (joinSubstring.includes(element)) {
where[element] = null;
} else {
where[element] = [null, ''];
}
} else if (substring.includes(element)) {
where[element] = { [Op.substring]: searchOptions[element] };
} else if (key.includes(element)) {
where[element] = searchOptions[element] == "1" ? true : false;
} else if (between.includes(element)) {
where[element] = { [Op.between]: [searchOptions[element][0], searchOptions[element][1]] };
}
}
if (sortOptions[element] == true) {
order.push([element, 'ASC']);
} else if (sortOptions[element] == false) {
order.push([element, 'DESC']);
}
});
dbOptions = { attributes, offset, limit, where, order };
const result = await ctx.model4.TShortMsg.findAndCountAll(dbOptions);
return result.rows.length == 0 ? false : result;
} catch (error) {
const blockName = fileName + "--" + "getHistoryMsg";
ctx.app.middleware.log('../../serviceLog', blockName + ">>>>" + error);
return 'error';
}
}
// 学生删除历史消息
async delHistoryMsg(uid, modelType, password, requestMsg) {
const { ctx } = this;
try {
const result = await ctx.model4.Account.findOne({ where: { uid } });
if (!result || result.dataValues.password !== this.shaForm(password, this.decryptRequest(result.dataValues.salt))) return false;
let where = {};
if (modelType == "single") {
const { card_id, encode_type, msg_data, origin_time } = requestMsg;
where = { user_uid: uid, card_id, encode_type, msg_data, created_at: origin_time };
} else if (modelType == "multiple") {
let card_id = [], encode_type = [], msg_data = [], created_at = [];
for (const key in requestMsg) {
requestMsg[key].forEach(element => {
card_id.push(element.card_id),
encode_type.push(element.encode_type),
msg_data.push(element.msg_data),
created_at.push(element.origin_time)
});
}
where = { user_uid: uid, card_id, encode_type, msg_data, created_at };
} else if (modelType == "all") {
where = { user_uid: uid };
}
const resetList = await ctx.model4.TShortMsg.destroy({ where });
return resetList == 0 ? false : resetList;
} catch (error) {
const blockName = fileName + "--" + "delHistoryMsg";
ctx.app.middleware.utils.log('../../../serviceLog', blockName + ">>>>" + error);
return 'error';
}
}
// 学生完成答题
async answer(uid, body) {
const { ctx } = this;
try {
// 根据 updated_at 来判断是否已经完成过答题,确保只能提交一次答题,如果已经完成答题则不允许再次提交答案
const userExam = await ctx.model4.Examination.findOne({ attributes: ['topic1', 'topic2', 'topic3', 'topic5'], where: { user_uid: uid, updated_at: null } });
if (!userExam) return false;
// 根据答案进行评分
const shortMsg = await ctx.model4.TShortMsg.findAll({ attributes: ['id', 'msg_data'], where: { user_uid: uid } });
if (shortMsg.length == 0) return false;
const { answer1, answer2, answer3, answer4, answer5 } = body;
const answerObj = {};
const answerArr = [answer1, answer2, answer3, answer4, answer5];
shortMsg.forEach(element => {
if (element.dataValues.id == answer1) {
if (element.dataValues.msg_data.length > 2) {
answerObj.answer1 = element.dataValues.msg_data.slice(0, 2);
} else {
answerObj.answer1 = element.dataValues.msg_data;
}
}
if (element.dataValues.id == answer2) {
if (element.dataValues.msg_data.length > 2) {
answerObj.answer2 = element.dataValues.msg_data.slice(0, 2);
} else {
answerObj.answer2 = element.dataValues.msg_data;
}
}
if (element.dataValues.id == answer3) {
if (element.dataValues.msg_data.length > 10) {
answerObj.answer3 = element.dataValues.msg_data.slice(0, 10);
} else {
answerObj.answer3 = element.dataValues.msg_data;
}
}
if (element.dataValues.id == answer4) {
if (element.dataValues.msg_data.length > 20) {
answerObj.answer4 = element.dataValues.msg_data.slice(0, 20);
} else {
answerObj.answer4 = element.dataValues.msg_data;
}
}
if (element.dataValues.id == answer5) {
if (element.dataValues.msg_data.length > 10) {
answerObj.answer5 = element.dataValues.msg_data.slice(0, 10);
} else {
answerObj.answer5 = element.dataValues.msg_data;
}
}
});
let score = 0;
let scoreCollection = [];
if (this.toHalfWidth(answerObj.answer1) == userExam.dataValues.topic1) {
score = score + 1;
scoreCollection.push(1);
} else {
scoreCollection.push(0);
}
if (this.toHalfWidth(answerObj.answer2) == userExam.dataValues.topic2) {
score = score + 1;
scoreCollection.push(1);
} else{
scoreCollection.push(0);
}
let topic3Arr = userExam.dataValues.topic3.split(",");
const radioAnswer = await ctx.model4.ChoiceTopic.findAll({ attributes: ['id', 'answer'], where: { id: topic3Arr } });
if (radioAnswer.length == 0) return false;
let answer3Str = "";
const radioAnswerObj = {};
radioAnswer.forEach(item => {
radioAnswerObj[item.dataValues.id] = item.dataValues.answer;
});
topic3Arr.forEach(element => {
answer3Str = answer3Str + radioAnswerObj[element];
});
if (this.toHalfWidth(answerObj.answer3) == answer3Str) {
score = score + 3;
scoreCollection.push(1);
} else {
scoreCollection.push(0);
}
if (this.toHalfWidth(answerObj.answer4).length == 17) {
const longitude = parseFloat(this.toHalfWidth(answerObj.answer4).slice(0, 3) + "." + this.toHalfWidth(answerObj.answer4).slice(3, 9));
const latitude = parseFloat(this.toHalfWidth(answerObj.answer4).slice(9, 11) + "." + this.toHalfWidth(answerObj.answer4).slice(11));
if (-180 <= longitude && longitude <= 180 && -90 <= latitude && latitude <= 90) {
score = score + 3;
scoreCollection.push(1);
} else {
scoreCollection.push(0);
}
}
if (this.toHalfWidth(answerObj.answer5) == userExam.dataValues.topic5) {
score = score + 2;
scoreCollection.push(1);
} else {
scoreCollection.push(0);
}
const updateMsg = {
answer: answerArr.join(","),
answer1: answerObj.answer1,
answer2: answerObj.answer2,
answer3: answerObj.answer3,
answer4: answerObj.answer4,
answer5: answerObj.answer5,
score,
score_collection: scoreCollection.join(","),
updated_at: new Date(),
};
const result = await ctx.model4.Examination.update(updateMsg, { where: { user_uid: uid, updated_at: null } });
return !result[0] == 0;
} catch (error) {
const blockName = fileName + "--" + "answer";
ctx.app.middleware.log('../../serviceLog', blockName + ">>>>" + error);
return 'error';
}
}
// 学生查看成绩信息
async grades(uid) {
const { ctx } = this;
try {
let include = [{
model: ctx.model4.Account,
attributes: ['account_name'],
}];
ctx.model4.Examination.belongsTo(ctx.model4.Account, { foreignKey: 'user_uid', targetKey: 'uid' });
const userExam = await ctx.model4.Examination.findOne({
attributes: ['score', 'score_collection', 'created_at', 'updated_at'],
where: { user_uid: uid, updated_at: { [Op.ne]: null } },
include
});
if (!userExam) return false;
// 查找得分比当前得分高的数据数目
const higherScoresCount = await ctx.model4.Examination.findAndCountAll({
where: {
score: { [Op.gt]: userExam.dataValues.score },
updated_at: { [Op.ne]: null }
}
});
// 查找相同得分的所有数据
const sameScores = await ctx.model4.Examination.findAndCountAll({
where: {
score: userExam.dataValues.score,
created_at: { [Op.lt]: userExam.dataValues.created_at },
updated_at: { [Op.ne]: null }
}
});
// 计算总排名(比当前得分高的数目 + 相同得分的数目 + 1(当前用户自己))
const totalRank = higherScoresCount.count + sameScores.count + 1;
userExam.dataValues.totalRank = totalRank;
return userExam;
} catch (error) {
const blockName = fileName + "--" + "grades";
ctx.app.middleware.log('../../serviceLog', blockName + ">>>>" + error);
return 'error';
}
}
}
module.exports = ExamService;