185 lines
5.1 KiB
Svelte
185 lines
5.1 KiB
Svelte
<!--
|
|
SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
|
|
|
SPDX-License-Identifier: MPL-2.0
|
|
-->
|
|
|
|
<script lang="ts">
|
|
import type { QuizData } from '$lib/quiz_types';
|
|
import { getLocalization } from '$lib/i18n';
|
|
import { get_question_title } from '$lib/admin.ts';
|
|
import type { PlayerAnswer } from '$lib/admin.ts';
|
|
import { socket } from './socket';
|
|
import { QuizQuestionType } from '$lib/quiz_types';
|
|
import Spinner from '$lib/Spinner.svelte';
|
|
import Controls from '$lib/play/admin/controls.svelte';
|
|
import Question from '$lib/play/admin/question.svelte';
|
|
|
|
const { t } = getLocalization();
|
|
const default_colors = ['#D6EDC9', '#B07156', '#7F7057', '#4E6E58'];
|
|
|
|
let question_results = $state(null);
|
|
let selected_question = $state(-1);
|
|
let timer_res: string = $state();
|
|
let shown_question_now: number = $state();
|
|
let final_results_clicked = $state(false);
|
|
let timer_interval: NodeJS.Timeout;
|
|
let answer_count = $state(0);
|
|
|
|
interface Props {
|
|
game_token: string;
|
|
quiz_data: QuizData;
|
|
bg_color: string;
|
|
final_results?: Array<null> | Array<Array<PlayerAnswer>>;
|
|
control_visible: boolean;
|
|
player_scores: any;
|
|
}
|
|
|
|
let {
|
|
game_token,
|
|
quiz_data = $bindable(),
|
|
bg_color,
|
|
final_results = $bindable([null]),
|
|
control_visible,
|
|
player_scores = $bindable()
|
|
}: Props = $props();
|
|
|
|
socket.on('get_question_results', () => {
|
|
console.log('get_question_results');
|
|
});
|
|
socket.on('set_question_number', (data) => {
|
|
timer_res = '0';
|
|
clearInterval(timer_interval);
|
|
question_results = null;
|
|
shown_question_now = data.question_index;
|
|
timer_res = quiz_data.questions[data.question_index].time;
|
|
selected_question = selected_question + 1;
|
|
answer_count = 0;
|
|
timer(timer_res);
|
|
});
|
|
|
|
socket.on('solutions', (_) => {
|
|
timer_res = '0';
|
|
clearInterval(timer_interval);
|
|
});
|
|
|
|
socket.on('final_results', (data) => {
|
|
// data = JSON.parse(data);
|
|
final_results_clicked = true;
|
|
timer_res = '0';
|
|
final_results = data;
|
|
});
|
|
|
|
socket.on('everyone_answered', (_) => {
|
|
timer_res = '0';
|
|
});
|
|
|
|
socket.on('question_results', (data) => {
|
|
console.log('question_results:', data);
|
|
question_results = data;
|
|
timer_res = '0';
|
|
});
|
|
|
|
socket.on('player_answer', (_) => {
|
|
answer_count += 1;
|
|
});
|
|
|
|
const timer = (time: string) => {
|
|
let seconds = Number(time);
|
|
timer_interval = setInterval(() => {
|
|
if (timer_res === '0') {
|
|
clearInterval(timer_interval);
|
|
return;
|
|
} else {
|
|
seconds--;
|
|
}
|
|
|
|
timer_res = seconds.toString();
|
|
}, 1000);
|
|
};
|
|
</script>
|
|
|
|
{#if control_visible}
|
|
<Controls
|
|
{bg_color}
|
|
{selected_question}
|
|
{quiz_data}
|
|
bind:timer_res
|
|
{final_results}
|
|
{socket}
|
|
{question_results}
|
|
{game_token}
|
|
{shown_question_now}
|
|
/>
|
|
{/if}
|
|
{#if timer_res !== '0' && selected_question >= 0}
|
|
<span
|
|
class="fixed top-0 bg-red-500 h-8 transition-all"
|
|
class:mt-10={control_visible}
|
|
style="width: {(100 / parseInt(quiz_data.questions[selected_question].time)) *
|
|
parseInt(timer_res)}vw"
|
|
></span>
|
|
{/if}
|
|
|
|
<div class="w-full h-full" class:pt-28={control_visible} class:pt-12={!control_visible}>
|
|
{#if timer_res !== undefined && !final_results_clicked && !question_results}
|
|
<!-- Question is shown -->
|
|
{#if quiz_data.questions[selected_question].type === QuizQuestionType.SLIDE}
|
|
{#await import('$lib/play/admin/slide.svelte')}
|
|
<Spinner my_20={false} />
|
|
{:then c}
|
|
<c.default question={quiz_data.questions[selected_question]} />
|
|
{/await}
|
|
{:else}
|
|
<Question {quiz_data} {selected_question} {timer_res} {answer_count} {default_colors} />
|
|
{/if}
|
|
{/if}
|
|
<br />
|
|
{#if timer_res === '0' && JSON.stringify(final_results) === JSON.stringify( [null] ) && quiz_data.questions[selected_question].type !== QuizQuestionType.SLIDE && question_results !== null && quiz_data.questions[selected_question]?.hide_results !== true}
|
|
{#if question_results === undefined}
|
|
{#if !final_results_clicked}
|
|
<div class="w-full flex justify-center">
|
|
<h1 class="text-3xl">{$t('admin_page.no_answers')}</h1>
|
|
</div>
|
|
{/if}
|
|
{:else if quiz_data.questions[selected_question].type === QuizQuestionType.VOTING}
|
|
{#await import('$lib/play/admin/voting_results.svelte')}
|
|
<Spinner />
|
|
{:then c}
|
|
<c.default
|
|
data={question_results}
|
|
question={quiz_data.questions[selected_question]}
|
|
/>
|
|
{/await}
|
|
{:else}
|
|
{#await import('$lib/play/admin/results.svelte')}
|
|
<Spinner />
|
|
{:then c}
|
|
<c.default
|
|
bind:data={player_scores}
|
|
question={quiz_data.questions[selected_question]}
|
|
new_data={question_results}
|
|
/>
|
|
{/await}
|
|
{/if}
|
|
{/if}
|
|
<br />
|
|
{#if get_question_title(selected_question + 1, quiz_data) === '' && selected_question + 1 === 0}
|
|
<div class="flex flex-col justify-center w-screen h-full">
|
|
<h1 class="text-7xl text-center">{@html quiz_data.title}</h1>
|
|
<p class="text-3xl pt-8 text-center">{@html quiz_data.description}</p>
|
|
{#if quiz_data.cover_image}
|
|
<div class="flex justify-center align-middle items-center">
|
|
<div class="h-[30vh] m-auto w-auto mt-12">
|
|
<img
|
|
class="max-h-full max-w-full block"
|
|
src="/api/v1/storage/download/{quiz_data.cover_image}"
|
|
alt="Not provided"
|
|
/>
|
|
</div>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
</div>
|