add First Letter column with special epistle handling

This commit is contained in:
George Powell
2026-01-26 23:31:24 -05:00
parent 77d6254a2c
commit 8c488d27df
2 changed files with 68 additions and 8 deletions

View File

@@ -1,4 +1,6 @@
<script lang="ts"> <script lang="ts">
import { bibleBooks } from "$lib/types/bible";
interface Guess { interface Guess {
book: { book: {
id: string; id: string;
@@ -9,6 +11,7 @@
testamentMatch: boolean; testamentMatch: boolean;
sectionMatch: boolean; sectionMatch: boolean;
adjacent: boolean; adjacent: boolean;
firstLetterMatch: boolean;
} }
let { guesses, correctBookId }: { guesses: Guess[]; correctBookId: string } = let { guesses, correctBookId }: { guesses: Guess[]; correctBookId: string } =
@@ -24,11 +27,28 @@
function getBoxContent( function getBoxContent(
guess: Guess, guess: Guess,
column: "book" | "testament" | "section", column: "book" | "firstLetter" | "testament" | "section",
): string { ): string {
switch (column) { switch (column) {
case "book": case "book":
return guess.book.name; return guess.book.name;
case "firstLetter":
// Check if this is the special Epistles + "1" case
const correctBook = bibleBooks.find((b) => b.id === correctBookId);
const correctIsEpistlesWithNumber =
(correctBook?.section === "Pauline Epistles" ||
correctBook?.section === "General Epistles") &&
correctBook.name[0] === "1";
const guessStartsWithNumber = guess.book.name[0] === "1";
if (
correctIsEpistlesWithNumber &&
guessStartsWithNumber &&
guess.firstLetterMatch
) {
return "Yes"; // Special wordplay case
}
return guess.book.name[0]; // Normal case: just show the first letter
case "testament": case "testament":
return ( return (
guess.book.testament.charAt(0).toUpperCase() + guess.book.testament.charAt(0).toUpperCase() +
@@ -43,29 +63,34 @@
{#if hasGuesses} {#if hasGuesses}
<div class="space-y-3"> <div class="space-y-3">
<!-- Column Headers --> <!-- Column Headers -->
<div class="flex gap-2 justify-center mb-4 pb-2 border-b border-gray-800"> <div class="flex gap-2 justify-center mb-4 pb-2 border-b border-gray-400">
<div <div
class="flex-1 text-center text-sm font-semibold text-gray-700" class="w-1/4 shrink-0 text-center text-sm font-semibold text-gray-700"
> >
Book Book
</div> </div>
<div <div
class="flex-1 text-center text-sm font-semibold text-gray-700" class="w-1/4 shrink-0 text-center text-sm font-semibold text-gray-700"
> >
Testament Testament
</div> </div>
<div <div
class="flex-1 text-center text-sm font-semibold text-gray-700" class="w-1/4 shrink-0 text-center text-sm font-semibold text-gray-700"
> >
Section Section
</div> </div>
<div
class="w-1/4 shrink-0 text-center text-sm font-semibold text-gray-700"
>
First Letter
</div>
</div> </div>
{#each guesses as guess, rowIndex (guess.book.id)} {#each guesses as guess, rowIndex (guess.book.id)}
<div class="flex gap-2 justify-center"> <div class="flex gap-2 justify-center">
<!-- Book Column --> <!-- Book Column -->
<div <div
class="flex-1 h-16 sm:h-20 md:h-24 border-2 border-opacity-80 rounded-lg flex items-center justify-center text-white font-bold text-xs sm:text-sm md:text-base shadow-md animate-flip-in {getBoxColor( class="w-1/4 shrink-0 h-16 sm:h-20 md:h-24 border-2 border-opacity-80 rounded-lg flex items-center justify-center text-white font-bold text-base sm:text-lg md:text-xl shadow-md animate-flip-in {getBoxColor(
guess.book.id === correctBookId, guess.book.id === correctBookId,
)}" )}"
style="animation-delay: {rowIndex * 1000 + 0 * 500}ms" style="animation-delay: {rowIndex * 1000 + 0 * 500}ms"
@@ -79,7 +104,7 @@
<!-- Testament Column --> <!-- Testament Column -->
<div <div
class="flex-1 h-16 sm:h-20 md:h-24 border-2 border-opacity-80 rounded-lg flex items-center justify-center text-white font-bold text-xs sm:text-sm md:text-base shadow-md animate-flip-in {getBoxColor( class="w-1/4 shrink-0 h-16 sm:h-20 md:h-24 border-2 border-opacity-80 rounded-lg flex items-center justify-center text-white font-bold text-base sm:text-lg md:text-xl shadow-md animate-flip-in {getBoxColor(
guess.testamentMatch, guess.testamentMatch,
)}" )}"
style="animation-delay: {rowIndex * 1000 + 1 * 500}ms" style="animation-delay: {rowIndex * 1000 + 1 * 500}ms"
@@ -93,7 +118,7 @@
<!-- Section Column --> <!-- Section Column -->
<div <div
class="relative flex-1 h-16 sm:h-20 md:h-24 border-2 border-opacity-80 rounded-lg flex items-center justify-center text-white font-bold text-xs sm:text-sm md:text-base shadow-md animate-flip-in {getBoxColor( class="relative w-1/4 shrink-0 h-16 sm:h-20 md:h-24 border-2 border-opacity-80 rounded-lg flex items-center justify-center text-white font-bold text-base sm:text-lg md:text-xl shadow-md animate-flip-in {getBoxColor(
guess.sectionMatch, guess.sectionMatch,
guess.adjacent, guess.adjacent,
)}" )}"
@@ -108,6 +133,20 @@
{/if} {/if}
</span> </span>
</div> </div>
<!-- First Letter Column -->
<div
class="w-1/4 shrink-0 h-16 sm:h-20 md:h-24 border-2 border-opacity-80 rounded-lg flex items-center justify-center text-white font-bold text-base sm:text-lg md:text-xl shadow-md animate-flip-in {getBoxColor(
guess.firstLetterMatch,
)}"
style="animation-delay: {rowIndex * 1000 + 3 * 500}ms"
>
<span
class="text-center leading-tight px-1"
style="text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);"
>{getBoxContent(guess, "firstLetter")}</span
>
</div>
</div> </div>
{/each} {/each}
</div> </div>

View File

@@ -17,6 +17,7 @@
testamentMatch: boolean; testamentMatch: boolean;
sectionMatch: boolean; sectionMatch: boolean;
adjacent: boolean; adjacent: boolean;
firstLetterMatch: boolean;
} }
let { data }: PageProps = $props(); let { data }: PageProps = $props();
@@ -87,6 +88,15 @@
const testamentMatch = book.testament === correctBook.testament; const testamentMatch = book.testament === correctBook.testament;
const sectionMatch = book.section === correctBook.section; const sectionMatch = book.section === correctBook.section;
const adjacent = isAdjacent(bookId, correctBookId); const adjacent = isAdjacent(bookId, correctBookId);
// Special case: if correct book is Epistles + starts with "1",
// any guess starting with "1" counts as first letter match
const correctIsEpistlesWithNumber = correctBook.section === "Epistles" && correctBook.name[0] === "1";
const guessStartsWithNumber = book.name[0] === "1";
const firstLetterMatch = correctIsEpistlesWithNumber && guessStartsWithNumber
? true
: book.name[0].toUpperCase() === correctBook.name[0].toUpperCase();
console.log( console.log(
`Guess: ${book.name} (order ${book.order}), Correct: ${correctBook.name} (order ${correctBook.order}), Adjacent: ${adjacent}` `Guess: ${book.name} (order ${book.order}), Correct: ${correctBook.name} (order ${correctBook.order}), Adjacent: ${adjacent}`
@@ -110,6 +120,7 @@
testamentMatch, testamentMatch,
sectionMatch, sectionMatch,
adjacent, adjacent,
firstLetterMatch,
}, },
...guesses, ...guesses,
]; ];
@@ -181,11 +192,21 @@
const testamentMatch = book.testament === correctBook.testament; const testamentMatch = book.testament === correctBook.testament;
const sectionMatch = book.section === correctBook.section; const sectionMatch = book.section === correctBook.section;
const adjacent = isAdjacent(bookId, correctBookId); const adjacent = isAdjacent(bookId, correctBookId);
// Apply same first letter logic as in submitGuess
const correctIsEpistlesWithNumber = correctBook.section === "Epistles" && correctBook.name[0] === "1";
const guessStartsWithNumber = book.name[0] === "1";
const firstLetterMatch = correctIsEpistlesWithNumber && guessStartsWithNumber
? true
: book.name[0].toUpperCase() === correctBook.name[0].toUpperCase();
return { return {
book, book,
testamentMatch, testamentMatch,
sectionMatch, sectionMatch,
adjacent, adjacent,
firstLetterMatch,
}; };
}); });
} }