Commit bcb44959 authored by SohanDanushka's avatar SohanDanushka

Merge remote-tracking branch 'origin/QA_RELEASE' into db_and_monitoring_IT17097284

parents a22f93b0 28bdfdce
......@@ -168,13 +168,17 @@ class LectureVideoViewSet(APIView):
# serializer = LectureVideoSerializer(data=request.data, many=True)
serializer = LectureVideoSerializer(data=request.data)
# serializer.create(validated_data=request.data)
data = {}
data_ser = {}
if serializer.is_valid(raise_exception=ValueError):
print('valid')
serializer.create(validated_data=request.data)
data = serializer.create(validated_data=request.data)
print('data: ', data)
# data_ser = LectureVideoSerializer(data, many=True)
return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(data, status=status.HTTP_201_CREATED)
# return Response(serializer.error_messages,
......@@ -462,6 +466,7 @@ class GetLectureEmotionReportViewSet(APIView):
lecture_emotions = LectureEmotionReport.objects.filter(lecture_video_id__lecture_video_id=lecture_video_id)
serializer = LectureEmotionSerializer(lecture_emotions, many=True)
print('data: ', serializer.data)
return Response({
"response": serializer.data,
......@@ -1565,3 +1570,80 @@ class TestRandom(APIView):
"response": random
})
# this API will display the upcoming lectures for the lecturer (temporary API)
class DisplayUpcomingLecturesAPI(APIView):
def get(self, request):
lecturer = request.query_params.get('lecturer')
lecturer = int(lecturer)
cur_date = datetime.datetime.now().date()
cur_time = datetime.datetime.now().time()
eligible_start_time = ''
eligible_end_time = ''
subject_id = 0
subject_name = ''
subject_code = ''
# retrieve the faculty timetable
faculty_timetable = FacultyTimetable.objects.all()
# serialize the timetable
faculty_timetable_serialized = FacultyTimetableSerializer(faculty_timetable, many=True)
# get the serialized timetable data
faculty_timetable_serialized_data = faculty_timetable_serialized.data
# iterate through the serialized timetable data
for timetable in faculty_timetable_serialized_data:
# get the 'timetable' field
daily_timetable = timetable['timetable']
# iterate through the 'timetable' field
for day_timetable in daily_timetable:
# get the 'time_slots' field for a given day
time_slots = day_timetable['time_slots']
# iterate through the time slots
for time_slot in time_slots:
# if the lecturer is the currently logged in lecturer
if lecturer == time_slot['lecturer']['id']:
# find the upcoming lecture for the logged-in lecturer
if cur_date == day_timetable['date']:
# get the start and end times
start_time = time_slot['start_time']
end_time = time_slot['end_time']
start_time_list = str(start_time).split(":")
start_time_date = datetime.datetime.now().replace(hour=int(start_time_list[0]), minute=int(start_time_list[1]), second=int(start_time_list[2]))
end_time_list = str(end_time).split(":")
end_time_date = datetime.datetime.now().replace(hour=int(end_time_list[0]), minute=int(end_time_list[1]), second=int(end_time_list[2]))
# check for the upcoming time slot
if (start_time_date.time() > cur_time):
eligible_start_time = start_time_date.time()
eligible_end_time = end_time_date.time()
subject_id = time_slot['subject']['id']
subject_name = time_slot['subject']['name']
subject_code = time_slot['subject']['subject_code']
return Response({
"start_time": eligible_start_time,
"end_time": eligible_end_time,
"subject_id": subject_id,
"subject_name": subject_name,
"subject_code": subject_code,
})
import requests
import json
def batch_process(video_id, video_name):
def student_behavior_batch_process(video_id, video_name):
is_all_processed = False
# call the activity process
activity_resp = requests.get('http://127.0.0.1:8000/process-lecture-activity/?lecture_video_name=' + video_name + '&lecture_video_id=' + video_id)
activity_resp = requests.get('http://127.0.0.1:8000/process-lecture-activity/', params={'lecture_video_name': video_name, 'lecture_video_id': video_id})
# if the activity process is success
if activity_resp.json()['response']:
# call the emotion process
emotion_resp = requests.get('http://127.0.0.1:8000/process-lecture-emotion/?lecture_video_name=', params={'lecture_video_name': video_name, 'lecture_video_id': video_id})
# call the emotion process
emotion_resp = requests.get('http://127.0.0.1:8000/process-lecture-emotion/?lecture_video_name=' + video_name + '&lecture_video_id=' + video_id)
# if the emotion process is success
if emotion_resp.json()['response']:
# call the gaze process
gaze_resp = requests.get('http://127.0.0.1:8000/process-lecture-gaze-estimation/?lecture_video_name=' + video_name + '&lecture_video_id=' + video_id)
# call the gaze process
gaze_resp = requests.get('http://127.0.0.1:8000/process-lecture-gaze-estimation/?lecture_video_name=', params={'lecture_video_name': video_name, 'lecture_video_id': video_id})
# if the gaze estimation process is successful
if gaze_resp.json()['response']:
is_all_processed = True
pass
return is_all_processed
# this method will save the lecture video
def save_student_lecture_video(student_video):
data_dumps = json.dumps(student_video)
headers = {
'Content-Type': 'application/json'
}
# call the API
student_video_save_resp = requests.post('http://127.0.0.1:8000/lecture-video', student_video)
\ No newline at end of file
# student_video_save_resp = requests.post('http://127.0.0.1:8000/lecture-video', student_video)
student_video_save_resp = requests.post(url='http://127.0.0.1:8000/lecture-video', data=data_dumps, headers=headers)
data = student_video_save_resp.json()
return data[0]
if __name__ == '__main__':
# content = {
# "lecturer": 1,
# "subject": 16,
# "date": "2020-12-09",
# "video_name": "Video_test_19.mp4",
# "video_length": "00:45:06"
# }
#
#
# data_dumps = json.dumps(content)
# data_json = json.loads(data_dumps)
#
#
# save_student_lecture_video(content)
student_behavior_batch_process(8, "Video_test_8.mp4")
......@@ -275,6 +275,11 @@ class LectureVideoSerializer(serializers.ModelSerializer):
video_length=video_length
)
# retrieve the created object
created_lecture_video = LectureVideo.objects.filter(lecture_video_id=lecture_video)
create_lecture_video_ser = LectureVideoSerializer(created_lecture_video, many=True)
create_lecture_video_ser_data = create_lecture_video_ser.data
# faculty_data = validated_data.pop('faculty')
# serialized_faculty = FacultySerializer(data=faculty_data)
#
......@@ -294,7 +299,7 @@ class LectureVideoSerializer(serializers.ModelSerializer):
#
# return lecturer
#
return lecture_video
return create_lecture_video_ser_data
return None
......
......@@ -2687,7 +2687,7 @@
</button>
</div>
<div class="modal-body text-center">
<h3 class="font-weight-bold">Student Activity vs. Student Emotions</h3>
<h3 class="font-weight-bold">Student Activity vs. Student Gaze</h3>
<!-- ajax loader -->
<div class="text-center" id="student_activity_gaze_corr_loader" hidden>
......
......@@ -21,6 +21,11 @@
<!-- 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>
<script type="text/javascript">
......@@ -32,12 +37,21 @@
var global_lecture_date = '';
var global_lecturer_video_name = '';
var lecturer_fps = 0;
var lecture_activity_frame_group_percentages = {};
var lecture_video_time_landmarks = [];
var CHART = '';
;
//jquery
$(document).ready(function () {
//disable the 'integrate_activity' button
$('#integrate_activity').hide();
//hide the 'Generate Report' button
{#$('#generate_report_before').hide();#}
$('#generate_report').hide();
//select a particular subject
$('input[type=radio]').click(function () {
let subject_id = $(this).attr('id');
......@@ -76,6 +90,7 @@
let real_class = clicked_class.split(' ')[1];
real_class = '.' + real_class;
let date = e.target.parentNode.parentNode.firstChild.innerHTML;
//assign the date
global_lecture_date = date;
......@@ -161,6 +176,9 @@
$('#generate_report_before').attr('disabled', false);
$('#video_modal').modal();
//display the 'integrate activity' button
$('#integrate_activity').show();
}
//binding a click event for 'btn-primary' buttons
......@@ -254,16 +272,15 @@
//fetch the lecture recorded video name
fetch('http://127.0.0.1:8000/get-lecture-recorded-video-name/?lecturer=' + global_lecturer + '&subject=' + global_subject + '&date=' + global_lecture_date)
.then((res) => res.json())
.then((out) => assignLecturerRecordedVideoName(out))
.catch((err) => alert('error: ' + err));
.then((res) => res.json())
.then((out) => assignLecturerRecordedVideoName(out))
.catch((err) => alert('error: ' + err));
{#global_lecturer_video_name = "Test_1.mp4";#}
{#global_lecturer_video_name = "Test_2.mp4";#}
{#global_lecturer_video_name = "Test_3.mp4";#}
//fetch data from the API
fetch('http://127.0.0.1:8000/get-lecture-activity-for-frame?video_name=' + global_video_name)
.then((res) => res.json())
......@@ -524,6 +541,189 @@
});
//this function will handle the activity 'summary' button
$('#graph-tab').click(function (e) {
//display the graph loader
$('#graph_loader').attr('hidden', false);
//fetch the video time landmark details
fetch('http://127.0.0.1:8000/get-lecture-video-summary-time-landmarks/?video_name=' + global_video_name)
.then((res) => res.json())
.then((out) => assignTimeLandmarks(out.response))
.catch((err) => alert('error: ' + err));
//change the innerHTML of the clicked button
{#e.target.innerHTML = "<span class='font-italic'>Processing</span>";#}
let phone_perct = $('#phone_perct').text().split("%")[0];
let listen_perct = $('#listening_perct').text().split("%")[0];
let note_perct = $('#writing_perct').text().split("%")[0];
//fetch the activity summary details
fetch('http://127.0.0.1:8000/get-lecture-activity-summary/?video_name=' + global_video_name + '&phone_perct=' + phone_perct + '&note_perct=' + note_perct + '&listen_perct=' + listen_perct)
.then((res) => res.json())
.then((out) => activityFrameGroupPercentages(out, e))
.catch((err) => alert('error: ' + err));
});
//this function will assign lecture video time landmarks
function assignTimeLandmarks(response) {
lecture_video_time_landmarks = response;
}
//this function will handle the retrieved activity frame group percentages
function activityFrameGroupPercentages(response, e) {
lecture_activity_frame_group_percentages = response.frame_group_percentages;
let frame_landmarks = response.frame_landmarks;
{#let frame_group_dict = response.frame_group_dict;#}
let activity_labels = response.activity_labels;
let comment_list = response.comments;
//render the chart onto the modal body
renderActivityChart(activity_labels);
}
//this function will call the activity chart function
function renderActivityChart(activity_labels) {
//hide the graph loader
$('#graph_loader').hide();
//get the activity label length
let activity_label_length = activity_labels.length;
let data = [];
//loop through the activity labels
for (let k = 0; k < activity_label_length; k++) {
let label = activity_labels[k];
let datapoints = [];
let count = 0;
//loop through the activity frame groups
for (let key in lecture_activity_frame_group_percentages) {
let frame_group_details = lecture_activity_frame_group_percentages[key];
let activity_perct = frame_group_details[label];
let point = {label: lecture_video_time_landmarks[count], y: activity_perct};
datapoints.push(point);
count++;
}
let obj = {
type: "line",
showInLegend: true,
name: label,
markerType: "square",
{#xValueFormatString: "DD MMM, YYYY",#}
xValueFormatString: "hh:mm:ss",
color: getRandomColor(),
dataPoints: datapoints
};
data.push(obj);
}
CHART = new CanvasJS.Chart("ActivityChartContainer", {
animationEnabled: true,
theme: "light2",
title: {
text: "Student Activity Behavior"
},
axisX: {
title: "Duration",
{#valueFormatString: "DD MMM",#}
valueFormatString: "hh:mm:ss",
crosshair: {
enabled: true,
snapToDataPoint: true
}
},
axisY: {
title: "Percentage",
includeZero: true,
crosshair: {
enabled: true
}
},
toolTip: {
shared: true
},
legend: {
cursor: "pointer",
verticalAlign: "top",
horizontalAlign: "right",
dockInsidePlotArea: true,
itemclick: toogleDataSeries
},
data: data
});
{#chart.render();#}
CHART.render();
//show the 'generate report' button
$('#generate_report').show();
}
//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;
}
//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 method will handle the 'Generate Report' button
$('#generate_report').click(function () {
let script = "<script src='https://canvasjs.com/assets/script/canvasjs.min.js'><\/script>";
CHART.print();
{#var prtContent = document.getElementById("ActivityChartContainer");#}
{#var WinPrint = window.open('', '', 'left=0,top=0,width=800,height=900,toolbar=0,scrollbars=0,status=0');#}
{#var WinPrint = window.open('');#}
{#WinPrint.document.write(prtContent.innerHTML);#}
{#WinPrint.document.write(script);#}
{#WinPrint.document.write('<h1>This is Ishan</h1>');#}
{#WinPrint.document.close();#}
{#WinPrint.focus();#}
{#WinPrint.print();#}
{#WinPrint.close();#}
});
});
</script>
......@@ -548,8 +748,12 @@
<!-- 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>
{# <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>#}
<button type="button" class="btn btn-primary" id="generate_report">Generate Report</button>
{# <button type="button"#}
{# class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm"#}
{# id="generate_report_before"><i#}
{# class="fas fa-download fa-sm text-white-50"></i> Generate Report#}
{# </button>#}
</div>
......@@ -702,18 +906,18 @@
<!--this area will display the progress bars -->
<div class="progress_area mt-4" hidden>
<!--talking with friends -->
<a href="#" class="btn btn-link labels" data-number="1"
data-label="talking-with-friends">
<h4 class="small font-weight-bold">Talking with friends</h4>
</a>
<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>
{# <a href="#" class="btn btn-link labels" data-number="1"#}
{# data-label="talking-with-friends">#}
{# <h4 class="small font-weight-bold">Talking with friends</h4>#}
{# </a>#}
{# <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 -->
<a href="#" class="btn btn-link labels" data-number="0"
......@@ -765,45 +969,44 @@
<!--graph tab -->
<div class="tab-pane fade" id="graph" role="tabpanel"
aria-labelledby="profile-tab">
<!-- graph loader -->
<div class="text-center mt-3" id="graph_loader" hidden>
<img src="{% static 'FirstApp/images/ajax-loader.gif' %}"
alt="Loader">
</div>
<!-- end of graph loader -->
<!--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">Student
Activities</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 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#}
{# Activities</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 id="ActivityChartContainer"
style="height: 370px; max-width: 920px; margin: 0px auto;"></div>
</div>
<!-- End of Card Body -->
</div>
</div>
......@@ -1084,11 +1287,11 @@
type="video/mp4">
Your browser does not support the video tag.
</video>
{# <video width="500" height="300" id="student_video" controls>#}
{# <source src="{% static 'FirstApp/videos/Video_test_2.mp4' %}"#}
{# type="video/mp4">#}
{# Your browser does not support the video tag.#}
{# </video>#}
{# <video width="500" height="300" id="student_video" controls>#}
{# <source src="{% static 'FirstApp/videos/Video_test_2.mp4' %}"#}
{# type="video/mp4">#}
{# Your browser does not support the video tag.#}
{# </video>#}
</div>
<!--end of student video section -->
......@@ -1155,10 +1358,10 @@
<!--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>#}
{# <!--temporary text -->#}
{# <div class="text-center" id="temp_lecturer_text">#}
{# <span class="font-italic">No video was found</span>#}
{# </div>#}
<!--display lecturer video -->
......
......@@ -21,6 +21,9 @@
<!-- 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>
<script type="text/javascript">
......@@ -31,10 +34,16 @@
var global_lecturer_subject_index = 0;
var global_lecturer_video_name = '';
var lecturer_fps = 0;
var lecture_emotion_frame_group_percentages = {};
var lecture_video_time_landmarks = [];
//jquery
$(document).ready(function () {
//hide the 'integrate emotion' button
$('#integrate_emotion').hide();
//select a particular subject
$('input[type=radio]').click(function () {
let subject_id = $(this).attr('id');
......@@ -145,8 +154,8 @@
$('#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_lecture_video_id = video.id;
global_lecture_video_id = video.lecture_video_id;
{#global_lecture_video_id = video.id;#}
global_video_name = video.video_name;
......@@ -157,6 +166,9 @@
}
$('#video_modal').modal();
//display the 'integrate emotion' button
$('#integrate_emotion').show();
}
//binding a click event for 'btn-primary' buttons
......@@ -255,9 +267,9 @@
//fetch the lecture recorded video name
fetch('http://127.0.0.1:8000/get-lecture-recorded-video-name/?lecturer=' + global_lecturer + '&subject=' + global_subject + '&date=' + global_lecture_date)
.then((res) => res.json())
.then((out) => assignLecturerRecordedVideoName(out))
.catch((err) => alert('error: ' + err));
.then((res) => res.json())
.then((out) => assignLecturerRecordedVideoName(out))
.catch((err) => alert('error: ' + err));
{#global_lecturer_video_name = "Test_1.mp4";#}
{#global_lecturer_video_name = "Test_2.mp4";#}
......@@ -537,6 +549,151 @@
});
//this function will handle the activity 'summary' button
$('#graph-tab').click(function (e) {
//display the graph loader
$('#graph_loader').attr('hidden', false);
//fetch the video time landmark details
fetch('http://127.0.0.1:8000/get-lecture-video-summary-time-landmarks/?video_name=' + global_video_name)
.then((res) => res.json())
.then((out) => assignTimeLandmarks(out.response))
.catch((err) => alert('error: ' + err));
//fetch the activity summary details
fetch('http://127.0.0.1:8000/get-lecture-emotion-summary/?video_name=' + global_video_name)
.then((res) => res.json())
.then((out) => emotionFrameGroupPercentages(out, e))
.catch((err) => alert('error: ' + err));
});
//this function will assign lecture video time landmarks
function assignTimeLandmarks(response) {
lecture_video_time_landmarks = response;
}
//this function will handle the retrieved emotion frame group percentages
function emotionFrameGroupPercentages(response, e) {
lecture_emotion_frame_group_percentages = response.frame_group_percentages;
let frame_landmarks = response.frame_landmarks;
let emotion_labels = response.emotion_labels;
//render the chart onto the modal body
renderEmotionChart(emotion_labels);
}
//this function will call the emotion chart function
function renderEmotionChart(emotion_labels) {
//get the activity label length
let emotion_label_length = emotion_labels.length;
let data = [];
//loop through the activity labels
for (let k = 0; k < emotion_label_length; k++) {
let label = emotion_labels[k];
let datapoints = [];
let count = 0;
//loop through the activity frame groups
for (let key in lecture_emotion_frame_group_percentages) {
let frame_group_details = lecture_emotion_frame_group_percentages[key];
let emotion_perct = frame_group_details[label];
let point = {label: lecture_video_time_landmarks[count], y: emotion_perct};
datapoints.push(point);
count++;
}
let obj = {
type: "line",
showInLegend: true,
name: label,
markerType: "square",
{#xValueFormatString: "DD MMM, YYYY",#}
xValueFormatString: "hh:mm:ss",
color: getRandomColor(),
dataPoints: datapoints
};
data.push(obj);
}
var chart = new CanvasJS.Chart("EmotionChartContainer", {
animationEnabled: true,
theme: "light2",
title: {
text: "Student Emotion Behavior"
},
axisX: {
title: "Duration",
{#valueFormatString: "DD MMM",#}
valueFormatString: "hh:mm:ss",
crosshair: {
enabled: true,
snapToDataPoint: true
}
},
axisY: {
title: "Percentage",
includeZero: true,
crosshair: {
enabled: true
}
},
toolTip: {
shared: true
},
legend: {
cursor: "pointer",
verticalAlign: "top",
horizontalAlign: "right",
dockInsidePlotArea: true,
itemclick: toogleDataSeries
},
data: data
});
chart.render();
}
//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;
}
//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();
}
});
</script>
......@@ -787,122 +944,122 @@
</div>
<!-- end of frame tab -->
<!--graph tab -->
<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">Student
Activities</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 id="EmotionChartContainer"
style="height: 270px; max-width: 920px; margin: 0px auto;"></div>
</div>
<!-- End of Card Body -->
</div>
</div>
</div>
</div>
</div>
</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 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 -->
<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_emotion">
Process
</button>
</div>
</div>
</div>
</div>
<!--end of 2nd column -->
</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 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>#}
<!-- end of 2nd row -->
<!--3rd row -->
......@@ -941,32 +1098,32 @@
{# </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_emotion">
Process
</button>
</div>
</div>
</div>
</div>
<!--end of 2nd 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_emotion">#}
{# Process#}
{# </button>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# <!--end of 2nd column -->#}
</div>
<!--end of 3rd row -->
......
......@@ -21,6 +21,11 @@
<!-- 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>
<script type="text/javascript">
......@@ -31,10 +36,15 @@
var global_lecturer_subject_index = 0;
var global_lecturer_video_name = '';
var lecturer_fps = 0;
var lecture_gaze_frame_group_percentages = {};
//jquery
$(document).ready(function () {
//hide the 'integrate gaze' button
$('#integrate_gaze').hide();
//select a particular subject
$('input[type=radio]').click(function () {
let subject_id = $(this).attr('id');
......@@ -144,8 +154,8 @@
$('#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_lecture_video_id = video.id;
global_lecture_video_id = video.lecture_video_id;
{#global_lecture_video_id = video.id;#}
global_video_name = video.video_name;
......@@ -157,6 +167,9 @@
}
$('#video_modal').modal();
//show the 'integrate gaze' button
$('#integrate_gaze').show();
}
......@@ -247,9 +260,9 @@
//fetch the lecture recorded video name
fetch('http://127.0.0.1:8000/get-lecture-recorded-video-name/?lecturer=' + global_lecturer + '&subject=' + global_subject + '&date=' + global_lecture_date)
.then((res) => res.json())
.then((out) => assignLecturerRecordedVideoName(out))
.catch((err) => alert('error: ' + err));
.then((res) => res.json())
.then((out) => assignLecturerRecordedVideoName(out))
.catch((err) => alert('error: ' + err));
{#global_lecturer_video_name = "Test_1.mp4";#}
{#global_lecturer_video_name = "Test_2.mp4";#}
......@@ -520,6 +533,150 @@
});
//this function will handle the activity 'summary' button
$('#graph-tab').click(function (e) {
//display the graph loader
$('#graph_loader').attr('hidden', false);
//fetch the video time landmark details
fetch('http://127.0.0.1:8000/get-lecture-video-summary-time-landmarks/?video_name=' + global_video_name)
.then((res) => res.json())
.then((out) => assignTimeLandmarks(out.response))
.catch((err) => alert('error: ' + err));
//fetch the gaze summary details
fetch('http://127.0.0.1:8000/get-lecture-gaze-summary/?video_name=' + global_video_name)
.then((res) => res.json())
.then((out) => gazeFrameGroupPercentages(out, e))
.catch((err) => alert('error: ' + err));
});
//this function will assign lecture video time landmarks
function assignTimeLandmarks(response) {
lecture_video_time_landmarks = response;
}
//this function will handle the retrieved gaze frame group percentages
function gazeFrameGroupPercentages(response, e) {
lecture_gaze_frame_group_percentages = response.frame_group_percentages;
let frame_landmarks = response.frame_landmarks;
let gaze_labels = response.gaze_labels;
//render the chart onto the modal body
renderGazeChart(gaze_labels);
}
//this function will call the chart function
function renderGazeChart(gaze_labels) {
//get the activity label length
let gaze_label_length = gaze_labels.length;
let data = [];
//loop through the activity labels
for (let k = 0; k < gaze_label_length; k++) {
let label = gaze_labels[k];
let datapoints = [];
let count = 0;
//loop through the activity frame groups
for (let key in lecture_gaze_frame_group_percentages) {
let frame_group_details = lecture_gaze_frame_group_percentages[key];
let gaze_perct = frame_group_details[label];
let point = {label: lecture_video_time_landmarks[count], y: gaze_perct};
datapoints.push(point);
count++;
}
let obj = {
type: "line",
showInLegend: true,
name: label,
markerType: "square",
{#xValueFormatString: "DD MMM, YYYY",#}
xValueFormatString: "hh:mm:ss",
color: getRandomColor(),
dataPoints: datapoints
};
data.push(obj);
}
var chart = new CanvasJS.Chart("GazeChartContainer", {
animationEnabled: true,
theme: "light2",
title: {
text: "Student Gaze estimation Behavior"
},
axisX: {
title: "Duration",
{#valueFormatString: "DD MMM",#}
valueFormatString: "hh:mm:ss",
crosshair: {
enabled: true,
snapToDataPoint: true
}
},
axisY: {
title: "Percentage",
includeZero: true,
crosshair: {
enabled: true
}
},
toolTip: {
shared: true
},
legend: {
cursor: "pointer",
verticalAlign: "top",
horizontalAlign: "right",
dockInsidePlotArea: true,
itemclick: toogleDataSeries
},
data: data
});
chart.render();
}
//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;
}
//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();
}
});
</script>
......@@ -771,53 +928,26 @@
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">Student
Activities</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 id="GazeChartContainer"
style="height: 370px; max-width: 920px; margin: 0px auto;"></div>
</div>
</div>
<!-- End of Card Body -->
</div>
</div>
</div>
</div>
</div>
<!-- end of 1st column -->
<!--2nd column -->
......@@ -846,17 +976,11 @@
</div>
</div>
<!--end of 2nd column -->
</div>
<!-- end of 2nd row -->
<!--3rd row -->
<div class="row p-2">
</div>
<!--end of 3rd row -->
{# </div>#}
<!-- end of 2nd row -->
</div>
......
......@@ -118,6 +118,7 @@
<div id="collapseThree" class="collapse" aria-labelledby="headingThree" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Components:</h6>
<a class="collapse-item" href="/summary/record">Record Lecture</a>
<a class="collapse-item" href="/summary/lecture">Summarization</a>
</div>
</div>
......
......@@ -192,6 +192,9 @@ urlpatterns = [
# perform random task (delete later)
url(r'^get-random-number/$', api.TestRandom.as_view()),
# perform random task (delete later)
url(r'^display-upcoming-lectures/$', api.DisplayUpcomingLecturesAPI.as_view()),
......
import sounddevice as sd
from scipy.io.wavfile import write
import wavio as wv
# Sampling frequency
freq = 44100
# Recording duration
duration = 10
# Start recorder with the given values of
# duration and sample frequency
recording = sd.rec(int(duration * freq),
samplerate=freq, channels=2)
# Record audio for the given number of seconds
sd.wait()
# This will convert the NumPy array to an audio
# file with the given sampling frequency
write("recording0.wav", freq, recording)
#Convert the NumPy array to audio file
wv.write("recording1.wav", recording, freq, sampwidth=2)
\ No newline at end of file
......@@ -54,3 +54,4 @@ class LectureNotices (models.Model):
def __str__(self):
return self.lecture_notice_id
{% extends 'FirstApp/template.html' %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lecture Recording</title>
</head>
<body>
% 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>
<!-- Load TensorFlow.js -->
<script src="https://unpkg.com/@tensorflow/tfjs"></script>
<!-- Load Posenet -->
<script src="https://unpkg.com/@tensorflow-models/posenet">
</script>
{% endblock %}
<div id="wrapper">
<div id="content-wrapper" class="d-flex flex-column">
<div id="content">
{% block 'container-fluid' %}
<div class="container-fluid">
{% load static %}
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Lecture Record</h1>
</div>
<div>
<button TYPE="button" class="btn btn-success audio_process">Start Recording</button>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
......@@ -8,6 +8,7 @@ router = routers.DefaultRouter()
urlpatterns = [
path('lecture', views.summarization),
path('record', views.lectureRecord),
# API to retrieve lecture summarizing details
......
......@@ -6,6 +6,14 @@ from .models import LectureAudio, LectureAudioNoiseRemoved, LectureSpeechToText,
from .serializer import LectureAudioSerializer, LectureAudioNoiseRemovedSerializer, LectureAudioSummarySerializer, \
LectureSpeechToTextSerializer, LectureNoticesSerializer
def lectureRecord(request):
lecture_audio = LectureAudio.objects.all()
lecture_audio_ser = LectureAudioSerializer(lecture_audio, many=True)
print('lecture record data: ', lecture_audio_ser.data)
return render(request, "LectureSummarizationApp/RecordLecture.html")
# Views used in Lecture Summarization
......@@ -108,4 +116,5 @@ class lectureSummaryList(APIView):
lecture_audio_id=request.data["lecture_audio_id"],
notice_text=request.data["notice_text"]
).save()
return Response({"response": request.data})
\ No newline at end of file
return Response({"response": request.data})
......@@ -24,5 +24,6 @@ urlpatterns = [
path('attendance/', include('AttendanceApp.urls')),
path('lecturer/', include('MonitorLecturerApp.urls')),
# path('lecturer/', include('MonitorLecturerApp.urls')),
path('summary/', include('LectureSummarizingApp.urls'))
path('summary/', include('LectureSummarizingApp.urls')),
path('record/', include('LectureSummarizingApp.urls'))
]
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