diff options
Diffstat (limited to 'yaksh')
-rw-r--r-- | yaksh/models.py | 44 | ||||
-rw-r--r-- | yaksh/static/yaksh/css/custom.css | 2 | ||||
-rw-r--r-- | yaksh/templates/yaksh/course_added_modules.html | 16 | ||||
-rw-r--r-- | yaksh/templates/yaksh/show_lesson_statistics.html | 152 | ||||
-rw-r--r-- | yaksh/templatetags/custom_filters.py | 7 | ||||
-rw-r--r-- | yaksh/urls.py | 4 | ||||
-rw-r--r-- | 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 %} </td> + <td> + {% if unit.type == "quiz" %} + {% if unit.quiz.questionpaper_set.get.id %} + <a href="{% url 'yaksh:show_statistics' unit.quiz.questionpaper_set.get.id course.id %}" class="btn btn-outline-primary"> + <i class="fa fa-line-chart"></i> + Statistics + </a> + {% else %} + ---- + {% endif %} + {% else %} + <a href="{% url 'yaksh:lesson_statistics' course.id unit.lesson.id %}" class="btn btn-outline-primary"> + <i class="fa fa-line-chart"></i> Statistics + </a> + {% endif %} + </td> </tr> {% endfor %} </table> 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}} +<div class="container-fluid"> + <br> + <a class="btn btn-primary" href="{% url 'yaksh:get_course_modules' course_id %}"> + <i class="fa fa-arrow-left"></i> Back + </a> + <br><br> + {% if data %} + <div class="row"> + <div class="col-md-3"> + <ul class="list-group"> + {% for toc, count in data.items %} + <li class="list-group-item"> + <div class="row"> + <div class="col-md-4"> + {{ toc.content_object.summary }} + </div> + <div class="col-md-4"> + {{toc.get_content_display}} + </div> + <div class="col-md-4"> + <a href="{% url 'yaksh:lesson_statistics' toc.course_id toc.lesson_id toc.id %}">Details</a> + </div> + </table> + </li> + {% endfor %} + </ul> + </div> + <div class="col-md-7"> + {% if not is_que_data %} + <table class="table table-responsive"> + <tr> + <th>TOC</th> + <th>Type</th> + <th>Submissions</th> + </tr> + {% for toc, count in data.items %} + <tr> + <td>{{ toc.content_object.summary }}</td> + <td>{{ toc.get_content_display }}</td> + <td>{{ count }}</td> + </tr> + {% endfor %} + </table> + {% else %} + <div class="card"> + {% with per_que_data.0 as question %} + <div class="card-header"> + {{question.summary}} + <div> + {% if question.language == "other" %} + <small class="text text-muted"><strong>Topic:</strong> <span class="badge badge-primary">{{question.topic}}</small></span> + {% else %} + <small class="textx text-muted"><strong>Language:</strong> <span class="badge badge-primary">{{question.language}}</span></small> + {% endif %} + {% if question.type == "mcq" %} + <small class="text text-muted"><strong>Type:</strong> <span class="badge badge-primary">SINGLE CORRECT CHOICE</span></small> + {% elif question.type == "mcc" %} + <small class="text text-muted"><strong>Type:</strong> <span class="badge badge-primary">MULTIPLE CORRECT CHOICES</span></small> + {% elif question.type == "code" %} + <small class="text text-muted"><strong>Type:</strong> <span class="badge badge-primary">PROGRAMMING</span></small> + {% elif question.type == "upload" %} + <small class="text text-muted"><strong>Type:</strong> <span class="badge badge-primary">ASSIGNMENT UPLOAD</span></small> + {% elif question.type == "integer" %} + <small class="text text-muted"><strong>Type:</strong> <span class="badge badge-primary">FILL IN THE BLANKS WITH INTEGER ANSWER</span></small> + {% elif question.type == "string" %} + <small class="text text-muted"><strong>Type:</strong> <span class="badge badge-primary">FILL IN THE BLANKS WITH STRING ANSWER</span></small> + {% if testcase.string_check == "lower" %} + <br>(CASE INSENSITIVE) + {% else %} + <br>(CASE SENSITIVE) + {% endif %} + {% elif question.type == "float" %} + <small class="text text-muted"><strong>Type:</strong> <span class="badge badge-primary">FILL IN THE BLANKS WITH FLOAT ANSWER</span></small> + {% elif question.type == "arrange" %} + <small class="text text-muted"><strong>Type:</strong> <span class="badge badge-primary">ARRANGE THE OPTIONS IN CORRECT ORDER</span></small> + {% endif %} + <span class="badge badge-info pull-right"> + <small><strong>Marks: {{ question.points }}</strong></small> + </span> + </div> + </div> + <div class="card-body"> + {{question.description|safe}} + <br> + {% for tc in question.get_test_cases %} + {% if question.type == "mcc" or question.type == "mcq" %} + {% if tc.correct %} + <span class="badge badge-pill badge-success"> + {{forloop.counter}}. + </span> + {% else %} + <span class="badge badge-pill badge-dark"> + {{ forloop.counter }}. + </span> + {% endif %} + {{tc.options}} + {% elif question.type == "integer" %} + <span class="badge badge-pill badge-success">Answer:</span> + {{tc.correct}} + {% elif question.type == "string" %} + <span class="badge badge-pill badge-success">Answer:</span> + {{tc.correct}} ({{tc.get_string_check_display}}) + {% elif question.type == "float" %} + {{tc.correct}} with Error Margin {{ tc.error_margin }} + {% endif %} + <br> + {% endfor %} + </div> + {% endwith %} + </div> + <br> + <table class="table table-responsive"> + <tr> + <th>Sr No.</th> + <th>Student Name</th> + <th>Email</th> + <th>Latest Answer</th> + <th>Status</th> + </tr> + {% for data in per_que_data.1 %} + <tr> + <td>{{forloop.counter}}</td> + <td>{{data.student__first_name}} {{data.student__last_name}}</td> + <td>{{data.student__email}}</td> + {% get_answers data.toc_id data.student_id as user_answer %} + <td>{{ user_answer.0 }}</td> + <td> + {% if user_answer.1 %} + <span class="badge badge-success"> + Correct + </span> + {% else %} + <span class="badge badge-secondary"> + Not correct + </span> + {% endif %} + </td> + </tr> + {% endfor %} + </table> + {% endif %} + </div> + </div> + {% else %} + <div class="alert alert-info"> + No lesson quizzes found + </div> + {% endif %} +</div> {% 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/<int:course_id>/<int:toc_id>', views.submit_marker_quiz, name='submit_marker_quiz'), path('manage/lesson/stats/<int:course_id>/<int:lesson_id>', - views.lessson_statistics, name='lessson_statistics'), + views.lesson_statistics, name='lesson_statistics'), + path('manage/lesson/stats/<int:course_id>/<int:lesson_id>/<int:toc_id>', + 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) |