Created
November 22, 2025 12:29
-
-
Save gatlin/4bee9645b96e8b9e733960453b972f49 to your computer and use it in GitHub Desktop.
(partially) vibe coded bible reading planner
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| cabal-version: 3.0 | |
| name: bible-reading | |
| version: 0.1.0.0 | |
| synopsis: Bible reading plan generator | |
| description: A simple program to generate Bible reading schedules following the tradition of reading 3 chapters Monday-Saturday and 5 on Sunday. | |
| license: MIT | |
| license-file: LICENSE | |
| author: Your Name | |
| maintainer: [email protected] | |
| homepage: https://github.com/yourusername/bible-reading | |
| category: Text | |
| build-type: Simple | |
| executable bible-reading | |
| main-is: Main.hs | |
| hs-source-dirs: . | |
| default-language: Haskell2010 | |
| build-depends: | |
| base >= 4.14 && < 5, | |
| time >= 1.9 && < 1.10, | |
| text >= 1.2 && < 2 | |
| ghc-options: | |
| -Werror | |
| -O2 | |
| default-extensions: | |
| OverloadedStrings |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import qualified Data.Time as T | |
| import qualified Data.Time.Calendar.WeekDate as WD | |
| import Text.Printf (printf) | |
| import System.Environment (getArgs) | |
| import Data.List (findIndex) | |
| main :: IO () | |
| main = do | |
| args <- getArgs | |
| case args of | |
| [dateStr, startBook, startChapterStr] -> do | |
| let startDate = readDay dateStr | |
| startChapter = (startBook, read startChapterStr) | |
| putStrLn "Bible Reading Plan" | |
| putStrLn "==================" | |
| mapM_ putStrLn $ generateReadingPlan startDate startChapter | |
| _ -> do | |
| putStrLn "Usage: bible-reading <date> <start-book> <start-chapter>" | |
| putStrLn "Example: bible-reading \"2023-12-01\" \"Genesis\" 1" | |
| putStrLn "" | |
| putStrLn "This program generates a 30-day Bible reading plan following" | |
| putStrLn "the tradition of reading 3 chapters Monday through Saturday," | |
| putStrLn "and 5 on Sunday." | |
| -- Bible book data structure | |
| data Book = Book | |
| { bookName :: String | |
| , bookChapters :: Int | |
| } deriving (Show, Eq) | |
| -- Chapter reference (book name, chapter number) | |
| type ChapterRef = (String, Int) | |
| -- Reading schedule: [Sun, Mon, Tues, Wed, Thu, Fri, Sat] | |
| schedule :: [Int] | |
| schedule = [5, 3, 3, 3, 3, 3, 3] | |
| -- Generate list of days with their reading assignments | |
| generateReadingPlan :: T.Day -> ChapterRef -> [String] | |
| generateReadingPlan startDate startChapter = | |
| take daysRemaining $ zipWith3 formatDayReading days chaps plan | |
| where | |
| days = map (`T.addDays` startDate) [0..] | |
| plan = [schedule !! dayOfWeek d | d <- days] | |
| startChapterNumber = chapterToNumber startChapter | |
| cumulative = scanl (+) startChapterNumber plan | |
| chaps = map numberToChapter cumulative | |
| totalChapters = sum (map bookChapters bibleBooks) | |
| daysRemaining = length $ takeWhile (<= totalChapters) cumulative | |
| -- Format a single day's reading | |
| formatDayReading :: T.Day -> ChapterRef -> Int -> String | |
| formatDayReading day (book, chapter) = | |
| printf "%s: %s %d (%d chapters)" (formatDay day) book chapter | |
| -- Format day as string | |
| formatDay :: T.Day -> String | |
| formatDay = T.formatTime T.defaultTimeLocale "%A, %B %d, %Y" | |
| -- Get book index by name | |
| bookIndexByName :: String -> Int | |
| bookIndexByName name = | |
| case findIndex (\b -> bookName b == name) bibleBooks of | |
| Just idx -> idx | |
| Nothing -> error $ "Unknown book: " ++ name | |
| -- Get book by index | |
| bookByIndex :: Int -> Book | |
| bookByIndex idx | |
| | idx < length bibleBooks = bibleBooks !! idx | |
| | otherwise = error "Ran out of Bible." | |
| -- Convert chapter reference to a simple number for easier calculation | |
| chapterToNumber :: ChapterRef -> Int | |
| chapterToNumber (bkName, chapter) = cumulative + chapter | |
| where | |
| bookIdx = bookIndexByName bkName | |
| cumulative = sum [bookChapters (bibleBooks !! i) | i <- [0..bookIdx-1]] | |
| -- Convert number back to chapter reference | |
| numberToChapter :: Int -> ChapterRef | |
| numberToChapter n = (bookName book, localChapter) | |
| where | |
| cumulative = scanl (+) 0 (map bookChapters bibleBooks) | |
| bookIdx = length (takeWhile (< n) cumulative) - 1 | |
| book = bookByIndex bookIdx | |
| localChapter = n - cumulative !! bookIdx | |
| -- Get day of week (0 = Sunday, 1 = Monday, etc.) | |
| dayOfWeek :: T.Day -> Int | |
| dayOfWeek day = d `mod` 7 where (_, _, d) = WD.toWeekDate day | |
| -- Simple date parsing | |
| readDay :: String -> T.Day | |
| readDay str = case map read (splitOn '-' str) :: [Int] of | |
| [year, month, day] -> T.fromGregorian (toInteger year) month day | |
| _ -> error "error parsing date string" | |
| -- Helper function to split string by delimiter | |
| splitOn :: Eq a => a -> [a] -> [[a]] | |
| splitOn _ [] = [] | |
| splitOn delim str = | |
| let (before, after) = break (== delim) str | |
| in before : case after of | |
| [] -> [] | |
| (_:rest) -> splitOn delim rest | |
| -- Bible books with their chapter counts | |
| bibleBooks :: [Book] | |
| bibleBooks = | |
| [ Book "Genesis" 50 | |
| , Book "Exodus" 40 | |
| , Book "Leviticus" 27 | |
| , Book "Numbers" 36 | |
| , Book "Deuteronomy" 34 | |
| , Book "Joshua" 24 | |
| , Book "Judges" 21 | |
| , Book "Ruth" 4 | |
| , Book "1 Samuel" 31 | |
| , Book "2 Samuel" 24 | |
| , Book "1 Kings" 22 | |
| , Book "2 Kings" 25 | |
| , Book "1 Chronicles" 29 | |
| , Book "2 Chronicles" 36 | |
| , Book "Ezra" 10 | |
| , Book "Nehemiah" 13 | |
| , Book "Esther" 10 | |
| , Book "Job" 42 | |
| , Book "Psalms" 150 | |
| , Book "Proverbs" 31 | |
| , Book "Ecclesiastes" 12 | |
| , Book "Song of Solomon" 8 | |
| , Book "Isaiah" 66 | |
| , Book "Jeremiah" 52 | |
| , Book "Lamentations" 5 | |
| , Book "Ezekiel" 48 | |
| , Book "Daniel" 12 | |
| , Book "Hosea" 14 | |
| , Book "Joel" 3 | |
| , Book "Amos" 9 | |
| , Book "Obadiah" 1 | |
| , Book "Jonah" 4 | |
| , Book "Micah" 7 | |
| , Book "Nahum" 3 | |
| , Book "Habakkuk" 3 | |
| , Book "Zephaniah" 3 | |
| , Book "Haggai" 2 | |
| , Book "Zechariah" 14 | |
| , Book "Malachi" 4 | |
| , Book "Matthew" 28 | |
| , Book "Mark" 16 | |
| , Book "Luke" 24 | |
| , Book "John" 21 | |
| , Book "Acts" 28 | |
| , Book "Romans" 16 | |
| , Book "1 Corinthians" 16 | |
| , Book "2 Corinthians" 13 | |
| , Book "Galatians" 6 | |
| , Book "Ephesians" 6 | |
| , Book "Philippians" 4 | |
| , Book "Colossians" 4 | |
| , Book "1 Thessalonians" 5 | |
| , Book "2 Thessalonians" 3 | |
| , Book "1 Timothy" 6 | |
| , Book "2 Timothy" 4 | |
| , Book "Titus" 3 | |
| , Book "Philemon" 1 | |
| , Book "Hebrews" 13 | |
| , Book "James" 5 | |
| , Book "1 Peter" 5 | |
| , Book "2 Peter" 3 | |
| , Book "1 John" 5 | |
| , Book "2 John" 1 | |
| , Book "3 John" 1 | |
| , Book "Jude" 1 | |
| , Book "Revelation" 22 | |
| ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment