File Coverage

blib/lib/Bible/Reference.pm
Criterion Covered Total %
statement 441 443 99.5
branch 158 180 87.7
condition 83 109 76.1
subroutine 27 27 100.0
pod 17 17 100.0
total 726 776 93.5


line stmt bran cond sub pod time code
1             package Bible::Reference;
2             # ABSTRACT: Simple Bible reference parser, tester, and canonicalizer
3              
4 1     1   229451 use 5.020;
  1         9  
5              
6 1     1   500 use exact;
  1         37879  
  1         6  
7 1     1   3023 use exact::class;
  1         11958  
  1         3  
8              
9             our $VERSION = '1.15'; # VERSION
10              
11             has acronyms => 0;
12             has sorting => 1;
13             has require_chapter_match => 0;
14             has require_verse_match => 0;
15             has require_book_ucfirst => 0;
16             has minimum_book_length => 3;
17             has add_detail => 0;
18             has simplify => 0;
19              
20             my $bibles = {
21             ESV => [
22             [
23             [ 'Genesis', 'Ge', 'Gn', 'Gen' ],
24             [ 'Exodus', 'Ex', 'Exo' ],
25             [ 'Leviticus', 'Lv', 'Lev' ],
26             [ 'Numbers', 'Nu', 'Nm', 'Num' ],
27             [ 'Deuteronomy', 'Dt', 'Deu' ],
28             [ 'Joshua', 'Jsh', 'Jos', 'Josh' ],
29             [ 'Judges', 'Jdg', 'Judg' ],
30             [ 'Ruth', 'Ru', 'Rut' ],
31             [ '1 Samuel', '1Sa', '1Sm', '1Sam' ],
32             [ '2 Samuel', '2Sa', '2Sm', '2Sam' ],
33             [ '1 Kings', '1Ki', '1Kg', '1Kgs', '1Kin' ],
34             [ '2 Kings', '2Ki', '2Kg', '2Kgs', '2Kin' ],
35             [ '1 Chronicles', '1Ch', '1Cr', '1Chr' ],
36             [ '2 Chronicles', '2Ch', '2Cr', '2Chr' ],
37             [ 'Ezra', 'Ezr' ],
38             [ 'Nehemiah', 'Ne', 'Neh' ],
39             [ 'Esther', 'Est', 'Esth' ],
40             [ 'Job', 'Jb', 'Jo', 'Job' ],
41             [ 'Psalm', 'Ps', 'Psa', 'Psalms' ],
42             [ 'Proverbs', 'Pr', 'Prv', 'Pro', 'Prov' ],
43             [ 'Ecclesiastes', 'Ec', 'Ecc', 'Eccl' ],
44             [ 'Song of Solomon', 'SS', 'SoS', 'Song of Songs' ],
45             [ 'Isaiah', 'Is', 'Isa' ],
46             [ 'Jeremiah', 'Jr', 'Jer' ],
47             [ 'Lamentations', 'Lm', 'La', 'Lam' ],
48             [ 'Ezekiel', 'Ezk', 'Ez', 'Eze', 'Ezek' ],
49             [ 'Daniel', 'Da', 'Dn', 'Dan' ],
50             [ 'Hosea', 'Ho', 'Hs', 'Hos' ],
51             [ 'Joel', 'Jl', 'Joe', 'Joel' ],
52             [ 'Amos', 'Am', 'Amo' ],
53             [ 'Obadiah', 'Ob', 'Oba' ],
54             [ 'Jonah', 'Jnh', 'Jon', 'Jona' ],
55             [ 'Micah', 'Mi', 'Mic' ],
56             [ 'Nahum', 'Na', 'Nah' ],
57             [ 'Habakkuk', 'Hab' ],
58             [ 'Zephaniah', 'Zp', 'Zep', 'Zph', 'Zeph' ],
59             [ 'Haggai', 'Hg', 'Hag' ],
60             [ 'Zechariah', 'Zec', 'Zch', 'Zech' ],
61             [ 'Malachi', 'Ml', 'Mal' ],
62             [ 'Matthew', 'Mt', 'Mat', 'Matt' ],
63             [ 'Mark', 'Mk', 'Mr', 'Mc', 'Mark' ],
64             [ 'Luke', 'Lk', 'Lu', 'Luk' ],
65             [ 'John', 'Joh' ],
66             [ 'Acts', 'Ac', 'Act' ],
67             [ 'Romans', 'Ro', 'Rm', 'Rom', 'Roms' ],
68             [ '1 Corinthians', '1Co', '1Cor' ],
69             [ '2 Corinthians', '2Co', '2Cor' ],
70             [ 'Galatians', 'Ga', 'Gl', 'Gal' ],
71             [ 'Ephesians', 'Ep', 'Eph' ],
72             [ 'Philippians', 'Php', 'Phil' ],
73             [ 'Colossians', 'Cl', 'Col' ],
74             [ '1 Thessalonians', '1Th', '1The' ],
75             [ '2 Thessalonians', '2Th', '2The' ],
76             [ '1 Timothy', '1Ti', '1Tm', '1Tim' ],
77             [ '2 Timothy', '2Ti', '2Tm', '2Tim' ],
78             [ 'Titus', 'Ti', 'Tt' ],
79             [ 'Philemon', 'Phm', 'Phlm', 'Phile' ],
80             [ 'Hebrews', 'He', 'Heb' ],
81             [ 'James', 'Jam', 'Jms', 'Jas' ],
82             [ '1 Peter', '1Pt', '1Pe', '1Pet' ],
83             [ '2 Peter', '2Pt', '2Pe', '2Pet' ],
84             [ '1 John', '1Jn', '1Jo', '1Joh' ],
85             [ '2 John', '2Jn', '2Jo', '2Joh' ],
86             [ '3 John', '3Jn', '3Jo', '3Joh' ],
87             [ 'Jude', 'Jud', 'Jude' ],
88             [ 'Revelation', 'Rv', 'Rev' ],
89             ],
90             [
91             [
92             31, 25, 24, 26, 32, 22, 24, 22, 29, 32, 32, 20, 18, 24, 21, 16, 27, 33, 38, 18, 34, 24, 20,
93             67, 34, 35, 46, 22, 35, 43, 55, 32, 20, 31, 29, 43, 36, 30, 23, 23, 57, 38, 34, 34, 28, 34,
94             31, 22, 33, 26,
95             ],
96             [
97             22, 25, 22, 31, 23, 30, 25, 32, 35, 29, 10, 51, 22, 31, 27, 36, 16, 27, 25, 26, 36, 31, 33,
98             18, 40, 37, 21, 43, 46, 38, 18, 35, 23, 35, 35, 38, 29, 31, 43, 38,
99             ],
100             [
101             17, 16, 17, 35, 19, 30, 38, 36, 24, 20, 47, 8, 59, 57, 33, 34, 16, 30, 37, 27, 24, 33, 44,
102             23, 55, 46, 34,
103             ],
104             [
105             54, 34, 51, 49, 31, 27, 89, 26, 23, 36, 35, 16, 33, 45, 41, 50, 13, 32, 22, 29, 35, 41, 30,
106             25, 18, 65, 23, 31, 40, 16, 54, 42, 56, 29, 34, 13,
107             ],
108             [
109             46, 37, 29, 49, 33, 25, 26, 20, 29, 22, 32, 32, 18, 29, 23, 22, 20, 22, 21, 20, 23, 30, 25,
110             22, 19, 19, 26, 68, 29, 20, 30, 52, 29, 12,
111             ],
112             [
113             18, 24, 17, 24, 15, 27, 26, 35, 27, 43, 23, 24, 33, 15, 63, 10, 18, 28, 51, 9, 45, 34, 16,
114             33,
115             ],
116             [ 36, 23, 31, 24, 31, 40, 25, 35, 57, 18, 40, 15, 25, 20, 20, 31, 13, 31, 30, 48, 25 ],
117             [ 22, 23, 18, 22 ],
118             [
119             28, 36, 21, 22, 12, 21, 17, 22, 27, 27, 15, 25, 23, 52, 35, 23, 58, 30, 24, 42, 15, 23, 29,
120             22, 44, 25, 12, 25, 11, 31, 13,
121             ],
122             [
123             27, 32, 39, 12, 25, 23, 29, 18, 13, 19, 27, 31, 39, 33, 37, 23, 29, 33, 43, 26, 22, 51, 39,
124             25,
125             ],
126             [ 53, 46, 28, 34, 18, 38, 51, 66, 28, 29, 43, 33, 34, 31, 34, 34, 24, 46, 21, 43, 29, 53 ],
127             [
128             18, 25, 27, 44, 27, 33, 20, 29, 37, 36, 21, 21, 25, 29, 38, 20, 41, 37, 37, 21, 26, 20, 37,
129             20, 30,
130             ],
131             [
132             54, 55, 24, 43, 26, 81, 40, 40, 44, 14, 47, 40, 14, 17, 29, 43, 27, 17, 19, 8, 30, 19, 32,
133             31, 31, 32, 34, 21, 30,
134             ],
135             [
136             17, 18, 17, 22, 14, 42, 22, 18, 31, 19, 23, 16, 22, 15, 19, 14, 19, 34, 11, 37, 20, 12, 21,
137             27, 28, 23, 9, 27, 36, 27, 21, 33, 25, 33, 27, 23,
138             ],
139             [ 11, 70, 13, 24, 17, 22, 28, 36, 15, 44 ],
140             [ 11, 20, 32, 23, 19, 19, 73, 18, 38, 39, 36, 47, 31 ],
141             [ 22, 23, 15, 17, 14, 14, 10, 17, 32, 3 ],
142             [
143             22, 13, 26, 21, 27, 30, 21, 22, 35, 22, 20, 25, 28, 22, 35, 22, 16, 21, 29, 29, 34, 30, 17,
144             25, 6, 14, 23, 28, 25, 31, 40, 22, 33, 37, 16, 33, 24, 41, 30, 24, 34, 17,
145             ],
146             [
147             6, 12, 8, 8, 12, 10, 17, 9, 20, 18, 7, 8, 6, 7, 5, 11, 15, 50, 14, 9, 13, 31, 6,
148             10, 22, 12, 14, 9, 11, 12, 24, 11, 22, 22, 28, 12, 40, 22, 13, 17, 13, 11, 5, 26, 17, 11,
149             9, 14, 20, 23, 19, 9, 6, 7, 23, 13, 11, 11, 17, 12, 8, 12, 11, 10, 13, 20, 7, 35, 36,
150             5, 24, 20, 28, 23, 10, 12, 20, 72, 13, 19, 16, 8, 18, 12, 13, 17, 7, 18, 52, 17, 16, 15,
151             5, 23, 11, 13, 12, 9, 9, 5, 8, 28, 22, 35, 45, 48, 43, 13, 31, 7, 10, 10, 9, 8, 18,
152             19, 2, 29, 176, 7, 8, 9, 4, 8, 5, 6, 5, 6, 8, 8, 3, 18, 3, 3, 21, 26, 9, 8,
153             24, 13, 10, 7, 12, 15, 21, 10, 20, 14, 9, 6,
154             ],
155             [
156             33, 22, 35, 27, 23, 35, 27, 36, 18, 32, 31, 28, 25, 35, 33, 33, 28, 24, 29, 30, 31, 29, 35,
157             34, 28, 28, 27, 28, 27, 33, 31,
158             ],
159             [ 18, 26, 22, 16, 20, 12, 29, 17, 18, 20, 10, 14 ],
160             [ 17, 17, 11, 16, 16, 13, 13, 14 ],
161             [
162             31, 22, 26, 6, 30, 13, 25, 22, 21, 34, 16, 6, 22, 32, 9, 14, 14, 7, 25, 6, 17, 25, 18,
163             23, 12, 21, 13, 29, 24, 33, 9, 20, 24, 17, 10, 22, 38, 22, 8, 31, 29, 25, 28, 28, 25, 13,
164             15, 22, 26, 11, 23, 15, 12, 17, 13, 12, 21, 14, 21, 22, 11, 12, 19, 12, 25, 24,
165             ],
166             [
167             19, 37, 25, 31, 31, 30, 34, 22, 26, 25, 23, 17, 27, 22, 21, 21, 27, 23, 15, 18, 14, 30, 40,
168             10, 38, 24, 22, 17, 32, 24, 40, 44, 26, 22, 19, 32, 21, 28, 18, 16, 18, 22, 13, 30, 5, 28,
169             7, 47, 39, 46, 64, 34,
170             ],
171             [ 22, 22, 66, 22, 22 ],
172             [
173             28, 10, 27, 17, 17, 14, 27, 18, 11, 22, 25, 28, 23, 23, 8, 63, 24, 32, 14, 49, 32, 31, 49,
174             27, 17, 21, 36, 26, 21, 26, 18, 32, 33, 31, 15, 38, 28, 23, 29, 49, 26, 20, 27, 31, 25, 24,
175             23, 35,
176             ],
177             [ 21, 49, 30, 37, 31, 28, 28, 27, 27, 21, 45, 13 ],
178             [ 11, 23, 5, 19, 15, 11, 16, 14, 17, 15, 12, 14, 16, 9 ],
179             [ 20, 32, 21 ],
180             [ 15, 16, 15, 13, 27, 14, 17, 14, 15 ],
181             [ 21 ],
182             [ 17, 10, 10, 11 ],
183             [ 16, 13, 12, 13, 15, 16, 20 ],
184             [ 15, 13, 19 ],
185             [ 17, 20, 19 ],
186             [ 18, 15, 20 ],
187             [ 15, 23 ],
188             [ 21, 13, 10, 14, 11, 15, 14, 23, 17, 12, 17, 14, 9, 21 ],
189             [ 14, 17, 18, 6 ],
190             [
191             25, 23, 17, 25, 48, 34, 29, 34, 38, 42, 30, 50, 58, 36, 39, 28, 27, 35, 30, 34, 46, 46, 39,
192             51, 46, 75, 66, 20,
193             ],
194             [ 45, 28, 35, 41, 43, 56, 37, 38, 50, 52, 33, 44, 37, 72, 47, 20 ],
195             [
196             80, 52, 38, 44, 39, 49, 50, 56, 62, 42, 54, 59, 35, 35, 32, 31, 37, 43, 48, 47, 38, 71, 56,
197             53,
198             ],
199             [ 51, 25, 36, 54, 47, 71, 53, 59, 41, 42, 57, 50, 38, 31, 27, 33, 26, 40, 42, 31, 25 ],
200             [
201             26, 47, 26, 37, 42, 15, 60, 40, 43, 48, 30, 25, 52, 28, 41, 40, 34, 28, 41, 38, 40, 30, 35,
202             27, 27, 32, 44, 31,
203             ],
204             [ 32, 29, 31, 25, 21, 23, 25, 39, 33, 21, 36, 21, 14, 23, 33, 27 ],
205             [ 31, 16, 23, 21, 13, 20, 40, 13, 27, 33, 34, 31, 13, 40, 58, 24 ],
206             [ 24, 17, 18, 18, 21, 18, 16, 24, 15, 18, 33, 21, 14 ],
207             [ 24, 21, 29, 31, 26, 18 ],
208             [ 23, 22, 21, 32, 33, 24 ],
209             [ 30, 30, 21, 23 ],
210             [ 29, 23, 25, 18 ],
211             [ 10, 20, 13, 18, 28 ],
212             [ 12, 17, 18 ],
213             [ 20, 15, 16, 16, 25, 21 ],
214             [ 18, 26, 17, 22 ],
215             [ 16, 15, 15 ],
216             [ 25 ],
217             [ 14, 18, 19, 16, 14, 20, 28, 13, 28, 39, 40, 29, 25 ],
218             [ 27, 26, 18, 17, 20 ],
219             [ 25, 25, 22, 19, 14 ],
220             [ 21, 22, 18 ],
221             [ 10, 29, 24, 21, 21 ],
222             [ 13 ],
223             [ 15 ],
224             [ 25 ],
225             [ 20, 29, 22, 11, 14, 17, 17, 13, 21, 11, 19, 17, 18, 20, 8, 21, 18, 24, 21, 15, 27, 21 ],
226             ],
227             ],
228             };
229              
230 3     3   17 sub _build_bible_template ( $source_name, $new_name, $bibles, $books_cb = undef, $verses_cb = undef ) {
  3         7  
  3         5  
  3         7  
  3         5  
  3         4  
  3         6  
231 3         4 $bibles->{$new_name} = [ map { [ map { [@$_] } @$_ ] } @{ $bibles->{$source_name} } ];
  6         17  
  432         1343  
  3         11  
232 3 100       40 $books_cb->( $bibles->{$new_name}[0] ) if ($books_cb);
233 3 100       23 $verses_cb->( $bibles->{$new_name}[1] ) if ($verses_cb);
234 3         10 return;
235             }
236              
237             _build_bible_template(
238             'ESV' => 'RSVCE',
239             $bibles,
240             sub ($books) {
241             splice( @$books, 25, 0,
242             [ 'Baruch', 'Ba', 'Br', 'Bar' ],
243             );
244              
245             splice( @$books, 22, 0,
246             [ 'Wisdom', 'Wi', 'Ws', 'Wis' ],
247             [ 'Sirach', 'Si', 'Sr', 'Sir' ],
248             );
249              
250             splice( @$books, 17, 0,
251             [ '1 Maccabees', '1Ma', '1Mac' ],
252             [ '2 Maccabees', '2Ma', '2Mac' ],
253             );
254              
255             splice( @$books, 16, 0,
256             [ 'Tobit', 'Tb', 'Tob' ],
257             [ 'Judith', 'Judi' ],
258             );
259             },
260             sub ($verses) {
261             push( @{ $verses->[26] }, 64, 42 );
262             splice( @$verses, 25, 0, [ 21, 35, 37, 37, 9, 73 ] );
263             splice( @$verses, 22, 0,
264             [ 16, 24, 19, 20, 23, 25, 30, 21, 18, 21, 26, 27, 19, 31, 19, 29, 21, 25, 22 ],
265             [
266             30, 18, 31, 31, 15, 37, 36, 19, 18, 31, 34, 18, 26, 27, 20, 30, 32, 33, 30, 31, 28, 27, 27,
267             34, 26, 29, 30, 26, 28, 25, 31, 24, 31, 26, 20, 26, 31, 34, 35, 30, 23, 25, 33, 23, 26, 20,
268             25, 25, 16, 29, 30,
269             ],
270             );
271             splice( @$verses, 16, 1,
272             [ 22, 14, 17, 21, 22, 17, 18, 21, 6, 12, 19, 22, 18, 15 ],
273             [ 16, 28, 10, 15, 24, 21, 32, 36, 14, 23, 23, 20, 20, 19, 13, 25 ],
274             [ 22, 23, 15, 19, 14, 14, 10, 17, 32, 1 ],
275             [ 64, 70, 60, 61, 68, 63, 50, 32, 73, 89, 74, 53, 53, 49, 41, 24 ],
276             [ 36, 32, 40, 50, 27, 31, 42, 36, 29, 38, 38, 45, 26, 46, 39 ],
277             );
278             },
279             );
280              
281             _build_bible_template(
282             'ESV' => 'RSV',
283             $bibles,
284             sub ($books) {
285             push( @$books,
286             [ 'Tobit', 'Tb', 'Tob' ],
287             [ 'Judith', 'Judi', 'Jdt' ],
288             [ 'Greek Esther', 'GkEsth' ],
289             [ 'Wisdom', 'Wi', 'Ws', 'Wis', 'Wisdom of Solomon' ],
290             [ 'Sirach', 'Si', 'Sr', 'Sir', 'Ben Sira', 'Wisdom of Ben Sira' ],
291             [ 'Baruch', 'Ba', 'Br', 'Bar' ],
292             [ 'Letter of Jeremiah', 'LJ', 'Let', 'EpJer' ],
293             [ 'Song of the Three Young Men', 'SgThr', 'Three', 'Prayer of Azariah' ],
294             [ 'Susanna', 'Sus' ],
295             [ 'Bel and the Dragon', 'Bel' ],
296             [ '1 Maccabees', '1Ma', '1Mac', '1Macc' ],
297             [ '2 Maccabees', '2Ma', '2Mac', '2Macc' ],
298             [ '1 Esdras', '1Es', '1Esd', '1Esdr' ],
299             [ 'Prayer of Manasseh', 'PM', 'Pra', 'Man', 'PrMan' ],
300             [ 'Psalm 151', 'Ps151', 'Psa151' ],
301             [ '3 Maccabees', '3Ma', '3Mac', '3Macc' ],
302             [ '2 Esdras', '2Es', '2Esd', '2Esdr' ],
303             [ '4 Maccabees', '4Ma', '4Mac', '4Macc' ],
304             );
305             },
306             sub ($verses) {
307             push( @$verses,
308             [ 22, 14, 17, 21, 21, 17, 18, 21, 6, 12, 19, 22, 18, 15 ],
309             [ 16, 28, 10, 15, 24, 21, 32, 36, 14, 23, 23, 20, 20, 19, 13, 25 ],
310             [ 22, 23, 15, 19, 14, 14, 10, 17, 32, 1 ],
311             [ 16, 24, 19, 20, 23, 25, 30, 21, 18, 21, 26, 27, 19, 31, 19, 29, 21, 25, 22 ],
312             [
313             30, 18, 31, 31, 15, 37, 36, 19, 18, 31, 34, 18, 26, 27, 20, 30, 32, 33, 30, 31, 28, 27, 27,
314             34, 26, 29, 30, 26, 28, 25, 31, 24, 31, 26, 20, 26, 31, 34, 35, 30, 23, 25, 33, 23, 26, 20,
315             25, 25, 16, 29, 30,
316             ],
317             [ 21, 35, 37, 37, 9 ],
318             [ 73 ],
319             [ 68 ],
320             [ 64 ],
321             [ 42 ],
322             [ 64, 70, 60, 61, 68, 63, 50, 32, 73, 89, 74, 53, 53, 49, 41, 24 ],
323             [ 36, 32, 40, 50, 27, 31, 42, 36, 29, 38, 38, 45, 26, 46, 39 ],
324             [ 58, 30, 24, 63, 73, 34, 15, 96, 55 ],
325             [ 15 ],
326             [ 7 ],
327             [ 29, 33, 30, 21, 51, 41, 23 ],
328             [ 40, 48, 36, 52, 56, 59, 140, 63, 47, 59, 46, 51, 58, 48, 63, 78 ],
329             [ 35, 24, 21, 26, 38, 35, 23, 29, 32, 21, 27, 19, 27, 20, 32, 25, 24, 24 ],
330             );
331             },
332             );
333              
334             $bibles->{Protestant} = $bibles->{ESV};
335             $bibles->{Catholic} = $bibles->{RSVCE};
336             $bibles->{Orthodox} = $bibles->{RSV};
337              
338             # has _bibles => $bibles;
339             has _bibles => { map { $_ => [ map { [ map { [ @$_] } @$_ ] } @{ $bibles->{$_} } ] } keys %$bibles };
340             has _bible => 'Protestant';
341             has _bible_data => {};
342             has _data => [];
343             has _cache => {};
344              
345 22     22 1 27018 sub bible ( $self, $name = undef ) {
  22         53  
  22         57  
  22         63  
346 22 100       97 return $self->_bible unless ($name);
347              
348 18   50     101 my $input = lc( $name || '' );
349 18         49 my ($bible) = grep { lc $_ eq $input } keys %{ $self->_bibles };
  118         493  
  18         69  
350              
351 18 100       303 croak "Could not determine a valid Bible type from input" unless ($bible);
352 17         80 $self->_bible($bible);
353              
354 17         160 my $books = [ map { [@$_] } @{ $self->_bibles->{ $self->_bible }[0] } ];
  1186         3042  
  17         50  
355              
356 17         80 my $bible_data;
357 17         57 for my $book_data (@$books) {
358 1186         2197 my ( $book, @acronyms ) = @$book_data;
359              
360 1186         5520 $bible_data->{book_to_acronym}{$book} = $acronyms[0];
361 1186         1463 push( @{ $bible_data->{books} }, $book );
  1186         2930  
362             }
363 17         48 my $book_count;
364 17         39 $bible_data->{book_order} = { map { $_ => ++$book_count } @{ $bible_data->{books} } };
  1186         2503  
  17         56  
365              
366 17         129 my $canonical = [ map { $_->[0] } @$books ];
  1186         1901  
367 17         93 my $options = { map { shift @$_ => $_ } @$books };
  1186         2335  
368             my $re_map = { map {
369 17         151 my $book = $_;
  1186         1786  
370 1186         1644 my $book_str = $_;
371 1186 50       4321 my @prefix = (
    100          
    100          
    100          
    100          
372             ( $book_str =~ s/^(\d)\s// ) ? (
373             (
374             (
375             ( $1 == 1 ) ? ( qw( I First ) ) :
376             ( $1 == 2 ) ? ( qw( II Second ) ) :
377             ( $1 == 3 ) ? ( qw( III Third ) ) :
378             ( $1 == 4 ) ? ( qw( IV Fourth ) ) : ()
379             ),
380             $1 . '*',
381             ),
382             $1,
383             ) : ()
384             );
385              
386 1186         4178 my @letters = split( '', $book_str );
387 1186         1715 my $unique;
388 1186         2528 while (@letters) {
389 3742         25751 $unique .= shift @letters;
390             last if (
391             length $unique >= $self->minimum_book_length
392             and (
393             not @prefix and
394             scalar( grep { index( $_, $unique ) == 0 } @$canonical ) == 1 or
395             @prefix and
396 3742 100 100     8213 scalar( grep { index( $_, $prefix[-1] . ' ' . $unique ) == 0 } @$canonical ) == 1
      100        
397             )
398             );
399             }
400              
401 1186         2760 my @matches = $unique;
402 1186         6399 push( @matches, $unique .= shift @letters ) while (@letters);
403              
404             @matches = map {
405 1186         1972 my $match = $_;
  6053         9076  
406              
407 6053         8854 $match .= ')i?(';
408 6053         21827 $match =~ s/^(\w)/$1)i-?(/;
409              
410 6053 100       16836 (@prefix) ? ( map { ')' . $_ . ':i?(' . ' ' . $match } @prefix ) : $match;
  6704         15709  
411             } @matches;
412              
413             map {
414 14048         23476 my $re = reverse $_;
415              
416 14048         21828 $re =~ s/\*/'[A-z]+'/ge;
  1676         4263  
417 14048         28573 $re =~ s/\s+/'[\s_]*'/ge;
  7842         20615  
418              
419 14048         43321 $re => $book;
420 1186         2075 } @matches, @{ $options->{$book} };
  1186         2737  
421             } @$canonical };
422              
423 17         4693 my @re_parts = sort { length $b <=> length $a } keys %$re_map;
  113410         143307  
424              
425 17         757 my $re_refs = '(?i:[\d:,;\s\-]|\bdna\b|\bro\b|&)*\.?';
426 17         81 my $re_refs_req =
427             '(?i:[\d:,;\s\-]|\bdna\b|\bro\b|&)*' .
428             '(?:\d\s*:\s*\d)' .
429             '(?i:[\d:,;\s\-]|\bdna\b|\bro\b|&)*\.?';
430              
431 17         84 my $re_refs_string = '\b(' . join( '|', map { $re_refs . $_ } @re_parts ) . ')\b';
  14048         28129  
432 17         946 my $re_refs_req_string = '\b(' . join( '|', map { $re_refs_req . $_ } @re_parts ) . ')\b';
  14048         31230  
433              
434 17         677329 $bible_data->{re_refs_s} = qr/$re_refs_string/;
435 17         1967936 $bible_data->{re_refs_sr} = qr/$re_refs_req_string/;
436 17         7908 $bible_data->{re_books_s} = [ map { [ qr/\b$_\b/, $re_map->{$_} ] } @re_parts ];
  14048         197427  
437              
438 17         13348 $re_refs_string =~ s/\(\?\-?i\)//g;
439 17         13438 $re_refs_req_string =~ s/\(\?\-?i\)//g;
440              
441 17         588456 $bible_data->{re_refs_i} = qr/$re_refs_string/i;
442 17         1809882 $bible_data->{re_refs_ir} = qr/$re_refs_req_string/i;
443             $bible_data->{re_books_i} = [ map {
444 17         6778 my $this_book = $re_map->{$_};
  14048         38021  
445 14048         49401 s/\(\?\-?i\)//g;
446 14048         191159 [ qr/\b$_\b/i, $this_book ];
447             } @re_parts ];
448              
449             $bible_data->{lengths} = {
450             map {
451 1186         13695 $bible_data->{books}[$_] => [ @{ $self->_bibles->{$bible}[1][$_] } ]
  1186         2184  
452 17         482 } 0 .. @{ $bible_data->{books} } - 1
  17         125  
453             };
454              
455 17         1120 $self->_bible_data($bible_data);
456 17         112005 return $bible;
457             }
458              
459 2     2 1 139 sub new ( $self, %params ) {
  2         6  
  2         6  
  2         4  
460 2         21 $self = $self->SUPER::new(%params);
461 2   33     1788 $self->bible( $params{bible} || $self->_bible );
462 2         19 return $self;
463             }
464              
465 213     213   393 sub _list ( $start, $stop ) {
  213         315  
  213         306  
  213         302  
466 213 50       515 $start++ if ( $start == 0 );
467 213 50       433 $stop++ if ( $stop == 0 );
468              
469 213         777 my ( $x, $y ) = sort { $a <=> $b } $start, $stop;
  426         610  
470 213         680 my @list = $x .. $y;
471 213 100       466 @list = reverse(@list) if ( $x < $start );
472              
473 213         1477 return @list;
474             };
475              
476 185     185 1 315 sub expand_ranges ( $self, $book, $text, $compress = 0 ) {
  185         368  
  185         282  
  185         498  
  185         299  
  185         274  
477 189     189   266 my $expand = sub ( $start, $stop ) {
  189         282  
  189         422  
  189         346  
478 189 100       680 my $start_ch = ( $start =~ s/(\d+):// ) ? $1 : 0;
479 189 100       514 my $stop_ch = ( $stop =~ s/(\d+):// ) ? $1 : 0;
480              
481 189 100 100     797 if ( not $start_ch and $stop_ch and $start > $stop_ch ) {
      100        
482             # A: "5-3:4" = translated to "5:1-3:4"
483              
484 1         116 $start_ch = $start;
485 1         4 $start = 1;
486             }
487              
488 189         300 my $skip_chapter_assumption_check = 0;
489 189 100 100     670 if ( $start_ch and $stop_ch and $start and $stop and $start_ch == $stop_ch ) {
      66        
      66        
      66        
490 2 100       8 if ( $start <= $stop ) {
491             # B: "3:4-3:7" = translated to "3:4-7"
492              
493 1         2 $stop_ch = 0;
494             }
495             else {
496             # Q: "3:37-3:4" is the reverse of 3:4-3:37
497              
498 1         2 $stop_ch = 0;
499 1         2 $skip_chapter_assumption_check = 1;
500             }
501             }
502              
503 189         328 my $expance = '';
504              
505 189 100 100     872 if ( not $start_ch and not $stop_ch ) {
    100 100        
    100 66        
    50 33        
506             # C: "3-3" = consider as "3"
507             # D: "3-5" = consider as a simple range
508             # E: "5-3" = consider as a simple reversed range
509              
510 101         253 $expance = join( ',', _list( $start, $stop ) );
511             }
512              
513             elsif ( $start_ch and not $stop_ch ) {
514             # F: "1:3-15" = consider 3-15 as verses
515             # G: "1:15-3" = consider 3 a chapter
516             # H: "1:3-3" = consider the second 3 a chapter
517             # I: "3:2-3" = consider 2-3 as verses
518             # J: "3:3-2" = consider 3-2 as verses
519              
520 71 100 100     247 if ( $start >= $stop and $stop > $start_ch and not $skip_chapter_assumption_check ) {
      100        
521 4         8 $stop_ch = $stop;
522 4         15 $stop = $self->_bible_data->{lengths}{$book}[ $start_ch - 1 ];
523             }
524              
525 71 100       315 $expance = join( ';', grep { defined }
  142         420  
526             $start_ch . ':' . join( ',', _list( $start, $stop ) ),
527             ( ($stop_ch) ? join( ';', _list( $start_ch + 1, $stop_ch ) ) : undef ),
528             );
529             }
530              
531             elsif ( not $start_ch and $stop_ch ) {
532             # K: "3-5:2" = 3-4 are full chapters; plus 5:1-5:2
533             # L: "3-3:2" = interpretted as "3:1-2"
534              
535 10         36 $start_ch = $start;
536 10         23 $start = 1;
537              
538 10         41 $expance = join( ':',
539             join( ';', _list( $start_ch, $stop_ch ) ),
540             join( ',', _list( $start, $stop ) ),
541             );
542             }
543              
544             elsif ( $start_ch and $stop_ch ) {
545             # M: "3:4-4:7" becomes "3:4-*;4:1-7"
546             # N: "4:7-3:4" becomes reverse of "3:4-*;4:1-7"
547             # O: "3:4-5:2" becomes "3:4-*;4;5:1-2"
548             # P: "5:2-3:4" becomes reverse of "3:4-*;4;5:2-*"
549              
550 7         14 my $reversed = 0;
551 7 100       17 if ( $start_ch >= $stop_ch ) {
552 3         10 ( $start_ch, $stop_ch, $start, $stop ) = ( $stop_ch, $start_ch, $stop, $start );
553 3         7 $reversed = 1;
554             }
555              
556 7 100       25 my $reverse = sub { ($reversed) ? reverse(@_) : @_ };
  24         905  
557              
558 21         175 $expance = join( ';', grep { defined }
559             $reverse->(
560             $start_ch . ':' . join( ',', $reverse->( _list(
561             $start,
562 7 100       32 $self->_bible_data->{lengths}{$book}[ $start_ch - 1 ],
563             ) ) ),
564             (
565             ( $stop_ch - $start_ch > 1 )
566             ? join( ',', $reverse->( _list( $start_ch + 1, $stop_ch - 1 ) ) )
567             : undef
568             ),
569             $stop_ch . ':' . join( ',', $reverse->( _list( 1, $stop ) ) ),
570             ),
571             );
572             }
573              
574 189         957 $expance;
575 185         1931 };
576              
577 185         871 $text =~ s/[\s,]+/,/g;
578 185         651 $text =~ s/^,//g;
579 185         971 $text =~ s/(\d+(?::\d+)?)\-(\d+(?::\d+)?)/ $expand->( $1, $2 ) /ge;
  189         481  
580 185 50       506 $text =~ s/([,;])/$1 /g unless $compress;
581              
582 185         2595 return $text;
583             };
584              
585 25     25 1 11470 sub in ( $self, @input ) {
  25         51  
  25         128  
  25         48  
586 25 50       109 return $self unless (@input);
587              
588             my $re_refs = $self->_bible_data->{
589 25 100       102 're_refs_' .
    100          
590             ( ( $self->require_book_ucfirst ) ? 's' : 'i' ) .
591             ( ( $self->require_verse_match ) ? 'r' : '' )
592             };
593              
594             my $re_books = ( $self->require_book_ucfirst )
595             ? $self->_bible_data->{re_books_s}
596 25 100       893 : $self->_bible_data->{re_books_i};
597              
598 25         489 for my $string (@input) {
599 176   100     800 $string = scalar( reverse $string // '' );
600 176         279 my @processed;
601 176         270 while (1) {
602 517         665704 my ( $pre, $ref, $post ) = split( /$re_refs/, $string, 2 );
603 517 100       1872 last unless ($ref);
604              
605 341         1024 $ref =~ s/(\d)([[:alpha:]])/$1 $2/;
606              
607 341         649 $string = $post;
608              
609 341 100       1508 my $space = ( $ref =~ s/^((?i:\W|\bdna\b|\bro\b|&)+)// ) ? $1 : '';
610 341         1198 $ref =~ s/\s+/ /g;
611 341         820 $pre = $pre . $space;
612 341         732 push( @processed, $pre );
613              
614 341         583 my $orig_ref = $ref;
615              
616 341         465 my $book;
617 341         781 for (@$re_books) {
618 156259 100       455105 if ( $ref =~ /$_->[0]/ ) {
619 341         1019 $book = $_->[1];
620 341         666 last;
621             }
622             }
623              
624 341         804 my $ref_out = [$book];
625 341         595 my $numbers = [];
626              
627 341         1653 $ref =~ s/(?:\bdna\b|\bro\b|&)/,/g;
628 341         891 $ref = scalar reverse $ref;
629              
630 341 100       1227 if ( $ref =~ /([\d:,;\s\-]+)$/ ) {
631 164         653 my $range = $self->expand_ranges( $book, $1, 1 );
632              
633 164         305 my $verse_context = 0;
634 164         276 my $last_d = 0;
635              
636 164         987 while ( $range =~ s/^(\d+)([:,;]?)\D*//g ) {
637 1418   100     4839 my ( $d, $s ) = ( $1, $2 || '' );
638              
639 1418 100 100     4461 $verse_context = 0 if ( $s eq ':' or $d <= $last_d );
640              
641 1418 100       2285 unless ($verse_context) {
642 683         1850 push( @$numbers, [$d] );
643             }
644             else {
645 735 100       968 push( @{ $numbers->[-1] }, [] ) unless ( @{ $numbers->[-1] } > 1 );
  136         292  
  735         1572  
646 735         1044 push( @{ $numbers->[-1][-1] }, $d );
  735         1616  
647             }
648              
649 1418 100       2449 $last_d = ($verse_context) ? $d : 0;
650              
651 1418 100       2440 $verse_context = 1 if ( $s eq ':' );
652 1418 100       6216 $verse_context = 0 if ( $s eq ';' );
653             }
654             }
655              
656 341 100 100     1511 if ( @$numbers or not $self->require_chapter_match ) {
657 340 100       2804 push( @$ref_out, $numbers ) if (@$numbers);
658 340         901 push( @processed, $ref_out );
659             }
660             else {
661 1         19 $processed[-1] .= $orig_ref;
662             }
663             }
664              
665 176         436 push( @processed, $string );
666             push(
667 176         614 @{ $self->_data },
668 176 100       258 [ grep { length } map { ( ref $_ ) ? $_ : scalar reverse $_ } reverse @processed ],
  857         2352  
  857         4011  
669             );
670             }
671              
672 25         195 return $self;
673             }
674              
675 24     24 1 103471 sub clear ($self) {
  24         574  
  24         49  
676 24         169 $self->_data([]);
677 24         1402 return $self;
678             }
679              
680 4     4 1 668 sub books ($self) {
  4         12  
  4         10  
681 4 50       16 return (wantarray) ? @{ $self->_bible_data->{books} } : $self->_bible_data->{books};
  4         19  
682             }
683              
684 59     59 1 144367 sub as_array ( $self, $data = undef ) {
  59         103  
  59         96  
  59         103  
685 59 50 100     264 if (
      0        
      66        
686             $data or
687             not $self->_cache->{data} or
688             not (
689             $self->_cache->{sorting} and $self->_cache->{sorting} == $self->sorting and
690             $self->_cache->{acronyms} and $self->_cache->{acronyms} == $self->acronyms
691             )
692             ) {
693 59   100     741 $data //= [ map { grep { ref } @$_ } @{ $self->_data } ];
  203         582  
  947         1837  
  19         59  
694             $data = [
695 59         153 map { [
696             map {
697 450         816 ( ref $_ ) ? [
698             map {
699 664 100       1652 ( ref $_ ) ? [
700             map {
701 921 100       1853 ( ref $_ ) ? [
  1095 50       4301  
702             @$_
703             ] : $_
704             } @$_
705             ] : $_
706             } @$_
707             ] : $_
708             } @$_
709             ] }
710             @$data
711             ];
712              
713             $data = [ map {
714 59 100       239 my $book = $_->[0];
  43         121  
715              
716 43 100       90 if ( ref $_->[1] ) {
717             $_->[1] = [ map {
718 100   100     290 $_->[1] //= [ 1 .. ( $self->_bible_data->{lengths}{$book}[ $_->[0] - 1 ] || 0 ) ];
      100        
719 100         1408 $_;
720 23         35 } @{ $_->[1] } ];
  23         46  
721             }
722             else {
723 20         25 my $chapter;
724 20         26 $_->[1] = [ map { [ ++$chapter, [ 1 .. $_ ] ] } @{ $self->_bible_data->{lengths}{$book} } ];
  209         1717  
  20         45  
725             }
726              
727 43         93 $_;
728             } @$data ] if ( $self->add_detail );
729              
730 59 100       690 if ( $self->sorting ) {
731 58         579 my $data_by_book = {};
732 58 100       138 push( @{ $data_by_book->{ $_->[0] } }, @{ $_->[1] || [] } ) for (@$data);
  411         918  
  411         1374  
733              
734             $data = [
735             map {
736 258         977 my $book = [ $_->[1] ];
737              
738 258         382 my $dedup;
739 258         387 for my $chapter ( @{ $data_by_book->{ $_->[1] } } ) {
  258         531  
740 1048   100     4226 $dedup->{ $chapter->[0] } //= {};
741 1048         1328 $dedup->{ $chapter->[0] }{$_} = 1 for ( @{ $chapter->[1] } );
  1048         8755  
742             }
743              
744             my $chapters = [
745             map {
746 927         1961 my $chapter = [$_];
747 927         1187 my @verses = keys %{ $dedup->{$_} };
  927         2867  
748 927 100       2062 push( @$chapter, [ sort { $a <=> $b } @verses ] ) if @verses;
  26330         34186  
749 927         1966 $chapter;
750             }
751 258         877 sort { $a <=> $b }
  2497         3239  
752             keys %$dedup
753             ];
754              
755 258 100       633 push( @$book, $chapters ) if (@$chapters);
756              
757 258         2542 $book;
758             }
759 647         1111 sort { $a->[0] <=> $b->[0] }
760 58         263 map { [ $self->_bible_data->{book_order}{$_}, $_ ] }
  258         2289  
761             keys %$data_by_book
762             ];
763             }
764              
765 59 100       338 if ( $self->acronyms ) {
766 1         18 for (@$data) {
767 22         221 $_->[0] = $self->_bible_data->{book_to_acronym}{ $_->[0] };
768             }
769             }
770              
771             $data = [ map {
772 59 100       732 my $book = $_->[0];
  4         30  
773              
774 4 50       11 if ( my $chapters = $_->[1] ) {
775 4         9 for my $chapter (@$chapters) {
776             pop @$chapter if (
777             $chapter->[1] and
778 18         82 join( ',', @{ $chapter->[1] } ) eq
779 18 50 50     283 join( ',', 1 .. ( $self->_bible_data->{lengths}{$book}[ $chapter->[0] - 1 ] || 0 ) )
      33        
780             );
781             }
782              
783             pop @$_ if (
784 18         34 join( ',', map { $_->[0] } grep { @$_ == 1 } @$chapters ) eq
  18         38  
785 4 100       73 join( ',', 1 .. scalar @{ $self->_bible_data->{lengths}{$book} } )
  4         11  
786             );
787             }
788              
789 4         60 $_;
790             } @$data ] if ( $self->simplify );
791              
792 59         600 $self->_cache->{data} = $data;
793             }
794              
795 59 100       2125 return (wantarray) ? @{ $self->_cache->{data} } : $self->_cache->{data};
  1         7  
796             }
797              
798 1     1 1 27 sub as_hash ( $self, $data = undef ) {
  1         2  
  1         4  
  1         3  
799 1         2 my $build = {};
800              
801 1         7 for my $book_block ( $self->as_array($data) ) {
802 22         52 my ( $book_name, $chapters ) = @$book_block;
803              
804 22         41 $build->{$book_name} = {};
805 22         41 for (@$chapters) {
806 77 100       108 push( @{ $build->{$book_name}{ $_->[0] } }, @{ $_->[1] || [] } );
  77         148  
  77         237  
807             }
808             }
809              
810 1 50       8 return (wantarray) ? %$build : $build;
811             }
812              
813 86     86   119 sub _compress_range ( $items = [] ) {
  86         144  
  86         104  
814 86         135 my ( $last, @items, @range );
815              
816             my $flush_range = sub {
817 198 100   198   358 if (@range) {
818 74         104 pop @items;
819 74         174 push( @items, join( '-', $range[0], $range[-1] ) );
820 74         151 @range = ();
821             }
822 86         260 };
823              
824 86         182 for my $item (@$items) {
825 502 100 100     1248 if ( not $last or $last + 1 != $item ) {
826 112         217 $flush_range->();
827 112         187 push( @items, $item );
828             }
829             else {
830 390         590 push( @range, $last, $item );
831             }
832              
833 502         720 $last = $item;
834             }
835 86         177 $flush_range->();
836              
837 86 50       438 return (wantarray) ? @items : join( ', ', @items );
838             }
839              
840 54     54   92 sub _as_type ( $self, $type, $data = undef ) {
  54         111  
  54         105  
  54         82  
  54         80  
841 54         151 $data = $self->as_array($data);
842              
843             return [
844             map {
845 54         530 my $book = $_->[0];
  170         315  
846              
847 170 100       318 if ( $_->[1] ) {
848 72         116 my ( @build, @buffer );
849              
850             my $flush_buffer = sub {
851 79 100   79   170 if (@buffer) {
852 27         66 push( @build, join( '; ', _compress_range(\@buffer) ) );
853 27         72 @buffer = ();
854             }
855 72         259 };
856              
857 72         107 for ( @{ $_->[1] } ) {
  72         198  
858 476         727 my $chapter = $_->[0];
859              
860 476 100       710 if ( $_->[1] ) {
861 70 100       200 if ( $type eq 'verses' ) {
    100          
    100          
862 11         15 push( @build, map { "$book $chapter:$_" } @{ $_->[1] } );
  58         129  
  11         21  
863             }
864             elsif ( $type eq 'runs' ) {
865 11         25 push( @build, map { "$book $chapter:$_" } _compress_range( $_->[1] ) );
  14         53  
866             }
867             elsif ( $type eq 'chapters' ) {
868 11         30 push( @build, "$book $chapter:" . join( ', ', _compress_range( $_->[1] ) ) );
869             }
870             else {
871 37         84 $flush_buffer->();
872 37         98 push( @build, $chapter . ':' . join( ', ', _compress_range( $_->[1] ) ) );
873             }
874             }
875             else {
876 406 100       647 unless ( $type eq 'books' ) {
877 198         395 push( @build, "$book $chapter" );
878             }
879             else {
880 208         334 push( @buffer, $chapter );
881             }
882             }
883             }
884              
885 72 100       166 unless ( $type eq 'books' ) {
886 30         273 @build;
887             }
888             else {
889 42         94 $flush_buffer->();
890 42         225 $book . ' ' . join( '; ', @build );
891             }
892             }
893             else {
894 98         230 $book;
895             }
896             } @$data
897             ];
898             }
899              
900 1     1 1 29 sub as_verses ( $self, $data = undef ) {
  1         3  
  1         4  
  1         2  
901 1         8 my $items = $self->_as_type( 'verses', $data );
902 1 50       72 return (wantarray) ? @$items : $items;
903             }
904              
905 1     1 1 43 sub as_runs ( $self, $data = undef ) {
  1         3  
  1         3  
  1         3  
906 1         6 my $items = $self->_as_type( 'runs', $data );
907 1 50       7 return (wantarray) ? @$items : $items;
908             }
909              
910 1     1 1 28 sub as_chapters ( $self, $data = undef ) {
  1         3  
  1         3  
  1         2  
911 1         7 my $items = $self->_as_type( 'chapters', $data );
912 1 50       7 return (wantarray) ? @$items : $items;
913             }
914              
915 51     51 1 102 sub as_books ( $self, $data = undef ) {
  51         82  
  51         82  
  51         87  
916 51         121 my $items = $self->_as_type( 'books', $data );
917 51 100       270 return (wantarray) ? @$items : $items;
918             }
919              
920 43     43 1 87 sub refs ( $self, $data = undef ) {
  43         64  
  43         68  
  43         68  
921 43         92 return join( '; ', $self->as_books($data) );
922             }
923              
924 2     2 1 30 sub as_text ($self) {
  2         4  
  2         5  
925             my @text = map {
926 19 100       69 join( '', map { ( ref $_ ) ? $self->refs([$_]) : $_ } @$_ );
  96         304  
927 2         5 } @{ $self->_data };
  2         9  
928              
929             return
930 2 100 66     31 ( @text > 1 and wantarray ) ? @text :
    50 66        
931             ( @text > 1 and not wantarray ) ? \@text : join( ' ', @text );
932             }
933              
934 4     4 1 2240 sub set_bible_data ( $self, $bible = undef, $book_data = undef, $verse_data = undef ) {
  4         8  
  4         7  
  4         8  
  4         5  
  4         8  
935 4 50 66     220 croak 'First argument to set_bible_data() must be a Bible name string'
      66        
936             unless ( $bible and not ref $bible and length $bible > 0 );
937 3 100 66     103 croak 'Second argument to set_bible_data() must be an arrayref of arrayrefs'
938             unless ( $book_data and ref $book_data eq 'ARRAY' );
939              
940 2         5 for (@$book_data) {
941 41 50 66     320 croak 'Second argument to set_bible_data() does not appear valid' unless (
      66        
      66        
      33        
942             ref $_ eq 'ARRAY' and
943             not ref $_->[0] and length $_->[0] > 0 and
944             not ref $_->[1] and length $_->[1] > 0
945             );
946             }
947              
948 1 50       5 unless ($verse_data) {
949 1         6 _build_bible_template( 'Orthodox' => $bible, $self->_bibles );
950 1         6 $self->_bibles->{$bible}[0] = $book_data;
951             }
952             else {
953 0         0 $self->_bibles->{$bible}[0] = $book_data;
954 0         0 $self->_bibles->{$bible}[1] = $verse_data;
955             }
956              
957 1         48 $self->bible($bible);
958 1         7 return $self;
959             }
960              
961 1     1 1 2051 sub get_bible_structure ( $self, $bible = undef ) {
  1         3  
  1         3  
  1         3  
962 1 50       7 $self->bible($bible) if ($bible);
963 1         5 return [ map { [ $_, $self->_bible_data->{lengths}{$_} ] } @{ $self->_bible_data->{books} } ];
  84         743  
  1         6  
964             }
965              
966 2     2 1 2764 sub identify_bible ( $self, @books ) {
  2         4  
  2         7  
  2         4  
967 2 100       195 croak('No books supplied; must supply at least 1 input') unless (@books);
968              
969 1         6 my $obj = $self->new( minimum_book_length => $self->minimum_book_length );
970             my $bibles = [
971 13         25 sort { $b->{count} <=> $a->{count} }
972             map {
973 7         49 $obj->bible($_);
974 7         65 my $books = scalar( $obj->clear->in(@books)->as_books );
975             {
976 7         67 name => $_,
977             books => $books,
978             count => scalar(@$books),
979             };
980             }
981 1         4 keys %{ $obj->_bibles }
  1         7  
982             ];
983              
984 7         23 $bibles = [ grep { $bibles->[0]{count} == $_->{count} } @$bibles ]
985 1 50       8 if ( $bibles->[0]{count} != $bibles->[-1]{count} );
986              
987 1         2847 return $bibles;
988             }
989              
990             1;
991              
992             __END__