diff --git a/src/lib/components/BingoCard.svelte b/src/lib/components/BingoCard.svelte index de30540..1c8ac17 100644 --- a/src/lib/components/BingoCard.svelte +++ b/src/lib/components/BingoCard.svelte @@ -27,8 +27,9 @@ if (!card) return; if (card.squares) { - yMax = Math.max(...card.squares.map((x) => x.y_pos)); - xMax = Math.max(...card.squares.map((x) => x.x_pos)); + // Height & Width of card is the largest y or x position, and must be at least 0 + yMax = Math.max(...card.squares.map((x) => x.y_pos), 0); + xMax = Math.max(...card.squares.map((x) => x.x_pos), 0); } const win = checkWin(card); if (win) { @@ -56,7 +57,7 @@ class="relative grid w-full rounded bg-base-950 p-2" bind:clientWidth={square_width} style=" - grid-template-columns: 30px repeat({xMax + 1}, {xMax + 1}fr); + grid-template-columns: 30px repeat({xMax + 1}, {xMax + 1}fr); grid-template-rows: 30px repeat({yMax + 1}, {yMax + 1}fr); aspect-ratio: {xMax + 1} / {yMax + 1} " -- 2.51.2 From 5d15e77ca0e37b6685cb7b912036c89056b775fe Mon Sep 17 00:00:00 2001 From: clxxiii Date: Thu, 31 Jul 2025 20:22:25 -0400 Subject: [PATCH 2/2] fix unclaimed squares --- src/lib/bingo-helpers/best_score.ts | 24 +++++------ src/lib/gamerules/meaning.ts | 51 ++++++++++++------------ src/lib/server/game/update_scores.ts | 12 +++--- src/routes/(main)/game/[id]/+page.svelte | 1 - 4 files changed, 43 insertions(+), 45 deletions(-) diff --git a/src/lib/bingo-helpers/best_score.ts b/src/lib/bingo-helpers/best_score.ts index 00f12c3..2a49938 100644 --- a/src/lib/bingo-helpers/best_score.ts +++ b/src/lib/bingo-helpers/best_score.ts @@ -2,19 +2,19 @@ * Takes a square and gets the best score on it depending on the * game's sorting method. */ -const evaluators: { [key: string]: (scores: Bingo.Score[]) => Bingo.Score } = { - score: (scores) => scores.sort((a, b) => b.score - a.score)[0], - accuracy: (scores) => scores.sort((a, b) => b.accuracy - a.accuracy)[0], - combo: (scores) => scores.sort((a, b) => b.max_combo - a.max_combo)[0], - pp: (scores) => scores.sort((a, b) => (b.pp ?? 0) - (a.pp ?? 0))[0] +const comparators: { [key: string]: (a: Bingo.Score, b: Bingo.Score) => number } = { + score: (a, b) => b.score - a.score, + accuracy: (a, b) => b.accuracy - a.accuracy, + combo: (a, b) => b.max_combo - a.max_combo, + pp: (a, b) => (b.pp ?? 0) - (a.pp ?? 0) }; export const getBest = (square: Bingo.Card.FullSquare, tiebreaker: string) => { - let evaluator = evaluators[tiebreaker]; + let evaluator = comparators[tiebreaker]; if (!evaluator) evaluator = evaluator['score']; const scores = square.scores.filter((x) => x.claimworthy); - return evaluator(scores); + return scores.sort(evaluator)[0]; }; export const scoreBeatsBest = ( @@ -22,15 +22,13 @@ export const scoreBeatsBest = ( next: Bingo.Score, tiebreaker: string ) => { - let evaluator = evaluators[tiebreaker]; - if (!evaluator) evaluator = evaluator['score']; + const evaluator = comparators[tiebreaker]; + if (!evaluator) return false; const scores: Bingo.Score[] = square.scores.filter((x) => x.claimworthy); if (scores.length == 0) return true; - const currentBest = evaluator(scores); - scores.push(next); - const nextBest = evaluator(scores); + const currentBest = getBest(square, tiebreaker); - return nextBest.id != currentBest.id; + return evaluator(currentBest, next) > 0; }; diff --git a/src/lib/gamerules/meaning.ts b/src/lib/gamerules/meaning.ts index 01e632b..a63f22e 100644 --- a/src/lib/gamerules/meaning.ts +++ b/src/lib/gamerules/meaning.ts @@ -1,33 +1,34 @@ -import type { Options } from "./options"; +import type { Options } from './options'; export const getClaimConditionMeaning = (c: Options.ClaimCondition) => { - const qLang1 = (q: "lt" | "gt" | "eq") => q == "gt" ? "more than" : q == "eq" ? "exactly" : "less than" - const qLang2 = (q: "lt" | "gt" | "eq") => q == "gt" ? "at least" : q == "eq" ? "exactly" : "at most" + const qLang1 = (q: 'lt' | 'gt' | 'eq') => + q == 'gt' ? 'more than' : q == 'eq' ? 'exactly' : 'less than'; + const qLang2 = (q: 'lt' | 'gt' | 'eq') => + q == 'gt' ? 'at least' : q == 'eq' ? 'exactly' : 'at most'; - const evaluate: { [key: string]: (c: Options.ClaimCondition) => string } = { - fc: () => "Get an FC", - pass: () => "Pass the map", - any: () => "Get any score", + const evaluate: { [key: string]: (c: Options.ClaimCondition) => string } = { + fc: () => 'Get an FC', + pass: () => 'Pass the map', + any: () => 'Get any score', - rank: (c) => `Get ${qLang2(c.quantifier ?? "gt")} a ${c.value} rank`, - score: (c) => `Get ${qLang2(c.quantifier ?? "gt")} ${parseInt(c.value).toLocaleString()} score`, - pp: (c) => `Get ${qLang2(c.quantifier ?? "gt")} ${c.value}pp`, - miss: (c) => `Get ${qLang2(c.quantifier ?? "gt")} ${c.value} miss${c.value != 1 ? "es" : ""}`, - accuracy: (c) => `Get ${qLang1(c.quantifier ?? "gt")} ${(parseFloat(c.value).toFixed(2))}% accuracy`, - combo: (c) => `Get ${qLang2(c.quantifier ?? "gt")} ${c.value} combo`, - } + rank: (c) => `Get ${qLang2(c.quantifier ?? 'gt')} a ${c.value} rank`, + score: (c) => `Get ${qLang2(c.quantifier ?? 'gt')} ${parseInt(c.value).toLocaleString()} score`, + pp: (c) => `Get ${qLang2(c.quantifier ?? 'gt')} ${c.value}pp`, + miss: (c) => `Get ${qLang2(c.quantifier ?? 'gt')} ${c.value} miss${c.value != 1 ? 'es' : ''}`, + accuracy: (c) => + `Get ${qLang1(c.quantifier ?? 'gt')} ${parseFloat(c.value).toFixed(2)}% accuracy`, + combo: (c) => `Get ${qLang2(c.quantifier ?? 'gt')} ${c.value} combo` + }; - return evaluate[c.metric](c); -} + return evaluate[c.metric](c); +}; export const getEventMeaning = (c: Options.Event) => { - console.log(c); + const events: { [key: string]: () => string } = { + start: () => `Start the game`, + claimchange: () => `Change claim condition: ${getClaimConditionMeaning(c.detail)}`, + finalcall: () => `Winner will be decided by tiebreaker conditions` + }; - const events: { [key: string]: () => string } = { - start: () => `Start the game`, - claimchange: () => `Change claim condition: ${getClaimConditionMeaning(c.detail)}`, - finalcall: () => `Winner will be decided by tiebreaker conditions`, - }; - - return events[c.event](); -} \ No newline at end of file + return events[c.event](); +}; diff --git a/src/lib/server/game/update_scores.ts b/src/lib/server/game/update_scores.ts index e6dfd74..007c429 100644 --- a/src/lib/server/game/update_scores.ts +++ b/src/lib/server/game/update_scores.ts @@ -84,7 +84,7 @@ export const updateScores = async (game_id: string) => { }); const processedScores = await q.getScoresFromGame(game.id); - const processedIds = processedScores.map(x => x.score_id); + const processedIds = processedScores.map((x) => x.score_id); const updates: { score: Bingo.Card.FullScore; square: Bingo.Card.FullSquare; claim: boolean }[] = []; @@ -136,7 +136,6 @@ const processScore = async (score: Osu.LazerScore, game: Bingo.Card) => { // TODO: Check that the score meets the mod requirements (also disallowing converts if configured to do so) - // Add score to database const rules = getRules(game); const claimworthy = isClaimworthy(score, rules.claim_condition); @@ -144,10 +143,6 @@ const processScore = async (score: Osu.LazerScore, game: Bingo.Card) => { if (!user) return; const newScore = await q.addScore(score, user, square.id, claimworthy); - // Update score on game object so the next score in this burst will be calculated correctly. - const sqIdx = game.squares.findIndex(x => x.id == square.id); - game.squares[sqIdx].scores.push(newScore); - // For sending to the client const update = { score: newScore, @@ -171,5 +166,10 @@ const processScore = async (score: Osu.LazerScore, game: Bingo.Card) => { update.winner = win.winner.toUpperCase(); } } + + // Update score on game object so the next score in this burst will be calculated correctly. + const sqIdx = game.squares.findIndex((x) => x.id == square.id); + game.squares[sqIdx].scores.push(newScore); + return update; }; diff --git a/src/routes/(main)/game/[id]/+page.svelte b/src/routes/(main)/game/[id]/+page.svelte index d137385..5b0fbb9 100644 --- a/src/routes/(main)/game/[id]/+page.svelte +++ b/src/routes/(main)/game/[id]/+page.svelte @@ -28,7 +28,6 @@ host = game.hosts.find((x) => x.id == data?.user?.id) != undefined; game_rules.set(getRules(game)); - console.log(getRules(game)); }); $: {