🚧 Changed GameState to make it dynamic with svelte components and cleaned code
This commit is contained in:
@@ -5,10 +5,7 @@ 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';
|
||||
@@ -20,31 +17,18 @@ SPDX-License-Identifier: MPL-2.0
|
||||
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;
|
||||
game_state: GameState;
|
||||
}
|
||||
|
||||
let {
|
||||
game_token,
|
||||
quiz_data = $bindable(),
|
||||
bg_color,
|
||||
final_results = $bindable([null]),
|
||||
control_visible,
|
||||
player_scores = $bindable(),
|
||||
game_state = $bindable()
|
||||
}: Props = $props();
|
||||
|
||||
@@ -52,70 +36,51 @@ SPDX-License-Identifier: MPL-2.0
|
||||
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);
|
||||
|
||||
game_state.timer_res = '0';
|
||||
game_state.question_results = null;
|
||||
game_state.shown_question_now = data.question_index;
|
||||
game_state.timer_res = quiz_data.questions[data.question_index].time;
|
||||
game_state.timer_res = game_state.quiz_data.questions[data.question_index].time;
|
||||
game_state.selected_question = game_state.selected_question + 1;
|
||||
game_state.answer_count = 0;
|
||||
|
||||
clearInterval(timer_interval);
|
||||
timer(game_state.timer_res);
|
||||
});
|
||||
|
||||
socket.on('solutions', (_) => {
|
||||
timer_res = '0';
|
||||
clearInterval(timer_interval);
|
||||
|
||||
game_state.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;
|
||||
|
||||
game_state.final_results = data;
|
||||
game_state.timer_res = '0';
|
||||
game_state.final_results = data;
|
||||
});
|
||||
|
||||
socket.on('everyone_answered', (_) => {
|
||||
timer_res = '0';
|
||||
game_state.timer_res = '0';
|
||||
});
|
||||
|
||||
socket.on('question_results', (data) => {
|
||||
console.log('question_results:', data);
|
||||
question_results = data;
|
||||
timer_res = '0';
|
||||
|
||||
game_state.question_results = data;
|
||||
game_state.timer_res = '0';
|
||||
});
|
||||
|
||||
socket.on('player_answer', (_) => {
|
||||
answer_count += 1;
|
||||
game_state.answer_count += 1;
|
||||
});
|
||||
|
||||
const timer = (time: string) => {
|
||||
let seconds = Number(time);
|
||||
timer_interval = setInterval(() => {
|
||||
if (timer_res === '0') {
|
||||
if (game_state.timer_res === '0') {
|
||||
clearInterval(timer_interval);
|
||||
return;
|
||||
} else {
|
||||
seconds--;
|
||||
}
|
||||
|
||||
timer_res = seconds.toString();
|
||||
game_state.timer_res = seconds.toString();
|
||||
}, 1000);
|
||||
};
|
||||
@@ -123,57 +88,51 @@ SPDX-License-Identifier: MPL-2.0
|
||||
const socket_game_controls: SocketGameControls = new SocketGameControls(socket);
|
||||
</script>
|
||||
|
||||
{#if control_visible}
|
||||
{#if game_state.control_visible}
|
||||
<Controls
|
||||
{bg_color}
|
||||
{selected_question}
|
||||
{quiz_data}
|
||||
bind:timer_res
|
||||
{final_results}
|
||||
{socket_game_controls}
|
||||
{question_results}
|
||||
{game_token}
|
||||
{shown_question_now}
|
||||
bind:game_state
|
||||
/>
|
||||
{/if}
|
||||
{#if timer_res !== '0' && selected_question >= 0}
|
||||
{#if game_state.timer_res !== '0' && game_state.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"
|
||||
class:mt-10={game_state.control_visible}
|
||||
style="width: {(100 / parseInt(game_state.quiz_data.questions[game_state.selected_question].time)) *
|
||||
parseInt(game_state.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}
|
||||
<div class="w-full h-full" class:pt-28={game_state.control_visible} class:pt-12={!game_state.control_visible}>
|
||||
{#if game_state.timer_res !== undefined && !final_results_clicked && !game_state.question_results}
|
||||
<!-- Question is shown -->
|
||||
{#if quiz_data.questions[selected_question].type === QuizQuestionType.SLIDE}
|
||||
{#if game_state.quiz_data.questions[game_state.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]} />
|
||||
<c.default question={game_state.quiz_data.questions[game_state.selected_question]} />
|
||||
{/await}
|
||||
{:else}
|
||||
<Question {quiz_data} {selected_question} {timer_res} {answer_count} {default_colors} />
|
||||
<Question quiz_data={game_state.quiz_data} selected_question={game_state.selected_question} timer_res={game_state.timer_res} answer_count={game_state.answer_count} default_colors={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 game_state.timer_res === '0' && JSON.stringify(game_state.final_results) === JSON.stringify( [null] ) && game_state.quiz_data.questions[game_state.selected_question].type !== QuizQuestionType.SLIDE && game_state.question_results !== null && game_state.quiz_data.questions[game_state.selected_question]?.hide_results !== true}
|
||||
{#if game_state.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}
|
||||
{:else if game_state.quiz_data.questions[game_state.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]}
|
||||
data={game_state.question_results}
|
||||
question={game_state.quiz_data.questions[game_state.selected_question]}
|
||||
/>
|
||||
{/await}
|
||||
{:else}
|
||||
@@ -181,24 +140,24 @@ SPDX-License-Identifier: MPL-2.0
|
||||
<Spinner />
|
||||
{:then c}
|
||||
<c.default
|
||||
bind:data={player_scores}
|
||||
question={quiz_data.questions[selected_question]}
|
||||
new_data={question_results}
|
||||
bind:data={game_state.player_scores}
|
||||
question={game_state.quiz_data.questions[game_state.selected_question]}
|
||||
new_data={game_state.question_results}
|
||||
/>
|
||||
{/await}
|
||||
{/if}
|
||||
{/if}
|
||||
<br />
|
||||
{#if selected_question === -1}
|
||||
{#if game_state.selected_question === -1}
|
||||
<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}
|
||||
<h1 class="text-7xl text-center">{@html game_state.quiz_data.title}</h1>
|
||||
<p class="text-3xl pt-8 text-center">{@html game_state.quiz_data.description}</p>
|
||||
{#if game_state.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}"
|
||||
src="/api/v1/storage/download/{game_state.quiz_data.cover_image}"
|
||||
alt="Not provided"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -6,35 +6,21 @@ SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
<script lang="ts">
|
||||
import { QuizQuestionType } from '$lib/quiz_types';
|
||||
import type { QuizData } from '$lib/quiz_types';
|
||||
import type { Socket } from 'socket.io-client';
|
||||
import { getLocalization } from '$lib/i18n';
|
||||
import { SocketGameControls } from '$lib/play/admin/socket_game_controls.ts';
|
||||
import { GameState } from '$lib/play/admin/game_state.ts';
|
||||
|
||||
interface Props {
|
||||
bg_color: string;
|
||||
selected_question: number;
|
||||
quiz_data: QuizData;
|
||||
timer_res: string;
|
||||
final_results: any;
|
||||
socket_game_controls: SocketGameControls;
|
||||
game_token: string;
|
||||
question_results: any;
|
||||
shown_question_now: number;
|
||||
game_state: GameState;
|
||||
}
|
||||
|
||||
let {
|
||||
bg_color,
|
||||
selected_question,
|
||||
quiz_data,
|
||||
timer_res = $bindable(),
|
||||
final_results,
|
||||
socket_game_controls,
|
||||
game_token,
|
||||
question_results,
|
||||
shown_question_now,
|
||||
game_state = $bindable()
|
||||
}: Props = $props();
|
||||
|
||||
@@ -42,7 +28,6 @@ SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
const show_solutions = () => {
|
||||
socket_game_controls.show_solutions();
|
||||
timer_res = '0';
|
||||
game_state.timer_res = '0';
|
||||
};
|
||||
</script>
|
||||
@@ -53,60 +38,60 @@ SPDX-License-Identifier: MPL-2.0
|
||||
class:text-black={bg_color}
|
||||
>
|
||||
<p class="mr-auto ml-0 col-start-1 col-end-1">
|
||||
{selected_question === -1 ? '0' : selected_question + 1}
|
||||
/{quiz_data.questions.length}
|
||||
{game_state.selected_question === -1 ? '0' : game_state.selected_question + 1}
|
||||
/{game_state.quiz_data.questions.length}
|
||||
</p>
|
||||
<div class="justify-self-end ml-auto mr-0 col-start-3 col-end-3">
|
||||
{#if selected_question + 1 === quiz_data.questions.length && ((timer_res === '0' && question_results !== null) || quiz_data?.questions?.[selected_question]?.type === QuizQuestionType.SLIDE)}
|
||||
{#if JSON.stringify(final_results) === JSON.stringify([null])}
|
||||
{#if game_state.selected_question + 1 === game_state.quiz_data.questions.length && ((game_state.timer_res === '0' && game_state.question_results !== null) || game_state.quiz_data?.questions?.[game_state.selected_question]?.type === QuizQuestionType.SLIDE)}
|
||||
{#if JSON.stringify(game_state.final_results) === JSON.stringify([null])}
|
||||
<button onclick={() => socket_game_controls.get_final_results()} class="admin-button"
|
||||
>{$t('admin_page.get_final_results')}
|
||||
</button>
|
||||
{/if}
|
||||
{:else if timer_res === '0' || selected_question === -1}
|
||||
{#if (selected_question + 1 !== quiz_data.questions.length && question_results !== null) || selected_question === -1}
|
||||
{:else if game_state.timer_res === '0' || game_state.selected_question === -1}
|
||||
{#if (game_state.selected_question + 1 !== game_state.quiz_data.questions.length && game_state.question_results !== null) || game_state.selected_question === -1}
|
||||
<button
|
||||
onclick={() => {
|
||||
socket_game_controls.set_question_number(selected_question + 1);
|
||||
socket_game_controls.set_question_number(game_state.selected_question + 1);
|
||||
}}
|
||||
class="admin-button"
|
||||
>{$t('admin_page.next_question', { question: selected_question + 2 })}
|
||||
>{$t('admin_page.next_question', { question: game_state.selected_question + 2 })}
|
||||
</button>
|
||||
{/if}
|
||||
{#if question_results === null && selected_question !== -1}
|
||||
{#if quiz_data.questions[selected_question].type === QuizQuestionType.SLIDE}
|
||||
{#if game_state.question_results === null && game_state.selected_question !== -1}
|
||||
{#if game_state.quiz_data.questions[game_state.selected_question].type === QuizQuestionType.SLIDE}
|
||||
<button
|
||||
onclick={() => {
|
||||
socket_game_controls.set_question_number(selected_question + 1);
|
||||
socket_game_controls.set_question_number(game_state.selected_question + 1);
|
||||
}}
|
||||
class="admin-button"
|
||||
>{$t('admin_page.next_question', { question: selected_question + 2 })}
|
||||
>{$t('admin_page.next_question', { question: game_state.selected_question + 2 })}
|
||||
</button>
|
||||
{:else if quiz_data.questions[selected_question]?.hide_results === true}
|
||||
{:else if game_state.quiz_data.questions[game_state.selected_question]?.hide_results === true}
|
||||
<button
|
||||
onclick={() => {
|
||||
socket_game_controls.get_question_results(game_token, shown_question_now);
|
||||
socket_game_controls.get_question_results(game_token, game_state.shown_question_now);
|
||||
setTimeout(() => {
|
||||
socket_game_controls.set_question_number(selected_question + 1);
|
||||
socket_game_controls.set_question_number(game_state.selected_question + 1);
|
||||
}, 200);
|
||||
}}
|
||||
class="admin-button"
|
||||
>{$t('admin_page.next_question', { question: selected_question + 2 })}
|
||||
>{$t('admin_page.next_question', { question: game_state.selected_question + 2 })}
|
||||
</button>
|
||||
{:else}
|
||||
<button onclick={() => socket_game_controls.get_question_results(game_token, shown_question_now)} class="admin-button"
|
||||
<button onclick={() => socket_game_controls.get_question_results(game_token, game_state.shown_question_now)} class="admin-button"
|
||||
>{$t('admin_page.show_results')}
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
{:else if selected_question !== -1}
|
||||
{#if quiz_data.questions[selected_question].type === QuizQuestionType.SLIDE}
|
||||
{:else if game_state.selected_question !== -1}
|
||||
{#if game_state.quiz_data.questions[game_state.selected_question].type === QuizQuestionType.SLIDE}
|
||||
<button
|
||||
onclick={() => {
|
||||
socket_game_controls.set_question_number(selected_question + 1);
|
||||
socket_game_controls.set_question_number(game_state.selected_question + 1);
|
||||
}}
|
||||
class="admin-button"
|
||||
>{$t('admin_page.next_question', { question: selected_question + 2 })}
|
||||
>{$t('admin_page.next_question', { question: game_state.selected_question + 2 })}
|
||||
</button>
|
||||
{:else}
|
||||
<button onclick={show_solutions} class="admin-button"
|
||||
|
||||
@@ -11,15 +11,16 @@ SPDX-License-Identifier: MPL-2.0
|
||||
import GrayButton from '$lib/components/buttons/gray.svelte';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { SocketGameControls } from '$lib/play/admin/socket_game_controls.ts';
|
||||
import { GameState } from '$lib/play/admin/game_state';
|
||||
|
||||
interface Props {
|
||||
game_pin: string;
|
||||
players: any;
|
||||
game_state: GameState;
|
||||
socket_game_controls: SocketGameControls;
|
||||
cqc_code: string;
|
||||
}
|
||||
|
||||
let { game_pin, players = $bindable(), socket_game_controls, cqc_code = $bindable() }: Props = $props();
|
||||
let { game_pin, game_state = $bindable(), socket_game_controls, cqc_code = $bindable() }: Props = $props();
|
||||
|
||||
let fullscreen_open = $state(false);
|
||||
const { t } = getLocalization();
|
||||
@@ -55,13 +56,13 @@ SPDX-License-Identifier: MPL-2.0
|
||||
<div class="m-auto">
|
||||
<div class="flex justify-center my-4">
|
||||
<p class="m-auto text-2xl">
|
||||
{#if players.length <= 1}
|
||||
{#if game_state.players.length <= 1}
|
||||
{$t('play_page.players_waiting', {
|
||||
count: players.length ?? 0
|
||||
count: game_state.players.length ?? 0
|
||||
})}
|
||||
{:else}
|
||||
{$t('play_page.players_waiting_plural', {
|
||||
count: players.length ?? 0
|
||||
count: game_state.players.length ?? 0
|
||||
})}
|
||||
{/if}
|
||||
</p>
|
||||
@@ -74,13 +75,13 @@ SPDX-License-Identifier: MPL-2.0
|
||||
{:else}
|
||||
<div class="flex justify-center">
|
||||
<p class="m-auto text-2xl">
|
||||
{#if players.length <= 1}
|
||||
{#if game_state.players.length <= 1}
|
||||
{$t('play_page.players_waiting', {
|
||||
count: players.length ?? 0
|
||||
count: game_state.players.length ?? 0
|
||||
})}
|
||||
{:else}
|
||||
{$t('play_page.players_waiting_plural', {
|
||||
count: players.length ?? 0
|
||||
count: game_state.players.length ?? 0
|
||||
})}
|
||||
{/if}
|
||||
</p>
|
||||
@@ -93,7 +94,7 @@ SPDX-License-Identifier: MPL-2.0
|
||||
<div class="flex justify-center w-full mt-4">
|
||||
<div>
|
||||
<GrayButton
|
||||
disabled={players.length < 1}
|
||||
disabled={game_state.players.length < 1}
|
||||
onclick={() => {
|
||||
socket_game_controls.start_game()
|
||||
}}
|
||||
@@ -102,13 +103,13 @@ SPDX-License-Identifier: MPL-2.0
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row w-full mt-4 px-10 flex-wrap">
|
||||
{#if players.length > 0}
|
||||
{#each players as player}
|
||||
{#if game_state.players.length > 0}
|
||||
{#each game_state.players as player}
|
||||
<div class="p-2 m-2 border-2 border-[#B07156] rounded-sm hover:cursor-pointer">
|
||||
<span
|
||||
class="hover:line-through text-lg"
|
||||
onclick={() => {
|
||||
socket_game_controls.kick_player(player.username, players);
|
||||
socket_game_controls.kick_player(player.username, game_state.players);
|
||||
}}>{player.username}</span
|
||||
>
|
||||
<!-- <button>{$t('words.kick')}</button>-->
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
export class GameState {
|
||||
public game_id: string;
|
||||
public players: any[];
|
||||
public selected_question: number;
|
||||
public timer_res: string;
|
||||
public question_results: any;
|
||||
public answer_count: number;
|
||||
public shown_question_now: number;
|
||||
public final_results: any;
|
||||
public game_started: boolean;
|
||||
import type { Player, PlayerAnswer } from '$lib/admin.ts';
|
||||
import { QuizData } from '$lib/quiz_types';
|
||||
|
||||
constructor(game_id: string, players: any[]) {
|
||||
this.game_id = game_id;
|
||||
this.players = players;
|
||||
this.selected_question = -1;
|
||||
this.timer_res = '0';
|
||||
this.question_results = null;
|
||||
this.answer_count = 0;
|
||||
this.shown_question_now = -1;
|
||||
this.final_results = null;
|
||||
this.game_started = false;
|
||||
}
|
||||
export interface IGameState {
|
||||
game_id: string;
|
||||
players: Player[];
|
||||
player_scores: Record<string, number>;
|
||||
selected_question: number;
|
||||
timer_res: string;
|
||||
question_results: any;
|
||||
answer_count: number;
|
||||
shown_question_now: number;
|
||||
final_results: Array<null> | Array<Array<PlayerAnswer>>;
|
||||
game_started: boolean;
|
||||
quiz_data: QuizData;
|
||||
control_visible: boolean;
|
||||
|
||||
constructor(game_id: string);
|
||||
}
|
||||
@@ -5,12 +5,9 @@ SPDX-License-Identifier: MPL-2.0
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import type { QuizData } from '$lib/quiz_types';
|
||||
|
||||
import { socket } from '$lib/socket';
|
||||
import { getLocalization } from '$lib/i18n';
|
||||
import { navbarVisible } from '$lib/stores.svelte.ts';
|
||||
import type { PlayerAnswer, Player } from '$lib/admin.ts';
|
||||
import SomeAdminScreen from '$lib/admin.svelte';
|
||||
import GameNotStarted from '$lib/play/admin/game_not_started.svelte';
|
||||
import { browser } from '$app/environment';
|
||||
@@ -19,7 +16,7 @@ SPDX-License-Identifier: MPL-2.0
|
||||
import GrayButton from '$lib/components/buttons/gray.svelte';
|
||||
import { page } from '$app/state';
|
||||
import { SocketGameControls } from '$lib/play/admin/socket_game_controls.ts';
|
||||
import { GameState } from '$lib/play/admin/game_state.ts';
|
||||
import { IGameState } from '$lib/play/admin/game_state.ts';
|
||||
import { QuizQuestionType } from '$lib/quiz_types';
|
||||
|
||||
navbarVisible.visible = false;
|
||||
@@ -35,25 +32,50 @@ SPDX-License-Identifier: MPL-2.0
|
||||
data: any;
|
||||
}
|
||||
|
||||
class GameState implements IGameState {
|
||||
public game_id: string;
|
||||
public players: Player[];
|
||||
public player_scores: Record<string, number>;
|
||||
public selected_question: number;
|
||||
public timer_res: string;
|
||||
public question_results: any;
|
||||
public answer_count: number;
|
||||
public shown_question_now: number;
|
||||
public final_results: Array<null> | Array<Array<PlayerAnswer>>;
|
||||
public game_started: boolean;
|
||||
public quiz_data: QuizData;
|
||||
public control_visible: boolean;
|
||||
|
||||
constructor(game_id: string) {
|
||||
this.game_id = game_id;
|
||||
this.players = $state([]);
|
||||
this.player_scores = $state({});
|
||||
this.selected_question = $state(-1);
|
||||
this.timer_res = $state(undefined);
|
||||
this.quiz_data = $state(null);
|
||||
this.control_visible = $state(true);
|
||||
this.shown_question_now = $state(-1);
|
||||
this.final_results = $state([null]);
|
||||
this.game_started = $state(false);
|
||||
this.question_results = $state(null);
|
||||
this.answer_count = $state(0);
|
||||
}
|
||||
}
|
||||
|
||||
let { data }: Props = $props();
|
||||
let game_mode = $state();
|
||||
let { auto_connect, game_token } = $state(data);
|
||||
const game_pin = data.game_pin;
|
||||
|
||||
let players: Array<Player> = $state([]);
|
||||
let player_scores = $state({});
|
||||
let errorMessage = $state('');
|
||||
let game_started = $state(false);
|
||||
let quiz_data: QuizData = $state();
|
||||
let control_visible = $state(true);
|
||||
//let question_number = '0';
|
||||
// let question_results = null;
|
||||
let final_results: Array<null> | Array<Array<PlayerAnswer>> = $state([null]);
|
||||
let success = $state(false);
|
||||
let dataexport_download_a = $state();
|
||||
let warnToLeave = true;
|
||||
let export_token = $state(undefined);
|
||||
|
||||
|
||||
const socket_game_controls: SocketGameControls = new SocketGameControls(socket);
|
||||
let game_state: GameState = $state(new GameState(game_token));
|
||||
|
||||
const connect = async () => {
|
||||
socket.emit('register_as_admin', {
|
||||
game_pin: game_pin,
|
||||
@@ -73,12 +95,12 @@ SPDX-License-Identifier: MPL-2.0
|
||||
});
|
||||
|
||||
socket.on('registered_as_admin', (data) => {
|
||||
quiz_data = JSON.parse(data['game']);
|
||||
console.log(quiz_data);
|
||||
game_state.quiz_data = JSON.parse(data['game']);
|
||||
console.log(game_state.quiz_data);
|
||||
success = true;
|
||||
});
|
||||
socket.on('player_joined', (int_data) => {
|
||||
players = [...players, int_data];
|
||||
game_state.players = [...game_state.players, int_data];
|
||||
});
|
||||
socket.on('already_registered_as_admin', () => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
@@ -87,11 +109,11 @@ SPDX-License-Identifier: MPL-2.0
|
||||
});
|
||||
|
||||
socket.on('start_game', (_) => {
|
||||
game_started = true;
|
||||
game_state.game_started = true;
|
||||
});
|
||||
|
||||
socket.on('control_visibility', (data) => {
|
||||
control_visible = data.visible;
|
||||
game_state.control_visible = data.visible;
|
||||
});
|
||||
|
||||
/* socket.on('question_results', (int_data) => {
|
||||
@@ -141,40 +163,39 @@ SPDX-License-Identifier: MPL-2.0
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||
}
|
||||
|
||||
let bg_color = $derived(quiz_data ? quiz_data.background_color : undefined);
|
||||
let bg_image = $derived(quiz_data ? quiz_data.background_image : undefined);
|
||||
let bg_color = $derived(game_state.quiz_data ? game_state.quiz_data.background_color : undefined);
|
||||
let bg_image = $derived(game_state.quiz_data ? game_state.quiz_data.background_image : undefined);
|
||||
let results_saved = $state(false);
|
||||
|
||||
let show_final_results = $derived(JSON.stringify(final_results) !== JSON.stringify([null]));
|
||||
|
||||
const socket_game_controls: SocketGameControls = new SocketGameControls(socket);
|
||||
let game_state: GameState = $state(new GameState(game_token));
|
||||
let show_final_results = $derived(JSON.stringify(game_state.final_results) !== JSON.stringify([null]));
|
||||
|
||||
// This function in called in every keyboard event in this page
|
||||
const next_action = (e: KeyboardEvent) => {
|
||||
if((e.key in ["Enter", " "])) return; // Don't catch events other than enter or spacebar
|
||||
|
||||
if(!game_started && players.length > 0) { // Game not started with conditions matched
|
||||
console.log(game_state);
|
||||
|
||||
if(!game_state.game_started && game_state.players.length > 0) { // Game not started with conditions matched
|
||||
socket_game_controls.start_game()
|
||||
}
|
||||
|
||||
// This is a messy condition to check if we can show final results
|
||||
else if(game_state.selected_question + 1 === quiz_data.questions.length && ((game_state.timer_res === '0' && game_state.question_results !== null) || quiz_data?.questions?.[game_state.selected_question]?.type === QuizQuestionType.SLIDE)){
|
||||
else if(game_state.selected_question + 1 === game_state.quiz_data.questions.length && ((game_state.timer_res === '0' && game_state.question_results !== null) || game_state.quiz_data?.questions?.[game_state.selected_question]?.type === QuizQuestionType.SLIDE)){
|
||||
socket_game_controls.get_final_results();
|
||||
}
|
||||
|
||||
// Game is ongoing and the current question is eather finished or quiz just started
|
||||
// Game is ongoing and the current question is either finished or quiz just started
|
||||
else if(game_state.timer_res === '0' || game_state.selected_question === -1) {
|
||||
// We are eather in the beginning of the quiz or in the end of it
|
||||
if((game_state.selected_question + 1 !== quiz_data.questions.length && game_state.question_results !== null) || game_state.selected_question === -1) {
|
||||
// We are either in the beginning of the quiz or in the end of it
|
||||
if((game_state.selected_question + 1 !== game_state.quiz_data.questions.length && game_state.question_results !== null) || game_state.selected_question === -1) {
|
||||
socket_game_controls.set_question_number(game_state.selected_question + 1);
|
||||
}
|
||||
// Else we are in the middle of a question
|
||||
else if(game_state.question_results === null && game_state.selected_question !== -1) {
|
||||
if(quiz_data.questions[game_state.selected_question].type === QuizQuestionType.SLIDE) {
|
||||
if(game_state.quiz_data.questions[game_state.selected_question].type === QuizQuestionType.SLIDE) {
|
||||
socket_game_controls.set_question_number(game_state.selected_question + 1);
|
||||
}
|
||||
else if(quiz_data.questions[game_state.selected_question]?.hide_results === true) {
|
||||
else if(game_state.quiz_data.questions[game_state.selected_question]?.hide_results === true) {
|
||||
socket_game_controls.get_question_results(game_token, game_state.shown_question_now);
|
||||
setTimeout(() => {
|
||||
socket_game_controls.set_question_number(game_state.selected_question + 1);
|
||||
@@ -188,7 +209,7 @@ SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
// Game started, question not finished we check if the question is slide or not
|
||||
else if(game_state.selected_question !== -1) {
|
||||
switch(quiz_data.questions[game_state.selected_question].type) {
|
||||
switch(game_state.quiz_data.questions[game_state.selected_question].type) {
|
||||
case QuizQuestionType.SLIDE:
|
||||
socket_game_controls.set_question_number(game_state.selected_question + 1);
|
||||
break;
|
||||
@@ -213,8 +234,8 @@ SPDX-License-Identifier: MPL-2.0
|
||||
: `unset`}; background-color: {bg_color ? bg_color : 'transparent'}"
|
||||
class:text-black={bg_color}
|
||||
>
|
||||
{#if JSON.stringify(final_results) !== JSON.stringify([null])}
|
||||
{#if control_visible}
|
||||
{#if JSON.stringify(game_state.final_results) !== JSON.stringify([null])}
|
||||
{#if game_state.control_visible}
|
||||
<div class="w-screen flex justify-center mt-16">
|
||||
<div class="w-fit">
|
||||
{#if export_token === undefined}
|
||||
@@ -254,27 +275,23 @@ SPDX-License-Identifier: MPL-2.0
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<FinalResults bind:data={player_scores} {show_final_results} />
|
||||
<FinalResults bind:data={game_state.player_scores} {show_final_results} />
|
||||
{/if}
|
||||
{#if !success}
|
||||
{#if errorMessage !== ''}
|
||||
<p class="text-red-700">{errorMessage}</p>
|
||||
{/if}
|
||||
{:else if !game_started}
|
||||
{:else if !game_state.game_started}
|
||||
<GameNotStarted
|
||||
{game_pin}
|
||||
bind:players
|
||||
bind:game_state
|
||||
{socket_game_controls}
|
||||
cqc_code={page.url.searchParams.get('cqc_code')}
|
||||
/>
|
||||
{:else}
|
||||
<SomeAdminScreen
|
||||
bind:final_results
|
||||
{game_token}
|
||||
bind:quiz_data
|
||||
{bg_color}
|
||||
bind:player_scores
|
||||
{control_visible}
|
||||
bind:game_state
|
||||
/>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user