feat: lms quizzes

This commit is contained in:
pateljannat
2021-06-09 13:17:42 +05:30
parent 586b39c0fd
commit 1cb81de5c0
28 changed files with 470 additions and 3 deletions

View File

@@ -43,7 +43,7 @@ def save_current_lesson(batch_name, lesson_name):
doctype="LMS Batch Membership",
filters={
"batch": batch_name,
"member_email": frappe.session.user
"member": frappe.session.user
},
fieldname="name")
if not name:

View File

@@ -40,6 +40,7 @@
"default": "1",
"fieldname": "index_",
"fieldtype": "Int",
"in_list_view": 1,
"label": "Index"
},
{
@@ -56,14 +57,13 @@
{
"fieldname": "index_label",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Index Label",
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-06-01 05:30:48.127494",
"modified": "2021-06-07 11:58:13.395438",
"modified_by": "Administrator",
"module": "LMS",
"name": "Lesson",

View File

@@ -0,0 +1,36 @@
{
"actions": [],
"creation": "2021-06-07 10:46:10.402684",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"option",
"is_correct"
],
"fields": [
{
"fieldname": "option",
"fieldtype": "Data",
"label": "Option"
},
{
"default": "0",
"fieldname": "is_correct",
"fieldtype": "Check",
"label": "Is Correct"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-06-07 10:48:45.290227",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Option",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class LMSOption(Document):
pass

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Quiz', {
// refresh: function(frm) {
// }
});

View File

@@ -0,0 +1,50 @@
{
"actions": [],
"autoname": "field:title",
"creation": "2021-06-07 10:50:17.893625",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"title",
"questions"
],
"fields": [
{
"fieldname": "title",
"fieldtype": "Data",
"label": "Title",
"unique": 1
},
{
"fieldname": "questions",
"fieldtype": "Table",
"label": "Questions",
"options": "LMS Quiz Question"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-06-07 12:22:37.333289",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Quiz",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -0,0 +1,36 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
import json
class LMSQuiz(Document):
pass
@frappe.whitelist()
def submit(quiz, result):
score = 0
result = json.loads(result)
quiz_details = frappe.get_doc("LMS Quiz", quiz)
print(result, type(result))
for response in result:
match = list(filter(lambda x: x.question == response.get("question"), quiz_details.questions))[0]
response["users_response"] = ("").join([ ans for ans in response.get("answer") ]).replace(" ", ", ")
del response["answer"]
print(response.get("users_response"), match.answer)
if response.get("users_response") == match.answer:
response["result"] = "Right"
score += 1
else:
response["result"] = "Wrong"
frappe.get_doc({
"doctype": "LMS Quiz Submission",
"quiz": quiz,
"result": result,
"score": score
}).save()
return score

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
# import frappe
import unittest
class TestLMSQuiz(unittest.TestCase):
pass

View File

@@ -0,0 +1,52 @@
{
"actions": [],
"creation": "2021-06-07 10:48:57.994714",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"question",
"options",
"answer",
"multiple_correct_answers"
],
"fields": [
{
"fieldname": "question",
"fieldtype": "Text",
"in_list_view": 1,
"label": "Question"
},
{
"fieldname": "options",
"fieldtype": "Text",
"in_list_view": 1,
"label": "Options"
},
{
"default": "0",
"fieldname": "multiple_correct_answers",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Multiple Correct Answers"
},
{
"fieldname": "answer",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Answer"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-06-07 12:47:22.787160",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Quiz Question",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class LMSQuizQuestion(Document):
pass

View File

@@ -0,0 +1,43 @@
{
"actions": [],
"creation": "2021-06-07 10:48:57.994714",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"question",
"options",
"multiple_correct_answers"
],
"fields": [
{
"fieldname": "question",
"fieldtype": "Data",
"label": "Question"
},
{
"fieldname": "options",
"fieldtype": "Table",
"label": "Options",
"options": "LMS Option"
},
{
"default": "0",
"fieldname": "multiple_correct_answers",
"fieldtype": "Check",
"label": "Multiple Correct Answers"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-06-07 10:48:57.994714",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Quiz Questions",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class LMSQuizQuestions(Document):
pass

View File

@@ -0,0 +1,45 @@
{
"actions": [],
"creation": "2021-06-07 14:19:23.683323",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"question",
"users_response",
"result"
],
"fields": [
{
"fieldname": "question",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Question"
},
{
"fieldname": "users_response",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Users Response"
},
{
"fieldname": "result",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Result",
"options": "Right\nWrong"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-06-07 14:21:07.768039",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Quiz Result",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class LMSQuizResult(Document):
pass

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2021, FOSS United and contributors
// For license information, please see license.txt
frappe.ui.form.on('LMS Quiz Submission', {
// refresh: function(frm) {
// }
});

View File

@@ -0,0 +1,55 @@
{
"actions": [],
"creation": "2021-06-07 14:19:54.958989",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"quiz",
"result",
"score"
],
"fields": [
{
"fieldname": "quiz",
"fieldtype": "Link",
"label": "Quiz",
"options": "LMS Quiz"
},
{
"fieldname": "result",
"fieldtype": "Table",
"label": "Result",
"options": "LMS Quiz Result"
},
{
"fieldname": "score",
"fieldtype": "Data",
"label": "Score"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-06-07 14:19:54.958989",
"modified_by": "Administrator",
"module": "LMS",
"name": "LMS Quiz Submission",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class LMSQuizSubmission(Document):
pass

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2021, FOSS United and Contributors
# See license.txt
# import frappe
import unittest
class TestLMSQuizSubmission(unittest.TestCase):
pass

View File

@@ -14,6 +14,10 @@ class LMSSection(Document):
if self.type == "exercise":
return frappe.get_doc("Exercise", self.id)
def get_quiz(self):
if self.type == "quiz":
return frappe.get_doc("LMS Quiz", self.id)
def get_latest_code_for_user(self):
"""Returns the latest code for the logged in user.
"""

View File

@@ -0,0 +1,67 @@
<h3 id="title">{{ quiz.title }}</h3>
<form id="quiz-form">
{% for question in quiz.questions %}
<div class="question mb-5" data-question="{{ question.question }}"
data-multi="{{ question.multiple_correct_answers}}">
<p> {{ loop.index }}. {{ question.question }}</p>
{% set options = question.options.split(",") %}
{% for option in options %}
<div class="checkbox">
<input {% if question.multiple_correct_answers %} type="checkbox" {% else %} type="radio"
name="{{ question.question | urlencode }}" {% endif %} class="option" value="{{ option }}">
<span class="label-area">{{ option }}</span>
</div>
{% endfor %}
</div>
{% endfor %}
<button class="btn btn-secondary hide mb-5" id="try-again">Try Again</button>
<button class="btn btn-primary" id="submit">Submit</button>
<h4 class="success-message"></h4>
<h5 class="score text-muted"></h5>
</form>
<script>
frappe.ready(() => {
$("#submit").click((e) => {
e.preventDefault();
var result = [];
$('.question').each((i, element) => {
var options = $(element).find(".option");
var answers = [];
options.filter((i, op) => $(op).prop("checked")).each((i, elem) => answers.push(elem.value));
result.push({
"question": element.dataset.question,
"answer": answers
});
});
frappe.call({
method: "community.lms.doctype.lms_quiz.lms_quiz.submit",
args: {
quiz: $("#title").text(),
result: result
},
callback: (data) => {
$("#submit").addClass("hide");
$("#try-again").removeClass("hide");
$(":input[type='checkbox']").prop("disabled", true);
$(":input[type='radio']").prop("disabled", true);
if (data.message == result.length) {
$(".success-message").text("Congratulations, you cleared the quiz!");
}
else {
$(".success-message").text("Some of your answers weren't correct. You can give it another shot.");
}
$(".score").text(`Score: ${data.message}/${result.length}`);
}
})
})
$("#try-again").click((e) => {
e.preventDefault();
$("#quiz-form").trigger("reset");
$(".success-message").text("");
$(".score").text("");
$("#submit").removeClass("hide");
$("#try-again").addClass("hide");
})
})
</script>

View File

@@ -23,6 +23,7 @@
--cta-color: var(--c4);
--send-message: var(--c7);
--received-message: var(--c8);
--checkbox-size: 14px;
}
body {
@@ -238,3 +239,7 @@ section {
.page-card .btn {
margin-top: 30px;
}
input[type=checkbox] {
appearance: auto;
}

View File

@@ -53,6 +53,8 @@
}}
{% elif s.type == "exercise" %}
{{ widgets.Exercise(exercise=s.get_exercise())}}
{% elif s.type == "quiz" %}
{{ widgets.Quiz(quiz=s.get_quiz())}}
{% else %}
<div>Unknown section type: {{s.type}}</div>
{% endif %}