Closed jamlen closed 10 years ago
I'd do something like the below, where you call get_intermediate_verses()
. It reaches pretty deeply into the bcv_parser object, so it could break in the future if the internal data structure ever changes. This is Coffeescript, not straight Javascript.
bcv_parser = require("./en_bcv_parser.min.js").bcv_parser
bcv = new bcv_parser
trans = "default"
book_order = []
# Assumes start and end are fully specified OSIS references and that they exist: "Gen.1.1", not "Gen.1". It also assumes you're using the default book order and number of verses in each chapter.
get_intermediate_verses = (start, end) ->
[sb, sc, sv] = start.split(".")
[eb, ec, ev] = end.split(".")
sc = parseInt sc, 10
sv = parseInt sv, 10
ec = parseInt ec, 10
ev = parseInt ev, 10
verses = []
# If it's the same book, just iterate through the chapters.
if sb is eb
# If the end chapter is before the start chapter, that's an error.
return [] if ec < sc
if sc == ec
# If the end verse is before the start verse, that's an error.
return [] if ev < sv
# Since they're in the same chapter, just iterate through the verses.
for v in [sv .. ev]
verses.push "#{sb}.#{sc}.#{v}"
# Different chapters in the same book.
else
# First get the verses from the start chapter.
verses = get_intermediate_verses start, "#{sb}.#{sc}.#{get_last_verse_in_chapter(sb, sc)}"
# Then get the verses from any chapters between the start and end chapters.
c = sc + 1
while c < ec
verses = verses.concat get_intermediate_verses "#{sb}.#{c}.1", "#{sb}.#{c}.#{get_last_verse_in_chapter(sb, c)}"
c++
# Then get the verses from the end chapter.
verses = verses.concat get_intermediate_verses "#{eb}.#{ec}.1", end
# Different books. Rare but complicated.
else
# Get an ordered list of all the books between the start and end books.
books = get_intermediate_books(sb, eb)
for b in books
# If it's the start book, set the start verse to the first verse in the range. Otherwise, we assume it's the first verse of the first chapter.
start_verse = if b is sb then start else "#{b}.1.1"
end_verse = ""
if b is eb
end_verse = end
# If it's not the end book, extend the range to the end of the book.
else
end_chapter = get_last_chapter_in_book b
end_verse = "#{b}.#{end_chapter}.#{get_last_verse_in_chapter(b, end_chapter)}"
# Recursively call this function for each book.
verses = verses.concat get_intermediate_verses start_verse, end_verse
verses
# Get all the books between the given start and end books, inclusively.
get_intermediate_books = (sb, eb) ->
start_i = bcv.translations[trans].order[sb]
end_i = bcv.translations[trans].order[eb]
# If the end book is before the start book, that's an error.
return [] if end_i < start_i
# We don't need to do anything complicated if the books are consecutive.
return [sb, eb] if end_i == start_i + 1
# Make sure the global variable is set.
get_book_order()
books = book_order.slice(start_i, end_i + 1)
get_last_verse_in_chapter = (b, c) ->
bcv.translations[trans].chapters[b][c - 1]
get_last_chapter_in_book = (b) ->
bcv.translations[trans].chapters[b].length
# Iterate through the translation and turn the `order` object into an array.
get_book_order = ->
return if book_order.length > 0
for own book, sort_order of bcv.translations[trans].order
book_order[sort_order] = book
# These return an array of intermediate verses.
console.log get_intermediate_verses("Gen.1.1", "Gen.1.3")
console.log get_intermediate_verses("Gen.1.2", "Gen.2.3")
console.log get_intermediate_verses("Gen.1.3", "Gen.3.3")
console.log get_intermediate_verses("Phlm.1.4", "Heb.4.3")
console.log get_intermediate_verses("Titus.1.5", "Heb.5.3")
# These return errors because the end verse is before the start verse.
console.log get_intermediate_verses("Gen.1.3", "Gen.1.1")
console.log get_intermediate_verses("Gen.2.3", "Gen.1.2")
console.log get_intermediate_verses("Gen.3.3", "Gen.1.3")
console.log get_intermediate_verses("Heb.4.3", "Phlm.1.4")
console.log get_intermediate_verses("Heb.5.3", "Titus.1.5")
That's great thanks, it has worked a treat...do you think it is worth adding so that if there is any structure changes it can be dealt with here rather than breaking calling code? Especially if there was some tests covering it!
How can I get an array of the verses that are in a range?
For example:
I want to get each verse so I can store it in a Mongo collection for querying later.