diff options
author | adityacp | 2020-11-06 18:21:48 +0530 |
---|---|---|
committer | adityacp | 2020-11-06 18:21:48 +0530 |
commit | fe5b3c41aa898fa7491a7ec9bce28c5e1c5b542d (patch) | |
tree | e831246ddb7cdbff9a11dde0a554cd4a37ced49d /stats | |
parent | 43958e5932d68fce533d60a1abb953680d422ba9 (diff) | |
download | online_test-fe5b3c41aa898fa7491a7ec9bce28c5e1c5b542d.tar.gz online_test-fe5b3c41aa898fa7491a7ec9bce28c5e1c5b542d.tar.bz2 online_test-fe5b3c41aa898fa7491a7ec9bce28c5e1c5b542d.zip |
Statistics app for video tracking
Diffstat (limited to 'stats')
-rw-r--r-- | stats/__init__.py | 0 | ||||
-rw-r--r-- | stats/admin.py | 8 | ||||
-rw-r--r-- | stats/apps.py | 5 | ||||
-rw-r--r-- | stats/models.py | 24 | ||||
-rw-r--r-- | stats/templates/view_lesson_tracking.html | 69 | ||||
-rw-r--r-- | stats/tests.py | 3 | ||||
-rw-r--r-- | stats/urls.py | 12 | ||||
-rw-r--r-- | stats/views.py | 54 |
8 files changed, 175 insertions, 0 deletions
diff --git a/stats/__init__.py b/stats/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/stats/__init__.py diff --git a/stats/admin.py b/stats/admin.py new file mode 100644 index 0000000..b400d27 --- /dev/null +++ b/stats/admin.py @@ -0,0 +1,8 @@ +# Django Imports +from django.contrib import admin + +# Local Imports +from stats.models import TrackLesson + + +admin.site.register(TrackLesson) diff --git a/stats/apps.py b/stats/apps.py new file mode 100644 index 0000000..2d09b92 --- /dev/null +++ b/stats/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class StatsConfig(AppConfig): + name = 'stats' diff --git a/stats/models.py b/stats/models.py new file mode 100644 index 0000000..f2f1bce --- /dev/null +++ b/stats/models.py @@ -0,0 +1,24 @@ +# Django Imports +from django.db import models +from django.utils import timezone +from django.contrib.auth.models import User + +# Local Imports +from yaksh.models import Course, Lesson + + +class TrackLesson(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) + course = models.ForeignKey(Course, on_delete=models.CASCADE) + lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE) + current_time = models.CharField(max_length=100, default="00:00:00") + video_duration = models.CharField(max_length=100, default="00:00:00") + last_access_time = models.DateTimeField(default=timezone.now) + creation_time = models.DateTimeField(auto_now_add=True) + + class Meta: + unique_together = ('user', 'course', 'lesson') + + 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 new file mode 100644 index 0000000..fd87d70 --- /dev/null +++ b/stats/templates/view_lesson_tracking.html @@ -0,0 +1,69 @@ +{% extends "manage.html" %} + +{% block title %} Lesson Views {% endblock %} +{% block script %} +<script type="text/javascript"> + function get_time_in_seconds(time) { + var time = time.split(":"); + var hh = parseInt(time[0]); + var mm = parseInt(time[1]); + var ss = parseInt(time[2]); + return hh * 3600 + mm * 60 + ss; + } + + $(document).ready(function() { + $('#stats-table tr').each(function() { + var td = $(this).find("td"); + var elapsed = td.eq(4).html(); + var duration = td.eq(5).html(); + var input = td.eq(6).find("input"); + if (elapsed != undefined && duration != undefined) { + percent = (get_time_in_seconds(elapsed) / get_time_in_seconds(duration)) * 100; + input.val(Math.round(percent)); + } + }); + }); +</script> +{% endblock %} +{% block content %} +<div class="container"> + {% with objects.object_list as trackings %} + <center> + <h3>Statistics for {% with trackings|first as entry %} {{entry.lesson}} {% endwith %}</h3> + </center> + <a class="btn btn-primary" href="{% url 'yaksh:lesson_statistics' course_id lesson_id %}"> + <i class="fa fa-arrow-left"></i> Back + </a> + <br><br> + {% include "yaksh/paginator.html" %} + <br> + <h4><strong>{{total}} student(s) viewed this lesson</strong></h4> + <table class="table table-responsive" id="stats-table"> + <tr> + <th>Sr No.</th> + <th>Student Name</th> + <th>Last access on</th> + <th>Started on</th> + <th>Current Time</th> + <th>Video Duration</th> + <th>Percentage watched</th> + </tr> + {% for track in trackings %} + <tr> + <td>{{ forloop.counter0|add:objects.start_index }}</td> + <td>{{track.user.get_full_name}}</td> + <td>{{track.last_access_time}}</td> + <td>{{track.creation_time}}</td> + <td>{{track.current_time}}</td> + <td>{{track.video_duration}}</td> + <td> + <input type="text" class="form-control" readonly=""> + </td> + </tr> + {% endfor %} + </table> + {% endwith %} + <br> + {% include "yaksh/paginator.html" %} +</div> +{% endblock %}
\ No newline at end of file diff --git a/stats/tests.py b/stats/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/stats/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/stats/urls.py b/stats/urls.py new file mode 100644 index 0000000..f11148f --- /dev/null +++ b/stats/urls.py @@ -0,0 +1,12 @@ +from django.urls import path +from stats import views + + +app_name = "stats" + +urlpatterns = [ + path('submit/video/watch/<int:tracker_id>', + views.add_tracker, name='add_tracker'), + path('view/watch/stats/<int:course_id>/<int:lesson_id>', + views.view_lesson_watch_stats, name='view_lesson_watch_stats'), +] diff --git a/stats/views.py b/stats/views.py new file mode 100644 index 0000000..ddbc1b3 --- /dev/null +++ b/stats/views.py @@ -0,0 +1,54 @@ +# Django Imports +from django.shortcuts import render, get_object_or_404 +from django.http import JsonResponse +from django.utils import timezone +from django.contrib.auth.decorators import login_required +from django.core.paginator import Paginator + +# Local Imports +from stats.models import TrackLesson +from yaksh.models import Course +from yaksh.decorators import email_verified + + +@login_required +@email_verified +def add_tracker(request, tracker_id): + user = request.user + track = get_object_or_404( + TrackLesson.objects.select_related("course"), id=tracker_id + ) + if not track.course.is_student(user): + raise Http404("You are not enrolled in this course") + context = {} + video_duration = request.POST.get('video_duration') + current_time = request.POST.get('current_video_time') + if current_time: + track.current_time = current_time + track.video_duration = video_duration + track.last_access_time = timezone.now() + track.save() + success = True + else: + success = False + context = {"success": success} + return JsonResponse(context) + + +@login_required +@email_verified +def view_lesson_watch_stats(request, course_id, lesson_id): + user = request.user + course = get_object_or_404(Course, pk=course_id) + if not course.is_creator(user) and not course.is_teacher(user): + raise Http404('This course does not belong to you') + trackings = TrackLesson.objects.get_queryset().filter( + course_id=course_id, lesson_id=lesson_id + ).order_by("id") + total = trackings.count() + paginator = Paginator(trackings, 30) + page = request.GET.get('page') + trackings = paginator.get_page(page) + context = {'objects': trackings, 'total': total, 'course_id': course_id, + 'lesson_id': lesson_id} + return render(request, 'view_lesson_tracking.html', context) |