summaryrefslogtreecommitdiff
path: root/yaksh
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh')
-rw-r--r--yaksh/models.py24
-rw-r--r--yaksh/static/yaksh/css/exam.css9
-rw-r--r--yaksh/static/yaksh/css/yakshcustom.css2
-rw-r--r--yaksh/templates/exam.html47
-rw-r--r--yaksh/templatetags/custom_filters.py5
-rw-r--r--yaksh/test_models.py58
-rw-r--r--yaksh/views.py8
7 files changed, 108 insertions, 45 deletions
diff --git a/yaksh/models.py b/yaksh/models.py
index 427b584..cce90e7 100644
--- a/yaksh/models.py
+++ b/yaksh/models.py
@@ -6,7 +6,8 @@ import ruamel.yaml
from ruamel.yaml.scalarstring import PreservedScalarString
from ruamel.yaml.comments import CommentedMap
from random import sample
-from collections import Counter
+from collections import Counter, defaultdict
+
from django.db import models
from django.contrib.auth.models import User, Group, Permission
from django.contrib.contenttypes.models import ContentType
@@ -80,6 +81,17 @@ string_check_type = (
("exact", "Case Sensitive"),
)
+legend_display_types = {
+ "mcq": {"label": "Objective Type"},
+ "mcc": {"label": "Objective Type"},
+ "code": {"label": "Programming"},
+ "upload": {"label": "Upload"},
+ "integer": {"label": "Objective Type"},
+ "string": {"label": "Objective Type"},
+ "float": {"label": "Objective Type"},
+ "arrange": {"label": "Objective Type"},
+ }
+
attempts = [(i, i) for i in range(1, 6)]
attempts.append((-1, 'Infinite'))
@@ -2091,6 +2103,16 @@ class AnswerPaper(models.Model):
def get_previous_answers(self, question):
return self.answers.filter(question=question).order_by('-id')
+ def get_categorized_question_indices(self):
+ category_question_map = defaultdict(list)
+ for index, question in enumerate(self.get_all_ordered_questions(), 1):
+ question_category = legend_display_types.get(question.type)
+ if question_category:
+ category_question_map[
+ question_category["label"]
+ ].append(index)
+ return dict(category_question_map)
+
def validate_answer(self, user_answer, question, json_data=None, uid=None,
server_port=SERVER_POOL_PORT):
"""
diff --git a/yaksh/static/yaksh/css/exam.css b/yaksh/static/yaksh/css/exam.css
index b0bb379..a246141 100644
--- a/yaksh/static/yaksh/css/exam.css
+++ b/yaksh/static/yaksh/css/exam.css
@@ -1,7 +1,14 @@
-table td, table th { border: #ff8295 solid 1px !important;
+#assertion td, #assertion th, #stdio td, #stdio th { border: #ff8295 solid 1px !important;
word-wrap: break-word !important;
white-space: pre-wrap !important;
}
#stdio, #assertion {
table-layout: fixed
}
+.legend_table{
+ border: 1px solid;
+ width: 15em;
+ background-color: white;
+ border-spacing: 5px;
+ border-collapse: collapse;
+}
diff --git a/yaksh/static/yaksh/css/yakshcustom.css b/yaksh/static/yaksh/css/yakshcustom.css
index 86403ac..a9b4349 100644
--- a/yaksh/static/yaksh/css/yakshcustom.css
+++ b/yaksh/static/yaksh/css/yakshcustom.css
@@ -228,5 +228,3 @@ html {
overflow-y: auto;
-ms-overflow-style: -ms-autohiding-scrollbar;
}
-
-/*---------------------*/ \ No newline at end of file
diff --git a/yaksh/templates/exam.html b/yaksh/templates/exam.html
index c452929..29ad167 100644
--- a/yaksh/templates/exam.html
+++ b/yaksh/templates/exam.html
@@ -1,10 +1,5 @@
{% extends "base.html" %}
{% load custom_filters %}
-
-
-
-
-{% load custom_filters %}
{% block nav %}
<div class="container-fluid yakshnav">
<nav class="navbar fixed-top navbar-expand-lg yakshheading yakshnav">
@@ -83,28 +78,26 @@
<p class="text-center">Question(s) left: <b>{{ paper.questions_left }}</b></p>
</div>
<br>
- <div class="">
- <div class="">
- <div class="">
- {% for types in question_types %}
- {% get_questions_by_type paper.get_all_ordered_questions types as questions_by_type %}
- {% if types == "mcq" %} Single Correct Choice
- {% elif types == "mcc" %} Multiple Correct Choice
- {% elif types == "code" %} Programming
- {% elif types == "upload" %} Assignment Upload
- {% elif types == "integer" %} Integer Blanks
- {% elif types == "string" %} String Blanks
- {% elif types == "float" %} Float Blanks
- {% elif types == "arrange" %} Arranging Options
- {% endif %}
- --->
- <b> {% for question in questions_by_type %} {{question.id}} {%endfor%} </b>
- <br>
- {%endfor%}
- </div>
- </div>
- </div>
-
+ <table class = "legend_table table-bordered table-sm">
+ <thead>
+ <tr>
+ <th>Category</th>
+ <th>Question No.</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for category, question_number in paper.get_categorized_question_indices.items %}
+ <tr>
+ <td>
+ {{category}}
+ </td>
+ <td>
+ {{question_number| join:", "}}
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
</div> <!--end of sidebar -->
<a href="#sidebar" data-toggle="collapse" id="sidebaricon"><i class="fa fa-navicon fa-lg"></i></a>
diff --git a/yaksh/templatetags/custom_filters.py b/yaksh/templatetags/custom_filters.py
index dcae7f9..29f4b59 100644
--- a/yaksh/templatetags/custom_filters.py
+++ b/yaksh/templatetags/custom_filters.py
@@ -85,10 +85,5 @@ def replace_spaces(name):
@register.simple_tag
-def get_questions_by_type(all_questions, question_type):
- return [question for question in all_questions if question.type == question_type]
-
-
-@register.simple_tag
def course_grade(course, user):
return course.get_grade(user)
diff --git a/yaksh/test_models.py b/yaksh/test_models.py
index aea47de..1f38d03 100644
--- a/yaksh/test_models.py
+++ b/yaksh/test_models.py
@@ -4,7 +4,7 @@ from yaksh.models import User, Profile, Question, Quiz, QuestionPaper,\
QuestionSet, AnswerPaper, Answer, Course, StandardTestCase,\
StdIOBasedTestCase, FileUpload, McqTestCase, AssignmentUpload,\
LearningModule, LearningUnit, Lesson, LessonFile, CourseStatus, \
- create_group
+ create_group, legend_display_types
from yaksh.code_server import (
ServerPool, get_result as get_result_from_code_server
)
@@ -21,6 +21,7 @@ import os
import shutil
import tempfile
from threading import Thread
+from collections import defaultdict
from yaksh import settings
@@ -287,9 +288,10 @@ class ProfileTestCases(unittest.TestCase):
def setUp(self):
self.creator = User.objects.get(username='creator')
self.profile = Profile.objects.get(user=self.creator)
- self.teacher = User.objects.create_user(username='teacher_profile',
- password='teacher_profile',
- email='teacher_profile@test.com')
+ self.teacher = User.objects.create_user(
+ username='teacher_profile',
+ password='teacher_profile',
+ email='teacher_profile@test.com')
Profile.objects.create(
user=self.teacher, roll_number=123, institute='IIT',
is_moderator=True, department='Chemical', position='Teacher'
@@ -329,6 +331,7 @@ class ProfileTestCases(unittest.TestCase):
self.teacher.delete()
self.course.delete()
+
###############################################################################
class QuestionTestCases(unittest.TestCase):
def setUp(self):
@@ -988,7 +991,6 @@ class AnswerPaperTestCases(unittest.TestCase):
quiz=self.quiz2, total_marks=3
)
self.qtn_paper_with_single_question.save()
-
all_questions = Question.objects.filter(user=self.user).order_by("id")
self.questions = all_questions[0:3]
self.start_time = timezone.now()
@@ -1021,6 +1023,7 @@ class AnswerPaperTestCases(unittest.TestCase):
)
self.answerpaper.questions_unanswered.add(*self.questions)
self.answerpaper.save()
+
# answers for the Answer Paper
self.answer_right = Answer(
question=self.question1,
@@ -1135,6 +1138,33 @@ class AnswerPaperTestCases(unittest.TestCase):
self.user2_answerpaper2 = self.question_paper.make_answerpaper(
self.user2, self.ip, 1, self.course.id
)
+ self.questions_list = Question.objects.filter(
+ summary__in=summary_list[0:5])
+ # create question_paper3
+ self.question_paper3 = QuestionPaper(
+ quiz=self.quiz2, total_marks=3, shuffle_questions=True)
+ self.question_paper3.save()
+ question_list_with_only_one_category = [
+ question for question in self.questions_list
+ if question.type == 'code']
+ self.question_paper3.fixed_questions.add(
+ *question_list_with_only_one_category
+ )
+ # create anspaper for user1 with questions of only one category
+ self.user1_answerpaper2 = self.question_paper3.make_answerpaper(
+ self.user, self.ip, 1, self.course.id
+ )
+ # create question_paper4
+ self.question_paper4 = QuestionPaper(
+ quiz=self.quiz, total_marks=0, shuffle_questions=True
+ )
+ self.question_paper4.save()
+
+ # create anspaper for user1 with no questions
+ self.user1_answerpaper3 = self.question_paper4.make_answerpaper(
+ self.user, self.ip, 1, self.course.id
+ )
+
settings.code_evaluators['python']['standardtestcase'] = \
"yaksh.python_assertion_evaluator.PythonAssertionEvaluator"
self.SERVER_POOL_PORT = 4000
@@ -1583,6 +1613,24 @@ class AnswerPaperTestCases(unittest.TestCase):
course=self.answerpaper.course
)
+ def test_get_categorized_question_indices_with_multiple_categories(self):
+ question_indices = {'Programming': [1], 'Objective Type': [2, 3]}
+ categorized_question_indices = \
+ self.answerpaper.get_categorized_question_indices()
+ self.assertDictEqual(question_indices, categorized_question_indices)
+
+ def test_get_categorized_question_indices_for_only_one_category(self):
+ question_indices = {'Programming': [1, 2, 3]}
+ categorized_question_indices = \
+ self.user1_answerpaper2.get_categorized_question_indices()
+ self.assertDictEqual(question_indices, categorized_question_indices)
+
+ def test_get_categorized_question_indices_for_no_questions(self):
+ question_indices = {}
+ categorized_question_indices = \
+ self.user1_answerpaper3.get_categorized_question_indices()
+ self.assertDictEqual(question_indices, categorized_question_indices)
+
###############################################################################
class CourseTestCases(unittest.TestCase):
diff --git a/yaksh/views.py b/yaksh/views.py
index 0f81931..6c7a12e 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -615,7 +615,6 @@ def show_question(request, question, paper, error_message=None,
course = Course.objects.get(id=course_id)
module = course.learning_module.get(id=module_id)
all_modules = course.get_learning_modules()
- all_question_types = [types[0] for types in question_types]
context = {
'question': question,
'paper': paper,
@@ -631,7 +630,6 @@ def show_question(request, question, paper, error_message=None,
'delay_time': delay_time,
'quiz_type': quiz_type,
'all_modules': all_modules,
- "question_types": all_question_types
}
answers = paper.get_previous_answers(question)
if answers:
@@ -905,8 +903,10 @@ def complete(request, reason=None, attempt_num=None, questionpaper_id=None,
"""Show a page to inform user that the quiz has been completed."""
user = request.user
if questionpaper_id is None:
- message = (reason or "An Unexpected Error occurred. Please contact your"
- " instructor/administrator.")
+ message = (
+ reason or "An Unexpected Error occurred."
+ " Please contact your instructor/administrator."
+ )
context = {'message': message}
return my_render_to_response(request, 'yaksh/complete.html', context)
else: