summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--yaksh/python_stdio_evaluator.py66
-rw-r--r--yaksh/static/yaksh/css/exam.css1
-rw-r--r--yaksh/templates/exam.html53
-rw-r--r--yaksh/templates/yaksh/question.html1
-rw-r--r--yaksh/templatetags/custom_filters.py5
5 files changed, 95 insertions, 31 deletions
diff --git a/yaksh/python_stdio_evaluator.py b/yaksh/python_stdio_evaluator.py
index a8c797d..ec5ed71 100644
--- a/yaksh/python_stdio_evaluator.py
+++ b/yaksh/python_stdio_evaluator.py
@@ -1,12 +1,16 @@
import sys
from contextlib import contextmanager
-
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
+try:
+ from itertools import zip_longest
+except ImportError:
+ from itertools import izip_longest as zip_longest
+
# Local imports
from .file_utils import copy_files, delete_files
from .base_evaluator import BaseEvaluator
@@ -21,35 +25,42 @@ def redirect_stdout():
finally:
sys.stdout = old_target # restore to the previous value
-
-def _show_expected_given(expected, given):
- return "Expected:\n{0}\nGiven:\n{1}\n".format(expected, given)
-
-
-def compare_outputs(given, expected):
- given_lines = given.splitlines()
+def _incorrect_user_lines(exp_lines, user_lines):
+ err_line_no = []
+ for i, (expected_line, user_line) in enumerate(zip_longest(exp_lines, user_lines)):
+ if not user_line or not expected_line:
+ err_line_no.append(i)
+ else:
+ if user_line.strip() != expected_line.strip():
+ err_line_no.append(i)
+ return err_line_no
+
+def compare_outputs(expected_output, user_output,given_input=None):
+ given_lines = user_output.splitlines()
+ exp_lines = expected_output.splitlines()
+ # if given_input:
+ # given_input = given_input.splitlines()
+ msg = {"given_input":given_input,
+ "expected_output": exp_lines,
+ "user_output":given_lines
+ }
ng = len(given_lines)
- exp_lines = expected.splitlines()
ne = len(exp_lines)
if ng != ne:
- msg = "ERROR: Got {0} lines in output, we expected {1}.\n".format(
- ng, ne
- )
- msg += _show_expected_given(expected, given)
+ err_line_no = _incorrect_user_lines(exp_lines, given_lines)
+ msg["error_no"] = err_line_no
+ msg["error"] = "We had expected {0} number of lines. We got {1} number of lines.".format(ne, ng)
return False, msg
else:
- for i, (given_line, expected_line) in \
- enumerate(zip(given_lines, exp_lines)):
- if given_line.strip() != expected_line.strip():
- msg = "ERROR:\n"
- msg += _show_expected_given(expected, given)
- msg += "\nError in line %d of output.\n" % (i+1)
- msg += "Expected line {0}:\n{1}\nGiven line {0}:\n{2}\n"\
- .format(
- i+1, expected_line, given_line
- )
- return False, msg
- return True, "Correct answer."
+ err_line_no = _incorrect_user_lines(exp_lines, given_lines)
+ if err_line_no:
+ msg["error_no"] = err_line_no
+ msg["error"] = "Line number(s) {0} did not match."\
+ .format(", ".join(map(str,[x+1 for x in err_line_no])))
+ return False, msg
+ else:
+ msg["error"] = "Correct answer"
+ return True, msg
class PythonStdIOEvaluator(BaseEvaluator):
@@ -89,5 +100,8 @@ class PythonStdIOEvaluator(BaseEvaluator):
def check_code(self):
mark_fraction = self.weight
- success, err = compare_outputs(self.output_value, self.expected_output)
+ success, err = compare_outputs(self.expected_output,
+ self.output_value,
+ self.expected_input
+ )
return success, err, mark_fraction
diff --git a/yaksh/static/yaksh/css/exam.css b/yaksh/static/yaksh/css/exam.css
new file mode 100644
index 0000000..88111dc
--- /dev/null
+++ b/yaksh/static/yaksh/css/exam.css
@@ -0,0 +1 @@
+.table td { border: black solid 1px !important; } \ No newline at end of file
diff --git a/yaksh/templates/exam.html b/yaksh/templates/exam.html
index a18a962..b5b6c46 100644
--- a/yaksh/templates/exam.html
+++ b/yaksh/templates/exam.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+{% load custom_filters %}
{% block css%}
<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/dashboard.css" type="text/css" />
{% endblock %}
@@ -77,13 +78,55 @@
{% if error_message %}
<div class="row" id="error_panel">
{% for error in error_message %}
- {% if error == "Correct answer" %}
- <div class="panel panel-success">
- {% else %}
<div class="panel panel-danger">
- {% endif %}
<div class="panel-heading">Testcase No. {{ forloop.counter }}</div>
- <div class="panel-body"><pre><code>{{ error }}</code></pre></div>
+ <div class="panel-body">
+ <div class="well well-sm">
+ {% if not error.expected_output %}
+ <pre><code> {{error|safe}} </code></pre>
+ {% else %}
+ {% if error.given_input %}
+ <table class="table table-bordered" width="100%">
+ <col width="30%">
+ <tr class = "active">
+ <td> For given Input value(s):</td>
+ <td>{{error.given_input}}</td>
+ </table>
+ {% endif %}
+ <table class="table table-bordered" width="100%">
+ <col width="10%">
+ <col width="40%">
+ <col width="40%">
+ <col width="10%">
+ <tr class="info">
+ <td><b><center>Line No.</center></b></td>
+ <td><b><center>Expected Output</center></b></td>
+ <td><b><center>User output</center></b></td>
+ <td><b><center>Status</center></b></td>
+ </tr>
+ {% for expected,user in error.expected_output|zip:error.user_output %}
+ <td> {{forloop.counter}} </td>
+ <td>{{expected|default:""}} </td>
+ <td>{{user|default:""}}</td>
+ {% if forloop.counter0 in error.error_no or not expected or not user %}
+ <td><span class ="glyphicon glyphicon-remove text-warning"></td>
+ {% else %}
+ <td><span class ="glyphicon glyphicon-ok text-success"></td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </table>
+ <table width="100%" class='table table-bordered'>
+ <col width="10">
+ <tr class = "danger">
+ <td><b>Error:</b></td>
+ <td>{{error.error}}</td>
+
+ </table>
+
+ {% endif %}
+ </div>
+ </div>
</div>
{% endfor %}
diff --git a/yaksh/templates/yaksh/question.html b/yaksh/templates/yaksh/question.html
index 0dad59d..e1cdcf8 100644
--- a/yaksh/templates/yaksh/question.html
+++ b/yaksh/templates/yaksh/question.html
@@ -6,6 +6,7 @@
<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/dashboard.css" type="text/css" />
<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/question.css" type="text/css" />
<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/codemirror/lib/codemirror.css" type="text/css" />
+<link rel="stylesheet" href="{{ URL_ROOT }}/static/yaksh/css/exam.css" type="text/css" />
<style>
.CodeMirror{
border-style: groove;
diff --git a/yaksh/templatetags/custom_filters.py b/yaksh/templatetags/custom_filters.py
index f610cc6..35ae795 100644
--- a/yaksh/templatetags/custom_filters.py
+++ b/yaksh/templatetags/custom_filters.py
@@ -1,5 +1,6 @@
from django import template
from django.template.defaultfilters import stringfilter
+from itertools import zip_longest
register = template.Library()
@@ -19,3 +20,7 @@ def completed(answerpaper):
@register.assignment_tag(name="inprogress")
def inprogress(answerpaper):
return answerpaper.filter(status="inprogress").count()
+
+@register.filter(name='zip')
+def zip_longest_out(a, b):
+ return zip_longest(a, b) \ No newline at end of file