|
|
|
|
@ -1,7 +1,7 @@
|
|
|
|
|
@section('title', 'Tutorial Test Kecemasan')
|
|
|
|
|
@extends('user.layouts.test_layout.index')
|
|
|
|
|
@section('content')
|
|
|
|
|
<div class="container">
|
|
|
|
|
<div class="container" id="tutorial_panel">
|
|
|
|
|
<div class="row justify-content-center">
|
|
|
|
|
<div class="col-md-8" id="tutorial_1">
|
|
|
|
|
<div class="card shadow-sm border-0">
|
|
|
|
|
@ -41,7 +41,7 @@
|
|
|
|
|
<button class="btn btn-secondary" onclick="copyLinkApiTobii()">Copy</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<p class="card-text mt-3" id="status_tobii">Status Tobii: Tidak Terhubung</p>
|
|
|
|
|
<p class="card-text mt-3" id="status_tobii">Memuat...</p>
|
|
|
|
|
<button class="btn btn-primary" id="back_btn" onclick="showTutorial(1, 'tutorial_2')">Back</button>
|
|
|
|
|
<button class="btn btn-primary" id="next_btn_connect_tobii" onclick="showTutorial(3, 'tutorial_2')">Next</button>
|
|
|
|
|
</div>
|
|
|
|
|
@ -51,21 +51,151 @@
|
|
|
|
|
<div class="card shadow-sm border-0">
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
<h3 class="card-title fw-bold mb-4">Tes Keakuratan Mata</h3>
|
|
|
|
|
<p class="card-text mb-3">Sebelum tes dimulai, cek keakuratan device Tobii anda, jika tidak akurat, lakukan kalibrasi kepada administrator.</p>
|
|
|
|
|
<button class="btn btn-primary" id="back_btn" onclick="showTutorial(2, 'tutorial_2')">Back</button>
|
|
|
|
|
<p class="card-text mb-3">Sebelum tes dimulai, cek keakuratan device Tobii anda (disarankan full-screen), jika tidak akurat, lakukan kalibrasi kepada administrator.</p>
|
|
|
|
|
<button class="btn btn-primary" id="back_btn" onclick="showTutorial(2, 'tutorial_3')">Back</button>
|
|
|
|
|
<button class="btn btn-secondary" id="fullscreen_btn" onclick="openFullscreen(this)" data-status="fullscreen">Fullscreen</button>
|
|
|
|
|
<button class="btn btn-secondary" id="hide_btn" onclick="hidePanelTutorial(this)" data-status="hide">Hide</button>
|
|
|
|
|
<a class="btn btn-primary">Mulai Ujian</a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- btn show -->
|
|
|
|
|
<button type="button" class="btn btn-secondary position-absolute" onclick="showCalibrationPoints()" id="show_calibration" style="z-index: 999">Show</button>
|
|
|
|
|
<div class="position-absolute bg-white" style="width: 100vw; height: 100vh; z-index: -1;" id="calibration_point">
|
|
|
|
|
<!-- row 1 -->
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 2%; left: 2%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 2%; left: 19.2%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 2%; left: 38.4%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 2%; left: 57.6%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 2%; left: 76.8%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 2%; left: 96%"></div>
|
|
|
|
|
|
|
|
|
|
<!-- row 2 -->
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 19.2%; left: 2%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 19.2%; left: 19.2%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 19.2%; left: 38.4%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 19.2%; left: 57.6%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 19.2%; left: 76.8%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 19.2%; left: 96%"></div>
|
|
|
|
|
|
|
|
|
|
<!-- row 3 -->
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 38.4%; left: 2%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 38.4%; left: 19.2%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 38.4%; left: 38.4%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 38.4%; left: 57.6%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 38.4%; left: 76.8%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 38.4%; left: 96%"></div>
|
|
|
|
|
|
|
|
|
|
<!-- row 4 -->
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 57.6%; left: 2%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 57.6%; left: 19.2%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 57.6%; left: 38.4%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 57.6%; left: 57.6%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 57.6%; left: 76.8%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 57.6%; left: 96%"></div>
|
|
|
|
|
|
|
|
|
|
<!-- row 5 -->
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 76.8%; left: 2%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 76.8%; left: 19.2%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 76.8%; left: 38.4%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 76.8%; left: 57.6%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 76.8%; left: 76.8%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 76.8%; left: 96%"></div>
|
|
|
|
|
|
|
|
|
|
<!-- row 6 -->
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 96%; left: 2%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 96%; left: 19.2%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 96%; left: 38.4%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 96%; left: 57.6%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 96%; left: 76.8%"></div>
|
|
|
|
|
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 96%; left: 96%"></div>
|
|
|
|
|
|
|
|
|
|
<div id="the_eye" class="rounded-circle bg-danger position-absolute" style="width: 0.5%; aspect-ratio: 1/1;"></div>
|
|
|
|
|
</div>
|
|
|
|
|
@endsection
|
|
|
|
|
|
|
|
|
|
@section('script')
|
|
|
|
|
<script>
|
|
|
|
|
let getDataInterval = false;
|
|
|
|
|
let checkTobiiInterval = null;
|
|
|
|
|
|
|
|
|
|
function showTutorial(step, tutorialId) {
|
|
|
|
|
$(`#${tutorialId}`).hide();
|
|
|
|
|
$(`#tutorial_${step}`).show();
|
|
|
|
|
|
|
|
|
|
if(step === 2) {
|
|
|
|
|
checkTobiiInterval = setInterval(() => {
|
|
|
|
|
checkTobiiConnection();
|
|
|
|
|
}, 2000);
|
|
|
|
|
} else {
|
|
|
|
|
if(checkTobiiInterval) {
|
|
|
|
|
clearInterval(checkTobiiInterval);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(step === 3) {
|
|
|
|
|
$('#calibration_point').show();
|
|
|
|
|
getDataInterval = true;
|
|
|
|
|
startPolling();
|
|
|
|
|
} else {
|
|
|
|
|
$('#calibration_point').hide();
|
|
|
|
|
getDataInterval = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function startPolling() {
|
|
|
|
|
while(getDataInterval) {
|
|
|
|
|
await fetchDataTobii();
|
|
|
|
|
await delay(1000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function delay(ms) {
|
|
|
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function hidePanelTutorial(btn) {
|
|
|
|
|
const status = $(btn).attr('data-status');
|
|
|
|
|
if (status === 'hide') {
|
|
|
|
|
$('#tutorial_panel').hide();
|
|
|
|
|
$('#show_calibration').show();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function showCalibrationPoints() {
|
|
|
|
|
$('#show_calibration').toggle();
|
|
|
|
|
$('#tutorial_panel').toggle();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function moveTheEye(x, y) {
|
|
|
|
|
const eye = $('#the_eye');
|
|
|
|
|
eye.css({ left: x + 'px', top: y + 'px' });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function openFullscreen() {
|
|
|
|
|
const status = $('#fullscreen_btn').attr('data-status');
|
|
|
|
|
const elem = document.documentElement;
|
|
|
|
|
if (status === 'fullscreen') {
|
|
|
|
|
if (elem.requestFullscreen) {
|
|
|
|
|
elem.requestFullscreen();
|
|
|
|
|
} else if (elem.webkitRequestFullscreen) {
|
|
|
|
|
elem.webkitRequestFullscreen(); // Safari
|
|
|
|
|
} else if (elem.msRequestFullscreen) {
|
|
|
|
|
elem.msRequestFullscreen(); // IE
|
|
|
|
|
}
|
|
|
|
|
$('#fullscreen_btn').attr('data-status', 'exit-fullscreen');
|
|
|
|
|
} else if (status === 'exit-fullscreen') {
|
|
|
|
|
if (document.exitFullscreen) {
|
|
|
|
|
document.exitFullscreen();
|
|
|
|
|
} else if (document.webkitExitFullscreen) {
|
|
|
|
|
document.webkitExitFullscreen(); // Safari
|
|
|
|
|
} else if (document.msExitFullscreen) {
|
|
|
|
|
document.msExitFullscreen(); // IE
|
|
|
|
|
}
|
|
|
|
|
$('#fullscreen_btn').attr('data-status', 'fullscreen');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function generateLinkApiTobii() {
|
|
|
|
|
@ -113,14 +243,26 @@ function checkTobiiConnection() {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function fetchDataTobii() {
|
|
|
|
|
try {
|
|
|
|
|
const response = await fetch('{{ route("tobii-receiver.fetchData", ['id_test_sessions' => $data_session->id_test_sessions]) }}');
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
throw new Error('Network response was not ok');
|
|
|
|
|
}
|
|
|
|
|
const data = await response.json();
|
|
|
|
|
moveTheEye(data.gaze_x, data.gaze_y);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error fetching Tobii data:', error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$(document).ready(function() {
|
|
|
|
|
$('#tutorial_2').hide();
|
|
|
|
|
$('#tutorial_3').hide();
|
|
|
|
|
$('#next_btn_connect_tobii').hide();
|
|
|
|
|
$('#calibration_point').hide();
|
|
|
|
|
$('#show_calibration').hide();
|
|
|
|
|
generateLinkApiTobii();
|
|
|
|
|
|
|
|
|
|
setInterval(() => {
|
|
|
|
|
checkTobiiConnection();
|
|
|
|
|
}, 2000);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|