all repos — bibel @ 01c758ad65f39049a6b57f85c0e09c74b5f1f1ea

Unnamed repository; edit this file 'description' to name the repository.

internal/dateprogression.go (view raw)

  1package bible
  2
  3import (
  4	"fmt"
  5	"time"
  6)
  7
  8// DateProgression handles calculating Bible position based on date
  9type DateProgression struct {
 10	bible       *Bible
 11	versesPerDay int
 12}
 13
 14// NewDateProgression creates a new date progression calculator
 15func NewDateProgression(bible *Bible) *DateProgression {
 16	return &DateProgression{bible: bible, versesPerDay: 12}
 17}
 18
 19// NewDateProgressionWithConfig creates a new date progression calculator with config
 20func NewDateProgressionWithConfig(bible *Bible, versesPerDay int) *DateProgression {
 21	if versesPerDay <= 0 {
 22		versesPerDay = 12
 23	}
 24	return &DateProgression{bible: bible, versesPerDay: versesPerDay}
 25}
 26
 27// GetPositionForDate calculates the verse range for a given date
 28func (dp *DateProgression) GetPositionForDate(date time.Time) (*Bookmark, error) {
 29	// Calculate day of year (1-366)
 30	dayOfYear := date.YearDay()
 31
 32	// Each day shows configured number of verses
 33	targetVerseOffset := (dayOfYear - 1) * dp.versesPerDay // Zero-indexed
 34
 35	// Walk through Gospels to find the position
 36	return dp.findPositionForOffset(targetVerseOffset)
 37}
 38
 39// findPositionForOffset finds the bookmark for a given cumulative verse offset
 40func (dp *DateProgression) findPositionForOffset(offset int) (*Bookmark, error) {
 41	// Iterate through books 40-43 (Matthew, Mark, Luke, John)
 42	for book := 40; book <= 43; book++ {
 43		// Find last chapter in this book
 44		maxChapter := 0
 45		for chapter := 1; ; chapter++ {
 46			if dp.bible.CountVersesInChapter(book, chapter) == 0 {
 47				maxChapter = chapter - 1
 48				break
 49			}
 50		}
 51
 52		// Iterate through chapters
 53		for chapter := 1; chapter <= maxChapter; chapter++ {
 54			versesInChapter := dp.bible.CountVersesInChapter(book, chapter)
 55
 56			// Check if offset falls within this chapter
 57			if offset < versesInChapter {
 58				// Offset is within this chapter
 59				firstVerse := offset + 1 // Convert from 0-indexed to 1-indexed
 60
 61				// Create initial bookmark (like AdvanceBookmark does)
 62				secondVerse := min(firstVerse+dp.versesPerDay-1, versesInChapter)
 63				bookmark := &Bookmark{
 64					Book:        BookIndex(book),
 65					Chapter:     chapter,
 66					FirstVerse:  firstVerse,
 67					SecondVerse: secondVerse,
 68				}
 69
 70				// Apply lookahead rule (like AdjustForLookahead)
 71				return dp.applyLookahead(bookmark), nil
 72			}
 73
 74			// Move to next chapter, subtracting this chapter's verses
 75			offset -= versesInChapter
 76		}
 77	}
 78
 79	// If we've gone through all Gospels and offset is still positive, wrap
 80	// around to beginning (start over) Calculate modulo offset within total
 81	// Gospel verses
 82	totalVerses := dp.GetTotalGospelVerses()
 83	if offset >= 0 {
 84		adjustedOffset := offset % totalVerses
 85		// Recursively find position for adjusted offset
 86		return dp.findPositionForOffset(adjustedOffset)
 87	}
 88
 89	return nil, fmt.Errorf("could not find position for offset %d", offset)
 90}
 91
 92// applyLookahead applies the lookahead rule (same as BookmarkManager.AdjustForLookahead)
 93func (dp *DateProgression) applyLookahead(bookmark *Bookmark) *Bookmark {
 94	versesInChapter := dp.bible.CountVersesInChapter(int(bookmark.Book), bookmark.Chapter)
 95	versesRemaining := versesInChapter - bookmark.SecondVerse
 96
 97	// If we're not at the end of the chapter and less than dp.versesPerDay verses remain for NEXT snippet
 98	if versesRemaining > 0 && versesRemaining < dp.versesPerDay {
 99		return &Bookmark{
100			Book:        bookmark.Book,
101			Chapter:     bookmark.Chapter,
102			FirstVerse:  bookmark.FirstVerse,
103			SecondVerse: versesInChapter,
104		}
105	}
106
107	// Otherwise return the original bookmark
108	return bookmark
109}
110
111// GetTotalGospelVerses returns the total number of verses in all four Gospels
112func (dp *DateProgression) GetTotalGospelVerses() int {
113	total := 0
114	for book := 40; book <= 43; book++ {
115		for chapter := 1; ; chapter++ {
116			verses := dp.bible.CountVersesInChapter(book, chapter)
117			if verses == 0 {
118				break
119			}
120			total += verses
121		}
122	}
123	return total
124}