+
{statsData.averageGuesses}
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index a2e7a2a..9fcaace 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -43,6 +43,7 @@
totalSolves: number;
averageGuesses: number;
tiedCount: number;
+ percentile: number;
} | null>(null);
let guessedIds = $derived(new Set(guesses.map((g) => g.book.id)));
diff --git a/src/routes/api/submit-completion/+server.ts b/src/routes/api/submit-completion/+server.ts
index 8039910..0b80d09 100644
--- a/src/routes/api/submit-completion/+server.ts
+++ b/src/routes/api/submit-completion/+server.ts
@@ -44,9 +44,11 @@ export const POST: RequestHandler = async ({ request }) => {
// Solve rank: position in time-ordered list
const solveRank = allCompletions.findIndex(c => c.anonymousId === anonymousId) + 1;
- // Guess rank: count how many had FEWER guesses (ties get same rank)
- const betterGuesses = allCompletions.filter(c => c.guessCount < guessCount).length;
- const guessRank = betterGuesses + 1;
+ // Guess rank: count how many DISTINCT guess counts are better (grouped ranking)
+ const uniqueBetterGuessCounts = new Set(
+ allCompletions.filter(c => c.guessCount < guessCount).map(c => c.guessCount)
+ );
+ const guessRank = uniqueBetterGuessCounts.size + 1;
// Count ties: how many have the SAME guessCount (excluding self)
const tiedCount = allCompletions.filter(c => c.guessCount === guessCount && c.anonymousId !== anonymousId).length;
@@ -55,9 +57,13 @@ export const POST: RequestHandler = async ({ request }) => {
const totalGuesses = allCompletions.reduce((sum, c) => sum + c.guessCount, 0);
const averageGuesses = Math.round((totalGuesses / totalSolves) * 10) / 10;
+ // Percentile: what percentage of people you beat (100 - your rank percentage)
+ const betterOrEqualCount = allCompletions.filter(c => c.guessCount <= guessCount).length;
+ const percentile = Math.round((betterOrEqualCount / totalSolves) * 100);
+
return json({
success: true,
- stats: { solveRank, guessRank, totalSolves, averageGuesses, tiedCount }
+ stats: { solveRank, guessRank, totalSolves, averageGuesses, tiedCount, percentile }
});
} catch (err) {
console.error('Error submitting completion:', err);
@@ -104,9 +110,11 @@ export const GET: RequestHandler = async ({ url }) => {
// Solve rank: position in time-ordered list
const solveRank = allCompletions.findIndex(c => c.anonymousId === anonymousId) + 1;
- // Guess rank: count how many had FEWER guesses (ties get same rank)
- const betterGuesses = allCompletions.filter(c => c.guessCount < guessCount).length;
- const guessRank = betterGuesses + 1;
+ // Guess rank: count how many DISTINCT guess counts are better (grouped ranking)
+ const uniqueBetterGuessCounts = new Set(
+ allCompletions.filter(c => c.guessCount < guessCount).map(c => c.guessCount)
+ );
+ const guessRank = uniqueBetterGuessCounts.size + 1;
// Count ties: how many have the SAME guessCount (excluding self)
const tiedCount = allCompletions.filter(c => c.guessCount === guessCount && c.anonymousId !== anonymousId).length;
@@ -115,9 +123,13 @@ export const GET: RequestHandler = async ({ url }) => {
const totalGuesses = allCompletions.reduce((sum, c) => sum + c.guessCount, 0);
const averageGuesses = Math.round((totalGuesses / totalSolves) * 10) / 10;
+ // Percentile: what percentage of people you beat (100 - your rank percentage)
+ const betterOrEqualCount = allCompletions.filter(c => c.guessCount <= guessCount).length;
+ const percentile = Math.round((betterOrEqualCount / totalSolves) * 100);
+
return json({
success: true,
- stats: { solveRank, guessRank, totalSolves, averageGuesses, tiedCount }
+ stats: { solveRank, guessRank, totalSolves, averageGuesses, tiedCount, percentile }
});
} catch (err) {
console.error('Error fetching stats:', err);