mirror of
https://github.com/pupperpowell/bibdle.git
synced 2026-04-05 17:33:31 -04:00
99 lines
2.8 KiB
TypeScript
99 lines
2.8 KiB
TypeScript
import type { Guess } from './game';
|
|
|
|
export function getVerseSnippet(verseText: string): string {
|
|
const words = verseText.trim().split(/\s+/);
|
|
const slice = words.slice(0, 25);
|
|
const text = slice.join(' ');
|
|
|
|
// Returns character index immediately after the Nth word (1-indexed)
|
|
function posAfterWord(n: number): number {
|
|
let pos = 0;
|
|
for (let w = 0; w < Math.min(n, slice.length); w++) {
|
|
if (w > 0) pos++; // space between words
|
|
pos += slice[w].length;
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
const start = posAfterWord(9);
|
|
const end = posAfterWord(25);
|
|
|
|
// Find first punctuation mark between words 10 and 25
|
|
const range = text.substring(start, end);
|
|
const match = range.match(/[,;:.!?—–-]/);
|
|
|
|
function withClosedQuotes(snippet: string): string {
|
|
const opens = (snippet.match(/\u201C/g) ?? []).length;
|
|
const closes = (snippet.match(/\u201D/g) ?? []).length;
|
|
const closeQuote = opens > closes ? '\u201D' : '';
|
|
return `\u201C${snippet}...${closeQuote}\u201D`;
|
|
}
|
|
|
|
if (match && match.index !== undefined) {
|
|
const cutPos = start + match.index;
|
|
return withClosedQuotes(text.substring(0, cutPos).trimEnd());
|
|
}
|
|
|
|
return withClosedQuotes(text);
|
|
}
|
|
|
|
export function generateShareText(params: {
|
|
guesses: Guess[];
|
|
correctBookId: string;
|
|
dailyVerseDate: string;
|
|
chapterCorrect: boolean;
|
|
isLoggedIn: boolean;
|
|
streak?: number;
|
|
origin: string;
|
|
verseText: string;
|
|
}): string {
|
|
const { guesses, correctBookId, dailyVerseDate, chapterCorrect, isLoggedIn, streak, origin, verseText } = params;
|
|
|
|
const emojis = guesses
|
|
.slice()
|
|
.reverse()
|
|
.map((guess) => {
|
|
if (guess.book.id === correctBookId) return "✅";
|
|
if (guess.adjacent) return "‼️";
|
|
if (guess.sectionMatch) return "🟩";
|
|
if (guess.testamentMatch) return "🟧";
|
|
return "🟥";
|
|
})
|
|
.join("");
|
|
|
|
const dateFormatter = new Intl.DateTimeFormat("en-US", {
|
|
month: "short",
|
|
day: "numeric",
|
|
year: "numeric",
|
|
});
|
|
const formattedDate = dateFormatter.format(
|
|
new Date(`${dailyVerseDate}T00:00:00`),
|
|
);
|
|
|
|
const bookEmoji = isLoggedIn ? "📜" : "📖";
|
|
|
|
const guessWord = guesses.length === 1 ? "guess" : "guesses";
|
|
const streakPart = streak !== undefined && streak > 1 ? ` ${streak} days 🔥` : "";
|
|
const chapterStar = guesses.length === 1 && chapterCorrect ? " ⭐" : "";
|
|
|
|
const lines = [
|
|
`${bookEmoji} Bibdle | ${formattedDate} ${bookEmoji}`,
|
|
`${guesses.length} ${guessWord}${streakPart ? `,${streakPart}` : ""}`,
|
|
`${emojis}${chapterStar}`
|
|
];
|
|
|
|
return lines.join("\n");
|
|
}
|
|
|
|
export async function shareResult(shareText: string): Promise<void> {
|
|
if ("share" in navigator) {
|
|
await (navigator as any).share({ text: shareText });
|
|
} else {
|
|
await (navigator as any).clipboard.writeText(shareText);
|
|
}
|
|
}
|
|
|
|
export async function copyToClipboard(shareText: string): Promise<void> {
|
|
await (navigator as any).clipboard.writeText(shareText);
|
|
}
|