halaman-psikolog #1
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\DataSoalModel;
|
||||
use App\Models\TestSessionsModel;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class HalamanUjianController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
|
||||
$id_session = null;
|
||||
if(session('id_test_sessions') != null) {
|
||||
$id_session = session('id_test_sessions');
|
||||
} else if($request->id_test_sessions != null) {
|
||||
$id_session = $request->id_test_sessions;
|
||||
} else {
|
||||
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.');
|
||||
}
|
||||
|
||||
$data_session = TestSessionsModel::where('id_test_sessions', $id_session)->first();
|
||||
if($data_session != null) {
|
||||
if($data_session->status_session != '1') {
|
||||
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes belum dimulai atau telah usai. Silahkan cek status dengan kode untuk informasi lebih lanjut.');
|
||||
}
|
||||
} else {
|
||||
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.');
|
||||
}
|
||||
|
||||
$question_number = null;
|
||||
$data_question = null;
|
||||
if(session('question') != null) {
|
||||
$question_number = session('question');
|
||||
} else if($request->question != null) {
|
||||
$question_number = $request->question;
|
||||
} else {
|
||||
$question_number = 1;
|
||||
}
|
||||
|
||||
$data_question = DataSoalModel::all();
|
||||
$total_question = null;
|
||||
$is_last_question = false;
|
||||
if($question_number <= 0 || $question_number > count($data_question)) {
|
||||
$question_number = 1;
|
||||
}
|
||||
if(count($data_question) == $question_number) {
|
||||
$is_last_question = true;
|
||||
}
|
||||
$total_question = count($data_question);
|
||||
$data_question = $data_question[$question_number - 1];
|
||||
|
||||
return view("user.pages.ujian.index", compact('data_session', 'data_question', 'total_question', 'is_last_question', 'question_number'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('soal', function (Blueprint $table) {
|
||||
$table->text('pertanyaan')->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('soal', function (Blueprint $table) {
|
||||
$table->string('pertanyaan', 255)->change();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -40,11 +40,11 @@
|
|||
======================================================== -->
|
||||
</head>
|
||||
|
||||
<body class="index-page">
|
||||
<body class="index-page" style="@yield('body_status_overflow')">
|
||||
|
||||
{{-- @include('user.layouts.navbar') --}}
|
||||
|
||||
<main class="main" style="width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center;">
|
||||
<main class="main" style="@yield('main_style')">
|
||||
|
||||
@yield('content')
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
@section('title', 'Tutorial Test Kecemasan')
|
||||
@section('body_status_overflow', 'overflow: hidden;')
|
||||
@section('main_style', 'width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center;')
|
||||
@extends('user.layouts.test_layout.index')
|
||||
@section('content')
|
||||
<div class="container" id="tutorial_panel">
|
||||
|
|
@ -73,7 +75,7 @@
|
|||
<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>
|
||||
<a class="btn btn-primary" id="start_ujian" href="#">Mulai Ujian</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -147,7 +149,8 @@ function showTutorial(step, tutorialId) {
|
|||
$(`#${tutorialId}`).hide();
|
||||
$(`#tutorial_${step}`).show();
|
||||
|
||||
if(step === 2) {
|
||||
if(step === 2 || step === 3) {
|
||||
startTobii();
|
||||
checkTobiiInterval = setInterval(() => {
|
||||
checkTobiiConnection();
|
||||
}, 2000);
|
||||
|
|
@ -155,26 +158,18 @@ function showTutorial(step, tutorialId) {
|
|||
if(checkTobiiInterval) {
|
||||
clearInterval(checkTobiiInterval);
|
||||
}
|
||||
stopTobii();
|
||||
}
|
||||
|
||||
if(step === 3) {
|
||||
$('#calibration_point').show();
|
||||
let test_url = '{{ route('ujian.index', ['id_test_sessions' => '__ID_TEST_SESSIONS__']) }}';
|
||||
$('#start_ujian').attr('href', test_url.replace('__ID_TEST_SESSIONS__', SESSION_ID));
|
||||
} else {
|
||||
$('#calibration_point').hide();
|
||||
}
|
||||
}
|
||||
|
||||
async function startPolling() {
|
||||
while(getDataInterval) {
|
||||
await fetchDataTobii();
|
||||
await delay(300);
|
||||
}
|
||||
}
|
||||
|
||||
function delay(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
function hidePanelTutorial(btn) {
|
||||
const status = $(btn).attr('data-status');
|
||||
if (status === 'hide') {
|
||||
|
|
@ -288,8 +283,8 @@ function copyLinkTokenTobii() {
|
|||
|
||||
function checkTobiiConnection() {
|
||||
ws.send(JSON.stringify({
|
||||
type: "check_temp_data",
|
||||
id_session: SESSION_ID
|
||||
type: "check_tobii_connection",
|
||||
session_id: SESSION_ID,
|
||||
}));
|
||||
|
||||
if(tobiiConnectedStatus) {
|
||||
|
|
@ -314,6 +309,22 @@ function checkTobiiConnection() {
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
}));
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#tutorial_2').hide();
|
||||
$('#tutorial_3').hide();
|
||||
|
|
@ -352,13 +363,24 @@ function checkTobiiConnection() {
|
|||
// }
|
||||
|
||||
if(data.type === 'tobii_data') {
|
||||
console.log('Tobii data not active:', data);
|
||||
try {
|
||||
moveTheEye(data.gaze_x, data.gaze_y);
|
||||
} catch(error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// if(data.type === 'status_tobii') {
|
||||
// if(data.status) {
|
||||
// tobiiConnectedStatus = true;
|
||||
// } else if(!data.status) {
|
||||
// tobiiConnectedStatus = false;
|
||||
// }
|
||||
// }
|
||||
|
||||
if(data.type === 'reset_start_tobii') {
|
||||
startTobii();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,146 @@
|
|||
@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" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0"></ul>
|
||||
<div class="d-flex fw-bold">Time Left: <span id="time_left"></span></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" style="text-align: justify">{{ $data_question->pertanyaan }}</div>
|
||||
<div class="col-md-12">
|
||||
<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_a">
|
||||
<label class="form-check-label" for="jawaban_a">{{ $data_question->jawaban_a }}</label>
|
||||
</div>
|
||||
<div class="form-check m-2">
|
||||
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_b">
|
||||
<label class="form-check-label" for="jawaban_b">{{ $data_question->jawaban_b }}</label>
|
||||
</div>
|
||||
<div class="form-check m-2">
|
||||
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_c">
|
||||
<label class="form-check-label" for="jawaban_c">{{ $data_question->jawaban_c }}</label>
|
||||
</div>
|
||||
<div class="form-check m-2">
|
||||
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_d">
|
||||
<label class="form-check-label" for="jawaban_d">{{ $data_question->jawaban_d }}</label>
|
||||
</div>
|
||||
<div class="form-check m-2">
|
||||
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_e">
|
||||
<label class="form-check-label" for="jawaban_e">{{ $data_question->jawaban_e }}</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">Navigasi Soal</div>
|
||||
@for ($i = 0; $i < $total_question; $i++)
|
||||
<div onclick="changeQuestion({{ $i + 1 }})" class="col-md-1 btn d-flex justify-content-center align-items-center bg-light-subtle border rounded p-0 m-1" style="aspect-ratio: 1/1.5;">{{ $i + 1 }}</div>
|
||||
@endfor
|
||||
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('script')
|
||||
<script>
|
||||
const ws = new WebSocket('{{ env("WEBSOCKET_URL") }}');
|
||||
let SESSION_ID = '{{ $data_session->id_test_sessions }}';
|
||||
let TOKEN_SESSION = '{{ $data_session->token_session }}';
|
||||
|
||||
function changeQuestion(num) {
|
||||
let url_temp = window.location.href;
|
||||
let current_num = new URLSearchParams(window.location.search).get('question');
|
||||
stopTobii();
|
||||
if(!url_temp.includes('question')) {
|
||||
window.location.href = url_temp + '&question=' + num;
|
||||
} else if(url_temp.includes('question')) {
|
||||
window.location.href = window.location.href.replace('&question=' + current_num, '&question=' + num);
|
||||
}
|
||||
}
|
||||
|
||||
function finishExam() {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command",
|
||||
action: "stop",
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
|
||||
//send_data_to_db
|
||||
ws.send(JSON.stringify({
|
||||
type: "send_data_to_db",
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
type: "update_status",
|
||||
status_sessions: false,
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
}
|
||||
|
||||
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
|
||||
}));
|
||||
}
|
||||
|
||||
$(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"
|
||||
}));
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
type: "update_status",
|
||||
status_sessions: true,
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
|
||||
startTobii();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
use App\Http\Controllers\CekStatusController;
|
||||
use App\Http\Controllers\DashboardController;
|
||||
use App\Http\Controllers\DataSoalController;
|
||||
use App\Http\Controllers\HalamanUjianController;
|
||||
use App\Http\Controllers\HasilTesController;
|
||||
use App\Http\Controllers\LandingController;
|
||||
use App\Http\Controllers\ProfileController;
|
||||
|
|
@ -36,6 +37,7 @@
|
|||
Route::resource('test-sessions', TestSessionsController::class)->only(['store', 'show']);
|
||||
Route::resource('tobii-receiver', TobiiReceiverController::class)->only(['store', 'show']);
|
||||
Route::get('tobii-receiver/fetch/data/{id_test_sessions}', [TobiiReceiverController::class, 'fetchDataTobii'])->name('tobii-receiver.fetchData');
|
||||
Route::resource('ujian', HalamanUjianController::class);
|
||||
Route::middleware(['auth', 'role.auth'])->group(function() {
|
||||
Route::resource('dashboard', DashboardController::class);
|
||||
Route::resource('users', UsersController::class);
|
||||
|
|
|
|||
Loading…
Reference in New Issue