summaryrefslogtreecommitdiff
path: root/yaksh
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh')
-rw-r--r--yaksh/bash_code_evaluator.py4
-rw-r--r--yaksh/bash_stdio_evaluator.py2
-rw-r--r--yaksh/cpp_code_evaluator.py2
-rw-r--r--yaksh/cpp_stdio_evaluator.py2
-rw-r--r--yaksh/forms.py53
-rw-r--r--yaksh/grader.py6
-rw-r--r--yaksh/java_code_evaluator.py2
-rw-r--r--yaksh/java_stdio_evaluator.py2
-rw-r--r--yaksh/management/commands/add_group.py11
-rw-r--r--yaksh/models.py6
-rw-r--r--yaksh/python_assertion_evaluator.py2
-rw-r--r--yaksh/scilab_code_evaluator.py6
-rw-r--r--yaksh/templates/yaksh/grade_user.html2
-rw-r--r--yaksh/templates/yaksh/monitor.html9
-rw-r--r--yaksh/templates/yaksh/question.html4
-rw-r--r--yaksh/templates/yaksh/user_data.html2
-rw-r--r--yaksh/templates/yaksh/view_answerpaper.html2
-rw-r--r--yaksh/templatetags/custom_filters.py10
-rw-r--r--yaksh/test_views.py11
19 files changed, 100 insertions, 38 deletions
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
}