From 5f02880d022053ed07ed218fd52d9e436f6455ee Mon Sep 17 00:00:00 2001 From: adityacp Date: Mon, 16 Nov 2020 16:54:07 +0530 Subject: Change stats and yaksh - Show total visits per student in lesson statistics - Remove settimeout ajax calls for tracking video positions - Show initial views per lesson in the course modules section --- stats/models.py | 16 +++++++++ stats/templates/view_lesson_tracking.html | 39 ++++++++++++++------- yaksh/static/yaksh/js/show_toc.js | 26 +++++++------- yaksh/templates/yaksh/course_added_modules.html | 34 ++++++++++++++++--- yaksh/templates/yaksh/courses.html | 20 ++++++----- yaksh/templates/yaksh/show_lesson_statistics.html | 41 +++++++++++++++++------ yaksh/templates/yaksh/show_video.html | 2 ++ yaksh/templatetags/custom_filters.py | 11 ++++++ 8 files changed, 139 insertions(+), 50 deletions(-) diff --git a/stats/models.py b/stats/models.py index 0200a80..56c7f0d 100644 --- a/stats/models.py +++ b/stats/models.py @@ -1,7 +1,11 @@ +# Python Imports +import pandas as pd + # Django Imports from django.db import models from django.utils import timezone from django.contrib.auth.models import User +from django.db.models import F # Local Imports from yaksh.models import Course, Lesson @@ -93,6 +97,18 @@ class TrackLesson(models.Model): return str(timezone.timedelta(seconds=total_duration)) return self.get_current_time() + def get_no_of_vists(self): + lesson_logs = self.lessonlog_set.values("last_access_time").annotate( + visits=F('last_access_time') + ) + df = pd.DataFrame(lesson_logs) + visits = 1 + if not df.empty: + visits = df.groupby( + [df['visits'].dt.date] + ).first().count()['visits'] + return visits + def __str__(self): return (f"Track {self.lesson} in {self.course} " f"for {self.user.get_full_name()}") diff --git a/stats/templates/view_lesson_tracking.html b/stats/templates/view_lesson_tracking.html index ef5c9ae..d8d35c2 100644 --- a/stats/templates/view_lesson_tracking.html +++ b/stats/templates/view_lesson_tracking.html @@ -5,26 +5,29 @@ {% endblock %} {% block content %} -
+
{% with objects.object_list as trackings %}

Statistics for {% with trackings|first as entry %} {{entry.lesson}} {% endwith %}

- +  Back

@@ -43,19 +46,29 @@ Percentage Watched  Watched Once Completely  Total Time Spent  + Total Visits  {% for track in trackings %} - {{ forloop.counter0|add:objects.start_index }} + {{ forloop.counter0 }} {{track.user.get_full_name}} {{track.get_last_access_time}} {{track.creation_time}} {{track.get_current_time}} {{track.get_video_duration}} {{track.get_percentage_complete}} - {{track.get_watched}} + + {% with track.get_watched as watched %} + {% if watched %} + {{watched}} + {% else %} + {{watched}} + {% endif %} + {% endwith %} + {{track.time_spent}} + {{track.get_no_of_vists}} {% endfor %} diff --git a/yaksh/static/yaksh/js/show_toc.js b/yaksh/static/yaksh/js/show_toc.js index 914ab1c..2bedc6a 100644 --- a/yaksh/static/yaksh/js/show_toc.js +++ b/yaksh/static/yaksh/js/show_toc.js @@ -27,10 +27,8 @@ $(document).ready(function() { var total_duration; player.on('ready loadedmetadata', event => { total_duration = parseInt(player.duration); + store_tracker_time(total_duration); $("#video_duration").val(get_time_in_hrs(total_duration)); - if (total_duration > 0) { - start_tracker((total_duration * 1000) / 4, player); - } }); player.on('timeupdate', event => { @@ -44,10 +42,17 @@ $(document).ready(function() { } else { if(player.fullscreen.active) player.fullscreen.exit(); + player.pause() url = $("#toc_"+content.id).val(); ajax_call(url, "GET", screen_lock=true); } } + if(markers.length > 0 && current_time >= markers[track_count]) { + track_count++; + var csrf = document.getElementById("track-form").elements[0].value; + ajax_call($("#track-form").attr("action"), $("#track-form").attr("method"), + $("#track-form").serialize(), csrf, screen_lock=false); + } }); player.on('ended', event => { var csrf = document.getElementById("track-form").elements[0].value; @@ -57,16 +62,11 @@ $(document).ready(function() { }); }); - -function start_tracker(slice_duration, player) { - setTimeout(function run() { - if(player && player.playing) { - var csrf = document.getElementById("track-form").elements[0].value; - ajax_call($("#track-form").attr("action"), $("#track-form").attr("method"), - $("#track-form").serialize(), csrf, screen_lock=false); - } - setTimeout(run, slice_duration); - }, slice_duration); +function store_tracker_time(duration) { + marker = duration / 4; + for(var i = marker; i <= duration - marker; i = i + marker) { + markers.push(i); + } } function show_topic(description, override) { diff --git a/yaksh/templates/yaksh/course_added_modules.html b/yaksh/templates/yaksh/course_added_modules.html index d420b95..80d87c0 100644 --- a/yaksh/templates/yaksh/course_added_modules.html +++ b/yaksh/templates/yaksh/course_added_modules.html @@ -1,3 +1,4 @@ +{% load custom_filters %} {% if is_modules %} {% block pagetitle %}

Course Modules

{% endblock %} @@ -49,7 +50,8 @@ {% for unit in units %} - + + diff --git a/yaksh/templates/yaksh/courses.html b/yaksh/templates/yaksh/courses.html index 151e1fb..38c106c 100644 --- a/yaksh/templates/yaksh/courses.html +++ b/yaksh/templates/yaksh/courses.html @@ -106,6 +106,17 @@
{{course.name}} +
+ {% if user.id != course.creator.id %} + + Allotted Course + + {% else %} + + Created Course + + {% endif %} +
@@ -119,15 +130,6 @@

-
- - {% if user.id != course.creator.id %} - Allotted Course - {% else %} - Created Course - {% endif %} - -
{% if course.active %} diff --git a/yaksh/templates/yaksh/show_lesson_statistics.html b/yaksh/templates/yaksh/show_lesson_statistics.html index 0c35e40..a7c2ebd 100644 --- a/yaksh/templates/yaksh/show_lesson_statistics.html +++ b/yaksh/templates/yaksh/show_lesson_statistics.html @@ -1,7 +1,31 @@ {% extends "manage.html" %} +{% load static %} {% load custom_filters %} {% block title %} Lesson Statistics {% endblock %} {% block pagetitle %} Statistics for {{lesson}} {% endblock %} +{% block script %} + + +{% endblock %} {% block content %}

@@ -11,11 +35,6 @@  Back
-

{% if data %} @@ -161,16 +180,18 @@

{% endif %} {% include "yaksh/paginator.html" %} -
+ {{forloop.counter}} {% if unit.type == "quiz" %} {% if unit.quiz.is_exercise %} @@ -69,12 +71,12 @@ {% if quiz.questionpaper_set.get.id %} - Edit Question Paper + Question Paper {% else %} - Add Question Paper + Question Paper {% endif %} {% endwith %} @@ -93,6 +95,14 @@ Lesson {% endif %} + {% if unit.type == "quiz" %} + ---- + {% else %} + {% get_lesson_views course.id unit.lesson.id as views %} + {{views.0}} views out of {{views.1}} + {% endif %} + {% if unit.type == "quiz" %} {% if unit.quiz.questionpaper_set.get.id %} @@ -104,9 +114,23 @@ ---- {% endif %} {% else %} - -  Statistics + {% endif %}
+
+ - - - + + + + {% for data in objects.object_list %} - + {% get_answers data.toc_id data.student_id as user_answer %} diff --git a/yaksh/templates/yaksh/show_video.html b/yaksh/templates/yaksh/show_video.html index 0151f6b..b4f5628 100644 --- a/yaksh/templates/yaksh/show_video.html +++ b/yaksh/templates/yaksh/show_video.html @@ -9,6 +9,8 @@ var contents_by_time = JSON.parse('{{ contents_by_time|safe }}'); var loc = 0; var video_time = []; + var markers = []; + var track_count = 0; diff --git a/yaksh/templatetags/custom_filters.py b/yaksh/templatetags/custom_filters.py index a3cd3f1..91681c2 100644 --- a/yaksh/templatetags/custom_filters.py +++ b/yaksh/templatetags/custom_filters.py @@ -11,7 +11,11 @@ except ImportError: from pygments import highlight from pygments.lexers import get_lexer_by_name from pygments.formatters import HtmlFormatter + +# Local Imports from yaksh.models import User, Course, Quiz, TableOfContents, Lesson +from stats.models import TrackLesson + register = template.Library() @@ -200,3 +204,10 @@ def has_lesson_video(lesson_id): def get_tc_percent(tc_id, data): return data.get(str(tc_id), 0) + +@register.simple_tag +def get_lesson_views(course_id, lesson_id): + course = Course.objects.get(id=course_id) + return TrackLesson.objects.filter( + course_id=course_id, lesson_id=lesson_id + ).count(), course.students.count() -- cgit
Sr No.Student NameEmailLatest SubmissionStudent Name Email Latest Submission 
{{ forloop.counter0|add:objects.start_index }}{{ forloop.counter }} {{data.student__first_name}} {{data.student__last_name}} {{data.student__email}}