@@ -9,18 +9,36 @@ import (
9
9
"os"
10
10
"path"
11
11
"runtime"
12
+ "strings"
12
13
13
14
"github.com/derekparker/trie"
14
15
)
15
16
17
+ type SearchNode struct {
18
+ Part * Part
19
+ Article * Article
20
+ Section * Section
21
+ Paragraph * Paragraph
22
+ }
23
+
24
+ // String creates a string representation for the SearchNode,
25
+ // ex. Part 1, Article 1, Section 1, Paragraph 1
26
+ func (s * SearchNode ) String () string {
27
+ return fmt .Sprintf ("Part %d, Article %d, Section %d, Paragraph %d" ,
28
+ s .Part .PartNumber ,
29
+ s .Article .ArticleNumber ,
30
+ s .Section .SectionNumber ,
31
+ s .Paragraph .ParagraphNumber );
32
+ }
33
+
16
34
const catechismTar = "catechism.tar.gz"
17
35
const catechismFilename = "catechism.json"
18
36
19
37
func NewCatechism () * Catechism {
20
38
_ , currFile , _ , _ := runtime .Caller (0 )
21
39
filename := fmt .Sprintf ("%s/%s" , path .Dir (currFile ), catechismTar )
22
40
23
- c := & Catechism {
41
+ catechism := & Catechism {
24
42
searchTree : trie .New (),
25
43
}
26
44
@@ -41,15 +59,55 @@ func NewCatechism() *Catechism {
41
59
42
60
switch h .Name {
43
61
case catechismFilename :
44
- c .Parts = decode (tr )
62
+ catechism .Parts = decode (tr )
45
63
}
46
64
}
47
65
48
- return c
66
+ // Build search tree
67
+ for i := range catechism .Parts {
68
+ p := catechism .Parts [i ]
69
+ for j := range p .Articles {
70
+ a := p .Articles [j ]
71
+ for k := range a .Sections {
72
+ s := a .Sections [k ]
73
+ for l := range s .Paragraphs {
74
+ par := s .Paragraphs [l ]
75
+ t := strings .ToLower (par .Text )
76
+ catechism .searchTree .Add (t , SearchNode {
77
+ Part : & p ,
78
+ Article : & a ,
79
+ Section : & s ,
80
+ Paragraph : & par ,
81
+ })
82
+ }
83
+ }
84
+ }
85
+ }
86
+
87
+ return catechism
49
88
}
50
89
51
90
func decode (r io.Reader ) []Part {
52
91
var parts []Part
53
92
json .NewDecoder (r ).Decode (& parts )
54
93
return parts
55
94
}
95
+
96
+ // Search finds top matching verses based on the given query.
97
+ // The number of search results are restricted by maxResults
98
+ func (c * Catechism ) Search (query string , maxResults int ) []SearchNode {
99
+ t := c .searchTree
100
+ keys := t .FuzzySearch (strings .ToLower (query ))
101
+ var nodes []SearchNode
102
+
103
+ for k := range keys {
104
+ res , _ := t .Find (keys [k ])
105
+ nodes = append (nodes , res .Meta ().(SearchNode ))
106
+
107
+ if len (nodes ) >= maxResults {
108
+ break
109
+ }
110
+ }
111
+
112
+ return nodes
113
+ }
0 commit comments