From 625dcf5adea9c206805a1b3b78b888b98ad86351 Mon Sep 17 00:00:00 2001
From: Steel <mael.acier@ensiie.fr>
Date: Fri, 6 Sep 2024 15:22:08 +0200
Subject: [PATCH] add timer

---
 package.json                    |  1 +
 pnpm-lock.yaml                  | 19 ++++++++++++++++--
 src/hooks.server.ts             | 20 +++++++++----------
 src/routes/quiz/+page.server.ts |  8 ++++----
 src/routes/quiz/+page.svelte    | 35 +++++++++++++++++++++++++++------
 5 files changed, 61 insertions(+), 22 deletions(-)

diff --git a/package.json b/package.json
index 5e22683..f01202a 100644
--- a/package.json
+++ b/package.json
@@ -51,6 +51,7 @@
     "http-status-codes": "^2.3.0",
     "msgpackr": "^1.11.0",
     "sveltekit-superforms": "^2.17.0",
+    "thumbhash": "^0.1.1",
     "zod": "^3.23.8"
   }
 }
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b85bddd..d44a781 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -32,6 +32,9 @@ importers:
       sveltekit-superforms:
         specifier: ^2.17.0
         version: 2.17.0(@sveltejs/kit@2.5.24(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.4.2(@types/node@22.5.0)))(svelte@4.2.18)(vite@5.4.2(@types/node@22.5.0)))(svelte@4.2.18)
+      thumbhash:
+        specifier: ^0.1.1
+        version: 0.1.1
       zod:
         specifier: ^3.23.8
         version: 3.23.8
@@ -126,6 +129,11 @@ packages:
       better-sqlite3: ^9.4.0
       lucia: ^3.2.0
       svelte: '4'
+    peerDependenciesMeta:
+      '@lucia-auth/adapter-sqlite':
+        optional: true
+      better-sqlite3:
+        optional: true
 
   '@ark/schema@0.2.0':
     resolution: {integrity: sha512-IkNWCSHdjaoemMXpps4uFHEAQzwJPbTAS8K2vcQpk90sa+eNBuPSVyB/81/Qyl1VYW0iX3ceGC5NL/OznQv1jg==}
@@ -2264,6 +2272,9 @@ packages:
   thenify@3.3.1:
     resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
 
+  thumbhash@0.1.1:
+    resolution: {integrity: sha512-kH5pKeIIBPQXAOni2AiY/Cu/NKdkFREdpH+TLdM0g6WA7RriCv0kPLgP731ady67MhTAqrVG/4mnEeibVuCJcg==}
+
   tiny-case@1.0.3:
     resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==}
 
@@ -2488,13 +2499,14 @@ snapshots:
 
   '@arise/aidc-sveltekit@0.4.1(@lucia-auth/adapter-sqlite@3.0.2(better-sqlite3@11.2.1)(lucia@3.2.0))(@sveltejs/kit@2.5.24(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.4.2(@types/node@22.5.0)))(svelte@4.2.18)(vite@5.4.2(@types/node@22.5.0)))(better-sqlite3@11.2.1)(lucia@3.2.0)(svelte@4.2.18)':
     dependencies:
-      '@lucia-auth/adapter-sqlite': 3.0.2(better-sqlite3@11.2.1)(lucia@3.2.0)
       '@sveltejs/kit': 2.5.24(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.4.2(@types/node@22.5.0)))(svelte@4.2.18)(vite@5.4.2(@types/node@22.5.0))
-      better-sqlite3: 11.2.1
       lucia: 3.2.0
       openid-client: 5.6.5
       readable-http-codes: 1.1.1
       svelte: 4.2.18
+    optionalDependencies:
+      '@lucia-auth/adapter-sqlite': 3.0.2(better-sqlite3@11.2.1)(lucia@3.2.0)
+      better-sqlite3: 11.2.1
 
   '@ark/schema@0.2.0':
     dependencies:
@@ -2829,6 +2841,7 @@ snapshots:
       lucia: 3.2.0
     optionalDependencies:
       better-sqlite3: 11.2.1
+    optional: true
 
   '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3':
     optional: true
@@ -4606,6 +4619,8 @@ snapshots:
     dependencies:
       any-promise: 1.3.0
 
+  thumbhash@0.1.1: {}
+
   tiny-case@1.0.3:
     optional: true
 
diff --git a/src/hooks.server.ts b/src/hooks.server.ts
index e78272b..41b8281 100644
--- a/src/hooks.server.ts
+++ b/src/hooks.server.ts
@@ -1,12 +1,12 @@
-import { sequence } from "@sveltejs/kit/hooks";
-import { type Handle, redirect } from "@sveltejs/kit";
-import { aidc } from "$lib/auth";
+// import { sequence } from "@sveltejs/kit/hooks";
+// import { type Handle, redirect } from "@sveltejs/kit";
+// import { aidc } from "$lib/auth";
 
-const authGuard: Handle = async ({ event, resolve }) => {
-  if (!event.locals.user) {
-    redirect(303, event.locals.authPaths.login);
-  }
-  return resolve(event);
-};
+// const authGuard: Handle = async ({ event, resolve }) => {
+//   if (!event.locals.user) {
+//     redirect(303, event.locals.authPaths.login);
+//   }
+//   return resolve(event);
+// };
 
-export const handle = sequence(aidc.handler(), authGuard);
+// export const handle = sequence(aidc.handler(), authGuard);
diff --git a/src/routes/quiz/+page.server.ts b/src/routes/quiz/+page.server.ts
index 933b6e2..ed60285 100644
--- a/src/routes/quiz/+page.server.ts
+++ b/src/routes/quiz/+page.server.ts
@@ -62,19 +62,19 @@ export async function load(event) {
     step: game.state.step,
     photo,
     label: game.state.label,
+    countdown: MAX_POINTS + SERVER_DELAY_MAX,
   };
 }
 
 const MAX_POINTS = 10;
 const MIN_POINTS = 3;
 // Durée maximale pour obtenir le score maximal
-const SERVER_DELAY_MAX = 3;
+const SERVER_DELAY_MAX = 1;
 
 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)),
+  return Math.ceil(
+    Math.max(MIN_POINTS, Math.min(SERVER_DELAY_MAX - elapsed, 0) + MAX_POINTS),
   );
 }
 
diff --git a/src/routes/quiz/+page.svelte b/src/routes/quiz/+page.svelte
index 792f1f9..3e7d980 100644
--- a/src/routes/quiz/+page.svelte
+++ b/src/routes/quiz/+page.svelte
@@ -2,6 +2,7 @@
   import { Fieldset, Control, Label } from "formsnap";
   import { superForm } from "sveltekit-superforms";
   import { scale } from "svelte/transition";
+  import { thumbHashToDataURL } from "thumbhash";
 
   export let data;
   export let form;
@@ -14,6 +15,19 @@
   const { form: formData, enhance } = sForm;
 
   const questionAmount = 10;
+
+  let thumbnail: string;
+
+  $: if (data.photo?.thumbnailHash) {
+    thumbnail = thumbHashToDataURL(
+      Uint8Array.from(atob(data.photo.thumbnailHash), (c) => c.charCodeAt(0)),
+    );
+  }
+  $: showSolution = form?.solution !== undefined;
+
+  setInterval(() => {
+    data.countdown = Math.max(0, data.countdown - 1);
+  }, 1000);
 </script>
 
 <div class="relative mx-auto my-12 w-full grow">
@@ -28,17 +42,26 @@
           <span> / {questionAmount} </span>
         </span>
         <span class="inline-block h-1.5 w-10 bg-zinc-800"></span>
-        <br />
-        <span class="top-24 pt-4 text-xl text-zinc-800">
+        <div class="top-24 text-xl text-zinc-800">
           {data.score - (form?.points ?? 0)}
           <small>pts</small>
-        </span>
+        </div>
+        {#if !showSolution}
+          <div class="pt-12 text-xl text-zinc-800">
+            {data.countdown} â§—
+          </div>
+        {/if}
       </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]"
         >
-          <img src={data.photo?.url} alt="Chargement..." class="w-auto" />
+          <img src={thumbnail} alt="" class="absolute w-full" />
+          <img
+            src={data.photo?.url}
+            alt="Chargement..."
+            class="absolute 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"
@@ -52,7 +75,7 @@
           >
             {#each data.options as option}
               {@const valid =
-                (form?.solution && option.value === form?.solution) || null}
+                (showSolution && option.value === form?.solution) || null}
               <div class="max-h-14 w-full min-w-52">
                 <Control let:attrs>
                   <input
@@ -61,7 +84,7 @@
                     bind:group={$formData.choice}
                     value={option.value}
                     class="peer sr-only"
-                    disabled={form?.solution !== undefined}
+                    disabled={showSolution}
                     data-valid={valid}
                   />
                   <Label
-- 
GitLab