mirror of
https://github.com/pupperpowell/bibdle.git
synced 2026-02-04 10:54:44 -05:00
Merge github/main into embeddings
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -27,6 +27,6 @@ vite.config.ts.timestamp-*
|
||||
|
||||
llms-*
|
||||
|
||||
engwebu_usfx.xml
|
||||
embeddings-cache-L12.json
|
||||
embeddings-cache-L6.json
|
||||
engwebu_usfx.xml
|
||||
|
||||
@@ -20271,7 +20271,7 @@
|
||||
<chapter number="56">
|
||||
<verse number="1">Thus says the Lord: “Keep justice, and do righteousness, For My salvation is about to come, And My righteousness to be revealed.</verse>
|
||||
<verse number="2">Blessed is the man who does this, And the son of man who lays hold on it; Who keeps from defiling the Sabbath, And keeps his hand from doing any evil.”</verse>
|
||||
<verse number="3">Do not let the son of the foreigner Who has joined himself to the LordSpeak, saying, “The Lord has utterly separated me from His people”; Nor let the eunuch say, “Here I am, a dry tree.”</verse>
|
||||
<verse number="3">Do not let the son of the foreigner Who has joined himself to the Lord speak, saying, “The Lord has utterly separated me from His people”; Nor let the eunuch say, “Here I am, a dry tree.”</verse>
|
||||
<verse number="4">For thus says the Lord: “To the eunuchs who keep My Sabbaths, And choose what pleases Me, And hold fast My covenant,</verse>
|
||||
<verse number="5">Even to them I will give in My house And within My walls a place and a name Better than that of sons and daughters; I will give them an everlasting name That shall not be cut off.</verse>
|
||||
<verse number="6">“Also the sons of the foreigner Who join themselves to the Lord, to serve Him, And to love the name of the Lord, to be His servants— Everyone who keeps from defiling the Sabbath, And holds fast My covenant—</verse>
|
||||
|
||||
53
scripts/average-guesses.ts
Normal file
53
scripts/average-guesses.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import Database from 'bun:sqlite';
|
||||
|
||||
// Database path - adjust if your database is located elsewhere
|
||||
const dbPath = process.env.DATABASE_URL || './local.db';
|
||||
|
||||
console.log(`Connecting to database: ${dbPath}`);
|
||||
|
||||
const db = new Database(dbPath);
|
||||
|
||||
// Query all rows from daily_completions
|
||||
const query = db.query(`
|
||||
SELECT date, guess_count
|
||||
FROM daily_completions
|
||||
ORDER BY date
|
||||
`);
|
||||
|
||||
const rows = query.all() as { date: string; guess_count: number }[];
|
||||
|
||||
if (rows.length === 0) {
|
||||
console.log('No completions found in the database.');
|
||||
db.close();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Group by date and calculate average guesses
|
||||
const dateStats = new Map<string, { total: number; count: number }>();
|
||||
|
||||
for (const row of rows) {
|
||||
const existing = dateStats.get(row.date) || { total: 0, count: 0 };
|
||||
existing.total += row.guess_count;
|
||||
existing.count += 1;
|
||||
dateStats.set(row.date, existing);
|
||||
}
|
||||
|
||||
// Display results
|
||||
console.log('\n=== Average Guesses Per Day ===\n');
|
||||
console.log('Date | Avg Guesses | Total Completions');
|
||||
console.log('--------------|-------------|-------------------');
|
||||
|
||||
for (const [date, stats] of dateStats) {
|
||||
const avg = (stats.total / stats.count).toFixed(2);
|
||||
console.log(`${date.padEnd(14)}| ${avg.padStart(11)}| ${stats.count.toString().padStart(19)}`);
|
||||
}
|
||||
|
||||
// Calculate overall average
|
||||
const totalGuesses = Array.from(dateStats.values()).reduce((sum, s) => sum + s.total, 0);
|
||||
const totalCompletions = Array.from(dateStats.values()).reduce((sum, s) => sum + s.count, 0);
|
||||
const overallAvg = (totalGuesses / totalCompletions).toFixed(2);
|
||||
|
||||
console.log('--------------|-------------|-------------------');
|
||||
console.log(`Overall Average: ${overallAvg} guesses across ${totalCompletions} completions`);
|
||||
|
||||
db.close();
|
||||
@@ -6,13 +6,16 @@
|
||||
let displayReference = $derived(
|
||||
dailyVerse.reference.replace(/^Psalms /, "Psalm ")
|
||||
);
|
||||
let displayVerseText = $derived(
|
||||
dailyVerse.verseText.replace(/^([a-z])/, (c) => c.toUpperCase())
|
||||
);
|
||||
</script>
|
||||
|
||||
<div class="bg-gray-50 rounded-2xl shadow-xl p-8 sm:p-12 mb-4 sm:mb-12 w-full">
|
||||
<blockquote
|
||||
class="text-xl sm:text-2xl font-triodion leading-relaxed text-gray-700 text-center"
|
||||
>
|
||||
{dailyVerse.verseText}
|
||||
{displayVerseText}
|
||||
</blockquote>
|
||||
{#if isWon}
|
||||
<p class="text-center text-lg! big-text text-green-600! font-bold mt-8">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { fade } from "svelte/transition";
|
||||
import { getBookById, toOrdinal, getNextGradeMessage } from "$lib/utils/game";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
interface StatsData {
|
||||
solveRank: number;
|
||||
@@ -33,10 +34,10 @@
|
||||
|
||||
// List of congratulations messages with weights
|
||||
const congratulationsMessages: WeightedMessage[] = [
|
||||
{ text: "🎉 Congratulations! 🎉", weight: 1000 },
|
||||
{ text: "⭐ You got it! ⭐", weight: 10 },
|
||||
{ text: "🎉 Yup 🎉", weight: 5 },
|
||||
{ text: "👍🏻 Very nice! 👍🏻", weight: 1 },
|
||||
{ text: "Congratulations!", weight: 10 },
|
||||
{ text: "You got it!", weight: 1000 },
|
||||
{ text: "Yup,", weight: 100 },
|
||||
{ text: "Very nice!", weight: 1 },
|
||||
];
|
||||
|
||||
// Function to select a random message based on weights
|
||||
@@ -45,9 +46,9 @@
|
||||
if (guessCount === 1) {
|
||||
const n = Math.random();
|
||||
if (n < 0.99) {
|
||||
return "🤯 First try! 🤯";
|
||||
return "🌟 First try! 🌟";
|
||||
} else {
|
||||
return "‼️ Axios ‼️";
|
||||
return "🗣️ Axios! 🗣️";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,13 +76,12 @@
|
||||
<div
|
||||
class="p-8 sm:p-12 w-full bg-linear-to-r from-green-400 to-green-600 text-white rounded-2xl shadow-2xl text-center fade-in"
|
||||
>
|
||||
<h2 class="text-2xl sm:text-4xl font-black mb-4 drop-shadow-lg">
|
||||
<!-- <h2 class="text-2xl sm:text-4xl font-black mb-4 drop-shadow-lg">
|
||||
{congratulationsMessage}
|
||||
</h2>
|
||||
<p class="text-lg sm:text-xl md:text-2xl">
|
||||
The verse is from <span class="font-black text-xl sm:text-2xl md:text-3xl"
|
||||
>{bookName}</span
|
||||
>
|
||||
</h2> -->
|
||||
<p class="text-xl sm:text-3xl md:text-4xl">
|
||||
{congratulationsMessage} The verse is from
|
||||
<span class="font-black text-xl sm:text-2xl md:text-3xl">{bookName}</span>.
|
||||
</p>
|
||||
<p
|
||||
class="text-2xl font-bold mt-6 p-2 mx-2 bg-black/20 rounded-lg inline-block"
|
||||
@@ -167,8 +167,8 @@
|
||||
{statsData.averageGuesses}
|
||||
</div>
|
||||
<div class="text-xs sm:text-sm opacity-90 mt-1">
|
||||
People guessed correctly after {statsData.averageGuesses} guesses on
|
||||
average
|
||||
People guessed correctly after {statsData.averageGuesses}
|
||||
{statsData.averageGuesses === 1 ? "guess" : "guesses"} on average
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -86,6 +86,18 @@
|
||||
`Guess: ${book.name} (order ${book.order}), Correct: ${correctBook.name} (order ${correctBook.order}), Adjacent: ${adjacent}`
|
||||
);
|
||||
|
||||
if (guesses.length === 0) {
|
||||
const key = `bibdle-first-guess-${dailyVerse.date}`;
|
||||
if (
|
||||
localStorage.getItem(key) !== "true" &&
|
||||
browser &&
|
||||
(window as any).umami
|
||||
) {
|
||||
(window as any).umami.track("First guess");
|
||||
localStorage.setItem(key, "true");
|
||||
}
|
||||
}
|
||||
|
||||
guesses = [
|
||||
{
|
||||
book,
|
||||
@@ -260,6 +272,18 @@
|
||||
submitStats();
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (!browser || !isWon) return;
|
||||
const key = `bibdle-win-tracked-${dailyVerse.date}`;
|
||||
if (localStorage.getItem(key) === "true") return;
|
||||
if ((window as any).umami) {
|
||||
(window as any).umami.track("Guessed correctly", {
|
||||
totalGuesses: guesses.length,
|
||||
});
|
||||
}
|
||||
localStorage.setItem(key, "true");
|
||||
});
|
||||
|
||||
function generateShareText(): string {
|
||||
const emojis = guesses
|
||||
.slice()
|
||||
@@ -362,11 +386,12 @@
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Bibdle — A daily bible game{isDev ? " (dev)" : ""}</title>
|
||||
<meta
|
||||
<!-- <title>Bibdle — A daily bible game{isDev ? " (dev)" : ""}</title> -->
|
||||
<title>A daily bible game{isDev ? " (dev)" : ""}</title>
|
||||
<!-- <meta
|
||||
name="description"
|
||||
content="A Wordle-inspired Bible game (short for Bible Daily)"
|
||||
/>
|
||||
content="Guess which book of the Bible a verse comes from."
|
||||
/> -->
|
||||
</svelte:head>
|
||||
|
||||
<div class="min-h-dvh md:bg-linear-to-br md:from-blue-50 md:to-indigo-200 py-8">
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
}
|
||||
|
||||
html, body {
|
||||
background: oklch(98.11% 0.02777 158.93);
|
||||
background: oklch(89.126% 0.06134 298.626);
|
||||
}
|
||||
|
||||
.big-text {
|
||||
|
||||
45
todo.md
45
todo.md
@@ -1,26 +1,37 @@
|
||||
# in progress
|
||||
|
||||
- root menu: classic / imposter mode / impossible mode (complete today's classic and imposter modes to unlock)
|
||||
|
||||
# todo
|
||||
|
||||
- Difficulty levels
|
||||
- difficult mode (guess old or new testament, first try _only_)
|
||||
- impossible mode (1894 scrivener koine greek NT or some hebrew version for OT) three guesses only
|
||||
- impossible mode (1904 greek bible) three guesses only.
|
||||
|
||||
- "login to see your stats, unlock practice mode, and more"
|
||||
- share both classic and impossible mode with both buttons
|
||||
|
||||
- add imposter mode
|
||||
|
||||
- instructions
|
||||
|
||||
- classic mode: identify what book the verse is from (e.g. Genesis, John, Revelations...) in as few guesses as possible.
|
||||
- imposter mode: out of four options, identify the verse that is not in the Bible
|
||||
- impossible mode: identify which book of the bible the verse is from in less than three guesses.
|
||||
|
||||
- add login + saved stats + streak etc.
|
||||
|
||||
- add deuterocanonical books
|
||||
|
||||
<!-- Login features -->
|
||||
|
||||
- Practice mode: Unlimited verses
|
||||
- Create public or private leaderboards
|
||||
- Passport book with badges:
|
||||
- Passport book with awards:
|
||||
|
||||
- Guess each Gospel first try
|
||||
- "Guessed all Gospels", "Perfect week", "Old Testament expert"
|
||||
- Theologian: Guess each book first try
|
||||
- If chapter is 6 and verse 7, earn award "Six seven"
|
||||
|
||||
- instructions
|
||||
|
||||
# places to send
|
||||
|
||||
- linkedin post
|
||||
- ocf discord server ✅
|
||||
- nick makiej ✅
|
||||
- difficult mode (guess old or new testament, first try _only_) (???)
|
||||
|
||||
# About this game
|
||||
|
||||
@@ -36,6 +47,16 @@ I created Bibdle from a combination of two things. The first is my lifelong desi
|
||||
|
||||
# done
|
||||
|
||||
## december 27th
|
||||
|
||||
- add event log to submitting first-guess or correct-guess to umami (to make bounce rate more accurate)
|
||||
|
||||
## december 26th
|
||||
|
||||
- created embeddings for every bible verse (verse similarity finder)
|
||||
- failed at having AI write a USFX format parser
|
||||
- found a npm library for parsing USFX
|
||||
|
||||
## december 23rd
|
||||
|
||||
- switched to local copy of NKJV
|
||||
|
||||
Reference in New Issue
Block a user