Commit e260a85b authored by I.K Seneviratne's avatar I.K Seneviratne

Committing some basic implementations for automating the student behavior module with SLPES.

.
parent ed774d47
...@@ -11,7 +11,7 @@ each method will return an HttpResponse that allows its data to be rendered into ...@@ -11,7 +11,7 @@ each method will return an HttpResponse that allows its data to be rendered into
arbitrary media types. arbitrary media types.
""" """
from random import Random
from MonitorLecturerApp.models import LectureRecordedVideo, LecturerVideoMetaData from MonitorLecturerApp.models import LectureRecordedVideo, LecturerVideoMetaData
from MonitorLecturerApp.serializers import LectureRecordedVideoSerializer, LecturerVideoMetaDataSerializer from MonitorLecturerApp.serializers import LectureRecordedVideoSerializer, LecturerVideoMetaDataSerializer
...@@ -24,6 +24,7 @@ from .logic import pdf_file_generator as pdf ...@@ -24,6 +24,7 @@ from .logic import pdf_file_generator as pdf
from .logic import head_gaze_estimation as hge from .logic import head_gaze_estimation as hge
from .logic import video_extraction as ve from .logic import video_extraction as ve
from .serializers import * from .serializers import *
from braces.views import CsrfExemptMixin
import datetime import datetime
...@@ -113,7 +114,8 @@ class LecturerSubjectViewSet(APIView): ...@@ -113,7 +114,8 @@ class LecturerSubjectViewSet(APIView):
# API for timetables # API for timetables
class FacultyTimetableViewSet(APIView): class FacultyTimetableViewSet(CsrfExemptMixin, APIView):
# authentication_classes = []
def get(self, request): def get(self, request):
timetable = FacultyTimetable.objects.all().filter() timetable = FacultyTimetable.objects.all().filter()
...@@ -1267,3 +1269,54 @@ class GetLectureGazeCorrelations(APIView): ...@@ -1267,3 +1269,54 @@ class GetLectureGazeCorrelations(APIView):
return Response({ return Response({
"correlations": gaze_correlations "correlations": gaze_correlations
}) })
##### BATCH PROCESS SECTION #####
# perform the student behavior analysis as a batch process
class BatchProcess(APIView):
def get(self, request):
video_name = request.query_params.get('video_name')
video_id = request.query_params.get('video_id')
return Response({
"response": True
})
# this API will check whether the lecture activity frame groupings exist
class CheckStudentBehaviorAvailability(APIView):
def get(self, request):
video_name = request.query_params.get('video_name')
#
# isActivityExist = LectureActivityFrameGroupings.objects.filter(
# lecture_activity_id__lecture_video_id__video_name=video_name).exists()
#
# isEmotionExist = LectureEmotionFrameGroupings.objects.filter(
# lecture_emotion_id__lecture_video_id__video_name=video_name).exists()
#
# isGazeExist = LectureGazeFrameGroupings.objects.filter(
# lecture_gaze_id__lecture_video_id__video_name=video_name).exists()
isActivityExist = bool(Random().randint(0,2))
isEmotionExist = bool(Random().randint(0,2))
isGazeExist = bool(Random().randint(0,2))
return Response({
"isActivityExist": isActivityExist,
"isEmotionExist": isEmotionExist,
"isGazeExist": isGazeExist
})
# this API will perform some random task (delete later)
class TestRandom(APIView):
def get(self, request):
random = Random().randint(0, 100)
return Response({
"response": random
})
\ No newline at end of file
import requests
def batch_process(video_id, video_name):
# call the activity process
activity_resp = requests.get('http://127.0.0.1:8000/process-lecture-activity/?lecture_video_name=' + video_name + '&lecture_video_id=' + video_id)
# call the emotion process
emotion_resp = requests.get('http://127.0.0.1:8000/process-lecture-emotion/?lecture_video_name=' + video_name + '&lecture_video_id=' + video_id)
# call the gaze process
gaze_resp = requests.get('http://127.0.0.1:8000/process-lecture-gaze-estimation/?lecture_video_name=' + video_name + '&lecture_video_id=' + video_id)
pass
\ No newline at end of file
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
<link rel="stylesheet" href="{% static 'FirstApp/css/sb-admin-2.min.css' %}"> <link rel="stylesheet" href="{% static 'FirstApp/css/sb-admin-2.min.css' %}">
<link rel="stylesheet" href="{% static 'FirstApp/css/slider.css' %}"> <link rel="stylesheet" href="{% static 'FirstApp/css/slider.css' %}">
<link href="{% static 'FirstApp/vendor/fontawesome-free/css/all.min.css' %}" rel="stylesheet" type="text/css"> <link href="{% static 'FirstApp/vendor/fontawesome-free/css/all.min.css' %}" rel="stylesheet" type="text/css">
<link href="{% static 'FirstApp/css/snackbar.css' %}" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
<link rel="stylesheet" href="{% static 'FirstApp/css/all.min.css' %}"> <link rel="stylesheet" href="{% static 'FirstApp/css/all.min.css' %}">
......
...@@ -40,6 +40,10 @@ ...@@ -40,6 +40,10 @@
$(document).ready(function () { $(document).ready(function () {
let folder = ''; let folder = '';
$('#activity_loader').attr('hidden', false);
{#$('#emotion_loader').attr('hidden', false);#}
{#$('#gaze_loader').attr('hidden', false);#}
//select a particular subject //select a particular subject
//select a particular subject //select a particular subject
$('input[type=radio]').click(function () { $('input[type=radio]').click(function () {
...@@ -134,7 +138,6 @@ ...@@ -134,7 +138,6 @@
.catch((error) => alert('an error occurred: ' + error)); .catch((error) => alert('an error occurred: ' + error));
} }
}); });
}); });
...@@ -198,19 +201,19 @@ ...@@ -198,19 +201,19 @@
let classname = $('#step_1').attr('class'); let classname = $('#step_1').attr('class');
setTimeout(() => { setTimeout(() => {
$('#step_1').attr('class', class1) $('#step_1').attr('class', class1)
}, 2000); }, 2000);
setTimeout(() => { setTimeout(() => {
$('#step_2').attr('class', class1) $('#step_2').attr('class', class1)
}, 4000); }, 4000);
setTimeout(() => { setTimeout(() => {
$('#step_3').attr('class', class1) $('#step_3').attr('class', class1)
}, 6000); }, 6000);
setTimeout(() => { setTimeout(() => {
$('#step_4').attr('class', class1) $('#step_4').attr('class', class1)
}, 8000); }, 8000);
...@@ -228,7 +231,6 @@ ...@@ -228,7 +231,6 @@
global_video_name = video_name; global_video_name = video_name;
//perform activity recognition //perform activity recognition
fetch('http://127.0.0.1:8000/process-lecture-activity/?lecture_video_name=' + global_video_name + '&lecture_video_id=' + global_lecture_video_id) fetch('http://127.0.0.1:8000/process-lecture-activity/?lecture_video_name=' + global_video_name + '&lecture_video_id=' + global_lecture_video_id)
.then((res) => res.json()) .then((res) => res.json())
...@@ -251,7 +253,7 @@ ...@@ -251,7 +253,7 @@
//display the emotion loader //display the emotion loader
$('#emotion_loader').attr('hidden', false); $('#emotion_loader').attr('hidden', false);
//sending the request to process the lecture emotions //sending the request to process the lecture emotions
fetch('http://127.0.0.1:8000/process-lecture-emotion/?lecture_video_name=' + global_video_name + '&lecture_video_id=' + global_lecture_video_id) fetch('http://127.0.0.1:8000/process-lecture-emotion/?lecture_video_name=' + global_video_name + '&lecture_video_id=' + global_lecture_video_id)
.then((res) => res.json()) .then((res) => res.json())
.then((out) => handleEmotionResponse(out.response)) .then((out) => handleEmotionResponse(out.response))
...@@ -292,15 +294,68 @@ ...@@ -292,15 +294,68 @@
//hide the activity loader //hide the activity loader
$('#gaze_loader').hide(); $('#gaze_loader').hide();
alert('good');
} }
} }
//this is a test function (delete later)
let interval = setInterval(() => {
{#let url = 'http://127.0.0.1:8000/get-random_number';#}
let url = 'http://127.0.0.1:8000/check-availability';
fetch(url)
.then((res) => res.json())
.then((out) => displayProcess(out))
.catch((err) => alert('error: ' + err))
}, 10000);
//this function will handle the displaying loaders and status in the workflow
function displayProcess(response) {
//if the lecture activity has completed processing
if (response.isActivityExist) {
$('#step_1').attr("class", class1);
$('#activity_loader').hide();
$('#emotion_loader').attr('hidden', false);
}
//if the lecture emotion has completed processing
if (response.isEmotionExist) {
$('#step_2').attr("class", class1);
$('#emotion_loader').hide();
$('#gaze_loader').attr('hidden', false);
}
//if the lecture gaze has completed processing
if (response.isGazeExist) {
$('#step_3').attr("class", class1);
$('#gaze_loader').hide();
}
//if all the processes are completed
if (response.isActivityExist && response.isEmotionExist && response.isGazeExist) {
var x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 3000);
//clear the setInterval function
clearInterval(interval);
}
}
}); });
...@@ -326,6 +381,7 @@ ...@@ -326,6 +381,7 @@
<!-- Page Heading --> <!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4"> <div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Lecture Video Results</h1> <h1 class="h3 mb-0 text-gray-800">Lecture Video Results</h1>
<h2><span id="time_display"></span></h2>
</div> </div>
<!--first row --> <!--first row -->
...@@ -370,19 +426,23 @@ ...@@ -370,19 +426,23 @@
</tr> </tr>
</thead> </thead>
<tbody id="timetable_body"> <tbody id="timetable_body">
{% for lecture in due_lectures %} {% for lecture in due_lectures %}
<tr> <tr>
<td class="font-weight-bolder">{{ lecture.date }}</td> <td class="font-weight-bolder">{{ lecture.date }}</td>
{# <td>{{ lecture.subject }}</td>#} {# <td>{{ lecture.subject }}</td>#}
<td class="font-weight-bolder">{{ lecture.subject_name }}</td> <td class="font-weight-bolder">{{ lecture.subject_name }}</td>
<td class="font-weight-bolder">{{ lecture.start_time }}</td> <td class="font-weight-bolder">{{ lecture.start_time }}</td>
<td class="font-weight-bolder">{{ lecture.end_time }}</td> <td class="font-weight-bolder">{{ lecture.end_time }}</td>
<td> <td>
<button type="button" class="btn btn-success batch_process" data-video-id="{{ lecture.video_id }}" data-video-name="{{ lecture.video_name }}" id="{{ lecture.subject }}">Process</button> <button type="button" class="btn btn-success batch_process"
{# <span class="font-italic font-weight-bolder text-success">Processing</span>#} data-video-id="{{ lecture.video_id }}"
</td> data-video-name="{{ lecture.video_name }}"
</tr> id="{{ lecture.subject }}">Process
{% endfor %} </button>
{# <span class="font-italic font-weight-bolder text-success">Processing</span>#}
</td>
</tr>
{% endfor %}
</tbody> </tbody>
</table> </table>
...@@ -417,27 +477,29 @@ ...@@ -417,27 +477,29 @@
<div class="progress-bar"></div> <div class="progress-bar"></div>
</div> </div>
<a class="smpl-step-icon text-center"><i class="fa fa-chart-line" <a class="smpl-step-icon text-center"><i class="fa fa-chart-line"
style="font-size: 40px; padding-top: 10px; color: white"></i></a> style="font-size: 40px; padding-top: 10px; color: white"></i></a>
<div class="smpl-step-info text-center"> <div class="smpl-step-info text-center">
<span class="font-italic font-weight-bolder">Perform Activity Recognition</span> <span class="font-italic font-weight-bolder">Perform Activity Recognition</span>
<br /> <br/>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="Loader" class="mt-2" id="activity_loader" hidden> <img src="{% static 'FirstApp/images/ajax-loader.gif' %}"
alt="Loader" class="mt-2" id="activity_loader" hidden>
</div> </div>
</div> </div>
<!-- end of step 1 --> <!-- end of step 1 -->
<!-- step 2 --> <!-- step 2 -->
<div class="col-4 smpl-step-step disabled" id="step_2"> <div class="col-4 smpl-step-step disabled" id="step_2">
<div class="text-center smpl-step-num font-weight-bolder">Step 3</div> <div class="text-center smpl-step-num font-weight-bolder">Step 2</div>
<div class="progress"> <div class="progress">
<div class="progress-bar"></div> <div class="progress-bar"></div>
</div> </div>
<a class="smpl-step-icon text-center"><i class="fa fa-user" <a class="smpl-step-icon text-center"><i class="fa fa-user"
style="font-size: 50px; padding-top: 10px; color: white"></i></a> style="font-size: 50px; padding-top: 10px; color: white"></i></a>
<div class="smpl-step-info text-center"> <div class="smpl-step-info text-center">
<span class="font-italic font-weight-bolder">Study Student Emotions</span> <span class="font-italic font-weight-bolder">Study Student Emotions</span>
<br /> <br/>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="Loader" class="mt-2" id="emotion_loader" hidden> <img src="{% static 'FirstApp/images/ajax-loader.gif' %}"
alt="Loader" class="mt-2" id="emotion_loader" hidden>
</div> </div>
</div> </div>
<!-- end of step 2 --> <!-- end of step 2 -->
...@@ -454,18 +516,18 @@ ...@@ -454,18 +516,18 @@
</a> </a>
<div class="smpl-step-info text-center"> <div class="smpl-step-info text-center">
<span class="font-italic font-weight-bolder">See students' Gazes</span> <span class="font-italic font-weight-bolder">See students' Gazes</span>
<br /> <br/>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="Loader" class="mt-2" id="gaze_loader" hidden> <img src="{% static 'FirstApp/images/ajax-loader.gif' %}"
alt="Loader" class="mt-2" id="gaze_loader" hidden>
</div> </div>
</div> </div>
<!-- end of step 3 --> <!-- end of step 3 -->
</div> </div>
<!-- end of progress row -->
{# <!-- simulation button row -->#}
{# <div class="row">#}
{# <button type="button" class="btn btn-outline-danger" id="simulate_process">Simulate</button>#}
{# </div>#}
</div> </div>
<!-- end of container --> <!-- end of container -->
...@@ -478,6 +540,10 @@ ...@@ -478,6 +540,10 @@
</div> </div>
<!-- end of progress row --> <!-- end of progress row -->
<!-- snackbar -->
<div id="snackbar">The lecture is completely processed..</div>
<!-- end of snackbar -->
</div> </div>
{% endblock %} {% endblock %}
<!-- End of container-fluid --> <!-- End of container-fluid -->
......
...@@ -173,6 +173,19 @@ urlpatterns = [ ...@@ -173,6 +173,19 @@ urlpatterns = [
url(r'^get-lecture-recorded-video-name/$', api.GetLecturerRecordedVideo.as_view()), url(r'^get-lecture-recorded-video-name/$', api.GetLecturerRecordedVideo.as_view()),
##### BATCH PROCESS #####
# perform batch process for student behavior
url(r'^student-behavior-batch-process/$', api.BatchProcess.as_view()),
# check availability for student behavior components
url(r'^check-availability/$', api.CheckStudentBehaviorAvailability.as_view()),
# perform random task (delete later)
url(r'^get-random_number/$', api.TestRandom.as_view()),
# routers # routers
# path('', include(router.urls)), # path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')) path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
......
...@@ -15,20 +15,18 @@ import os ...@@ -15,20 +15,18 @@ import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
# SECRET_KEY = 'typgn#m(t#byxnp#ut@^gfqyh*1doa28gkqu(ap*k4s5!q&oyo' #original one # SECRET_KEY = 'typgn#m(t#byxnp#ut@^gfqyh*1doa28gkqu(ap*k4s5!q&oyo' #original one
SECRET_KEY = '!3-gwi-1#5-4**85xb#z(t-8#ayc#*gguw4v4+fkax4037sp=)' # exported one SECRET_KEY = '!3-gwi-1#5-4**85xb#z(t-8#ayc#*gguw4v4+fkax4037sp=)' # exported one
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
ALLOWED_HOSTS = [] ALLOWED_HOSTS = []
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
...@@ -36,6 +34,7 @@ INSTALLED_APPS = [ ...@@ -36,6 +34,7 @@ INSTALLED_APPS = [
'AttendanceApp.apps.AttendanceappConfig', 'AttendanceApp.apps.AttendanceappConfig',
'MonitorLecturerApp.apps.MonitorlecturerappConfig', 'MonitorLecturerApp.apps.MonitorlecturerappConfig',
'LectureSummarizingApp.apps.LectureSummarizingAppConfig', 'LectureSummarizingApp.apps.LectureSummarizingAppConfig',
'corsheaders',
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
...@@ -48,6 +47,7 @@ INSTALLED_APPS = [ ...@@ -48,6 +47,7 @@ INSTALLED_APPS = [
] ]
MIDDLEWARE = [ MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
...@@ -59,6 +59,9 @@ MIDDLEWARE = [ ...@@ -59,6 +59,9 @@ MIDDLEWARE = [
ROOT_URLCONF = 'integrated_slpes.urls' ROOT_URLCONF = 'integrated_slpes.urls'
# adding the CORS attributes
CORS_ALLOW_ALL_ORIGINS = True
TEMPLATES = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
...@@ -78,7 +81,6 @@ TEMPLATES = [ ...@@ -78,7 +81,6 @@ TEMPLATES = [
WSGI_APPLICATION = 'integrated_slpes.wsgi.application' WSGI_APPLICATION = 'integrated_slpes.wsgi.application'
# Database # Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases # https://docs.djangoproject.com/en/2.2/ref/settings/#databases
...@@ -93,7 +95,6 @@ DATABASES = { ...@@ -93,7 +95,6 @@ DATABASES = {
} }
} }
# Password validation # Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
...@@ -112,7 +113,6 @@ AUTH_PASSWORD_VALIDATORS = [ ...@@ -112,7 +113,6 @@ AUTH_PASSWORD_VALIDATORS = [
}, },
] ]
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/ # https://docs.djangoproject.com/en/2.2/topics/i18n/
...@@ -126,7 +126,6 @@ USE_L10N = True ...@@ -126,7 +126,6 @@ USE_L10N = True
USE_TZ = True USE_TZ = True
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/ # https://docs.djangoproject.com/en/2.2/howto/static-files/
...@@ -137,7 +136,6 @@ STATICFILES_DIRS = [ ...@@ -137,7 +136,6 @@ STATICFILES_DIRS = [
] ]
STATIC_ROOT = os.path.join(BASE_DIR, 'assets') STATIC_ROOT = os.path.join(BASE_DIR, 'assets')
# media files # media files
MEDIA_URL = '/media/' MEDIA_URL = '/media/'
...@@ -145,7 +143,9 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media') ...@@ -145,7 +143,9 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# REST FRAMEWORK # REST FRAMEWORK
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [ # 'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated', # 'rest_framework.permissions.IsAuthenticated',
] # ]
} 'DEFAULT_AUTHENTICATION_CLASSES': [],
\ No newline at end of file 'DEFAULT_PERMISSION_CLASSES': []
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment