Merge pull request #902 from pateljannat/quiz-limit
feat: limit questions in quiz
This commit is contained in:
@@ -270,6 +270,9 @@ const quiz = createResource({
|
|||||||
if (data.shuffle_questions) {
|
if (data.shuffle_questions) {
|
||||||
data.questions = data.questions.sort(() => Math.random() - 0.5)
|
data.questions = data.questions.sort(() => Math.random() - 0.5)
|
||||||
}
|
}
|
||||||
|
if (data.limit_questions_to) {
|
||||||
|
data.questions = data.questions.slice(0, data.limit_questions_to)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
19
lms/hooks.py
19
lms/hooks.py
@@ -242,25 +242,6 @@ has_website_permission = {
|
|||||||
"LMS Certificate": "lms.lms.doctype.lms_certificate.lms_certificate.has_website_permission",
|
"LMS Certificate": "lms.lms.doctype.lms_certificate.lms_certificate.has_website_permission",
|
||||||
}
|
}
|
||||||
|
|
||||||
profile_mandatory_fields = [
|
|
||||||
"first_name",
|
|
||||||
"last_name",
|
|
||||||
"user_image",
|
|
||||||
"bio",
|
|
||||||
"linkedin",
|
|
||||||
"education",
|
|
||||||
"skill",
|
|
||||||
"preferred_functions",
|
|
||||||
"preferred_industries",
|
|
||||||
"dream_companies",
|
|
||||||
"attire",
|
|
||||||
"collaboration",
|
|
||||||
"role",
|
|
||||||
"location_preference",
|
|
||||||
"time",
|
|
||||||
"company_type",
|
|
||||||
]
|
|
||||||
|
|
||||||
## Markdown Macros for Lessons
|
## Markdown Macros for Lessons
|
||||||
lms_markdown_macro_renderers = {
|
lms_markdown_macro_renderers = {
|
||||||
"Exercise": "lms.plugins.exercise_renderer",
|
"Exercise": "lms.plugins.exercise_renderer",
|
||||||
|
|||||||
@@ -8,10 +8,11 @@
|
|||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"title",
|
"title",
|
||||||
"passing_percentage",
|
|
||||||
"column_break_gaac",
|
|
||||||
"max_attempts",
|
"max_attempts",
|
||||||
|
"limit_questions_to",
|
||||||
|
"column_break_gaac",
|
||||||
"total_marks",
|
"total_marks",
|
||||||
|
"passing_percentage",
|
||||||
"section_break_hsiv",
|
"section_break_hsiv",
|
||||||
"show_answers",
|
"show_answers",
|
||||||
"column_break_rocd",
|
"column_break_rocd",
|
||||||
@@ -23,8 +24,7 @@
|
|||||||
"section_break_3",
|
"section_break_3",
|
||||||
"lesson",
|
"lesson",
|
||||||
"column_break_5",
|
"column_break_5",
|
||||||
"course",
|
"course"
|
||||||
"time"
|
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@@ -54,13 +54,6 @@
|
|||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"label": "Max Attempts"
|
"label": "Max Attempts"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "time",
|
|
||||||
"fieldtype": "Int",
|
|
||||||
"hidden": 1,
|
|
||||||
"label": "Time Per Question (in Seconds)"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fetch_from": "lesson.course",
|
"fetch_from": "lesson.course",
|
||||||
"fieldname": "course",
|
"fieldname": "course",
|
||||||
@@ -131,11 +124,16 @@
|
|||||||
"fieldname": "shuffle_questions",
|
"fieldname": "shuffle_questions",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Shuffle Questions"
|
"label": "Shuffle Questions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "limit_questions_to",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"label": "Limit Questions To"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-04-24 12:37:20.578041",
|
"modified": "2024-06-27 22:03:48.576489",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Quiz",
|
"name": "LMS Quiz",
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ from lms.lms.utils import (
|
|||||||
class LMSQuiz(Document):
|
class LMSQuiz(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_duplicate_questions()
|
self.validate_duplicate_questions()
|
||||||
self.total_marks = set_total_marks(self.name, self.questions)
|
self.validate_limit()
|
||||||
|
self.calculate_total_marks()
|
||||||
|
|
||||||
def validate_duplicate_questions(self):
|
def validate_duplicate_questions(self):
|
||||||
questions = [row.question for row in self.questions]
|
questions = [row.question for row in self.questions]
|
||||||
@@ -28,6 +29,25 @@ class LMSQuiz(Document):
|
|||||||
_("Rows {0} have the duplicate questions.").format(frappe.bold(comma_and(rows)))
|
_("Rows {0} have the duplicate questions.").format(frappe.bold(comma_and(rows)))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def validate_limit(self):
|
||||||
|
if self.limit_questions_to and self.limit_questions_to >= len(self.questions):
|
||||||
|
frappe.throw(
|
||||||
|
_("Limit cannot be greater than or equal to the number of questions in the quiz.")
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.limit_questions_to and self.limit_questions_to < len(self.questions):
|
||||||
|
marks = [question.marks for question in self.questions]
|
||||||
|
if len(set(marks)) > 1:
|
||||||
|
frappe.throw(_("All questions should have the same marks if the limit is set."))
|
||||||
|
|
||||||
|
def calculate_total_marks(self):
|
||||||
|
if self.limit_questions_to:
|
||||||
|
self.total_marks = sum(
|
||||||
|
question.marks for question in self.questions[: self.limit_questions_to]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.total_marks = sum(question.marks for question in self.questions)
|
||||||
|
|
||||||
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")
|
||||||
@@ -50,7 +70,7 @@ class LMSQuiz(Document):
|
|||||||
return result[0]
|
return result[0]
|
||||||
|
|
||||||
|
|
||||||
def set_total_marks(quiz, questions):
|
def set_total_marks(questions):
|
||||||
marks = 0
|
marks = 0
|
||||||
for question in questions:
|
for question in questions:
|
||||||
marks += question.get("marks")
|
marks += question.get("marks")
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"default_home",
|
"default_home",
|
||||||
"force_profile_completion",
|
|
||||||
"is_onboarding_complete",
|
"is_onboarding_complete",
|
||||||
"column_break_zdel",
|
"column_break_zdel",
|
||||||
"unsplash_access_key",
|
"unsplash_access_key",
|
||||||
@@ -104,13 +103,6 @@
|
|||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Course List Search Bar Placeholder"
|
"label": "Course List Search Bar Placeholder"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "force_profile_completion",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 1,
|
|
||||||
"label": "Force users to complete their Profile"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"fieldname": "terms_of_use",
|
"fieldname": "terms_of_use",
|
||||||
@@ -431,7 +423,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-05-31 20:17:07.362088",
|
"modified": "2024-06-27 21:57:02.193336",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Settings",
|
"name": "LMS Settings",
|
||||||
|
|||||||
@@ -776,10 +776,6 @@ def get_lesson_count(course):
|
|||||||
return lesson_count
|
return lesson_count
|
||||||
|
|
||||||
|
|
||||||
def check_profile_restriction():
|
|
||||||
return frappe.db.get_single_value("LMS Settings", "force_profile_completion")
|
|
||||||
|
|
||||||
|
|
||||||
def get_restriction_details():
|
def get_restriction_details():
|
||||||
user = frappe.db.get_value(
|
user = frappe.db.get_value(
|
||||||
"User", frappe.session.user, ["profile_complete", "username"], as_dict=True
|
"User", frappe.session.user, ["profile_complete", "username"], as_dict=True
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ class CustomUser(User):
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
super().validate()
|
super().validate()
|
||||||
self.validate_username_duplicates()
|
self.validate_username_duplicates()
|
||||||
self.validate_completion()
|
|
||||||
|
|
||||||
def validate_username_duplicates(self):
|
def validate_username_duplicates(self):
|
||||||
while not self.username or self.username_exists():
|
while not self.username or self.username_exists():
|
||||||
@@ -38,19 +37,6 @@ class CustomUser(User):
|
|||||||
else:
|
else:
|
||||||
frappe.throw(_("Skills must be unique"))
|
frappe.throw(_("Skills must be unique"))
|
||||||
|
|
||||||
def validate_completion(self):
|
|
||||||
if frappe.db.get_single_value("LMS Settings", "force_profile_completion"):
|
|
||||||
all_fields_have_value = True
|
|
||||||
profile_mandatory_fields = frappe.get_hooks("profile_mandatory_fields")
|
|
||||||
docfields = frappe.get_meta(self.doctype).fields
|
|
||||||
|
|
||||||
for field in profile_mandatory_fields:
|
|
||||||
if not self.get(field):
|
|
||||||
all_fields_have_value = False
|
|
||||||
break
|
|
||||||
|
|
||||||
self.profile_complete = all_fields_have_value
|
|
||||||
|
|
||||||
def get_batch_count(self) -> int:
|
def get_batch_count(self) -> int:
|
||||||
"""Returns the number of batches authored by this user."""
|
"""Returns the number of batches authored by this user."""
|
||||||
return frappe.db.count(
|
return frappe.db.count(
|
||||||
|
|||||||
@@ -91,17 +91,6 @@ class LiveCodeExtension(PageExtension):
|
|||||||
return frappe.render_template("templates/livecode/extension_footer.html", context)
|
return frappe.render_template("templates/livecode/extension_footer.html", context)
|
||||||
|
|
||||||
|
|
||||||
def set_mandatory_fields_for_profile():
|
|
||||||
profile_form = frappe.get_doc("Web Form", "profile")
|
|
||||||
profile_mandatory_fields = frappe.get_hooks("profile_mandatory_fields")
|
|
||||||
for field in profile_form.web_form_fields:
|
|
||||||
field.reqd = 0
|
|
||||||
if field.fieldname in profile_mandatory_fields:
|
|
||||||
field.reqd = 1
|
|
||||||
|
|
||||||
profile_form.save()
|
|
||||||
|
|
||||||
|
|
||||||
def quiz_renderer(quiz_name):
|
def quiz_renderer(quiz_name):
|
||||||
if frappe.session.user == "Guest":
|
if frappe.session.user == "Guest":
|
||||||
return " <div class='alert alert-info'>" + _(
|
return " <div class='alert alert-info'>" + _(
|
||||||
|
|||||||
Reference in New Issue
Block a user