MIF_E31231392/resources/views/user/pages/ujian/temp_index.blade.php

291 lines
11 KiB
PHP

@section('title', 'Ujian Kecemasan')
{{-- @section('body_status_overflow', 'overflow: hidden;') --}}
@section('main_style', 'min-height: 100vh;')
@extends('user.layouts.test_layout.index')
@section('content')
<div class="container-fluid p-0 d-flex flex-column" style="min-height: 100vh">
<nav class="navbar navbar-expand-lg bg-body-tertiary px-2">
<div class="container-fluid">
<a class="navbar-brand" href="#">Smart Anxiety</a>
<div class="collapse navbar-collapse justify-content-between" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0"></ul>
<div class="d-flex col-md-4">
<div class="col-md-4 d-flex justify-content-center align-items-center">
Time Left: <span id="time_left"></span>
</div>
<div class="col-md-4 d-flex justify-content-center align-items-center">
<span id="bg_status_tobii" class="rounded bg-warning d-block mx-2" style="width: 10px; aspect-ratio: 1/1;"></span>Status Tobii
</div>
<div class="col-md-4 d-flex justify-content-center align-items-center">
<button id="fullscreen_btn" data-status="fullscreen" class="btn btn-sm btn-outline-secondary" onclick="openFullscreen()">Fullscreen</button>
</div>
</div>
</div>
</div>
</nav>
<div class="d-flex flex-grow-1 container-fluid">
<div class="row flex-grow-1">
<div class="col-md-9 border-end">
<div class="row justify-content-center flex-column p-4">
<div class="col-md-12 border-bottom fs-4 fw-bold p-2">Soal</div>
<div class="col-md-12 p-2" id="text_question" style="text-align: justify"></div>
<div class="col-md-12" id="answer_field">
<div class="fs-4 fw-bold p-2">Jawaban:</div>
{{-- <div class="form-check m-2">
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_{{ $item['key'] }}">
<label class="form-check-label" for="jawaban_{{ $item['key'] }}">{{ $item['value'] }}</label>
</div> --}}
</div>
</div>
</div>
<div class="col-md-3">
<div class="row p-3">
<div class="col-md-12 border-bottom fs-4 fw-bold p-2 mb-3" id="navigation_field">Navigasi Soal</div>
{{-- @foreach ($answered_question as $question)
<div onclick="changeQuestion({{ $question['nomor_soal'] }})" id="nomor_{{ $question['nomor_soal'] }}" class="col-md-1 btn d-flex justify-content-center align-items-center {{ $question['answered'] ? 'bg-secondary-subtle' : 'bg-light-subtle' }} border rounded p-0 m-1" style="aspect-ratio: 1/1.5;">{{ $question['nomor_soal'] }}</div>
@endforeach
<div class="col-md-12 p-0 mt-3">
@if ($question_number > 1)
<div class="btn btn-secondary" onclick="changeQuestion({{ $question_number - 1 }})">Previous</div>
@endif
@if ($is_last_question)
<div class="btn btn-success" onclick="finishExam()">Finish</div>
@else
<div class="btn btn-primary" onclick="changeQuestion({{ $question_number + 1 }})">Next</div>
@endif
</div> --}}
</div>
<div class="row p-3">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<h5 class="card-title">Instruksi</h5>
<p class="card-text">Silahkan baca soal dengan teliti dan pilih jawaban yang paling tepat.</p>
<div class="card-text d-flex align-items-center">
<span class="col-md-1 bg-light-subtle border rounded p-0 m-1" style="aspect-ratio: 1/1.5;"></span>
<span>adalah tanda bahwa jawaban BELUM diisi.</span>
</div>
<div class="card-text d-flex align-items-center">
<span class="col-md-1 bg-secondary-subtle border rounded p-0 m-1" style="aspect-ratio: 1/1.5;"></span>
<span>adalah tanda bahwa jawaban SUDAH diisi.</span>
</div>
<div class="card-text d-flex align-items-center">
<span class="col-md-1 bg-info border rounded p-0 m-1 text-white" style="aspect-ratio: 1/1.5;"></span>
<span>adalah tanda bahwa anda sedang membaca/menjawab soal ini.</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('script')
<script>
const ws = new WebSocket('{{ env("WEBSOCKET_URL") }}');
const SESSION_ID = '{{ $data_session->id_test_sessions }}';
const TOKEN_SESSION = '{{ $data_session->token_session }}';
let UNIX_END_TIME = null;
let QUESTION_INDEX = 1;
function fetchQuestion(question_index) {
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
let response = JSON.parse(this.responseText);
if(response.status) {
$('#text_question').html(response.data.pertanyaan);
getCurrentAnswer(response.data.id_soal);
} else {
Swal.fire({
title: 'Error',
icon: 'error',
text: 'Terjadi kesalahan saat mengambil soal. Silahkan refresh halaman ini.',
confirmButtonText: 'OK'
});
}
}
}
xhttp.open("GET", "{{ route('ujian.fetchQuestion') }}?session_id=" + SESSION_ID + "&question_index=" + question_index, false);
xhttp.send();
}
function getCurrentAnswer(id_question) {
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let response = JSON.parse(this.responseText);
if (response.status) {
let choices_html = '';
$('#answer_field').html('<div class="fs-4 fw-bold p-2">Jawaban:</div>');
response.choices.forEach((choice) => {
choices_html += `
<div class="form-check m-2">
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_${choice.key}">
<label class="form-check-label" for="jawaban_${choice.key}">${choice.value}</label>
</div>
`;
});
$('#answer_field').append(choices_html);
}
}
};
xhttp.open("GET", "{{ route('ujian.getCurrentAnswer') }}?session_id=" + SESSION_ID + "&id_question=" + id_question, false);
xhttp.send();
}
function getTimeLeft() {
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let response = JSON.parse(this.responseText);
console.log('Time left:', response.time_left);
UNIX_END_TIME = response.time_left;
}
};
xhttp.open("GET", "{{ route('ujian.getTimeLeft') }}?session_id=" + SESSION_ID, false);
xhttp.send();
}
function updateTimeLeft() {
let time_left = UNIX_END_TIME - Math.floor(Date.now() / 1000);
if(time_left < 0) {
time_left = 0;
finishExam();
}
let minutes = Math.floor(time_left / 60);
let seconds = time_left % 60;
document.getElementById('time_left').innerText = ' ' + minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
}
function startTobii() {
ws.send(JSON.stringify({
type: "command",
action: "start",
session_id: SESSION_ID
}));
}
function stopTobii() {
ws.send(JSON.stringify({
type: "command",
action: "stop",
session_id: SESSION_ID
}));
}
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');
$('#fullscreen_btn').text('Exit Fullscreen');
startTobii();
} 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');
$('#fullscreen_btn').text('Enter Fullscreen');
}
}
function checkFullscreen() {
if (!document.fullscreenElement) {
ws.send(JSON.stringify({
type: "command",
action: "stop",
session_id: SESSION_ID
}));
Swal.fire({
title: 'Alert',
icon: 'warning',
text: 'Anda keluar dari mode fullscreen, harap masuk ke mode fullscreen untuk melanjutkan ujian.',
confirmButtonText: 'Ya',
showCancelButton: false,
showCloseButton: false,
allowOutsideClick: false,
allowEscapeKey: false,
backdrop: `rgba(0, 0, 0, 0.4)`
}).then((result) => {
if (result.isConfirmed) {
openFullscreen();
}
});
}
}
$(document).ready(function() {
ws.onopen = () => {
console.log("Connected to WebSocket");
ws.send(JSON.stringify({
type: "register",
session_id: SESSION_ID,
token_session: TOKEN_SESSION,
role: "web"
}));
document.addEventListener('fullscreenchange', checkFullscreen);
// checkFullscreen();
ws.send(JSON.stringify({
type: "update_status",
status_sessions: true,
session_id: SESSION_ID
}));
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if(data.type === 'reset_start_tobii') {
startTobii();
}
if(data.type === 'status_tobii_device') {
if(data.status) {
console.log('Tobii device is connected');
// document.getElementById('status_tobii_device').innerText = 'Connected';
document.getElementById('bg_status_tobii').classList.remove('bg-warning');
document.getElementById('bg_status_tobii').classList.remove('bg-danger');
document.getElementById('bg_status_tobii').classList.add('bg-success');
} else {
console.log('Tobii device is not connected');
// document.getElementById('status_tobii_device').innerText = 'Not Connected';
document.getElementById('bg_status_tobii').classList.remove('bg-success');
document.getElementById('bg_status_tobii').classList.remove('bg-warning');
document.getElementById('bg_status_tobii').classList.add('bg-danger');
}
}
};
startTobii();
// getCurrentAnswer();
getTimeLeft();
setInterval(updateTimeLeft, 1000);
fetchQuestion(QUESTION_INDEX);
};
});
</script>
@endsection