aboutsummaryrefslogtreecommitdiff
path: root/internal/bible/bible.go
blob: 1bc898312ad2405c7ca8242c9e3f38f4fc823536 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package bible

import (
	"embed"
	"sort"
	"strconv"
	"strings"
	"sync"
)

//go:embed corpora
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
}

// CorpusBooks returns the book names present in a version's corpus, sorted
// (empty for a version with no embedded corpus, e.g. "bt").
func CorpusBooks(version string) []string {
	c := load(version)
	books := make([]string, 0, len(c.books))
	for b := range c.books {
		books = append(books, b)
	}
	sort.Strings(books)
	return books
}