summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoradityacp2020-11-06 18:21:48 +0530
committeradityacp2020-11-06 18:21:48 +0530
commitfe5b3c41aa898fa7491a7ec9bce28c5e1c5b542d (patch)
treee831246ddb7cdbff9a11dde0a554cd4a37ced49d
parent43958e5932d68fce533d60a1abb953680d422ba9 (diff)
downloadonline_test-fe5b3c41aa898fa7491a7ec9bce28c5e1c5b542d.tar.gz
online_test-fe5b3c41aa898fa7491a7ec9bce28c5e1c5b542d.tar.bz2
online_test-fe5b3c41aa898fa7491a7ec9bce28c5e1c5b542d.zip
Statistics app for video tracking
-rw-r--r--stats/__init__.py0
-rw-r--r--stats/admin.py8
-rw-r--r--stats/apps.py5
-rw-r--r--stats/models.py24
-rw-r--r--stats/templates/view_lesson_tracking.html69
-rw-r--r--stats/tests.py3
-rw-r--r--stats/urls.py12
-rw-r--r--stats/views.py54
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>&nbsp;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)