summaryrefslogtreecommitdiff
path: root/yaksh
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh')
-rw-r--r--yaksh/forms.py2
-rw-r--r--yaksh/models.py54
-rw-r--r--yaksh/templates/manage.html2
-rw-r--r--yaksh/templates/yaksh/course_detail.html6
-rw-r--r--yaksh/templates/yaksh/course_modules.html1
-rw-r--r--yaksh/templates/yaksh/courses.html4
-rw-r--r--yaksh/templatetags/custom_filters.py7
-rw-r--r--yaksh/test_models.py98
-rw-r--r--yaksh/views.py23
9 files changed, 191 insertions, 6 deletions
diff --git a/yaksh/forms.py b/yaksh/forms.py
index 9a44cfa..41c9176 100644
--- a/yaksh/forms.py
+++ b/yaksh/forms.py
@@ -282,7 +282,7 @@ class CourseForm(forms.ModelForm):
class Meta:
model = Course
fields = ['name', 'enrollment', 'active', 'code', 'instructions',
- 'start_enroll_time', 'end_enroll_time']
+ 'start_enroll_time', 'end_enroll_time', 'grading_system']
class ProfileForm(forms.ModelForm):
diff --git a/yaksh/models.py b/yaksh/models.py
index 826c0e8..d011bb0 100644
--- a/yaksh/models.py
+++ b/yaksh/models.py
@@ -35,7 +35,7 @@ from yaksh.code_server import (
from yaksh.settings import SERVER_POOL_PORT, SERVER_HOST_NAME
from django.conf import settings
from django.forms.models import model_to_dict
-
+from grades.models import GradingSystem
languages = (
("python", "Python"),
@@ -331,7 +331,8 @@ class Quiz(models.Model):
allow_skip = models.BooleanField("Allow students to skip questions",
default=True)
- weightage = models.FloatField(default=1.0)
+ weightage = models.FloatField(help_text='Will be considered as percentage',
+ default=100)
is_exercise = models.BooleanField(default=False)
@@ -605,6 +606,8 @@ class Course(models.Model):
null=True
)
+ grading_system = models.ForeignKey(GradingSystem, null=True, blank=True)
+
objects = CourseManager()
def _create_duplicate_instance(self, creator, course_name=None):
@@ -775,6 +778,14 @@ class Course(models.Model):
percent = round((count / len(modules)))
return percent
+ def get_grade(self, user):
+ course_status = CourseStatus.objects.filter(course=self, user=user)
+ if course_status.exists():
+ grade = course_status.first().get_grade()
+ else:
+ grade = "NA"
+ return grade
+
def days_before_start(self):
""" Get the days remaining for the start of the course """
if timezone.now() < self.start_enroll_time:
@@ -796,7 +807,44 @@ class CourseStatus(models.Model):
course = models.ForeignKey(Course)
user = models.ForeignKey(User)
grade = models.CharField(max_length=255, null=True, blank=True)
- total_marks = models.FloatField(default=0.0)
+ percentage = models.FloatField(default=0.0)
+
+ def get_grade(self):
+ return self.grade
+
+ def set_grade(self):
+ if self.is_course_complete():
+ self.calculate_percentage()
+ if self.course.grading_system is None:
+ grading_system = GradingSystem.objects.get(name='default')
+ else:
+ grading_system = self.course.grading_system
+ grade = grading_system.get_grade(self.percentage)
+ self.grade = grade
+ self.save()
+
+ def calculate_percentage(self):
+ if self.is_course_complete():
+ quizzes = self.course.get_quizzes()
+ total_weightage = 0
+ sum = 0
+ for quiz in quizzes:
+ total_weightage += quiz.weightage
+ marks = AnswerPaper.objects.get_user_best_of_attempts_marks(
+ quiz, self.user.id, self.course.id)
+ out_of = quiz.questionpaper_set.first().total_marks
+ sum += (marks/out_of)*quiz.weightage
+ self.percentage = (sum/total_weightage)*100
+ self.save()
+
+ def is_course_complete(self):
+ modules = self.course.get_learning_modules()
+ complete = False
+ for module in modules:
+ complete = module.get_status(self.user, self.course) == 'completed'
+ if not complete:
+ break
+ return complete
###############################################################################
diff --git a/yaksh/templates/manage.html b/yaksh/templates/manage.html
index 17ce23e..c1f9da3 100644
--- a/yaksh/templates/manage.html
+++ b/yaksh/templates/manage.html
@@ -18,7 +18,7 @@
<li><a href="{{ URL_ROOT }}/exam/manage/courses">Courses</a></li>
<li><a href="{{ URL_ROOT }}/exam/manage/monitor">Monitor</a></li>
<li><a href="{{ URL_ROOT }}/exam/manage/gradeuser">Grade User</a></li>
- <li><a href="{{ URL_ROOT }}/exam/manage/grader"> Grader </a></li>
+ <li><a href="{{ url_root }}/exam/manage/grader"> Regrade </a></li>
<li><a href="{{ URL_ROOT }}/exam/reset/changepassword">Change Password</a></li>
<li><a href="{{ URL_ROOT }}/exam/viewprofile"> {{ user.get_full_name.title }} </a></li>
<li><a href="{{URL_ROOT}}/exam/logout/" id="logout">Logout</a></li>
diff --git a/yaksh/templates/yaksh/course_detail.html b/yaksh/templates/yaksh/course_detail.html
index a5d10a7..9fcae68 100644
--- a/yaksh/templates/yaksh/course_detail.html
+++ b/yaksh/templates/yaksh/course_detail.html
@@ -136,12 +136,14 @@
<th>Sr No.</th>
<th>Students</th>
<th>Total</th>
+ <th>Grade</th>
<th colspan="{{modules|length}}">Modules</th>
</tr>
<tr>
<th scope="row"></th>
<th></th>
<th></th>
+ <th></th>
{% if modules %}
{% for module in modules %}
<th>
@@ -171,6 +173,10 @@
{% course_completion_percent course student as c_percent %}
{{c_percent}} %
</td>
+ <td>
+ {% course_grade course student as grade %}
+ {{grade}}
+ </td>
{% if modules %}
{% for module in modules %}
<td>
diff --git a/yaksh/templates/yaksh/course_modules.html b/yaksh/templates/yaksh/course_modules.html
index afbae75..6c93e97 100644
--- a/yaksh/templates/yaksh/course_modules.html
+++ b/yaksh/templates/yaksh/course_modules.html
@@ -17,6 +17,7 @@
<center>{{ msg }}</center>
</div>
{% endif %}
+<b>Grade: {% if grade %} {{ grade }} {% else %} Will be available once the course is complete {% endif %}</b>
{% if learning_modules %}
<table class="table">
{% for module in learning_modules %}
diff --git a/yaksh/templates/yaksh/courses.html b/yaksh/templates/yaksh/courses.html
index dabf8eb..ba09c6d 100644
--- a/yaksh/templates/yaksh/courses.html
+++ b/yaksh/templates/yaksh/courses.html
@@ -56,6 +56,10 @@
<a href="{{URL_ROOT}}/exam/manage/courses/all_learning_module">
Add/View Modules</a>
</li>
+ <li>
+ <a href="{% url 'grades:grading_systems'%}">
+ Add/View Grading Systems </a>
+ </li>
</ul>
</div>
</div>
diff --git a/yaksh/templatetags/custom_filters.py b/yaksh/templatetags/custom_filters.py
index 26646b1..0c5eb5a 100644
--- a/yaksh/templatetags/custom_filters.py
+++ b/yaksh/templatetags/custom_filters.py
@@ -66,8 +66,13 @@ def course_completion_percent(course, user):
@register.simple_tag
+def course_grade(course, user):
+ return course.get_grade(user)
+
+
+@register.simple_tag
def get_ordered_testcases(question, answerpaper):
- return question.get_ordered_test_cases(answerpaper)
+ return question.get_ordered_test_cases(answerpaper)
@register.simple_tag
def get_answer_for_arrange_options(ans, question):
diff --git a/yaksh/test_models.py b/yaksh/test_models.py
index e7a6fe5..41730c3 100644
--- a/yaksh/test_models.py
+++ b/yaksh/test_models.py
@@ -1838,3 +1838,101 @@ class AssignmentUploadTestCases(unittest.TestCase):
actual_file_name = self.quiz.description.replace(" ", "_")
file_name = file_name.replace(" ", "_")
self.assertIn(actual_file_name, file_name)
+
+
+class CourseStatusTestCases(unittest.TestCase):
+ def setUp(self):
+ user = User.objects.get(username='creator')
+ self.course = Course.objects.create(name="Demo Course", creator=user,
+ enrollment="Enroll Request")
+ self.module = LearningModule.objects.create(name='M1', creator=user,
+ description='module one')
+ self.quiz1 = Quiz.objects.create(time_between_attempts=0, weightage=50,
+ description='qz1')
+ self.quiz2 = Quiz.objects.create(time_between_attempts=0, weightage=100,
+ description='qz2')
+ question = Question.objects.first()
+ self.qpaper1 = QuestionPaper.objects.create(quiz=self.quiz1)
+ self.qpaper2 = QuestionPaper.objects.create(quiz=self.quiz2)
+ self.qpaper1.fixed_questions.add(question)
+ self.qpaper2.fixed_questions.add(question)
+ self.qpaper1.update_total_marks()
+ self.qpaper2.update_total_marks()
+ self.qpaper1.save()
+ self.qpaper2.save()
+ self.unit_1_quiz = LearningUnit.objects.create(order=1, type='quiz',
+ quiz=self.quiz1)
+ self.unit_2_quiz = LearningUnit.objects.create(order=2, type='quiz',
+ quiz=self.quiz2)
+ self.module.learning_unit.add(self.unit_1_quiz)
+ self.module.learning_unit.add(self.unit_2_quiz)
+ self.module.save()
+ self.course.learning_module.add(self.module)
+ student = User.objects.get(username='course_user')
+ self.course.students.add(student)
+ self.course.save()
+
+ attempt = 1
+ ip = '127.0.0.1'
+ self.answerpaper1 = self.qpaper1.make_answerpaper(student, ip, attempt,
+ self.course.id)
+ self.answerpaper2 = self.qpaper2.make_answerpaper(student, ip, attempt,
+ self.course.id)
+
+ self.course_status = CourseStatus.objects.create(course=self.course,
+ user=student)
+
+ def tearDown(self):
+ self.course_status.delete()
+ self.answerpaper1.delete()
+ self.answerpaper2.delete()
+ self.qpaper1.delete()
+ self.qpaper2.delete()
+ self.quiz1.delete()
+ self.quiz2.delete()
+ self.unit_1_quiz.delete()
+ self.unit_2_quiz.delete()
+ self.module.delete()
+ self.course.delete()
+
+ def test_course_is_complete(self):
+ # When
+ self.course_status.completed_units.add(self.unit_1_quiz)
+ # Then
+ self.assertFalse(self.course_status.is_course_complete())
+
+ # When
+ self.course_status.completed_units.add(self.unit_2_quiz)
+ # Then
+ self.assertTrue(self.course_status.is_course_complete())
+
+ # Given
+ self.answerpaper1.marks_obtained = 1
+ self.answerpaper1.save()
+ self.answerpaper2.marks_obtained = 0
+ self.answerpaper2.save()
+ # When
+ self.course_status.calculate_percentage()
+ # Then
+ self.assertEqual(round(self.course_status.percentage, 2), 33.33)
+ # When
+ self.course_status.set_grade()
+ # Then
+ self.assertEqual(self.course_status.get_grade(), 'F')
+
+ # Given
+ self.answerpaper1.marks_obtained = 0
+ self.answerpaper1.save()
+ self.answerpaper2.marks_obtained = 1
+ self.answerpaper2.save()
+ # When
+ self.course_status.calculate_percentage()
+ # Then
+ self.assertEqual(round(self.course_status.percentage, 2), 66.67)
+ # When
+ self.course_status.set_grade()
+ # Then
+ self.assertEqual(self.course_status.get_grade(), 'B')
+
+ # Test get course grade after completion
+ self.assertEqual(self.course.get_grade(self.answerpaper1.user), 'B')
diff --git a/yaksh/views.py b/yaksh/views.py
index 083fd67..1cb77fc 100644
--- a/yaksh/views.py
+++ b/yaksh/views.py
@@ -1672,6 +1672,10 @@ def grade_user(request, quiz_id=None, user_id=None, attempt_number=None,
'comments_%d' % paper.question_paper.id, 'No comments')
paper.save()
+ course_status = CourseStatus.objects.filter(course=course, user=user)
+ if course_status.exists():
+ course_status.first().set_grade()
+
return my_render_to_response(
'yaksh/grade_user.html', context, context_instance=ci
)
@@ -1927,14 +1931,27 @@ def regrade(request, course_id, question_id=None, answerpaper_id=None,
answerpaper = get_object_or_404(AnswerPaper, pk=answerpaper_id)
for question in answerpaper.questions.all():
details.append(answerpaper.regrade(question.id))
+ course_status = CourseStatus.objects.filter(user=answerpaper.user,
+ course=answerpaper.course)
+ if course_status.exists():
+ course_status.first().set_grade()
if questionpaper_id is not None and question_id is not None:
answerpapers = AnswerPaper.objects.filter(questions=question_id,
question_paper_id=questionpaper_id, course_id=course_id)
for answerpaper in answerpapers:
details.append(answerpaper.regrade(question_id))
+ course_status = CourseStatus.objects.filter(user=answerpaper.user,
+ course=answerpaper.course)
+ if course_status.exists():
+ course_status.first().set_grade()
if answerpaper_id is not None and question_id is not None:
answerpaper = get_object_or_404(AnswerPaper, pk=answerpaper_id)
details.append(answerpaper.regrade(question_id))
+ course_status = CourseStatus.objects.filter(user=answerpaper.user,
+ course=answerpaper.course)
+ if course_status.exists():
+ course_status.first().set_grade()
+
return grader(request, extra_context={'details': details})
@@ -2723,6 +2740,12 @@ def course_modules(request, course_id, msg=None):
learning_modules = course.get_learning_modules()
context = {"course": course, "learning_modules": learning_modules,
"user": user, "msg": msg}
+ course_status = CourseStatus.objects.filter(course=course, user=user)
+ if course_status.exists():
+ course_status = course_status.first()
+ if not course_status.grade:
+ course_status.set_grade()
+ context['grade'] = course_status.get_grade()
return my_render_to_response('yaksh/course_modules.html', context)