mirror of
https://github.com/pupperpowell/bibdle.git
synced 2026-04-05 17:33:31 -04:00
Refactor game logic into utility modules and add cross-device sync
Extracted game state management, share logic, and stats API calls into dedicated modules (game-persistence.svelte.ts, share.ts, stats-client.ts), and moved daily verse loading to client-side to fix timezone issues. Added a guesses column to daily_completions for cross-device state restoration for logged-in users, a new GET /api/stats endpoint, and a staging deploy script. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
import { bibleBooks, type BibleBook } from '$lib/types/bible';
|
||||
|
||||
export interface Guess {
|
||||
book: BibleBook;
|
||||
testamentMatch: boolean;
|
||||
sectionMatch: boolean;
|
||||
adjacent: boolean;
|
||||
firstLetterMatch: boolean;
|
||||
}
|
||||
|
||||
export function getBookById(id: string): BibleBook | undefined {
|
||||
return bibleBooks.find((b) => b.id === id);
|
||||
}
|
||||
@@ -10,7 +18,47 @@ export function isAdjacent(id1: string, id2: string): boolean {
|
||||
return !!(b1 && b2 && Math.abs(b1.order - b2.order) === 1);
|
||||
}
|
||||
|
||||
export function getGrade(numGuesses: number, popularity: number): string {
|
||||
export function getFirstLetter(bookName: string): string {
|
||||
const match = bookName.match(/[a-zA-Z]/);
|
||||
return match ? match[0] : bookName[0];
|
||||
}
|
||||
|
||||
export function evaluateGuess(guessBookId: string, correctBookId: string): Guess | null {
|
||||
const book = getBookById(guessBookId);
|
||||
const correctBook = getBookById(correctBookId);
|
||||
if (!book || !correctBook) return null;
|
||||
|
||||
const testamentMatch = book.testament === correctBook.testament;
|
||||
const sectionMatch = book.section === correctBook.section;
|
||||
const adjacent = isAdjacent(guessBookId, correctBookId);
|
||||
|
||||
// Special case: if correct book is in the Epistles + starts with "1",
|
||||
// any guess starting with "1" counts as first letter match
|
||||
const correctIsEpistlesWithNumber =
|
||||
(correctBook.section === "Pauline Epistles" ||
|
||||
correctBook.section === "General Epistles") &&
|
||||
correctBook.name[0] === "1";
|
||||
const guessIsEpistlesWithNumber =
|
||||
(book.section === "Pauline Epistles" ||
|
||||
book.section === "General Epistles") &&
|
||||
book.name[0] === "1";
|
||||
|
||||
const firstLetterMatch =
|
||||
correctIsEpistlesWithNumber && guessIsEpistlesWithNumber
|
||||
? true
|
||||
: getFirstLetter(book.name).toUpperCase() ===
|
||||
getFirstLetter(correctBook.name).toUpperCase();
|
||||
|
||||
return {
|
||||
book,
|
||||
testamentMatch,
|
||||
sectionMatch,
|
||||
adjacent,
|
||||
firstLetterMatch,
|
||||
};
|
||||
}
|
||||
|
||||
export function getGrade(numGuesses: number): string {
|
||||
if (numGuesses === 1) return "S+";
|
||||
if (numGuesses === 2) return "A+";
|
||||
if (numGuesses === 3) return "A";
|
||||
@@ -49,4 +97,4 @@ export function generateUUID(): string {
|
||||
const v = c === "x" ? r : (r & 0x3) | 0x8;
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user