diff options
-rw-r--r-- | Quiz_instructions.txt | 18 | ||||
-rw-r--r-- | yaksh/bash_code_evaluator.py | 4 | ||||
-rw-r--r-- | yaksh/bash_stdio_evaluator.py | 2 | ||||
-rw-r--r-- | yaksh/cpp_code_evaluator.py | 2 | ||||
-rw-r--r-- | yaksh/cpp_stdio_evaluator.py | 2 | ||||
-rw-r--r-- | yaksh/forms.py | 53 | ||||
-rw-r--r-- | yaksh/grader.py | 6 | ||||
-rw-r--r-- | yaksh/java_code_evaluator.py | 2 | ||||
-rw-r--r-- | yaksh/java_stdio_evaluator.py | 2 | ||||
-rw-r--r-- | yaksh/management/commands/add_group.py | 11 | ||||
-rw-r--r-- | yaksh/models.py | 6 | ||||
-rw-r--r-- | yaksh/python_assertion_evaluator.py | 2 | ||||
-rw-r--r-- | yaksh/scilab_code_evaluator.py | 6 | ||||
-rw-r--r-- | yaksh/templates/yaksh/grade_user.html | 2 | ||||
-rw-r--r-- | yaksh/templates/yaksh/monitor.html | 9 | ||||
-rw-r--r-- | yaksh/templates/yaksh/question.html | 4 | ||||
-rw-r--r-- | yaksh/templates/yaksh/user_data.html | 2 | ||||
-rw-r--r-- | yaksh/templates/yaksh/view_answerpaper.html | 2 | ||||
-rw-r--r-- | yaksh/templatetags/custom_filters.py | 10 | ||||
-rw-r--r-- | yaksh/test_views.py | 11 |
20 files changed, 100 insertions, 56 deletions
diff --git a/Quiz_instructions.txt b/Quiz_instructions.txt deleted file mode 100644 index 34e010f..0000000 --- a/Quiz_instructions.txt +++ /dev/null @@ -1,18 +0,0 @@ -<p> -This examination system has been developed with the intention of making you -learn programming and be assessed in an interactive and fun manner. -You will be presented with a series of programming questions and problems that -you will answer online and get immediate feedback for. -</p> -<p> Here are some important instructions and rules that you should understand carefully.</p> -<ul> -<li>For any programming questions, you can submit solutions as many times as you want without a penalty. You may skip questions and solve them later. -</li> -<li> You <strong>may</strong> use your computer's Python/IPython shell or an editor to solve the problem and cut/paste the solution to the web interface. -</li> -<li> <strong>You are <strong>not allowed</strong> to use any internet resources, i.e. no google etc.</strong> </li> -<li> Do not copy or share the questions or answers with anyone until the exam is complete <strong>for everyone</strong>.</li> -<li> <strong>All</strong> your attempts at the questions are logged. Do not try to outsmart and break the testing system. If you do, we know who you are and we will expel you from the course. You have been warned. -</li> -</ul> -<p> We hope you enjoy taking this exam !!!</p> diff --git a/yaksh/bash_code_evaluator.py b/yaksh/bash_code_evaluator.py index 9da404a..a4f1389 100644 --- a/yaksh/bash_code_evaluator.py +++ b/yaksh/bash_code_evaluator.py @@ -112,7 +112,7 @@ class BashCodeEvaluator(BaseEvaluator): ) proc, stdnt_stdout, stdnt_stderr = ret if inst_stdout == stdnt_stdout: - mark_fraction = float(self.weight) if self.partial_grading else 0.0 + mark_fraction = 1.0 if self.partial_grading else 0.0 return True, None, mark_fraction else: err = "Error: expected %s, got %s" % (inst_stdout + inst_stderr, @@ -155,7 +155,7 @@ class BashCodeEvaluator(BaseEvaluator): proc, stdnt_stdout, stdnt_stderr = ret valid_answer = inst_stdout == stdnt_stdout if valid_answer and (num_lines == loop_count): - mark_fraction = float(self.weight) if self.partial_grading else 0.0 + mark_fraction = 1.0 if self.partial_grading else 0.0 return True, None, mark_fraction else: err = ("Error:expected" diff --git a/yaksh/bash_stdio_evaluator.py b/yaksh/bash_stdio_evaluator.py index 50ee0d6..334620d 100644 --- a/yaksh/bash_stdio_evaluator.py +++ b/yaksh/bash_stdio_evaluator.py @@ -55,5 +55,5 @@ class BashStdIOEvaluator(StdIOEvaluator): self.expected_input, self.expected_output ) - mark_fraction = float(self.weight) if self.partial_grading and success else 0.0 + mark_fraction = 1.0 if self.partial_grading and success else 0.0 return success, err, mark_fraction diff --git a/yaksh/cpp_code_evaluator.py b/yaksh/cpp_code_evaluator.py index d4e2253..4c8e938 100644 --- a/yaksh/cpp_code_evaluator.py +++ b/yaksh/cpp_code_evaluator.py @@ -139,7 +139,7 @@ class CppCodeEvaluator(BaseEvaluator): proc, stdout, stderr = ret if proc.returncode == 0: success, err = True, None - mark_fraction = float(self.weight) if self.partial_grading else 0.0 + mark_fraction = 1.0 if self.partial_grading else 0.0 else: err = "{0} \n {1}".format(stdout, stderr) else: diff --git a/yaksh/cpp_stdio_evaluator.py b/yaksh/cpp_stdio_evaluator.py index d1dcd65..b302fa4 100644 --- a/yaksh/cpp_stdio_evaluator.py +++ b/yaksh/cpp_stdio_evaluator.py @@ -112,5 +112,5 @@ class CppStdIOEvaluator(StdIOEvaluator): err = err + "\n" + e except: err = err + "\n" + stdnt_stderr - mark_fraction = float(self.weight) if self.partial_grading and success else 0.0 + mark_fraction = 1.0 if self.partial_grading and success else 0.0 return success, err, mark_fraction diff --git a/yaksh/forms.py b/yaksh/forms.py index 6fbaf5d..1d18d29 100644 --- a/yaksh/forms.py +++ b/yaksh/forms.py @@ -9,6 +9,7 @@ from taggit.managers import TaggableManager from taggit.forms import TagField from django.forms.models import inlineformset_factory from django.db.models import Q +from textwrap import dedent try: from string import letters except ImportError: @@ -165,6 +166,58 @@ class QuizForm(forms.ModelForm): self.fields['prerequisite'].required = False self.fields['course'] = forms.ModelChoiceField( queryset=Course.objects.filter(id=course_id), empty_label=None) + self.fields["instructions"].initial = dedent("""\ + <p> + This examination system has been + developed with the intention of + making you learn programming and + be assessed in an interactive and + fun manner. + You will be presented with a + series of programming questions + and problems that you will answer + online and get immediate + feedback for. + </p> + <p> + Here are some important + instructions and rules that you + should understand carefully.</p> + <ul> + <li>For any programming questions, + you can submit solutions as many + times as you want without a + penalty. You may skip questions + and solve them later.</li> + <li> You <strong>may</strong> + use your computer's Python/IPython + shell or an editor to solve the + problem and cut/paste the + solution to the web interface. + </li> + <li> <strong>You are not allowed + to use any internet resources, + i.e. no google etc.</strong> + </li> + <li> Do not copy or share the + questions or answers with anyone + until the exam is complete + <strong>for everyone</strong>. + </li> + <li> <strong>All</strong> your + attempts at the questions are + logged. Do not try to outsmart + and break the testing system. + If you do, we know who you are + and we will expel you from the + course. You have been warned. + </li> + </ul> + <p> + We hope you enjoy taking this + exam !!! + </p> + """) class Meta: model = Quiz diff --git a/yaksh/grader.py b/yaksh/grader.py index 0c057c2..086abb7 100644 --- a/yaksh/grader.py +++ b/yaksh/grader.py @@ -100,10 +100,10 @@ class Grader(object): self.setup() test_case_instances = self.get_evaluator_objects(kwargs) with change_dir(self.in_dir): - success, error, mark = self.safe_evaluate(test_case_instances) + success, error, weight = self.safe_evaluate(test_case_instances) self.teardown() - result = {'success': success, 'error': error, 'weight': mark} + result = {'success': success, 'error': error, 'weight': weight} return result # Private Protocol ########## @@ -144,7 +144,7 @@ class Grader(object): test_case_instance.compile_code() test_case_success, err, mark_fraction = test_case_instance.check_code() if test_case_success: - weight += mark_fraction + weight += mark_fraction * test_case_instance.weight else: error.append(err) test_case_success_status[idx] = test_case_success diff --git a/yaksh/java_code_evaluator.py b/yaksh/java_code_evaluator.py index df6abf5..e6dc628 100644 --- a/yaksh/java_code_evaluator.py +++ b/yaksh/java_code_evaluator.py @@ -147,7 +147,7 @@ class JavaCodeEvaluator(BaseEvaluator): proc, stdout, stderr = ret if proc.returncode == 0: success, err = True, None - mark_fraction = float(seelf.weight) if self.partial_grading else 0.0 + mark_fraction = 1.0 if self.partial_grading else 0.0 else: err = stdout + "\n" + stderr else: diff --git a/yaksh/java_stdio_evaluator.py b/yaksh/java_stdio_evaluator.py index a854847..48f265d 100644 --- a/yaksh/java_stdio_evaluator.py +++ b/yaksh/java_stdio_evaluator.py @@ -85,5 +85,5 @@ class JavaStdIOEvaluator(StdIOEvaluator): err = err + "\n" + e except: err = err + "\n" + stdnt_stderr - mark_fraction = float(self.weight) if self.partial_grading and success else 0.0 + mark_fraction = 1.0 if self.partial_grading and success else 0.0 return success, err, mark_fraction diff --git a/yaksh/management/commands/add_group.py b/yaksh/management/commands/add_group.py index 03ef103..624ff3c 100644 --- a/yaksh/management/commands/add_group.py +++ b/yaksh/management/commands/add_group.py @@ -15,7 +15,7 @@ class Command(BaseCommand): help = 'Adds the moderator group' def handle(self, *args, **options): - app = 'yaksh' + app_label = 'yaksh' group = Group(name='moderator') try: group.save() @@ -23,11 +23,10 @@ class Command(BaseCommand): raise CommandError("The group already exits") else: # Get the models for the given app - content_types = ContentType.objects.filter(app_label=app) + content_types = ContentType.objects.filter(app_label=app_label) # Get list of permissions for the models - permission_list = Permission.objects.filter(content_type=content_types) - for permission in permission_list: - group.permissions.add(permission) - group.save() + permission_list = Permission.objects.filter(content_type__in=content_types) + group.permissions.add(*permission_list) + group.save() self.stdout.write('Moderator group added successfully') diff --git a/yaksh/models.py b/yaksh/models.py index b54e6a0..d65970b 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -81,10 +81,6 @@ def has_profile(user): def get_upload_dir(instance, filename): return "question_%s/%s" % (instance.question.id, filename) -def get_quiz_instructions_info(): - file_path = os.path.join(os.getcwd(), "Quiz_instructions.txt") - with open(file_path, 'r') as file: - return file.read() ############################################################################### class CourseManager(models.Manager): @@ -546,7 +542,7 @@ class Quiz(models.Model): is_trial = models.BooleanField(default=False) instructions = models.TextField('Instructions for Students', - default=get_quiz_instructions_info) + default=None, blank=True, null=True) view_answerpaper = models.BooleanField('Allow student to view their answer\ paper', default=False) diff --git a/yaksh/python_assertion_evaluator.py b/yaksh/python_assertion_evaluator.py index 749a6ec..ae86c46 100644 --- a/yaksh/python_assertion_evaluator.py +++ b/yaksh/python_assertion_evaluator.py @@ -91,6 +91,6 @@ class PythonAssertionEvaluator(BaseEvaluator): else: success = True err = None - mark_fraction = float(self.weight) if self.partial_grading else 0.0 + mark_fraction = 1.0 if self.partial_grading else 0.0 del tb return success, err, mark_fraction diff --git a/yaksh/scilab_code_evaluator.py b/yaksh/scilab_code_evaluator.py index 7ffcd2b..f5c81b5 100644 --- a/yaksh/scilab_code_evaluator.py +++ b/yaksh/scilab_code_evaluator.py @@ -47,7 +47,7 @@ class ScilabCodeEvaluator(BaseEvaluator): self._remove_scilab_exit(self.user_answer.lstrip()) success = False - test_case_weight = 0.0 + mark_fraction = 0.0 self.write_to_submit_code_file(self.submit_code_path, self.user_answer) self.write_to_submit_code_file(self.test_code_path, self.test_case) # Throw message if there are commmands that terminates scilab @@ -75,13 +75,13 @@ class ScilabCodeEvaluator(BaseEvaluator): stdout = self._strip_output(stdout) if proc.returncode == 5: success, err = True, None - test_case_weight = float(self.weight) if self.partial_grading else 0.0 + mark_fraction = 1.0 if self.partial_grading else 0.0 else: err = add_err + stdout else: err = add_err + stderr - return success, err, test_case_weight + return success, err, mark_fraction def _remove_scilab_exit(self, string): """ diff --git a/yaksh/templates/yaksh/grade_user.html b/yaksh/templates/yaksh/grade_user.html index 6fb8187..ec8c244 100644 --- a/yaksh/templates/yaksh/grade_user.html +++ b/yaksh/templates/yaksh/grade_user.html @@ -130,7 +130,7 @@ Status : <b style="color: green;"> Passed </b><br/> {% if question.type == "mcq" or question.type == "mcc" %} <h5> <u>Choices:</u></h5> {% for testcase in question.get_test_cases %} - <br/><strong>{{ forloop.counter }}. {{ testcase.options }}</strong> + <br/><strong>{{ forloop.counter }}. {{ testcase.options|safe }}</strong> {% endfor %} {% else %} <h5> <u>Test cases: </u></h5> diff --git a/yaksh/templates/yaksh/monitor.html b/yaksh/templates/yaksh/monitor.html index 7a3297b..0ad6401 100644 --- a/yaksh/templates/yaksh/monitor.html +++ b/yaksh/templates/yaksh/monitor.html @@ -1,4 +1,5 @@ {% extends "manage.html" %} +{% load custom_filters %} {% block pagetitle %} Quiz results {% endblock pagetitle %} @@ -49,6 +50,14 @@ $(document).ready(function() {% if papers %} <p>Number of papers: {{ papers|length }} </p> +{% completed papers as completed_papers %} + {# template tag used to get the count of completed papers #} + <p>Papers completed: <b> {{ completed_papers }} </b></p> + +{% inprogress papers as inprogress_papers %} + {# template tag used to get the count of inprogress papers #} + <p>Papers in progress:<b> {{ inprogress_papers }} </b></p> + <p><a href="{{URL_ROOT}}/exam/manage/statistics/question/{{papers.0.question_paper.id}}">Question Statisitics</a></p> <p><a href="{{URL_ROOT}}/exam/manage/monitor/download_csv/{{papers.0.question_paper.id}}">Download CSV</a></p> <table id="result-table" class="tablesorter table"> diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html index fe696fe..7cbca57 100644 --- a/yaksh/templates/yaksh/question.html +++ b/yaksh/templates/yaksh/question.html @@ -173,7 +173,7 @@ function call_skip(url) </p> {% endif %} {% for test_case in test_cases %} - <input name="answer" type="radio" value="{{ test_case.options }}" />{{ test_case.options }} <br/> + <input name="answer" type="radio" value="{{ test_case.options }}" />{{ test_case.options|safe }} <br/> {% endfor %} {% endif %} {% if question.type == "mcc" %} @@ -189,7 +189,7 @@ function call_skip(url) </p> {% endif %} {% for test_case in test_cases %} - <input name="answer" type="checkbox" value="{{ test_case.options }}"> {{ test_case.options }} + <input name="answer" type="checkbox" value="{{ test_case.options }}"> {{ test_case.options|safe }} <br> {% endfor %} {% endif %} diff --git a/yaksh/templates/yaksh/user_data.html b/yaksh/templates/yaksh/user_data.html index 856433d..9c11dd9 100644 --- a/yaksh/templates/yaksh/user_data.html +++ b/yaksh/templates/yaksh/user_data.html @@ -66,7 +66,7 @@ User IP address: {{ paper.user_ip }} {% if question.type == "mcq" or question.type == "mcc" %} <h5> <u>Choices:</u></h5> {% for testcase in question.get_test_cases %} - <br/><strong>{{ forloop.counter }}. {{ testcase.options }}</strong> + <br/><strong>{{ forloop.counter }}. {{ testcase.options|safe }}</strong> {% endfor %} {% else %} <h5> <u>Test cases: </u></h5> diff --git a/yaksh/templates/yaksh/view_answerpaper.html b/yaksh/templates/yaksh/view_answerpaper.html index 9dfbda0..8dec5b3 100644 --- a/yaksh/templates/yaksh/view_answerpaper.html +++ b/yaksh/templates/yaksh/view_answerpaper.html @@ -42,7 +42,7 @@ {% if question.type == "mcq" or question.type == "mcc" %} <h5> <u>Choices:</u></h5> {% for testcase in question.get_test_cases %} - <br/><strong>{{ forloop.counter }}. {{ testcase.options }}</strong> + <br/><strong>{{ forloop.counter }}. {{ testcase.options|safe }}</strong> {% endfor %} {%endif%} diff --git a/yaksh/templatetags/custom_filters.py b/yaksh/templatetags/custom_filters.py index 9d7b939..f610cc6 100644 --- a/yaksh/templatetags/custom_filters.py +++ b/yaksh/templatetags/custom_filters.py @@ -10,4 +10,12 @@ def escape_quotes(value): escape_single_quotes = value.replace("'", "\\'") escape_single_and_double_quotes = escape_single_quotes.replace('"', '\\"') - return escape_single_and_double_quotes
\ No newline at end of file + return escape_single_and_double_quotes + +@register.assignment_tag(name="completed") +def completed(answerpaper): + return answerpaper.filter(status="completed").count() + +@register.assignment_tag(name="inprogress") +def inprogress(answerpaper): + return answerpaper.filter(status="inprogress").count() diff --git a/yaksh/test_views.py b/yaksh/test_views.py index 2419591..e052441 100644 --- a/yaksh/test_views.py +++ b/yaksh/test_views.py @@ -146,9 +146,6 @@ class TestAddQuiz(TestCase): self.mod_group = Group.objects.create(name='moderator') tzone = pytz.timezone('UTC') - file_path = os.path.join(os.getcwd(), "Quiz_instructions.txt") - with open(file_path, 'r') as file: - self.file_data = file.read() # Create Moderator with profile self.user_plaintext_pass = 'demo' self.user = User.objects.create_user( @@ -187,7 +184,7 @@ class TestAddQuiz(TestCase): self.pre_req_quiz = Quiz.objects.create( start_date_time=datetime(2014, 2, 1, 5, 8, 15, 0, tzone), end_date_time=datetime(2015, 10, 9, 10, 8, 15, 0, tzone), - duration=30, active=True, instructions=self.file_data, + duration=30, active=True, instructions="Demo Instructions", attempts_allowed=-1, time_between_attempts=0, description='pre requisite quiz', pass_criteria=40, language='Python', prerequisite=None, @@ -197,7 +194,7 @@ class TestAddQuiz(TestCase): self.quiz = Quiz.objects.create( start_date_time=datetime(2014, 10, 9, 10, 8, 15, 0, tzone), end_date_time=datetime(2015, 10, 9, 10, 8, 15, 0, tzone), - duration=30, active=True, instructions=self.file_data, + duration=30, active=True, instructions="Demo Instructions", attempts_allowed=-1, time_between_attempts=0, description='demo quiz', pass_criteria=40, language='Python', prerequisite=self.pre_req_quiz, @@ -274,7 +271,7 @@ class TestAddQuiz(TestCase): 'description': 'updated demo quiz', 'pass_criteria': 40, 'language': 'java', - 'instructions': self.file_data, + 'instructions': "Demo Instructions", 'prerequisite': self.pre_req_quiz.id, 'course': self.course.id } @@ -321,7 +318,7 @@ class TestAddQuiz(TestCase): 'description': 'new demo quiz', 'pass_criteria': 50, 'language': 'python', - 'instructions': self.file_data, + 'instructions': "Demo Instructions", 'prerequisite': self.pre_req_quiz.id, 'course': self.course.id } |