defmodule BibleEx.Reference do @moduledoc """ Is a general Bible reference struct. """ alias BibleEx.Librarian alias BibleEx.Chapter alias BibleEx.Verse @enforce_keys [:book] defstruct book: "", book_names: %{}, book_number: nil, reference: nil, reference_type: nil, start_chapter: nil, start_chapter_number: nil, start_verse: nil, start_verse_number: nil, end_chapter: nil, end_chapter_number: nil, end_verse: nil, end_verse_number: nil, is_valid: false, chapters: [], verses: [], osis: nil, abbr: nil, short: nil @doc """ Make a new `%Reference{}` struct. ## Parameters - *book*: a string that is one of the four possible book name formats - `"GEN"` (abbr) - `"Genesis"` (name) - `"Gen"` (osis) - `"Gn"` (short) - *start_chapter*: an integer that is the start chapter number - *start_verse*: an integer that is the start verse number - *end_chapter*: an integer that is the end chapter number - *end_verse*: an integer that is the end verse number ## Examples iex> alias BibleEx.Reference iex> genesis_ref = Reference.new(book: "Genesis", start_chapter: 2, start_verse: 3, end_chapter: 4, end_verse: 5) %BibleEx.Reference{ book: "Genesis", book_names: %{abbr: "GEN", name: "Genesis", osis: "Gen", short: "Gn"}, book_number: 1, reference: "Genesis 2:3 - 4:5", reference_type: :chapter_range, start_chapter: %BibleEx.Chapter{ ... } } iex> alias BibleEx.Reference iex> Reference.new(book: "3 John") %BibleEx.Reference{ book: "3 John", book_names: %{abbr: "3JO", name: "3 John", osis: "3John", short: "3 Jn"}, book_number: 64, reference: "3 John", reference_type: :chapter, start_chapter: %BibleEx.Chapter{ book: "3 John", book_names: %{abbr: "3JO", name: "3 John", osis: "3John", short: "3 Jn"}, reference_type: :chapter, reference: "3 John 1", chapter_number: 1, start_verse_number: 1, start_verse: %BibleEx.Verse{ book: "3 John", book_names: %{abbr: "3JO", name: "3 John", osis: "3John", short: "3 Jn"}, book_number: 64, reference_type: :verse, reference: "3 John 1:1", chapter_number: 1, verse_number: 1, is_valid: true }, end_verse: %BibleEx.Verse{ book: "3 John", book_names: %{abbr: "3JO", name: "3 John", osis: "3John", short: "3 Jn"}, book_number: 64, reference_type: :verse, reference: "3 John 1:15", chapter_number: 1, verse_number: 15, is_valid: true }, end_verse_number: 15, verses: [ ... ], is_valid: true }, start_chapter_number: 1, start_verse: %BibleEx.Verse{ book: "3 John", book_names: %{abbr: "3JO", name: "3 John", osis: "3John", short: "3 Jn"}, book_number: 64, reference_type: :verse, reference: "3 John 1:1", chapter_number: 1, verse_number: 1, is_valid: true }, start_verse_number: 1, end_chapter: %BibleEx.Chapter{ book: "3 John", book_names: %{abbr: "3JO", name: "3 John", osis: "3John", short: "3 Jn"}, reference_type: :chapter, reference: nil, chapter_number: nil, start_verse_number: 1, start_verse: %BibleEx.Verse{ book: "3 John", book_names: %{abbr: "3JO", name: "3 John", osis: "3John", short: "3 Jn"}, book_number: 64, reference_type: :verse, reference: nil, chapter_number: nil, verse_number: 1, is_valid: false }, end_verse: %BibleEx.Verse{ book: "3 John", book_names: %{abbr: "3JO", name: "3 John", osis: "3John", short: "3 Jn"}, book_number: 64, reference_type: :verse, reference: "3 John 1:15", chapter_number: 1, verse_number: 15, is_valid: true }, end_verse_number: 15, verses: nil, is_valid: true }, end_chapter_number: 1, end_verse: 15, end_verse_number: 15, is_valid: true, chapters: [ %BibleEx.Chapter{ book: "3 John", book_names: %{abbr: "3JO", name: "3 John", osis: "3John", short: "3 Jn"}, reference_type: :chapter, reference: "3 John 1", chapter_number: 1, start_verse_number: 1, start_verse: %BibleEx.Verse{ book: "3 John", book_names: %{abbr: "3JO", name: "3 John", osis: "3John", short: "3 Jn"}, book_number: 64, reference_type: :verse, reference: "3 John 1:1", chapter_number: 1, verse_number: 1, is_valid: true }, end_verse: %BibleEx.Verse{ book: "3 John", book_names: %{abbr: "3JO", name: "3 John", osis: "3John", short: "3 Jn"}, book_number: 64, reference_type: :verse, reference: "3 John 1:15", chapter_number: 1, verse_number: 15, is_valid: true }, end_verse_number: 15, verses: [ ... ], is_valid: true } ], verses: [ ... ] } """ def new(book: book) do new(book: book, start_chapter: nil, start_verse: nil, end_chapter: nil, end_verse: nil) end def new( book: book, start_chapter: start_chapter ) do new( book: book, start_chapter: start_chapter, start_verse: nil, end_chapter: nil, end_verse: nil ) end def new( book: book, start_chapter: start_chapter, start_verse: start_verse ) do new( book: book, start_chapter: start_chapter, start_verse: start_verse, end_chapter: nil, end_verse: nil ) end def new( book: book, start_chapter: start_chapter, start_verse: start_verse, end_chapter: end_chapter ) do new( book: book, start_chapter: start_chapter, start_verse: start_verse, end_chapter: end_chapter, end_verse: nil ) end def new( book: book, start_chapter: start_chapter, start_verse: start_verse, end_chapter: end_chapter, end_verse: end_verse ) do bname = case Librarian.get_book_names(book: book) do book_names = %{ osis: _osis, abbr: _abbr, name: _name, short: _short } -> Map.get(book_names, :name, book) %{} -> book end sc = if !is_nil(start_chapter) do Chapter.new(book: bname, chapter_number: start_chapter) else Chapter.new(book: bname, chapter_number: 1) end scn = if !is_nil(start_chapter) do start_chapter else 1 end ec = if !is_nil(end_chapter) do Chapter.new(book: bname, chapter_number: end_chapter) else if !is_nil(start_chapter) do Chapter.new(book: bname, chapter_number: start_chapter) else Chapter.new(book: bname, chapter_number: end_chapter) end end ecn = if !is_nil(end_chapter) do end_chapter else if !is_nil(start_chapter) do scn else Librarian.get_last_chapter_number(book: bname) end end sv = if !is_nil(start_verse) do Verse.new(book: bname, chapter_number: start_chapter, verse_number: start_verse) else Verse.new(book: bname, chapter_number: 1, verse_number: 1) end svn = if !is_nil(start_verse) do start_verse else 1 end ev = if !is_nil(end_verse) do Verse.new(book: bname, chapter_number: scn, verse_number: end_verse) else if !is_nil(start_verse) do Verse.new(book: bname, chapter_number: scn, verse_number: start_verse) else Librarian.get_last_verse_number(book: bname, chapter: scn) end end evn = if !is_nil(end_verse) do end_verse else if !is_nil(start_verse) do start_verse else Librarian.get_last_verse_number(book: bname, chapter: ecn) end end chapters = Librarian.get_chapters( book: bname, start_chapter: scn, end_chapter: ecn ) chapter_list = scn..ecn |> Enum.to_list() verse_collection = Enum.map(chapter_list, fn x -> # if svn is nil then choose 1, else choose svn find_start_verse = if !is_nil(svn) and x == Enum.at(chapter_list, 0) do svn else 1 end # if evn is nil then choose last verse, else choose evn find_last_verse = if !is_nil(evn) and x == List.last(chapter_list) do evn else Librarian.get_last_verse_number(book: bname, chapter: x) end Librarian.get_verses( book: bname, chapter: x, start_verse: find_start_verse, end_verse: find_last_verse ) end) book_names = Librarian.get_book_names(book: bname) osis_book = Map.get(Librarian.get_book_names(book: bname), :osis, nil) abbr_book = Map.get(Librarian.get_book_names(book: bname), :abbr, nil) short_book = Map.get(Librarian.get_book_names(book: bname), :short, nil) %__MODULE__{ book: bname, book_names: book_names, book_number: Librarian.find_book_number(book: bname), reference: Librarian.create_reference_string( book: bname, start_chapter: start_chapter, start_verse: start_verse, end_chapter: ecn, end_verse: end_verse ), reference_type: Librarian.identify_reference_type( book: bname, start_chapter: scn, start_verse: start_verse, end_chapter: ecn, end_verse: end_verse ), start_chapter: sc, start_chapter_number: scn, end_chapter: ec, end_chapter_number: ecn, start_verse: sv, start_verse_number: svn, end_verse: ev, end_verse_number: evn, is_valid: Librarian.verify_reference( book: bname, start_chapter: scn, start_verse: start_verse, end_chapter: ecn, end_verse: end_verse ), chapters: chapters, verses: List.flatten(verse_collection), osis: osis_book, abbr: abbr_book, short: short_book } end @doc """ Make a chapter `%Reference{}` struct. ## Parameters - *book*: a string that is one of the four possible book name formats - `"GEN"` (abbr) - `"Genesis"` (name) - `"Gen"` (osis) - `"Gn"` (short) - *chapter*: an integer that is the chapter number ## Examples iex> alias BibleEx.Reference iex> genesis_ref = Reference.chapter(book: "Genesis", chapter: 1) %BibleEx.Reference{ book: "Genesis", book_names: %{abbr: "GEN", name: "Genesis", osis: "Gen", short: "Gn"}, book_number: 1, reference: "Genesis 1", reference_type: :chapter, start_chapter: %BibleEx.Chapter{ ... } } """ def chapter(book: book, chapter: chapter) do new(book: book, start_chapter: chapter) end @doc """ Make a verse `%Reference{}` struct. ## Parameters - *book*: a string that is one of the four possible book name formats - `"GEN"` (abbr) - `"Genesis"` (name) - `"Gen"` (osis) - `"Gn"` (short) - *chapter*: an integer that is the chapter number - *verse*: an integer that is the verse number ## Examples iex> alias BibleEx.Reference iex> gen_11 = Reference.verse(book: "Genesis", chapter: 1, verse: 1) %BibleEx.Reference{ book: "Genesis", book_names: %{abbr: "GEN", name: "Genesis", osis: "Gen", short: "Gn"}, book_number: 1, reference: "Genesis 1:1", reference_type: :verse, start_chapter: %BibleEx.Chapter{ ... } ... } """ def verse(book: book, chapter: chapter, verse: verse) do new(book: book, start_chapter: chapter, start_verse: verse) end @doc """ Make a chapter_range `%Reference{}` struct. ## Parameters - *book*: a string that is one of the four possible book name formats - `"GEN"` (abbr) - `"Genesis"` (name) - `"Gen"` (osis) - `"Gn"` (short) - *start_chapter*: an integer that is the chapter number - *end_chapter*: an integer that is the chapter number ## Examples iex> alias BibleEx.Reference iex> gen_1_to_2 = Reference.verse(book: "Genesis", start_chapter: 1, end_chapter: 2) %BibleEx.Reference{ book: "Genesis", book_names: %{abbr: "GEN", name: "Genesis", osis: "Gen", short: "Gn"}, book_number: 1, reference: "Genesis 1-2", reference_type: :chapter_range, start_chapter: %BibleEx.Chapter{ ... } ... } """ def chapter_range(book: book, start_chapter: start_chapter, end_chapter: end_chapter) do new( book: book, start_chapter: start_chapter, start_verse: nil, end_chapter: end_chapter, end_verse: nil ) end @doc """ Make a verse_range `%Reference{}` struct. ## Parameters - *book*: a string that is one of the four possible book name formats - `"GEN"` (abbr) - `"Genesis"` (name) - `"Gen"` (osis) - `"Gn"` (short) - *start_verse*: an integer that is the start verse number - *end_verse*: an integer that is the end verse number ## Examples iex> alias BibleEx.Reference iex> matt2410 = Reference.verse_range(book: "Mat", chapter: 2, start_verse: 4, end_verse: 10) %BibleEx.Reference{ book: "Matthew", book_names: %{abbr: "MAT", name: "Matthew", osis: "Matt", short: "Mt"}, book_number: 40, reference: "Matthew 2:4-10", reference_type: :verse_range, start_chapter: %BibleEx.Chapter{ ... } ... } """ def verse_range(book: book, chapter: chapter, start_verse: start_verse, end_verse: end_verse) do new( book: book, start_chapter: chapter, start_verse: start_verse, end_chapter: nil, end_verse: end_verse ) end end