summaryrefslogtreecommitdiff
path: root/yaksh
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh')
-rw-r--r--yaksh/models.py44
-rw-r--r--yaksh/static/yaksh/css/custom.css2
-rw-r--r--yaksh/templates/yaksh/course_added_modules.html16
-rw-r--r--yaksh/templates/yaksh/show_lesson_statistics.html152
-rw-r--r--yaksh/templatetags/custom_filters.py7
-rw-r--r--yaksh/urls.py4
-rw-r--r--yaksh/views.py16
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>&nbsp;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>&nbsp;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)