feat: quiz validations and marks

This commit is contained in:
Jannat Patel
2023-10-16 19:52:36 +05:30
parent 174ea1ddd4
commit 12bec14c92
10 changed files with 140 additions and 47 deletions

View File

@@ -32,11 +32,11 @@
"column_break_lknb", "column_break_lknb",
"explanation_4", "explanation_4",
"section_break_hkfe", "section_break_hkfe",
"possible_answer_1", "possibility_1",
"possible_answer_3", "possibility_3",
"column_break_wpjr", "column_break_wpjr",
"possible_answer_2", "possibility_2",
"possible_answer_4" "possibility_4"
], ],
"fields": [ "fields": [
{ {
@@ -167,34 +167,34 @@
"fieldtype": "Section Break" "fieldtype": "Section Break"
}, },
{ {
"fieldname": "possible_answer_1", "fieldname": "column_break_wpjr",
"fieldtype": "Column Break"
},
{
"fieldname": "possibility_1",
"fieldtype": "Small Text", "fieldtype": "Small Text",
"label": "Possible Answer 1", "label": "Possible Answer 1",
"mandatory_depends_on": "eval: doc.type == 'User Input'" "mandatory_depends_on": "eval: doc.type == 'User Input'"
}, },
{ {
"fieldname": "possible_answer_3", "fieldname": "possibility_3",
"fieldtype": "Small Text", "fieldtype": "Small Text",
"label": "Possible Answer 3" "label": "Possible Answer 3"
}, },
{ {
"fieldname": "column_break_wpjr", "fieldname": "possibility_2",
"fieldtype": "Column Break"
},
{
"fieldname": "possible_answer_2",
"fieldtype": "Small Text", "fieldtype": "Small Text",
"label": "Possible Answer 2" "label": "Possible Answer 2"
}, },
{ {
"fieldname": "possible_answer_4", "fieldname": "possibility_4",
"fieldtype": "Small Text", "fieldtype": "Small Text",
"label": "Possible Answer 4" "label": "Possible Answer 4"
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2023-10-10 16:03:38.776125", "modified": "2023-10-16 11:39:39.757008",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Question", "name": "LMS Question",

View File

@@ -12,6 +12,10 @@
"column_break_gaac", "column_break_gaac",
"max_attempts", "max_attempts",
"show_submission_history", "show_submission_history",
"section_break_hsiv",
"passing_percentage",
"column_break_rocd",
"total_marks",
"section_break_sbjx", "section_break_sbjx",
"questions", "questions",
"section_break_3", "section_break_3",
@@ -90,11 +94,30 @@
"fieldname": "show_submission_history", "fieldname": "show_submission_history",
"fieldtype": "Check", "fieldtype": "Check",
"label": "Show Submission History" "label": "Show Submission History"
},
{
"fieldname": "section_break_hsiv",
"fieldtype": "Section Break"
},
{
"fieldname": "passing_percentage",
"fieldtype": "Int",
"label": "Passing Percentage"
},
{
"fieldname": "column_break_rocd",
"fieldtype": "Column Break"
},
{
"fieldname": "total_marks",
"fieldtype": "Int",
"label": "Total Marks",
"read_only": 1
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2023-07-04 15:26:24.457745", "modified": "2023-10-16 17:21:33.932981",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Quiz", "name": "LMS Quiz",

View File

@@ -5,7 +5,7 @@ import json
import frappe import frappe
from frappe import _ from frappe import _
from frappe.model.document import Document from frappe.model.document import Document
from frappe.utils import cstr from frappe.utils import cstr, comma_and
from lms.lms.doctype.lms_question.lms_question import validate_correct_answers from lms.lms.doctype.lms_question.lms_question import validate_correct_answers
from lms.lms.utils import ( from lms.lms.utils import (
generate_slug, generate_slug,
@@ -15,6 +15,17 @@ from lms.lms.utils import (
class LMSQuiz(Document): class LMSQuiz(Document):
def validate(self):
self.validate_duplicate_questions()
def validate_duplicate_questions(self):
questions = [row.question for row in self.questions]
rows = [i + 1 for i, x in enumerate(questions) if questions.count(x) > 1]
if len(rows):
frappe.throw(
_("Rows {0} have the duplicate questions.").format(frappe.bold(comma_and(rows)))
)
def autoname(self): def autoname(self):
if not self.name: if not self.name:
self.name = generate_slug(self.title, "LMS Quiz") self.name = generate_slug(self.title, "LMS Quiz")
@@ -44,11 +55,13 @@ def quiz_summary(quiz, results):
for result in results: for result in results:
correct = result["is_correct"][0] correct = result["is_correct"][0]
result["question"] = frappe.db.get_value( question_name = frappe.db.get_value(
"LMS Quiz Question", "LMS Quiz Question",
{"parent": quiz, "idx": result["question_index"] + 1}, {"parent": quiz, "idx": result["question_index"] + 1},
["question"], ["question"],
) )
result["question_name"] = question_name
result["question"] = frappe.db.get_value("LMS Question", question_name, "question")
for point in result["is_correct"]: for point in result["is_correct"]:
correct = correct and point correct = correct and point
@@ -184,9 +197,7 @@ def check_choice_answers(question, answers):
fields.append(f"option_{cstr(num)}") fields.append(f"option_{cstr(num)}")
fields.append(f"is_correct_{cstr(num)}") fields.append(f"is_correct_{cstr(num)}")
question_details = frappe.db.get_value( question_details = frappe.db.get_value("LMS Question", question, fields, as_dict=1)
"LMS Quiz Question", question, fields, as_dict=1
)
for num in range(1, 5): for num in range(1, 5):
if question_details[f"option_{num}"] in answers: if question_details[f"option_{num}"] in answers:

View File

@@ -5,22 +5,34 @@
"editable_grid": 1, "editable_grid": 1,
"engine": "InnoDB", "engine": "InnoDB",
"field_order": [ "field_order": [
"question" "question",
"marks"
], ],
"fields": [ "fields": [
{ {
"fieldname": "question", "fieldname": "question",
"fieldtype": "Link", "fieldtype": "Link",
"in_list_view": 1, "in_list_view": 1,
"in_preview": 1,
"label": "Question", "label": "Question",
"options": "LMS Question", "options": "LMS Question",
"reqd": 1 "reqd": 1
},
{
"default": "1",
"fieldname": "marks",
"fieldtype": "Int",
"in_list_view": 1,
"in_preview": 1,
"label": "Marks",
"non_negative": 1,
"reqd": 1
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2023-10-10 15:42:51.791902", "modified": "2023-10-16 19:51:03.893143",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Quiz Question", "name": "LMS Quiz Question",

View File

@@ -6,8 +6,11 @@
"engine": "InnoDB", "engine": "InnoDB",
"field_order": [ "field_order": [
"question", "question",
"answer", "section_break_fztv",
"is_correct" "question_name",
"is_correct",
"column_break_flus",
"answer"
], ],
"fields": [ "fields": [
{ {
@@ -31,12 +34,26 @@
"in_list_view": 1, "in_list_view": 1,
"label": "Is Correct", "label": "Is Correct",
"read_only": 1 "read_only": 1
},
{
"fieldname": "section_break_fztv",
"fieldtype": "Section Break"
},
{
"fieldname": "question_name",
"fieldtype": "Link",
"label": "Question Name",
"options": "LMS Question"
},
{
"fieldname": "column_break_flus",
"fieldtype": "Column Break"
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2022-11-24 11:15:45.931119", "modified": "2023-10-16 15:25:03.380843",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Quiz Result", "name": "LMS Quiz Result",

View File

@@ -73,4 +73,5 @@ lms.patches.v1_0.change_naming_for_batch_course #14-09-2023
execute:frappe.permissions.reset_perms("LMS Enrollment") execute:frappe.permissions.reset_perms("LMS Enrollment")
lms.patches.v1_0.create_student_role lms.patches.v1_0.create_student_role
lms.patches.v1_0.mark_confirmation_for_batch_students lms.patches.v1_0.mark_confirmation_for_batch_students
lms.patches.v1_0.create_quiz_questions lms.patches.v1_0.create_quiz_questions
lms.patches.v1_0.add_default_marks #16-10-2023

View File

@@ -0,0 +1,16 @@
import frappe
def execute():
questions = frappe.get_all("LMS Quiz Question", pluck="name")
for question in questions:
frappe.db.set_value("LMS Quiz Question", question, "marks", 1)
quizzes = frappe.get_all("LMS Quiz", pluck="name")
for quiz in quizzes:
questions_count = frappe.db.count("LMS Quiz Question", {"parent": quiz})
frappe.db.set_value(
"LMS Quiz", quiz, {"total_marks": questions_count, "passing_percentage": 100}
)

View File

@@ -3,31 +3,21 @@ import frappe
def execute(): def execute():
frappe.reload_doc("lms", "doctype", "lms_question") frappe.reload_doc("lms", "doctype", "lms_question")
frappe.reload_doc("lms", "doctype", "lms_quiz_question")
fields = ["name", "question", "type", "multiple"]
for num in range(1, 5):
fields.append(f"option_{num}")
fields.append(f"is_correct_{num}")
fields.append(f"explanation_{num}")
fields.append(f"possibility_{num}")
questions = frappe.get_all( questions = frappe.get_all(
"LMS Quiz Question", "LMS Quiz Question",
fields=[ fields=fields,
"name",
"question",
"type",
"multiple",
"option_1",
"is_correct_1",
"explanation_1",
"option_2",
"is_correct_2",
"explanation_2",
"option_3",
"is_correct_3",
"explanation_3",
"option_4",
"is_correct_4",
"explanation_4",
],
) )
for question in questions: for question in questions:
print(question.name)
doc = frappe.new_doc("LMS Question") doc = frappe.new_doc("LMS Question")
doc.update( doc.update(
{ {
@@ -44,9 +34,10 @@ def execute():
f"option_{num}": question[f"option_{num}"], f"option_{num}": question[f"option_{num}"],
f"is_correct_{num}": question[f"is_correct_{num}"], f"is_correct_{num}": question[f"is_correct_{num}"],
f"explanation_{num}": question[f"explanation_{num}"], f"explanation_{num}": question[f"explanation_{num}"],
f"possibility_{num}": question[f"possibility_{num}"],
} }
) )
doc.save() doc.save()
print(doc.name)
frappe.db.set_value("LMS Quiz Question", question.name, "question", doc.name) frappe.db.set_value("LMS Quiz Question", question.name, "question", doc.name)

View File

@@ -109,7 +109,28 @@ def quiz_renderer(quiz_name):
) )
+"</div>" +"</div>"
quiz = frappe.get_doc("LMS Quiz", quiz_name) quiz = frappe.db.get_value(
"LMS Quiz",
quiz_name,
["name", "title", "max_attempts", "show_answers", "show_submission_history"],
as_dict=True,
)
quiz.questions = []
fields = ["name", "question", "type", "multiple"]
for num in range(1, 5):
fields.append(f"option_{num}")
fields.append(f"is_correct_{num}")
fields.append(f"explanation_{num}")
fields.append(f"possibility_{num}")
questions = frappe.get_all(
"LMS Quiz Question", {"parent": quiz.name}, pluck="question", order_by="idx"
)
for question in questions:
details = frappe.db.get_value("LMS Question", question, fields, as_dict=1)
quiz.questions.append(details)
no_of_attempts = frappe.db.count( no_of_attempts = frappe.db.count(
"LMS Quiz Submission", {"owner": frappe.session.user, "quiz": quiz_name} "LMS Quiz Submission", {"owner": frappe.session.user, "quiz": quiz_name}
) )

View File

@@ -51,7 +51,8 @@
data-multi="{{ question.multiple }}" data-qt-index="{{ loop.index }}"> data-multi="{{ question.multiple }}" data-qt-index="{{ loop.index }}">
<div> <div>
<div class="question-number"> <div class="question-number">
{{ _("Question ") }}{{ loop.index }}: {{ instruction }}</div> {{ _("Question ") }}{{ loop.index }}: {{ instruction }}
</div>
<div class="question-text"> <div class="question-text">
{{ question.question }} {{ question.question }}
</div> </div>