Added Image Questions

This commit is contained in:
2025-09-11 19:06:01 +02:00
parent fd4b2fd341
commit b98e25d4e7
7 changed files with 127 additions and 7 deletions

View File

@@ -0,0 +1,55 @@
<script lang="ts">
import type { ImageQuestion } from "./games/games";
const path = "/images/";
interface Props {
question: ImageQuestion;
showAnswer: boolean;
showQuestion: boolean;
isBuzzed: boolean;
[key: string]: unknown;
}
let { question, showAnswer, showQuestion, isBuzzed }: Props = $props();
</script>
<div class="mb-4 flex w-full grow flex-col items-center gap-2 text-6xl">
{#if showQuestion || showAnswer}
<div class="flex grow items-center">
<div class="text-center">{question.data.question}</div>
</div>
<div class="container grow-6">
<img
src={path + question.data.image}
alt={path + question.data.image}
class={isBuzzed ? "blurry" : ""}
/>
</div>
{/if}
{#if showAnswer}
<div class="flex grow items-center text-center">
{question.data.answer}
</div>
{/if}
</div>
<style>
.container {
position: relative;
}
.container > img {
position: absolute;
top: 50%;
left: 50%;
max-height: 100%;
max-width: 100%;
display: block;
transform: translate(-50%, -50%);
}
.blurry {
filter: blur(60px);
}
</style>

View File

@@ -6,5 +6,7 @@ export enum MessageType {
HIDE_ANSWER = "HIDE_ANSWER", HIDE_ANSWER = "HIDE_ANSWER",
SHOW_QUESTION = "SHOW_QUESTION", SHOW_QUESTION = "SHOW_QUESTION",
HIDE_QUESTION = "HIDE_QUESTION", HIDE_QUESTION = "HIDE_QUESTION",
BUZZER_PRESSED = "BUZZER_PRESSED",
BUZZER_RELEASED = "BUZZER_RELEASED",
VISITED_QUESTIONS = "VISITED_QUESTIONS" VISITED_QUESTIONS = "VISITED_QUESTIONS"
} }

View File

@@ -28,17 +28,19 @@ const games: Games = [
}, },
{ {
points: 200, points: 200,
type: "SIMPLE", type: "IMAGE",
data: { data: {
question: "Question 2?", question: "Question 2?",
image: "firstImage.jpg",
answer: "Answer 2" answer: "Answer 2"
} }
}, },
{ {
points: 300, points: 300,
type: "SIMPLE", type: "IMAGE",
data: { data: {
question: "Question 3?", question: "Question 3?",
image: "test/secondImage.jpg",
answer: "Answer 3" answer: "Answer 3"
} }
}, },
@@ -1222,7 +1224,7 @@ const games: Games = [
} }
]; ];
export type QuestionType = "SIMPLE" | "MULTIPLE_CHOICE"; export type QuestionType = "SIMPLE" | "MULTIPLE_CHOICE" | "IMAGE";
export type Question = { export type Question = {
points: number; points: number;
@@ -1248,16 +1250,28 @@ export type MultipleChoiceQuestion = Question & {
}; };
}; };
export type ImageQuestion = Question & {
type: "IMAGE";
data: {
question: string;
image: string;
answer: string;
};
};
export function isSimpleQuestion(question: Question): question is SimpleQuestion { export function isSimpleQuestion(question: Question): question is SimpleQuestion {
return (question as SimpleQuestion).type === "SIMPLE"; return (question as SimpleQuestion).type === "SIMPLE";
} }
export function isMultipleChoiceQuestion(question: Question): question is MultipleChoiceQuestion { export function isMultipleChoiceQuestion(question: Question): question is MultipleChoiceQuestion {
return (question as MultipleChoiceQuestion).type === "MULTIPLE_CHOICE"; return (question as MultipleChoiceQuestion).type === "MULTIPLE_CHOICE";
} }
export function isImageQuestion(question: Question): question is ImageQuestion {
return (question as ImageQuestion).type === "IMAGE";
}
export type Category = { export type Category = {
name: string; name: string;
questions: (SimpleQuestion | MultipleChoiceQuestion)[]; questions: (SimpleQuestion | MultipleChoiceQuestion | ImageQuestion)[];
}; };
export type Wall = { export type Wall = {

View File

@@ -3,11 +3,12 @@
import { page } from "$app/state"; import { page } from "$app/state";
import { error } from "@sveltejs/kit"; import { error } from "@sveltejs/kit";
import SimpleQuestionComponent from "$lib/SimpleQuestionComponent.svelte"; import SimpleQuestionComponent from "$lib/SimpleQuestionComponent.svelte";
import { isMultipleChoiceQuestion, isSimpleQuestion } from "$lib/games/games"; import { isImageQuestion, isMultipleChoiceQuestion, isSimpleQuestion } from "$lib/games/games";
import ws from "$lib/websocket.svelte"; import ws from "$lib/websocket.svelte";
import { MessageType } from "$lib/MessageType"; import { MessageType } from "$lib/MessageType";
import { untrack } from "svelte"; import { untrack } from "svelte";
import MultipleChoiceQuestionComponent from "$lib/MultipleChoiceQuestionComponent.svelte"; import MultipleChoiceQuestionComponent from "$lib/MultipleChoiceQuestionComponent.svelte";
import ImageQuestionComponent from "$lib/ImageQuestionComponent.svelte";
console.log("wall:", page.params.wall); console.log("wall:", page.params.wall);
@@ -60,6 +61,7 @@
let showAnswer = $state(false); let showAnswer = $state(false);
let showQuestion = $state(false); let showQuestion = $state(false);
let isBuzzed = $state(false);
$effect(() => { $effect(() => {
if (ws.messageNum <= 0) return; if (ws.messageNum <= 0) return;
@@ -92,6 +94,18 @@
showAnswer = false; showAnswer = false;
}); });
} }
if (json.type == MessageType.BUZZER_PRESSED) {
ws.nextMessage();
untrack(() => {
isBuzzed = true;
});
}
if (json.type == MessageType.BUZZER_RELEASED) {
ws.nextMessage();
untrack(() => {
isBuzzed = false;
});
}
} catch (e) {} } catch (e) {}
}); });
</script> </script>
@@ -110,6 +124,8 @@
<SimpleQuestionComponent {question} {showAnswer} {showQuestion} /> <SimpleQuestionComponent {question} {showAnswer} {showQuestion} />
{:else if isMultipleChoiceQuestion(question)} {:else if isMultipleChoiceQuestion(question)}
<MultipleChoiceQuestionComponent {question} {showAnswer} {showQuestion} /> <MultipleChoiceQuestionComponent {question} {showAnswer} {showQuestion} />
{:else if isImageQuestion(question)}
<ImageQuestionComponent {question} {showAnswer} {showQuestion} {isBuzzed} />
{:else} {:else}
<p>Type of question unknown</p> <p>Type of question unknown</p>
{/if} {/if}

View File

@@ -5,8 +5,8 @@
import { import {
isMultipleChoiceQuestion, isMultipleChoiceQuestion,
isSimpleQuestion, isSimpleQuestion,
type Game, isImageQuestion,
type Question type Game
} from "$lib/games/games"; } from "$lib/games/games";
import ws from "$lib/websocket.svelte"; import ws from "$lib/websocket.svelte";
import { page } from "$app/state"; import { page } from "$app/state";
@@ -17,6 +17,7 @@
import PlusMinusButton from "$lib/PlusMinusButton.svelte"; import PlusMinusButton from "$lib/PlusMinusButton.svelte";
import type { VisitedQuestions } from "$lib/Types.js"; import type { VisitedQuestions } from "$lib/Types.js";
import MultipleChoiceQuestionComponent from "$lib/MultipleChoiceQuestionComponent.svelte"; import MultipleChoiceQuestionComponent from "$lib/MultipleChoiceQuestionComponent.svelte";
import ImageQuestionComponent from "$lib/ImageQuestionComponent.svelte";
let startDisabled = $state(true); let startDisabled = $state(true);
@@ -67,6 +68,7 @@
public answerIsShowing = $state(false); public answerIsShowing = $state(false);
public questionIsShowing = $state(false); public questionIsShowing = $state(false);
public isBuzzed = $state(false);
constructor(game: Game) { constructor(game: Game) {
this.game = game; this.game = game;
@@ -166,6 +168,20 @@
}); });
} }
buzzerPressed() {
this.isBuzzed = true;
ws.sendMessage({
type: MessageType.BUZZER_PRESSED
});
}
buzzerReleased() {
this.isBuzzed = false;
ws.sendMessage({
type: MessageType.BUZZER_RELEASED
});
}
showQuestion() { showQuestion() {
this.questionIsShowing = true; this.questionIsShowing = true;
ws.sendMessage({ ws.sendMessage({
@@ -209,6 +225,7 @@
setupGoingBack(): void { setupGoingBack(): void {
this.answerIsShowing = false; this.answerIsShowing = false;
this.questionIsShowing = false; this.questionIsShowing = false;
this.isBuzzed = false;
} }
finishQuestion(): void { finishQuestion(): void {
@@ -342,6 +359,13 @@
showAnswer={true} showAnswer={true}
showQuestion={true} showQuestion={true}
/> />
{:else if isImageQuestion(gameManager.question)}
<ImageQuestionComponent
question={gameManager.question}
showAnswer={true}
showQuestion={true}
isBuzzed={false}
/>
{:else} {:else}
<p>Type of question unknown</p> <p>Type of question unknown</p>
{/if} {/if}
@@ -366,6 +390,15 @@
>Antwort aufdecken</button >Antwort aufdecken</button
> >
{/if} {/if}
{#if gameManager.isBuzzed}
<button class="btn" onclick={() => gameManager.buzzerReleased()}
>Entbuzzern</button
>
{:else}
<button class="btn" onclick={() => gameManager.buzzerPressed()}
>Buzzern</button
>
{/if}
{#each gameManager.players as player} {#each gameManager.players as player}
<PlusMinusButton <PlusMinusButton
label={player.name} label={player.name}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 MiB