refactor: exercise model and auto grading middleware
This commit is contained in:
parent
24cba3b988
commit
ee4f1814e4
|
|
@ -141,12 +141,32 @@ export const getExerciseById = async (req, res) => {
|
||||||
const questionType = exercise.QUESTION_TYPE;
|
const questionType = exercise.QUESTION_TYPE;
|
||||||
|
|
||||||
if (questionType === "MCQ") {
|
if (questionType === "MCQ") {
|
||||||
|
if (exerciseData.multipleChoices) {
|
||||||
|
exerciseData.multipleChoices = exerciseData.multipleChoices.map(
|
||||||
|
(choice) => {
|
||||||
|
const { ANSWER_KEY, ...rest } = choice.dataValues;
|
||||||
|
return rest;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
delete exerciseData.matchingPairs;
|
delete exerciseData.matchingPairs;
|
||||||
delete exerciseData.trueFalse;
|
delete exerciseData.trueFalse;
|
||||||
} else if (questionType === "MPQ") {
|
} else if (questionType === "MPQ") {
|
||||||
|
if (exerciseData.matchingPairs) {
|
||||||
|
exerciseData.matchingPairs = exerciseData.matchingPairs.map((pair) => {
|
||||||
|
const { LEFT_PAIR, RIGHT_PAIR, ...rest } = pair.dataValues;
|
||||||
|
return rest;
|
||||||
|
});
|
||||||
|
}
|
||||||
delete exerciseData.multipleChoices;
|
delete exerciseData.multipleChoices;
|
||||||
delete exerciseData.trueFalse;
|
delete exerciseData.trueFalse;
|
||||||
} else if (questionType === "TFQ") {
|
} else if (questionType === "TFQ") {
|
||||||
|
if (exerciseData.trueFalse) {
|
||||||
|
exerciseData.trueFalse = exerciseData.trueFalse.map((tf) => {
|
||||||
|
const { IS_TRUE, ...rest } = tf.dataValues;
|
||||||
|
return rest;
|
||||||
|
});
|
||||||
|
}
|
||||||
delete exerciseData.multipleChoices;
|
delete exerciseData.multipleChoices;
|
||||||
delete exerciseData.matchingPairs;
|
delete exerciseData.matchingPairs;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -167,7 +187,6 @@ export const getExerciseByLevelId = async (req, res) => {
|
||||||
const { idLevel } = req.params;
|
const { idLevel } = req.params;
|
||||||
|
|
||||||
const levelExists = await models.Level.findByPk(idLevel);
|
const levelExists = await models.Level.findByPk(idLevel);
|
||||||
|
|
||||||
if (!levelExists) {
|
if (!levelExists) {
|
||||||
return response(404, null, "Level not found", res);
|
return response(404, null, "Level not found", res);
|
||||||
}
|
}
|
||||||
|
|
@ -199,12 +218,34 @@ export const getExerciseByLevelId = async (req, res) => {
|
||||||
const questionType = exercise.QUESTION_TYPE;
|
const questionType = exercise.QUESTION_TYPE;
|
||||||
|
|
||||||
if (questionType === "MCQ") {
|
if (questionType === "MCQ") {
|
||||||
|
if (exerciseData.multipleChoices) {
|
||||||
|
exerciseData.multipleChoices = exerciseData.multipleChoices.map(
|
||||||
|
(choice) => {
|
||||||
|
const { ANSWER_KEY, ...rest } = choice.dataValues; // Exclude ANSWER_KEY
|
||||||
|
return rest;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
delete exerciseData.matchingPairs;
|
delete exerciseData.matchingPairs;
|
||||||
delete exerciseData.trueFalse;
|
delete exerciseData.trueFalse;
|
||||||
} else if (questionType === "MPQ") {
|
} else if (questionType === "MPQ") {
|
||||||
|
if (exerciseData.matchingPairs) {
|
||||||
|
exerciseData.matchingPairs = exerciseData.matchingPairs.map(
|
||||||
|
(pair) => {
|
||||||
|
const { LEFT_PAIR, RIGHT_PAIR, ...rest } = pair.dataValues; // Exclude LEFT_PAIR, RIGHT_PAIR
|
||||||
|
return rest;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
delete exerciseData.multipleChoices;
|
delete exerciseData.multipleChoices;
|
||||||
delete exerciseData.trueFalse;
|
delete exerciseData.trueFalse;
|
||||||
} else if (questionType === "TFQ") {
|
} else if (questionType === "TFQ") {
|
||||||
|
if (exerciseData.trueFalse) {
|
||||||
|
exerciseData.trueFalse = exerciseData.trueFalse.map((tf) => {
|
||||||
|
const { IS_TRUE, ...rest } = tf.dataValues; // Exclude IS_TRUE
|
||||||
|
return rest;
|
||||||
|
});
|
||||||
|
}
|
||||||
delete exerciseData.multipleChoices;
|
delete exerciseData.multipleChoices;
|
||||||
delete exerciseData.matchingPairs;
|
delete exerciseData.matchingPairs;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ export const getLevels = async (req, res) => {
|
||||||
export const getLevelById = async (req, res) => {
|
export const getLevelById = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
||||||
const level = await models.Level.findByPk(id, {
|
const level = await models.Level.findByPk(id, {
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: [
|
exclude: [
|
||||||
|
|
@ -47,13 +48,38 @@ export const getLevelById = async (req, res) => {
|
||||||
"ROUTE_6",
|
"ROUTE_6",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: models.Topic,
|
||||||
|
as: "levelTopic",
|
||||||
|
attributes: ["NAME_TOPIC"],
|
||||||
|
include: {
|
||||||
|
model: models.Section,
|
||||||
|
as: "topicSection",
|
||||||
|
attributes: ["NAME_SECTION"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!level) {
|
if (!level) {
|
||||||
return response(404, null, "Level not found", res);
|
return response(404, null, "Level not found", res);
|
||||||
}
|
}
|
||||||
|
|
||||||
response(200, level, "Success", res);
|
const levelJSON = level.toJSON();
|
||||||
|
const NAME_SECTION = levelJSON.levelTopic.topicSection.NAME_SECTION;
|
||||||
|
const NAME_TOPIC = levelJSON.levelTopic.NAME_TOPIC;
|
||||||
|
|
||||||
|
delete levelJSON.levelTopic;
|
||||||
|
delete levelJSON.levelTopic?.topicSection;
|
||||||
|
|
||||||
|
const responsePayload = {
|
||||||
|
NAME_SECTION,
|
||||||
|
NAME_TOPIC,
|
||||||
|
...levelJSON,
|
||||||
|
};
|
||||||
|
|
||||||
|
response(200, responsePayload, "Success", res);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
response(500, null, "Internal Server Error", res);
|
response(500, null, "Internal Server Error", res);
|
||||||
|
|
@ -65,7 +91,14 @@ export const getLevelsByTopicId = async (req, res) => {
|
||||||
const { idTopic } = req.params;
|
const { idTopic } = req.params;
|
||||||
const { ID } = req.user;
|
const { ID } = req.user;
|
||||||
|
|
||||||
const topicExists = await models.Topic.findByPk(idTopic);
|
const topicExists = await models.Topic.findByPk(idTopic, {
|
||||||
|
include: {
|
||||||
|
model: models.Section,
|
||||||
|
as: "topicSection",
|
||||||
|
attributes: ["NAME_SECTION"],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (!topicExists) {
|
if (!topicExists) {
|
||||||
return response(404, null, "Topic not found", res);
|
return response(404, null, "Topic not found", res);
|
||||||
}
|
}
|
||||||
|
|
@ -94,6 +127,16 @@ export const getLevelsByTopicId = async (req, res) => {
|
||||||
},
|
},
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
model: models.Topic,
|
||||||
|
as: "levelTopic",
|
||||||
|
attributes: ["NAME_TOPIC"],
|
||||||
|
include: {
|
||||||
|
model: models.Section,
|
||||||
|
as: "topicSection",
|
||||||
|
attributes: ["NAME_SECTION"],
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -129,9 +172,17 @@ export const getLevelsByTopicId = async (req, res) => {
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const levelJSON = level.toJSON();
|
const levelJSON = level.toJSON();
|
||||||
|
|
||||||
|
const NAME_SECTION = levelJSON.levelTopic.topicSection.NAME_SECTION;
|
||||||
|
const NAME_TOPIC = levelJSON.levelTopic.NAME_TOPIC;
|
||||||
|
|
||||||
delete levelJSON.stdLearning;
|
delete levelJSON.stdLearning;
|
||||||
|
delete levelJSON.levelTopic;
|
||||||
|
delete levelJSON.levelTopic?.topicSection;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
NAME_SECTION,
|
||||||
|
NAME_TOPIC,
|
||||||
...levelJSON,
|
...levelJSON,
|
||||||
ID_STUDENT_LEARNING,
|
ID_STUDENT_LEARNING,
|
||||||
SCORE,
|
SCORE,
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ export const getTopicBySectionId = async (req, res) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createTopic = async (req, res) => {
|
export const createTopic = async (req, res) => {
|
||||||
const { ID_SECTION, NAME_TOPIC, DESCRIPTION_TOPIC, OBJECTIVES } = req.body;
|
const { ID_SECTION, NAME_TOPIC, DESCRIPTION_TOPIC } = req.body;
|
||||||
|
|
||||||
if (!ID_SECTION) {
|
if (!ID_SECTION) {
|
||||||
return response(400, null, "Section ID is required", res);
|
return response(400, null, "Section ID is required", res);
|
||||||
|
|
@ -66,10 +66,6 @@ export const createTopic = async (req, res) => {
|
||||||
return response(400, null, "Topic description is required", res);
|
return response(400, null, "Topic description is required", res);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!OBJECTIVES) {
|
|
||||||
return response(400, null, "Topic objectives are required", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const section = await models.Section.findByPk(ID_SECTION);
|
const section = await models.Section.findByPk(ID_SECTION);
|
||||||
if (!section) {
|
if (!section) {
|
||||||
|
|
@ -80,7 +76,6 @@ export const createTopic = async (req, res) => {
|
||||||
ID_SECTION,
|
ID_SECTION,
|
||||||
NAME_TOPIC,
|
NAME_TOPIC,
|
||||||
DESCRIPTION_TOPIC,
|
DESCRIPTION_TOPIC,
|
||||||
OBJECTIVES,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
response(201, newTopic, "Topic created successfully", res);
|
response(201, newTopic, "Topic created successfully", res);
|
||||||
|
|
@ -92,7 +87,7 @@ export const createTopic = async (req, res) => {
|
||||||
|
|
||||||
export const updateTopicById = async (req, res) => {
|
export const updateTopicById = async (req, res) => {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
const { ID_SECTION, NAME_TOPIC, DESCRIPTION_TOPIC, OBJECTIVES } = req.body;
|
const { ID_SECTION, NAME_TOPIC, DESCRIPTION_TOPIC } = req.body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const topic = await models.Topic.findByPk(id);
|
const topic = await models.Topic.findByPk(id);
|
||||||
|
|
@ -117,10 +112,6 @@ export const updateTopicById = async (req, res) => {
|
||||||
topic.DESCRIPTION_TOPIC = DESCRIPTION_TOPIC;
|
topic.DESCRIPTION_TOPIC = DESCRIPTION_TOPIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OBJECTIVES) {
|
|
||||||
topic.OBJECTIVES = OBJECTIVES;
|
|
||||||
}
|
|
||||||
|
|
||||||
await topic.save();
|
await topic.save();
|
||||||
|
|
||||||
response(200, topic, "Topic updated successfully", res);
|
response(200, topic, "Topic updated successfully", res);
|
||||||
|
|
@ -171,7 +162,6 @@ export const getCompletedTopics = async (req, res) => {
|
||||||
"ID_TOPIC",
|
"ID_TOPIC",
|
||||||
"NAME_TOPIC",
|
"NAME_TOPIC",
|
||||||
"DESCRIPTION_TOPIC",
|
"DESCRIPTION_TOPIC",
|
||||||
"OBJECTIVES",
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -200,7 +190,6 @@ export const getCompletedTopics = async (req, res) => {
|
||||||
ID_TOPIC: topic.ID_TOPIC,
|
ID_TOPIC: topic.ID_TOPIC,
|
||||||
NAME_TOPIC: topic.NAME_TOPIC,
|
NAME_TOPIC: topic.NAME_TOPIC,
|
||||||
DESCRIPTION_TOPIC: topic.DESCRIPTION_TOPIC,
|
DESCRIPTION_TOPIC: topic.DESCRIPTION_TOPIC,
|
||||||
OBJECTIVES: topic.OBJECTIVES,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,14 @@ export const getStdExerciseById = async (req, res) => {
|
||||||
|
|
||||||
export const stdAnswerExercise = async (req, res, next) => {
|
export const stdAnswerExercise = async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const { ID_STUDENT_LEARNING, ID_ADMIN_EXERCISE, ANSWER_STUDENT } = req.body;
|
const { answers } = req.body;
|
||||||
|
|
||||||
|
if (!Array.isArray(answers) || answers.length === 0) {
|
||||||
|
return response(400, null, "Answers array is required", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const answer of answers) {
|
||||||
|
const { ID_STUDENT_LEARNING, ID_ADMIN_EXERCISE, ANSWER_STUDENT } = answer;
|
||||||
|
|
||||||
if (!ID_STUDENT_LEARNING) {
|
if (!ID_STUDENT_LEARNING) {
|
||||||
return response(400, null, "Id student learning is required", res);
|
return response(400, null, "Id student learning is required", res);
|
||||||
|
|
@ -69,7 +76,6 @@ export const stdAnswerExercise = async (req, res, next) => {
|
||||||
|
|
||||||
if (existingStdExercise) {
|
if (existingStdExercise) {
|
||||||
existingStdExercise.ANSWER_STUDENT = ANSWER_STUDENT;
|
existingStdExercise.ANSWER_STUDENT = ANSWER_STUDENT;
|
||||||
|
|
||||||
await existingStdExercise.save();
|
await existingStdExercise.save();
|
||||||
} else {
|
} else {
|
||||||
await models.StdExercise.create({
|
await models.StdExercise.create({
|
||||||
|
|
@ -78,8 +84,9 @@ export const stdAnswerExercise = async (req, res, next) => {
|
||||||
ANSWER_STUDENT,
|
ANSWER_STUDENT,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
req.params.id = ID_STUDENT_LEARNING;
|
req.params.id = answers[0].ID_STUDENT_LEARNING;
|
||||||
next();
|
next();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,8 @@ export const updateStudentClassByName = async (req, res) => {
|
||||||
|
|
||||||
const updateResults = [];
|
const updateResults = [];
|
||||||
let hasError = false;
|
let hasError = false;
|
||||||
|
let successCount = 0;
|
||||||
|
let failureCount = 0;
|
||||||
|
|
||||||
for (const { NAME_USERS, NISN } of STUDENTS) {
|
for (const { NAME_USERS, NISN } of STUDENTS) {
|
||||||
if (!NAME_USERS || !NISN) {
|
if (!NAME_USERS || !NISN) {
|
||||||
|
|
@ -126,6 +128,7 @@ export const updateStudentClassByName = async (req, res) => {
|
||||||
error: "User name and NISN are required for each student",
|
error: "User name and NISN are required for each student",
|
||||||
});
|
});
|
||||||
hasError = true;
|
hasError = true;
|
||||||
|
failureCount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,6 +151,7 @@ export const updateStudentClassByName = async (req, res) => {
|
||||||
error: "Student with the given name and NISN not found",
|
error: "Student with the given name and NISN not found",
|
||||||
});
|
});
|
||||||
hasError = true;
|
hasError = true;
|
||||||
|
failureCount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,6 +162,7 @@ export const updateStudentClassByName = async (req, res) => {
|
||||||
error: "Student is already in the selected class",
|
error: "Student is already in the selected class",
|
||||||
});
|
});
|
||||||
hasError = true;
|
hasError = true;
|
||||||
|
failureCount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,6 +202,8 @@ export const updateStudentClassByName = async (req, res) => {
|
||||||
"Student's class and related monitoring updated successfully",
|
"Student's class and related monitoring updated successfully",
|
||||||
studentUpdateResults,
|
studentUpdateResults,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
successCount++;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error processing student:", error.message);
|
console.error("Error processing student:", error.message);
|
||||||
updateResults.push({
|
updateResults.push({
|
||||||
|
|
@ -206,24 +213,22 @@ export const updateStudentClassByName = async (req, res) => {
|
||||||
details: error.message,
|
details: error.message,
|
||||||
});
|
});
|
||||||
hasError = true;
|
hasError = true;
|
||||||
|
failureCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasError) {
|
let responseMessage = "";
|
||||||
return response(
|
|
||||||
400,
|
if (failureCount === STUDENTS.length) {
|
||||||
{ updateResults },
|
responseMessage = "Failed to update all students.";
|
||||||
"Some students could not be updated due to errors",
|
} else if (successCount > 0 && failureCount > 0) {
|
||||||
res
|
responseMessage =
|
||||||
);
|
"Some students updated successfully, but there were errors with others.";
|
||||||
} else {
|
} else if (successCount === STUDENTS.length) {
|
||||||
return response(
|
responseMessage = "All students updated successfully.";
|
||||||
200,
|
|
||||||
{ updateResults },
|
|
||||||
"Students classes updated successfully",
|
|
||||||
res
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return response(200, { updateResults }, responseMessage, res);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
response(500, null, "Internal Server Error", res);
|
response(500, null, "Internal Server Error", res);
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,13 @@ export const getStudents = async (req, res) => {
|
||||||
model: models.Student,
|
model: models.Student,
|
||||||
as: "students",
|
as: "students",
|
||||||
attributes: ["NISN"],
|
attributes: ["NISN"],
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: models.Class,
|
||||||
|
as: "studentClass",
|
||||||
|
attributes: ["NAME_CLASS"],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
raw: true,
|
raw: true,
|
||||||
|
|
@ -115,6 +122,7 @@ export const getStudents = async (req, res) => {
|
||||||
NAME_USERS: student.NAME_USERS,
|
NAME_USERS: student.NAME_USERS,
|
||||||
EMAIL: student.EMAIL,
|
EMAIL: student.EMAIL,
|
||||||
NISN: student.students.NISN,
|
NISN: student.students.NISN,
|
||||||
|
NAME_CLASS: student.students.studentClass.NAME_CLASS,
|
||||||
ROLE: student.ROLE,
|
ROLE: student.ROLE,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
@ -125,6 +133,50 @@ export const getStudents = async (req, res) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getStudentsWithNoClass = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const studentsWithoutClass = await models.User.findAll({
|
||||||
|
where: {
|
||||||
|
ROLE: "student",
|
||||||
|
},
|
||||||
|
attributes: ["ID", "NAME_USERS", "EMAIL", "ROLE"],
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: models.Student,
|
||||||
|
as: "students",
|
||||||
|
attributes: ["NISN", "ID_CLASS"],
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: models.Class,
|
||||||
|
as: "studentClass",
|
||||||
|
attributes: ["NAME_CLASS"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
where: {
|
||||||
|
ID_CLASS: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
raw: true,
|
||||||
|
nest: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const formattedStudents = studentsWithoutClass.map((student) => ({
|
||||||
|
ID: student.ID,
|
||||||
|
NAME_USERS: student.NAME_USERS,
|
||||||
|
EMAIL: student.EMAIL,
|
||||||
|
NISN: student.students.NISN,
|
||||||
|
NAME_CLASS: student.students.studentClass.NAME_CLASS,
|
||||||
|
ROLE: student.ROLE,
|
||||||
|
}));
|
||||||
|
|
||||||
|
response(200, formattedStudents, "Success", res);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
response(500, null, "Error retrieving students with no class", res);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const getUserById = async (req, res) => {
|
export const getUserById = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export const checkCorrectAnswers = async (req, res, next) => {
|
||||||
const exercise = await models.Exercise.findByPk(ID_ADMIN_EXERCISE);
|
const exercise = await models.Exercise.findByPk(ID_ADMIN_EXERCISE);
|
||||||
if (!exercise) continue;
|
if (!exercise) continue;
|
||||||
|
|
||||||
const weight = parseFloat(exercise.SCORE_WEIGHT); // Ensure weight is a float
|
const weight = parseFloat(exercise.SCORE_WEIGHT);
|
||||||
const questionType = exercise.QUESTION_TYPE;
|
const questionType = exercise.QUESTION_TYPE;
|
||||||
|
|
||||||
switch (questionType) {
|
switch (questionType) {
|
||||||
|
|
@ -79,7 +79,7 @@ export const checkCorrectAnswers = async (req, res, next) => {
|
||||||
|
|
||||||
const correctPercentage = correctCount / matchingPairs.length;
|
const correctPercentage = correctCount / matchingPairs.length;
|
||||||
stdExercise.IS_CORRECT = correctCount > 0 ? 1 : 0;
|
stdExercise.IS_CORRECT = correctCount > 0 ? 1 : 0;
|
||||||
stdExercise.RESULT_SCORE_STUDENT = correctPercentage * weight; // Use float arithmetic
|
stdExercise.RESULT_SCORE_STUDENT = correctPercentage * weight;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,13 +37,6 @@ const TopicModel = (DataTypes) => {
|
||||||
notEmpty: true,
|
notEmpty: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
OBJECTIVES: {
|
|
||||||
type: DataTypes.STRING(1024),
|
|
||||||
allowNull: false,
|
|
||||||
validate: {
|
|
||||||
notEmpty: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
TIME_TOPIC: {
|
TIME_TOPIC: {
|
||||||
type: DataTypes.DATE,
|
type: DataTypes.DATE,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ const ClassModel = (DataTypes) => {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
},
|
},
|
||||||
TIME_REPORT: {
|
TIME_CLASS: {
|
||||||
type: DataTypes.DATE,
|
type: DataTypes.DATE,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
defaultValue: DataTypes.NOW,
|
defaultValue: DataTypes.NOW,
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,17 @@ const StudentModel = (DataTypes) => {
|
||||||
notEmpty: true,
|
notEmpty: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ID_CLASS: {
|
||||||
|
type: DataTypes.UUID,
|
||||||
|
allowNull: false,
|
||||||
|
validate: {
|
||||||
|
notEmpty: true,
|
||||||
|
},
|
||||||
|
references: {
|
||||||
|
model: "class",
|
||||||
|
key: "ID_CLASS",
|
||||||
|
},
|
||||||
|
},
|
||||||
ID: {
|
ID: {
|
||||||
type: DataTypes.UUID,
|
type: DataTypes.UUID,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
|
|
||||||
BIN
public/uploads/avatar/user-0d4423b278e286084768458758c5d8f3.jpg
Normal file
BIN
public/uploads/avatar/user-0d4423b278e286084768458758c5d8f3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 MiB |
|
|
@ -2,7 +2,7 @@ import express from "express";
|
||||||
import { getStdExercises, getStdExerciseById, stdAnswerExercise } from "../../controllers/learningControllers/stdExercise.js";
|
import { getStdExercises, getStdExerciseById, stdAnswerExercise } from "../../controllers/learningControllers/stdExercise.js";
|
||||||
import { verifyLoginUser } from "../../middlewares/User/authUser.js";
|
import { verifyLoginUser } from "../../middlewares/User/authUser.js";
|
||||||
import { updateStdLearningById } from "../../controllers/learningControllers/stdLearning.js";
|
import { updateStdLearningById } from "../../controllers/learningControllers/stdLearning.js";
|
||||||
import { checkCorrectAnswers,calculateScore, checkFirstFiveCorrect, nextLearning } from "../../middlewares/autoGrading.js";
|
import { checkCorrectAnswers, calculateScore, checkFirstFiveCorrect, nextLearning } from "../../middlewares/autoGrading.js";
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import { getUsers, getAdmins, getTeachers, getStudents, getUserById, getUserByName, updateUserById, updateUserPasswordById, deleteUserById, getMe } from "../../controllers/usersControllers/user.js";
|
import { getUsers, getAdmins, getTeachers, getStudents, getStudentsWithNoClass, getUserById, getUserByName, updateUserById, updateUserPasswordById, deleteUserById, getMe } from "../../controllers/usersControllers/user.js";
|
||||||
import { verifyLoginUser, adminOnly, adminOrTeacherOnly } from "../../middlewares/User/authUser.js";
|
import { verifyLoginUser, adminOnly, adminOrTeacherOnly } from "../../middlewares/User/authUser.js";
|
||||||
import handleUpload from "../../middlewares/User/uploadUser.js";
|
import handleUpload from "../../middlewares/User/uploadUser.js";
|
||||||
|
|
||||||
|
|
@ -14,6 +14,8 @@ router.get("/user/teacher", verifyLoginUser, adminOnly, getTeachers);
|
||||||
|
|
||||||
router.get("/user/student", verifyLoginUser, adminOrTeacherOnly, getStudents);
|
router.get("/user/student", verifyLoginUser, adminOrTeacherOnly, getStudents);
|
||||||
|
|
||||||
|
router.get("/user/student/unassigned", verifyLoginUser, adminOrTeacherOnly, getStudentsWithNoClass);
|
||||||
|
|
||||||
router.get("/user/:id", verifyLoginUser, getUserById);
|
router.get("/user/:id", verifyLoginUser, getUserById);
|
||||||
|
|
||||||
router.get("/user/name/:name", verifyLoginUser, adminOrTeacherOnly, getUserByName);
|
router.get("/user/name/:name", verifyLoginUser, adminOrTeacherOnly, getUserByName);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user