91 lines
2.9 KiB
Svelte
91 lines
2.9 KiB
Svelte
<script lang="ts">
|
|
import AudioPlayerComponent from "./AudioPlayerComponent.svelte";
|
|
import type { AudioMultipleChoiceQuestion } from "./games/games";
|
|
import { url } from "./util";
|
|
|
|
const path = "/sounds/";
|
|
|
|
interface Props {
|
|
question: AudioMultipleChoiceQuestion;
|
|
showAnswer: boolean;
|
|
showQuestion: boolean;
|
|
showPlayer: boolean;
|
|
isLegacy?: boolean;
|
|
randomize?: boolean;
|
|
[key: string]: unknown;
|
|
}
|
|
|
|
let {
|
|
question,
|
|
showAnswer,
|
|
showQuestion,
|
|
showPlayer,
|
|
isLegacy = true,
|
|
randomize = true
|
|
}: Props = $props();
|
|
|
|
function shuffle<T>(array: T[]) {
|
|
let currentIndex = array.length;
|
|
|
|
// While there remain elements to shuffle...
|
|
while (currentIndex != 0) {
|
|
// Pick a remaining element...
|
|
let randomIndex = Math.floor(Math.random() * currentIndex);
|
|
currentIndex--;
|
|
|
|
// And swap it with the current element.
|
|
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
|
|
}
|
|
}
|
|
|
|
const answer = $derived(question.data.choices[0]);
|
|
|
|
let _choices = $derived.by(() => {
|
|
let c = [...question.data.choices];
|
|
if (randomize) shuffle(c);
|
|
return c;
|
|
});
|
|
|
|
let audioPath = $derived.by(() => {
|
|
if (question.data.audio === null) return undefined;
|
|
if (isLegacy) return `${path}${question.data.audio}`;
|
|
let audio = question.data.audio;
|
|
if (typeof audio === "string") {
|
|
return url(`/cdn/${question.owner}/${audio}`);
|
|
} else {
|
|
return url(`/cdn/${audio?.user}/${audio?._id}`);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<div class="mb-4 flex grow flex-col items-center text-6xl">
|
|
{#if showQuestion}
|
|
<div class="flex grow-1 items-center">
|
|
<div class="text-center">{question.data.question}</div>
|
|
</div>
|
|
{/if}
|
|
{#if showPlayer}
|
|
<div class="flex w-full flex-col justify-center">
|
|
{#if audioPath}
|
|
<AudioPlayerComponent src={audioPath} />
|
|
{:else}
|
|
<div class="flex h-full w-full flex-col items-center justify-center">
|
|
<div class="text-[128px] text-gray-300">
|
|
<i class="fa-solid fa-file-audio"></i>
|
|
</div>
|
|
<div class="text-[24px] text-gray-500 select-none">Kein Audio ausgewählt</div>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
{#if showQuestion}
|
|
<div class="flex w-full grow-1 flex-wrap items-center justify-around gap-2">
|
|
{#each _choices as choice}
|
|
<div class="choiceCard {showAnswer && choice === answer ? 'choice-answer' : ''}">
|
|
{choice}
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
</div>
|