Commit 1b776b39 authored by I.K Seneviratne's avatar I.K Seneviratne

Merge branch 'monitoring_student_behavior_IT17138000' into 'QA_RELEASE'

Monitoring student behavior it17138000

See merge request !7
parents 865e853d 23d79aeb
......@@ -40,6 +40,15 @@ class Lecturer(models.Model):
return self.lecturer_id
# admin model
class Admin(models.Model):
admin_id = models.CharField(max_length=10)
name = models.CharField(max_length=20)
email = models.EmailField()
def __str__(self):
return self.admin_id
# Lecturer_subject model
class LecturerSubject(models.Model):
lec_subject_id = models.CharField(max_length=10)
......@@ -56,6 +65,12 @@ class LecturerCredentials(models.Model):
password = models.CharField(max_length=15)
# admin credential details
class AdminCredentialDetails(models.Model):
username = models.ForeignKey(Admin, on_delete=models.CASCADE)
password = models.CharField(max_length=15)
# timetable based on daily basis
class DailyTimeTable(models.Model):
slot_id = models.AutoField(auto_created=True, primary_key=True)
......@@ -285,7 +300,7 @@ class LectureEmotionFrameRecognitions(models.Model):
# POSE section
# lecture pose estimation
# lecture gaze estimation
class LectureGazeEstimation(models.Model):
lecture_gaze_id = models.CharField(max_length=10)
lecture_video_id = models.ForeignKey(LectureVideo, on_delete=models.CASCADE)
......
......@@ -12,4 +12,6 @@ admin.site.register(LecturerCredentials)
admin.site.register(FacultyTimetable)
admin.site.register(LectureVideo)
admin.site.register(LectureActivity)
admin.site.register(LectureGazeEstimation)
\ No newline at end of file
admin.site.register(LectureGazeEstimation)
admin.site.register(Admin)
admin.site.register(AdminCredentialDetails)
\ No newline at end of file
......@@ -300,7 +300,6 @@ class LectureActivityProcess(APIView):
LectureActivity(
lecture_activity_id=new_lecture_activity_id,
lecture_video_id_id=lec_video_id,
talking_perct=percentages['talking_perct'],
phone_perct=percentages['phone_perct'],
listening_perct=percentages['listening_perct'],
writing_perct=percentages['writing_perct']
......@@ -473,16 +472,18 @@ class LectureEmotionProcess(APIView):
pass
def save_emotion_report(self, lec_video_id, percentages):
lec_video = LectureVideo.objects.get(lecture_video_id=lec_video_id)
lec_video = LectureVideo.objects.filter(lecture_video_id=lec_video_id)
lec_video_serializer = LectureVideoSerializer(lec_video, many=True)
lec_video_data = lec_video_serializer.data[0]
last_lec_emotion = LectureEmotionReport.objects.order_by('lecture_emotion_id').last()
new_lecture_emotion_id = ig.generate_new_id(last_lec_emotion.lecture_emotion_id)
lecture_video_id = lec_video_data['id']
# creating a new lecture emotion report
LectureEmotionReport(
lecture_emotion_id=new_lecture_emotion_id,
lecture_video_id=lec_video,
lecture_video_id_id=lecture_video_id,
happy_perct=percentages.happy_perct,
sad_perct=percentages.sad_perct,
angry_perct=percentages.angry_perct,
......@@ -685,17 +686,23 @@ class ProcessLectureGazeEstimation(APIView):
pass
def estimate_gaze(self, lec_video_id, percentages):
lec_video = LectureVideo.objects.get(lecture_video_id=lec_video_id)
lec_video = LectureVideo.objects.filter(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)
lec_video_data = lec_video_serializer.data[0]
new_lecture_gaze_id = "LG000001" if (last_lec_gaze is None) else ig.generate_new_id(
last_lec_gaze.lecture_gaze_id)
new_lecture_gaze_primary_id = 1 if (last_lec_gaze is None) else int(last_lec_gaze.id) + 1
# get the video id
lecture_video_id = lec_video_data['id']
# creating a new lecture gaze estimation
LectureGazeEstimation(
id=new_lecture_gaze_primary_id,
lecture_gaze_id=new_lecture_gaze_id,
lecture_video_id=lec_video,
lecture_video_id_id=lecture_video_id,
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'],
......@@ -723,7 +730,7 @@ class GetLectureGazeEstimationViewSet(APIView):
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)
# extracted = hge.getExtractedFrames(lecture_video_name)
lecture_gaze_estimations = LectureGazeEstimation.objects.filter(
lecture_video_id__lecture_video_id=lecture_video_id)
......@@ -731,7 +738,7 @@ class GetLectureGazeEstimationViewSet(APIView):
return Response({
"response": serializer.data,
"extracted": extracted
# "extracted": extracted
})
......
This diff is collapsed.
......@@ -57,4 +57,51 @@ class LecturerCredentialsForm(forms.ModelForm):
fields = '__all__'
widgets = {
'password': forms.PasswordInput()
}
\ No newline at end of file
}
# admin login form
class AdminLoginForm(forms.Form):
# username = forms.CharField(max_length=100)
email = forms.EmailField()
password = forms.CharField(widget=forms.PasswordInput())
def clean(self):
# cleaned_username = self.cleaned_data.get('username')
cleaned_email = self.cleaned_data.get('email')
cleaned_password = self.cleaned_data.get('password')
admin = Admin.objects.get(email=cleaned_email)
# if an admin is already in the system
if (admin):
# retrieve the User object
user = User.objects.get(email=cleaned_email)
is_user = user.check_password(cleaned_password)
# if the password is correct
if (is_user):
# lec_credentials = LecturerCredentials.objects.filter(username_id=lecturer.id)
admin_credentials = AdminCredentialDetails.objects.get(username_id=admin.id)
print('credentials: ', admin_credentials)
# if lecture credentials are already created
if (admin_credentials):
admin_credentials.password = user.password
admin_credentials.save(force_update=True)
else:
LecturerCredentials(
username_id=admin.id,
password=user.password
).save()
else:
raise forms.ValidationError("Username or password is incorrect")
else:
print('the admin does not exist')
raise forms.ValidationError("The admin does not exist")
return super(AdminLoginForm, self).clean()
This diff is collapsed.
This diff is collapsed.
import os
import cv2
import shutil
import datetime
# import datetime
from datetime import timedelta
from FirstApp.MongoModels import *
from FirstApp.serializers import *
......@@ -94,7 +95,7 @@ def getTimeLandmarks(video_name):
THRESHOLD_GAP = 5
# calculating the real duration
real_duration = datetime.timedelta(seconds=(duration+THRESHOLD_GAP))
real_duration = timedelta(seconds=(duration))
# defines the number of seconds included for a frame group
THRESHOLD_TIME = 10
......@@ -112,7 +113,7 @@ def getTimeLandmarks(video_name):
# loop through the threshold gap limit to define the time landmarks
for i in range(THRESHOLD_GAP):
initial_landmark += unit_gap
time_landmark = str(datetime.timedelta(seconds=initial_landmark))
time_landmark = str(timedelta(seconds=initial_landmark))
time_landmark_value = initial_landmark
time_landmarks.append(time_landmark)
time_landmarks_values.append(time_landmark_value)
......@@ -204,6 +205,9 @@ def getFrameLandmarks(video_name, category):
# this section will handle some database operations
def save_time_landmarks(video_name):
# for testing purposes
print('starting the saving time landmarks process')
last_lec_video_time_landmarks = LectureVideoTimeLandmarks.objects.order_by('lecture_video_time_landmarks_id').last()
new_lecture_video_time_landmarks_id = "LVTL00001" if (last_lec_video_time_landmarks is None) else \
ig.generate_new_id(last_lec_video_time_landmarks.lecture_video_time_landmarks_id)
......@@ -233,12 +237,18 @@ def save_time_landmarks(video_name):
new_lec_video_time_landmarks.lecture_video_id_id = lec_video_id
new_lec_video_time_landmarks.time_landmarks = db_time_landmarks
# for testing purposes
print('ending the saving time landmarks process')
new_lec_video_time_landmarks.save()
# this method will save frame landmarks to the database
def save_frame_landmarks(video_name):
# for testing purposes
print('starting the saving frame landmarks process')
# retrieve the previous lecture video frame landmarks details
last_lec_video_frame_landmarks = LectureVideoFrameLandmarks.objects.order_by(
'lecture_video_frame_landmarks_id').last()
......@@ -271,6 +281,9 @@ def save_frame_landmarks(video_name):
new_lec_video_frame_landmarks.save()
# for testing purposes
print('ending the saving frame landmarks process')
# now return the frame landmarks and the frame group dictionary
return frame_landmarks, frame_group_dict
......
# Generated by Django 2.2.11 on 2020-10-20 16:27
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('FirstApp', '0014_lecturegazeframerecognitions'),
]
operations = [
migrations.CreateModel(
name='Admin',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('admin_id', models.CharField(max_length=10)),
('name', models.CharField(max_length=20)),
('email', models.EmailField(max_length=254)),
],
),
migrations.CreateModel(
name='AdminCredentialDetails',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=15)),
('username', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='FirstApp.Admin')),
],
),
migrations.DeleteModel(
name='LecturePoseEstimation',
),
]
{% extends 'FirstApp/template.html' %}
<!DOCTYPE html>
<html lang="en">
<body id="page-top">
<!-- 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">
{% load static %}
<!-- 404 Error Text -->
<div class="text-center">
<div class="error mx-auto" data-text="404">401</div>
<p class="lead text-gray-800 mb-5">Unauthorized access</p>
<p class="text-gray-500 mb-0">It looks like you do not have access to this url</p>
<p class="text-gray-500 mb-0">Please login with the correct user type</p>
<a href="/logout">&larr; Back to Login Page</a>
</div>
</div>
{% endblock %}
<!--end of container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2019</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<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="login.html">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>
......@@ -742,7 +742,7 @@
//to handle the 'integrate' modal
$('#integrate_gaze').click(function () {
$('#integrate_activity').click(function () {
//define the student video src
let video_src = "{% static '' %}FirstApp/videos/" + global_video_name;
......@@ -1215,66 +1215,6 @@
</div>
<!--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 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 -->
......@@ -1292,7 +1232,7 @@
<!--button -->
<div class="text-right m-4">
<button type="button" class="btn btn-outline-success" id="integrate_gaze">
<button type="button" class="btn btn-outline-success" id="integrate_activity">
Process
</button>
</div>
......
{% load static %}
<!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>
<!-- Custom fonts for this template-->
<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="{% static 'FirstApp/css/sb-admin-2.min.css' %}" rel="stylesheet">
</head>
<body class="bg-gradient-primary">
<div class="container">
<!-- Outer Row -->
<div class="row justify-content-center">
<div class="col-xl-10 col-lg-12 col-md-9">
<div class="card o-hidden border-0 shadow-lg my-5">
<div class="card-body p-0">
<!-- Nested Row within Card Body -->
<div class="row">
<div class="col-lg-6 d-none d-lg-block">
<img src="{% static 'FirstApp/images/admin.jpg' %}" width="400" height="600"
alt="No image">
</div>
<div class="col-lg-6">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4">Welcome Back!</h1>
</div>
<!--form -->
<form action="/process-admin-login" method="POST" name="loginForm" class="user">
{% csrf_token %}
<div class="form-group">
<input type="email" name="email" class="form-control form-control-user"
id="exampleInputEmail" aria-describedby="emailHelp"
placeholder="Enter Email Address...">
</div>
<div class="form-group">
<input type="password" name="password" class="form-control form-control-user"
id="exampleInputPassword" placeholder="Password">
<div class="alert alert-danger m-4">{{ message }}</div>
</div>
<div class="form-group">
<div class="custom-control custom-checkbox small">
<input type="checkbox" class="custom-control-input" id="customCheck">
<label class="custom-control-label" for="customCheck">Remember Me</label>
</div>
</div>
<button type="submit" class="btn btn-primary btn-user btn-block">Login</button>
<hr>
</form>
<hr>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 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>
<!-- Core plugin JavaScript-->
<script src="{% static 'FirstApp/vendor/jquery-easing/jquery.easing.min.js' %}"></script>
<!-- Custom scripts for all pages-->
<script src="{% static 'FirstApp/js/sb-admin-2.min.js' %}"></script>
</body>
</html>
......@@ -216,6 +216,7 @@
//to handle the 'btn-success' (process) button
$(document).on('click', '.btn-success', function (e) {
//sending the POST request to process the lecture activities
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())
......
......@@ -66,6 +66,8 @@
Interface
</div>
{% if request.session.user_type == "Lecturer" %}
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="true" aria-controls="collapseTwo">
......@@ -83,6 +85,7 @@
</div>
</li>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseThree" aria-expanded="true" aria-controls="collapseThree">
......@@ -97,6 +100,8 @@
</div>
</li>
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseFour" aria-expanded="true" aria-controls="collapseThree">
<i class="fas fa-fw fa-cog"></i>
......@@ -127,6 +132,8 @@
</div>
</li>
{% endif %}
<!-- Divider -->
<hr class="sidebar-divider">
......@@ -178,6 +185,8 @@
</div>
</ul>
<!-- End of Sidebar -->
<div id="content-wrapper" class="d-flex flex-column">
......
{% load static %}
<!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>
<!-- Custom fonts for this template-->
<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="{% static 'FirstApp/css/sb-admin-2.min.css' %}" rel="stylesheet">
</head>
<body class="bg-gradient-primary">
<div class="container">
<!-- Outer Row -->
<div class="row justify-content-center">
<div class="col-xl-10 col-lg-12 col-md-9">
<div class="card o-hidden border-0 shadow-lg my-5">
<div class="card-body p-0">
<!-- Nested Row within Card Body -->
<div class="row">
<div class="col-lg-6 d-none d-lg-block">
<img src="{% static 'FirstApp/images/user_redirect.png' %}" width="400" height="500"
alt="No image">
</div>
<div class="col-lg-6">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4">Select the user type</h1>
</div>
<!--form -->
<form action="/process-user-redirect" method="POST" name="loginForm" class="user">
{% csrf_token %}
<div class="form-check mx-3">
<input class="form-check-input" type="radio" name="user_type"
id="admin" value="admin" checked>
<label class="form-check-label" for="admin">
Admin
</label>
</div>
<div style="padding-top: 20px">
<div class="form-check mx-3">
<input class="form-check-input" type="radio" name="user_type"
id="lecturer" value="lecturer">
<label class="form-check-label" for="lecturer">
Lecturer
</label>
</div>
<div style="padding-top: 20px">
<button type="submit" class="btn btn-primary btn-user btn-block">Proceed</button>
<hr>
</form>
<hr>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 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>
<!-- Core plugin JavaScript-->
<script src="{% static 'FirstApp/vendor/jquery-easing/jquery.easing.min.js' %}"></script>
<!-- Custom scripts for all pages-->
<script src="{% static 'FirstApp/js/sb-admin-2.min.js' %}"></script>
</body>
</html>
......@@ -14,6 +14,7 @@ urlpatterns = [
path('logout', views.logoutView),
path('register-user', views.register),
path('404', views.view404),
path('401', views.view401),
path('500', views.view500),
path('blank', views.blank),
path('gaze', views.gaze),
......@@ -32,10 +33,20 @@ urlpatterns = [
# video results
path('video_result', views.video_result),
# this is used for login
# this is used to process login
path('process-login', views.loggedInView),
# this is used for login
# this is used to process admin login
path('process-admin-login', views.processAdminLogin),
# this is used for user-redirect processing
path('process-user-redirect', views.processUserRedirect),
# this is used for admin login page
path('admin-login', views.adminLogin),
# this is used for activity
path('activity', views.activity),
# tables view
......@@ -44,6 +55,10 @@ urlpatterns = [
# test view (delete later)
path('test', views.test),
# user direct view
path('user-direct', views.userDirect),
url(r'^register', views.RegisterViewSet),
# re_path('video/?video_name<str:video_name>', views.video),
url(r'^teachers/', views.teachersList.as_view()),
......
This diff is collapsed.
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