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; const weight = parseFloat(exercise.SCORE_WEIGHT); 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; stdExercise.RESULT_SCORE_STUDENT = correctPercentage * weight; } 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, IS_DELETED: 0, }, }); 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, IS_DELETED: 0, }, order: [ [ models.Sequelize.literal( "CAST(SUBSTRING_INDEX(TITLE, ' ', -1) AS UNSIGNED)" ), "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, IS_DELETED: 0, }, 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); } };