package bible import ( "embed" "sort" "strconv" "strings" "sync" ) //go:embed corpora/wuj.tsv corpora/vul.tsv corpora/grb.tsv corpora/drb.tsv var corporaFS embed.FS // Verse is a single verse. type Verse struct { Chapter, Verse int Text string } type corpus struct { books map[string]map[int][]Verse // book -> chapter -> verses (verse-ordered) } var ( corpora = map[string]*corpus{} corporaMu sync.Mutex ) func load(version string) *corpus { corporaMu.Lock() defer corporaMu.Unlock() if c, ok := corpora[version]; ok { return c } data, err := corporaFS.ReadFile("corpora/" + version + ".tsv") if err != nil { corpora[version] = &corpus{books: map[string]map[int][]Verse{}} return corpora[version] } c := &corpus{books: map[string]map[int][]Verse{}} for _, line := range strings.Split(string(data), "\n") { f := strings.Split(line, "\t") if len(f) != 6 { continue } chap, _ := strconv.Atoi(f[3]) vn, _ := strconv.Atoi(f[4]) book := f[0] if c.books[book] == nil { c.books[book] = map[int][]Verse{} } c.books[book][chap] = append(c.books[book][chap], Verse{chap, vn, f[5]}) } corpora[version] = c return c } // Verses returns all verses of one chapter of a book in a version (may be empty). func Verses(version, book string, chap int) []Verse { return load(version).books[book][chap] } // Chapters returns the chapter numbers present for a book in a version, sorted // ascending (empty if the version has no such book). func Chapters(version, book string) []int { chapMap := load(version).books[book] chaps := make([]int, 0, len(chapMap)) for ch := range chapMap { chaps = append(chaps, ch) } sort.Ints(chaps) return chaps }