diff --git a/; b/; deleted file mode 100644 index c8cc76a..0000000 --- a/; +++ /dev/null @@ -1,15 +0,0 @@ -{ pkgs, config, ... }: { - languages.typescript.enable = true; - dotenv.disableHint = true; - packages = with pkgs; [ - bun - eslint_d - ]; - env.DEVSHELL_NAME = " devenv/#fab387| Bun/yellow"; - processes = { - server = { - ports.http.allocate = 5173; - exec = "bun run dev"; - }; - }; -} diff --git a/src/lib/server/databaseManager.ts b/src/lib/server/databaseManager.ts index d418eb1..f629ea4 100644 --- a/src/lib/server/databaseManager.ts +++ b/src/lib/server/databaseManager.ts @@ -107,6 +107,7 @@ export async function getAllRegisteredEventPlayers(eventId: number) { id: players.playerId, firstName: players.firstName, lastName: players.lastName, + registeredPlayerId: players.registeredPlayerId, placement: players.placement, bracket: players.bracket, eventId: players.eventId, diff --git a/src/lib/server/db/schema.ts b/src/lib/server/db/schema.ts index 1a81cb4..9a3b7a6 100644 --- a/src/lib/server/db/schema.ts +++ b/src/lib/server/db/schema.ts @@ -160,6 +160,7 @@ export const registeredEventPlayersView = sqliteView('registeredEventPlayersView return qb .select({ playerId: players.id, + registeredPlayerId: registeredPlayers.id, firstName: players.firstName, lastName: players.lastName, placement: registeredPlayers.placement, diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 592abc0..3c422c8 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -177,7 +177,10 @@ {:else if event.state == 2} Won By {event.winner.name}Won By {event.winner.name} at {new Date(event.completed) + .toLocaleTimeString() + .slice(0, -3)} {/if} diff --git a/src/routes/api/eventResults/+server.ts b/src/routes/api/eventResults/+server.ts index b53bb22..992b8b8 100644 --- a/src/routes/api/eventResults/+server.ts +++ b/src/routes/api/eventResults/+server.ts @@ -22,7 +22,6 @@ export async function POST({ request }: any) { return new Error(); } let scoringPreset = eventData.events[0].scoringPreset; - console.log(scoringPreset); // make a new main ledger entry let newLedgerEntry = await db @@ -45,41 +44,77 @@ export async function POST({ request }: any) { ); } - // for every bracket and player + // Create a Map to collect total scores per team + const teamScores = new Map(); + + // for every bracket for (let bracket in responseBody.brackets) { + // for every player for (let player in responseBody.brackets[bracket].players) { // variable fun let currentPlayer = responseBody.brackets[bracket].players[player]; - console.log(currentPlayer); let currentPlayerTeam = currentPlayer.teamId; let currentPlayerPosition = currentPlayer.position; - // If they put in a score + // If they put in a score / result if (currentPlayerPosition > 0) { let score = getPoints(scoringPreset, currentPlayerPosition); // If their score is in the preset and they put in a score if (currentPlayer.scores.length > 0) { if (score > 0) { - // put the scores on the board baby - // THIS SHOULDNT BE REFERENCED THIS IS INTENDED - let newScoreLedgerEntry = await db - .insert(schema.scoreLedger) - .values({ ledgerID: ledgerEntryId, teamID: currentPlayerTeam, points: score }); + // Accumulate points for this team instead of inserting right away + const currentTeamScore = teamScores.get(currentPlayerTeam) || 0; + teamScores.set(currentPlayerTeam, currentTeamScore + score); } + + // PLACEMENT LOGIC (Left untouched) let newPlayerPlacement = await db .update(schema.registeredPlayers) .set({ placement: currentPlayerPosition }) - .where(eq(schema.registeredPlayers.playerID, currentPlayer.id)) + .where(eq(schema.registeredPlayers.id, currentPlayer.registeredPlayerId)) .returning(); - console.log(newPlayerPlacement); + console.log(newPlayerPlacement[0].placement, currentPlayer.firstName); } } } } + + // After calculating all player scores, batch insert team scores into the ledger + if (teamScores.size > 0) { + const ledgerEntries = Array.from(teamScores.entries()).map(([teamID, points]) => ({ + ledgerID: ledgerEntryId, + teamID, + points + })); + + let newScores = await db.insert(schema.scoreLedger).values(ledgerEntries).returning(); + console.log(newScores); + } + + // 2. Determine the winner right here using the same Map data + let highestScore = -1; + let winningTeamId = null; + + for (let [teamID, points] of teamScores.entries()) { + if (points > highestScore) { + highestScore = points; + winningTeamId = teamID; + } + } + + if (winningTeamId) { + let teamWinnerUpdate = await db + .update(schema.registeredEvents) + .set({ teamWinner: winningTeamId, state: 2, timeCompleted: Date.now() }) + .where(eq(schema.registeredEvents.id, responseBody.eventId)) + .returning(); + console.log(teamWinnerUpdate); + } } + // Update the frontends globalEmitter.emit('scoreUpdate'); - // Return a resonse because + // Return a response because return new Response('coolsies'); } } diff --git a/src/routes/event/[eventId]/+page.svelte b/src/routes/event/[eventId]/+page.svelte index d6e4881..6e02276 100644 --- a/src/routes/event/[eventId]/+page.svelte +++ b/src/routes/event/[eventId]/+page.svelte @@ -41,7 +41,29 @@ 'Content-type': 'application/json; charset=UTF-8' } }); - return response.json(); + + const data = await response.json(); + + // Sort the players inside each bracket before returning the data + if (data && data[0] && data[0].registeredPlayers) { + data[0].registeredPlayers.forEach((bracket: any) => { + bracket.items.sort((a: any, b: any) => { + // 1. Both have no placement (placement === 0) -> keep original order + if (a.placement === 0 && b.placement === 0) return 0; + + // 2. 'a' has no placement, but 'b' does -> move 'b' to the top + if (a.placement === 0) return 1; + + // 3. 'a' has a placement, but 'b' doesn't -> keep 'a' on top + if (b.placement === 0) return -1; + + // 4. Both have placements -> sort ascending (1st, 2nd, 3rd, etc.) + return a.placement - b.placement; + }); + }); + } + + return data; } let eventDataPromise = getEventData(); diff --git a/src/routes/event/scoring/[eventId]/+page.svelte b/src/routes/event/scoring/[eventId]/+page.svelte index f7c7ce0..e02eb03 100644 --- a/src/routes/event/scoring/[eventId]/+page.svelte +++ b/src/routes/event/scoring/[eventId]/+page.svelte @@ -29,7 +29,7 @@ return { destroy: () => ro.disconnect() }; } - let eventId = params.eventId; + let eventId = parseInt(params.eventId); let eventEndpoint: EventSource; type Player = { firstName: string; lastName: string; teamColor: string; [key: string]: any }; @@ -93,6 +93,19 @@ ...bracket, items: sortByScore ? [...bracket.items].sort((a, b) => { + // 1. Check if players actually have committed scores + const scoresA = committedScores[a.id]?.filter((s) => s !== null) ?? []; + const scoresB = committedScores[b.id]?.filter((s) => s !== null) ?? []; + + const hasA = scoresA.length > 0; + const hasB = scoresB.length > 0; + + // 2. Handle cases where one or both don't have scores + if (!hasA && !hasB) return 0; // Neither have scores, keep order + if (!hasA) return 1; // 'a' has no score -> push down + if (!hasB) return -1; // 'b' has no score -> push down + + // 3. Both have scores, fallback to standard leaderboard sorting const fallback = lowerIsBetter ? Infinity : -Infinity; const sa = useAverage ? average(committedScores[a.id] ?? [], fallback) @@ -100,6 +113,7 @@ const sb = useAverage ? average(committedScores[b.id] ?? [], fallback) : best(committedScores[b.id] ?? [], fallback); + return lowerIsBetter ? sa - sb : sb - sa; }) : bracket.items @@ -238,9 +252,9 @@ {event.name} - {event.division} - scoring {#if event.state == 1}- ONGOING @@ -323,6 +337,7 @@ {