From d61acb552a9b786c02c960e430fb5179b028ef08 Mon Sep 17 00:00:00 2001 From: Anand Chitipothu Date: Wed, 19 May 2021 20:00:19 +0530 Subject: [PATCH] feat: added Exercise and Exercise Submission doctypes Also: - added methods to submit an exercise and get the submission for a user - added test cases Issue #90 --- community/lms/doctype/exercise/__init__.py | 0 community/lms/doctype/exercise/exercise.js | 8 ++ community/lms/doctype/exercise/exercise.json | 99 +++++++++++++++++++ community/lms/doctype/exercise/exercise.py | 44 +++++++++ .../lms/doctype/exercise/test_exercise.py | 37 +++++++ .../doctype/exercise_submission/__init__.py | 0 .../exercise_submission.js | 8 ++ .../exercise_submission.json | 59 +++++++++++ .../exercise_submission.py | 8 ++ .../test_exercise_submission.py | 8 ++ 10 files changed, 271 insertions(+) create mode 100644 community/lms/doctype/exercise/__init__.py create mode 100644 community/lms/doctype/exercise/exercise.js create mode 100644 community/lms/doctype/exercise/exercise.json create mode 100644 community/lms/doctype/exercise/exercise.py create mode 100644 community/lms/doctype/exercise/test_exercise.py create mode 100644 community/lms/doctype/exercise_submission/__init__.py create mode 100644 community/lms/doctype/exercise_submission/exercise_submission.js create mode 100644 community/lms/doctype/exercise_submission/exercise_submission.json create mode 100644 community/lms/doctype/exercise_submission/exercise_submission.py create mode 100644 community/lms/doctype/exercise_submission/test_exercise_submission.py diff --git a/community/lms/doctype/exercise/__init__.py b/community/lms/doctype/exercise/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/community/lms/doctype/exercise/exercise.js b/community/lms/doctype/exercise/exercise.js new file mode 100644 index 00000000..740634b4 --- /dev/null +++ b/community/lms/doctype/exercise/exercise.js @@ -0,0 +1,8 @@ +// Copyright (c) 2021, FOSS United and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Exercise', { + // refresh: function(frm) { + + // } +}); diff --git a/community/lms/doctype/exercise/exercise.json b/community/lms/doctype/exercise/exercise.json new file mode 100644 index 00000000..a54f84af --- /dev/null +++ b/community/lms/doctype/exercise/exercise.json @@ -0,0 +1,99 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2021-05-19 17:43:39.923430", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "title", + "description", + "code", + "answer", + "column_break_4", + "course", + "hints", + "tests", + "image" + ], + "fields": [ + { + "fieldname": "title", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Title" + }, + { + "fieldname": "course", + "fieldtype": "Link", + "label": "Course", + "options": "LMS Course" + }, + { + "columns": 4, + "fieldname": "description", + "fieldtype": "Markdown Editor", + "in_list_view": 1, + "label": "Description" + }, + { + "columns": 4, + "fieldname": "answer", + "fieldtype": "Code", + "label": "Answer" + }, + { + "fieldname": "tests", + "fieldtype": "Code", + "label": "Tests" + }, + { + "fieldname": "column_break_4", + "fieldtype": "Column Break" + }, + { + "columns": 4, + "fieldname": "hints", + "fieldtype": "Markdown Editor", + "label": "Hints" + }, + { + "columns": 4, + "fieldname": "code", + "fieldtype": "Code", + "label": "Code" + }, + { + "fieldname": "image", + "fieldtype": "Code", + "label": "Image", + "read_only": 1 + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-05-19 18:27:40.475515", + "modified_by": "Administrator", + "module": "LMS", + "name": "Exercise", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "search_fields": "title", + "sort_field": "modified", + "sort_order": "DESC", + "title_field": "title", + "track_changes": 1 +} \ No newline at end of file diff --git a/community/lms/doctype/exercise/exercise.py b/community/lms/doctype/exercise/exercise.py new file mode 100644 index 00000000..ae9c44eb --- /dev/null +++ b/community/lms/doctype/exercise/exercise.py @@ -0,0 +1,44 @@ +# Copyright (c) 2021, FOSS United and contributors +# For license information, please see license.txt + +import frappe +from frappe.model.document import Document + +class Exercise(Document): + def get_user_submission(self): + """Returns the latest submission for this user. + """ + user = frappe.session.user + if not user or user == "Guest": + return + + result = frappe.get_all('Exercise Submission', + fields="*", + filters={ + "owner": user, + "exercise": self.name + }, + order_by="creation desc", + page_length=1) + if result: + return result[0] + + def submit(self, code): + """Submits the given code as solution to exercise. + """ + user = frappe.session.user + if not user or user == "Guest": + return + + old_submission = self.get_user_submission() + if old_submission and old_submission.solution == code: + return old_submission + + doc = frappe.get_doc( + doctype="Exercise Submission", + exercise=self.name, + exercise_title=self.title, + solution=code) + doc.insert() + return doc + diff --git a/community/lms/doctype/exercise/test_exercise.py b/community/lms/doctype/exercise/test_exercise.py new file mode 100644 index 00000000..02dc2c38 --- /dev/null +++ b/community/lms/doctype/exercise/test_exercise.py @@ -0,0 +1,37 @@ +# Copyright (c) 2021, FOSS United and Contributors +# See license.txt + +import frappe +import unittest + +class TestExercise(unittest.TestCase): + def setUp(self): + frappe.db.sql('delete from `tabExercise Submission`') + frappe.db.sql('delete from `tabExercise`') + + def new_exercise(self): + e = frappe.get_doc({ + "doctype": "Exercise", + "name": "test-problem", + "title": "Test Problem", + "description": "draw a circle", + "code": "# draw a single cicle", + "answer": ( + "# draw a single circle\n" + + "circle(100, 100, 50)") + }) + e.insert() + return e + + def test_exercise(self): + e = self.new_exercise() + assert e.get_user_submission() is None + + def test_exercise_submission(self): + e = self.new_exercise() + submission = e.submit("circle(100, 100, 50)") + assert submission is not None + + user_submission = e.get_user_submission() + assert user_submission is not None + assert user_submission.name == submission.name diff --git a/community/lms/doctype/exercise_submission/__init__.py b/community/lms/doctype/exercise_submission/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/community/lms/doctype/exercise_submission/exercise_submission.js b/community/lms/doctype/exercise_submission/exercise_submission.js new file mode 100644 index 00000000..5f1d8399 --- /dev/null +++ b/community/lms/doctype/exercise_submission/exercise_submission.js @@ -0,0 +1,8 @@ +// Copyright (c) 2021, FOSS United and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Exercise Submission', { + // refresh: function(frm) { + + // } +}); diff --git a/community/lms/doctype/exercise_submission/exercise_submission.json b/community/lms/doctype/exercise_submission/exercise_submission.json new file mode 100644 index 00000000..ab26ff8e --- /dev/null +++ b/community/lms/doctype/exercise_submission/exercise_submission.json @@ -0,0 +1,59 @@ +{ + "actions": [], + "creation": "2021-05-19 11:41:18.108316", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "exercise", + "solution", + "exercise_title" + ], + "fields": [ + { + "fieldname": "exercise", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Exercise", + "options": "Exercise" + }, + { + "fieldname": "solution", + "fieldtype": "Code", + "in_list_view": 1, + "label": "Solution" + }, + { + "fetch_from": "exercise.title", + "fieldname": "exercise_title", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Exercise Title", + "read_only": 1 + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2021-05-19 19:41:55.852069", + "modified_by": "Administrator", + "module": "LMS", + "name": "Exercise 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 +} \ No newline at end of file diff --git a/community/lms/doctype/exercise_submission/exercise_submission.py b/community/lms/doctype/exercise_submission/exercise_submission.py new file mode 100644 index 00000000..fd631eb8 --- /dev/null +++ b/community/lms/doctype/exercise_submission/exercise_submission.py @@ -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 ExerciseSubmission(Document): + pass diff --git a/community/lms/doctype/exercise_submission/test_exercise_submission.py b/community/lms/doctype/exercise_submission/test_exercise_submission.py new file mode 100644 index 00000000..eed851a5 --- /dev/null +++ b/community/lms/doctype/exercise_submission/test_exercise_submission.py @@ -0,0 +1,8 @@ +# Copyright (c) 2021, FOSS United and Contributors +# See license.txt + +# import frappe +import unittest + +class TestExerciseSubmission(unittest.TestCase): + pass