Commit 0e91389b authored by I.K Seneviratne's avatar I.K Seneviratne

Initial commit to the monitoring_student_behavior branch

parent 2a3db16a
......@@ -128,7 +128,7 @@ class LectureActivity(models.Model):
# Lecture emotion report
class LectureEmotionReport(models.Model):
lecture_emotion_id = models.CharField(max_length=10)
lecture_video_id = models.ForeignKey(LectureVideo, on_delete=models.CASCADE)
lecture_video_id = models.ForeignKey(LectureVideo, on_delete=models.CASCADE, default=0)
happy_perct = models.DecimalField(default=0.0, max_digits=3, decimal_places=1)
sad_perct = models.DecimalField(default=0.0, max_digits=3, decimal_places=1)
angry_perct = models.DecimalField(default=0.0, max_digits=3, decimal_places=1)
......@@ -143,6 +143,14 @@ class LectureEmotionReport(models.Model):
# POSE section
# lecture pose estimation
class LecturePoseEstimation(models.Model):
lecture_pose_id = models.CharField(max_length=10)
lecture_video_id = models.ForeignKey(LectureVideo, on_delete=models.CASCADE)
\ No newline at end of file
class LectureGazeEstimation(models.Model):
lecture_gaze_id = models.CharField(max_length=10)
lecture_video_id = models.ForeignKey(LectureVideo, on_delete=models.CASCADE)
looking_up_and_right_perct = models.DecimalField(default=0.0, max_digits=3, decimal_places=1)
looking_up_and_left_perct = models.DecimalField(default=0.0, max_digits=3, decimal_places=1)
looking_down_and_right_perct = models.DecimalField(default=0.0, max_digits=3, decimal_places=1)
looking_down_and_left_perct = models.DecimalField(default=0.0, max_digits=3, decimal_places=1)
looking_front_perct = models.DecimalField(default=0.0, max_digits=3, decimal_places=1)
def __str__(self):
return self.lecture_gaze_id
\ No newline at end of file
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from . MongoModels import *
from .MongoModels import *
from rest_framework.views import *
from . ImageOperations import saveImage
from . logic import head_pose_estimation
from . logic import video_extraction
from . logic import activity_recognition as ar
from . logic import posenet_calculation as pc
from .ImageOperations import saveImage
from .logic import head_pose_estimation
from .logic import video_extraction
from .logic import activity_recognition as ar
from .logic import posenet_calculation as pc
from . import emotion_detector as ed
from . logic import id_generator as ig
from . models import Teachers, Video, VideoMeta, RegisterUser
from . MongoModels import *
from . serializers import *
from .logic import id_generator as ig
from .logic import pdf_file_generator as pdf
from .logic import head_gaze_estimation as hge
from .models import Teachers, Video, VideoMeta, RegisterUser
from .MongoModels import *
from .serializers import *
import datetime
# to create images
class ImageViewSet(APIView):
......@@ -41,6 +46,7 @@ class VideoExtractionViewSet(APIView):
response = video_extraction.VideoExtractor(request.data)
return Response({"response": response})
# lecture emotions view set
class LectureEmotionViewSet(APIView):
......@@ -75,6 +81,7 @@ class LectureViewSet(APIView):
).save()
return Response({"response": request})
# API for Faculties
class FacultyViewSet(APIView):
......@@ -90,6 +97,7 @@ class FacultyViewSet(APIView):
).save()
return Response(status=201, data={"response": "successfully added"})
# API for subjects
class SubjectViewSet(APIView):
......@@ -99,7 +107,6 @@ class SubjectViewSet(APIView):
return Response(serializer.data)
def post(self, request):
serializer = SubjectSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
serializer.create(validated_data=request.data)
......@@ -118,7 +125,6 @@ class LecturerViewSet(APIView):
return Response(serializer.data)
def post(self, request):
serializer = LecturerSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
serializer.create(validated_data=request.data)
......@@ -137,7 +143,6 @@ class LecturerSubjectViewSet(APIView):
return Response(serializer.data)
def post(self, request):
serializer = LecturerSubjectSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
serializer.create(validated_data=request.data)
......@@ -156,7 +161,6 @@ class FacultyTimetableViewSet(APIView):
return Response(serializer.data)
def post(self, request):
serializer = FacultyTimetableSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
serializer.create(validated_data=request.data)
......@@ -175,7 +179,6 @@ class LectureVideoViewSet(APIView):
return Response(serializer.data)
def post(self, request):
serializer = LectureVideoSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
serializer.create(validated_data=request.data)
......@@ -215,7 +218,6 @@ class LectureActivityViewSet(APIView):
return Response(serializer.data)
def post(self, request):
serializer = LectureActivitySerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
serializer.create(validated_data=request.data)
......@@ -337,6 +339,38 @@ class GetLectureActivityRecognitionsForFrames(APIView):
})
# API to create reports for Activity
class GenerateActivityReport(APIView):
def get(self, request):
subject = request.query_params.get('subject')
lecturer = int(request.query_params.get('lecturer'))
date = request.query_params.get('date')
# retrieve the subject name
subject_query = Subject.objects.filter(subject_code=subject)
subject_serializer = SubjectSerializer(subject_query, many=True)
subject_name = subject_serializer.data[0]['name']
# retrieve the lecturer name
# lecturer_query = Lecturer.objects.filter(lecturer_id=lecturer)
lecturer_query = Lecturer.objects.filter(id=lecturer)
lecturer_serializer = LecturerSerializer(lecturer_query, many=True)
lecturer_lname = lecturer_serializer.data[0]['lname']
lecturer_fname = lecturer_serializer.data[0]['fname']
lecturer_fullname = lecturer_fname + " " + lecturer_lname
# set the dictionary
object = {}
object['subject_name'] = subject_name
object['lecturer_name'] = lecturer_fullname
object['date'] = date
pdf.generate_pdf_file(object)
return Response({
"response": "success"
})
###### EMOTIONS section #####
......@@ -358,6 +392,7 @@ class GetLectureEmotionAvailability(APIView):
"isActivityFound": isActivityFound
})
# to process lecture emotions for a lecture video
class LectureEmotionProcess(APIView):
......@@ -455,11 +490,12 @@ class GetLectureVideoForPose(APIView):
def get(self, request):
lecturer = request.query_params.get('lecturer')
date = request.query_params.get('date')
index = int(request.query_params.get('index'))
lecturer_video = LectureVideo.objects.filter(lecturer_id=lecturer, date=date)
serializer = LectureVideoSerializer(lecturer_video, many=True)
return Response({
"response": serializer.data
"response": serializer.data[index]
})
......@@ -514,3 +550,168 @@ class ProcessIndividualStudentPoseEstimation(APIView):
})
##### GAZE ESTIMATION SECTION #####
class GetLectureGazeEstimationAvailaibility(APIView):
def get(self, request):
lecturer = request.query_params.get('lecturer')
date = request.query_params.get('date')
index = int(request.query_params.get('index'))
lecturer_video = LectureVideo.objects.filter(lecturer_id=lecturer, date=date)
serializer = LectureVideoSerializer(lecturer_video, many=True)
lecture_video_id = serializer.data[index]['lecture_video_id']
gaze_estimation = LectureGazeEstimation.objects.filter(lecture_video_id__lecture_video_id=lecture_video_id)
isGazeEstimationFound = (len(gaze_estimation) > 0)
return Response({
"response": serializer.data[index],
"isGazeEstimationFound": isGazeEstimationFound
})
# the API to process lecture gaze estimation
class ProcessLectureGazeEstimation(APIView):
def get(self, request):
video_name = request.query_params.get('lecture_video_name')
video_id = request.query_params.get('lecture_video_id')
percentages = hge.process_gaze_estimation(video_name)
self.estimate_gaze(video_id, percentages)
return Response({"response": True})
def post(self, request):
pass
def estimate_gaze(self, lec_video_id, percentages):
lec_video = LectureVideo.objects.get(lecture_video_id=lec_video_id)
last_lec_gaze = LectureGazeEstimation.objects.order_by('lecture_gaze_id').last()
lec_video_serializer = LectureVideoSerializer(lec_video, many=True)
new_lecture_gaze_id = "LG000001" if (last_lec_gaze is None) else ig.generate_new_id(
last_lec_gaze.lecture_gaze_id)
# creating a new lecture gaze estimation
LectureGazeEstimation(
lecture_gaze_id=new_lecture_gaze_id,
lecture_video_id=lec_video,
looking_up_and_right_perct=percentages['head_up_right_perct'],
looking_up_and_left_perct=percentages['head_up_left_perct'],
looking_down_and_right_perct=percentages['head_down_right_perct'],
looking_down_and_left_perct=percentages['head_down_left_perct'],
looking_front_perct=percentages['head_front_perct']
).save()
# the API to retrieve lecture gaze estimation
class GetLectureGazeEstimationViewSet(APIView):
def get(self, request):
lecture_video_id = request.query_params.get('lecture_video_id')
lecture_video_name = request.query_params.get('lecture_video_name')
# retrieve the extracted frames
extracted = hge.getExtractedFrames(lecture_video_name)
lecture_gaze_estimations = LectureGazeEstimation.objects.filter(
lecture_video_id__lecture_video_id=lecture_video_id)
serializer = LectureGazeEstimationSerializer(lecture_gaze_estimations, many=True)
return Response({
"response": serializer.data,
"extracted": extracted
})
# the API to retrieve Gaze estimation for frames
class GetLectureGazeEstimationForFrames(APIView):
def get(self, request):
video_name = request.query_params.get('video_name')
frame_detections, frame_rate = hge.get_lecture_gaze_esrimation_for_frames(video_name)
return Response({
"response": frame_detections,
"frame_rate": frame_rate
})
##### VIDEO RESULTS SECTION #####
# this API find the lectures which are yet to be processed
class LectureProcessAvailability(APIView):
def get(self, request):
lecturer = request.query_params.get('lecturer')
lecturer_videos = LectureVideo.objects.filter(lecturer_id=lecturer)
serializer = LectureVideoSerializer(lecturer_videos, many=True)
data = serializer.data
for video in data:
print('video name: ', video['video_name'])
return Response({
"response": "hello"
})
##### VIEW STUDENT BEHAVIOR SUMMARY SECTION #####
# this API will retrieve student behavior summary for specified time period
class GetStudentBehaviorSummaryForPeriod(APIView):
def get(self, request):
option = request.query_params.get('option')
lecturer = request.query_params.get('lecturer')
int_lecturer = int(lecturer)
int_option = int(option)
# int_option = 150
isRecordFound = False
activity_percentages = {}
emotion_percentages = {}
individual_lec_activties = []
individual_lec_emotions = []
activity_labels = []
emotion_labels = []
current_date = datetime.datetime.now().date()
option_date = datetime.timedelta(days=int_option)
previous_date = current_date - option_date
# retrieving lecture activities
lec_activity = LectureActivity.objects.filter(
lecture_video_id__date__gte=previous_date,
lecture_video_id__date__lte=current_date,
lecture_video_id__lecturer=lecturer
)
if len(lec_activity) > 0:
isRecordFound = True
activity_serializer = LectureActivitySerializer(lec_activity, many=True)
activity_data = activity_serializer.data
activity_percentages, individual_lec_activties, activity_labels = ar.get_student_activity_summary_for_period(activity_data)
# retrieving lecture emotions
lec_emotion = LectureEmotionReport.objects.filter(
lecture_video_id__date__gte=previous_date,
lecture_video_id__date__lte=current_date,
lecture_video_id__lecturer=lecturer
)
if len(lec_emotion) > 0:
emotion_serializer = LectureEmotionSerializer(lec_emotion, many=True)
emotion_data = emotion_serializer.data
emotion_percentages, individual_lec_emotions, emotion_labels = ed.get_student_emotion_summary_for_period(emotion_data)
return Response({
"activity_response": activity_percentages,
"emotion_response": emotion_percentages,
"individual_activities": individual_lec_activties,
"individual_emotions": individual_lec_emotions,
"activity_labels": activity_labels,
"emotion_labels": emotion_labels,
"isRecordFound": isRecordFound
})
......@@ -66,7 +66,6 @@ def detect_emotion(video):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_classifier.detectMultiScale(gray,1.3,5)
print('number of faces: ', len(faces))
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)
......@@ -104,13 +103,9 @@ def detect_emotion(video):
elif (label == 'Sad'):
count_sad += 1
# path = os.path.join(BASE_DIR, 'static\\images\\Sad')
# cv2.imwrite(os.path.join(path, 'Sad-{0}.jpg'.format(count)), frame)
elif (label == 'Surprise'):
count_surprise += 1
# path = os.path.join(BASE_DIR, 'static\\images\\Surprise')
# cv2.imwrite(os.path.join(path, 'Surprise-{0}.jpg'.format(count)), frame)
label_position = (x, y)
# cv2.putText(frame, label, label_position, cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 0), 3)
......@@ -118,13 +113,9 @@ def detect_emotion(video):
else:
cv2.putText(frame, 'No Face Found', (20, 60), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 0), 3)
# cv2.imshow('Emotion Detector',frame)
count_frames += 1
# if cv2.waitKey(1) & 0xFF == ord('q'):
# break
# setting up the counted values
meta_data.frame_count = count_frames
meta_data.happy_count = count_happy
meta_data.sad_count = count_sad
......@@ -328,11 +319,11 @@ def get_frame_emotion_recognition(video_name):
# calculating the percentages for the frame
happy_perct = float(happy_count / detection_count) * 100
sad_perct = float(sad_count / detection_count) * 100
angry_perct = float(angry_count / detection_count) * 100
neutral_perct = float(neutral_count / detection_count) * 100
surprise_perct = float(surprise_count / detection_count) * 100
happy_perct = float(happy_count / detection_count) * 100 if detection_count > 0 else 0
sad_perct = float(sad_count / detection_count) * 100 if detection_count > 0 else 0
angry_perct = float(angry_count / detection_count) * 100 if detection_count > 0 else 0
neutral_perct = float(neutral_count / detection_count) * 100 if detection_count > 0 else 0
surprise_perct = float(surprise_count / detection_count) * 100 if detection_count > 0 else 0
# this dictionary will be returned
frame_details['happy_perct'] = happy_perct
......@@ -348,4 +339,63 @@ def get_frame_emotion_recognition(video_name):
sorted_activity_frame_recognitions = cs.custom_object_sorter(frame_emotion_recognitions)
# return the detected frame percentages
return sorted_activity_frame_recognitions
\ No newline at end of file
return sorted_activity_frame_recognitions
# this method will retrieve student activity summary for given time period
def get_student_emotion_summary_for_period(emotions):
# declare variables to add percentage values
happy_perct_combined = 0.0
sad_perct_combined = 0.0
angry_perct_combined = 0.0
disgust_perct_combined = 0.0
surprise_perct_combined = 0.0
neutral_perct_combined = 0.0
# get the number of activties to calculate average
no_of_emotions = len(emotions)
individual_lec_emotions = []
emotion_labels = ["happy_perct", "sad_perct", "angry_perct", "disgust_perct", "surprise_perct", "neutral_perct"]
# iterate through the activities
for emotion in emotions:
individual_emotion = {}
individual_emotion["happy_perct"] = float(emotion['happy_perct'])
individual_emotion["sad_perct"] = float(emotion['sad_perct'])
individual_emotion["angry_perct"] = float(emotion['angry_perct'])
individual_emotion["disgust_perct"] = float(emotion['disgust_perct'])
individual_emotion["surprise_perct"] = float(emotion['surprise_perct'])
individual_emotion["neutral_perct"] = float(emotion['neutral_perct'])
happy_perct_combined += float(emotion['happy_perct'])
sad_perct_combined += float(emotion['sad_perct'])
angry_perct_combined += float(emotion['angry_perct'])
disgust_perct_combined += float(emotion['disgust_perct'])
surprise_perct_combined += float(emotion['surprise_perct'])
neutral_perct_combined += float(emotion['neutral_perct'])
# append to the list
individual_lec_emotions.append(individual_emotion)
# calculate the average percentages
happy_average_perct = round((happy_perct_combined / no_of_emotions), 1)
sad_average_perct = round((sad_perct_combined / no_of_emotions), 1)
angry_average_perct = round((angry_perct_combined / no_of_emotions), 1)
disgust_average_perct = round((disgust_perct_combined / no_of_emotions), 1)
surprise_average_perct = round((surprise_perct_combined / no_of_emotions), 1)
neutral_average_perct = round((neutral_perct_combined / no_of_emotions), 1)
percentages = {}
percentages["happy_perct"] = happy_average_perct
percentages["sad_perct"] = sad_average_perct
percentages["angry_perct"] = angry_average_perct
percentages["disgust_perct"] = disgust_average_perct
percentages["surprise_perct"] = surprise_average_perct
percentages["neutral_perct"] = neutral_average_perct
return percentages, individual_lec_emotions, emotion_labels
\ No newline at end of file
......@@ -51,7 +51,7 @@ def activity_recognition(video_path):
note_taking_count = 0
listening_count = 0
# video activity didrectory
# video activity directory
VIDEO_ACTIVITY_DIR = os.path.join(ACTIVITY_DIR, video_path)
# creating the directory for the video
......@@ -75,7 +75,6 @@ def activity_recognition(video_path):
os.mkdir(FRAME_DIR)
image = cv2.resize(image, size)
# image = ImageOps.fit(image, size, Image.ANTIALIAS)
detections = person_detection(image, net)
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
......@@ -130,10 +129,10 @@ def activity_recognition(video_path):
p.write("yes")
# calculating the percentages for each label
phone_perct = float(phone_checking_count / total_detections) * 100
talking_perct = float(talking_count / total_detections) * 100
note_perct = float(note_taking_count / total_detections) * 100
listening_perct = float(listening_count / total_detections) * 100
phone_perct = float(phone_checking_count / total_detections) * 100 if total_detections > 0 else 0
talking_perct = float(talking_count / total_detections) * 100 if total_detections > 0 else 0
note_perct = float(note_taking_count / total_detections) * 100 if total_detections > 0 else 0
listening_perct = float(listening_count / total_detections) * 100 if total_detections > 0 else 0
# assigning the percentages to the dictionary
percentages["phone_perct"] = phone_perct
......@@ -571,4 +570,48 @@ def get_individual_student_evaluation(video_name, student_name):
percentages['writing_perct'] = writing_perct
percentages['listening_perct'] = listening_perct
return percentages
\ No newline at end of file
return percentages
# this method will retrieve student activity summary for given time period
def get_student_activity_summary_for_period(activities):
# declare variables to add percentage values
phone_checking_perct_combined = 0.0
listening_perct_combined = 0.0
note_taking_perct_combined = 0.0
# get the number of activties to calculate average
no_of_activities = len(activities)
individual_lec_activities = []
activity_labels = ["phone_perct", "listening_perct", "writing_perct"]
# iterate through the activities
for activity in activities:
individual_activity = {}
individual_activity["phone_perct"] = float(activity['phone_perct'])
individual_activity["listening_perct"] = float(activity['listening_perct'])
individual_activity["writing_perct"] = float(activity['writing_perct'])
phone_checking_perct_combined += float(activity['phone_perct'])
listening_perct_combined += float(activity['listening_perct'])
note_taking_perct_combined += float(activity['writing_perct'])
# append to the list
individual_lec_activities.append(individual_activity)
# calculate the average percentages
phone_checking_average_perct = round((phone_checking_perct_combined / no_of_activities), 1)
listening_average_perct = round((listening_perct_combined / no_of_activities), 1)
note_taking_average_perct = round((note_taking_perct_combined / no_of_activities), 1)
percentages = {}
percentages["phone_perct"] = phone_checking_average_perct
percentages["listening_perct"] = listening_average_perct
percentages["writing_perct"] = note_taking_average_perct
return percentages, individual_lec_activities, activity_labels
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
Created on Wed Jul 29 17:52:00 2020
@author: hp
"""
import cv2
import numpy as np
import os
def get_face_detector(modelFile = "models/res10_300x300_ssd_iter_140000.caffemodel",
configFile = "models/deploy.prototxt"):
"""
Get the face detection caffe model of OpenCV's DNN module
Parameters
----------
modelFile : string, optional
Path to model file. The default is "models/res10_300x300_ssd_iter_140000.caffemodel".
configFile : string, optional
Path to config file. The default is "models/deploy.prototxt".
Returns
-------
model : dnn_Net
"""
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
CLASSIFIER_DIR = os.path.join(BASE_DIR, "FirstApp\\classifiers")
modelFile = os.path.join(CLASSIFIER_DIR, "res10_300x300_ssd_iter_140000.caffemodel")
configFile = os.path.join(CLASSIFIER_DIR, "deploy.prototxt")
model = cv2.dnn.readNetFromCaffe(configFile, modelFile)
return model
def find_faces(img, model):
"""
Find the faces in an image
Parameters
----------
img : np.uint8
Image to find faces from
model : dnn_Net
Face detection model
Returns
-------
faces : list
List of coordinates of the faces detected in the image
"""
h, w = img.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(img, (300, 300)), 1.0,
(300, 300), (104.0, 177.0, 123.0))
model.setInput(blob)
res = model.forward()
faces = []
for i in range(res.shape[2]):
confidence = res[0, 0, i, 2]
if confidence > 0.5:
box = res[0, 0, i, 3:7] * np.array([w, h, w, h])
(x, y, x1, y1) = box.astype("int")
faces.append([x, y, x1, y1])
return faces
def draw_faces(img, faces):
"""
Draw faces on image
Parameters
----------
img : np.uint8
Image to draw faces on
faces : List of face coordinates
Coordinates of faces to draw
Returns
-------
None.
"""
for x, y, x1, y1 in faces:
cv2.rectangle(img, (x, y), (x1, y1), (0, 0, 255), 3)
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
Created on Wed Jul 29 19:47:08 2020
@author: hp
"""
import cv2
import numpy as np
import tensorflow as tf
from tensorflow import keras
import os
def get_landmark_model():
"""
Get the facial landmark model.
Original repository: https://github.com/yinguobing/cnn-facial-landmark
Parameters
----------
saved_model : string, optional
Path to facial landmarks model. The default is 'models/pose_model'.
Returns
-------
model : Tensorflow model
Facial landmarks model
"""
# define the location of the pose model
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
saved_model = os.path.join(BASE_DIR, "FirstApp\\classifiers\\pose_model")
model = keras.models.load_model(saved_model)
return model
def get_square_box(box):
"""Get a square box out of the given box, by expanding it."""
left_x = box[0]
top_y = box[1]
right_x = box[2]
bottom_y = box[3]
box_width = right_x - left_x
box_height = bottom_y - top_y
# Check if box is already a square. If not, make it a square.
diff = box_height - box_width
delta = int(abs(diff) / 2)
if diff == 0: # Already a square.
return box
elif diff > 0: # Height > width, a slim box.
left_x -= delta
right_x += delta
if diff % 2 == 1:
right_x += 1
else: # Width > height, a short box.
top_y -= delta
bottom_y += delta
if diff % 2 == 1:
bottom_y += 1
# Make sure box is always square.
assert ((right_x - left_x) == (bottom_y - top_y)), 'Box is not square.'
return [left_x, top_y, right_x, bottom_y]
def move_box(box, offset):
"""Move the box to direction specified by vector offset"""
left_x = box[0] + offset[0]
top_y = box[1] + offset[1]
right_x = box[2] + offset[0]
bottom_y = box[3] + offset[1]
return [left_x, top_y, right_x, bottom_y]
def detect_marks(img, model, face):
"""
Find the facial landmarks in an image from the faces
Parameters
----------
img : np.uint8
The image in which landmarks are to be found
model : Tensorflow model
Loaded facial landmark model
face : list
Face coordinates (x, y, x1, y1) in which the landmarks are to be found
Returns
-------
marks : numpy array
facial landmark points
"""
offset_y = int(abs((face[3] - face[1]) * 0.1))
box_moved = move_box(face, [0, offset_y])
facebox = get_square_box(box_moved)
# reassigning the facebox values
facebox[0] = facebox[0] if facebox[0] > 0 else 0
facebox[1] = facebox[1] if facebox[1] > 0 else 0
facebox[2] = facebox[2] if facebox[2] > 0 else 0
facebox[3] = facebox[3] if facebox[3] > 0 else 0
# draw a bounding box
cv2.rectangle(img, (facebox[0], facebox[1]), (facebox[2], facebox[3]), (0, 255, 0), 2)
face_img = img[facebox[1]: facebox[3],
facebox[0]: facebox[2]]
marks = np.zeros((68, 2))
# if the list length is more than 0
if len(face_img) > 0:
face_img = cv2.resize(face_img, (128, 128))
face_img = cv2.cvtColor(face_img, cv2.COLOR_BGR2RGB)
# # Actual detection.
predictions = model.signatures["predict"](
tf.constant([face_img], dtype=tf.uint8))
# Convert predictions to landmarks.
marks = np.array(predictions['output']).flatten()[:136]
marks = np.reshape(marks, (-1, 2))
marks *= (facebox[2] - facebox[0])
marks[:, 0] += facebox[0]
marks[:, 1] += facebox[1]
marks = marks.astype(np.uint)
# return marks
# return detected facial marks and face coordinates
return marks, facebox
def draw_marks(image, marks, color=(0, 255, 0)):
"""
Draw the facial landmarks on an image
Parameters
----------
image : np.uint8
Image on which landmarks are to be drawn.
marks : list or numpy array
Facial landmark points
color : tuple, optional
Color to which landmarks are to be drawn with. The default is (0, 255, 0).
Returns
-------
None.
"""
for mark in marks:
cv2.circle(image, (mark[0], mark[1]), 2, color, -1, cv2.LINE_AA)
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
Created on Fri Jul 31 03:00:36 2020
@author: hp
"""
from decimal import Decimal
from . custom_sorter import *
import cv2
import numpy as np
import math
from . face_detector import get_face_detector, find_faces
from . face_landmarks import get_landmark_model, detect_marks
import os
import shutil
import math
def get_2d_points(img, rotation_vector, translation_vector, camera_matrix, val):
"""Return the 3D points present as 2D for making annotation box"""
point_3d = []
dist_coeffs = np.zeros((4, 1))
rear_size = val[0]
rear_depth = val[1]
point_3d.append((-rear_size, -rear_size, rear_depth))
point_3d.append((-rear_size, rear_size, rear_depth))
point_3d.append((rear_size, rear_size, rear_depth))
point_3d.append((rear_size, -rear_size, rear_depth))
point_3d.append((-rear_size, -rear_size, rear_depth))
front_size = val[2]
front_depth = val[3]
point_3d.append((-front_size, -front_size, front_depth))
point_3d.append((-front_size, front_size, front_depth))
point_3d.append((front_size, front_size, front_depth))
point_3d.append((front_size, -front_size, front_depth))
point_3d.append((-front_size, -front_size, front_depth))
point_3d = np.array(point_3d, dtype=np.float).reshape(-1, 3)
# Map to 2d img points
(point_2d, _) = cv2.projectPoints(point_3d,
rotation_vector,
translation_vector,
camera_matrix,
dist_coeffs)
point_2d = np.int32(point_2d.reshape(-1, 2))
return point_2d
def draw_annotation_box(img, rotation_vector, translation_vector, camera_matrix,
rear_size=300, rear_depth=0, front_size=500, front_depth=400,
color=(255, 255, 0), line_width=2):
"""
Draw a 3D anotation box on the face for head pose estimation
Parameters
----------
img : np.unit8
Original Image.
rotation_vector : Array of float64
Rotation Vector obtained from cv2.solvePnP
translation_vector : Array of float64
Translation Vector obtained from cv2.solvePnP
camera_matrix : Array of float64
The camera matrix
rear_size : int, optional
Size of rear box. The default is 300.
rear_depth : int, optional
The default is 0.
front_size : int, optional
Size of front box. The default is 500.
front_depth : int, optional
Front depth. The default is 400.
color : tuple, optional
The color with which to draw annotation box. The default is (255, 255, 0).
line_width : int, optional
line width of lines drawn. The default is 2.
Returns
-------
None.
"""
rear_size = 1
rear_depth = 0
front_size = img.shape[1]
front_depth = front_size * 2
val = [rear_size, rear_depth, front_size, front_depth]
point_2d = get_2d_points(img, rotation_vector, translation_vector, camera_matrix, val)
# # Draw all the lines
cv2.polylines(img, [point_2d], True, color, line_width, cv2.LINE_AA)
cv2.line(img, tuple(point_2d[1]), tuple(
point_2d[6]), color, line_width, cv2.LINE_AA)
cv2.line(img, tuple(point_2d[2]), tuple(
point_2d[7]), color, line_width, cv2.LINE_AA)
cv2.line(img, tuple(point_2d[3]), tuple(
point_2d[8]), color, line_width, cv2.LINE_AA)
def head_pose_points(img, rotation_vector, translation_vector, camera_matrix):
"""
Get the points to estimate head pose sideways
Parameters
----------
img : np.unit8
Original Image.
rotation_vector : Array of float64
Rotation Vector obtained from cv2.solvePnP
translation_vector : Array of float64
Translation Vector obtained from cv2.solvePnP
camera_matrix : Array of float64
The camera matrix
Returns
-------
(x, y) : tuple
Coordinates of line to estimate head pose
"""
rear_size = 1
rear_depth = 0
front_size = img.shape[1]
front_depth = front_size * 2
val = [rear_size, rear_depth, front_size, front_depth]
point_2d = get_2d_points(img, rotation_vector, translation_vector, camera_matrix, val)
y = (point_2d[5] + point_2d[8]) // 2
x = point_2d[2]
return (x, y)
# this method will perform gaze estimation for a lecture
def process_gaze_estimation(video_path):
# get the base directory
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
VIDEO_PATH = os.path.join(BASE_DIR, "assets\\FirstApp\\videos\\{}".format(video_path))
GAZE_DIR = os.path.join(BASE_DIR, "static\\FirstApp\\gaze")
# create a folder with the same name as the video
VIDEO_DIR = os.path.join(GAZE_DIR, video_path)
# define a dictionary to return the percentage values
percentages = {}
# checking whether the video directory exist
if os.path.isdir(VIDEO_DIR):
shutil.rmtree(VIDEO_DIR)
# create the new directory
os.mkdir(VIDEO_DIR)
# load the face detection model
face_model = get_face_detector()
# load the facial landamrk model
landmark_model = get_landmark_model()
cap = cv2.VideoCapture(VIDEO_PATH)
ret, img = cap.read()
size = img.shape
font = cv2.FONT_HERSHEY_SIMPLEX
# 3D model points.
model_points = np.array([
(0.0, 0.0, 0.0), # Nose tip
(0.0, -330.0, -65.0), # Chin
(-225.0, 170.0, -135.0), # Left eye left corner
(225.0, 170.0, -135.0), # Right eye right corne
(-150.0, -150.0, -125.0), # Left Mouth corner
(150.0, -150.0, -125.0) # Right mouth corner
])
# setting up the count variables
head_front_count = 0
head_up_right_count = 0
head_up_left_count = 0
head_down_right_count = 0
head_down_left_count = 0
# define a variable to count the frames
frame_count = 0
face_count = 0
# set a threshold angle
# THRESHOLD = 15
THRESHOLD = 22
# THRESHOLD = 30
# THRESHOLD = 45
# THRESHOLD = 48
# Camera internals
focal_length = size[1]
center = (size[1] / 2, size[0] / 2)
camera_matrix = np.array(
[[focal_length, 0, center[0]],
[0, focal_length, center[1]],
[0, 0, 1]], dtype="double"
)
# iterate the video frames
while True:
ret, img = cap.read()
if ret == True:
faces = find_faces(img, face_model)
# print('no of faces found: ', len(faces))
student_count = 0
# iterate through each detected face
for face in faces:
# declaring boolean variables
isLookingUp = False
isLookingDown = False
isLookingRight = False
isLookingLeft = False
isLookingFront = False
# deriving the student name to display in the image
student_name = 'student-{}'.format(student_count)
# retrieving the facial landmarks and face bounding box coordinates
marks, facebox = detect_marks(img, landmark_model, face)
# mark_detector.draw_marks(img, marks, color=(0, 255, 0))
image_points = np.array([
marks[30], # Nose tip
marks[8], # Chin
marks[36], # Left eye left corner
marks[45], # Right eye right corne
marks[48], # Left Mouth corner
marks[54] # Right mouth corner
], dtype="double")
dist_coeffs = np.zeros((4, 1)) # Assuming no lens distortion
(success, rotation_vector, translation_vector) = cv2.solvePnP(model_points, image_points, camera_matrix,
dist_coeffs, flags=cv2.SOLVEPNP_UPNP)
# Project a 3D point (0, 0, 1000.0) onto the image plane.
# We use this to draw a line sticking out of the nose
(nose_end_point2D, jacobian) = cv2.projectPoints(np.array([(0.0, 0.0, 1000.0)]), rotation_vector,
translation_vector, camera_matrix, dist_coeffs)
p1 = (int(image_points[0][0]), int(image_points[0][1]))
p2 = (int(nose_end_point2D[0][0][0]), int(nose_end_point2D[0][0][1]))
x1, x2 = head_pose_points(img, rotation_vector, translation_vector, camera_matrix)
# measuring the angles
try:
m = (p2[1] - p1[1]) / (p2[0] - p1[0])
ang1 = int(math.degrees(math.atan(m)))
except:
ang1 = 90
try:
m = (x2[1] - x1[1]) / (x2[0] - x1[0])
ang2 = int(math.degrees(math.atan(-1 / m)))
except:
ang2 = 90
# print('angle 1: {}, angle 2: {}'.format(ang1, ang2))
# checking for angle 1
if ang1 >= THRESHOLD:
# cv2.putText(img, 'looking down', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
isLookingDown = True
elif ang1 <= -THRESHOLD:
# cv2.putText(img, 'looking up', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
isLookingUp = True
else:
# cv2.putText(img, 'looking front', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
isLookingFront = True
# checking for angle 2
if ang2 >= THRESHOLD:
# cv2.putText(img, 'looking right', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
isLookingRight = True
elif ang2 <= -THRESHOLD:
# cv2.putText(img, 'looking left', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
isLookingLeft = True
# checking for vertical and horizontal directions
if isLookingDown & isLookingRight:
cv2.putText(img, 'looking down and right', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
head_down_right_count += 1
elif isLookingDown & isLookingLeft:
cv2.putText(img, 'looking down and left', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
head_down_left_count += 1
elif isLookingUp & isLookingRight:
cv2.putText(img, 'looking up and right', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
head_up_right_count += 1
elif isLookingUp & isLookingLeft:
cv2.putText(img, 'looking up and left', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
head_up_left_count += 1
elif isLookingFront:
cv2.putText(img, 'Head front', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
head_front_count += 1
# indicate the student name
cv2.putText(img, student_name, (facebox[2], facebox[3]), font, 2, (255, 255, 128), 3)
# increment the face count
face_count += 1
# naming the new image
image_name = "frame-{}.png".format(frame_count)
# new image path
image_path = os.path.join(VIDEO_DIR, image_name)
# save the new image
cv2.imwrite(image_path, img)
# increment the frame count
frame_count += 1
else:
break
# after extracting the frames, save the changes to static content
p = os.popen("python manage.py collectstatic", "w")
p.write("yes")
# calculate percentages
head_up_right_perct = (Decimal(head_up_right_count) / Decimal(face_count)) * 100
head_up_left_perct = (Decimal(head_up_left_count) / Decimal(face_count)) * 100
head_down_right_perct = (Decimal(head_down_right_count) / Decimal(face_count)) * 100
head_down_left_perct = (Decimal(head_down_left_count) / Decimal(face_count)) * 100
head_front_perct = (Decimal(head_front_count) / Decimal(face_count)) * 100
# collect the percentages to a dictionary
percentages['head_up_right_perct'] = head_up_right_perct
percentages['head_up_left_perct'] = head_up_left_perct
percentages['head_down_right_perct'] = head_down_right_perct
percentages['head_down_left_perct'] = head_down_left_perct
percentages['head_front_perct'] = head_front_perct
cv2.destroyAllWindows()
cap.release()
# return the dictionary
return percentages
# this method will retrieve extracted frames
def getExtractedFrames(lecture_video_name):
image_list = []
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
EXTRACTED_DIR = os.path.join(BASE_DIR, "assets\\FirstApp\\gaze\\{}".format(lecture_video_name))
# listing all the images in the directory
for image_path in os.listdir(EXTRACTED_DIR):
image_list.append(image_path)
# checking for the number of frames
if (len(image_list) > 0):
image_list = custom_sort(image_list)
return image_list
else:
return "No extracted frames were found"
# this method will retrieve lecture gaze estimation for each frame
def get_lecture_gaze_esrimation_for_frames(video_name):
# get the base directory
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
VIDEO_PATH = os.path.join(BASE_DIR, "assets\\FirstApp\\videos\\{}".format(video_name))
# play the video
video = cv2.VideoCapture(VIDEO_PATH)
frame_rate = video.get(cv2.CAP_PROP_FPS)
frame_detections = []
face_model = get_face_detector()
landmark_model = get_landmark_model()
cap = cv2.VideoCapture(VIDEO_PATH)
ret, img = cap.read()
size = img.shape
font = cv2.FONT_HERSHEY_SIMPLEX
# 3D model points.
model_points = np.array([
(0.0, 0.0, 0.0), # Nose tip
(0.0, -330.0, -65.0), # Chin
(-225.0, 170.0, -135.0), # Left eye left corner
(225.0, 170.0, -135.0), # Right eye right corne
(-150.0, -150.0, -125.0), # Left Mouth corner
(150.0, -150.0, -125.0) # Right mouth corner
])
# define a variable to count the frames
frame_count = 0
# set a threshold angle
# THRESHOLD = 15
THRESHOLD = 22
# THRESHOLD = 30
# THRESHOLD = 45
# THRESHOLD = 48
# Camera internals
focal_length = size[1]
center = (size[1] / 2, size[0] / 2)
camera_matrix = np.array(
[[focal_length, 0, center[0]],
[0, focal_length, center[1]],
[0, 0, 1]], dtype="double"
)
# iterate the video frames
while True:
ret, img = cap.read()
if ret == True:
# setting up the count variables
head_front_count = 0
head_up_right_count = 0
head_up_left_count = 0
head_down_right_count = 0
head_down_left_count = 0
face_count = 0
# find the number of faces
faces = find_faces(img, face_model)
student_count = 0
# iterate through each detected face
for face in faces:
# declaring boolean variables
isLookingUp = False
isLookingDown = False
isLookingRight = False
isLookingLeft = False
isLookingFront = False
# deriving the student name to display in the image
student_name = 'student-{}'.format(student_count)
# retrieving the facial landmarks and face bounding box coordinates
marks, facebox = detect_marks(img, landmark_model, face)
# mark_detector.draw_marks(img, marks, color=(0, 255, 0))
image_points = np.array([
marks[30], # Nose tip
marks[8], # Chin
marks[36], # Left eye left corner
marks[45], # Right eye right corne
marks[48], # Left Mouth corner
marks[54] # Right mouth corner
], dtype="double")
dist_coeffs = np.zeros((4, 1)) # Assuming no lens distortion
(success, rotation_vector, translation_vector) = cv2.solvePnP(model_points, image_points, camera_matrix,
dist_coeffs, flags=cv2.SOLVEPNP_UPNP)
# Project a 3D point (0, 0, 1000.0) onto the image plane.
# We use this to draw a line sticking out of the nose
(nose_end_point2D, jacobian) = cv2.projectPoints(np.array([(0.0, 0.0, 1000.0)]), rotation_vector,
translation_vector, camera_matrix, dist_coeffs)
p1 = (int(image_points[0][0]), int(image_points[0][1]))
p2 = (int(nose_end_point2D[0][0][0]), int(nose_end_point2D[0][0][1]))
x1, x2 = head_pose_points(img, rotation_vector, translation_vector, camera_matrix)
# measuring the angles
try:
m = (p2[1] - p1[1]) / (p2[0] - p1[0])
ang1 = int(math.degrees(math.atan(m)))
except:
ang1 = 90
try:
m = (x2[1] - x1[1]) / (x2[0] - x1[0])
ang2 = int(math.degrees(math.atan(-1 / m)))
except:
ang2 = 90
# print('angle 1: {}, angle 2: {}'.format(ang1, ang2))
# checking for angle 1
if ang1 >= THRESHOLD:
# cv2.putText(img, 'looking down', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
isLookingDown = True
elif ang1 <= -THRESHOLD:
# cv2.putText(img, 'looking up', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
isLookingUp = True
else:
# cv2.putText(img, 'looking front', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
isLookingFront = True
# checking for angle 2
if ang2 >= THRESHOLD:
# cv2.putText(img, 'looking right', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
isLookingRight = True
elif ang2 <= -THRESHOLD:
# cv2.putText(img, 'looking left', (facebox[0], facebox[1]), font, 2, (255, 255, 128), 3)
isLookingLeft = True
# checking for vertical and horizontal directions
if isLookingDown & isLookingRight:
head_down_right_count += 1
elif isLookingDown & isLookingLeft:
head_down_left_count += 1
elif isLookingUp & isLookingRight:
head_up_right_count += 1
elif isLookingUp & isLookingLeft:
head_up_left_count += 1
elif isLookingFront:
head_front_count += 1
# increment the face count
face_count += 1
# the percentages will be calculated here
head_up_right_perct = (Decimal(head_up_right_count) / Decimal(face_count)) * 100 if (face_count != 0) else 0
head_up_left_perct = (Decimal(head_up_left_count) / Decimal(face_count)) * 100 if (face_count != 0) else 0
head_down_right_perct = (Decimal(head_down_right_count) / Decimal(face_count)) * 100 if (face_count != 0) else 0
head_down_left_perct = (Decimal(head_down_left_count) / Decimal(face_count)) * 100 if (face_count != 0) else 0
head_front_perct = (Decimal(head_front_count) / Decimal(face_count)) * 100 if (face_count != 0) else 0
# the dictionary
percentages = {}
# collect the percentages to a dictionary
percentages['frame_name'] = "frame-{}".format(frame_count)
percentages['head_up_right_perct'] = head_up_right_perct
percentages['head_up_left_perct'] = head_up_left_perct
percentages['head_down_right_perct'] = head_down_right_perct
percentages['head_down_left_perct'] = head_down_left_perct
percentages['head_front_perct'] = head_front_perct
# append the calculated percentages to the frame_detections
frame_detections.append(percentages)
frame_count += 1
else:
break
return frame_detections, frame_rate
\ No newline at end of file
import jinja2 as ji
import pdfkit
import os
# from DemoProject import jinja2
from integrated_slpes import jinja2
def generate_pdf_file(object):
# templateLoader = jinja2.FileSystemLoader(searchpath="../")
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
TEMPLATE_DIR = os.path.join(BASE_DIR, "FirstApp\\templates\\FirstApp")
HTML_PATH = os.path.join(TEMPLATE_DIR, "pdf_template_1.html")
PDF_DIRECTORY = os.path.join(BASE_DIR, "FirstApp\\files")
templateLoader = ji.FileSystemLoader(TEMPLATE_DIR)
new_env = jinja2.environment()
templateEnv = jinja2.Environment(loader=templateLoader)
TEMPLATE_FILE = "pdf_template.html"
template = templateEnv.get_template(TEMPLATE_FILE)
print('variables: ', templateEnv.globals['dict'])
# render the template
outputText = template.render(lecturer_name=object['lecturer_name'], subject=object['subject_name'], date=object['date'], static=new_env.globals['static'])
html_file = open(HTML_PATH, "w")
html_file.write(outputText)
html_file.close()
# create a new pdf file path
NEW_PDF_PATH = os.path.join(PDF_DIRECTORY, "activity.pdf")
asset_path = os.path.join('D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/css/sb-admin-2.min.css')
network_path = "file:/" + asset_path
# options = {'enable-local-file-access': network_path}
options = {'enable-local-file-access': asset_path, 'load-error-handling': 'ignore'}
# create a new pdf file
pdfkit.from_file(HTML_PATH, NEW_PDF_PATH, options=options)
......@@ -117,10 +117,6 @@ def calculate_pose_estimation_for_student(video_name, student, poses):
left_upper_x = 0 if (middle_x - fraction) < 0 else (middle_x - fraction)
print('head_y: ', head_y)
print('fraction: ', fraction)
print('distance: ', distance)
print('left_upper_x: ', left_upper_x)
# extract the new image
new_img = detection_img[head_y:head_y+fraction, left_upper_x:left_upper_x+distance]
......
# Generated by Django 2.2.11 on 2020-08-25 11:28
import FirstApp.MongoModels
from django.db import migrations, models
import django.db.models.deletion
import djongo.models.fields
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0006_lecturercredentials'),
]
operations = [
migrations.RenameField(
model_name='lectureemotionreport',
old_name='lecture_id',
new_name='lecture_emotion_id',
),
migrations.AlterField(
model_name='lectureemotionreport',
name='angry_perct',
field=models.DecimalField(decimal_places=1, default=0.0, max_digits=3),
),
migrations.AlterField(
model_name='lectureemotionreport',
name='disgust_perct',
field=models.DecimalField(decimal_places=1, default=0.0, max_digits=3),
),
migrations.AlterField(
model_name='lectureemotionreport',
name='happy_perct',
field=models.DecimalField(decimal_places=1, default=0.0, max_digits=3),
),
migrations.AlterField(
model_name='lectureemotionreport',
name='neutral_perct',
field=models.DecimalField(decimal_places=1, default=0.0, max_digits=3),
),
migrations.AlterField(
model_name='lectureemotionreport',
name='sad_perct',
field=models.DecimalField(decimal_places=1, default=0.0, max_digits=3),
),
migrations.AlterField(
model_name='lectureemotionreport',
name='surprise_perct',
field=models.DecimalField(decimal_places=1, default=0.0, max_digits=3),
),
migrations.CreateModel(
name='LectureVideo',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_video_id', models.CharField(max_length=10)),
('date', models.DateField()),
('video_name', models.CharField(max_length=50)),
('video_length', models.DurationField()),
('lecturer', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Lecturer')),
('subject', models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Subject')),
],
),
migrations.CreateModel(
name='LectureGazeEstimation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_gaze_id', models.CharField(max_length=10)),
('lecture_video_id',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.LectureVideo')),
],
),
migrations.CreateModel(
name='LectureActivity',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lecture_activity_id', models.CharField(max_length=10)),
('talking_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('listening_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('writing_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('phone_perct', models.DecimalField(decimal_places=1, default=0.0, max_digits=3)),
('lecture_video_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.LectureVideo')),
],
),
migrations.CreateModel(
name='FacultyTimetable',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('timetable_id', models.CharField(max_length=10)),
('timetable', djongo.models.fields.ArrayField(model_container=FirstApp.MongoModels.DateTimeTable)),
('faculty', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Faculty')),
],
),
migrations.AddField(
model_name='lectureemotionreport',
name='lecture_video_id',
field=models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='FirstApp.LectureVideo'),
),
]
# Generated by Django 2.2.11 on 2020-08-25 12:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0007_auto_20200825_1658'),
]
operations = [
migrations.AddField(
model_name='lecturegazeestimation',
name='looking_down_and_left_perct',
field=models.DecimalField(decimal_places=1, default=0.0, max_digits=3),
),
migrations.AddField(
model_name='lecturegazeestimation',
name='looking_down_and_right_perct',
field=models.DecimalField(decimal_places=1, default=0.0, max_digits=3),
),
migrations.AddField(
model_name='lecturegazeestimation',
name='looking_front_perct',
field=models.DecimalField(decimal_places=1, default=0.0, max_digits=3),
),
migrations.AddField(
model_name='lecturegazeestimation',
name='looking_up_and_left_perct',
field=models.DecimalField(decimal_places=1, default=0.0, max_digits=3),
),
migrations.AddField(
model_name='lecturegazeestimation',
name='looking_up_and_right_perct',
field=models.DecimalField(decimal_places=1, default=0.0, max_digits=3),
),
]
......@@ -226,3 +226,12 @@ class VideoMetaSerializer(serializers.ModelSerializer):
class Meta:
model = VideoMeta
fields = '__all__'
# lecture gaze serializer
class LectureGazeEstimationSerializer(serializers.ModelSerializer):
lecture_video_id = LectureVideoSerializer()
class Meta:
model = LectureGazeEstimation
fields = '__all__'
\ No newline at end of file
{% extends 'FirstApp/template.html' %}
<!DOCTYPE html>
<html lang="en">
<!--{% block 'head' %}-->
<!--{% endblock %}-->
{#{% block 'head' %}#}
{# {% endblock %}#}
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
{% block javascript %}
{% load static %}
<!-- Bootstrap core JavaScript-->
<script src="{% static 'FirstApp/vendor/jquery/jquery.min.js' %}"></script>
<script src="{% static 'FirstApp/vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<!-- Page level plugins -->
<script src="{% static 'FirstApp/vendor/datatables/jquery.dataTables.min.js' %}"></script>
<script src="{% static 'FirstApp/vendor/datatables/dataTables.bootstrap4.min.js' %}"></script>
<!-- Page level custom scripts -->
<script src="{% static 'FirstApp/js/demo/datatables-demo.js' %}"></script>
<!-- Core plugin JavaScript-->
<script src="{% static 'FirstApp/vendor/jquery-easing/jquery.easing.min.js' %}"></script>
<!-- canvasJS implementation -->
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<!--basic jquery functions-->
<script type="text/javascript">
var global_lecturer = 0;
var global_lecturer_subject_index = 0;
var global_lecture_date = '';
var global_lecture_video_id = '';
var global_video_name = '';
var student_behavior_summary = {};
$(document).ready(function () {
$('.lecture_radio').click(function () {
//hide the previously displayed progress areas
$('#progress_areas').attr('hidden', true);
//hide the summary button
$('#student_behavior_OR_text').attr('hidden', true);
//hide the summart button
$('#student_behavior_view_summary').attr('hidden', true);
global_lecturer_subject_index = $(this).attr('data-index');
global_lecturer = $(this).attr('data-lecturer');
global_lecture_date = $(this).attr('data-date');
let real_date = new Date(global_lecture_date);
//extract the day
let day = '' + real_date.getDate();
let month = '' + (real_date.getMonth() + 1);
let year = '' + real_date.getFullYear();
if (month.length < 2)
month = '0' + month;
if (day.length < 2)
day = '0' + day;
let date_format = [year, month, day].join('-');
//hide the message
$('#student_behavior_overview').attr('hidden', true);
//display the loader
$('#student_behavior_loader').attr('hidden', false);
//display the video loading message
$('#student_behavior_video_loading').attr('hidden', false);
fetch('http://127.0.0.1:8000/get-lecture-video/?lecturer=' + global_lecturer + '&date=' + date_format + '&index=' + global_lecturer_subject_index)
.then((res) => res.json())
.then((out) => retrieveLectureVideoDetails(out))
.catch((error) => alert('an error occurred: ' + error));
});
//function to display student behavior
function displayStudentBehavior(res) {
//hide the loader
$('#student_behavior_loader').attr('hidden', true);
}
//this function will retrieve lecture video details
function retrieveLectureVideoDetails(lecVideo) {
//hide the loading video details message
$('#student_behavior_video_loading').attr('hidden', true);
//display the activity loading message
$('#student_behavior_activity').attr('hidden', false);
//get the lecture video response
let video = lecVideo.response;
global_lecture_video_id = video.lecture_video_id;
global_video_name = video.video_name;
//after retrieving lecture video details, get lecture activity details
fetch('http://127.0.0.1:8000/get-lecture-activity/?lecture_video_id=' + global_lecture_video_id + '&lecture_video_name=' + global_video_name)
.then((res) => res.json())
.then((out) => displayActivity(out))
.catch((err) => alert('error: ' + err));
}
//this function will display the activity
function displayActivity(activity) {
//hide the activity loading message
$('#student_behavior_video_loading').attr('hidden', true);
//hide the loading message
$('#student_behavior_activity').attr('hidden', true);
//display the emotion loading message
$('#student_behavior_emotion').hide();
activity.response.map((act, index) => {
//setting the percentage values
$('#phone_perct').text(act.phone_perct + '%');
$('#talking_perct').text(act.talking_perct + '%');
$('#listening_perct').text(act.listening_perct + '%');
$('#writing_perct').text(act.writing_perct + '%');
//setting the width in the progress bars
$('#phone_width').width(act.phone_perct + '%');
$('#talking_width').width(act.talking_perct + '%');
$('#listening_width').width(act.listening_perct + '%');
$('#writing_width').width(act.writing_perct + '%');
});
//retrieve the lecture emotions
retrieveLectureEmotion();
}
//this function will retrieve lecture emotion details
function retrieveLectureEmotion() {
//using fetch API
fetch('http://127.0.0.1:8000/get-lecture-emotion/?lecture_video_id=' + global_lecture_video_id + '&lecture_video_name=' + global_video_name)
.then((res) => res.json())
.then((out) => displayEmotion(out))
.catch((err) => alert('error: ' + err));
}
//displaying the activity percentages in the progress bars
function displayEmotion(emotion) {
//hide the emotion loading message
$('#student_behavior_emotion').attr('hidden', true);
//display the gaze message
$('#student_behavior_gaze').attr('hidden', false);
emotion.response.map((act, index) => {
//setting the percentage values
$('#happy_perct').text(act.happy_perct + '%');
$('#sad_perct').text(act.sad_perct + '%');
$('#anger_perct').text(act.angry_perct + '%');
$('#surprise_perct').text(act.surprise_perct + '%');
$('#neutral_perct').text(act.neutral_perct + '%');
//setting the width in the progress bars
$('#happy_width').width(act.happy_perct + '%');
$('#sad_width').width(act.sad_perct + '%');
$('#anger_width').width(act.angry_perct + '%');
$('#surprise_width').width(act.surprise_perct + '%');
$('#neutral_width').width(act.neutral_perct + '%');
});
//retrieve the lecture gaze estimation
retrieveLectureGazeEstimation();
//display the progress bar area
//$('#progress_areas').attr('hidden', false);
}
//this function will retrieve lecture gaze estimations
function retrieveLectureGazeEstimation() {
//using fetch API
fetch('http://127.0.0.1:8000/get-lecture-gaze-estimation/?lecture_video_id=' + global_lecture_video_id + '&lecture_video_name=' + global_video_name)
.then((res) => res.json())
.then((out) => displayGazeEstimation(out))
.catch((err) => alert('error: ' + err));
}
//displaying the activity percentages in the progress bars
function displayGazeEstimation(gaze_estimation) {
//hide the loader
$('#student_behavior_loader').attr('hidden', true);
//hide the emotion loading message
$('#student_behavior_gaze').attr('hidden', true);
gaze_estimation.response.map((act, index) => {
//setting the percentage values
$('#looking_up_right_perct').text(act.looking_up_and_right_perct + '%');
$('#looking_up_left_perct').text(act.looking_up_and_left_perct + '%');
$('#looking_down_right_perct').text(act.looking_down_and_right_perct + '%');
$('#looking_down_left_perct').text(act.looking_down_and_left_perct + '%');
$('#looking_front_perct').text(act.looking_front_perct + '%');
//setting the width in the progress bars
$('#looking_up_right_width').width(act.looking_up_and_right_perct + '%');
$('#looking_up_left_width').width(act.looking_up_and_left_perct + '%');
$('#looking_down_right_width').width(act.looking_down_and_right_perct + '%');
$('#looking_down_left_width').width(act.looking_down_and_left_perct + '%');
$('#looking_front_width').width(act.looking_front_perct + '%');
});
//display the progress bar area
$('#progress_areas').attr('hidden', false);
}
//this function will handle the 'summary' button
$('#summary_btn').click(function () {
//open the modal
$('#summaryModal').modal();
let test_date = new Date(0, 0, 0, 0, 12, 30, 0);
//render the chart onto the modal body
renderChart();
});
//this function will call the chart function
function renderChart() {
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
theme: "light2",
title: {
text: "Student Behavior"
},
axisX: {
title: "Duration",
{#valueFormatString: "DD MMM",#}
valueFormatString: "hh:mm:ss",
crosshair: {
enabled: true,
snapToDataPoint: true
}
},
axisY: {
title: "Number of Students",
includeZero: true,
crosshair: {
enabled: true
}
},
toolTip: {
shared: true
},
legend: {
cursor: "pointer",
verticalAlign: "bottom",
horizontalAlign: "left",
dockInsidePlotArea: true,
itemclick: toogleDataSeries
},
data: [{
type: "line",
showInLegend: true,
name: "Activity",
markerType: "square",
{#xValueFormatString: "DD MMM, YYYY",#}
xValueFormatString: "hh:mm:ss",
color: "#000000",
dataPoints: [
{x: new Date(2017, 0, 3, 0, 2, 0), y: 650},
{x: new Date(2017, 0, 4, 0, 4, 0), y: 700},
{x: new Date(2017, 0, 5, 0, 6, 0), y: 710},
{x: new Date(2017, 0, 6, 0, 8, 0), y: 658},
{x: new Date(2017, 0, 7, 0, 10, 0), y: 734},
{x: new Date(2017, 0, 8, 0, 12, 0), y: 963},
{x: new Date(2017, 0, 9, 0, 14, 0), y: 847},
{x: new Date(2017, 0, 10, 0, 16, 0), y: 853},
{x: new Date(2017, 0, 11, 0, 18, 0), y: 869},
{x: new Date(2017, 0, 12, 0, 20, 0), y: 943},
{x: new Date(2017, 0, 13, 0, 22, 0), y: 970},
{x: new Date(2017, 0, 14, 0, 24, 0), y: 869},
{x: new Date(2017, 0, 15, 0, 26, 0), y: 890},
{x: new Date(2017, 0, 16, 0, 28, 0), y: 930}
]
},
{
type: "line",
showInLegend: true,
name: "Emotion",
lineDashType: "dash",
dataPoints: [
{x: new Date(2017, 0, 3, 0, 2, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 4, 0, 4, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 5, 0, 6, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 6, 0, 8, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 7, 0, 10, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 8, 0, 12, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 9, 0, 14, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 10, 0, 16, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 11, 0, 18, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 12, 0, 20, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 13, 0, 22, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 14, 0, 24, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 15, 0, 26, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 16, 0, 28, 0), y: Number(Math.round(Math.random() * 1000), 0)}
]
},
{
type: "line",
showInLegend: true,
name: "Gaze",
lineDashType: "dash",
dataPoints: [
{x: new Date(2017, 0, 3, 0, 2, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 4, 0, 4, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 5, 0, 6, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 6, 0, 8, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 7, 0, 10, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 8, 0, 12, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 9, 0, 14, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 10, 0, 16, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 11, 0, 18, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 12, 0, 20, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 13, 0, 22, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 14, 0, 24, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 15, 0, 26, 0), y: Number(Math.round(Math.random() * 1000), 0)},
{x: new Date(2017, 0, 16, 0, 28, 0), y: Number(Math.round(Math.random() * 1000), 0)}
]
}]
});
chart.render();
}
//this function will render the chart for Activity statistics
function renderActivityStatistics() {
let individual_activities = student_behavior_summary.individual_activities;
let activity_labels = student_behavior_summary.activity_labels;
let activity_length = individual_activities.length;
let label_length = activity_labels.length;
let data = [];
let colors = [
"#000000",
"#00FF00",
"#0000FF"
];
for (let i = 0; i < label_length; i++) {
let label = activity_labels[i];
let datapoints = [];
for (let j = 0; j < activity_length; j++) {
let activity = individual_activities[j];
datapoints.push({label: "lecture " + (j+1), y: activity[label]});
}
let obj = {
type: "line",
showInLegend: true,
name: label,
markerType: "square",
{#xValueFormatString: "DD MMM, YYYY",#}
xValueFormatString: "Lec " + (i+1),
color: getRandomColor(),
dataPoints: datapoints
};
data.push(obj);
}
var chart = new CanvasJS.Chart("activity_stats_chart", {
animationEnabled: true,
theme: "light2",
title: {
text: "Activity Statistics"
},
axisX: {
title: "Lecture",
{#valueFormatString: "DD MMM",#}
valueFormatString: "lec",
crosshair: {
enabled: true,
snapToDataPoint: true
}
},
axisY: {
title: "Percentage",
includeZero: true,
crosshair: {
enabled: true
}
},
toolTip: {
shared: true
},
legend: {
cursor: "pointer",
verticalAlign: "bottom",
horizontalAlign: "center",
{#dockInsidePlotArea: true,#}
itemclick: toogleDataSeries
},
data: data
});
chart.render();
}
//this function render the chart for Emotion statistics
function renderEmotionStatistics() {
let individual_emotions = student_behavior_summary.individual_emotions;
let emotion_labels = student_behavior_summary.emotion_labels;
let emotion_length = individual_emotions.length;
let label_length = emotion_labels.length;
let data = [];
let colors = [
"#000000",
"#00FF00",
"#0000FF"
];
for (let i = 0; i < label_length; i++) {
let label = emotion_labels[i];
let datapoints = [];
for (let j = 0; j < emotion_length; j++) {
let emotion = individual_emotions[j];
datapoints.push({label: "lecture " + (j+1), y: emotion[label]});
}
let obj = {
type: "line",
showInLegend: true,
name: label,
markerType: "square",
{#xValueFormatString: "DD MMM, YYYY",#}
xValueFormatString: "Lec " + (i+1),
color: colors[i - 1],
dataPoints: datapoints
};
data.push(obj);
}
var chart = new CanvasJS.Chart("emotion_stats_chart", {
animationEnabled: true,
theme: "light2",
title: {
text: "Emotion Statistics"
},
axisX: {
title: "Lecture",
{#valueFormatString: "DD MMM",#}
valueFormatString: "lec" ,
crosshair: {
enabled: true,
snapToDataPoint: true
}
},
axisY: {
title: "Percentage",
includeZero: true,
crosshair: {
enabled: true
}
},
toolTip: {
shared: true
},
legend: {
cursor: "pointer",
verticalAlign: "bottom",
horizontalAlign: "center",
{#dockInsidePlotArea: true,#}
itemclick: toogleDataSeries
},
data: data
});
chart.render();
}
//this function will toggle the content
function toogleDataSeries(e) {
if (typeof (e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
e.dataSeries.visible = false;
} else {
e.dataSeries.visible = true;
}
chart.render();
}
//this function will handle the 'View Summary' button click events
$('#student_behavior_view_summary_btn').click(function () {
$('#student_behavior_view_summary_modal').modal();
});
//this function will handle the view summary option form
$('#view_summary_option_form').submit(function (e) {
let option = $("input[name='option']:checked").val();
let lecturer = "{{ lecturer }}";
e.preventDefault();
//send the data using fetch API
fetch('http://127.0.0.1:8000/get-student-behavior-summary-for-period/?option=' + option + "&lecturer=" + lecturer)
.then((res) => res.json())
.then((out) => displayPeriodStudentActivitySummary(out))
.catch((err) => alert('error: ' + err))
});
//this function will display the percentages
function displayPeriodStudentActivitySummary(out) {
//assign the response to the global variable
student_behavior_summary = out;
if (out.isRecordFound) {
//show the summary tables
$('#student_behavior_summary_for_period').attr('hidden', false);
//assign the activity values
$('#phone_perct_for_period').text(out.activity_response.phone_perct);
$('#listening_perct_for_period').text(out.activity_response.listening_perct);
$('#writing_perct_for_period').text(out.activity_response.writing_perct);
//assign the emotion values
$('#happy_perct_for_period').text(out.emotion_response.happy_perct);
$('#sad_perct_for_period').text(out.emotion_response.sad_perct);
$('#angry_perct_for_period').text(out.emotion_response.angry_perct);
$('#disgust_perct_for_period').text(out.emotion_response.disgust_perct);
$('#surprise_perct_for_period').text(out.emotion_response.surprise_perct);
$('#neutral_perct_for_period').text(out.emotion_response.neutral_perct);
} else {
$('#student_summary_not_found_message').attr('hidden', false);
}
//hide the modal
$('#student_behavior_view_summary_modal').modal("hide");
}
//this function will view activity statistics
$('#view_activity_stats').click(function () {
//render the chart
renderActivityStatistics();
//open the modal
$('#activity_stats_modal').modal();
});
//this function will view emotion statistics
$('#view_emotion_stats').click(function () {
//render the chart
renderEmotionStatistics();
//open the modal
$('#emotion_stats_modal').modal();
});
//this function will generate random colors
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
});
</script>
{% endblock %}
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Begin Page Content -->
{% block 'container-fluid' %}
<div class="container-fluid">
<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">{{object.Message}}</h1>
<a href="#" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm"><i class="fas fa-download fa-sm text-white-50"></i> Generate Report</a>
</div>
<!-- Content Row -->
<div class="row">
<!-- Earnings (Monthly) Card Example -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-primary shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Earnings (Monthly)</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">$40,000</div>
</div>
<div class="col-auto">
<i class="fas fa-calendar fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Main Content -->
<div id="content">
<!-- Earnings (Monthly) Card Example -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-success shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">Earnings (Annual)</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">$215,000</div>
</div>
<div class="col-auto">
<i class="fas fa-dollar-sign fa-2x text-gray-300"></i>
<!-- Begin Page Content -->
{% block 'container-fluid' %}
<div class="container-fluid">
<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">{{ object.Message }}</h1>
{# <a href="#" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm"><i class="fas fa-download fa-sm text-white-50"></i> Generate Report</a>#}
</div>
</div>
</div>
</div>
</div>
<!-- Earnings (Monthly) Card Example -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">Tasks</div>
<div class="row no-gutters align-items-center">
<div class="col-auto">
<div class="h5 mb-0 mr-3 font-weight-bold text-gray-800">50%</div>
<!-- Content Row -->
{# <div class="row">#}
{##}
{# <!-- Earnings (Monthly) Card Example -->#}
{# <div class="col-xl-3 col-md-6 mb-4">#}
{# <div class="card border-left-primary shadow h-100 py-2">#}
{# <div class="card-body">#}
{# <div class="row no-gutters align-items-center">#}
{# <div class="col mr-2">#}
{# <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Earnings (Monthly)</div>#}
{# <div class="h5 mb-0 font-weight-bold text-gray-800">$40,000</div>#}
{# </div>#}
{# <div class="col-auto">#}
{# <i class="fas fa-calendar fa-2x text-gray-300"></i>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{##}
{# <!-- Earnings (Monthly) Card Example -->#}
{# <div class="col-xl-3 col-md-6 mb-4">#}
{# <div class="card border-left-success shadow h-100 py-2">#}
{# <div class="card-body">#}
{# <div class="row no-gutters align-items-center">#}
{# <div class="col mr-2">#}
{# <div class="text-xs font-weight-bold text-success text-uppercase mb-1">Earnings (Annual)</div>#}
{# <div class="h5 mb-0 font-weight-bold text-gray-800">$215,000</div>#}
{# </div>#}
{# <div class="col-auto">#}
{# <i class="fas fa-dollar-sign fa-2x text-gray-300"></i>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{##}
{# <!-- Earnings (Monthly) Card Example -->#}
{# <div class="col-xl-3 col-md-6 mb-4">#}
{# <div class="card border-left-info shadow h-100 py-2">#}
{# <div class="card-body">#}
{# <div class="row no-gutters align-items-center">#}
{# <div class="col mr-2">#}
{# <div class="text-xs font-weight-bold text-info text-uppercase mb-1">Tasks</div>#}
{# <div class="row no-gutters align-items-center">#}
{# <div class="col-auto">#}
{# <div class="h5 mb-0 mr-3 font-weight-bold text-gray-800">50%</div>#}
{# </div>#}
{# <div class="col">#}
{# <div class="progress progress-sm mr-2">#}
{# <div class="progress-bar bg-info" role="progressbar" style="width: 50%" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# <div class="col-auto">#}
{# <i class="fas fa-clipboard-list fa-2x text-gray-300"></i>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{##}
{# <!-- Pending Requests Card Example -->#}
{# <div class="col-xl-3 col-md-6 mb-4">#}
{# <div class="card border-left-warning shadow h-100 py-2">#}
{# <div class="card-body">#}
{# <div class="row no-gutters align-items-center">#}
{# <div class="col mr-2">#}
{# <div class="text-xs font-weight-bold text-warning text-uppercase mb-1">Pending Requests</div>#}
{# <div class="h5 mb-0 font-weight-bold text-gray-800">18</div>#}
{# </div>#}
{# <div class="col-auto">#}
{# <i class="fas fa-comments fa-2x text-gray-300"></i>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{##}
{# </div>#}
<!-- Content Row -->
<div class="row">
<!-- Area Chart -->
<div class="col-lg-6">
<div class="card shadow mb-4">
<!-- Card Header - Dropdown -->
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Student Behavior Overview</h6>
<div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
</div>
</div>
<!-- Card Body -->
<div class="card-body">
<!-- default message -->
<div class="text-center" id="student_behavior_overview">
<span class="font-italic">Please select a date to preview</span>
</div>
<!-- OR message -->
<div class="text-center mt-4" id="student_behavior_OR_text">
<span class="font-italic">---OR---</span>
</div>
<!-- 'View summary' button section -->
<div class="text-center my-4" id="student_behavior_view_summary">
<button type="button" class="btn btn-primary"
id="student_behavior_view_summary_btn">View Summary
</button>
</div>
<!-- loading video details message -->
<div class="text-center" id="student_behavior_video_loading" hidden>
<span class="font-italic">Loading Video Details...</span>
</div>
<!-- loading lecture activity message -->
<div class="text-center" id="student_behavior_activity" hidden>
<span class="font-italic">Loading Student Activity...</span>
</div>
<!-- loading lecture emotion message -->
<div class="text-center" id="student_behavior_emotion" hidden>
<span class="font-italic">Loading Student Emotion...</span>
</div>
<!-- loading lecture gaze estimation message -->
<div class="text-center" id="student_behavior_gaze" hidden>
<span class="font-italic">Loading Student Gaze estimation...</span>
</div>
<!--loader -->
<div class="text-center" id="student_behavior_loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="Loader">
</div>
<!-- student summary not found message -->
<div class="text-center mt-4" id="student_summary_not_found_message" hidden>
<span class="font-italic">No student summary was found</span>
</div>
<!-- to display student behavior summary for period -->
<div class="text-center" id="student_behavior_summary_for_period" hidden>
<!-- Activity card -->
<div class="card shadow-lg mb-2">
<div class="card-body">
<!-- put the heading -->
<div class="text-center mt-2">
<h4 class="font-weight-bold">Activity</h4>
</div>
<!-- percentages -->
<div class="text-center">
<!-- activity table -->
<table class="table table-borderless table-striped">
<tbody>
<tr>
<td>
Phone percentage
<hr style="height: 5px">
</td>
<td id="phone_perct_for_period"></td>
</tr>
<tr>
<td>
Listening percentage
<hr style="height: 5px">
</td>
<td id="listening_perct_for_period"></td>
</tr>
<tr>
<td>
Note taking percentage
<hr style="height: 5px">
</td>
<td id="writing_perct_for_period"></td>
</tr>
</tbody>
</table>
<!-- end of activity table -->
</div>
<!-- stats button -->
<div class="float-right">
<button type="button" class="btn btn-primary"
id="view_activity_stats">
<i class="fa fa-line-chart"></i>
View stats
</button>
</div>
<!-- end of stats button -->
</div>
</div>
<!-- end of Activity card -->
<!-- Emotion card -->
<div class="card shadow-lg mb-2">
<div class="card-body">
<!-- put the heading -->
<div class="text-center mt-2">
<h4 class="font-weight-bold">Emotion</h4>
</div>
<!-- percentages -->
<div class="text-center">
<!-- emotion table -->
<table class="table table-borderless table-striped">
<tbody>
<tr>
<td>
Happy percentage
<hr style="height: 5px">
</td>
<td id="happy_perct_for_period"></td>
</tr>
<tr>
<td>
Sad percentage
<hr style="height: 5px">
</td>
<td id="sad_perct_for_period"></td>
</tr>
<tr>
<td>
Angry percentage
<hr style="height: 5px">
</td>
<td id="angry_perct_for_period"></td>
</tr>
<tr>
<td>
Disgust percentage
<hr style="height: 5px">
</td>
<td id="disgust_perct_for_period"></td>
</tr>
<tr>
<td>
Surprise percentage
<hr style="height: 5px">
</td>
<td id="surprise_perct_for_period"></td>
</tr>
<tr>
<td>
Neutral percentage
<hr style="height: 5px">
</td>
<td id="neutral_perct_for_period"></td>
</tr>
</tbody>
</table>
<!-- end of emotion table -->
</div>
<!-- end of percentages -->
<!-- stats button -->
<div class="float-right">
<button type="button" class="btn btn-primary"
id="view_emotion_stats">
<i class="fa fa-line-chart"></i>
View stats
</button>
</div>
<!-- end of stats button -->
</div>
</div>
<!-- end of Emotion card -->
</div>
<!-- end of student behavior summary -->
<!-- a vertical list displaying the student engagement categories -->
<ul class="list-group" id="progress_areas" hidden>
<li class="list-group-item border">
<button type="button" class="btn btn-link"
data-target="#progress_area_activity" data-toggle="collapse">
<h5 class="font-weight-bold">Activity</h5>
</button>
<!--this area will display the activity progress bars -->
<div id="progress_area_activity" class="collapse">
<!--talking with friends -->
<h4 class="small font-weight-bold">Talking with friends</h4>
<span class="float-right" id="talking_perct">40%</span>
<div class="progress mb-4">
<div class="progress-bar bg-danger" role="progressbar"
id="talking_width"
style="width: 20%"
aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--phone checking -->
<h4 class="small font-weight-bold">Phone checking</h4>
<span class="float-right" id="phone_perct">45%</span>
<div class="progress mb-4">
<div class="progress-bar bg-warning" role="progressbar"
id="phone_width"
style="width: 40%"
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--note taking -->
<h4 class="small font-weight-bold">Writing</h4>
<span class="float-right" id="writing_perct">50%</span>
<div class="progress mb-4">
<div class="progress-bar" role="progressbar" id="writing_width"
style="width: 60%"
aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--listening-->
<h4 class="small font-weight-bold">Listening</h4>
<span class="float-right" id="listening_perct">60%</span>
<div class="progress mb-4">
<div class="progress-bar bg-info" role="progressbar"
id="listening_width" style="width: 80%"
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
<!-- end of progress area (activity) -->
<hr>
</li>
<!-- end of the activity list item -->
<!-- beginning of the emotion list item -->
<li class="list-group-item">
<button type="button" class="btn btn-link"
data-target="#progress_area_emotion"
data-toggle="collapse">
<h5 class="font-weight-bold">Emotion</h5>
</button>
<!-- this area will display the emotion progress bars -->
<!--this area will display the progress bars -->
<div id="progress_area_emotion" class="collapse">
<!--Happy -->
<h4 class="small font-weight-bold">Happy</h4>
<span class="float-right" id="happy_perct">40%</span>
<div class="progress mb-4">
<div class="progress-bar bg-danger" role="progressbar"
id="happy_width"
style="width: 20%"
aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--sad -->
<h4 class="small font-weight-bold">Sad</h4>
<span class="float-right" id="sad_perct">45%</span>
<div class="progress mb-4">
<div class="progress-bar bg-warning" role="progressbar"
id="sad_width"
style="width: 40%"
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--anger -->
<h4 class="small font-weight-bold">Anger</h4>
<span class="float-right" id="anger_perct">50%</span>
<div class="progress mb-4">
<div class="progress-bar" role="progressbar" id="anger_width"
style="width: 60%"
aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--surprise-->
<h4 class="small font-weight-bold">Surprise</h4>
<span class="float-right" id="surprise_perct">60%</span>
<div class="progress mb-4">
<div class="progress-bar bg-info" role="progressbar"
id="surprise_width" style="width: 80%"
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--neutral-->
<h4 class="small font-weight-bold">Neutral</h4>
<span class="float-right" id="neutral_perct">60%</span>
<div class="progress mb-4">
<div class="progress-bar bg-info" role="progressbar"
id="neutral_width" style="width: 80%"
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
<!-- end of emotion progress bars -->
<hr>
</li>
<!-- end of the emotion list item -->
<!-- beginning of the gaze list item -->
<li class="list-group-item border">
<button type="button" class="btn btn-link"
data-target="#progress_area_gaze" data-toggle="collapse">
<h5 class="font-weight-bold">Gaze</h5>
</button>
<!--this area will display the activity progress bars -->
<div id="progress_area_gaze" class="collapse">
<!--looking up and right -->
<h4 class="small font-weight-bold">Looking up and right</h4>
<span class="float-right" id="looking_up_right_perct">40%</span>
<div class="progress mb-4">
<div class="progress-bar bg-danger" role="progressbar"
id="looking_up_right_width"
style="width: 20%"
aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--looking up and left -->
<h4 class="small font-weight-bold">Looking up and left</h4>
<span class="float-right" id="looking_up_left_perct">45%</span>
<div class="progress mb-4">
<div class="progress-bar bg-warning" role="progressbar"
id="looking_up_left_width"
style="width: 40%"
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--looking down and right -->
<h4 class="small font-weight-bold">Looking down and right</h4>
<span class="float-right" id="looking_down_right_perct">50%</span>
<div class="progress mb-4">
<div class="progress-bar bg-success" role="progressbar" id="looking_down_right_width"
style="width: 60%"
aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--Looking down and left-->
<h4 class="small font-weight-bold">Looking down and left</h4>
<span class="float-right" id="looking_down_left_perct">60%</span>
<div class="progress mb-4">
<div class="progress-bar bg-info" role="progressbar"
id="looking_down_left_width" style="width: 80%"
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--Looking front-->
<h4 class="small font-weight-bold">Looking front</h4>
<span class="float-right" id="looking_front_perct">60%</span>
<div class="progress mb-4">
<div class="progress-bar bg-secondary" role="progressbar"
id="looking_front_width" style="width: 80%"
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
<!-- end of progress area (gaze) -->
<hr>
</li>
<!-- end of the gaze list item -->
<!-- button to view a summary -->
<li class="list-group-item">
<button type="button" class="btn btn-primary float-right" id="summary_btn">
Summary
</button>
</li>
</ul>
</div>
</div>
</div>
<div class="col">
<div class="progress progress-sm mr-2">
<div class="progress-bar bg-info" role="progressbar" style="width: 50%" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!-- list of recent lectures -->
<div class="col-lg-6">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Recent Lecture Recordings</h6>
</div>
<div class="card-body">
<table class="table table-bordered">
<thead>
<tr>
<th></th>
<th>Date</th>
<th>Subject</th>
</tr>
</thead>
<tbody>
{% for lecturer_detail in lecturer_details %}
<tr>
<td>
<div class="radio">
<label><input type="radio"
class="lecture_radio"
name="recent_recordings_radio"
data-lecturer="{{ lecturer_detail.lecturer }}"
data-index="{{ lecturer_detail.index }}"
data-date="{{ lecturer_detail.date }}">
</label>
</div>
</td>
<td>
{{ lecturer_detail.date }}
</td>
<td>
{{ lecturer_detail.subject_name }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- end of table -->
<!-- button -->
{# <div class="float-right">#}
{# <button type="button" class="btn btn-info" id="weekly_summary">Weekly Summary</button>#}
{# </div>#}
</div>
</div>
</div>
</div>
</div>
<div class="col-auto">
<i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Pending Requests Card Example -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-warning shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">Pending Requests</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">18</div>
</div>
<div class="col-auto">
<i class="fas fa-comments fa-2x text-gray-300"></i>
<!-- Content Row -->
<div class="row">
<!-- 1st Column -->
<div class="col-lg-6 mb-4">
{% load static %}
<!-- Project Card Example -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Attendance Preview</h6>
</div>
<div class="card-body">
<div class="text-center" id="temp_attendance_content">
<span class="font-italic">Attendance preview will be displayed here</span>
</div>
</div>
</div>
<!-- Color System -->
{# <div class="row">#}
{# <div class="col-lg-6 mb-4">#}
{# <div class="card bg-primary text-white shadow">#}
{# <div class="card-body">#}
{# Primary#}
{# <div class="text-white-50 small">#4e73df</div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# <div class="col-lg-6 mb-4">#}
{# <div class="card bg-success text-white shadow">#}
{# <div class="card-body">#}
{# Success#}
{# <div class="text-white-50 small">#1cc88a</div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# <div class="col-lg-6 mb-4">#}
{# <div class="card bg-info text-white shadow">#}
{# <div class="card-body">#}
{# Info#}
{# <div class="text-white-50 small">#36b9cc</div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# <div class="col-lg-6 mb-4">#}
{# <div class="card bg-warning text-white shadow">#}
{# <div class="card-body">#}
{# Warning#}
{# <div class="text-white-50 small">#f6c23e</div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# <div class="col-lg-6 mb-4">#}
{# <div class="card bg-danger text-white shadow">#}
{# <div class="card-body">#}
{# Danger#}
{# <div class="text-white-50 small">#e74a3b</div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# <div class="col-lg-6 mb-4">#}
{# <div class="card bg-secondary text-white shadow">#}
{# <div class="card-body">#}
{# Secondary#}
{# <div class="text-white-50 small">#858796</div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
</div>
<!-- 2nd column -->
<div class="col-lg-6 mb-4">
<!-- Approach -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">My Performances</h6>
</div>
<div class="card-body">
<!-- beginning of the table -->
<table class="table table-bordered">
<thead>
<tr>
<th></th>
<th>Date</th>
<th>Subject</th>
</tr>
</thead>
<tbody>
{% for lecturer_detail in lecturer_details %}
<tr>
<td>
<div class="radio">
<label><input type="radio"
id="{{ subject.0.subject_code }}"
name="recent_recordings_radio"
data-lecturer="{{ lecturer }}"
data-index="{{ lecturer_detail.index }}"
data-date="{{ lecturer_detail.date }}">
</label>
</div>
</td>
<td>
{{ lecturer_detail.date }}
</td>
<td>
{{ lecturer_detail.subject_name }}
</td>
<td>
<button type="button" class="btn btn-primary">View</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- end of table -->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
{% endblock %}
</div>
<!-- Content Row -->
<div class="row">
<!-- Area Chart -->
<div class="col-xl-8 col-lg-7">
<div class="card shadow mb-4">
<!-- Card Header - Dropdown -->
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Attendance Overview</h6>
<div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink">
<div class="dropdown-header">Dropdown Header:</div>
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</div>
</div>
<!-- End of Main Content -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- scroll to top button-->
{% block 'modal' %}
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<!-- Card Body -->
<div class="card-body">
<div class="chart-area">
<canvas id="myAreaChart"></canvas>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="/logout">Logout</a>
</div>
</div>
</div>
</div>
</div>
<!-- end of logout modal -->
<!-- Pie Chart -->
<div class="col-xl-4 col-lg-5">
<div class="card shadow mb-4">
<!-- Card Header - Dropdown -->
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Revenue Sources</h6>
<div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink">
<div class="dropdown-header">Dropdown Header:</div>
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</div>
<!-- summary Modal-->
<div class="modal fade" id="summaryModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document" style="max-width: 1300px">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Summary</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<!-- Card Body -->
<div class="card-body">
<div class="chart-pie pt-4 pb-2">
<canvas id="myPieChart"></canvas>
</div>
<div class="mt-4 text-center small">
<span class="mr-2">
<i class="fas fa-circle text-primary"></i> Direct
</span>
<span class="mr-2">
<i class="fas fa-circle text-success"></i> Social
</span>
<span class="mr-2">
<i class="fas fa-circle text-info"></i> Referral
</span>
</div>
<div class="modal-body">
<div id="chartContainer" style="height: 370px; max-width: 920px; margin: 0px auto;"></div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
<!-- Content Row -->
<div class="row">
</div>
</div>
<!-- end of summary modal -->
<!-- Content Column -->
<div class="col-lg-6 mb-4">
<!-- Project Card Example -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Student Behavior</h6>
<!-- student behavior view summary modal -->
<div class="modal fade" id="student_behavior_view_summary_modal" tabindex="-1" role="dialog"
aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document" style="max-width: 500px">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="exampleModalLabel">View Summary Options</h3>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="card-body">
{% load static %}
<video width="500" height="300" controls>
<source src="{% static 'FirstApp/videos/Classroom_Video.mp4' %}" type="video/mp4">
Your browser does not support the video tag.
</video>
<a href="/webcam" class="btn btn-outline-primary" id="processBtn">Process</a>
</div>
</div>
<!-- Color System -->
<div class="row">
<div class="col-lg-6 mb-4">
<div class="card bg-primary text-white shadow">
<div class="card-body">
Primary
<div class="text-white-50 small">#4e73df</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-4">
<div class="card bg-success text-white shadow">
<div class="card-body">
Success
<div class="text-white-50 small">#1cc88a</div>
<div class="modal-body">
<div class="form-group">
<h5>View Summary for...</h5>
</div>
</div>
<!-- list of options -->
<form action="#" method="get" id="view_summary_option_form">
<div class="custom-control custom-radio mt-2">
<input type="radio" class="custom-control-input" id="customRadio" name="option" value="7">
<label class="custom-control-label" for="customRadio">one week</label>
</div>
<div class="custom-control custom-radio mt-2">
<input type="radio" class="custom-control-input" id="customRadio1" name="option" value="14">
<label class="custom-control-label" for="customRadio1">2 weeks</label>
</div>
<div class="custom-control custom-radio mt-2">
<input type="radio" class="custom-control-input" id="customRadio2" name="option" value="30">
<label class="custom-control-label" for="customRadio2">one month</label>
</div>
<div class="custom-control custom-radio mt-2">
<input type="radio" class="custom-control-input" id="customRadio3" name="option" value="10000">
<label class="custom-control-label" for="customRadio3">All</label>
</div>
<div class="form-group mt-4">
<button type="submit" class="btn btn-outline-success" id="submit_view_summary_option">
Submit
</button>
</div>
</form>
<!-- end of list of options -->
</div>
<div class="col-lg-6 mb-4">
<div class="card bg-info text-white shadow">
<div class="card-body">
Info
<div class="text-white-50 small">#36b9cc</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
</div>
<div class="col-lg-6 mb-4">
<div class="card bg-warning text-white shadow">
<div class="card-body">
Warning
<div class="text-white-50 small">#f6c23e</div>
</div>
</div>
</div>
</div>
</div>
<!-- end of student behavior view summary modal -->
<!-- activity statistics Modal-->
<div class="modal fade" id="activity_stats_modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document" style="max-width: 1400px">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Activity Statistics</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="col-lg-6 mb-4">
<div class="card bg-danger text-white shadow">
<div class="card-body">
Danger
<div class="text-white-50 small">#e74a3b</div>
</div>
</div>
<div class="modal-body text-center">
<div id="activity_stats_chart" style="height: 370px; width: 100%"></div>
</div>
<div class="col-lg-6 mb-4">
<div class="card bg-secondary text-white shadow">
<div class="card-body">
Secondary
<div class="text-white-50 small">#858796</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
</div>
<!-- end of activity statistics modal -->
<div class="col-lg-6 mb-4">
<!-- Illustrations -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Lecture Recordings</h6>
<!-- emotion statistics Modal-->
<div class="modal fade" id="emotion_stats_modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document" style="max-width: 1400px">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Emotion Statistics</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="card-body">
<table class="table table-bordered">
<thead>
<tr>
<th>Video Name</th>
<th>Length</th>
</tr>
</thead>
<tbody>
{% for video in Videos %}
<tr>
<td>
<a href="{% url 'video' %}?video_name={{video.name}}" class="btn btn-link">{{video.name}}</a>
</td>
<td>{{video.duration}}</td>
<td>
<a href="{% url 'video' %}?video_name={{video.name}}" class="btn btn-outline-info">Process</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- <div class="text-center">-->
<!-- <img class="img-fluid px-3 px-sm-4 mt-3 mb-4" style="width: 25rem;" src="img/undraw_posting_photo.svg" alt="">-->
<!-- </div>-->
<!-- <p>Add some quality, svg illustrations to your project courtesy of <a target="_blank" rel="nofollow" href="https://undraw.co/">unDraw</a>, a constantly updated collection of beautiful svg images that you can use completely free and without attribution!</p>-->
<!-- <a target="_blank" rel="nofollow" href="https://undraw.co/">Browse Illustrations on unDraw &rarr;</a>-->
</div>
</div>
<!-- Approach -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Development Approach</h6>
<div class="modal-body text-center">
<div id="emotion_stats_chart" style="height: 370px; width: 100%"></div>
</div>
<div class="card-body">
<p>SB Admin 2 makes extensive use of Bootstrap 4 utility classes in order to reduce CSS bloat and poor page performance. Custom CSS classes are used to create custom components and custom utility classes.</p>
<p class="mb-0">Before working with this theme, you should become familiar with the Bootstrap framework, especially the utility classes.</p>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
{% endblock %}
</div>
<!-- End of Main Content -->
</div>
<!-- End of Content Wrapper -->
<!-- end of activity statistics modal -->
</div>
<!-- End of Page Wrapper -->
<!-- scroll to top button-->
{% block 'modal' %}
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="/logout">Logout</a>
</div>
</div>
</div>
</div>
{% endblock %}
{% endblock %}
<!--scripts-->
{% block 'scripts' %}
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
{% block 'scripts' %}
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous"></script>
<script src="{% static 'FirstApp/vendor/jquery/jquery.min.js' %}"></script>
<script src="{% static 'FirstApp/vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
......@@ -365,6 +1498,6 @@
<script src="{% static 'FirstApp/js/demo/chart-area-demo.js' %}"></script>
<script src="{% static 'FirstApp/js/demo/chart-pie-demo.js' %}"></script>
{% endblock %}
{% endblock %}
</body>
</html>
\ No newline at end of file
......@@ -29,6 +29,7 @@
var global_lecture_video_id = '';
var global_video_name = '';
var global_lecturer_subject_index = 0;
var global_lecture_date = '';
//jquery
$(document).ready(function () {
......@@ -72,6 +73,8 @@
real_class = '.' + real_class;
let date = e.target.parentNode.parentNode.firstChild.innerHTML;
//assign the date
global_lecture_date = date;
fetch('http://127.0.0.1:8000/get-lecture-video/?lecturer=' + global_lecturer + '&date=' + date + '&index=' + global_lecturer_subject_index)
.then((res) => res.json())
......@@ -79,7 +82,7 @@
.catch((error) => alert('an error occurred: ' + error));
});
//this function will display the timetable for the lecturer
function createTimeTable(timetable, subject, lecturer) {
$('#loader').attr('hidden', true);
$('#timetable').attr('hidden', false);
......@@ -146,16 +149,19 @@
if (lectureVideo.isActivityFound) {
e.target.parentNode.parentNode.lastChild.innerHTML = '<button type="button" class="btn btn-primary">Results</button>';
e.target.parentNode.parentNode.lastChild.innerHTML = '<button type="button" class="btn btn-primary" id="result_btn">Results</button>';
} else {
e.target.parentNode.parentNode.lastChild.innerHTML = '<button type="button" class="btn btn-success">Process</button>';
}
//enable the 'generate report' button
$('#generate_report_before').attr('disabled', false);
$('#video_modal').modal();
}
//binding a click event for 'btn-primary' buttons
$(document).on('click', '.btn-primary', function (e) {
$(document).on('click', '#result_btn', function (e) {
//removing the previous frames (if there is any)
$('#main_frames').remove();
......@@ -215,15 +221,15 @@
//sending the POST request to process the lecture activities
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((out) => handleResponse(out.response, e))
.then((out) => handleActivityResponse(out.response, e))
.catch((error) => alert('error: ' + error));
});
//this is to change the button from 'process' to 'results'
function handleResponse(response, e) {
//this is to detect the response gained from activity recognition porcess
function handleActivityResponse(response, e) {
//change the button, if the response is positive
if (response) {
e.target.parentNode.parentNode.lastChild.innerHTML = '<button type="button" class="btn btn-primary">Results</button>';
e.target.parentNode.parentNode.lastChild.innerHTML = '<button type="button" class="btn btn-primary" id="result_btn">Results</button>';
}
}
......@@ -736,7 +742,7 @@
//to handle the 'integrate' modal
$('#integrate_activity').click(function () {
$('#integrate_gaze').click(function () {
//define the student video src
let video_src = "{% static '' %}FirstApp/videos/" + global_video_name;
......@@ -852,7 +858,7 @@
$('#listening_instant_value').width(listening_number + '%');
*/
}, 1000);
}, 33);
//check for the current class
if (classes === play_class) {
......@@ -878,6 +884,29 @@
});
//this method will call the API to generate activity report
$('#generate_report_btn').click(function () {
//call the fetch API
//hide the message
$('#generate_report_message').hide();
fetch('http://127.0.0.1:8000/lecture-activity-report-generation/?lecturer=' + global_lecturer + '&subject=' + global_subject + '&date=' + global_lecture_date)
.then((res) => res.json())
.then((out) => {
//show the loader and loading message
$('#generate_report_loader').attr('hidden', true);
$('#generate_report_loading_message').attr('hidden', true);
$('#generateReportModal').modal('hide');
})
.catch((err) => alert('error: ' + err))
});
});
......@@ -901,9 +930,12 @@
{% load static %}
<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Student Activity Recognition</h1>
</div>
{# <div class="d-sm-flex align-items-center justify-content-between mb-4">#}
{# <h1 class="h3 mb-0 text-gray-800">Student Activity Recognition</h1>#}
{# <button type="button" data-target="#generateReportModal" data-toggle="modal" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm" id="generate_report_before" disabled><i#}
{# class="fas fa-download fa-sm text-white-50"></i> Generate Report</button>#}
{# </div>#}
<!--first row -->
<div class="row p-2">
......@@ -1183,63 +1215,90 @@
<!--2nd column -->
<div class="col-lg-6">
<!--card content -->
<div class="card shadow mb-4">
<!--card header -->
<div class="card-header py-3">
<h5 class="m-0 font-weight-bold text-primary">Frame Detections</h5>
</div>
{# <div class="col-lg-6">#}
{# <!--card content -->#}
{# <div class="card shadow mb-4">#}
{# <!--card header -->#}
{# <div class="card-header py-3">#}
{# <h5 class="m-0 font-weight-bold text-primary">Frame Detections</h5>#}
{# </div>#}
{##}
{# <!--card body -->#}
{# <div class="text-center p-4" id="detection_frames">#}
{##}
{# <!--no content message-->#}
{# <div class="text-center p-2" id="no_detection_message_content">#}
{# <span class="font-italic">No frame is selected</span>#}
{# </div>#}
{##}
{# <div class="text-left m-3" id="detection_number_area" hidden>#}
{# <p>No of detections: <span id="no_of_detections"></span></p>#}
{# </div>#}
{# <!--the detection loader -->#}
{# <div class="text-center p-2" id="detection_loader" hidden>#}
{# <img src="{% static 'FirstApp/images/ajax-loader.gif' %}"#}
{# alt="Loader">#}
{# </div>#}
{# </div>#}
{# </div>#}
<!--card body -->
<div class="text-center p-4" id="detection_frames">
<!--no content message-->
<div class="text-center p-2" id="no_detection_message_content">
<span class="font-italic">No frame is selected</span>
</div>
<div class="text-left m-3" id="detection_number_area" hidden>
<p>No of detections: <span id="no_of_detections"></span></p>
</div>
<!--the detection loader -->
<div class="text-center p-2" id="detection_loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}"
alt="Loader">
</div>
</div>
</div>
<!--detection person card -->
{# <div class="card shadow mb-4">#}
{# <!--card header -->#}
{# <div class="card-header py-3">#}
{# <h5 class="m-0 font-weight-bold text-primary">Detected Students (by activity#}
{# type)</h5>#}
{# </div>#}
{##}
{# <!--card body -->#}
{# <div class="text-center p-4" id="detection_students">#}
{# <!--activity type line -->#}
{# <div class="text-center p-2" id="activity_type" hidden>#}
{# <p>Activity Type: <span class="font-weight-bold" id="activity_type_text"></span>#}
{# </p>#}
{# </div>#}
{##}
{# <!--no content message-->#}
{# <div class="text-center p-2" id="no_detection_student_content">#}
{# <span class="font-italic">No activity type is selected</span>#}
{# </div>#}
{##}
{# <!--the detection student loader -->#}
{# <div class="text-center p-2" id="detection_student_loader" hidden>#}
{# <img src="{% static 'FirstApp/images/ajax-loader.gif' %}"#}
{# alt="Loader">#}
{# </div>#}
{##}
{# </div>#}
{# </div>#}
{# </div>#}
<!--2nd column -->
<div class="col-lg-6">
<!--card -->
<div class="card shadow mb-4">
<!--card header -->
<div class="card-header py-3">
<h5 class="m-0 font-weight-bold text-primary">Detected Students (by activity
type)</h5>
<div class="card-header">
<h5 class="m-0 font-weight-bold text-primary">Integrated Evaluation</h5>
</div>
<!--card body -->
<div class="text-center p-4" id="detection_students">
<!--activity type line -->
<div class="text-center p-2" id="activity_type" hidden>
<p>Activity Type: <span class="font-weight-bold" id="activity_type_text"></span>
</p>
</div>
<!--no content message-->
<div class="text-center p-2" id="no_detection_student_content">
<span class="font-italic">No activity type is selected</span>
<div class="card-body">
<div class="text-center" id="integrate_message">
<span class="font-italic">The integrated version student and lecturer evaluations will display here.</span>
</div>
<!--the detection student loader -->
<div class="text-center p-2" id="detection_student_loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}"
alt="Loader">
<!--button -->
<div class="text-right m-4">
<button type="button" class="btn btn-outline-success" id="integrate_gaze">
Process
</button>
</div>
</div>
</div>
</div>
<!--end of 2nd column -->
</div>
......@@ -1250,63 +1309,37 @@
<!--1st column -->
<div class="col-lg-6">
<!--card -->
<div class="card shadow mb-4">
<!--card header -->
<div class="card-header">
<h5 class="m-0 font-weight-bold text-primary">Evaluated Students</h5>
</div>
<!--card body -->
<div class="card-body" id="evaluation_students">
<!--no content message-->
<div class="text-center p-2" id="no_evaluated_student_content">
<span class="font-italic">Press 'Evaluate' button to evaluate students</span>
</div>
<!--the detection student loader -->
<div class="text-center p-2" id="evaluate_student_loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}"
alt="Loader">
</div>
<!--end of student detection loader -->
</div>
</div>
{# <!--card -->#}
{# <div class="card shadow mb-4">#}
{# <!--card header -->#}
{# <div class="card-header">#}
{# <h5 class="m-0 font-weight-bold text-primary">Evaluated Students</h5>#}
{# </div>#}
{##}
{# <!--card body -->#}
{# <div class="card-body" id="evaluation_students">#}
{##}
{# <!--no content message-->#}
{# <div class="text-center p-2" id="no_evaluated_student_content">#}
{# <span class="font-italic">Press 'Evaluate' button to evaluate students</span>#}
{# </div>#}
{##}
{# <!--the detection student loader -->#}
{# <div class="text-center p-2" id="evaluate_student_loader" hidden>#}
{# <img src="{% static 'FirstApp/images/ajax-loader.gif' %}"#}
{# alt="Loader">#}
{# </div>#}
{# <!--end of student detection loader -->#}
{##}
{##}
{# </div>#}
{##}
{# </div>#}
</div>
<!--end of 1st column -->
<!--2nd column -->
<div class="col-lg-6">
<!--card -->
<div class="card shadow mb-4">
<!--card header -->
<div class="card-header">
<h5 class="m-0 font-weight-bold text-primary">Integrated Evaluation</h5>
</div>
<!--card body -->
<div class="card-body">
<div class="text-center" id="integrate_message">
<span class="font-italic">The integrated version student and lecturer evaluations will display here.</span>
</div>
<!--button -->
<div class="text-right m-4">
<button type="button" class="btn btn-outline-success" id="integrate_activity">
Process
</button>
</div>
</div>
</div>
</div>
<!--end of 2nd column -->
</div>
<!--end of 3rd row -->
......@@ -1451,6 +1484,37 @@
</div>
<!-- generate report Modal-->
<div class="modal fade" id="generateReportModal" tabindex="-1" role="dialog" aria-labelledby="generateReportModal"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Generate Activity Report</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div id="generate_report_message">
Are you sure you want to generate the report without going through the content?
</div>
<div class="text-center" id="generate_report_loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader-1.gif' %}" alt="loader">y
</div>
<div class="text-center" id="generate_report_loading_message" hidden>
<span class="font-italic">This will take some time</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal" id="generate_report_btn">Yes</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">No</button>
</div>
</div>
</div>
</div>
<!--integrate modal -->
<div class="modal fade" id="integrate_modal" tabindex="-1" role="dialog" aria-labelledby="integrate_modal">
<div class="modal-dialog" style="max-width: 1300px">
......@@ -1548,12 +1612,12 @@
<span class="font-italic">No video was found</span>
</div>
<video width="500" height="300" id="lecturer_video" controls>
<source src="#"
type="video/mp4">
Your browser does not support the video tag.
</video>
<!-- video -->
{# <video width="500" height="300" id="lecturer_video" controls>#}
{# <source src="#"#}
{# type="video/mp4">#}
{# Your browser does not support the video tag.#}
{# </video>#}
</div>
<!--end of lecture video section -->
......
......@@ -3,6 +3,8 @@
<head>
{% load static %}
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
......@@ -12,11 +14,11 @@
<title>SB Admin 2 - Charts</title>
<!-- Custom fonts for this template-->
<link href="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="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
<link href="{% static 'FirstApp/css/sb-admin-2.min.css' %}" rel="stylesheet">
</head>
......
......@@ -195,7 +195,6 @@
activity.response.map((act, index) => {
//setting the percentage values
alert('happy perct: ' + act);
$('#happy_perct').text(act.happy_perct + '%');
$('#sad_perct').text(act.sad_perct + '%');
$('#anger_perct').text(act.angry_perct + '%');
......@@ -1151,10 +1150,10 @@
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--evaluate button -->
<button type="button" class="btn btn-danger float-right"
id="evaluate_button">Evaluate
</button>
{# <!--evaluate button -->#}
{# <button type="button" class="btn btn-danger float-right"#}
{# id="evaluate_button">Evaluate#}
{# </button>#}
</div>
......@@ -1215,63 +1214,63 @@
<!--2nd column -->
<div class="col-lg-6">
<!--card content -->
<div class="card shadow mb-4">
<!--card header -->
<div class="card-header py-3">
<h5 class="m-0 font-weight-bold text-primary">Frame Detections</h5>
</div>
<!--card body -->
<div class="text-center p-4" id="detection_frames">
<!--no content message-->
<div class="text-center p-2" id="no_detection_message_content">
<span class="font-italic">No frame is selected</span>
</div>
<div class="text-left m-3" id="detection_number_area" hidden>
<p>No of detections: <span id="no_of_detections"></span></p>
</div>
<!--the detection loader -->
<div class="text-center p-2" id="detection_loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}"
alt="Loader">
</div>
</div>
</div>
<!--detection person card -->
<div class="card shadow mb-4">
<!--card header -->
<div class="card-header py-3">
<h5 class="m-0 font-weight-bold text-primary">Detected Students (by emotion
type)</h5>
</div>
<!--card body -->
<div class="text-center p-4" id="detection_students">
<!--activity type line -->
<div class="text-center p-2" id="activity_type" hidden>
<p>Activity Type: <span class="font-weight-bold" id="activity_type_text"></span>
</p>
</div>
<!--no content message-->
<div class="text-center p-2" id="no_detection_student_content">
<span class="font-italic">No activity type is selected</span>
</div>
<!--the detection student loader -->
<div class="text-center p-2" id="detection_student_loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}"
alt="Loader">
</div>
</div>
</div>
</div>
{# <div class="col-lg-6">#}
{# <!--card content -->#}
{# <div class="card shadow mb-4">#}
{# <!--card header -->#}
{# <div class="card-header py-3">#}
{# <h5 class="m-0 font-weight-bold text-primary">Frame Detections</h5>#}
{# </div>#}
{##}
{# <!--card body -->#}
{# <div class="text-center p-4" id="detection_frames">#}
{##}
{# <!--no content message-->#}
{# <div class="text-center p-2" id="no_detection_message_content">#}
{# <span class="font-italic">No frame is selected</span>#}
{# </div>#}
{##}
{# <div class="text-left m-3" id="detection_number_area" hidden>#}
{# <p>No of detections: <span id="no_of_detections"></span></p>#}
{# </div>#}
{# <!--the detection loader -->#}
{# <div class="text-center p-2" id="detection_loader" hidden>#}
{# <img src="{% static 'FirstApp/images/ajax-loader.gif' %}"#}
{# alt="Loader">#}
{# </div>#}
{# </div>#}
{# </div>#}
{##}
{# <!--detection person card -->#}
{# <div class="card shadow mb-4">#}
{# <!--card header -->#}
{# <div class="card-header py-3">#}
{# <h5 class="m-0 font-weight-bold text-primary">Detected Students (by emotion#}
{# type)</h5>#}
{# </div>#}
{##}
{# <!--card body -->#}
{# <div class="text-center p-4" id="detection_students">#}
{# <!--activity type line -->#}
{# <div class="text-center p-2" id="activity_type" hidden>#}
{# <p>Activity Type: <span class="font-weight-bold" id="activity_type_text"></span>#}
{# </p>#}
{# </div>#}
{##}
{# <!--no content message-->#}
{# <div class="text-center p-2" id="no_detection_student_content">#}
{# <span class="font-italic">No activity type is selected</span>#}
{# </div>#}
{##}
{# <!--the detection student loader -->#}
{# <div class="text-center p-2" id="detection_student_loader" hidden>#}
{# <img src="{% static 'FirstApp/images/ajax-loader.gif' %}"#}
{# alt="Loader">#}
{# </div>#}
{##}
{# </div>#}
{# </div>#}
{# </div>#}
</div>
......@@ -1281,36 +1280,36 @@
<div class="row p-2">
<!--1st column -->
<div class="col-lg-6">
<!--card -->
<div class="card shadow mb-4">
<!--card header -->
<div class="card-header">
<h5 class="m-0 font-weight-bold text-primary">Evaluated Students</h5>
</div>
<!--card body -->
<div class="card-body" id="evaluation_students">
<!--no content message-->
<div class="text-center p-2" id="no_evaluated_student_content">
<span class="font-italic">Press 'Evaluate' button to evaluate students</span>
</div>
<!--the detection student loader -->
<div class="text-center p-2" id="evaluate_student_loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}"
alt="Loader">
</div>
<!--end of student detection loader -->
</div>
</div>
</div>
{# <div class="col-lg-6">#}
{# <!--card -->#}
{# <div class="card shadow mb-4">#}
{# <!--card header -->#}
{# <div class="card-header">#}
{# <h5 class="m-0 font-weight-bold text-primary">Evaluated Students</h5>#}
{# </div>#}
{##}
{# <!--card body -->#}
{# <div class="card-body" id="evaluation_students">#}
{##}
{# <!--no content message-->#}
{# <div class="text-center p-2" id="no_evaluated_student_content">#}
{# <span class="font-italic">Press 'Evaluate' button to evaluate students</span>#}
{# </div>#}
{##}
{# <!--the detection student loader -->#}
{# <div class="text-center p-2" id="evaluate_student_loader" hidden>#}
{# <img src="{% static 'FirstApp/images/ajax-loader.gif' %}"#}
{# alt="Loader">#}
{# </div>#}
{# <!--end of student detection loader -->#}
{##}
{##}
{# </div>#}
{##}
{# </div>#}
{##}
{##}
{# </div>#}
<!--end of 1st column -->
......
......@@ -73,7 +73,7 @@
let date = e.target.parentNode.parentNode.firstChild.innerHTML;
fetch('http://127.0.0.1:8000/get-lecture-video/?lecturer=' + global_lecturer + '&date=' + date + '&index=' + global_lecturer_subject_index)
fetch('http://127.0.0.1:8000/get-lecture-video-gaze-estimation-availability/?lecturer=' + global_lecturer + '&date=' + date + '&index=' + global_lecturer_subject_index)
.then((res) => res.json())
.then((out) => displayLectureVideoDetails(out, object))
.catch((error) => alert('an error occurred: ' + error));
......@@ -144,17 +144,19 @@
global_video_name = video.video_name;
if (lectureVideo.isActivityFound) {
e.target.parentNode.parentNode.lastChild.innerHTML = '<button type="button" class="btn btn-primary">Results</button>';
if (lectureVideo.isGazeEstimationFound) {
e.target.parentNode.parentNode.lastChild.innerHTML = '<button type="button" class="btn btn-primary" id="result_btn">Results</button>';
} else {
e.target.parentNode.parentNode.lastChild.innerHTML = '<button type="button" class="btn btn-success">Process</button>';
{#e.target.parentNode.parentNode.lastChild.innerHTML = "<span class='font-italic font-weight-bold text-danger'>Needs to be processed</span>";#}
e.target.parentNode.parentNode.lastChild.innerHTML = '<button type="button" class="btn btn-success" id="process_gaze">Process</button>';
}
$('#video_modal').modal();
}
//binding a click event for 'btn-primary' buttons
$(document).on('click', '.btn-primary', function (e) {
$(document).on('click', '#result_btn', function (e) {
//removing the previous frames (if there is any)
$('#main_frames').remove();
......@@ -164,7 +166,7 @@
//hiding the temporary text
$('#temporary_text').attr('hidden', true);
fetch('http://127.0.0.1:8000/get-lecture-activity/?lecture_video_id=' + global_lecture_video_id + '&lecture_video_name=' + global_video_name)
fetch('http://127.0.0.1:8000/get-lecture-gaze-estimation/?lecture_video_id=' + global_lecture_video_id + '&lecture_video_name=' + global_video_name)
.then((res) => res.json())
.then((out) => {
let frames = createFrames(out);
......@@ -179,7 +181,7 @@
});
//displaying the activity percentages in the progress bars
function displayActivity(activity) {
function displayGazeEstimation(gaze) {
//hiding the loader (for the frames)
$('#frame_loader').attr('hidden', true);
......@@ -190,29 +192,31 @@
$('video').attr({'hidden': false, 'src': src});
activity.response.map((act, index) => {
gaze.response.map((act, index) => {
//setting the percentage values
$('#phone_perct').text(act.phone_perct + '%');
$('#talking_perct').text(act.talking_perct + '%');
$('#listening_perct').text(act.listening_perct + '%');
$('#writing_perct').text(act.writing_perct + '%');
$('#looking_up_right_perct').text(act.looking_up_and_right_perct + '%');
$('#looking_up_left_perct').text(act.looking_up_and_left_perct + '%');
$('#looking_down_right_perct').text(act.looking_down_and_right_perct + '%');
$('#looking_down_left_perct').text(act.looking_down_and_left_perct + '%');
$('#looking_front_perct').text(act.looking_front_perct + '%');
//setting the width in the progress bars
$('#phone_width').width(act.phone_perct + '%');
$('#talking_width').width(act.talking_perct + '%');
$('#listening_width').width(act.listening_perct + '%');
$('#writing_width').width(act.writing_perct + '%');
$('#looking_up_right_width').width(act.looking_up_and_right_perct + '%');
$('#looking_up_left_width').width(act.looking_up_and_left_perct + '%');
$('#looking_down_right_width').width(act.looking_down_and_right_perct + '%');
$('#looking_down_left_width').width(act.looking_down_and_left_perct + '%');
$('#looking_front_width').width(act.looking_front_perct + '%');
});
//display the progress bar area
$('.progress_area').attr('hidden', false);
}
//to handle the 'btn-success' (process) button
$(document).on('click', '.btn-success', function (e) {
//to handle the process button
$(document).on('click', '#process_gaze', function (e) {
//sending the POST request to process the lecture activities
fetch('http://127.0.0.1:8000/process-lecture-activity/?lecture_video_name=' + global_video_name + '&lecture_video_id=' + global_lecture_video_id)
//sending the get request to process the lecture gaze estimations
fetch('http://127.0.0.1:8000/process-lecture-gaze-estimation/?lecture_video_name=' + global_video_name + '&lecture_video_id=' + global_lecture_video_id)
.then((res) => res.json())
.then((out) => handleResponse(out.response, e))
.catch((error) => alert('error: ' + error));
......@@ -222,7 +226,7 @@
function handleResponse(response, e) {
//change the button, if the response is positive
if (response) {
e.target.parentNode.parentNode.lastChild.innerHTML = '<button type="button" class="btn btn-primary">Results</button>';
e.target.parentNode.parentNode.lastChild.innerHTML = '<button type="button" class="btn btn-primary" id="result_btn" >Results</button>';
}
}
......@@ -236,15 +240,14 @@
//loop through the frames
res.extracted.map((image) => {
let img_src = "";
let len = image.detections.length;
if (count === 0) {
main_frame_content += "<li class='list-group-item text-center' id='image_0'>";
img_src = "<img src='{% static '' %}FirstApp/activity/" + global_video_name + "/" + res.extracted[0].frame + "/" + res.extracted[0].detections[0] + "' width='400' height='400'>";
img_src = "<img src='{% static '' %}FirstApp/gaze/" + global_video_name + "/" + res.extracted[0] + "' width='400' height='400'>";
} else {
main_frame_content += "<li class='list-group-item other-frames' id='image_" + count + "' hidden>";
img_src = "<img src='{% static '' %}FirstApp/activity/" + global_video_name + "/" + image.frame + "/" + image.detections[len - 1] + "' class='img-link' width='400' height='400'>";
img_src = "<img src='{% static '' %}FirstApp/gaze/" + global_video_name + "/" + image + "' class='img-link' width='400' height='400'>";
}
......@@ -261,12 +264,176 @@
$('#myActivityRange').attr({'min': 0, 'max': count});
//display the progress bars
displayActivity(res);
displayGazeEstimation(res);
return main_frame_content;
}
//to handle the 'integrate' modal
$('#integrate_activity').click(function () {
//define the student video src
let video_src = "{% static '' %}FirstApp/videos/" + global_video_name;
//assign the video src
$('#student_video').attr('src', video_src);
$('#integrate_modal').modal();
//fetch data from the API
fetch('http://127.0.0.1:8000/get-lecture-gaze-estimation-for-frame/?video_name=' + global_video_name)
.then((res) => res.json())
.then((out) => displayGazeEstimationForFrame(out.response))
.catch((err) => alert('error: ' + err));
});
//this function will load the activity recognition for frames
function displayGazeEstimationForFrame(response) {
//hide the loader
$('#student_video_progress_loader').attr('hidden', true);
//show the progress bars
$('#student_video_progress').attr('hidden', false);
//creating the html string
let htmlString = "";
//creating the html string, iteratively
response.map((frame) => {
let frame_name = frame.frame_name;
let look_up_right = Math.round(frame.head_up_right_perct, 0);
let look_up_left = Math.round(frame.head_up_left_perct, 0);
let look_down_right = Math.round(frame.head_down_right_perct, 0);
let look_down_left = Math.round(frame.head_down_left_perct, 0);
let look_front = Math.round(frame.head_front_perct, 0);
//append to the html string
//looking up and right
htmlString += "<div class='progress_area' id='progress_" +frame_name+ "' hidden>";
htmlString += "<h4 class='small font-weight-bold'>Looking up and right</h4>";
htmlString += "<span class='float-right' id='look_up_right_instant_" +frame_name+ "'>" +look_up_right+ "%</span>";
htmlString += "<div class='progress mb-4'>";
htmlString += "<div class='progress-bar bg-warning' role='progressbar' id='look_up_right_instant_value_" +frame_name+ "' style='width: " +look_up_right+ "%' aria-valuenow='40' aria-valuemin='0' aria-valuemax='100'></div>";
htmlString += "</div>";
//looking up and left
htmlString += "<h4 class='small font-weight-bold'>Looking up and left</h4>";
htmlString += "<span class='float-right' id='look_up_left_instant_" +frame_name+ "'>" +look_up_left+ "%</span>";
htmlString += "<div class='progress mb-4'>";
htmlString += "<div class='progress-bar' role='progressbar' id='look_up_left_instant_value_" +frame_name+ "' style='width: " +look_up_left+ "%' aria-valuenow='0' aria-valuemin='0' aria-valuemax='100'></div>";
htmlString += "</div>";
//looking down and right
htmlString += "<h4 class='small font-weight-bold'>Looking down and right</h4>";
htmlString += "<span class='float-right' id='look_down_right_instant_" +frame_name+ "'>" +look_down_right+ "%</span>";
htmlString += "<div class='progress mb-4'>";
htmlString += "<div class='progress-bar bg-info' role='progressbar' id='look_down_right_instant_value_" +frame_name+ "' style='width: " +look_down_right+ "%' aria-valuenow='80' aria-valuemin='0' aria-valuemax='100'></div>";
htmlString += "</div>";
//looking down and left
htmlString += "<h4 class='small font-weight-bold'>Looking down and left</h4>";
htmlString += "<span class='float-right' id='look_down_left_instant_" +frame_name+ "'>" +look_down_left+ "%</span>";
htmlString += "<div class='progress mb-4'>";
htmlString += "<div class='progress-bar bg-info' role='progressbar' id='look_down_left_instant_value_" +frame_name+ "' style='width: " +look_down_left+ "%' aria-valuenow='80' aria-valuemin='0' aria-valuemax='100'></div>";
htmlString += "</div>";
//looking front
htmlString += "<h4 class='small font-weight-bold'>Looking front</h4>";
htmlString += "<span class='float-right' id='look_front_instant_" +frame_name+ "'>" +look_front+ "%</span>";
htmlString += "<div class='progress mb-4'>";
htmlString += "<div class='progress-bar bg-info' role='progressbar' id='look_front_instant_value_" +frame_name+ "' style='width: " +look_front+ "%' aria-valuenow='80' aria-valuemin='0' aria-valuemax='100'></div>";
htmlString += "</div>";
//ending the progress area
htmlString += "</div>";
});
//append the html
$('#student_video_column').append(htmlString);
}
//to handle the 'integrate' play button
$('#play_integrate_button').click(function () {
let video = $('video')[0];
let test_video = document.getElementsByTagName('video')[0];
let play_class = 'btn btn-outline-danger play';
let pause_class = 'btn btn-outline-danger pause';
let count = 0;
let classes = $(this).attr('class');
let video_interval = setInterval(() => {
{#let talking_number = Math.round(Math.random() * 100, 0);#}
{#let phone_number = Math.round(Math.random() * 100, 0);#}
{#let note_number = Math.round(Math.random() * 100, 0);#}
{#let listening_number = Math.round(Math.random() * 100, 0);#}
//get the relevant progress area
let progress_area = "progress_frame-" + count;
let progress_area_id = "#" + progress_area;
//find the corresponding progress area
let progress_area_html = document.getElementById(progress_area);
//display the retrieved progress area
$(progress_area_id).attr('hidden', false);
//replace the current progress area with the selected one
$('#student_video_progress').html(progress_area_html);
//increment the count
count++;
//setting the values
{#$('#looking_up_right_instant_perct').text(talking_number + '%');#}
{#$('#looking_up_left_instant_perct').text(phone_number + '%');#}
{#$('#looking_down_right_instant_perct').text(note_number + '%');#}
{#$('#looking_down_left_instant_perct').text(listening_number + '%');#}
{#$('#looking_front_instant_perct').text(listening_number + '%');#}
{##}
{#//setting the width#}
{#$('#talking_instant_value').width(talking_number + '%');#}
{#$('#phone_checking_instant_value').width(phone_number + '%');#}
{#$('#note_taking_instant_value').width(note_number + '%');#}
{#$('#listening_instant_value').width(listening_number + '%');#}
}, 33);
//check for the current class
if (classes === play_class) {
$(this).text('Pause');
$(this).attr('class', pause_class);
video.play();
} else if (classes === pause_class) {
$(this).text('Play');
$(this).attr('class', play_class);
video.pause();
}
//function to do when the video is paused
//function to do when the video is ended
video.onended = function (e) {
//stop changing the activity values
clearInterval(video_interval);
}
});
//declaring the variable for setInterval function
let timeVar = null;
......@@ -422,10 +589,9 @@
if (student_count === 0) {
images += "<li class='list-group-item frame-0' id='image_0_" +title+ "'>";
}
else {
images += "<li class='list-group-item other-student-frames' id='image_" +student_count+ "_" +title+ "' hidden>";
images += "<li class='list-group-item frame-0' id='image_0_" + title + "'>";
} else {
images += "<li class='list-group-item other-student-frames' id='image_" + student_count + "_" + title + "' hidden>";
}
images += "<img src='{% static '' %}FirstApp/Activity/" + global_video_name + "/" + frame.frame + "/" + student + "' width='200' height='200'>";
......@@ -443,10 +609,10 @@
htmlString += "<div class='slidecontainer'>";
htmlString += "<div class='row m-3'></div>";
htmlString += "<div class='row'>";
htmlString += "<span><i class='fas fa-play play-pause-icon-student-frames' id='icon_" +title+ "'></i></span>";
htmlString += "<span><i class='fas fa-play play-pause-icon-student-frames' id='icon_" + title + "'></i></span>";
htmlString += "</div>";
htmlString += "<input type='range' min='1' max='100' value='0' class='slider' id='slider_" +title+ "'>";
htmlString += "<p>No of frames: <span id='demo_" +title+ "'></span></p>";
htmlString += "<input type='range' min='1' max='100' value='0' class='slider' id='slider_" + title + "'>";
htmlString += "<p>No of frames: <span id='demo_" + title + "'></span></p>";
htmlString += "</div>";
htmlString += "</div>";
});
......@@ -500,7 +666,7 @@
output.innerHTML = new_slider_value.toString();
let selectedImage = '#image_' +Number(value)+ '_' + title;
let selectedImage = '#image_' + Number(value) + '_' + title;
//displaying the relevant image
$('#image_0_' + title).html($(selectedImage).html());
......@@ -707,53 +873,66 @@
<!--this area will display the progress bars -->
<div class="progress_area" hidden>
<!--talking with friends -->
<!--Looking up and right -->
<a href="#" class="btn btn-link labels" data-number="1">
<h4 class="small font-weight-bold">Talking with friends</h4>
<h4 class="small font-weight-bold">Looking up and right</h4>
</a>
<span class="float-right" id="talking_perct">40%</span>
<span class="float-right" id="looking_up_right_perct">40%</span>
<div class="progress mb-4">
<div class="progress-bar bg-danger" role="progressbar"
id="talking_width"
id="looking_up_right_width"
style="width: 20%"
aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--phone checking -->
<!--looking up and left -->
<a href="#" class="btn btn-link labels" data-number="0">
<h4 class="small font-weight-bold">Phone checking</h4>
<h4 class="small font-weight-bold">Looking up and left</h4>
</a>
<span class="float-right" id="phone_perct">45%</span>
<span class="float-right" id="looking_up_left_perct">45%</span>
<div class="progress mb-4">
<div class="progress-bar bg-warning" role="progressbar"
id="phone_width"
id="looking_up_left_width"
style="width: 40%"
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--note taking -->
<!--looking down and right -->
<a href="#" class="btn btn-link labels" data-number="2">
<h4 class="small font-weight-bold">Writing</h4>
<h4 class="small font-weight-bold">Looking down and right</h4>
</a>
<span class="float-right" id="writing_perct">50%</span>
<span class="float-right" id="looking_down_right_perct">50%</span>
<div class="progress mb-4">
<div class="progress-bar" role="progressbar" id="writing_width"
<div class="progress-bar" role="progressbar"
id="looking_down_right_width"
style="width: 60%"
aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--listening-->
<!--Looking down and left-->
<a href="#" class="btn btn-link labels">
<h4 class="small font-weight-bold">Looking down and left</h4>
</a>
<span class="float-right" id="looking_down_left_perct">60%</span>
<div class="progress mb-4">
<div class="progress-bar bg-info" role="progressbar"
id="looking_down_left_width" style="width: 80%"
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--Looking front-->
<a href="#" class="btn btn-link labels">
<h4 class="small font-weight-bold">Listening</h4>
<h4 class="small font-weight-bold">Looking Front</h4>
</a>
<span class="float-right" id="listening_perct">60%</span>
<span class="float-right" id="looking_front_perct">60%</span>
<div class="progress mb-4">
<div class="progress-bar bg-info" role="progressbar"
id="listening_width" style="width: 80%"
id="looking_front_width" style="width: 80%"
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
<!-- end of progress area -->
</div>
......@@ -813,55 +992,29 @@
<!--2nd column -->
<div class="col-lg-6">
<!--card content -->
<div class="card shadow mb-4">
<!--card header -->
<div class="card-header py-3">
<h5 class="m-0 font-weight-bold text-primary">Frame Detections</h5>
</div>
<!--card body -->
<div class="text-center p-4" id="detection_frames">
<!--no content message-->
<div class="text-center p-2" id="no_detection_message_content">
<span class="font-italic">No frame is selected</span>
</div>
<div class="text-left m-3" id="detection_number_area" hidden>
<p>No of detections: <span id="no_of_detections"></span></p>
</div>
<!--the detection loader -->
<div class="text-center p-2" id="detection_loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}"
alt="Loader">
</div>
</div>
</div>
<!--detection person card -->
<!--card -->
<div class="card shadow mb-4">
<!--card header -->
<div class="card-header py-3">
<h5 class="m-0 font-weight-bold text-primary">Detected Students</h5>
<div class="card-header">
<h5 class="m-0 font-weight-bold text-primary">Integrated Evaluation</h5>
</div>
<!--card body -->
<div class="text-center p-4" id="detection_students">
<!--no content message-->
<div class="text-center p-2" id="no_detection_student_content">
<span class="font-italic">No activity type is selected</span>
<div class="card-body">
<div class="text-center" id="integrate_message">
<span class="font-italic">The integrated version student and lecturer evaluations will display here.</span>
</div>
<!--the detection student loader -->
<div class="text-center p-2" id="detection_student_loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}"
alt="Loader">
<!--button -->
<div class="text-right m-4">
<button type="button" class="btn btn-outline-success" id="integrate_activity">
Process
</button>
</div>
</div>
</div>
</div>
<!--end of 2nd column -->
</div>
......@@ -943,6 +1096,157 @@
</div>
</div>
</div>
<!-- end of logout modal -->
<!--integrate modal -->
<div class="modal fade" id="integrate_modal" tabindex="-1" role="dialog" aria-labelledby="integrate_modal">
<div class="modal-dialog" style="max-width: 1300px">
<div class="modal-content">
<!--modal header -->
<div class="modal-header">
<h4 class="modal-title">Integrated Version</h4>
</div>
<!--modal body -->
<div class="modal-body">
<div class="container-fluid">
<div class="row">
<!--1st column -->
<div class="col-md-6" id="student_video_column" style="border-right: 1px solid black">
<div class="text-center">
<span class="h3 font-italic font-weight-bold">Student Behavior</span>
</div>
<!--display student video -->
<div class="text-center m-3" id="student_video_section">
<video width="500" height="300" id="student_video" controls>
<source src="#"
type="video/mp4">
Your browser does not support the video tag.
</video>
</div>
<!--end of student video section -->
<!-- ajax loader section -->
<div class="text-center mt-3" id="student_video_progress_loader">
<img src="{% static 'FirstApp/images/ajax-loader-1.gif' %}" alt="loader">
</div>
<!--progress bar section -->
<div class="progress_area" id="student_video_progress" hidden>
<!--Looking up and right -->
<a href="#" class="btn btn-link labels" data-number="1">
<h4 class="small font-weight-bold">Looking up and right</h4>
</a>
<span class="float-right" id="looking_up_right_instant_perct">40%</span>
<div class="progress mb-4">
<div class="progress-bar bg-danger" role="progressbar"
id="looking_up_right_instant_width"
style="width: 20%"
aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--looking up and left -->
<a href="#" class="btn btn-link labels" data-number="0">
<h4 class="small font-weight-bold">Looking up and left</h4>
</a>
<span class="float-right" id="looking_up_left_instant_perct">45%</span>
<div class="progress mb-4">
<div class="progress-bar bg-warning" role="progressbar"
id="looking_up_left_instant_width"
style="width: 40%"
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--looking down and right -->
<a href="#" class="btn btn-link labels" data-number="2">
<h4 class="small font-weight-bold">Looking down and right</h4>
</a>
<span class="float-right" id="looking_down_right_instant_perct">50%</span>
<div class="progress mb-4">
<div class="progress-bar" role="progressbar" id="looking_down_right_instant_width"
style="width: 60%"
aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--Looking down and left-->
<a href="#" class="btn btn-link labels">
<h4 class="small font-weight-bold">Looking down and left</h4>
</a>
<span class="float-right" id="looking_down_left_instant_perct">60%</span>
<div class="progress mb-4">
<div class="progress-bar bg-info" role="progressbar"
id="looking_down_left_instant_width" style="width: 80%"
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--Looking front-->
<a href="#" class="btn btn-link labels">
<h4 class="small font-weight-bold">Looking Front</h4>
</a>
<span class="float-right" id="looking_front_instant_perct">60%</span>
<div class="progress mb-4">
<div class="progress-bar bg-info" role="progressbar"
id="looking_front_instant_width" style="width: 80%"
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
<!--end of progress bar section -->
</div>
<!--end of 1st column -->
<!--2nd column -->
<div class="col-md-6">
<div class="text-center">
<span class="h3 font-italic font-weight-bold">Lecturer Performance</span>
</div>
<!--display lecture video -->
<div class="text-center m-3" id="lecturer_video_section">
<!--temporary text -->
<div class="text-center" id="temp_lecturer_text">
<span class="font-italic">No video was found</span>
</div>
{# <video width="500" height="300" id="lecturer_video" controls>#}
{# <source src="#"#}
{# type="video/mp4">#}
{# Your browser does not support the video tag.#}
{# </video>#}
</div>
<!--end of lecture video section -->
</div>
<!--end of 2nd column -->
</div>
<!--end of 1st row -->
<!--2nd row -->
<div class="row">
<!--play button -->
<div class="col-md-12">
<div class="text-center p-3">
<button type="button" class="btn btn-outline-danger play"
id="play_integrate_button">Play
</button>
</div>
</div>
</div>
<!--end of 2nd row -->
</div>
</div>
<!-- modal footer -->
<div class="modal-footer">
<button type="button" data-dismiss="modal" class="btn btn-danger text-white">Close</button>
</div>
</div>
</div>
</div>
<!--end of integrate modal -->
{% endblock %}
</body>
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SLPES</title>
<link rel="shortcut icon" href="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/images/favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link rel="stylesheet" href="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/css/sb-admin-2.min.css" type="text/css">
<link rel="stylesheet" href="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/css/slider.css" type="text/css">
<link href="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/vendor/fontawesome-free/css/all.min.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 rel="stylesheet" href="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/css/all.min.css" type="text/css">
<link href="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet" type="text/css">
</head>
<body id="page-top">
<!-- main content -->
<div id="wrapper">
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<!--form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form-->
<!-- logo -->
<div id="logo" class="text-left">
<img src="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/images/logo.PNG" alt="Logo" width="80" height="60">
</div>
<div class="m-4">
<h5>Student and Lecturer</h5>
<h5>Performance Enhancement System</h5>
</div>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
{# <button class="btn btn-primary" type="button">#}
{# <i class="fas fa-search fa-sm"></i>#}
{# </button>#}
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{# <i class="fas fa-bell fa-fw"></i>#}
<!-- Counter - Alerts -->
{# <span class="badge badge-danger badge-counter">3+</span>#}
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{# <i class="fas fa-envelope fa-fw"></i>#}
<!-- Counter - Messages -->
{# <span class="badge badge-danger badge-counter">7</span>#}
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/fn_BT9fwg_E/60x60"
alt="">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.
</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/AU4VPcFN4LE/60x60"
alt="">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?
</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/CS2uCrpNzJY/60x60"
alt="">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!
</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...
</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<img src="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/images/sliit.png" alt="sliit" width="200" height="70">
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- beginning of container-fluid -->
<div class="container-fluid">
<!-- Page Heading -->
{# <div class="d-sm-flex align-items-center justify-content-between mb-4">#}
{# <h1 class="mb-0 text-gray-800">Activity Recognition</h1>#}
{# </div>#}
<div class="text-center">
<h1 class="mb-0">Activity Recognition</h1>
</div>
<hr class="p-2">
<!--1st row -->
<div class="row">
<!-- 1st column -->
<div class="col-lg-6">
<!-- card -->
<div class="card shadow mb-4 bg-white">
<div class="card-header">
<h5 class="m-0 font-weight-bold text-primary">Lecturer Information</h5>
</div>
<!-- card body -->
<div class="card-body">
<table class="table table-borderless">
<tr>
<td class="font-weight-bold h4">Name</td>
<td>{{ lecturer_name }}</td>
</tr>
<tr>
<td class="font-weight-bold h4">Subject</td>
<td>{{ subject }}</td>
</tr>
<tr>
<td class="font-weight-bold h4">Date</td>
<td>{{ date }}</td>
</tr>
</table>
</div>
</div>
</div>
<!-- end of 1st column -->
<!-- 2nd column -->
<div class="col-lg-6">
<!-- card -->
<div class="card shadow mb-4 bg-white">
<div class="card-header">
<h5 class="m-0 font-weight-bold text-primary">Activity Information</h5>
</div>
<!-- card body -->
<div class="card-body">
<div class="progress_area">
<!--talking with friends -->
<h4 class="small font-weight-bold">Talking with friends</h4>
<span class="float-right" id="talking_perct">40%</span>
<div class="progress mb-4">
<div class="progress-bar bg-danger" role="progressbar"
id="talking_width"
style="width: 20%"
aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--phone checking -->
<h4 class="small font-weight-bold">Phone checking</h4>
<span class="float-right" id="phone_perct">45%</span>
<div class="progress mb-4">
<div class="progress-bar bg-warning" role="progressbar"
id="phone_width"
style="width: 40%"
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--note taking -->
<h4 class="small font-weight-bold">Writing</h4>
<span class="float-right" id="writing_perct">50%</span>
<div class="progress mb-4">
<div class="progress-bar" role="progressbar" id="writing_width"
style="width: 60%"
aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!--listening-->
<h4 class="small font-weight-bold">Listening</h4>
<span class="float-right" id="listening_perct">60%</span>
<div class="progress mb-4">
<div class="progress-bar bg-info" role="progressbar"
id="listening_width" style="width: 80%"
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>
</div>
</div>
<!-- end of 2nd column -->
</div>
<!-- end of 1st row -->
<!-- 2nd row -->
<!-- Area Chart -->
<div class="col-xl-8 col-lg-7">
<div class="card shadow mb-4">
<!-- Card Header - Dropdown -->
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Activity Overview</h6>
<div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
aria-labelledby="dropdownMenuLink">
<div class="dropdown-header">Dropdown Header:</div>
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</div>
</div>
<!-- Card Body -->
<div class="card-body">
<div class="chart-area">
<canvas id="myAreaChart"></canvas>
</div>
</div>
</div>
</div>
<!-- end of 2nd row -->
</div>
<!-- end of container-fluid -->
</div>
<!--end of content -->
</div>
<!--end of content-wrapper -->
</div>
<!--end of wrapper -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous"></script>
<script src="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/vendor/jquery/jquery.js"></script>
<script src="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/vendor/chart.js/Chart.min.js"></script>
<!-- Page level custom scripts -->
<script src="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/js/demo/chart-area-demo.js"></script>
<script src="file:///D:/SLIIT/Year 4/CDAP/project/2020-101/assets/FirstApp/js/demo/chart-pie-demo.js"></script>
</body>
</html>
\ No newline at end of file
......@@ -20,6 +20,9 @@
<link rel="stylesheet" href="{% static 'FirstApp/css/all.min.css' %}">
<link href="{% static 'FirstApp/vendor/datatables/dataTables.bootstrap4.min.css' %}" rel="stylesheet">
<!-- this link will import process workflow CSS -->
<link href="{% static 'FirstApp/css/process-worflow.css' %}" rel="stylesheet" type="text/css">
</head>
{% endblock %}
......@@ -72,7 +75,7 @@
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Components:</h6>
<a class="collapse-item" href="/pose">Pose</a>
{# <a class="collapse-item" href="/pose">Pose</a>#}
<a class="collapse-item" href="/gaze">Gaze</a>
<a class="collapse-item" href="/emotion">Emotion</a>
<a class="collapse-item" href="/activity">Activity</a>
......@@ -89,10 +92,10 @@
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item" href="/extract">Video Extractor</a>
{# <a class="collapse-item" href="/extract">Video Extractor</a>#}
<a class="collapse-item" href="/video_result">Video Results</a>
<a class="collapse-item" href="utilities-animation.html">Animations</a>
<a class="collapse-item" href="utilities-other.html">Other</a>
{# <a class="collapse-item" href="utilities-animation.html">Animations</a>#}
{# <a class="collapse-item" href="utilities-other.html">Other</a>#}
</div>
</div>
</li>
......@@ -100,44 +103,44 @@
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
{# <!-- Heading -->#}
{# <div class="sidebar-heading">#}
{# Addons#}
{# </div>#}
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages" aria-expanded="true" aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="/login">Login</a>
<a class="collapse-item" href="/register">Register</a>
<a class="collapse-item" href="/forgot-password">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="/404">404 Page</a>
<a class="collapse-item" href="/blank">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item">
<a class="nav-link" href="charts.html">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item">
<a class="nav-link" href="/tables">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
{# <li class="nav-item">#}
{# <a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages" aria-expanded="true" aria-controls="collapsePages">#}
{# <i class="fas fa-fw fa-folder"></i>#}
{# <span>Pages</span>#}
{# </a>#}
{# <div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">#}
{# <div class="bg-white py-2 collapse-inner rounded">#}
{# <h6 class="collapse-header">Login Screens:</h6>#}
{# <a class="collapse-item" href="/login">Login</a>#}
{# <a class="collapse-item" href="/register">Register</a>#}
{# <a class="collapse-item" href="/forgot-password">Forgot Password</a>#}
{# <div class="collapse-divider"></div>#}
{# <h6 class="collapse-header">Other Pages:</h6>#}
{# <a class="collapse-item" href="/404">404 Page</a>#}
{# <a class="collapse-item" href="/blank">Blank Page</a>#}
{# </div>#}
{# </div>#}
{# </li>#}
{# <!-- Nav Item - Charts -->#}
{# <li class="nav-item">#}
{# <a class="nav-link" href="charts.html">#}
{# <i class="fas fa-fw fa-chart-area"></i>#}
{# <span>Charts</span></a>#}
{# </li>#}
{##}
{# <!-- Nav Item - Tables -->#}
{# <li class="nav-item">#}
{# <a class="nav-link" href="/tables">#}
{# <i class="fas fa-fw fa-table"></i>#}
{# <span>Tables</span></a>#}
{# </li>#}
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
......@@ -164,144 +167,144 @@
</button>
<!-- Topbar Search -->
<form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
{# <form class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">#}
{# <div class="input-group">#}
{# <input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2">#}
{# <div class="input-group-append">#}
{# <button class="btn btn-primary" type="button">#}
{# <i class="fas fa-search fa-sm"></i>#}
{# </button>#}
{# </div>#}
{# </div>#}
{# </form>#}
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in" aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
{# <li class="nav-item dropdown no-arrow d-sm-none">#}
{# <a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">#}
{# <i class="fas fa-search fa-fw"></i>#}
{# </a>#}
{# <!-- Dropdown - Messages -->#}
{# <div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in" aria-labelledby="searchDropdown">#}
{# <form class="form-inline mr-auto w-100 navbar-search">#}
{# <div class="input-group">#}
{# <input type="text" class="form-control bg-light border-0 small" placeholder="Search for..." aria-label="Search" aria-describedby="basic-addon2">#}
{# <div class="input-group-append">#}
{# <button class="btn btn-primary" type="button">#}
{# <i class="fas fa-search fa-sm"></i>#}
{# </button>#}
{# </div>#}
{# </div>#}
{# </form>#}
{# </div>#}
{# </li>#}
{##}
{# <!-- Nav Item - Alerts -->#}
{# <li class="nav-item dropdown no-arrow mx-1">#}
{# <a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">#}
{# <i class="fas fa-bell fa-fw"></i>#}
{# <!-- Counter - Alerts -->#}
{# <span class="badge badge-danger badge-counter">3+</span>#}
{# </a>#}
{# <!-- Dropdown - Alerts -->#}
{# <div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="alertsDropdown">#}
{# <h6 class="dropdown-header">#}
{# Alerts Center#}
{# </h6>#}
{# <a class="dropdown-item d-flex align-items-center" href="#">#}
{# <div class="mr-3">#}
{# <div class="icon-circle bg-primary">#}
{# <i class="fas fa-file-alt text-white"></i>#}
{# </div>#}
{# </div>#}
{# <div>#}
{# <div class="small text-gray-500">December 12, 2019</div>#}
{# <span class="font-weight-bold">A new monthly report is ready to download!</span>#}
{# </div>#}
{# </a>#}
{# <a class="dropdown-item d-flex align-items-center" href="#">#}
{# <div class="mr-3">#}
{# <div class="icon-circle bg-success">#}
{# <i class="fas fa-donate text-white"></i>#}
{# </div>#}
{# </div>#}
{# <div>#}
{# <div class="small text-gray-500">December 7, 2019</div>#}
{# $290.29 has been deposited into your account!#}
{# </div>#}
{# </a>#}
{# <a class="dropdown-item d-flex align-items-center" href="#">#}
{# <div class="mr-3">#}
{# <div class="icon-circle bg-warning">#}
{# <i class="fas fa-exclamation-triangle text-white"></i>#}
{# </div>#}
{# </div>#}
{# <div>#}
{# <div class="small text-gray-500">December 2, 2019</div>#}
{# Spending Alert: We've noticed unusually high spending for your account.#}
{# </div>#}
{# </a>#}
{# <a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>#}
{# </div>#}
{# </li>#}
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/fn_BT9fwg_E/60x60" alt="">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/AU4VPcFN4LE/60x60" alt="">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/CS2uCrpNzJY/60x60" alt="">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60" alt="">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
{# <li class="nav-item dropdown no-arrow mx-1">#}
{# <a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">#}
{# <i class="fas fa-envelope fa-fw"></i>#}
{# <!-- Counter - Messages -->#}
{# <span class="badge badge-danger badge-counter">7</span>#}
{# </a>#}
{# <!-- Dropdown - Messages -->#}
{# <div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="messagesDropdown">#}
{# <h6 class="dropdown-header">#}
{# Message Center#}
{# </h6>#}
{# <a class="dropdown-item d-flex align-items-center" href="#">#}
{# <div class="dropdown-list-image mr-3">#}
{# <img class="rounded-circle" src="https://source.unsplash.com/fn_BT9fwg_E/60x60" alt="">#}
{# <div class="status-indicator bg-success"></div>#}
{# </div>#}
{# <div class="font-weight-bold">#}
{# <div class="text-truncate">Hi there! I am wondering if you can help me with a problem I've been having.</div>#}
{# <div class="small text-gray-500">Emily Fowler · 58m</div>#}
{# </div>#}
{# </a>#}
{# <a class="dropdown-item d-flex align-items-center" href="#">#}
{# <div class="dropdown-list-image mr-3">#}
{# <img class="rounded-circle" src="https://source.unsplash.com/AU4VPcFN4LE/60x60" alt="">#}
{# <div class="status-indicator"></div>#}
{# </div>#}
{# <div>#}
{# <div class="text-truncate">I have the photos that you ordered last month, how would you like them sent to you?</div>#}
{# <div class="small text-gray-500">Jae Chun · 1d</div>#}
{# </div>#}
{# </a>#}
{# <a class="dropdown-item d-flex align-items-center" href="#">#}
{# <div class="dropdown-list-image mr-3">#}
{# <img class="rounded-circle" src="https://source.unsplash.com/CS2uCrpNzJY/60x60" alt="">#}
{# <div class="status-indicator bg-warning"></div>#}
{# </div>#}
{# <div>#}
{# <div class="text-truncate">Last month's report looks great, I am very happy with the progress so far, keep up the good work!</div>#}
{# <div class="small text-gray-500">Morgan Alvarez · 2d</div>#}
{# </div>#}
{# </a>#}
{# <a class="dropdown-item d-flex align-items-center" href="#">#}
{# <div class="dropdown-list-image mr-3">#}
{# <img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60" alt="">#}
{# <div class="status-indicator bg-success"></div>#}
{# </div>#}
{# <div>#}
{# <div class="text-truncate">Am I a good boy? The reason I ask is because someone told me that people say this to all dogs, even if they aren't good...</div>#}
{# <div class="small text-gray-500">Chicken the Dog · 2w</div>#}
{# </div>#}
{# </a>#}
{# <a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>#}
{# </div>#}
{# </li>#}
<div class="topbar-divider d-none d-sm-block"></div>
......
......@@ -5,11 +5,11 @@
<!-- Page Wrapper -->
{% block javascript %}
{% load static %}
{% load static %}
<!-- Bootstrap core JavaScript-->
<script src="{% static 'FirstApp/vendor/jquery/jquery.min.js' %}"></script>
<script src="{% static 'FirstApp/vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<!-- Bootstrap core JavaScript-->
<script src="{% static 'FirstApp/vendor/jquery/jquery.min.js' %}"></script>
<script src="{% static 'FirstApp/vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<!-- Page level plugins -->
<script src="{% static 'FirstApp/vendor/datatables/jquery.dataTables.min.js' %}"></script>
......@@ -18,213 +18,290 @@
<!-- Page level custom scripts -->
<script src="{% static 'FirstApp/js/demo/datatables-demo.js' %}"></script>
<!-- Core plugin JavaScript-->
<script src="{% static 'FirstApp/vendor/jquery-easing/jquery.easing.min.js' %}"></script>
<!-- Core plugin JavaScript-->
<script src="{% static 'FirstApp/vendor/jquery-easing/jquery.easing.min.js' %}"></script>
<script type="text/javascript">
var global_subject = '';
var global_lecturer = '';
var global_lecture_video_id = '';
var global_video_name = '';
var global_lecturer_subject_index = 0;
var global_lecture_date = '';
var class1 = 'col-4 smpl-step-step complete';
var class2 = 'col-4 smpl-step-step active';
var class3 = 'col-4 smpl-step-step disabled';
//jquery
$(document).ready(function () {
let folder = '';
//select a particular subject
//select a particular subject
$('input[type=radio]').click(function () {
let subject_id = $(this).attr('id');
global_subject = subject_id;
let lecturer = $(this).attr('data-lecturer');
global_lecturer = lecturer;
let subject_name = $(this).attr('data-name');
$('#timetable').attr('hidden', false);
{#$('#timetable').attr('hidden', true);#}
$('#no_timetable_content').attr('hidden', true);
$('.student-detection-rows').remove();
$('#timetable_body').children().map(function () {
$(this).remove();
});
$('#no_subject_selected').attr('hidden', true);
$('#timetable_caption').text('subject: ' +subject_name);
$('#timetable_caption').text('subject: ' + subject_name);
$('#loader').attr('hidden', false);
//fetching the timetable from the db
fetch('http://127.0.0.1:8000/timetables')
.then((res) => res.json())
.then((out) => createTimeTable(out, subject_id, lecturer))
.catch((error) => alert('this is the error: ' + error))
});
//view the video details
$('.modal-expand').click(function () {
let clicked_id = $(this).attr('id');
folder = clicked_id;
$('input[type=hidden]').each(function () {
let hidden_id = $(this).attr('id');
//this function will display the timetable for the lecturer
function createTimeTable(timetable, subject, lecturer) {
$('#loader').attr('hidden', true);
$('#timetable').attr('hidden', false);
let isTimetableSubject = false;
if (clicked_id === hidden_id) {
let duration = $(this).attr('data-duration');
$('#video_name').text(clicked_id);
$('#video_duration').text(duration);
$('#video_date').text(new Date().toDateString());
timetable.map((item, i) => {
item.timetable.map((table, index) => {
}
});
let lecturer_subject_index_arr = [];
//after data assigning, load the modal
$('#video_modal').modal();
});
//to get the number of subjects taught by the lecturer in a day
table.time_slots.forEach((slot1, ind) => {
let isLecturer = slot1.lecturer.id === Number(lecturer);
//retrieve the lecture details
$('.retrieve').click(function () {
let lecture = $(this).attr('data-id');
if (isLecturer) {
lecturer_subject_index_arr.push(ind);
}
});
//removing the previous frames
$('#main_frames').remove();
//iterating each slot (for a given day)
table.time_slots.forEach((slot, in1) => {
let isLecturer = slot.lecturer.id === Number(lecturer);
let isLecSubject = slot.subject.subject_code === subject;
let message = '';
if (isLecturer && isLecSubject) {
let html = '';
let isProcessPerformed = false;
global_lecturer_subject_index = lecturer_subject_index_arr.findIndex((inner) => inner === in1);
isTimetableSubject = true;
{#check for the lecture video status#}
let date = table.date;
//assign the date
global_lecture_date = date;
fetch('http://127.0.0.1:8000/get-lecture-video/?lecturer=' + global_lecturer + '&date=' + date + '&index=' + global_lecturer_subject_index)
.then((res) => res.json())
.then((out) => {
isProcessPerformed = out.response.isActivityFound;
alert('response: ' + out.response.isActivityFound);
if (isProcessPerformed) {
message = '<td><span class="font-italic font-weight-bold text-primary" id="message">Already processed</span></td>';
} else {
message = '<td><button type="button" class="btn btn-success">Process</button></td>';
}
html += "<tr class='lecture-details'><td class='slot_date'>" + table.date + "</td>"
+ "<td>" + slot.location + "</td>"
+ "<td>" + slot.start_time + "</td>"
+ "<td>" + slot.end_time + "</td>"
+ message
+ "</tr>";
$('#timetable_body').append(html);
})
.catch((error) => alert('an error occurred: ' + error));
}
});
});
$('#error_message').attr('hidden', true);
$('#nav_bar').attr('hidden', true);
$('#tabContentDetails').attr('hidden', true);
if (!isTimetableSubject) {
$('#timetable').attr('hidden', true);
$('#no_timetable_content').attr('hidden', false);
}
//disabling all the 'retrive' buttons
$('.retrieve').each(function () {
$(this).attr('disabled', 'disabled');
});
}
let url = 'http://127.0.0.1:8000/videoExtract/?folder_name=' + lecture;
//retrieve frames
fetch(url)
.then((res) => res.json())
.then((out) => {
//create the frames
let frameHTML = createFrames(out.response, lecture);
return frameHTML;
})
.then((obj) => {
//after loading the frames, display the rest of the images
$('#loader').attr('hidden', false);
setTimeout(() => {
$('#nav_bar').attr('hidden', false);
$('#tabContentDetails').attr('hidden', false);
$('#loader').attr('hidden', true);
//enabling the 'retrive' buttons
$('.retrieve').each(function () {
$(this).removeAttr('disabled');
});
}, 65000);
{#$('#nav_bar').attr('hidden', false);#}
{#$('#tabContentDetails').attr('hidden', false);#}
//load the frames
$('#emotion_frames').prepend(obj);
})
.catch((error) => {
$('#error_message').attr('hidden', false);
//enabling the 'retrieve' buttons
$('.retrieve').each(function () {
$(this).removeAttr('disabled');
//this function will retrieve the lecture video for a given lecture
$(document).on('click', '.btn-info', function (e) {
});
});
let clicked_class = e.target.className;
let object = e;
let real_class = clicked_class.split(' ')[1];
real_class = '.' + real_class;
//setting some values
$('#no_content_message').attr('hidden', true);
let date = e.target.parentNode.parentNode.firstChild.innerHTML;
//assign the date
global_lecture_date = date;
fetch('http://127.0.0.1:8000/get-lecture-video/?lecturer=' + global_lecturer + '&date=' + date + '&index=' + global_lecturer_subject_index)
.then((res) => res.json())
.then((out) => displayLectureVideoDetails(out, object))
.catch((error) => alert('an error occurred: ' + error));
});
//function to display lecture video details
function displayLectureVideoDetails(lectureVideo, e) {
//creating the frame content
function createFrames(response, folder) {
let main_frame_content = "<div class='row' id='main_frames'>";
main_frame_content += "<ul class='list-group list-group-horizontal'>";
let count = 0;
//loop through the frames
response.map((image) => {
let img_src = "";
//get the lecture video response
let video = lectureVideo.response;
if (count === 0) {
main_frame_content += "<li class='list-group-item text-center' id='image_0'>";
img_src = "<img src='{% static '' %}FirstApp/extracted/" + folder + "/" + response[0].image + "' width='500' height='500'>";
}
else {
main_frame_content += "<li class='list-group-item other-frames' id='image_" +count+ "' hidden>";
img_src = "<img src='{% static '' %}FirstApp/extracted/" + folder + "/" + image.image + "' width='500' height='500'>";
}
$('#video_name').text(video.video_name);
$('#video_duration').text(video.video_length);
$('#video_date').text(video.date);
global_lecture_video_id = video.lecture_video_id;
global_video_name = video.video_name;
main_frame_content += img_src;
main_frame_content += "</li>";
count++;
});
if (lectureVideo.isActivityFound) {
{#e.target.parentNode.parentNode.lastChild.innerHTML = '<span class="font-italic font-weight-bold text-primary" id="message">Already processed</span>';#}
alert('I was found');
} else {
{#e.target.parentNode.parentNode.lastChild.innerHTML = '<button type="button" class="btn btn-success">Process</button>';#}
alert('I am not here');
}
}
main_frame_content += "</ul>";
main_frame_content += "</div>";
// this function simulate the process workflow
$('#simulate_process').click(function () {
//setting the min, max values of the slider
$('#myRange').attr({'min': 0, 'max': count});
return main_frame_content;
}
let classname = $('#step_1').attr('class');
//declaring the variable for setInterval function
let timeVar = null;
setTimeout(() => {
$('#step_1').attr('class', class1)
}, 2000);
//handling the play button
$('#play_pause_icon').click(function () {
//defining the two possible classes
let play_class = "fas fa-play";
let pause_class = "fas fa-pause";
setTimeout(() => {
$('#step_2').attr('class', class1)
}, 4000);
//retrieving the current icon class
let current_class = $(this).attr('class');
setTimeout(() => {
$('#step_3').attr('class', class1)
}, 6000);
//assigning the correct class based on the icon clicked
let new_class = (current_class === play_class) ? pause_class : play_class;
setTimeout(() => {
$('#step_4').attr('class', class1)
}, 8000);
//setting the new class
$(this).attr('class', new_class);
//handling the slider
let slider = document.getElementById("myRange");
let output = document.getElementById("demo");
});
//when the button is playing
if (current_class === play_class) {
timeVar = setInterval(() => {
let value = slider.value;
let new_slider_value = Number(value) + 1;
slider.value = new_slider_value;
output.innerHTML = new_slider_value.toString();
//this function will handle the batch process button
$('.batch_process').click(function () {
let video_id = $(this).attr("data-video-id");
let video_name = $(this).attr("data-video-name");
//display the activity loader
$('#activity_loader').attr("hidden", false);
let selectedImage = '#image_' + Number(value);
global_lecture_video_id = video_id;
global_video_name = video_name;
//displaying the relevant image
$('#image_0').html($(selectedImage).html());
}, 10);
}
//when the button is paused
else if (current_class === pause_class) {
clearInterval(timeVar);
}
//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)
.then((res) => res.json())
.then((out) => handleActivityResponse(out.response))
.catch((error) => alert('error: ' + error));
});
//handling the slider
let slider = document.getElementById("myRange");
let output = document.getElementById("demo");
output.innerHTML = slider.value;
//this is to detect the response gained from activity recognition porcess
function handleActivityResponse(response, e) {
//change the button, if the response is positive
if (response) {
//display the activity process as completed
$('#step_1').attr('class', class1);
slider.oninput = function () {
output.innerHTML = this.value;
let selectedImage = '#image_' + Number(this.value);
//hide the activity loader
$('#activity_loader').hide();
//hide
{#$('#image_0').attr('hidden', true);#}
$('#image_0').html($(selectedImage).html());
//display the emotion loader
$('#emotion_loader').attr('hidden', false);
//setting the selected image
{#$(selectedImage).attr('hidden', false);#}
//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)
.then((res) => res.json())
.then((out) => handleEmotionResponse(out.response))
.catch((error) => alert('error: ' + error));
}
}
//this is to detect the response gained from emotion recognition process
function handleEmotionResponse(response) {
//change the button, if the response is positive
if (response) {
//display the activity process as completed
$('#step_2').attr('class', class1);
//hide the emotion loader
$('#emotion_loader').hide();
//display the gaze loader
$('#gaze_loader').attr('hidden', false);
//sending the get request to process the lecture gaze estimations
fetch('http://127.0.0.1:8000/process-lecture-gaze-estimation/?lecture_video_name=' + global_video_name + '&lecture_video_id=' + global_lecture_video_id)
.then((res) => res.json())
.then((out) => handleGazeResponse(out.response, e))
.catch((error) => alert('error: ' + error));
}
}
//this is to detect the response gained from emotion recognition process
function handleGazeResponse(response) {
//change the button, if the response is positive
if (response) {
//display the activity process as completed
$('#step_3').attr('class', class1);
//hide the activity loader
$('#gaze_loader').hide();
alert('good');
}
}
});
</script>
......@@ -248,488 +325,158 @@
<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Video Results</h1>
<h1 class="h3 mb-0 text-gray-800">Lecture Video Results</h1>
</div>
<!--first row -->
<div class="row p-2">
<!--first column -->
<div class="col-lg-6">
<div class="card shadow mb-4">
<!--card header -->
<div class="card-header py-3">
<h5 class="m-0 font-weight-bold text-primary">Lecturer Subjects</h5>
</div>
<!--card body -->
<div class="card-body">
{% if lecturer_subjects.count == 0 %}
<div class="text-center">
<span class="font-italic">No subjects</span>
</div>
{% else %}
<div class="table-responsive">
<table class="table table-bordered" id="datatable">
<thead>
<tr>
<th></th>
<th>Subject Name</th>
<th>Year</th>
</tr>
</thead>
<tbody>
{% for subject in subjects %}
<tr class="subjects not_clicked" id="{{ subject.0.subject_code }}">
<td>
<div class="radio">
<label><input type="radio" id="{{ subject.0.subject_code }}" name="subject_radio" data-name="{{ subject.0.name }}"></label>
</div>
</td>
<td>{{ subject.0.name}}</td>
<td>{{ subject.0.year }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
</div>
</div>
<!--end of first column -->
<!--second column (timetable column) -->
<div class="col-lg-6">
<div class="col-lg-8" style="overflow-x: scroll">
<div class="card shadow mb-4">
<!--card header -->
<div class="card-header py-3">
<h5 class="m-0 font-weight-bold text-primary">View timetable</h5>
<h5 class="m-0 font-weight-bold text-primary">Waiting List</h5>
</div>
<!--card body -->
<div class="card-body">
<!--loading gif -->
{% if due_lectures.count == 0 %}
<div class="text-center" id="no_subject_selected">
<span class="font-italic">No lecture is to be processed</span>
</div>
{% endif %}
<!--no lecture selected message -->
<div class="text-center" id="no_subject_selected">
<span class="font-italic">No lecture is selected</span>
<div class="text-center" id="loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="Loader">
</div>
<!--no lecture selected message -->
<div class="text-center" id="no_timetable_content" hidden>
<span class="font-italic">Not included in the timetable</span>
</div>
<!--displaying the timetable -->
<table class="table table-striped" id="timetable" hidden>
<caption id="timetable_caption"></caption>
<thead>
<tr>
<th>Date</th>
<th>Hall No.</th>
<th>Time</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
<!--end of first column -->
</div>
<div class="row p-2">
<!--first column-->
<div class="col-lg-6">
<!-- card content -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h5 class="m-0 font-weight-bold text-primary">List of Lecture Videos</h5>
</div>
<div class="card-body">
<table class="table table-bordered">
<table class="table table-striped" id="timetable">
{# <caption id="timetable_caption"></caption>#}
<thead>
<tr>
<th>Video Name</th>
<th>Length</th>
<th></th>
<th>Date</th>
<th>Subject</th>
<th>start time</th>
<th>end time</th>
<th></th>
</tr>
</thead>
<tbody>
{% for video in Videos %}
<tr class="video_row" id="{{ video.name }}" data-duration="{{ video.duration }}">
<td>
{{ video.name }}
</td>
<td>{{ video.duration }}</td>
<td>
<button class="btn btn-link modal-expand" id="{{ video.name }}">View</button>
</td>
<td>
<button class="btn btn-info retrieve" data-id="{{ video.name }}">Retrieve</button>
</td>
<!--<td>
<select name="category" id="select_{{ video.name }}" class="form-control select_cat">
<option value="">-------</option>
<option value="Emotion">Emotion</option>
<option value="Gaze">Gaze</option>
<option value="Activity">Activity</option>
</select>
</td>-->
<!-- to store the video details -->
<td hidden>
<input type="hidden" id="{{ video.name }}" data-duration="{{ video.duration }}">
</td>
</tr>
{% endfor %}
<tbody id="timetable_body">
{% for lecture in due_lectures %}
<tr>
<td class="font-weight-bolder">{{ lecture.date }}</td>
{# <td>{{ lecture.subject }}</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.end_time }}</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>
{# <span class="font-italic font-weight-bolder text-success">Processing</span>#}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<!--second column-->
<div class="col-lg-6">
<!-- card content -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h5 class="m-0 font-weight-bold text-primary">Emotion Detection</h5>
</div>
<div class="card-body">
<!-- no video selected messge -->
<div class="text-center" id="no_content_message">
<p>No content to be displayed</p>
</div>
<!-- error messge -->
<div class="text-center text-danger" id="error_message" hidden>
<p class="font-italic">No frames were found for this video</p>
</div>
<!-- loader -->
<div class="text-center" id="loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="Loading image">
</div>
<!--nav tabs-->
<ul class="nav nav-tabs nav-fill" id="nav_bar" role="tablist" hidden>
<li class="nav-item">
<a class="nav-link active" id="frame-tab" data-toggle="tab" href="#frame" role="tab" aria-controls="frame" aria-selected="true">Frame</a>
</li>
<li class="nav-item">
<a class="nav-link" id="graph-tab" data-toggle="tab" href="#graph" role="tab" aria-controls="graph" aria-selected="false">Graphs</a>
</li>
</ul>
<!--tab content -->
<div class="tab-content" id="tabContentDetails" hidden>
<div class="tab-pane fade show active" id="frame" role="tabpanel" aria-labelledby="home-tab">
<div class="text-center p-4" id="emotion_frames">
<!-- slide container -->
<div class="slidecontainer">
<div class="row">
<div class="col-1">0</div>
<div class="col-9"></div>
<div class="col-2">100</div>
</div>
<!-- play/pause icon -->
<div class="row">
<span><i class="fas fa-play" id="play_pause_icon"></i></span>
</div>
<input type="range" min="1" max="100" value="0" class="slider" id="myRange">
<p>No of frames: <span id="demo"></span></p>
</div>
</div>
</div>
<!-- graph content -->
<div class="tab-pane fade" id="graph" role="tabpanel" aria-labelledby="profile-tab">
<!--card content -->
<div class="card shadow mb-4 p-3">
<!-- Card Header - Dropdown -->
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Revenue Sources</h6>
<div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button"
id="dropdownMenuLink" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
aria-labelledby="dropdownMenuLink">
<div class="dropdown-header">Dropdown Header:</div>
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</div>
</div>
<!-- Card Body -->
<div class="card-body">
<div class="chart-pie pt-4 pb-2">
<canvas id="myPieChart"></canvas>
</div>
<div class="mt-4 text-center small">
<span class="mr-2">
<i class="fas fa-circle text-primary"></i> Direct
</span>
<span class="mr-2">
<i class="fas fa-circle text-success"></i> Social
</span>
<span class="mr-2">
<i class="fas fa-circle text-info"></i> Referral
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!--end of first column -->
</div>
<!-- end of 2nd row -->
<!--3rd row -->
<div class="row p-2">
<!-- progress row -->
<div class="row p-2" id="progress_row">
<!--1st column -->
<!--second column-->
<div class="col-lg-6">
<!--first column-->
<div class="col-lg-12">
<!-- card content -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h5 class="m-0 font-weight-bold text-primary">Gaze Estimation</h5>
<div class="card-header py-3 text-center">
<h5 class="m-0 font-weight-bold text-primary">Process Workflow</h5>
</div>
<div class="card-body">
<!-- no video selected messge -->
<div class="text-center" id="no_content_message_gaze">
<p>No Gaze estimation content to be displayed</p>
</div>
<!-- error message -->
<div class="text-center text-danger" id="error_message_gaze" hidden>
<p class="font-italic">No frames were found for this video</p>
</div>
<!-- loader -->
<div class="text-center" id="loader_gaze" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="Loading image">
</div>
<!--nav tabs-->
<ul class="nav nav-tabs nav-fill" id="nav_bar_gaze" role="tablist" hidden>
<li class="nav-item">
<a class="nav-link active" id="frame-tab_gaze" data-toggle="tab" href="#frame_gaze"
role="tab" aria-controls="frame_gaze" aria-selected="true">Frame</a>
</li>
<li class="nav-item">
<a class="nav-link" id="graph-tab_gaze" data-toggle="tab" href="#graph_gaze"
role="tab" aria-controls="graph_gaze" aria-selected="false">Graphs</a>
</li>
</ul>
<!--tab content -->
<div class="tab-content" id="tabContentDetails_gaze" hidden>
<div class="tab-pane fade show active" id="frame_gaze" role="tabpanel"
aria-labelledby="frame-tab_gaze">
<div class="text-center p-4" id="gaze_frames">
<!-- slide container -->
<div class="slidecontainer_gaze">
<div class="row">
<div class="col-1">0</div>
<div class="col-9"></div>
<div class="col-2">100</div>
</div>
<!-- play/pause icon -->
<div class="row">
<span><i class="fas fa-play" id="play_pause_icon_gaze"></i></span>
</div>
<input type="range" min="1" max="100" value="0" class="slider"
id="myRange_gaze">
<p>No of frames: <span id="demo_gaze"></span></p>
<div class="container">
<div class="row smpl-step" style="border-bottom: 0; min-width: 500px;">
<!-- step 1 -->
<div class="col-4 smpl-step-step disabled" id="step_1">
<div class="text-center smpl-step-num font-weight-bolder">Step 1</div>
<div class="progress">
<div class="progress-bar"></div>
</div>
<a class="smpl-step-icon text-center"><i class="fa fa-chart-line"
style="font-size: 40px; padding-top: 10px; color: white"></i></a>
<div class="smpl-step-info text-center">
<span class="font-italic font-weight-bolder">Perform Activity Recognition</span>
<br />
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="Loader" class="mt-2" id="activity_loader" hidden>
</div>
</div>
</div>
<!-- end of step 1 -->
<!-- graph content -->
<div class="tab-pane fade" id="graph_gaze" role="tabpanel"
aria-labelledby="graph-tab_gaze">
<!--card content -->
<div class="card shadow mb-4 p-3">
<!-- Card Header - Dropdown -->
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Gaze distribution</h6>
<div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button"
id="dropdownMenuLink" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
aria-labelledby="dropdownMenuLink">
<div class="dropdown-header">Graph options:</div>
<a class="dropdown-item" href="#">Pie</a>
<a class="dropdown-item" href="#">Bar</a>
<div class="dropdown-divider">Column</div>
<a class="dropdown-item" href="#">Line</a>
</div>
</div>
<!-- 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="progress">
<div class="progress-bar"></div>
</div>
<!-- Card Body -->
<div class="card-body">
<div class="chart-pie pt-4 pb-2">
<canvas id="myPieChart_gaze"></canvas>
</div>
<div class="mt-4 text-center small">
<span class="mr-2">
<i class="fas fa-circle text-primary"></i> Direct
</span>
<span class="mr-2">
<i class="fas fa-circle text-success"></i> Social
</span>
<span class="mr-2">
<i class="fas fa-circle text-info"></i> Referral
</span>
</div>
<a class="smpl-step-icon text-center"><i class="fa fa-user"
style="font-size: 50px; padding-top: 10px; color: white"></i></a>
<div class="smpl-step-info text-center">
<span class="font-italic font-weight-bolder">Study Student Emotions</span>
<br />
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="Loader" class="mt-2" id="emotion_loader" hidden>
</div>
</div>
<!-- end of step 2 -->
</div>
</div>
</div>
</div>
</div>
<!-- end of gaze column -->
<!-- student activity column -->
<div class="col-lg-6">
<!-- card content -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h5 class="m-0 font-weight-bold text-primary">Student Activity Recognition</h5>
</div>
<div class="card-body">
<!-- no video selected messge -->
<div class="text-center" id="no_content_message_activity">
<p>No Activity Recognition content to be displayed</p>
</div>
<!-- error messge -->
<div class="text-center text-danger" id="error_message_activity" hidden>
<p class="font-italic">No frames were found for this video</p>
</div>
<!-- loader -->
<div class="text-center" id="loader_activity" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="Loading image">
</div>
<!--nav tabs-->
<ul class="nav nav-tabs nav-fill" id="nav_bar_activity" role="tablist" hidden>
<li class="nav-item">
<a class="nav-link active" id="frame-tab_activity" data-toggle="tab" href="#frame_activity" role="tab" aria-controls="frame_activity" aria-selected="true">Frame</a>
</li>
<li class="nav-item">
<a class="nav-link" id="graph-tab_activity" data-toggle="tab" href="#graph_activity" role="tab" aria-controls="graph_activity" aria-selected="false">Graphs</a>
</li>
</ul>
<!--tab content -->
<div class="tab-content" id="tabContentDetails_activity" hidden>
<div class="tab-pane fade show active" id="frame_activity" role="tabpanel" aria-labelledby="frame-tab_activity">
<div class="text-center p-4" id="activity_frames">
<!-- slide container -->
<div class="slidecontainer_activity">
<div class="row">
<div class="col-1">0</div>
<div class="col-9"></div>
<div class="col-2">100</div>
</div>
<!-- play/pause icon -->
<div class="row">
<span><i class="fas fa-play" id="play_pause_icon_activity"></i></span>
</div>
<input type="range" min="1" max="100" value="0" class="slider" id="myRange_activity">
<p>No of frames: <span id="demo_activity"></span></p>
<!-- step 3 -->
<div class="col-4 smpl-step-step disabled" id="step_3">
<div class="text-center smpl-step-num font-weight-bolder">Step 3</div>
<div class="progress">
<div class="progress-bar"></div>
</div>
</div>
</div>
<!-- graph content -->
<div class="tab-pane fade" id="graph_activity" role="tabpanel" aria-labelledby="graph-tab_gaze">
<!--card content -->
<div class="card shadow mb-4 p-3">
<!-- Card Header - Dropdown -->
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Activity Distribution</h6>
<div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button"
id="dropdownMenuLink" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
aria-labelledby="dropdownMenuLink">
<div class="dropdown-header">Graph options:</div>
<a class="dropdown-item" href="#">Pie</a>
<a class="dropdown-item" href="#">Bar</a>
<div class="dropdown-divider">Column</div>
<a class="dropdown-item" href="#">Line</a>
</div>
</div>
</div>
<!-- Card Body -->
<div class="card-body">
<div class="chart-pie pt-4 pb-2">
<canvas id="myPieChart"></canvas>
</div>
<div class="mt-4 text-center small">
<span class="mr-2">
<i class="fas fa-circle text-primary"></i> Direct
</span>
<span class="mr-2">
<i class="fas fa-circle text-success"></i> Social
</span>
<span class="mr-2">
<i class="fas fa-circle text-info"></i> Referral
</span>
</div>
<a class="smpl-step-icon">
<i class="fa fa-eye"
style="font-size: 60px; padding-left: 7px; padding-top: 5px; color: white;"></i>
</a>
<div class="smpl-step-info text-center">
<span class="font-italic font-weight-bolder">See students' Gazes</span>
<br />
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}" alt="Loader" class="mt-2" id="gaze_loader" hidden>
</div>
</div>
<!-- end of step 3 -->
</div>
{# <!-- simulation button row -->#}
{# <div class="row">#}
{# <button type="button" class="btn btn-outline-danger" id="simulate_process">Simulate</button>#}
{# </div>#}
</div>
<!-- end of container -->
</div>
</div>
</div>
<!--end of student activity column -->
<!-- end of 1st column -->
</div>
<!--end of 3rd row -->
<!-- end of progress row -->
</div>
{% endblock %}
......@@ -781,24 +528,24 @@
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="/logout">Logout</a>
</div>
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="/logout">Logout</a>
</div>
</div>
</div>
</div>
{% endblock %}
</body>
......
......@@ -41,6 +41,9 @@ urlpatterns = [
# tables view
path('tables', views.tables),
# test view (delete later)
path('test', views.test),
url(r'^register', views.RegisterViewSet),
# re_path('video/?video_name<str:video_name>', views.video),
url(r'^teachers/', views.teachersList.as_view()),
......@@ -75,7 +78,6 @@ urlpatterns = [
# timetable API
url(r'^timetable', api.FacultyTimetableViewSet.as_view()),
##### VIDEO Section #####
# lecture video API
......@@ -84,7 +86,6 @@ urlpatterns = [
# lecture video API (to retrieve a lecture)
url(r'^get-lecture-video/$', api.GetLectureVideoViewSet.as_view()),
##### ACTIVITIES API #####
# lecture activity API (to retrieve lecture activities)
......@@ -112,6 +113,9 @@ urlpatterns = [
url(r'^get-lecture-activity-individual-student-evaluation/$',
api.GetLectureActivityIndividualStudentEvaluation.as_view()),
# lecture activity report generation
url(r'^lecture-activity-report-generation/$',
api.GenerateActivityReport.as_view()),
###### EMOTION Section #####
# getting lecture emotion record availability
......@@ -133,7 +137,6 @@ urlpatterns = [
# lecture emotion detection for frames API (to retrieve detections for each frame in lecture video)
url(r'^get-lecture-emotion-for-frame/$', api.GetLectureEmotionRecognitionsForFrames.as_view()),
###### POSE Section #####
# lecture video API (for Pose estimation)
url(r'^get-lecture-video-for-pose/$', api.GetLectureVideoForPose.as_view()),
......@@ -147,6 +150,27 @@ urlpatterns = [
# lecture video individual student process pose estimation API (for Pose estimation)
url(r'^process-lecture-video-individual-pose-estimation', api.ProcessIndividualStudentPoseEstimation.as_view()),
##### GAZE Section #####
# lecture video Gaze estimation
url(r'^get-lecture-video-gaze-estimation-availability/$', api.GetLectureGazeEstimationAvailaibility.as_view()),
# process a lecture Gaze estimation
url(r'^process-lecture-gaze-estimation/$', api.ProcessLectureGazeEstimation.as_view()),
# retrieve a Lecture Gaze estimation
url(r'^get-lecture-gaze-estimation/$', api.GetLectureGazeEstimationViewSet.as_view()),
# lecture gaze estimation for frames API (to retrieve detections for each frame in lecture video)
url(r'^get-lecture-gaze-estimation-for-frame/$', api.GetLectureGazeEstimationForFrames.as_view()),
##### VIEW STUDENT BEHAVIOR SUMMARY SECTION #####
# retrieves student behavior summary for specified time period
url(r'^get-student-behavior-summary-for-period/$', api.GetStudentBehaviorSummaryForPeriod.as_view()),
# routers
# path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
......
......@@ -20,7 +20,7 @@ from . logic import video_extraction
from . forms import *
import cv2
import os
import datetime
from datetime import datetime
# hashing
......@@ -113,27 +113,85 @@ class LectureViewSet(APIView):
def hello(request):
username = request.user.username
# retrieve the lecturer
lecturer = request.session['lecturer']
# retrieve the lecturer's timetable slots
lecturer_timetable = FacultyTimetable.objects.filter()
# serialize the timetable
lecturer_timetable_serialized = FacultyTimetableSerializer(lecturer_timetable, many=True)
lecturer_details = []
# loop through the serialized timetable
for timetable in lecturer_timetable_serialized.data:
# retrieve daily timetable
daily_timetable = timetable['timetable']
# loop through the daily timetable
for day_timetable in daily_timetable:
date = ''
lecture_index = 0
# loop through each timeslots
for slots in day_timetable:
if slots == "date":
date = day_timetable[slots]
elif slots == "time_slots":
slot = day_timetable[slots]
# loop through each slot
for lecture in slot:
# check whether the lecturer is the current lecturer
if lecturer == lecture['lecturer']['id']:
lecturer_lecture_details = {}
lecturer_lecture_details['date'] = date
lecturer_lecture_details['start_time'] = lecture['start_time']
lecturer_lecture_details['end_time'] = lecture['end_time']
lecturer_lecture_details['subject_name'] = lecture['subject']['name']
lecturer_lecture_details['index'] = lecture_index
lecturer_lecture_details['lecturer'] = lecture['lecturer']['id']
# append to the lecturer_details
lecturer_details.append(lecturer_lecture_details)
# increment the index
lecture_index += 1
# sorting the dates in lecturer_details list
# for details in lecturer_details:
lecturer_details.sort(key=lambda date: datetime.strptime(str(date['date']), "%Y-%m-%d"), reverse=True)
obj = {'Message': 'Student and Lecturer Performance Enhancement System', 'username': username}
folder = os.path.join(BASE_DIR, os.path.join('static\\FirstApp\\videos'))
videoPaths = [os.path.join(folder, file) for file in os.listdir(folder)]
videos = []
durations = []
for videoPath in videoPaths:
video = Video()
cap = cv2.VideoCapture(videoPath)
fps = cap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS"
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
duration = int(frame_count / fps)
durations.append(duration)
videoName = os.path.basename(videoPath)
# videoName = videos.append(os.path.basename(videoPath))
durationObj = datetime.timedelta(seconds=duration)
video.path = videoPath
video.name = videoName
video.duration = str(durationObj)
videos.append(video)
context = {'object': obj, 'Videos': videos, 'durations': durations, 'template_name': 'FirstApp/template.html'}
#
# for videoPath in videoPaths:
# video = Video()
# cap = cv2.VideoCapture(videoPath)
# fps = cap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS"
# frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# duration = int(frame_count / fps)
# durations.append(duration)
# videoName = os.path.basename(videoPath)
# # videoName = videos.append(os.path.basename(videoPath))
# durationObj = datetime.timedelta(seconds=duration)
# video.path = videoPath
# video.name = videoName
# video.duration = str(durationObj)
# videos.append(video)
context = {'object': obj, 'Videos': videos, 'durations': durations, 'template_name': 'FirstApp/template.html', 'lecturer_details': lecturer_details, "lecturer": lecturer}
return render(request, 'FirstApp/Home.html', context)
def view404(request):
......@@ -302,64 +360,87 @@ def child(request):
# displaying video results
@login_required(login_url='/login')
def video_result(request):
try:
# retrieving data from the db
lecturer = request.session['lecturer']
to_do_lecture_list = []
due_lecture_list = []
lecturer_videos = LectureVideo.objects.filter(lecturer_id=lecturer)
serializer = LectureVideoSerializer(lecturer_videos, many=True)
data = serializer.data
# iterate through the existing lecture videos for the lecturer
for video in data:
video_id = video['id']
date = video['date']
subject = video['subject']['id']
# check whether the video id exist in the Activity Recognition table
lec_activity = LectureActivity.objects.filter(lecture_video_id_id=video_id).exists()
if lec_activity == False:
to_do_lecture_list.append({
"lecturer": lecturer,
"date": date,
"subject": subject,
"video_id": video['id'],
"video_name": video['video_name']
})
# once the lectures that needs to be processed are found out, extract the corresponding timetable details
# retrieve the lecturer's timetable slots
lecturer_timetable = FacultyTimetable.objects.filter()
# serialize the timetable
lecturer_timetable_serialized = FacultyTimetableSerializer(lecturer_timetable, many=True)
# loop through the serialized timetable
for timetable in lecturer_timetable_serialized.data:
# retrieve daily timetable
daily_timetable = timetable['timetable']
# loop through the daily timetable
for day_timetable in daily_timetable:
# print('day timetable" ', day_timetable)
# loop through the to-do lecture list
for item in to_do_lecture_list:
isDate = item['date'] == str(day_timetable['date'])
# isLecturer = item['lecturer'] ==
# check for the particular lecture on the day
if isDate:
slots = day_timetable['time_slots']
# loop through the slots
for slot in slots:
# check for the lecturer and subject
isLecturer = item['lecturer'] == slot['lecturer']['id']
isSubject = item['subject'] == slot['subject']['id']
if isLecturer & isSubject:
obj = {}
obj['date'] = item['date']
obj['subject'] = slot['subject']['subject_code']
obj['subject_name'] = slot['subject']['name']
obj['start_time'] = slot['start_time']
obj['end_time'] = slot['end_time']
obj['video_id'] = item['video_id']
obj['video_name'] = item['video_name']
# append to the list
due_lecture_list.append(obj)
lecturer_subjects = LecturerSubject.objects.filter(lecturer_id_id=lecturer)
lec_sub_serilizer = LecturerSubjectSerializer(lecturer_subjects, many=True)
subject_list = []
subjects = lec_sub_serilizer.data[0]['subjects']
for sub in subjects:
subject = Subject.objects.filter(id=sub)
subject_serialized = SubjectSerializer(subject, many=True)
subject_list.append(subject_serialized.data)
folder = os.path.join(BASE_DIR, os.path.join('static\\FirstApp\\videos'))
videoPaths = [os.path.join(folder, file) for file in os.listdir(folder)]
videos = []
durations = []
# setting up the first video details
first_video_path = videoPaths[0]
first_video = Video()
cap = cv2.VideoCapture(first_video_path)
fps = cap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS"
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
duration = int(frame_count / fps)
videoName = os.path.basename(first_video_path)
durationObj = datetime.timedelta(seconds=duration)
first_video.path = first_video_path
first_video.name = videoName
first_video.duration = str(durationObj)
for videoPath in videoPaths:
video = Video()
cap = cv2.VideoCapture(videoPath)
fps = cap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS"
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
duration = int(frame_count / fps)
durations.append(duration)
videoName = os.path.basename(videoPath)
durationObj = datetime.timedelta(seconds=duration)
video.path = videoPath
video.name = videoName
video.duration = str(durationObj)
videos.append(video)
context = {'Videos': videos, 'firstVideo': first_video, 'durations': durations, 'lecturer_subjects': lecturer_subjects, 'subjects': subject_list,
'template_name': 'FirstApp/template.html'}
except Exception as ex:
except Exception as exc:
print('what is wrong?: ', exc)
return redirect('/500')
return render(request, 'FirstApp/video_results.html', context)
return render(request, "FirstApp/video_results.html",
{"lecturer": lecturer, "due_lectures": due_lecture_list})
# view for emotion page
......@@ -437,6 +518,7 @@ def view500(request):
def tables(request):
return render(request, "FirstApp/tables.html")
@login_required(login_url='/login')
def activity(request):
try:
......@@ -459,4 +541,8 @@ def activity(request):
except Exception as exc:
return redirect('/500')
return render(request, "FirstApp/activity.html", {"lecturer_subjects": lecturer_subjects, "subjects": subject_list, "lecturer": lecturer})
\ No newline at end of file
return render(request, "FirstApp/activity.html", {"lecturer_subjects": lecturer_subjects, "subjects": subject_list, "lecturer": lecturer})
def test(request):
return render(request, "FirstApp/pdf_template.html")
\ No newline at end of file
from django.templatetags.static import static
from django.urls import reverse
from jinja2 import Environment
def environment(**options):
env = Environment(**options)
env.globals.update({
'static': static,
'url': reverse,
})
return env
\ No newline at end of file
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