From 059034c0ec77d130eeb55af62c456773c2a64b2a Mon Sep 17 00:00:00 2001 From: maheshgudi Date: Wed, 11 Jan 2017 18:18:06 +0530 Subject: changed mcq to single correct choice --- yaksh/models.py | 2 +- yaksh/templates/yaksh/question.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/yaksh/models.py b/yaksh/models.py index 2d84622..4292cc0 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -36,7 +36,7 @@ languages = ( ) question_types = ( - ("mcq", "Multiple Choice"), + ("mcq", "Single Correct Choice"), ("mcc", "Multiple Correct Choices"), ("code", "Code"), ("upload", "Assignment Upload"), diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index 6218b18..27b2956 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -142,7 +142,7 @@ function call_skip(url)

{{ question.summary }} {% if question.type == "mcq" %} - (Single Correct Choice Questions) + (Single Correct Choice) {% elif question.type == "mcc" %} (Multiple Correct Choices) {% elif question.type == "code" %} -- cgit From 4ef5f9377c27a3e88ae3a1a4e2a446984fc14b70 Mon Sep 17 00:00:00 2001 From: maheshgudi Date: Thu, 26 Jan 2017 01:43:47 +0530 Subject: added integer based question type --- yaksh/db.cnf | 5 +++++ yaksh/forms.py | 4 +++- yaksh/models.py | 16 ++++++++++++++++ yaksh/templates/exam.html | 8 ++++++-- yaksh/templates/yaksh/add_question.html | 1 + yaksh/templates/yaksh/grade_user.html | 7 +++++++ yaksh/templates/yaksh/question.html | 13 ++++++++++++- yaksh/templates/yaksh/user_data.html | 8 ++++++++ yaksh/templates/yaksh/view_answerpaper.html | 7 +++++++ yaksh/views.py | 11 ++++++++++- 10 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 yaksh/db.cnf diff --git a/yaksh/db.cnf b/yaksh/db.cnf new file mode 100644 index 0000000..22c68e3 --- /dev/null +++ b/yaksh/db.cnf @@ -0,0 +1,5 @@ +# new.cnf +[client] +database = online_test +user = root +default-character-set = utf8 diff --git a/yaksh/forms.py b/yaksh/forms.py index 6ec031c..4bf4fcf 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -1,7 +1,7 @@ from django import forms from yaksh.models import get_model_class, Profile, Quiz, Question, TestCase, Course,\ QuestionPaper, StandardTestCase, StdIOBasedTestCase, \ - HookTestCase + HookTestCase, IntegerTestCase from django.contrib.auth import authenticate from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType @@ -35,6 +35,7 @@ question_types = ( ("mcc", "Multiple Correct Choices"), ("code", "Code"), ("upload", "Assignment Upload"), + ("integer", "Answer in Integer"), ) test_case_types = ( @@ -42,6 +43,7 @@ test_case_types = ( ("stdiobasedtestcase", "StdIO Based Testcase"), ("mcqtestcase", "MCQ Testcase"), ("hooktestcase", "Hook Testcase"), + ("integertestcase", "Integer Testcase"), ) UNAME_CHARS = letters + "._" + digits diff --git a/yaksh/models.py b/yaksh/models.py index 4292cc0..81b8d7f 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -40,6 +40,7 @@ question_types = ( ("mcc", "Multiple Correct Choices"), ("code", "Code"), ("upload", "Assignment Upload"), + ("integer", "Answer in Integer"), ) enrollment_methods = ( @@ -52,6 +53,7 @@ test_case_types = ( ("stdiobasedtestcase", "StdIO Based Testcase"), ("mcqtestcase", "MCQ Testcase"), ("hooktestcase", "Hook Testcase"), + ("integertestcase", "Integer Testcase"), ) attempts = [(i, i) for i in range(1, 6)] @@ -1133,6 +1135,11 @@ class AnswerPaper(models.Model): if set(user_answer) == set(expected_answers): result['success'] = True result['error'] = ['Correct answer'] + elif question.type == 'integer': + expected_answer = question.get_test_case().correct + if expected_answer == int(user_answer): + result['success'] = True + result['error'] = ['Correct answer'] elif question.type == 'code': user_dir = self.user.profile.get_user_dir() json_result = code_server.run_code( @@ -1280,3 +1287,12 @@ class HookTestCase(TestCase): def __str__(self): return u'Hook Testcase | Correct: {0}'.format(self.hook_code) + +class IntegerTestCase(TestCase): + correct = models.IntegerField(default=False) + + def get_field_value(self): + return {"test_case_type": "integertestcase", "correct": self.correct} + + def __str__(self): + return u'Integer Testcase | Correct: {0}'.format(self.correct) diff --git a/yaksh/templates/exam.html b/yaksh/templates/exam.html index b497cc0..ae1a620 100644 --- a/yaksh/templates/exam.html +++ b/yaksh/templates/exam.html @@ -84,9 +84,13 @@
{{ error }}

{% endfor %} - + {% if error != "Incorrect answer" %} +
Testcase No. {{ forloop.counter }}
+
{{ error }}
+ {% endif %} - {% endif %} + {% endfor %} + {% endif %} diff --git a/yaksh/templates/yaksh/add_question.html b/yaksh/templates/yaksh/add_question.html index 75802b4..a1b5e90 100644 --- a/yaksh/templates/yaksh/add_question.html +++ b/yaksh/templates/yaksh/add_question.html @@ -56,6 +56,7 @@ +

diff --git a/yaksh/templates/yaksh/grade_user.html b/yaksh/templates/yaksh/grade_user.html index 63ff5eb..7801b0b 100644 --- a/yaksh/templates/yaksh/grade_user.html +++ b/yaksh/templates/yaksh/grade_user.html @@ -139,6 +139,13 @@ Status : Passed
{{ forloop.counter }}. {{ testcase.options|safe }} {% endif %} {% endfor %} + + {% elif question.type == "integer" %} +
Correct Answer:
+ {% for testcase in question.get_test_cases %} + {{ testcase.correct }} + {% endfor %} + {% else %}
Test cases:
{% for testcase in question.get_test_cases %} diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index 27b2956..35c8052 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -149,6 +149,8 @@ function call_skip(url) (PROGRAMMING) {% elif question.type == "upload" %} (ASSIGNMENT UPLOAD) + {% elif question.type == "integer" %} + (ANSWER IN INTEGER) {% endif %}
(Marks : {{ question.points }}) @@ -167,6 +169,14 @@ function call_skip(url) {{ test_case.options|safe }}
{% endfor %} {% endif %} + + {% if question.type == "integer" %} + Enter Integer:     + +
+ {% endif %} + + {% if question.type == "mcc" %} {% for test_case in test_cases %} {{ test_case.options|safe }} @@ -192,10 +202,11 @@ function call_skip(url) {% endif %}
- {% if question.type == "mcq" or question.type == "mcc"%} + {% if question.type == "mcq" or question.type == "mcc" or question.type == "integer" %}
   {% elif question.type == "upload" %}
   + {% else %}    {% endif %} diff --git a/yaksh/templates/yaksh/user_data.html b/yaksh/templates/yaksh/user_data.html index 9be28fb..b667676 100644 --- a/yaksh/templates/yaksh/user_data.html +++ b/yaksh/templates/yaksh/user_data.html @@ -75,6 +75,14 @@ User IP address: {{ paper.user_ip }} {{ forloop.counter }}. {{ testcase.options|safe }} {% endif %} {% endfor %} + + {% elif question.type == "integer" %} +
Correct Answer:
+ {% for testcase in question.get_test_cases %} + {{ testcase.correct }} + {% endfor %} + + {% else %}
Test cases:
{% for testcase in question.get_test_cases %} diff --git a/yaksh/templates/yaksh/view_answerpaper.html b/yaksh/templates/yaksh/view_answerpaper.html index 5eb55df..76369db 100644 --- a/yaksh/templates/yaksh/view_answerpaper.html +++ b/yaksh/templates/yaksh/view_answerpaper.html @@ -51,6 +51,13 @@ {{ forloop.counter }}. {{ testcase.options|safe }} {% endif %} {% endfor %} + + {% elif question.type == "integer" %} +
Correct Answer:
+ {% for testcase in question.get_test_cases %} + {{ testcase.correct }} + {% endfor %} + {% else %}
Test cases:
{% for testcase in question.get_test_cases %} diff --git a/yaksh/views.py b/yaksh/views.py index 74c409c..996a3ce 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -25,7 +25,8 @@ import six # Local imports. from yaksh.models import get_model_class, Quiz, Question, QuestionPaper, QuestionSet, Course from yaksh.models import Profile, Answer, AnswerPaper, User, TestCase, FileUpload,\ - has_profile, StandardTestCase, McqTestCase, StdIOBasedTestCase, HookTestCase + has_profile, StandardTestCase, McqTestCase,\ + StdIOBasedTestCase, HookTestCase, IntegerTestCase from yaksh.forms import UserRegisterForm, UserLoginForm, QuizForm,\ QuestionForm, RandomQuestionForm,\ QuestionFilterForm, CourseForm, ProfileForm, UploadFileForm,\ @@ -468,6 +469,14 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): # Add the answer submitted, regardless of it being correct or not. if current_question.type == 'mcq': user_answer = request.POST.get('answer') + + elif current_question.type == 'integer': + try: + user_answer = int(request.POST.get('answer')) + except ValueError: + msg = ["Please enter an Integer Value"] + return show_question(request, current_question, paper, msg) + elif current_question.type == 'mcc': user_answer = request.POST.getlist('answer') elif current_question.type == 'upload': -- cgit From ddf3e13669f7232acf6019a0f2f33f397a6e6d51 Mon Sep 17 00:00:00 2001 From: maheshgudi Date: Mon, 30 Jan 2017 16:20:18 +0530 Subject: added string based questions. --- yaksh/forms.py | 2 +- yaksh/models.py | 34 ++++++++++++++++++++++++++++++++- yaksh/static/yaksh/css/question.css | 5 +++++ yaksh/templates/yaksh/add_question.html | 1 + yaksh/templates/yaksh/question.html | 11 +++++++++-- yaksh/views.py | 14 ++++++++++---- 6 files changed, 59 insertions(+), 8 deletions(-) diff --git a/yaksh/forms.py b/yaksh/forms.py index 4bf4fcf..df590de 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -1,7 +1,7 @@ from django import forms from yaksh.models import get_model_class, Profile, Quiz, Question, TestCase, Course,\ QuestionPaper, StandardTestCase, StdIOBasedTestCase, \ - HookTestCase, IntegerTestCase + HookTestCase, IntegerTestCase, StringTestCase from django.contrib.auth import authenticate from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType diff --git a/yaksh/models.py b/yaksh/models.py index 81b8d7f..6381d4b 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -41,6 +41,7 @@ question_types = ( ("code", "Code"), ("upload", "Assignment Upload"), ("integer", "Answer in Integer"), + ("string", "Answer in String"), ) enrollment_methods = ( @@ -54,6 +55,12 @@ test_case_types = ( ("mcqtestcase", "MCQ Testcase"), ("hooktestcase", "Hook Testcase"), ("integertestcase", "Integer Testcase"), + ("stringtestcase", "String Testcase"), + ) + +string_check_type = ( + ("lower", "Lower case Checking"), + ("exact", "Exact case String Checking"), ) attempts = [(i, i) for i in range(1, 6)] @@ -1135,11 +1142,24 @@ class AnswerPaper(models.Model): if set(user_answer) == set(expected_answers): result['success'] = True result['error'] = ['Correct answer'] + elif question.type == 'integer': expected_answer = question.get_test_case().correct if expected_answer == int(user_answer): result['success'] = True result['error'] = ['Correct answer'] + + elif question.type == 'string': + testcase = question.get_test_case() + if testcase.string_check == "lower": + if testcase.correct.lower() == user_answer.lower(): + result['success'] = True + result['error'] = ['Correct answer'] + else: + if testcase.correct == user_answer: + result['success'] = True + result['error'] = ['Correct answer'] + elif question.type == 'code': user_dir = self.user.profile.get_user_dir() json_result = code_server.run_code( @@ -1289,10 +1309,22 @@ class HookTestCase(TestCase): return u'Hook Testcase | Correct: {0}'.format(self.hook_code) class IntegerTestCase(TestCase): - correct = models.IntegerField(default=False) + correct = models.IntegerField(default=None) def get_field_value(self): return {"test_case_type": "integertestcase", "correct": self.correct} def __str__(self): return u'Integer Testcase | Correct: {0}'.format(self.correct) + + +class StringTestCase(TestCase): + correct = models.TextField(default=None) + string_check = models.CharField(max_length=200,choices=string_check_type) + + def get_field_value(self): + return {"test_case_type": "stringtestcase", "correct": self.correct, + "string_check":self.string_check} + + def __str__(self): + return u'String Testcase | Correct: {0}'.format(self.correct) diff --git a/yaksh/static/yaksh/css/question.css b/yaksh/static/yaksh/css/question.css index 9fb2e1a..fdbe5f2 100644 --- a/yaksh/static/yaksh/css/question.css +++ b/yaksh/static/yaksh/css/question.css @@ -36,3 +36,8 @@ .lineObj{ color: grey; } + +#string{ + width: 60em; + height: 10em; +} diff --git a/yaksh/templates/yaksh/add_question.html b/yaksh/templates/yaksh/add_question.html index a1b5e90..de3ce56 100644 --- a/yaksh/templates/yaksh/add_question.html +++ b/yaksh/templates/yaksh/add_question.html @@ -57,6 +57,7 @@ +

diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index 35c8052..13726c0 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -142,15 +142,17 @@ function call_skip(url)

{{ question.summary }} {% if question.type == "mcq" %} - (Single Correct Choice) + (SINGLE CORRECT CHOICE) {% elif question.type == "mcc" %} - (Multiple Correct Choices) + (MULTIPLE CORRECT CHOICES) {% elif question.type == "code" %} (PROGRAMMING) {% elif question.type == "upload" %} (ASSIGNMENT UPLOAD) {% elif question.type == "integer" %} (ANSWER IN INTEGER) + {% elif question.type == "string" %} + (ANSWER IN STRING) {% endif %} (Marks : {{ question.points }}) @@ -176,6 +178,11 @@ function call_skip(url)
{% endif %} + {% if question.type == "string" %} + Enter Text:
+ +

+ {% endif %} {% if question.type == "mcc" %} {% for test_case in test_cases %} diff --git a/yaksh/views.py b/yaksh/views.py index 996a3ce..6a19744 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -16,6 +16,7 @@ from django.contrib.auth.decorators import login_required from django.contrib.auth.models import Group from django.forms.models import inlineformset_factory from django.utils import timezone +from django.core.exceptions import MultipleObjectsReturned import pytz from taggit.models import Tag from itertools import chain @@ -469,13 +470,14 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): # Add the answer submitted, regardless of it being correct or not. if current_question.type == 'mcq': user_answer = request.POST.get('answer') - elif current_question.type == 'integer': try: user_answer = int(request.POST.get('answer')) except ValueError: msg = ["Please enter an Integer Value"] return show_question(request, current_question, paper, msg) + elif current_question.type == 'string': + user_answer = str(request.POST.get('answer')) elif current_question.type == 'mcc': user_answer = request.POST.getlist('answer') @@ -504,9 +506,13 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): # If we were not skipped, we were asked to check. For any non-mcq # questions, we obtain the results via XML-RPC with the code executed # safely in a separate process (the code_server.py) running as nobody. - json_data = current_question.consolidate_answer_data(user_answer) \ - if current_question.type == 'code' else None - result = paper.validate_answer(user_answer, current_question, json_data) + try: + json_data = current_question.consolidate_answer_data(user_answer) \ + if current_question.type == 'code' else None + result = paper.validate_answer(user_answer, current_question, json_data) + except MultipleObjectsReturned: + msg = ["Multiple objects returned. Contact admin."] + return show_question(request, current_question, paper, msg) if result.get('success'): new_answer.marks = (current_question.points * result['weight'] / current_question.get_maximum_test_case_weight()) \ -- cgit From 321343d45bc1f4d20cd348773bd8b214d9c4d692 Mon Sep 17 00:00:00 2001 From: maheshgudi Date: Fri, 3 Feb 2017 23:42:30 +0530 Subject: added float based questions --- yaksh/forms.py | 4 ++++ yaksh/models.py | 25 +++++++++++++++++++++++++ yaksh/templates/yaksh/add_question.html | 1 + yaksh/templates/yaksh/question.html | 10 +++++++++- yaksh/views.py | 6 ++++++ 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/yaksh/forms.py b/yaksh/forms.py index df590de..fdc881f 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -36,6 +36,8 @@ question_types = ( ("code", "Code"), ("upload", "Assignment Upload"), ("integer", "Answer in Integer"), + ("string", "Answer in String"), + ("float", "Answer in Decimal"), ) test_case_types = ( @@ -44,6 +46,8 @@ test_case_types = ( ("mcqtestcase", "MCQ Testcase"), ("hooktestcase", "Hook Testcase"), ("integertestcase", "Integer Testcase"), + ("stringtestcase", "String Testcase"), + ("floattestcase", "Float Testcase"), ) UNAME_CHARS = letters + "._" + digits diff --git a/yaksh/models.py b/yaksh/models.py index 6381d4b..12c4a1c 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -42,6 +42,7 @@ question_types = ( ("upload", "Assignment Upload"), ("integer", "Answer in Integer"), ("string", "Answer in String"), + ("float", "Answer in Decimal"), ) enrollment_methods = ( @@ -56,6 +57,7 @@ test_case_types = ( ("hooktestcase", "Hook Testcase"), ("integertestcase", "Integer Testcase"), ("stringtestcase", "String Testcase"), + ("floattestcase", "Float Testcase"), ) string_check_type = ( @@ -1160,6 +1162,14 @@ class AnswerPaper(models.Model): result['success'] = True result['error'] = ['Correct answer'] + elif question.type == 'float': + testcase = question.get_test_case() + if testcase.correct-testcase.error_margin\ + <= float(user_answer)\ + <= testcase.correct+testcase.error_margin: + result['success'] = True + result['error'] = ['Correct answer'] + elif question.type == 'code': user_dir = self.user.profile.get_user_dir() json_result = code_server.run_code( @@ -1328,3 +1338,18 @@ class StringTestCase(TestCase): def __str__(self): return u'String Testcase | Correct: {0}'.format(self.correct) + + +class FloatTestCase(TestCase): + correct = models.FloatField(default=None) + error_margin = models.FloatField(default=0.0, null=True, blank=True, + help_text="Margin of error") + + def get_field_value(self): + return {"test_case_type": "floattestcase", "correct": self.correct, + "error_margin":self.error_margin} + + def __str__(self): + return u'Testcase | Correct: {0} | Error Margin: +or- {1}'.format(self.correct, + self.error_margin + ) \ No newline at end of file diff --git a/yaksh/templates/yaksh/add_question.html b/yaksh/templates/yaksh/add_question.html index de3ce56..6bd96d3 100644 --- a/yaksh/templates/yaksh/add_question.html +++ b/yaksh/templates/yaksh/add_question.html @@ -58,6 +58,7 @@ +

diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index 13726c0..161db5a 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -153,6 +153,8 @@ function call_skip(url) (ANSWER IN INTEGER) {% elif question.type == "string" %} (ANSWER IN STRING) + {% elif question.type == "float" %} + (ANSWER IN DECIMAL) {% endif %} (Marks : {{ question.points }}) @@ -175,7 +177,7 @@ function call_skip(url) {% if question.type == "integer" %} Enter Integer:     -
+

{% endif %} {% if question.type == "string" %} @@ -184,6 +186,12 @@ function call_skip(url)

{% endif %} + {% if question.type == "float" %} + Enter Decimal Value :     + +

+ {% endif %} + {% if question.type == "mcc" %} {% for test_case in test_cases %} {{ test_case.options|safe }} diff --git a/yaksh/views.py b/yaksh/views.py index 6a19744..d067393 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -476,6 +476,12 @@ def check(request, q_id, attempt_num=None, questionpaper_id=None): except ValueError: msg = ["Please enter an Integer Value"] return show_question(request, current_question, paper, msg) + elif current_question.type == 'float': + try: + user_answer = float(request.POST.get('answer')) + except ValueError: + msg = ["Please enter a Decimal Value"] + return show_question(request, current_question, paper, msg) elif current_question.type == 'string': user_answer = str(request.POST.get('answer')) -- cgit From 23018fa38afcdfec93f1338bd783a769a0fe91e7 Mon Sep 17 00:00:00 2001 From: maheshgudi Date: Wed, 8 Feb 2017 17:48:55 +0530 Subject: changed string check names --- yaksh/forms.py | 2 +- yaksh/models.py | 14 ++++++-------- yaksh/templates/yaksh/question.html | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/yaksh/forms.py b/yaksh/forms.py index fdc881f..c6283c8 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -37,7 +37,7 @@ question_types = ( ("upload", "Assignment Upload"), ("integer", "Answer in Integer"), ("string", "Answer in String"), - ("float", "Answer in Decimal"), + ("float", "Answer in Float"), ) test_case_types = ( diff --git a/yaksh/models.py b/yaksh/models.py index 12c4a1c..665805e 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -42,7 +42,7 @@ question_types = ( ("upload", "Assignment Upload"), ("integer", "Answer in Integer"), ("string", "Answer in String"), - ("float", "Answer in Decimal"), + ("float", "Answer in Float"), ) enrollment_methods = ( @@ -61,8 +61,8 @@ test_case_types = ( ) string_check_type = ( - ("lower", "Lower case Checking"), - ("exact", "Exact case String Checking"), + ("lower", "Case Insensitive"), + ("exact", "Case Sensitive"), ) attempts = [(i, i) for i in range(1, 6)] @@ -1154,19 +1154,17 @@ class AnswerPaper(models.Model): elif question.type == 'string': testcase = question.get_test_case() if testcase.string_check == "lower": - if testcase.correct.lower() == user_answer.lower(): + if testcase.correct.lower().splitlines() == user_answer.lower().splitlines(): result['success'] = True result['error'] = ['Correct answer'] else: - if testcase.correct == user_answer: + if testcase.correct.splitlines() == user_answer.splitlines(): result['success'] = True result['error'] = ['Correct answer'] elif question.type == 'float': testcase = question.get_test_case() - if testcase.correct-testcase.error_margin\ - <= float(user_answer)\ - <= testcase.correct+testcase.error_margin: + if abs(testcase.correct-user_answer) <= testcase.error_margin: result['success'] = True result['error'] = ['Correct answer'] diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index 161db5a..930c57d 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -154,7 +154,7 @@ function call_skip(url) {% elif question.type == "string" %} (ANSWER IN STRING) {% elif question.type == "float" %} - (ANSWER IN DECIMAL) + (ANSWER IN FLOAT) {% endif %} (Marks : {{ question.points }}) -- cgit From a7a54b43f36571adc5bb999f454fe57e1dcb5c0f Mon Sep 17 00:00:00 2001 From: maheshgudi Date: Thu, 9 Feb 2017 00:48:34 +0530 Subject: added test cases for float,integer and string type questions --- .../evaluator_tests/test_simple_question_types.py | 296 +++++++++++++++++++++ yaksh/models.py | 2 +- 2 files changed, 297 insertions(+), 1 deletion(-) create mode 100644 yaksh/evaluator_tests/test_simple_question_types.py diff --git a/yaksh/evaluator_tests/test_simple_question_types.py b/yaksh/evaluator_tests/test_simple_question_types.py new file mode 100644 index 0000000..ca93220 --- /dev/null +++ b/yaksh/evaluator_tests/test_simple_question_types.py @@ -0,0 +1,296 @@ +import unittest +from datetime import datetime, timedelta +from django.utils import timezone +import pytz +from yaksh.models import User, Profile, Question, Quiz, QuestionPaper,\ + QuestionSet, AnswerPaper, Answer, Course, IntegerTestCase, FloatTestCase,\ + StringTestCase + + +def setUpModule(): + # create user profile + user = User.objects.create_user(pk=1,username='demo_user', + password='demo', + email='demo@test.com') + Profile.objects.create(user=user, roll_number=1, + institute='IIT', department='Aerospace', + position='Student') + + # create 2 questions + for i in range(101, 103): + Question.objects.create(summary='Q%d' % (i), points=1, + type='code', user=user) + + # create a course + course = Course.objects.create(name="Python Course", + enrollment="Enroll Request", creator=user) + + quiz = Quiz.objects.create(start_date_time=datetime(2015, 10, 9, 10, 8, 15, 0, + tzinfo=pytz.utc), + end_date_time=datetime(2199, 10, 9, 10, 8, 15, 0, + tzinfo=pytz.utc), + duration=30, active=True, attempts_allowed=1, + time_between_attempts=0, description='demo quiz', + pass_criteria=0,language='Python', + prerequisite=None,course=course, + instructions="Demo Instructions" + ) + question_paper = QuestionPaper.objects.create(pk=1, quiz=quiz, + total_marks=1.0) + + answerpaper = AnswerPaper.objects.create(user=user, user_ip='101.0.0.1', + start_time=timezone.now(), + question_paper=question_paper, + end_time=timezone.now() + +timedelta(minutes=5), + attempt_number=1 + ) + + with open('/tmp/test.txt', 'wb') as f: + f.write('2'.encode('ascii')) + +def tearDownModule(): + User.objects.all().delete() + Question.objects.all().delete() + Quiz.objects.all().delete() + + +class IntegerQuestionTestCases(unittest.TestCase): + @classmethod + def setUpClass(self): + # Creating Quiz + # Creating Question paper + self.question_paper = QuestionPaper.objects.get(pk=1) + + #Creating User + self.user = User.objects.get(pk=1) + + #Creating Question + self.question1 = Question.objects.get(summary='Q101') + self.question1.language = 'python' + self.question1.type = "integer" + self.question1.test_case_type = 'integertestcase' + self.question1.description = 'sum of 12+13?' + self.question1.save() + + #Creating answerpaper + self.answerpaper = AnswerPaper.objects.get(question_paper\ + =self.question_paper) + self.answerpaper.attempt_number = 1 + self.answerpaper.save() + # For question + self.integer_based_testcase = IntegerTestCase(question=self.question1, + correct=25, + type = 'integertestcase', + ) + self.integer_based_testcase.save() + + def test_integer_correct_answer(self): + # Given + integer_answer = 25 + self.answer = Answer(question=self.question1, + answer=integer_answer, + ) + self.answer.save() + self.answerpaper.answers.add(self.answer) + + # When + json_data = None + result = self.answerpaper.validate_answer(integer_answer, + self.question1, + json_data, + ) + # Then + self.assertTrue(result['success']) + + def test_integer_incorrect_answer(self): + # Given + integer_answer = 26 + self.answer = Answer(question=self.question1, + answer=integer_answer, + ) + self.answer.save() + self.answerpaper.answers.add(self.answer) + + # When + json_data = None + result = self.answerpaper.validate_answer(integer_answer, + self.question1, json_data + ) + + # Then + self.assertFalse(result['success']) + + +class StringQuestionTestCases(unittest.TestCase): + @classmethod + def setUpClass(self): + # Creating Question paper + self.question_paper = QuestionPaper.objects.get(pk=1) + + #Creating User + self.user = User.objects.get(pk=1) + + #Creating Question + self.question1 = Question.objects.get(summary='Q101') + self.question1.language = 'python' + self.question1.type = "string" + self.question1.test_case_type = 'stringtestcase' + self.question1.description = 'Write Hello, EARTH!' + self.question1.save() + + self.question2 = Question.objects.get(summary='Q102') + self.question2.language = 'python' + self.question2.type = "string" + self.question2.test_case_type = 'stringtestcase' + self.question2.description = 'Write Hello, EARTH!' + self.question2.save() + + #Creating answerpaper + self.answerpaper = AnswerPaper.objects.get(question_paper\ + =self.question_paper) + self.answerpaper.attempt_number = 1 + self.answerpaper.save() + + # For question + self.lower_string_testcase = StringTestCase(question=self.question1, + correct="Hello, EARTH!", + string_check="lower", + type = 'stringtestcase', + ) + self.lower_string_testcase.save() + + self.exact_string_testcase = StringTestCase(question=self.question2, + correct="Hello, EARTH!", + string_check="exact", + type = 'stringtestcase', + ) + self.exact_string_testcase.save() + + def test_case_insensitive_string_correct_answer(self): + # Given + string_answer = "hello, earth!" + answer = Answer(question=self.question1,answer=string_answer) + answer.save() + self.answerpaper.answers.add(answer) + + # When + json_data = None + result = self.answerpaper.validate_answer(string_answer, + self.question1, json_data + ) + # Then + self.assertTrue(result['success']) + + def test_case_insensitive_string_incorrect_answer(self): + # Given + string_answer = "hello, mars!" + answer = Answer(question=self.question1,answer=string_answer) + answer.save() + self.answerpaper.answers.add(answer) + + # When + json_data = None + result = self.answerpaper.validate_answer(string_answer, + self.question1, json_data + ) + + # Then + self.assertFalse(result['success']) + + def test_case_sensitive_string_correct_answer(self): + # Given + string_answer = "Hello, EARTH!" + answer = Answer(question=self.question2,answer=string_answer) + answer.save() + self.answerpaper.answers.add(answer) + + # When + json_data = None + result = self.answerpaper.validate_answer(string_answer, + self.question2, json_data + ) + # Then + self.assertTrue(result['success']) + + def test_case_sensitive_string_incorrect_answer(self): + # Given + string_answer = "hello, earth!" + answer = Answer(question=self.question2,answer=string_answer) + answer.save() + self.answerpaper.answers.add(answer) + + # When + json_data = None + result = self.answerpaper.validate_answer(string_answer, + self.question2, json_data + ) + + # Then + self.assertFalse(result['success']) + + +class FloatQuestionTestCases(unittest.TestCase): + @classmethod + def setUpClass(self): + #Creating User + self.user = User.objects.get(pk=1) + + # Creating Question paper + self.question_paper = QuestionPaper.objects.get(pk=1) + + #Creating Question + self.question1 = Question.objects.get(summary='Q101') + self.question1.language = 'python' + self.question1.type = "float" + self.question1.test_case_type = 'floattestcase' + self.question1.save() + + #Creating answerpaper + self.answerpaper = AnswerPaper.objects.get(question_paper\ + =self.question_paper) + self.answerpaper.attempt_number = 1 + self.answerpaper.save() + # For question + self.float_based_testcase = FloatTestCase(question=self.question1, + correct=100, + error_margin=0.1, + type = 'floattestcase', + ) + self.float_based_testcase.save() + + def test_float_correct_answer(self): + # Given + float_answer = 99.9 + self.answer = Answer(question=self.question1, + answer=float_answer, + ) + self.answer.save() + self.answerpaper.answers.add(self.answer) + + # When + json_data = None + result = self.answerpaper.validate_answer(float_answer, + self.question1, + json_data, + ) + # Then + self.assertTrue(result['success']) + + def test_integer_incorrect_answer(self): + # Given + float_answer = 99.8 + self.answer = Answer(question=self.question1, + answer=float_answer, + ) + self.answer.save() + self.answerpaper.answers.add(self.answer) + + # When + json_data = None + result = self.answerpaper.validate_answer(float_answer, + self.question1, json_data + ) + + # Then + self.assertFalse(result['success']) diff --git a/yaksh/models.py b/yaksh/models.py index 665805e..a356ec1 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -1350,4 +1350,4 @@ class FloatTestCase(TestCase): def __str__(self): return u'Testcase | Correct: {0} | Error Margin: +or- {1}'.format(self.correct, self.error_margin - ) \ No newline at end of file + ) -- cgit From bb95cc5a42a54e895a0b16d907af3bb9a267990d Mon Sep 17 00:00:00 2001 From: maheshgudi Date: Thu, 9 Feb 2017 01:36:41 +0530 Subject: modified answerpaper views for integer, float and string type --- yaksh/db.cnf | 5 ----- yaksh/templates/yaksh/grade_user.html | 4 ++-- yaksh/templates/yaksh/question.html | 8 +++++++- yaksh/templates/yaksh/user_data.html | 4 ++-- yaksh/templates/yaksh/view_answerpaper.html | 4 ++-- 5 files changed, 13 insertions(+), 12 deletions(-) delete mode 100644 yaksh/db.cnf diff --git a/yaksh/db.cnf b/yaksh/db.cnf deleted file mode 100644 index 22c68e3..0000000 --- a/yaksh/db.cnf +++ /dev/null @@ -1,5 +0,0 @@ -# new.cnf -[client] -database = online_test -user = root -default-character-set = utf8 diff --git a/yaksh/templates/yaksh/grade_user.html b/yaksh/templates/yaksh/grade_user.html index 7801b0b..8653dc7 100644 --- a/yaksh/templates/yaksh/grade_user.html +++ b/yaksh/templates/yaksh/grade_user.html @@ -140,10 +140,10 @@ Status : Passed
{% endif %} {% endfor %} - {% elif question.type == "integer" %} + {% elif question.type == "integer" or "string" or "float" %}
Correct Answer:
{% for testcase in question.get_test_cases %} - {{ testcase.correct }} + {{ testcase.correct|safe }} {% endfor %} {% else %} diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index 930c57d..bfc90a8 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -153,6 +153,12 @@ function call_skip(url) (ANSWER IN INTEGER) {% elif question.type == "string" %} (ANSWER IN STRING) + {% if testcase.string_check == "lower" %} +
(CASE INSENSITIVE)
+ {% else %} +
(CASE SENSITIVE)
+ {% endif %} + {% elif question.type == "float" %} (ANSWER IN FLOAT) {% endif %} @@ -217,7 +223,7 @@ function call_skip(url) {% endif %}
- {% if question.type == "mcq" or question.type == "mcc" or question.type == "integer" %} + {% if question.type == "mcq" or "mcc" or "integer" or "float" or "string" %}
   {% elif question.type == "upload" %}
   diff --git a/yaksh/templates/yaksh/user_data.html b/yaksh/templates/yaksh/user_data.html index b667676..832e343 100644 --- a/yaksh/templates/yaksh/user_data.html +++ b/yaksh/templates/yaksh/user_data.html @@ -76,10 +76,10 @@ User IP address: {{ paper.user_ip }} {% endif %} {% endfor %} - {% elif question.type == "integer" %} + {{% elif question.type == "integer" or "string" or "float" %}
Correct Answer:
{% for testcase in question.get_test_cases %} - {{ testcase.correct }} + {{ testcase.correct|safe }} {% endfor %} diff --git a/yaksh/templates/yaksh/view_answerpaper.html b/yaksh/templates/yaksh/view_answerpaper.html index 76369db..633be9e 100644 --- a/yaksh/templates/yaksh/view_answerpaper.html +++ b/yaksh/templates/yaksh/view_answerpaper.html @@ -52,10 +52,10 @@ {% endif %} {% endfor %} - {% elif question.type == "integer" %} + {% elif question.type == "integer" or "string" or "float" %}
Correct Answer:
{% for testcase in question.get_test_cases %} - {{ testcase.correct }} + {{ testcase.correct|safe }} {% endfor %} {% else %} -- cgit From 211c12eb1c2002945e228e0f33cd45d494df74ff Mon Sep 17 00:00:00 2001 From: maheshgudi Date: Thu, 2 Mar 2017 20:33:34 +0530 Subject: removed pk/id based querying in test cases --- .../evaluator_tests/test_simple_question_types.py | 38 ++++--- yaksh/models.py | 1 - yaksh/test_models.py | 110 +++++++++++---------- 3 files changed, 74 insertions(+), 75 deletions(-) diff --git a/yaksh/evaluator_tests/test_simple_question_types.py b/yaksh/evaluator_tests/test_simple_question_types.py index ca93220..1d0a1e2 100644 --- a/yaksh/evaluator_tests/test_simple_question_types.py +++ b/yaksh/evaluator_tests/test_simple_question_types.py @@ -9,20 +9,19 @@ from yaksh.models import User, Profile, Question, Quiz, QuestionPaper,\ def setUpModule(): # create user profile - user = User.objects.create_user(pk=1,username='demo_user', + user = User.objects.create_user(username='demo_user_100', password='demo', email='demo@test.com') Profile.objects.create(user=user, roll_number=1, institute='IIT', department='Aerospace', position='Student') - # create 2 questions for i in range(101, 103): Question.objects.create(summary='Q%d' % (i), points=1, type='code', user=user) # create a course - course = Course.objects.create(name="Python Course", + course = Course.objects.create(name="Python Course 100", enrollment="Enroll Request", creator=user) quiz = Quiz.objects.create(start_date_time=datetime(2015, 10, 9, 10, 8, 15, 0, @@ -30,12 +29,12 @@ def setUpModule(): end_date_time=datetime(2199, 10, 9, 10, 8, 15, 0, tzinfo=pytz.utc), duration=30, active=True, attempts_allowed=1, - time_between_attempts=0, description='demo quiz', + time_between_attempts=0, description='demo quiz 100', pass_criteria=0,language='Python', prerequisite=None,course=course, instructions="Demo Instructions" ) - question_paper = QuestionPaper.objects.create(pk=1, quiz=quiz, + question_paper = QuestionPaper.objects.create(quiz=quiz, total_marks=1.0) answerpaper = AnswerPaper.objects.create(user=user, user_ip='101.0.0.1', @@ -46,24 +45,20 @@ def setUpModule(): attempt_number=1 ) - with open('/tmp/test.txt', 'wb') as f: - f.write('2'.encode('ascii')) - def tearDownModule(): - User.objects.all().delete() - Question.objects.all().delete() - Quiz.objects.all().delete() + User.objects.get(username="demo_user_100").delete() class IntegerQuestionTestCases(unittest.TestCase): @classmethod def setUpClass(self): # Creating Quiz + self.quiz = Quiz.objects.get(description="demo quiz 100") # Creating Question paper - self.question_paper = QuestionPaper.objects.get(pk=1) + self.question_paper = QuestionPaper.objects.get(quiz=self.quiz) #Creating User - self.user = User.objects.get(pk=1) + self.user = User.objects.get(username='demo_user_100') #Creating Question self.question1 = Question.objects.get(summary='Q101') @@ -125,12 +120,12 @@ class IntegerQuestionTestCases(unittest.TestCase): class StringQuestionTestCases(unittest.TestCase): @classmethod def setUpClass(self): + # Creating Quiz + self.quiz = Quiz.objects.get(description="demo quiz 100") # Creating Question paper - self.question_paper = QuestionPaper.objects.get(pk=1) - + self.question_paper = QuestionPaper.objects.get(quiz=self.quiz) #Creating User - self.user = User.objects.get(pk=1) - + self.user = User.objects.get(username='demo_user_100') #Creating Question self.question1 = Question.objects.get(summary='Q101') self.question1.language = 'python' @@ -233,12 +228,13 @@ class StringQuestionTestCases(unittest.TestCase): class FloatQuestionTestCases(unittest.TestCase): @classmethod def setUpClass(self): - #Creating User - self.user = User.objects.get(pk=1) - + # Creating Quiz + self.quiz = Quiz.objects.get(description="demo quiz 100") # Creating Question paper - self.question_paper = QuestionPaper.objects.get(pk=1) + self.question_paper = QuestionPaper.objects.get(quiz=self.quiz) + #Creating User + self.user = User.objects.get(username='demo_user_100') #Creating Question self.question1 = Question.objects.get(summary='Q101') self.question1.language = 'python' diff --git a/yaksh/models.py b/yaksh/models.py index a356ec1..d60a377 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -683,7 +683,6 @@ class QuestionPaper(models.Model): # Total marks for the question paper. total_marks = models.FloatField(default=0.0, blank=True) - objects = QuestionPaperManager() def update_total_marks(self): diff --git a/yaksh/test_models.py b/yaksh/test_models.py index 91d8806..ada5a65 100644 --- a/yaksh/test_models.py +++ b/yaksh/test_models.py @@ -44,7 +44,7 @@ def setUpModule(): tzinfo=pytz.utc), duration=30, active=True, attempts_allowed=1, time_between_attempts=0, - description='demo quiz', pass_criteria=0, + description='demo quiz 1', pass_criteria=0, language='Python', prerequisite=None, course=course, instructions="Demo Instructions") @@ -54,7 +54,7 @@ def setUpModule(): tzinfo=pytz.utc), duration=30, active=False, attempts_allowed=-1, time_between_attempts=0, - description='demo quiz', pass_criteria=40, + description='demo quiz 2', pass_criteria=40, language='Python', prerequisite=quiz, course=course, instructions="Demo Instructions") @@ -65,6 +65,8 @@ def tearDownModule(): User.objects.all().delete() Question.objects.all().delete() Quiz.objects.all().delete() + Course.objects.all().delete() + QuestionPaper.objects.all().delete() que_id_list = ["25", "22", "24", "27"] for que_id in que_id_list: @@ -75,9 +77,9 @@ def tearDownModule(): ############################################################################### class ProfileTestCases(unittest.TestCase): def setUp(self): - self.user1 = User.objects.get(pk=1) - self.profile = Profile.objects.get(pk=1) - self.user2 = User.objects.get(pk=3) + self.user1 = User.objects.get(username="demo_user") + self.profile = Profile.objects.get(user=self.user1) + self.user2 = User.objects.get(username='demo_user3') def test_user_profile(self): """ Test user profile""" @@ -92,9 +94,9 @@ class ProfileTestCases(unittest.TestCase): class QuestionTestCases(unittest.TestCase): def setUp(self): # Single question details - self.user1 = User.objects.get(pk=1) - self.user2 = User.objects.get(pk=2) - self.question1 = Question(summary='Demo question', + self.user1 = User.objects.get(username="demo_user") + self.user2 = User.objects.get(username="demo_user2") + self.question1 = Question.objects.create(summary='Demo Python 1', language='Python', type='Code', active=True, @@ -103,9 +105,8 @@ class QuestionTestCases(unittest.TestCase): snippet='def myfunc()', user=self.user1 ) - self.question1.save() - self.question2 = Question(summary='Demo Json', + self.question2 = Question.objects.create(summary='Demo Json', language='python', type='code', active=True, @@ -114,7 +115,6 @@ class QuestionTestCases(unittest.TestCase): snippet='def fact()', user=self.user2 ) - self.question2.save() # create a temp directory and add files for loading questions test file_path = "/tmp/test.txt" @@ -161,7 +161,7 @@ class QuestionTestCases(unittest.TestCase): def test_question(self): """ Test question """ - self.assertEqual(self.question1.summary, 'Demo question') + self.assertEqual(self.question1.summary, 'Demo Python 1') self.assertEqual(self.question1.language, 'Python') self.assertEqual(self.question1.type, 'Code') self.assertEqual(self.question1.description, 'Write a function') @@ -203,8 +203,8 @@ class QuestionTestCases(unittest.TestCase): """ Test load questions into database from json """ question = Question() result = question.load_questions(self.json_questions_data, self.user1) - question_data = Question.objects.get(pk=25) - file = FileUpload.objects.get(question=25) + question_data = Question.objects.get(summary="Json Demo") + file = FileUpload.objects.get(question=question_data) test_case = question_data.get_test_cases() self.assertEqual(question_data.summary, 'Json Demo') self.assertEqual(question_data.language, 'Python') @@ -220,10 +220,10 @@ class QuestionTestCases(unittest.TestCase): ############################################################################### class QuizTestCases(unittest.TestCase): def setUp(self): - self.creator = User.objects.get(pk=1) - self.teacher = User.objects.get(pk=2) - self.quiz1 = Quiz.objects.get(pk=1) - self.quiz2 = Quiz.objects.get(pk=2) + self.creator = User.objects.get(username="demo_user") + self.teacher = User.objects.get(username="demo_user2") + self.quiz1 = Quiz.objects.get(description='demo quiz 1') + self.quiz2 = Quiz.objects.get(description='demo quiz 2') self.trial_course = Course.objects.create_trial_course(self.creator) def test_quiz(self): @@ -234,7 +234,7 @@ class QuizTestCases(unittest.TestCase): '10:08:15') self.assertEqual(self.quiz1.duration, 30) self.assertTrue(self.quiz1.active) - self.assertEqual(self.quiz1.description, 'demo quiz') + self.assertEqual(self.quiz1.description, 'demo quiz 1') self.assertEqual(self.quiz1.language, 'Python') self.assertEqual(self.quiz1.pass_criteria, 0) self.assertEqual(self.quiz1.prerequisite, None) @@ -270,7 +270,9 @@ class QuizTestCases(unittest.TestCase): self.creator, True ) - self.assertEqual(trial_quiz.description, "Trial_orig_id_1_godmode") + self.assertEqual(trial_quiz.description, + "Trial_orig_id_{}_godmode".format(self.quiz1.id) + ) self.assertTrue(trial_quiz.is_trial) self.assertEqual(trial_quiz.duration, 1000) self.assertTrue(trial_quiz.active) @@ -285,7 +287,8 @@ class QuizTestCases(unittest.TestCase): self.creator, False ) - self.assertEqual(trial_quiz.description, "Trial_orig_id_2_usermode") + self.assertEqual(trial_quiz.description, + "Trial_orig_id_{}_usermode".format(self.quiz2.id)) self.assertTrue(trial_quiz.is_trial) self.assertEqual(trial_quiz.duration, self.quiz2.duration) self.assertEqual(trial_quiz.active, self.quiz2.active) @@ -316,7 +319,7 @@ class QuestionPaperTestCases(unittest.TestCase): def setUpClass(self): # All active questions self.questions = Question.objects.filter(active=True) - self.quiz = Quiz.objects.get(id=1) + self.quiz = Quiz.objects.get(description="demo quiz 1") # create question paper self.question_paper = QuestionPaper.objects.create(quiz=self.quiz, @@ -359,7 +362,7 @@ class QuestionPaperTestCases(unittest.TestCase): # ip address for AnswerPaper self.ip = '127.0.0.1' - self.user = User.objects.get(pk=1) + self.user = User.objects.get(username="demo_user") self.attempted_papers = AnswerPaper.objects.filter( question_paper=self.question_paper, @@ -373,7 +376,7 @@ class QuestionPaperTestCases(unittest.TestCase): def test_questionpaper(self): """ Test question paper""" - self.assertEqual(self.question_paper.quiz.description, 'demo quiz') + self.assertEqual(self.question_paper.quiz.description, 'demo quiz 1') self.assertSequenceEqual(self.question_paper.fixed_questions.all(), [self.questions[3], self.questions[5]]) self.assertTrue(self.question_paper.shuffle_questions) @@ -453,17 +456,17 @@ class AnswerPaperTestCases(unittest.TestCase): @classmethod def setUpClass(self): self.ip = '101.0.0.1' - self.user = User.objects.get(id=1) + self.user = User.objects.get(username='demo_user') self.profile = self.user.profile - self.quiz = Quiz.objects.get(pk=1) + self.quiz = Quiz.objects.get(description='demo quiz 1') self.question_paper = QuestionPaper(quiz=self.quiz, total_marks=3) self.question_paper.save() - self.questions = Question.objects.filter(id__in=[1,2,3]) + self.questions = Question.objects.all()[0:3] self.start_time = timezone.now() self.end_time = self.start_time + timedelta(minutes=20) - self.question1 = self.questions.get(id=1) - self.question2 = self.questions.get(id=2) - self.question3 = self.questions.get(id=3) + self.question1 = self.questions[0] + self.question2 = self.questions[1] + self.question3 = self.questions[2] # create answerpaper self.answerpaper = AnswerPaper(user=self.user, @@ -483,12 +486,12 @@ class AnswerPaperTestCases(unittest.TestCase): self.answerpaper.questions_unanswered.add(*self.questions) self.answerpaper.save() # answers for the Answer Paper - self.answer_right = Answer(question=Question.objects.get(id=1), + self.answer_right = Answer(question=self.question1, answer="Demo answer", correct=True, marks=1, error=json.dumps([]) ) - self.answer_wrong = Answer(question=Question.objects.get(id=2), + self.answer_wrong = Answer(question=self.question2, answer="My answer", correct=False, marks=0, @@ -501,14 +504,17 @@ class AnswerPaperTestCases(unittest.TestCase): self.question1.language = 'python' self.question1.test_case_type = 'standardtestcase' + self.question1.summary = "Question1" self.question1.save() self.question2.language = 'python' self.question2.type = 'mcq' self.question2.test_case_type = 'mcqtestcase' + self.question2.summary = "Question2" self.question2.save() self.question3.language = 'python' self.question3.type = 'mcc' self.question3.test_case_type = 'mcqtestcase' + self.question3.summary = "Question3" self.question3.save() self.assertion_testcase = StandardTestCase( question=self.question1, @@ -660,21 +666,21 @@ class AnswerPaperTestCases(unittest.TestCase): self.assertEqual(self.answerpaper.questions_left(), 3) # Test current_question() method of Answer Paper current_question = self.answerpaper.current_question() - self.assertEqual(current_question.id, 1) + self.assertEqual(current_question.summary, "Question1") # Test completed_question() method of Answer Paper - question = self.answerpaper.completed_question(1) + question = self.answerpaper.completed_question(self.question1.id) self.assertEqual(self.answerpaper.questions_left(), 2) # Test next_question() method of Answer Paper current_question = self.answerpaper.current_question() - self.assertEqual(current_question.id, 2) + self.assertEqual(current_question.summary, "Question2") # When next_question_id = self.answerpaper.next_question(current_question.id) # Then self.assertTrue(next_question_id is not None) - self.assertEqual(next_question_id.id, 3) + self.assertEqual(next_question_id.summary, "Question3") # Given, here question is already answered current_question_id = 1 @@ -684,7 +690,7 @@ class AnswerPaperTestCases(unittest.TestCase): # Then self.assertTrue(next_question_id is not None) - self.assertEqual(next_question_id.id, 2) + self.assertEqual(next_question_id.summary, "Question2") # Given, wrong question id current_question_id = 12 @@ -694,7 +700,7 @@ class AnswerPaperTestCases(unittest.TestCase): # Then self.assertTrue(next_question_id is not None) - self.assertEqual(next_question_id.id, 2) + self.assertEqual(next_question_id.summary, "Question2") # Given, last question in the list current_question_id = 3 @@ -704,7 +710,7 @@ class AnswerPaperTestCases(unittest.TestCase): # Then self.assertTrue(next_question_id is not None) - self.assertEqual(next_question_id.id, 2) + self.assertEqual(next_question_id.summary, "Question2") # Test get_questions_answered() method # When @@ -724,14 +730,14 @@ class AnswerPaperTestCases(unittest.TestCase): # Test completed_question and next_question # When all questions are answered - current_question = self.answerpaper.completed_question(2) + current_question = self.answerpaper.completed_question(self.question2.id) # Then self.assertEqual(self.answerpaper.questions_left(), 1) - self.assertEqual(current_question.id, 3) + self.assertEqual(current_question.summary, "Question3") # When - current_question = self.answerpaper.completed_question(3) + current_question = self.answerpaper.completed_question(self.question3.id) # Then self.assertEqual(self.answerpaper.questions_left(), 0) @@ -791,12 +797,12 @@ class AnswerPaperTestCases(unittest.TestCase): ############################################################################### class CourseTestCases(unittest.TestCase): def setUp(self): - self.course = Course.objects.get(pk=1) - self.creator = User.objects.get(pk=1) - self.student1 = User.objects.get(pk=2) - self.student2 = User.objects.get(pk=3) - self.quiz1 = Quiz.objects.get(pk=1) - self.quiz2 = Quiz.objects.get(pk=2) + self.course = Course.objects.get(name="Python Course") + self.creator = User.objects.get(username="demo_user") + self.student1 = User.objects.get(username="demo_user2") + self.student2 = User.objects.get(username="demo_user3") + self.quiz1 = Quiz.objects.get(description='demo quiz 1') + self.quiz2 = Quiz.objects.get(description='demo quiz 2') def test_is_creator(self): @@ -873,21 +879,19 @@ class CourseTestCases(unittest.TestCase): def test_create_trial_course(self): """Test to check if trial course is created""" - # Test for manager method create_trial_course trial_course = Course.objects.create_trial_course(self.creator) self.assertEqual(trial_course.name, "trial_course") self.assertEqual(trial_course.enrollment, "open") self.assertTrue(trial_course.active) - self.assertEqual(trial_course.students.get(user=self.creator.id), - self.creator - ) + self.assertEqual(self.creator, trial_course.creator) + self.assertIn(self.creator, trial_course.students.all()) self.assertTrue(trial_course.is_trial) ############################################################################### class TestCaseTestCases(unittest.TestCase): def setUp(self): - self.user = User.objects.get(pk=1) + self.user = User.objects.get(username="demo_user") self.question1 = Question(summary='Demo question 1', language='Python', type='Code', -- cgit From 1c5e1dfef3fb4af8bc070fe190cec552ef3732b0 Mon Sep 17 00:00:00 2001 From: maheshgudi Date: Thu, 9 Mar 2017 01:18:51 +0530 Subject: pep8 changes in models and user_data --- yaksh/models.py | 7 ++++--- yaksh/templates/yaksh/user_data.html | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/yaksh/models.py b/yaksh/models.py index d60a377..fdf10bd 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -1153,7 +1153,8 @@ class AnswerPaper(models.Model): elif question.type == 'string': testcase = question.get_test_case() if testcase.string_check == "lower": - if testcase.correct.lower().splitlines() == user_answer.lower().splitlines(): + if testcase.correct.lower().splitlines()\ + == user_answer.lower().splitlines(): result['success'] = True result['error'] = ['Correct answer'] else: @@ -1164,8 +1165,8 @@ class AnswerPaper(models.Model): elif question.type == 'float': testcase = question.get_test_case() if abs(testcase.correct-user_answer) <= testcase.error_margin: - result['success'] = True - result['error'] = ['Correct answer'] + result['success'] = True + result['error'] = ['Correct answer'] elif question.type == 'code': user_dir = self.user.profile.get_user_dir() diff --git a/yaksh/templates/yaksh/user_data.html b/yaksh/templates/yaksh/user_data.html index 832e343..0bfd00e 100644 --- a/yaksh/templates/yaksh/user_data.html +++ b/yaksh/templates/yaksh/user_data.html @@ -76,7 +76,7 @@ User IP address: {{ paper.user_ip }} {% endif %} {% endfor %} - {{% elif question.type == "integer" or "string" or "float" %} + {% elif question.type == "integer" or "string" or "float" %}
Correct Answer:
{% for testcase in question.get_test_cases %} {{ testcase.correct|safe }} -- cgit From ac292ed1099b49f9d0e8a7ed3699bacdd8031de3 Mon Sep 17 00:00:00 2001 From: maheshgudi Date: Sat, 11 Mar 2017 02:17:41 +0530 Subject: made minor template changes and fixed test_models --- yaksh/models.py | 11 ++++++----- yaksh/templates/exam.html | 8 ++------ yaksh/templates/yaksh/question.html | 4 ++-- yaksh/test_models.py | 18 +++++++++++------- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/yaksh/models.py b/yaksh/models.py index a323994..d583f7b 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -1163,13 +1163,14 @@ class AnswerPaper(models.Model): result['success'] = True result['error'] = ['Correct answer'] else: - if testcase.correct.splitlines() == user_answer.splitlines(): + if testcase.correct.splitlines()\ + == user_answer.splitlines(): result['success'] = True result['error'] = ['Correct answer'] elif question.type == 'float': testcase = question.get_test_case() - if abs(testcase.correct-user_answer) <= testcase.error_margin: + if abs(testcase.correct - user_answer) <= testcase.error_margin: result['success'] = True result['error'] = ['Correct answer'] @@ -1353,6 +1354,6 @@ class FloatTestCase(TestCase): "error_margin":self.error_margin} def __str__(self): - return u'Testcase | Correct: {0} | Error Margin: +or- {1}'.format(self.correct, - self.error_margin - ) + return u'Testcase | Correct: {0} | Error Margin: +or- {1}'.format( + self.correct, self.error_margin + ) diff --git a/yaksh/templates/exam.html b/yaksh/templates/exam.html index 4818717..02ff70a 100644 --- a/yaksh/templates/exam.html +++ b/yaksh/templates/exam.html @@ -86,13 +86,9 @@
{{ error }}
{% endfor %} - {% if error != "Incorrect answer" %} -
Testcase No. {{ forloop.counter }}
-
{{ error }}
- {% endif %} +

- {% endfor %} -
+ {% endif %} {% endif %} diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index 93ed531..3f668cd 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -194,7 +194,7 @@ function call_skip(url) {% endif %} {% if question.type == "integer" %} - Enter Integer:     + Enter Integer:


{% endif %} @@ -206,7 +206,7 @@ function call_skip(url) {% endif %} {% if question.type == "float" %} - Enter Decimal Value :     + Enter Decimal Value :


{% endif %} diff --git a/yaksh/test_models.py b/yaksh/test_models.py index f0bb310..e6e4f74 100644 --- a/yaksh/test_models.py +++ b/yaksh/test_models.py @@ -669,7 +669,7 @@ class AnswerPaperTestCases(unittest.TestCase): self.assertEqual(current_question.summary, "Question1") # Test completed_question() method of Answer Paper - question = self.answerpaper.completed_question(self.question1.id) + question = self.answerpaper.add_completed_question(self.question1.id) self.assertEqual(self.answerpaper.questions_left(), 2) # Test next_question() method of Answer Paper @@ -684,7 +684,7 @@ class AnswerPaperTestCases(unittest.TestCase): self.assertEqual(next_question_id.summary, "Question3") # Given, here question is already answered - current_question_id = 1 + current_question_id = self.question1.id # When next_question_id = self.answerpaper.next_question(current_question_id) @@ -702,10 +702,10 @@ class AnswerPaperTestCases(unittest.TestCase): # Then self.assertTrue(next_question_id is not None) - self.assertEqual(next_question_id.summary, "Question2") + self.assertEqual(next_question_id.summary, "Question1") # Given, last question in the list - current_question_id = 3 + current_question_id = self.question3.id # When next_question_id = self.answerpaper.next_question(current_question_id) @@ -713,7 +713,7 @@ class AnswerPaperTestCases(unittest.TestCase): # Then self.assertTrue(next_question_id is not None) - self.assertEqual(next_question_id.summary, "Question2") + self.assertEqual(next_question_id.summary, "Question1") # Test get_questions_answered() method # When @@ -734,14 +734,18 @@ class AnswerPaperTestCases(unittest.TestCase): # Test completed_question and next_question # When all questions are answered - current_question = self.answerpaper.completed_question(self.question2.id) + current_question = self.answerpaper.add_completed_question( + self.question2.id + ) # Then self.assertEqual(self.answerpaper.questions_left(), 1) self.assertEqual(current_question.summary, "Question3") # When - current_question = self.answerpaper.completed_question(self.question3.id) + current_question = self.answerpaper.add_completed_question( + self.question3.id + ) # Then self.assertEqual(self.answerpaper.questions_left(), 0) -- cgit From f0c7992aa21c4ab69985eb43e82f14b2764c8d8c Mon Sep 17 00:00:00 2001 From: mahesh Date: Mon, 20 Mar 2017 17:23:16 +0530 Subject: Changed question type names --- yaksh/templates/yaksh/question.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index 1bb95df..8eb7d4e 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -164,9 +164,9 @@ function call_skip(url) {% elif question.type == "upload" %} (ASSIGNMENT UPLOAD) {% elif question.type == "integer" %} - (ANSWER IN INTEGER) + (FILL IN THE BLANKS WITH INTEGER ANSWER) {% elif question.type == "string" %} - (ANSWER IN STRING) + (FILL IN THE BLANKS WITH STRING ANSWER) {% if testcase.string_check == "lower" %}
(CASE INSENSITIVE)
{% else %} @@ -174,7 +174,7 @@ function call_skip(url) {% endif %} {% elif question.type == "float" %} - (ANSWER IN FLOAT) + (FILL IN THE BLANKS WITH FLOAT ANSWER) {% endif %} (Marks : {{ question.points }}) -- cgit From 977399542df00349cc87917191af343226c44596 Mon Sep 17 00:00:00 2001 From: mahesh Date: Mon, 20 Mar 2017 17:23:51 +0530 Subject: added migrations for fill in the blanks --- yaksh/migrations/0002_auto_20170320_1135.py | 52 +++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 yaksh/migrations/0002_auto_20170320_1135.py diff --git a/yaksh/migrations/0002_auto_20170320_1135.py b/yaksh/migrations/0002_auto_20170320_1135.py new file mode 100644 index 0000000..81c7572 --- /dev/null +++ b/yaksh/migrations/0002_auto_20170320_1135.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.5 on 2017-03-20 11:35 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('yaksh', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='FloatTestCase', + fields=[ + ('testcase_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='yaksh.TestCase')), + ('correct', models.FloatField(default=None)), + ('error_margin', models.FloatField(blank=True, default=0.0, help_text='Margin of error', null=True)), + ], + bases=('yaksh.testcase',), + ), + migrations.CreateModel( + name='IntegerTestCase', + fields=[ + ('testcase_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='yaksh.TestCase')), + ('correct', models.IntegerField(default=None)), + ], + bases=('yaksh.testcase',), + ), + migrations.CreateModel( + name='StringTestCase', + fields=[ + ('testcase_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='yaksh.TestCase')), + ('correct', models.TextField(default=None)), + ('string_check', models.CharField(choices=[('lower', 'Case Insensitive'), ('exact', 'Case Sensitive')], max_length=200)), + ], + bases=('yaksh.testcase',), + ), + migrations.AlterField( + model_name='question', + name='type', + field=models.CharField(choices=[('mcq', 'Single Correct Choice'), ('mcc', 'Multiple Correct Choices'), ('code', 'Code'), ('upload', 'Assignment Upload'), ('integer', 'Answer in Integer'), ('string', 'Answer in String'), ('float', 'Answer in Float')], max_length=24), + ), + migrations.AlterField( + model_name='testcase', + name='type', + field=models.CharField(choices=[('standardtestcase', 'Standard Testcase'), ('stdiobasedtestcase', 'StdIO Based Testcase'), ('mcqtestcase', 'MCQ Testcase'), ('hooktestcase', 'Hook Testcase'), ('integertestcase', 'Integer Testcase'), ('stringtestcase', 'String Testcase'), ('floattestcase', 'Float Testcase')], max_length=24, null=True), + ), + ] -- cgit From d974d4db89af71dd844d76849678f287eedc75ce Mon Sep 17 00:00:00 2001 From: mahesh Date: Tue, 21 Mar 2017 19:57:52 +0530 Subject: added documentation for simple question types --- yaksh/documentation/images/float_testcase.jpg | Bin 0 -> 81100 bytes yaksh/documentation/images/integer_testcase.jpg | Bin 0 -> 82479 bytes yaksh/documentation/images/string_testcase.jpg | Bin 0 -> 84962 bytes .../moderator_docs/creating_question.rst | 37 +++++++++++++++++++++ 4 files changed, 37 insertions(+) create mode 100644 yaksh/documentation/images/float_testcase.jpg create mode 100644 yaksh/documentation/images/integer_testcase.jpg create mode 100644 yaksh/documentation/images/string_testcase.jpg diff --git a/yaksh/documentation/images/float_testcase.jpg b/yaksh/documentation/images/float_testcase.jpg new file mode 100644 index 0000000..2b6827c Binary files /dev/null and b/yaksh/documentation/images/float_testcase.jpg differ diff --git a/yaksh/documentation/images/integer_testcase.jpg b/yaksh/documentation/images/integer_testcase.jpg new file mode 100644 index 0000000..ca70a41 Binary files /dev/null and b/yaksh/documentation/images/integer_testcase.jpg differ diff --git a/yaksh/documentation/images/string_testcase.jpg b/yaksh/documentation/images/string_testcase.jpg new file mode 100644 index 0000000..7286eff Binary files /dev/null and b/yaksh/documentation/images/string_testcase.jpg differ diff --git a/yaksh/documentation/moderator_docs/creating_question.rst b/yaksh/documentation/moderator_docs/creating_question.rst index 94bb95c..69bb635 100644 --- a/yaksh/documentation/moderator_docs/creating_question.rst +++ b/yaksh/documentation/moderator_docs/creating_question.rst @@ -251,6 +251,43 @@ How to write Test cases .. image:: ../images/hook_testcase.jpg :width: 80% + * **Create Integer Based Test Case** + + Select **Answer in Integer** from Type field. + + Select Integer from Add Test Case field. + + In the Correct field, add the correct integer value for the question. + + .. image:: ../images/integer_testcase.jpg + :width: 80% + + * **Create String Based Test Case** + + Select **Answer in String** from Type field. + + Select **String** from Add Test Case field. + + In the **Correct** field, add the exact string answer for the question. + + In **String Check** field, select if the checking of the string answer + should be case sensitive or not. + + .. image:: ../images/string_testcase.jpg + :width: 80% + + * **Create Float Based Test Case** + + Select **Answer in Float** from Type field. + + Select **Float** from Add Test Case field. + + In the **Correct** field, add the correct float value for the question. + + In the **Error Margin** field, add the margin of error that will be allowed. + + .. image:: ../images/float_testcase.jpg + :width: 80% Features in Question -- cgit From 99b0bd05370e92ee3663354e5ca9122b75cfb2a7 Mon Sep 17 00:00:00 2001 From: mahesh Date: Wed, 22 Mar 2017 12:58:04 +0530 Subject: changed input type to number in questions.html --- yaksh/templates/yaksh/question.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index 45a524d..0dad59d 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -196,7 +196,7 @@ function call_skip(url) {% if question.type == "integer" %} Enter Integer:
- +

{% endif %} @@ -208,7 +208,7 @@ function call_skip(url) {% if question.type == "float" %} Enter Decimal Value :
- +

{% endif %} -- cgit