From 8e1cfbcb6f8e98bc37ffa4270c61943b4588b7c1 Mon Sep 17 00:00:00 2001 From: RezHackXYZ Date: Sun, 18 May 2025 12:42:44 +0530 Subject: [PATCH] rBD IS WORKING!!!! at least for now! --- jsconfig.json | 3 +- package.json | 2 +- src/routes/create/logic/InsertGameInDB.js | 2 +- src/routes/create/logic/StartGame.js | 17 ++-- .../DuringGame/QuetionsAwnsred.svelte | 2 +- src/routes/host/[gamePin]/logic/GameOver.js | 7 ++ .../host/[gamePin]/logic/HostsData.svelte.js | 2 +- .../host/[gamePin]/logic/WaitForAwnser.js | 32 ++++++++ .../[gamePin]/logic/onNewPlayerAwnsered.js | 23 ++++++ src/routes/host/[gamePin]/logic/startGame.js | 9 +-- src/routes/join/logic/InsertPlayerInDB.js | 15 ++-- src/routes/join/logic/joinGame.js | 9 +-- src/routes/play/[gamePin]/+page.js | 2 +- src/routes/play/[gamePin]/+page.svelte | 11 ++- .../DuringGame/PeopleAwnsered.svelte | 13 --- .../DuringGame/QuetionsAwnsred.svelte | 13 --- .../components/DuringGame/display.svelte | 9 --- .../awnseringQuetions/Awnsers.svelte | 22 +++++ .../awnseringQuetions/ProgressBar.svelte | 13 +++ .../buttons/SelectFirst.svelte | 4 + .../buttons/submitAwnser.svelte | 9 +++ .../awnseringQuetions/display.svelte | 28 +++++++ .../awnseringQuetions/text/Quetion.svelte | 7 ++ .../awnseringQuetions/text/wait.svelte | 1 + .../play/[gamePin]/logic/HostsData.svelte.js | 16 ++-- .../[gamePin]/logic/IntializeGameStart.js | 22 +++++ src/routes/play/[gamePin]/logic/NewStatus.js | 41 ++++++++++ .../play/[gamePin]/logic/SubmitAnswer.js | 31 +++++++ src/routes/play/[gamePin]/logic/startGame.js | 4 +- src/routes/results/[gamePin]/+page.js | 5 ++ src/routes/results/[gamePin]/+page.svelte | 81 +++++++++++++++++++ 31 files changed, 374 insertions(+), 81 deletions(-) create mode 100644 src/routes/host/[gamePin]/logic/GameOver.js create mode 100644 src/routes/host/[gamePin]/logic/WaitForAwnser.js create mode 100644 src/routes/host/[gamePin]/logic/onNewPlayerAwnsered.js delete mode 100644 src/routes/play/[gamePin]/components/DuringGame/PeopleAwnsered.svelte delete mode 100644 src/routes/play/[gamePin]/components/DuringGame/QuetionsAwnsred.svelte delete mode 100644 src/routes/play/[gamePin]/components/DuringGame/display.svelte create mode 100644 src/routes/play/[gamePin]/components/awnseringQuetions/Awnsers.svelte create mode 100644 src/routes/play/[gamePin]/components/awnseringQuetions/ProgressBar.svelte create mode 100644 src/routes/play/[gamePin]/components/awnseringQuetions/buttons/SelectFirst.svelte create mode 100644 src/routes/play/[gamePin]/components/awnseringQuetions/buttons/submitAwnser.svelte create mode 100644 src/routes/play/[gamePin]/components/awnseringQuetions/display.svelte create mode 100644 src/routes/play/[gamePin]/components/awnseringQuetions/text/Quetion.svelte create mode 100644 src/routes/play/[gamePin]/components/awnseringQuetions/text/wait.svelte create mode 100644 src/routes/play/[gamePin]/logic/IntializeGameStart.js create mode 100644 src/routes/play/[gamePin]/logic/NewStatus.js create mode 100644 src/routes/play/[gamePin]/logic/SubmitAnswer.js create mode 100644 src/routes/results/[gamePin]/+page.js create mode 100644 src/routes/results/[gamePin]/+page.svelte diff --git a/jsconfig.json b/jsconfig.json index d99405d..fd2b2b8 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -7,6 +7,5 @@ "module": "es2015", "types": ["svelte"] }, - "include": ["src/**/*"], - "exclude": ["node_modules/*"], + "exclude": ["**/node_modules/**", "**/build/**", "**/.svelte-kit/**", "**/out/**", "!src/**"], } diff --git a/package.json b/package.json index 7b25e2b..42d38d1 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.0.1", "type": "module", "scripts": { - "dev": "vite dev", + "dev": "vite dev --host", "build": "vite build", "preview": "vite preview", "prepare": "svelte-kit sync || echo ''", diff --git a/src/routes/create/logic/InsertGameInDB.js b/src/routes/create/logic/InsertGameInDB.js index 229396f..8502ced 100644 --- a/src/routes/create/logic/InsertGameInDB.js +++ b/src/routes/create/logic/InsertGameInDB.js @@ -1,7 +1,7 @@ import { supabase } from '$lib/supabase'; export async function createGame(questions, gamePin) { - // Insert the game into the GAMES table + const { data: gameData, error: gameError } = await supabase.from('games').insert({ creator: 'anonymous', creationdate: new Date().toISOString(), diff --git a/src/routes/create/logic/StartGame.js b/src/routes/create/logic/StartGame.js index eaa080e..d734c7a 100644 --- a/src/routes/create/logic/StartGame.js +++ b/src/routes/create/logic/StartGame.js @@ -1,18 +1,17 @@ -import { goto } from '$app/navigation'; -import { createGame } from './InsertGameInDB.js'; -import { questions } from './GameCreateData.svelte.js'; +import { createGame } from "./InsertGameInDB.js"; +import { questions } from "./GameCreateData.svelte.js"; export async function startGame() { - if (questions.v.some((q) => q.name === '')) return alert('Please fill all questions'); - if (questions.v.some((q) => q.answers.some((a) => a === ''))) return alert('Fill all options'); + if (questions.v.some((q) => q.name === "")) return alert("Please fill all questions"); + if (questions.v.some((q) => q.answers.some((a) => a === ""))) return alert("Fill all options"); if (questions.v.some((q) => q.correctAnswer === undefined)) - return alert('Select correct answers'); + return alert("Select correct answers"); const gamePin = Math.floor(Math.random() * 1000000) .toString() - .padStart(6, '0'); + .padStart(6, "0"); - createGame(questions.v, gamePin); + await createGame(questions.v, gamePin); - goto('/host/' + gamePin); + window.location.href = "/host/" + gamePin; } diff --git a/src/routes/host/[gamePin]/components/DuringGame/QuetionsAwnsred.svelte b/src/routes/host/[gamePin]/components/DuringGame/QuetionsAwnsred.svelte index c51c04d..b12bb08 100644 --- a/src/routes/host/[gamePin]/components/DuringGame/QuetionsAwnsred.svelte +++ b/src/routes/host/[gamePin]/components/DuringGame/QuetionsAwnsred.svelte @@ -7,7 +7,7 @@
diff --git a/src/routes/host/[gamePin]/logic/GameOver.js b/src/routes/host/[gamePin]/logic/GameOver.js new file mode 100644 index 0000000..6749660 --- /dev/null +++ b/src/routes/host/[gamePin]/logic/GameOver.js @@ -0,0 +1,7 @@ +import { supabase } from "$lib/supabase.js"; + +export async function GameOver(GamePin) { + await supabase.from("games").update({ status: `completed` }).eq("gamepin", GamePin); + + window.location.replace("/results/" + GamePin + "?playerID=host-null"); +} diff --git a/src/routes/host/[gamePin]/logic/HostsData.svelte.js b/src/routes/host/[gamePin]/logic/HostsData.svelte.js index c1d8316..fae9f0f 100644 --- a/src/routes/host/[gamePin]/logic/HostsData.svelte.js +++ b/src/routes/host/[gamePin]/logic/HostsData.svelte.js @@ -1,6 +1,6 @@ export let players = $state({ v: [] }); export let Status = $state({ v: "lobby" }); -export let questions = $state({ v: [] }); +export let questions = { v: [] }; export let CurrentQuestion = $state({ v: -1 }); export let currentQuestion = $state({ v: 0 }); diff --git a/src/routes/host/[gamePin]/logic/WaitForAwnser.js b/src/routes/host/[gamePin]/logic/WaitForAwnser.js new file mode 100644 index 0000000..1812132 --- /dev/null +++ b/src/routes/host/[gamePin]/logic/WaitForAwnser.js @@ -0,0 +1,32 @@ +import { supabase } from "$lib/supabase.js"; +import { onNewPlayerAwnsered } from "./onNewPlayerAwnsered.js"; +import { currentQuestion, questions } from "./HostsData.svelte.js"; + +let WaitingForAwnserConection; + +export async function WaitForAwnser(questionid, gamePin) { + if (questionid != 0) { + await supabase.removeChannel(WaitingForAwnserConection); + } + + await supabase + .from("games") + .update({ status: `question-${currentQuestion.v}` }) + .eq("gamepin", gamePin); + + WaitingForAwnserConection = supabase + .channel("answeredby-realtime") + .on( + "postgres_changes", + { + event: "INSERT", + schema: "public", + table: "answeredby", + filter: `questionid=eq.${questions.v[questionid].id}`, + }, + (payload) => { + onNewPlayerAwnsered(gamePin); + }, + ) + .subscribe(); +} diff --git a/src/routes/host/[gamePin]/logic/onNewPlayerAwnsered.js b/src/routes/host/[gamePin]/logic/onNewPlayerAwnsered.js new file mode 100644 index 0000000..8c1176d --- /dev/null +++ b/src/routes/host/[gamePin]/logic/onNewPlayerAwnsered.js @@ -0,0 +1,23 @@ +import { + Totalplayers, + PeopleAwnseredQ, + currentQuestion, + totalQuetions, +} from "./HostsData.svelte.js"; +import { GameOver } from "./GameOver.js"; +import { WaitForAwnser } from "./WaitForAwnser.js"; + +export async function onNewPlayerAwnsered(GamePin) { + PeopleAwnseredQ.v++; + + if (PeopleAwnseredQ.v == Totalplayers.v) { + currentQuestion.v++; + if (currentQuestion.v == totalQuetions.v) { + GameOver(GamePin); + return; + } + PeopleAwnseredQ.v = 0; + + WaitForAwnser(currentQuestion.v, GamePin); + } +} diff --git a/src/routes/host/[gamePin]/logic/startGame.js b/src/routes/host/[gamePin]/logic/startGame.js index 5941e99..f0c88b1 100644 --- a/src/routes/host/[gamePin]/logic/startGame.js +++ b/src/routes/host/[gamePin]/logic/startGame.js @@ -1,6 +1,7 @@ import { supabase } from "$lib/supabase.js"; import { LobbyConnection } from "./UpdatePlayersList.js"; import { questions, Status, CurrentQuestion, currentQuestion } from "./HostsData.svelte.js"; +import { WaitForAwnser } from "./WaitForAwnser.js"; export async function startGame(gamePin) { await supabase.removeChannel(LobbyConnection); @@ -12,14 +13,10 @@ export async function startGame(gamePin) { .select("*") .eq("gameid", Number(gamePin)) .order("id", { ascending: true }); + questions.v = data; CurrentQuestion.v = 0; - await supabase - .from("games") - .update({ status: `question-${currentQuestion.v}` }) - .eq("gamepin", gamePin); - - + WaitForAwnser(0, gamePin); } diff --git a/src/routes/join/logic/InsertPlayerInDB.js b/src/routes/join/logic/InsertPlayerInDB.js index 8669847..9c696c7 100644 --- a/src/routes/join/logic/InsertPlayerInDB.js +++ b/src/routes/join/logic/InsertPlayerInDB.js @@ -1,14 +1,19 @@ import { supabase } from "$lib/supabase"; export async function addPlayer(name, gamePin) { - const { error } = await supabase.from("players").insert({ - gameid: gamePin, - score: 0, - playername: name, - }); + const { data, error } = await supabase + .from("players") + .insert({ + gameid: gamePin, + score: 0, + playername: name, + }) + .select("id"); if (error) { alert("Failed to join game: " + error.message + "\n\nPlease try again."); return; } + + return data[0].id; } diff --git a/src/routes/join/logic/joinGame.js b/src/routes/join/logic/joinGame.js index bb80720..dacf139 100644 --- a/src/routes/join/logic/joinGame.js +++ b/src/routes/join/logic/joinGame.js @@ -1,4 +1,3 @@ -import { goto } from "$app/navigation"; import { addPlayer } from "./InsertPlayerInDB.js"; import { validateGamePin } from "./validateGamePin.js"; import { Checking } from "./JoinGameData.svelte.js"; @@ -12,11 +11,9 @@ export async function joinGame(pin, name) { return; } - addPlayer(name, pin); - + let id = await addPlayer(name, pin); + Checking.v = false; - goto("/play/" + pin, { - state: { name }, - }); + window.location.href = `./play/${pin}?name=${name}&playerid=${id}`; } diff --git a/src/routes/play/[gamePin]/+page.js b/src/routes/play/[gamePin]/+page.js index 43d524c..aea5dc3 100644 --- a/src/routes/play/[gamePin]/+page.js +++ b/src/routes/play/[gamePin]/+page.js @@ -2,4 +2,4 @@ export function load({ params }) { return { gamePin: params.gamePin }; -} \ No newline at end of file +} diff --git a/src/routes/play/[gamePin]/+page.svelte b/src/routes/play/[gamePin]/+page.svelte index 2719c2e..d102bb5 100644 --- a/src/routes/play/[gamePin]/+page.svelte +++ b/src/routes/play/[gamePin]/+page.svelte @@ -1,11 +1,12 @@ @@ -23,7 +28,7 @@ {#if Status.v == "lobby"} {:else if Status.v == "started"} - + {/if} diff --git a/src/routes/play/[gamePin]/components/DuringGame/PeopleAwnsered.svelte b/src/routes/play/[gamePin]/components/DuringGame/PeopleAwnsered.svelte deleted file mode 100644 index 672183b..0000000 --- a/src/routes/play/[gamePin]/components/DuringGame/PeopleAwnsered.svelte +++ /dev/null @@ -1,13 +0,0 @@ - - -
-

{PeopleAwnseredQ.v} out of {Totalplayers.v} have awnsered the quetion

-
-
-
-
diff --git a/src/routes/play/[gamePin]/components/DuringGame/QuetionsAwnsred.svelte b/src/routes/play/[gamePin]/components/DuringGame/QuetionsAwnsred.svelte deleted file mode 100644 index c51c04d..0000000 --- a/src/routes/play/[gamePin]/components/DuringGame/QuetionsAwnsred.svelte +++ /dev/null @@ -1,13 +0,0 @@ - - -
-

Question {currentQuestion.v + 1} of {totalQuetions.v} is beeing awnsered

-
-
-
-
diff --git a/src/routes/play/[gamePin]/components/DuringGame/display.svelte b/src/routes/play/[gamePin]/components/DuringGame/display.svelte deleted file mode 100644 index c6d1a1b..0000000 --- a/src/routes/play/[gamePin]/components/DuringGame/display.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - -

HOSTING

- - diff --git a/src/routes/play/[gamePin]/components/awnseringQuetions/Awnsers.svelte b/src/routes/play/[gamePin]/components/awnseringQuetions/Awnsers.svelte new file mode 100644 index 0000000..b8b3e9b --- /dev/null +++ b/src/routes/play/[gamePin]/components/awnseringQuetions/Awnsers.svelte @@ -0,0 +1,22 @@ + + +
+ {#each questions.v.answers as answer, index} +
+ + +
+ {/each} +
diff --git a/src/routes/play/[gamePin]/components/awnseringQuetions/ProgressBar.svelte b/src/routes/play/[gamePin]/components/awnseringQuetions/ProgressBar.svelte new file mode 100644 index 0000000..34de775 --- /dev/null +++ b/src/routes/play/[gamePin]/components/awnseringQuetions/ProgressBar.svelte @@ -0,0 +1,13 @@ + + +
+

Question {CurrentQuestion.v + 1} of {TotalQuestions.v}

+
+
+
+
diff --git a/src/routes/play/[gamePin]/components/awnseringQuetions/buttons/SelectFirst.svelte b/src/routes/play/[gamePin]/components/awnseringQuetions/buttons/SelectFirst.svelte new file mode 100644 index 0000000..7e6470e --- /dev/null +++ b/src/routes/play/[gamePin]/components/awnseringQuetions/buttons/SelectFirst.svelte @@ -0,0 +1,4 @@ + diff --git a/src/routes/play/[gamePin]/components/awnseringQuetions/buttons/submitAwnser.svelte b/src/routes/play/[gamePin]/components/awnseringQuetions/buttons/submitAwnser.svelte new file mode 100644 index 0000000..d461b19 --- /dev/null +++ b/src/routes/play/[gamePin]/components/awnseringQuetions/buttons/submitAwnser.svelte @@ -0,0 +1,9 @@ + + + diff --git a/src/routes/play/[gamePin]/components/awnseringQuetions/display.svelte b/src/routes/play/[gamePin]/components/awnseringQuetions/display.svelte new file mode 100644 index 0000000..3b77ab0 --- /dev/null +++ b/src/routes/play/[gamePin]/components/awnseringQuetions/display.svelte @@ -0,0 +1,28 @@ + + +
+
+ + {#if CurrentQuestion.v != null} + + + {#if Selected.v != null} + + {:else} + + {/if} + {:else} + + {/if} +
+
diff --git a/src/routes/play/[gamePin]/components/awnseringQuetions/text/Quetion.svelte b/src/routes/play/[gamePin]/components/awnseringQuetions/text/Quetion.svelte new file mode 100644 index 0000000..b5d79fa --- /dev/null +++ b/src/routes/play/[gamePin]/components/awnseringQuetions/text/Quetion.svelte @@ -0,0 +1,7 @@ + + +

+ Q{CurrentQuestion.v + 1}. {questions.v.question} +

diff --git a/src/routes/play/[gamePin]/components/awnseringQuetions/text/wait.svelte b/src/routes/play/[gamePin]/components/awnseringQuetions/text/wait.svelte new file mode 100644 index 0000000..32d5985 --- /dev/null +++ b/src/routes/play/[gamePin]/components/awnseringQuetions/text/wait.svelte @@ -0,0 +1 @@ +

Please wait for everyone else to answer the question.

diff --git a/src/routes/play/[gamePin]/logic/HostsData.svelte.js b/src/routes/play/[gamePin]/logic/HostsData.svelte.js index c1d8316..d596117 100644 --- a/src/routes/play/[gamePin]/logic/HostsData.svelte.js +++ b/src/routes/play/[gamePin]/logic/HostsData.svelte.js @@ -1,9 +1,9 @@ -export let players = $state({ v: [] }); +export let players = $state({ v: {} }); export let Status = $state({ v: "lobby" }); -export let questions = $state({ v: [] }); -export let CurrentQuestion = $state({ v: -1 }); - -export let currentQuestion = $state({ v: 0 }); -export let totalQuetions = $state({ v: 3 }); -export let PeopleAwnseredQ = $state({ v: 0 }); -export let Totalplayers = $state({ v: 3 }); +export let questions = $state({ v: {} }); +export let CurrentQuestion = $state({ v: null }); +export let TotalQuestions = $state({ v: 0 }); +export let Selected = $state({ v: null }); +export let isWait = $state({ v: true }); +export let name = $state({ v: "" }); +export let playerid = $state({ v: null }); diff --git a/src/routes/play/[gamePin]/logic/IntializeGameStart.js b/src/routes/play/[gamePin]/logic/IntializeGameStart.js new file mode 100644 index 0000000..cdd12c8 --- /dev/null +++ b/src/routes/play/[gamePin]/logic/IntializeGameStart.js @@ -0,0 +1,22 @@ +import { supabase } from "$lib/supabase.js"; +import { NewStatus } from "./NewStatus.js"; + +export async function IntializeGameStart(gamepin) { + supabase + .channel(`game_status_${gamepin}`) + .on( + "postgres_changes", + { + event: "UPDATE", + schema: "public", + table: "games", + filter: `gamepin=eq.${gamepin}`, + }, + (payload) => { + if (payload.new.status) { + NewStatus(payload.new.status, gamepin); + } + }, + ) + .subscribe(); +} diff --git a/src/routes/play/[gamePin]/logic/NewStatus.js b/src/routes/play/[gamePin]/logic/NewStatus.js new file mode 100644 index 0000000..9e427ba --- /dev/null +++ b/src/routes/play/[gamePin]/logic/NewStatus.js @@ -0,0 +1,41 @@ +import { + CurrentQuestion, + Status, + questions, + isWait, + Selected, + playerid, +} from "./HostsData.svelte.js"; +import { supabase } from "$lib/supabase.js"; + +export async function NewStatus(NewStatus, gamePin) { + if (NewStatus == "completed") { + window.location.replace("/results/" + gamePin + "?playerID=" + playerid.v); + return; + } + + Status.v = "started"; + CurrentQuestion.v = Number(NewStatus.replace("question-", "")); + + const { data: questionsData } = await supabase + .from("questions") + .select("id,questionstext,correctanswer") + .eq("gameid", Number(gamePin)) + .order("id", { ascending: true }); + + const { data: answers } = await supabase + .from("answers") + .select("content") + .eq("questionid", Number(questionsData[CurrentQuestion.v].id)) + .order("id", { ascending: true }); + + questions.v = { + question: questionsData[CurrentQuestion.v].questionstext, + correctAnswer: questionsData[CurrentQuestion.v].correctanswer, + answers: answers.map((answer) => answer.content), + questionid: questionsData[CurrentQuestion.v].id, + }; + + isWait.v = false; + Selected.v = null; +} diff --git a/src/routes/play/[gamePin]/logic/SubmitAnswer.js b/src/routes/play/[gamePin]/logic/SubmitAnswer.js new file mode 100644 index 0000000..add80c2 --- /dev/null +++ b/src/routes/play/[gamePin]/logic/SubmitAnswer.js @@ -0,0 +1,31 @@ +import { CurrentQuestion, Selected, questions, playerid } from "./HostsData.svelte.js"; +import { supabase } from "$lib/supabase.js"; + +export async function SubmitAnswer() { + CurrentQuestion.v = null; + + if (Selected.v == questions.v.correctAnswer) { + await supabase + .from("answeredby") + .insert([ + { questionid: questions.v.questionid, nameofanswerer: playerid.v, correct: true }, + ]) + .select(); + + let { data: score } = await supabase.from("players").select("score").eq("id", playerid.v); + + await supabase + .from("players") + .update({ score: score[0].score + 1 }) + .eq("id", playerid.v) + .select(); + + } else { + await supabase + .from("answeredby") + .insert([ + { questionid: questions.v.questionid, nameofanswerer: playerid.v, correct: false }, + ]) + .select(); + } +} diff --git a/src/routes/play/[gamePin]/logic/startGame.js b/src/routes/play/[gamePin]/logic/startGame.js index 5941e99..8a2fe31 100644 --- a/src/routes/play/[gamePin]/logic/startGame.js +++ b/src/routes/play/[gamePin]/logic/startGame.js @@ -1,6 +1,6 @@ import { supabase } from "$lib/supabase.js"; import { LobbyConnection } from "./UpdatePlayersList.js"; -import { questions, Status, CurrentQuestion, currentQuestion } from "./HostsData.svelte.js"; +import { questions, Status, CurrentQuestion } from "./HostsData.svelte.js"; export async function startGame(gamePin) { await supabase.removeChannel(LobbyConnection); @@ -18,7 +18,7 @@ export async function startGame(gamePin) { await supabase .from("games") - .update({ status: `question-${currentQuestion.v}` }) + .update({ status: `question-${CurrentQuestion.v}` }) .eq("gamepin", gamePin); diff --git a/src/routes/results/[gamePin]/+page.js b/src/routes/results/[gamePin]/+page.js new file mode 100644 index 0000000..aea5dc3 --- /dev/null +++ b/src/routes/results/[gamePin]/+page.js @@ -0,0 +1,5 @@ +export function load({ params }) { + return { + gamePin: params.gamePin + }; +} diff --git a/src/routes/results/[gamePin]/+page.svelte b/src/routes/results/[gamePin]/+page.svelte new file mode 100644 index 0000000..33e76a1 --- /dev/null +++ b/src/routes/results/[gamePin]/+page.svelte @@ -0,0 +1,81 @@ + + +
+
+

Leaderboard

+ + {#each players as player, i} + {#if player.id == playerID} +
+
+ {i + 1} +
+ +
{player.playername}
+ +
+
+
+ +
{player.score} points
+
+ {:else} +
+
+ {i + 1} +
+ +
{player.playername}
+ +
+
+
+ +
{player.score} points
+
+ {/if} + {/each} + + +
+