CalebKoster/Translation_Note_Alignment
0
1import re2from functools import cache3 4class ScriptureReference:5 verse_ones = [6 1, 1534, 2747, 3606, 4895, 5854, 6512, 7130, 7215, 8026, 8721, 9538, 10257, 11200, 12022, 12302, 12707, 12874, 13944,7 16471, 17386, 17608, 17725, 19016, 20380, 20534, 21807, 22164, 22361, 22434, 22580, 22601, 22649, 22754, 22801, 22857, 8 22910, 22948, 23159, 23214, 24285, 24963, 26114, 26993, 27999, 28432, 28869, 29125, 29274, 29429, 29533, 29628, 29717, 9 29764, 29877, 29960, 30006, 30031, 30334, 30442, 30547, 30608, 30713, 30726, 30741, 30766, 3117110 ]11 12 book_codes = {13 'GEN': {14 'codes': ['Gen', 'Gn', '1M'],15 'verses': [31, 25, 24, 26, 32, 22, 24, 22, 29, 32, 32, 20, 18, 24, 21, 16, 27, 33, 38, 18, 34, 24, 20, 67, 34, 16 35, 46, 22, 35, 43, 55, 32, 20, 31, 29, 43, 36, 30, 23, 23, 57, 38, 34, 34, 28, 34, 31, 22, 33, 26]17 },18 'EXO': {19 'codes': ['Ex', '2M'],20 'verses': [22, 25, 22, 31, 23, 30, 25, 32, 35, 29, 10, 51, 22, 31, 27, 36, 16, 27, 25, 26, 36, 31, 33, 18, 40, 21 37, 21, 43, 46, 38, 18, 35, 23, 35, 35, 38, 29, 31, 43, 38]22 },23 'LEV': {24 'codes': ['Lev', 'Lv', '3M'],25 'verses': [17, 16, 17, 35, 19, 30, 38, 36, 24, 20, 47, 8, 59, 57, 33, 34, 16, 30, 37, 27, 24, 33, 44, 23, 55, 26 46, 34]27 },28 'NUM': {29 'codes': ['Nm', 'Nu', '4M'],30 'verses': [54, 34, 51, 49, 31, 27, 89, 26, 23, 36, 35, 16, 33, 45, 41, 50, 13, 32, 22, 29, 35, 41, 30, 25, 18, 31 65, 23, 31, 40, 16, 54, 42, 56, 29, 34, 13]32 },33 'DEU': {34 'codes': ['Deut', 'Dt', '5M'],35 'verses': [46, 37, 29, 49, 33, 25, 26, 20, 29, 22, 32, 32, 18, 29, 23, 22, 20, 22, 21, 20, 23, 30, 25, 22, 19, 36 19, 26, 68, 29, 20, 30, 52, 29, 12]37 },38 'JOS': {39 'codes': ['Josh', 'Jos'],40 'verses': [18, 24, 17, 24, 15, 27, 26, 35, 27, 43, 23, 24, 33, 15, 63, 10, 18, 28, 51, 9, 45, 34, 16, 33]41 },42 'JDG': {43 'codes': ['Jdg', 'Judg'],44 'verses': [36, 23, 31, 24, 31, 40, 25, 35, 57, 18, 40, 15, 25, 20, 20, 31, 13, 31, 30, 48, 25]45 },46 'RUT': {47 'codes': ['Ru', 'Rth'],48 'verses': [22, 23, 18, 22]49 },50 '1SA': {51 'codes': ['1Sam', '1Sm'],52 'verses': [28, 36, 21, 22, 12, 21, 17, 22, 27, 27, 15, 25, 23, 52, 35, 23, 58, 30, 24, 42, 15, 23, 29, 22, 44, 53 25, 12, 25, 11, 31, 13]54 },55 '2SA': {56 'codes': ['2Sam', '2Sm'],57 'verses': [27, 32, 39, 12, 25, 23, 29, 18, 13, 19, 27, 31, 39, 33, 37, 23, 29, 33, 43, 26, 22, 51, 39, 25]58 },59 '1KI': {60 'codes': ['1Kg', '1K'],61 'verses': [53, 46, 28, 34, 18, 38, 51, 66, 28, 29, 43, 33, 34, 31, 34, 34, 24, 46, 21, 43, 29, 53]62 },63 '2KI': {64 'codes': ['2Kg', '2K'],65 'verses': [18, 25, 27, 44, 27, 33, 20, 29, 37, 36, 21, 21, 25, 29, 38, 20, 41, 37, 37, 21, 26, 20, 37, 20, 30]66 },67 '1CH': {68 'codes': ['1Ch'],69 'verses': [54, 55, 24, 43, 26, 81, 40, 40, 44, 14, 47, 40, 14, 17, 29, 43, 27, 17, 19, 8, 30, 19, 32, 31, 31, 70 32, 34, 21, 30]71 },72 '2CH': {73 'codes': ['2Ch'],74 'verses': [17, 18, 17, 22, 14, 42, 22, 18, 31, 19, 23, 16, 22, 15, 19, 14, 19, 34, 11, 37, 20, 12, 21, 27, 28, 75 23, 9, 27, 36, 27, 21, 33, 25, 33, 27, 23]76 },77 'EZR': {78 'codes': ['Ezr'],79 'verses': [11, 70, 13, 24, 17, 22, 28, 36, 15, 44]80 },81 'NEH': {82 'codes': ['Neh'],83 'verses': [11, 20, 32, 23, 19, 19, 73, 18, 38, 39, 36, 47, 31]84 },85 'EST': {86 'codes': ['Est'],87 'verses': [22, 23, 15, 17, 14, 14, 10, 17, 32, 3]88 },89 'JOB': {90 'codes': ['Jb', 'Job'],91 'verses': [22, 13, 26, 21, 27, 30, 21, 22, 35, 22, 20, 25, 28, 22, 35, 22, 16, 21, 29, 29, 34, 30, 17, 25, 6, 92 14, 23, 28, 25, 31, 40, 22, 33, 37, 16, 33, 24, 41, 30, 24, 34, 17]93 },94 'PSA': {95 'codes': ['Ps'],96 'verses': [6, 12, 8, 8, 12, 10, 17, 9, 20, 18, 7, 8, 6, 7, 5, 11, 15, 50, 14, 9, 13, 31, 6, 10, 22, 12, 14, 9, 97 11, 12, 24, 11, 22, 22, 28, 12, 40, 22, 13, 17, 13, 11, 5, 26, 17, 11, 9, 14, 20, 23, 19, 9, 6, 7, 98 23, 13, 11, 11, 17, 12, 8, 12, 11, 10, 13, 20, 7, 35, 36, 5, 24, 20, 28, 23, 10, 12, 20, 72, 13, 19, 99 16, 8, 18, 12, 13, 17, 7, 18, 52, 17, 16, 15, 5, 23, 11, 13, 12, 9, 9, 5, 8, 28, 22, 35, 45, 48, 43, 100 13, 31, 7, 10, 10, 9, 8, 18, 19, 2, 29, 176, 7, 8, 9, 4, 8, 5, 6, 5, 6, 8, 8, 3, 18, 3, 3, 21, 26, 101 9, 8, 24, 13, 10, 7, 12, 15, 21, 10, 20, 14, 9, 6]102 },103 'PRO': {104 'codes': ['Pr'],105 'verses': [33, 22, 35, 27, 23, 35, 27, 36, 18, 32, 31, 28, 25, 35, 33, 33, 28, 24, 29, 30, 31, 29, 35, 34, 28, 106 28, 27, 28, 27, 33, 31]107 },108 'ECC': {109 'codes': ['Ec', 'Qoh'],110 'verses': [18, 26, 22, 16, 20, 12, 29, 17, 18, 20, 10, 14]111 },112 'SNG': {113 'codes': ['Sos', 'Song'],114 'verses': [17, 17, 11, 16, 16, 13, 13, 14]115 },116 'ISA': {117 'codes': ['Isa'],118 'verses': [31, 22, 26, 6, 30, 13, 25, 22, 21, 34, 16, 6, 22, 32, 9, 14, 14, 7, 25, 6, 17, 25, 18, 23, 12, 21, 119 13, 29, 24, 33, 9, 20, 24, 17, 10, 22, 38, 22, 8, 31, 29, 25, 28, 28, 25, 13, 15, 22, 26, 11, 23, 120 15, 12, 17, 13, 12, 21, 14, 21, 22, 11, 12, 19, 12, 25, 24]121 },122 'JER': {123 'codes': ['Jer', 'Jr'],124 'verses': [19, 37, 25, 31, 31, 30, 34, 22, 26, 25, 23, 17, 27, 22, 21, 21, 27, 23, 15, 18, 14, 30, 40, 10, 38, 125 24, 22, 17, 32, 24, 40, 44, 26, 22, 19, 32, 21, 28, 18, 16, 18, 22, 13, 30, 5, 28, 7, 47, 39, 46, 64, 126 34]127 },128 'LAM': {129 'codes': ['Lam', 'Lm'],130 'verses': [22, 22, 66, 22, 22]131 },132 'EZK': {133 'codes': ['Ezek', 'Ezk'],134 'verses': [28, 10, 27, 17, 17, 14, 27, 18, 11, 22, 25, 28, 23, 23, 8, 63, 24, 32, 14, 49, 32, 31, 49, 27, 17, 21, 135 36, 26, 21, 26, 18, 32, 33, 31, 15, 38, 28, 23, 29, 49, 26, 20, 27, 31, 25, 24, 23, 35]136 },137 'DAN': {138 'codes': ['Dn', 'Dan'],139 'verses': [21, 49, 30, 37, 31, 28, 28, 27, 27, 21, 45, 13]140 },141 'HOS': {142 'codes': ['Hos', 'Hs'],143 'verses': [11, 23, 5, 19, 15, 11, 16, 14, 17, 15, 12, 10, 14, 9]144 },145 'JOL': {146 'codes': ['Joel', 'Jl'],147 'verses': [20, 32, 21]148 },149 'AMO': {150 'codes': ['Am'],151 'verses': [15, 16, 15, 13, 27, 14, 17, 14, 15]152 },153 'OBA': {154 'codes': ['Ob'],155 'verses': [21]156 },157 'JON': {158 'codes': ['Jon'],159 'verses': [17, 10, 10, 11]160 },161 'MIC': {162 'codes': ['Mi', 'Mc'],163 'verses': [16, 13, 12, 13, 15, 16, 20]164 },165 'NAM': {166 'codes': ['Na'],167 'verses': [15, 13, 19]168 },169 'HAB': {170 'codes': ['Hab'],171 'verses': [17, 20, 19]172 },173 'ZEP': {174 'codes': ['Zep', 'Zp'],175 'verses': [18, 15, 20]176 },177 'HAG': {178 'codes': ['Hag', 'Hg'],179 'verses': [15, 23]180 },181 'ZEC': {182 'codes': ['Zc', 'Zec'],183 'verses': [21, 13, 10, 14, 11, 15, 14, 20, 12, 21, 17, 14, 20, 9, 15, 21]184 },185 'MAL': {186 'codes': ['Mal', 'Ml'],187 'verses': [14, 17, 18, 6]188 },189 'MAT': {190 'codes': ['Mt', 'Mat'],191 'verses': [25, 23, 17, 25, 48, 34, 29, 34, 38, 42, 30, 50, 58, 36, 39, 28, 30, 34, 34, 46, 30, 46, 39, 28, 34, 192 31, 46, 46, 38, 71, 66, 20]193 },194 'MRK': {195 'codes': ['Mk', 'Mar'],196 'verses': [45, 28, 35, 41, 43, 56, 29, 38, 50, 52, 33, 44, 37, 72, 47, 20]197 },198 'LUK': {199 'codes': ['Lk', 'Lu'],200 'verses': [80, 52, 38, 44, 39, 49, 50, 56, 62, 42, 54, 59, 35, 35, 32, 31, 37, 43, 48, 47, 38, 71, 56, 39, 49, 201 57, 80, 55, 28, 35, 32, 31, 37, 50, 26, 46, 51, 66, 53, 59, 37, 35, 50, 40, 46, 51, 69, 53, 56, 20]202 },203 'JHN': {204 'codes': ['Jn', 'Joh', 'Jhn'],205 'verses': [51, 25, 36, 54, 47, 71, 53, 59, 41, 42, 57, 50, 38, 31, 27, 33, 26, 40, 42, 31, 25]206 },207 'ACT': {208 'codes': ['Ac'],209 'verses': [26, 47, 26, 37, 42, 15, 60, 40, 43, 48, 30, 25, 52, 28, 41, 40, 34, 28, 40, 38, 40, 30, 35, 27, 27, 210 32, 44, 31]211 },212 'ROM': {213 'codes': ['Ro', 'Rm'],214 'verses': [32, 29, 31, 25, 21, 23, 25, 39, 33, 21, 36, 21, 14, 23, 33, 27]215 },216 '1CO': {217 'codes': ['1Co'],218 'verses': [31, 16, 23, 21, 13, 20, 40, 13, 27, 33, 34, 31, 13, 40, 58, 24]219 },220 '2CO': {221 'codes': ['2Co'],222 'verses': [24, 17, 18, 18, 21, 18, 16, 24, 15, 18, 33, 21, 14]223 },224 'GAL': {225 'codes': ['Gal', 'Gl'],226 'verses': [24, 21, 29, 31, 26, 18]227 },228 'EPH': {229 'codes': ['Ep'],230 'verses': [23, 22, 21, 32, 33, 24]231 },232 'PHP': {233 'codes': ['Php', 'Philip'],234 'verses': [30, 30, 21, 23]235 },236 'COL': {237 'codes': ['Col'],238 'verses': [29, 23, 25, 18]239 },240 '1TH': {241 'codes': ['1Th'],242 'verses': [10, 20, 13, 18, 28]243 },244 '2TH': {245 'codes': ['2Th'],246 'verses': [12, 17, 18]247 },248 '1TI': {249 'codes': ['1Ti', '1Tm'],250 'verses': [20, 15, 16, 16, 25, 21, 25]251 },252 '2TI': {253 'codes': ['2Ti', '2Tm'],254 'verses': [18, 26, 17, 22]255 },256 'TIT': {257 'codes': ['Tit'],258 'verses': [16, 15, 15]259 },260 'PHM': {261 'codes': ['Phile', 'Phm'],262 'verses': [25]263 },264 'HEB': {265 'codes': ['Hb', 'Heb'],266 'verses': [14, 18, 19, 16, 14, 20, 28, 13, 28, 39, 40, 29, 25]267 },268 'JAS': {269 'codes': ['Ja', 'Jm'],270 'verses': [27, 26, 18, 17, 20]271 },272 '1PE': {273 'codes': ['1Pe', '2Pt'],274 'verses': [25, 25, 22, 19, 14]275 },276 '2PE': {277 'codes': ['2Pe', '2Pt'],278 'verses': [21, 22, 18]279 },280 '1JN': {281 'codes': ['1Jn', '1Jo', '1Jh'],282 'verses': [10, 29, 24, 21, 21]283 },284 '2JN': {285 'codes': ['2Jn', '2Jo', '2Jh'],286 'verses': [13]287 },288 '3JN': {289 'codes': ['3Jn', '3Jo', '3Jh'],290 'verses': [14]291 },292 'JUD': {293 'codes': ['Ju', 'Jd'],294 'verses': [25]295 },296 'REV': {297 'codes': ['Rev', 'Rv'],298 'verses': [20, 29, 22, 18, 14, 20, 17, 18, 20, 15, 23, 19, 21, 18, 18, 24, 22, 21, 21, 15, 27, 21]299 }300 }301 302 303 def __init__(self, reference):304 self.reference = reference305 self._structured_ref = self.parse_scripture_reference(reference)306 307 @property308 def is_valid(self):309 return bool(self._structured_ref['bookCode'] and self._structured_ref['startChapter'] and self._structured_ref['startVerse'])310 311 @classmethod312 def parse_scripture_reference(cls, input_ref):313 normalized_input = re.sub(r"\s+", "", input_ref).upper()314 regex = re.compile(r"^(\d)?(\D+)(\d+)?(?::(\d+))?(?:-(\d+)?(?::(\d+))?)?$")315 match = regex.match(normalized_input)316 317 if not match:318 return {'bookCode': '', 'startChapter': 0, 'endChapter': 0, 'startVerse': 0, 'endVerse': 0}319 320 bookPrefix, bookName, startChapter, startVerse, endChapterOrVerse, endVerse = match.groups()321 322 fullBookName = f"{bookPrefix or ''}{bookName}".upper()323 bookCode = ''324 for code, book in cls.book_codes.items():325 if any(fullBookName.startswith(name.upper()) for name in book['codes']):326 bookCode = code327 break328 329 # startChap = int(startChapter) if startChapter else 0330 # endChap = int(endChapterOrVerse) if endChapterOrVerse and endVerse else startChap331 # startVer = int(startVerse) if startVerse else 0332 # endVer = int(endVerse) if endVerse else int(endChapterOrVerse) if endChapterOrVerse and not endVerse else startVer333 334 # if startVer != 0 and endVer == 0:335 # endVer = startVer336 337 if bookCode:338 num_chapters = len(cls.book_codes[bookCode]['verses'])339 startChap = min(int(startChapter), num_chapters) if startChapter else 0340 endChap = min(int(endChapterOrVerse), num_chapters) if endChapterOrVerse and endVerse else startChap341 342 if startChap > 0:343 num_verses_in_start_chap = cls.book_codes[bookCode]['verses'][startChap - 1]344 startVer = min(int(startVerse), num_verses_in_start_chap) if startVerse else 0345 else:346 startVer = 0347 348 if endChap > 0:349 num_verses_in_end_chap = cls.book_codes[bookCode]['verses'][endChap - 1]350 endVer = min(int(endVerse), num_verses_in_end_chap) if endVerse else startVer351 else:352 endVer = startVer353 else:354 startChap = endChap = startVer = endVer = 0355 356 return {357 'bookCode': bookCode,358 'startChapter': startChap,359 'endChapter': endChap,360 'startVerse': startVer,361 'endVerse': endVer,362 }363 364 @property365 @cache366 def structured_ref(self):367 return self._structured_ref368 369 370 @property371 @cache372 def line_number(self):373 book_code = self.structured_ref['bookCode']374 start_chapter = self.structured_ref['startChapter']375 start_verse = self.structured_ref['startVerse']376 377 # Find the index of the book to get the starting line number378 book_index = list(self.book_codes.keys()).index(book_code)379 start_line_of_book = self.verse_ones[book_index]380 381 # Calculate the number of verses before the specified chapter382 verses_before = sum(self.book_codes[book_code]['verses'][:start_chapter - 1])383 384 # Calculate the line number of the verse385 line_number = start_line_of_book + verses_before + start_verse - 1386 387 return line_number388 389 # Override eq method to allow comparison of ScriptureReference objects based on line number390 # def __eq__(self, other):391 # return self.line_number == other.line_number392 393 # def __hash__(self):394 # book_code = self.structured_ref['bookCode']395 # start_chapter = self.structured_ref['startChapter']396 # start_verse = self.structured_ref['startVerse']397 # book_index = list(self.book_codes.keys()).index(book_code)398 # start_line_of_book = self.verse_ones[book_index]399 # verses_before = sum(self.book_codes[book_code]['verses'][:start_chapter - 1])400 # line_number = start_line_of_book + verses_before + start_verse - 1401 # return hash(line_number)402 403 404 405# # Example usage:406# reference = "1Jn 5:7-8"407# scripture_ref = ScriptureReference(reference)408# print("Structured Reference:", scripture_ref.get_structured_ref())409# print("Line Number:", scripture_ref.line_number)410 