Merge pull request #2131 from pateljannat/issues-195

fix: verify quiz answers on server side
This commit is contained in:
Jannat Patel
2026-02-25 16:57:05 +05:30
committed by GitHub
3 changed files with 41 additions and 26 deletions
+3 -6
View File
@@ -465,7 +465,7 @@ watch(
)
const quizSubmission = createResource({
url: 'lms.lms.doctype.lms_quiz.lms_quiz.quiz_summary',
url: 'lms.lms.doctype.lms_quiz.lms_quiz.submit_quiz',
makeParams(values) {
return {
quiz: quiz.data.name,
@@ -538,7 +538,7 @@ const checkAnswer = () => {
url: 'lms.lms.doctype.lms_quiz.lms_quiz.check_answer',
params: {
question: currentQuestion.value,
type: questionDetails.data.type,
question_type: questionDetails.data.type,
answers: JSON.stringify(answers),
},
auto: true,
@@ -569,10 +569,7 @@ const addToLocalStorage = () => {
let quizData = JSON.parse(localStorage.getItem(quiz.data.title))
let questionData = {
question_name: currentQuestion.value,
answer: getAnswers().join(),
is_correct: showAnswers.filter((answer) => {
return answer != undefined
}),
answer: getAnswers(),
}
if (quizData) {
@@ -186,6 +186,7 @@ const upcoming_evals = createListResource({
'evaluator_name',
'course_title',
'member',
'member_name',
'google_meet_link',
],
orderBy: 'date',
+37 -20
View File
@@ -101,7 +101,7 @@ def set_total_marks(questions: list) -> int:
@frappe.whitelist()
def quiz_summary(quiz: str, results: str):
def submit_quiz(quiz: str, results: str):
results = results and json.loads(results)
percentage = 0
@@ -128,14 +128,13 @@ def quiz_summary(quiz: str, results: str):
score_out_of = quiz_details.total_marks
percentage = (score / score_out_of) * 100 if score_out_of else 0
submission = create_submission(quiz, results, score_out_of, quiz_details.passing_percentage)
save_progress_after_quiz(quiz_details, percentage)
return {
"score": score,
"score_out_of": score_out_of,
"submission": submission.name,
"pass": percentage == quiz_details.passing_percentage,
"pass": percentage >= quiz_details.passing_percentage,
"percentage": percentage,
"is_open_ended": is_open_ended,
}
@@ -158,21 +157,14 @@ def process_results(results: list, quiz_details: dict):
result["marks_out_of"] = question_details.marks
if question_details.type != "Open Ended":
if len(result["is_correct"]) > 0:
correct = result["is_correct"][0]
for point in result["is_correct"]:
correct = correct and point
result["is_correct"] = correct
else:
result["is_correct"] = 0
correct = verify_answer(question_details.question, result["answer"])
result["answer"] = ", ".join(result["answer"])
if correct:
marks = question_details.marks
result["marks"] = question_details.marks
else:
marks = -quiz_details.marks_to_cut if quiz_details.enable_negative_marking else 0
result["marks"] = -quiz_details.marks_to_cut if quiz_details.enable_negative_marking else 0
result["marks"] = marks
score += marks
score += result["marks"]
else:
is_open_ended = True
@@ -188,6 +180,26 @@ def process_results(results: list, quiz_details: dict):
}
def verify_answer(question: str, answer: list):
question_details = get_question_details(question)
correct = False
if question_details.multiple:
for num in range(1, 5):
if question_details[f"option_{num}"] in answer:
correct = question_details[f"is_correct_{num}"]
if not correct:
return False
if question_details[f"is_correct_{num}"] and question_details[f"option_{num}"] not in answer:
return False
return True
for num in range(1, 5):
if question_details[f"option_{num}"] in answer:
correct = question_details[f"is_correct_{num}"]
return correct
def _save_file(match: re.Match) -> str:
data = match.group(1).split("data:")[1]
headers, content = data.split(",")
@@ -258,22 +270,27 @@ def save_progress_after_quiz(quiz_details: dict, percentage: float):
@frappe.whitelist()
def check_answer(question: str, type: str, answers: str):
answers = json.loads(answers)
if type == "Choices":
def check_answer(question: str, question_type: str, answers: str):
answers = answers and json.loads(answers)
if question_type == "Choices":
return check_choice_answers(question, answers)
else:
return check_input_answers(question, answers[0])
def check_choice_answers(question: str, answers: list):
def get_question_details(question: str):
fields = ["multiple"]
is_correct = []
for num in range(1, 5):
fields.append(f"option_{cstr(num)}")
fields.append(f"is_correct_{cstr(num)}")
question_details = frappe.db.get_value("LMS Question", question, fields, as_dict=1)
return question_details
def check_choice_answers(question: str, answers: list):
is_correct = []
question_details = get_question_details(question)
for num in range(1, 5):
if question_details[f"option_{num}"] in answers: