From 98908b86a94da4a2552564e057457c48b46d4ac3 Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 14 Sep 2020 16:04:35 +0530 Subject: Show lesson quiz statistics --- yaksh/models.py | 44 ++++++- yaksh/static/yaksh/css/custom.css | 2 +- yaksh/templates/yaksh/course_added_modules.html | 16 +++ yaksh/templates/yaksh/show_lesson_statistics.html | 152 +++++++++++++++++++++- yaksh/templatetags/custom_filters.py | 7 +- yaksh/urls.py | 4 +- yaksh/views.py | 16 ++- 7 files changed, 227 insertions(+), 14 deletions(-) diff --git a/yaksh/models.py b/yaksh/models.py index 19f3302..9f8c634 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -2748,13 +2748,47 @@ class Comment(ForumBase): class TOCManager(models.Manager): def get_data(self, course_id, lesson_id): - toc = TableOfContents.objects.filter( + contents = TableOfContents.objects.filter( course_id=course_id, lesson_id=lesson_id, content__in=[2, 3, 4] ) - answers = LessonQuizAnswer.objects.select_related("toc").filter( - toc__course_id=course_id, toc__lesson_id=lesson_id - ) - return answers + data = {} + for toc in contents: + data[toc] = LessonQuizAnswer.objects.filter( + toc_id=toc.id).values_list("toc_id").distinct().count() + return data + + def get_question_stats(self, toc_id): + answers = LessonQuizAnswer.objects.filter( + toc_id=toc_id) + question = answers.first().toc.content_object + answers = answers.values( + "student__first_name", "student__last_name", "student__email", + "student_id", "toc_id" + ).distinct() + return question, answers + + def get_answer(self, toc_id, user_id): + submission = LessonQuizAnswer.objects.filter( + toc_id=toc_id, student_id=user_id).last() + question = submission.toc.content_object + attempted_answer = submission.answer + if question.type == "mcq": + submitted_answer = literal_eval(attempted_answer.answer) + answers = [ + tc.options + for tc in question.get_test_cases(id=submitted_answer) + ] + answer = ",".join(answers) + elif question.type == "mcc": + submitted_answer = literal_eval(attempted_answer.answer) + answers = [ + tc.options + for tc in question.get_test_cases(id__in=submitted_answer) + ] + answer = ",".join(answers) + else: + answer = attempted_answer.answer + return answer, attempted_answer.correct class TableOfContents(models.Model): diff --git a/yaksh/static/yaksh/css/custom.css b/yaksh/static/yaksh/css/custom.css index 9d4ab76..9f29349 100644 --- a/yaksh/static/yaksh/css/custom.css +++ b/yaksh/static/yaksh/css/custom.css @@ -68,7 +68,7 @@ body, .dropdown-menu { } #sidebar.active { - margin-left: -370px; + margin-left: -350px; } #sidebar .sidebar-header { diff --git a/yaksh/templates/yaksh/course_added_modules.html b/yaksh/templates/yaksh/course_added_modules.html index 2d194b9..d420b95 100644 --- a/yaksh/templates/yaksh/course_added_modules.html +++ b/yaksh/templates/yaksh/course_added_modules.html @@ -93,6 +93,22 @@ Lesson {% endif %} + + {% if unit.type == "quiz" %} + {% if unit.quiz.questionpaper_set.get.id %} + + + Statistics + + {% else %} + ---- + {% endif %} + {% else %} + +  Statistics + + {% endif %} + {% endfor %} diff --git a/yaksh/templates/yaksh/show_lesson_statistics.html b/yaksh/templates/yaksh/show_lesson_statistics.html index 36b1fbd..f3e40b4 100644 --- a/yaksh/templates/yaksh/show_lesson_statistics.html +++ b/yaksh/templates/yaksh/show_lesson_statistics.html @@ -1,5 +1,155 @@ {% extends "manage.html" %} +{% load custom_filters %} {% block title %} Lesson Statistics {% endblock %} +{% block pagetitle %} Statistics for {{lesson}} {% endblock %} {% block content %} -{{data}} +
+
+ +  Back + +

+ {% if data %} +
+
+
    + {% for toc, count in data.items %} +
  • +
    +
    + {{ toc.content_object.summary }} +
    +
    + {{toc.get_content_display}} +
    +
    + Details +
    + +
  • + {% endfor %} +
+
+
+ {% if not is_que_data %} + + + + + + + {% for toc, count in data.items %} + + + + + + {% endfor %} +
TOCTypeSubmissions
{{ toc.content_object.summary }}{{ toc.get_content_display }}{{ count }}
+ {% else %} +
+ {% with per_que_data.0 as question %} +
+ {{question.summary}} +
+ {% if question.language == "other" %} + Topic: {{question.topic}} + {% else %} + Language: {{question.language}} + {% endif %} + {% if question.type == "mcq" %} + Type: SINGLE CORRECT CHOICE + {% elif question.type == "mcc" %} + Type: MULTIPLE CORRECT CHOICES + {% elif question.type == "code" %} + Type: PROGRAMMING + {% elif question.type == "upload" %} + Type: ASSIGNMENT UPLOAD + {% elif question.type == "integer" %} + Type: FILL IN THE BLANKS WITH INTEGER ANSWER + {% elif question.type == "string" %} + Type: FILL IN THE BLANKS WITH STRING ANSWER + {% if testcase.string_check == "lower" %} +
(CASE INSENSITIVE) + {% else %} +
(CASE SENSITIVE) + {% endif %} + {% elif question.type == "float" %} + Type: FILL IN THE BLANKS WITH FLOAT ANSWER + {% elif question.type == "arrange" %} + Type: ARRANGE THE OPTIONS IN CORRECT ORDER + {% endif %} + + Marks: {{ question.points }} + +
+
+
+ {{question.description|safe}} +
+ {% for tc in question.get_test_cases %} + {% if question.type == "mcc" or question.type == "mcq" %} + {% if tc.correct %} + + {{forloop.counter}}. + + {% else %} + + {{ forloop.counter }}. + + {% endif %} + {{tc.options}} + {% elif question.type == "integer" %} + Answer: + {{tc.correct}} + {% elif question.type == "string" %} + Answer: + {{tc.correct}} ({{tc.get_string_check_display}}) + {% elif question.type == "float" %} + {{tc.correct}} with Error Margin {{ tc.error_margin }} + {% endif %} +
+ {% endfor %} +
+ {% endwith %} +
+
+ + + + + + + + + {% for data in per_que_data.1 %} + + + + + {% get_answers data.toc_id data.student_id as user_answer %} + + + + {% endfor %} +
Sr No.Student NameEmailLatest AnswerStatus
{{forloop.counter}}{{data.student__first_name}} {{data.student__last_name}}{{data.student__email}}{{ user_answer.0 }} + {% if user_answer.1 %} + + Correct + + {% else %} + + Not correct + + {% endif %} +
+ {% endif %} +
+
+ {% else %} +
+ No lesson quizzes found +
+ {% endif %} +
{% endblock %} \ No newline at end of file diff --git a/yaksh/templatetags/custom_filters.py b/yaksh/templatetags/custom_filters.py index 0446ef3..c3dbba3 100644 --- a/yaksh/templatetags/custom_filters.py +++ b/yaksh/templatetags/custom_filters.py @@ -10,7 +10,7 @@ except ImportError: from pygments import highlight from pygments.lexers import get_lexer_by_name from pygments.formatters import HtmlFormatter -from yaksh.models import User, Course, Quiz +from yaksh.models import User, Course, Quiz, TableOfContents register = template.Library() @@ -178,3 +178,8 @@ def specail_attempt_monitor(user_id, course_id, quiz_id): if micromanagers.exists(): context['micromanager'] = micromanagers.first() return context + + +@register.simple_tag +def get_answers(toc_id, user_id): + return TableOfContents.objects.get_answer(toc_id, user_id) \ No newline at end of file diff --git a/yaksh/urls.py b/yaksh/urls.py index ada5829..7bd3182 100644 --- a/yaksh/urls.py +++ b/yaksh/urls.py @@ -264,5 +264,7 @@ urlpatterns = [ path('submit/marker/quiz//', views.submit_marker_quiz, name='submit_marker_quiz'), path('manage/lesson/stats//', - views.lessson_statistics, name='lessson_statistics'), + views.lesson_statistics, name='lesson_statistics'), + path('manage/lesson/stats///', + views.lesson_statistics, name='lesson_statistics'), ] diff --git a/yaksh/views.py b/yaksh/views.py index c817c51..ab0f95d 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -3900,13 +3900,19 @@ def submit_marker_quiz(request, course_id, toc_id): @login_required @email_verified -def lessson_statistics(request, course_id, lesson_id): +def lesson_statistics(request, course_id, lesson_id, toc_id=None): user = request.user course = get_object_or_404(Course, pk=course_id) if (not is_moderator(user) or not course.is_creator(user) or not course.is_creator(user)): raise Http404("You are not allowed to view this page") - toc = TableOfContents.objects.get_data(course_id, lesson_id) - return render(request, 'yaksh/show_lesson_statistics.html', { - 'data': toc, - }) + context = {} + data = TableOfContents.objects.get_data(course_id, lesson_id) + context['data'] = data + context['lesson'] = next(iter(data)).lesson + context['course_id'] = course_id + if toc_id: + per_que_data = TableOfContents.objects.get_question_stats(toc_id) + context['per_que_data'] = per_que_data + context['is_que_data'] = True + return render(request, 'yaksh/show_lesson_statistics.html', context) -- cgit