Skip to content
Extraits de code Groupes Projets
Valider 58eb6ec4 rédigé par Steel's avatar Steel
Parcourir les fichiers

feat: variable score

parent f6926eb3
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -19,7 +19,8 @@ export const gameStateSchema = z.object({ ...@@ -19,7 +19,8 @@ export const gameStateSchema = z.object({
year: z.number(), year: z.number(),
maxYear: z.number().optional(), maxYear: z.number().optional(),
label: z.string(), label: z.string(),
solution: z.string() solution: z.string(),
timestamp: z.number()
}); });
export type GameState = z.infer<typeof gameStateSchema>; export type GameState = z.infer<typeof gameStateSchema>;
...@@ -44,12 +45,14 @@ export class Game { ...@@ -44,12 +45,14 @@ export class Game {
year: 0, year: 0,
options: [], options: [],
solution: '', solution: '',
label: '?' label: '?',
timestamp: 0
}; };
} }
save() { save() {
// console.log('SAVE:', GameStage[this.state.stage], this.state); // console.log('SAVE:', GameStage[this.state.stage], this.state);
this.state.timestamp = Date.now();
this.cookie.write(this.state); this.cookie.write(this.state);
} }
......
...@@ -62,6 +62,19 @@ export async function load(event) { ...@@ -62,6 +62,19 @@ export async function load(event) {
}; };
} }
const MAX_POINTS = 10;
const MIN_POINTS = 0;
// Durée maximale pour obtenir le score maximal
const SERVER_DELAY_MAX = 3;
function computePoints(timestamp: number): number {
const elapsed = (Date.now() - timestamp) / 1000;
return Math.max(
MIN_POINTS,
Math.floor(MAX_POINTS - Math.min(MAX_POINTS + SERVER_DELAY_MAX, elapsed))
);
}
export const actions = { export const actions = {
async results(event) { async results(event) {
const form = await superValidate(event, zod(schema)); const form = await superValidate(event, zod(schema));
...@@ -72,15 +85,16 @@ export const actions = { ...@@ -72,15 +85,16 @@ export const actions = {
const state = new Game(event.cookies); const state = new Game(event.cookies);
if (form.data.choice === state.state.solution) { const points =
state.state.score += 10; form.data.choice === state.state.solution ? computePoints(state.state.timestamp) : 0;
} state.state.score += points;
state.state.history.push(state.state.solution); state.state.history.push(state.state.solution);
state.save(); state.save();
return { return {
form, form,
solution: state.state.solution solution: state.state.solution,
points
}; };
}, },
......
<script lang="ts"> <script lang="ts">
import { Fieldset, Control, Label } from 'formsnap'; import { Fieldset, Control, Label } from 'formsnap';
import { superForm } from 'sveltekit-superforms'; import { superForm } from 'sveltekit-superforms';
import { scale } from 'svelte/transition';
export let data; export let data;
export let form; export let form;
...@@ -17,7 +18,7 @@ ...@@ -17,7 +18,7 @@
<div class="relative mx-auto my-12 w-full grow"> <div class="relative mx-auto my-12 w-full grow">
<section class="relative m-auto flex flex-col items-center"> <section class="relative m-auto flex flex-col items-center">
<h1 class="absolute -top-8 text-xl">Qui est-ce ? {data.label}</h1> <h1 class="absolute -top-8 text-xl">Qui est-ce ?</h1>
<div class="relative"> <div class="relative">
<span class="absolute right-[calc(100%_+_0.5rem)] text-right"> <span class="absolute right-[calc(100%_+_0.5rem)] text-right">
<span class="flex flex-col items-end"> <span class="flex flex-col items-end">
...@@ -27,14 +28,20 @@ ...@@ -27,14 +28,20 @@
<span class="inline-block h-1.5 w-10 bg-zinc-800"></span> <span class="inline-block h-1.5 w-10 bg-zinc-800"></span>
<br /> <br />
<span class="top-24 pt-4 text-xl text-zinc-800"> <span class="top-24 pt-4 text-xl text-zinc-800">
{data.score} {data.score - (form?.points ?? 0)}
<small>pts</small> <small>pts</small>
</span> </span>
</span> </span>
<div <div>
class="relative z-10 flex h-64 w-64 items-center justify-center overflow-hidden rounded-2xl border-6 border-solid border-zinc-800 bg-white before:absolute before:-z-10 before:h-32 before:w-32 before:rounded-full before:bg-slate-300 before:opacity-100 before:transition-[0.65s] before:duration-[ease-in-out] after:absolute after:-z-10 after:h-32 after:w-32 after:scale-0 after:rounded-full after:border-solid after:border-slate-300 after:transition-[0.4s] after:duration-[ease-in-out]" <div
> class="relative z-10 flex h-64 w-64 items-center justify-center overflow-hidden rounded-2xl border-6 border-solid border-zinc-800 bg-white before:absolute before:-z-10 before:h-32 before:w-32 before:rounded-full before:bg-slate-300 before:opacity-100 before:transition-[0.65s] before:duration-[ease-in-out] after:absolute after:-z-10 after:h-32 after:w-32 after:scale-0 after:rounded-full after:border-solid after:border-slate-300 after:transition-[0.4s] after:duration-[ease-in-out]"
<img src={data.photo?.url} alt="Chargement..." class="w-auto" /> >
<img src={data.photo?.url} alt="Chargement..." class="w-auto" />
</div>
<span
class="absolute left-0 top-0 z-20 rounded-br-xl rounded-tl-2xl bg-zinc-800 px-2 text-xl text-white"
>{data.label}</span
>
</div> </div>
<form method="post" use:enhance> <form method="post" use:enhance>
<Fieldset form={sForm} name="choice"> <Fieldset form={sForm} name="choice">
...@@ -42,6 +49,7 @@ ...@@ -42,6 +49,7 @@
class="relative -top-6 z-20 mx-auto my-0 flex w-44 flex-col items-center space-y-0.5 rounded-2xl bg-zinc-800 px-5 py-0" class="relative -top-6 z-20 mx-auto my-0 flex w-44 flex-col items-center space-y-0.5 rounded-2xl bg-zinc-800 px-5 py-0"
> >
{#each data.options as option} {#each data.options as option}
{@const valid = (form?.solution && option.value === form?.solution) || null}
<div class="max-h-14 w-full min-w-52"> <div class="max-h-14 w-full min-w-52">
<Control let:attrs> <Control let:attrs>
<input <input
...@@ -51,13 +59,18 @@ ...@@ -51,13 +59,18 @@
value={option.value} value={option.value}
class="peer sr-only" class="peer sr-only"
disabled={form?.solution !== undefined} disabled={form?.solution !== undefined}
data-valid={(form?.solution && option.value === form?.solution) || null} data-valid={valid}
/> />
<Label <Label
tabindex={0} tabindex={0}
class="relative block cursor-pointer select-none overflow-hidden rounded-2xl border-6 border-solid border-zinc-800 bg-slate-300 p-2 text-center text-lg transition-[0.45s] before:absolute before:left-2/4 before:top-2/4 before:-z-10 before:h-[200px] before:w-[200px] before:-translate-x-2/4 before:-translate-y-2/4 before:scale-0 before:rounded-full before:bg-indigo-300 before:transition-[0.2s] before:duration-[ease-in-out] focus:[outline:none] active:before:-translate-x-2/4 active:before:-translate-y-2/4 active:before:scale-100 peer-enabled:hover:translate-y-[-3px] peer-enabled:hover:bg-slate-400 peer-enabled:focus:border-indigo-500 peer-checked:peer-enabled:bg-indigo-300 peer-disabled:cursor-default peer-disabled:text-[#94acbd] peer-checked:peer-disabled:bg-red-400 peer-checked:peer-disabled:text-inherit peer-data-[valid]:!bg-lime-400 peer-data-[valid]:text-inherit" class="relative block cursor-pointer select-none overflow-hidden rounded-2xl border-6 border-solid border-zinc-800 bg-slate-300 p-2 text-center text-lg transition-[0.45s] before:absolute before:left-2/4 before:top-2/4 before:-z-10 before:h-[200px] before:w-[200px] before:-translate-x-2/4 before:-translate-y-2/4 before:scale-0 before:rounded-full before:bg-indigo-300 before:transition-[0.2s] before:duration-[ease-in-out] focus:[outline:none] active:before:-translate-x-2/4 active:before:-translate-y-2/4 active:before:scale-100 peer-enabled:hover:translate-y-[-3px] peer-enabled:hover:bg-slate-400 peer-enabled:focus:border-indigo-500 peer-checked:peer-enabled:bg-indigo-300 peer-disabled:cursor-default peer-disabled:text-[#94acbd] peer-checked:peer-disabled:bg-red-400 peer-checked:peer-disabled:text-inherit peer-data-[valid]:!bg-lime-400 peer-data-[valid]:text-inherit"
> >
{option.label} {option.label}
{#if valid && form?.points}
<span class="absolute right-0 mr-1.5 rounded-full bg-white px-1.5" in:scale>
+{form.points}
</span>
{/if}
</Label> </Label>
</Control> </Control>
</div> </div>
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter