2024-09-13 13:03:35 +00:00
|
|
|
import models from "../models/index.js";
|
|
|
|
|
import response from "../response.js";
|
|
|
|
|
|
|
|
|
|
export const checkCorrectAnswers = async (req, res, next) => {
|
|
|
|
|
const { id } = req.params;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const stdExercises = await models.StdExercise.findAll({
|
|
|
|
|
where: { ID_STUDENT_LEARNING: id },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!stdExercises || stdExercises.length === 0) {
|
|
|
|
|
return response(404, null, "No student exercises found", res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const stdExercise of stdExercises) {
|
|
|
|
|
const { ID_ADMIN_EXERCISE, ANSWER_STUDENT } = stdExercise;
|
|
|
|
|
|
|
|
|
|
const exercise = await models.Exercise.findByPk(ID_ADMIN_EXERCISE);
|
|
|
|
|
if (!exercise) continue;
|
|
|
|
|
|
2024-09-30 01:06:15 +00:00
|
|
|
const weight = parseFloat(exercise.SCORE_WEIGHT);
|
2024-09-13 13:03:35 +00:00
|
|
|
const questionType = exercise.QUESTION_TYPE;
|
|
|
|
|
|
|
|
|
|
switch (questionType) {
|
|
|
|
|
case "MCQ": {
|
|
|
|
|
const multipleChoice = await models.MultipleChoices.findOne({
|
|
|
|
|
where: { ID_ADMIN_EXERCISE },
|
|
|
|
|
});
|
|
|
|
|
if (multipleChoice) {
|
|
|
|
|
stdExercise.IS_CORRECT =
|
|
|
|
|
ANSWER_STUDENT === multipleChoice.ANSWER_KEY ? 1 : 0;
|
|
|
|
|
stdExercise.RESULT_SCORE_STUDENT =
|
|
|
|
|
ANSWER_STUDENT === multipleChoice.ANSWER_KEY ? weight : 0.0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case "TFQ": {
|
|
|
|
|
const trueFalse = await models.TrueFalse.findOne({
|
|
|
|
|
where: { ID_ADMIN_EXERCISE },
|
|
|
|
|
});
|
|
|
|
|
if (trueFalse) {
|
|
|
|
|
const isTrueStudent = ANSWER_STUDENT === "1";
|
|
|
|
|
stdExercise.IS_CORRECT =
|
|
|
|
|
isTrueStudent === Boolean(trueFalse.IS_TRUE) ? 1 : 0;
|
|
|
|
|
stdExercise.RESULT_SCORE_STUDENT =
|
|
|
|
|
isTrueStudent === Boolean(trueFalse.IS_TRUE) ? weight : 0.0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case "MPQ": {
|
|
|
|
|
const matchingPairs = await models.MatchingPairs.findAll({
|
|
|
|
|
where: { ID_ADMIN_EXERCISE },
|
|
|
|
|
});
|
|
|
|
|
if (matchingPairs && matchingPairs.length > 0) {
|
|
|
|
|
const studentAnswers = ANSWER_STUDENT.split(",").map((pair) => {
|
|
|
|
|
const [left, right] = pair.split("-");
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
LEFT_PAIR: left ? left.trim() : "",
|
|
|
|
|
RIGHT_PAIR: right ? right.trim() : "",
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let correctCount = 0;
|
|
|
|
|
for (const studentAnswer of studentAnswers) {
|
|
|
|
|
if (
|
|
|
|
|
matchingPairs.some(
|
|
|
|
|
(pair) =>
|
|
|
|
|
pair.LEFT_PAIR === studentAnswer.LEFT_PAIR &&
|
|
|
|
|
pair.RIGHT_PAIR === studentAnswer.RIGHT_PAIR
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
correctCount++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const correctPercentage = correctCount / matchingPairs.length;
|
|
|
|
|
stdExercise.IS_CORRECT = correctCount > 0 ? 1 : 0;
|
2024-09-30 01:06:15 +00:00
|
|
|
stdExercise.RESULT_SCORE_STUDENT = correctPercentage * weight;
|
2024-09-13 13:03:35 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await stdExercise.save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
next();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error checking correct answers:", error);
|
|
|
|
|
response(500, null, "Internal Server Error", res);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const calculateScore = async (req, res, next) => {
|
|
|
|
|
const { id } = req.params;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const stdLearning = await models.StdLearning.findByPk(id);
|
|
|
|
|
|
|
|
|
|
if (!stdLearning) {
|
|
|
|
|
return response(404, null, "Student Learning record not found", res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const allExercises = await models.Exercise.findAll({
|
|
|
|
|
where: { ID_LEVEL: stdLearning.ID_LEVEL },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!allExercises || allExercises.length === 0) {
|
|
|
|
|
return response(404, null, "No exercises found for this level", res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const stdExercises = await models.StdExercise.findAll({
|
|
|
|
|
where: { ID_STUDENT_LEARNING: id },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let totalWeight = 0;
|
|
|
|
|
for (const exercise of allExercises) {
|
|
|
|
|
totalWeight += exercise.SCORE_WEIGHT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let totalScore = 0;
|
|
|
|
|
for (const stdExercise of stdExercises) {
|
|
|
|
|
const exercise = allExercises.find(
|
|
|
|
|
(ex) => ex.ID_ADMIN_EXERCISE === stdExercise.ID_ADMIN_EXERCISE
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (exercise && stdExercise.RESULT_SCORE_STUDENT !== null) {
|
|
|
|
|
totalScore += stdExercise.RESULT_SCORE_STUDENT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const finalScore = Math.round((totalScore / totalWeight) * 100);
|
|
|
|
|
|
|
|
|
|
req.body.SCORE = finalScore;
|
|
|
|
|
|
|
|
|
|
next();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.log(error);
|
|
|
|
|
response(500, null, "Internal Server Error", res);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const checkFirstFiveCorrect = async (req, res, next) => {
|
|
|
|
|
const { id } = req.params;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const stdLearning = await models.StdLearning.findByPk(id);
|
|
|
|
|
|
|
|
|
|
if (!stdLearning) {
|
|
|
|
|
return response(404, null, "Student Learning record not found", res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const firstFiveExercises = await models.Exercise.findAll({
|
|
|
|
|
where: { ID_LEVEL: stdLearning.ID_LEVEL },
|
|
|
|
|
order: [["TITLE", "ASC"]],
|
|
|
|
|
limit: 5,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!firstFiveExercises || firstFiveExercises.length < 5) {
|
|
|
|
|
return response(404, null, "Not enough exercises for this level", res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const stdExercises = await models.StdExercise.findAll({
|
|
|
|
|
where: { ID_STUDENT_LEARNING: id },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const allCorrect = firstFiveExercises.every((exercise) => {
|
|
|
|
|
const stdExercise = stdExercises.find(
|
|
|
|
|
(se) => se.ID_ADMIN_EXERCISE === exercise.ID_ADMIN_EXERCISE
|
|
|
|
|
);
|
|
|
|
|
return stdExercise && stdExercise.IS_CORRECT === 1;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
req.body.FIRST_FIVE_CORRECT = allCorrect;
|
|
|
|
|
|
|
|
|
|
next();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error checking first five correct answers:", error);
|
|
|
|
|
res.status(500).json({ message: "Internal Server Error" });
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const nextLearning = async (req, res, next) => {
|
|
|
|
|
const { SCORE, FIRST_FIVE_CORRECT } = req.body;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const stdLearning = await models.StdLearning.findByPk(req.params.id, {
|
|
|
|
|
include: [
|
|
|
|
|
{
|
|
|
|
|
model: models.Level,
|
|
|
|
|
as: "level",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!stdLearning) {
|
|
|
|
|
return response(404, null, "Student Learning record not found", res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const topic_id = stdLearning.level.ID_TOPIC;
|
|
|
|
|
|
|
|
|
|
const levels = await models.Level.findAll({
|
|
|
|
|
where: { ID_TOPIC: topic_id },
|
|
|
|
|
order: [["NAME_LEVEL", "ASC"]],
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const levelMap = levels.reduce((map, level) => {
|
|
|
|
|
map[level.NAME_LEVEL] = level;
|
|
|
|
|
return map;
|
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
|
|
let nextLearningLevel = null;
|
|
|
|
|
let currentLevelNumber = parseInt(
|
|
|
|
|
stdLearning.level.NAME_LEVEL.split(" ")[1]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (stdLearning.level.IS_PRETEST) {
|
|
|
|
|
if (SCORE >= 0 && SCORE <= 50) {
|
|
|
|
|
nextLearningLevel = levelMap["Level 1"];
|
|
|
|
|
} else if (SCORE >= 51 && SCORE <= 60) {
|
|
|
|
|
nextLearningLevel = levelMap["Level 2"];
|
|
|
|
|
} else if (SCORE >= 61 && SCORE <= 70) {
|
|
|
|
|
nextLearningLevel = levelMap["Level 3"];
|
|
|
|
|
} else if (SCORE >= 71 && SCORE <= 80) {
|
|
|
|
|
nextLearningLevel = levelMap["Level 4"];
|
|
|
|
|
} else if (SCORE >= 81 && SCORE <= 90) {
|
|
|
|
|
nextLearningLevel = levelMap["Level 5"];
|
|
|
|
|
} else if (SCORE >= 91 && SCORE <= 100) {
|
|
|
|
|
nextLearningLevel = levelMap["Level 6"];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (SCORE >= 75 && FIRST_FIVE_CORRECT) {
|
|
|
|
|
currentLevelNumber += SCORE >= 85 ? 2 : 1;
|
|
|
|
|
currentLevelNumber = Math.min(6, currentLevelNumber);
|
|
|
|
|
} else if (
|
|
|
|
|
(SCORE >= 75 && !FIRST_FIVE_CORRECT) ||
|
|
|
|
|
(SCORE >= 51 && SCORE <= 74)
|
|
|
|
|
) {
|
|
|
|
|
currentLevelNumber = currentLevelNumber;
|
|
|
|
|
} else if (SCORE >= 41 && SCORE <= 50) {
|
|
|
|
|
currentLevelNumber = Math.max(1, currentLevelNumber - 1);
|
|
|
|
|
} else if (SCORE >= 0 && SCORE <= 40) {
|
|
|
|
|
currentLevelNumber = Math.max(1, currentLevelNumber - 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentLevelNumber = Math.max(1, Math.min(6, currentLevelNumber));
|
|
|
|
|
|
|
|
|
|
nextLearningLevel = levelMap[`Level ${currentLevelNumber}`];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nextLearningLevel) {
|
|
|
|
|
return response(404, null, "Next learning level not found", res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.body.NEXT_LEARNING = nextLearningLevel.ID_LEVEL;
|
|
|
|
|
req.body.IS_PASS =
|
|
|
|
|
SCORE > 85 &&
|
|
|
|
|
stdLearning.level.NAME_LEVEL === "Level 6" &&
|
|
|
|
|
FIRST_FIVE_CORRECT
|
|
|
|
|
? 1
|
|
|
|
|
: 0;
|
|
|
|
|
|
|
|
|
|
next();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.log(error);
|
|
|
|
|
response(500, null, "Error determining next learning path", res);
|
|
|
|
|
}
|
|
|
|
|
};
|