use std::collections::HashMap;
use std::sync::LazyLock;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ParallelTypeChirho {
SynopticChirho,
HistoryChirho,
ProphecyChirho,
QuotationChirho,
ThematicChirho,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParallelPassageChirho {
pub osis_ref_chirho: String,
pub book_chirho: String,
pub chapter_chirho: u8,
pub verse_start_chirho: u8,
pub verse_end_chirho: u8,
pub parallel_type_chirho: ParallelTypeChirho,
}
impl ParallelPassageChirho {
pub fn new_chirho(
book_chirho: &str,
chapter_chirho: u8,
verse_start_chirho: u8,
verse_end_chirho: u8,
parallel_type_chirho: ParallelTypeChirho,
) -> Self {
let osis_ref_chirho = if verse_start_chirho == verse_end_chirho {
format!("{}.{}.{}", book_chirho, chapter_chirho, verse_start_chirho)
} else {
format!(
"{}.{}.{}-{}",
book_chirho, chapter_chirho, verse_start_chirho, verse_end_chirho
)
};
Self {
osis_ref_chirho,
book_chirho: book_chirho.to_string(),
chapter_chirho,
verse_start_chirho,
verse_end_chirho,
parallel_type_chirho,
}
}
pub fn single_chirho(book_chirho: &str, chapter_chirho: u8, verse_chirho: u8, parallel_type_chirho: ParallelTypeChirho) -> Self {
Self::new_chirho(book_chirho, chapter_chirho, verse_chirho, verse_chirho, parallel_type_chirho)
}
pub fn display_ref_chirho(&self) -> String {
if self.verse_start_chirho == self.verse_end_chirho {
format!("{} {}:{}", self.book_chirho, self.chapter_chirho, self.verse_start_chirho)
} else {
format!(
"{} {}:{}-{}",
self.book_chirho, self.chapter_chirho, self.verse_start_chirho, self.verse_end_chirho
)
}
}
}
#[derive(Debug, Clone)]
pub struct ParallelSetChirho {
pub description_chirho: String,
pub passages_chirho: Vec<ParallelPassageChirho>,
pub parallel_type_chirho: ParallelTypeChirho,
}
impl ParallelSetChirho {
pub fn new_chirho(
description_chirho: &str,
passages_chirho: Vec<ParallelPassageChirho>,
parallel_type_chirho: ParallelTypeChirho,
) -> Self {
Self {
description_chirho: description_chirho.to_string(),
passages_chirho,
parallel_type_chirho,
}
}
}
pub struct ParallelManagerChirho {
ref_to_sets_chirho: HashMap<String, Vec<usize>>,
parallel_sets_chirho: Vec<ParallelSetChirho>,
}
static SYNOPTIC_PARALLELS_CHIRHO: LazyLock<Vec<ParallelSetChirho>> = LazyLock::new(|| {
let synoptic_chirho = ParallelTypeChirho::SynopticChirho;
vec![
ParallelSetChirho::new_chirho(
"Baptism of Jesus",
vec![
ParallelPassageChirho::new_chirho("Matt", 3, 13, 17, synoptic_chirho),
ParallelPassageChirho::new_chirho("Mark", 1, 9, 11, synoptic_chirho),
ParallelPassageChirho::new_chirho("Luke", 3, 21, 22, synoptic_chirho),
],
synoptic_chirho,
),
ParallelSetChirho::new_chirho(
"Temptation of Jesus",
vec![
ParallelPassageChirho::new_chirho("Matt", 4, 1, 11, synoptic_chirho),
ParallelPassageChirho::new_chirho("Mark", 1, 12, 13, synoptic_chirho),
ParallelPassageChirho::new_chirho("Luke", 4, 1, 13, synoptic_chirho),
],
synoptic_chirho,
),
ParallelSetChirho::new_chirho(
"Feeding of the 5000",
vec![
ParallelPassageChirho::new_chirho("Matt", 14, 13, 21, synoptic_chirho),
ParallelPassageChirho::new_chirho("Mark", 6, 30, 44, synoptic_chirho),
ParallelPassageChirho::new_chirho("Luke", 9, 10, 17, synoptic_chirho),
ParallelPassageChirho::new_chirho("John", 6, 1, 14, synoptic_chirho),
],
synoptic_chirho,
),
ParallelSetChirho::new_chirho(
"Peter's Confession",
vec![
ParallelPassageChirho::new_chirho("Matt", 16, 13, 20, synoptic_chirho),
ParallelPassageChirho::new_chirho("Mark", 8, 27, 30, synoptic_chirho),
ParallelPassageChirho::new_chirho("Luke", 9, 18, 21, synoptic_chirho),
],
synoptic_chirho,
),
ParallelSetChirho::new_chirho(
"Transfiguration",
vec![
ParallelPassageChirho::new_chirho("Matt", 17, 1, 8, synoptic_chirho),
ParallelPassageChirho::new_chirho("Mark", 9, 2, 8, synoptic_chirho),
ParallelPassageChirho::new_chirho("Luke", 9, 28, 36, synoptic_chirho),
],
synoptic_chirho,
),
ParallelSetChirho::new_chirho(
"Triumphal Entry",
vec![
ParallelPassageChirho::new_chirho("Matt", 21, 1, 11, synoptic_chirho),
ParallelPassageChirho::new_chirho("Mark", 11, 1, 11, synoptic_chirho),
ParallelPassageChirho::new_chirho("Luke", 19, 28, 44, synoptic_chirho),
ParallelPassageChirho::new_chirho("John", 12, 12, 19, synoptic_chirho),
],
synoptic_chirho,
),
ParallelSetChirho::new_chirho(
"Last Supper",
vec![
ParallelPassageChirho::new_chirho("Matt", 26, 17, 30, synoptic_chirho),
ParallelPassageChirho::new_chirho("Mark", 14, 12, 26, synoptic_chirho),
ParallelPassageChirho::new_chirho("Luke", 22, 7, 23, synoptic_chirho),
],
synoptic_chirho,
),
ParallelSetChirho::new_chirho(
"Crucifixion",
vec![
ParallelPassageChirho::new_chirho("Matt", 27, 32, 56, synoptic_chirho),
ParallelPassageChirho::new_chirho("Mark", 15, 21, 41, synoptic_chirho),
ParallelPassageChirho::new_chirho("Luke", 23, 26, 49, synoptic_chirho),
ParallelPassageChirho::new_chirho("John", 19, 17, 37, synoptic_chirho),
],
synoptic_chirho,
),
ParallelSetChirho::new_chirho(
"Resurrection",
vec![
ParallelPassageChirho::new_chirho("Matt", 28, 1, 10, synoptic_chirho),
ParallelPassageChirho::new_chirho("Mark", 16, 1, 8, synoptic_chirho),
ParallelPassageChirho::new_chirho("Luke", 24, 1, 12, synoptic_chirho),
ParallelPassageChirho::new_chirho("John", 20, 1, 10, synoptic_chirho),
],
synoptic_chirho,
),
ParallelSetChirho::new_chirho(
"Lord's Prayer",
vec![
ParallelPassageChirho::new_chirho("Matt", 6, 9, 13, synoptic_chirho),
ParallelPassageChirho::new_chirho("Luke", 11, 2, 4, synoptic_chirho),
],
synoptic_chirho,
),
ParallelSetChirho::new_chirho(
"Beatitudes",
vec![
ParallelPassageChirho::new_chirho("Matt", 5, 3, 12, synoptic_chirho),
ParallelPassageChirho::new_chirho("Luke", 6, 20, 26, synoptic_chirho),
],
synoptic_chirho,
),
]
});
static HISTORY_PARALLELS_CHIRHO: LazyLock<Vec<ParallelSetChirho>> = LazyLock::new(|| {
let history_chirho = ParallelTypeChirho::HistoryChirho;
vec![
ParallelSetChirho::new_chirho(
"David becomes king of Israel",
vec![
ParallelPassageChirho::new_chirho("2Sam", 5, 1, 5, history_chirho),
ParallelPassageChirho::new_chirho("1Chr", 11, 1, 3, history_chirho),
],
history_chirho,
),
ParallelSetChirho::new_chirho(
"David captures Jerusalem",
vec![
ParallelPassageChirho::new_chirho("2Sam", 5, 6, 10, history_chirho),
ParallelPassageChirho::new_chirho("1Chr", 11, 4, 9, history_chirho),
],
history_chirho,
),
ParallelSetChirho::new_chirho(
"Ark brought to Jerusalem",
vec![
ParallelPassageChirho::new_chirho("2Sam", 6, 1, 19, history_chirho),
ParallelPassageChirho::new_chirho("1Chr", 13, 1, 14, history_chirho),
],
history_chirho,
),
ParallelSetChirho::new_chirho(
"Solomon's reign begins",
vec![
ParallelPassageChirho::new_chirho("1Kgs", 1, 28, 53, history_chirho),
ParallelPassageChirho::new_chirho("1Chr", 29, 21, 25, history_chirho),
],
history_chirho,
),
ParallelSetChirho::new_chirho(
"Solomon's temple dedication",
vec![
ParallelPassageChirho::new_chirho("1Kgs", 8, 1, 66, history_chirho),
ParallelPassageChirho::new_chirho("2Chr", 5, 1, 14, history_chirho),
],
history_chirho,
),
ParallelSetChirho::new_chirho(
"Hezekiah's illness and recovery",
vec![
ParallelPassageChirho::new_chirho("2Kgs", 20, 1, 11, history_chirho),
ParallelPassageChirho::new_chirho("2Chr", 32, 24, 26, history_chirho),
ParallelPassageChirho::new_chirho("Isa", 38, 1, 8, history_chirho),
],
history_chirho,
),
]
});
impl ParallelManagerChirho {
pub fn new_chirho() -> Self {
let mut manager_chirho = Self {
ref_to_sets_chirho: HashMap::new(),
parallel_sets_chirho: Vec::new(),
};
for set_chirho in SYNOPTIC_PARALLELS_CHIRHO.iter() {
manager_chirho.add_parallel_set_chirho(set_chirho.clone());
}
for set_chirho in HISTORY_PARALLELS_CHIRHO.iter() {
manager_chirho.add_parallel_set_chirho(set_chirho.clone());
}
manager_chirho
}
pub fn add_parallel_set_chirho(&mut self, set_chirho: ParallelSetChirho) {
let set_idx_chirho = self.parallel_sets_chirho.len();
for passage_chirho in &set_chirho.passages_chirho {
self.ref_to_sets_chirho
.entry(passage_chirho.osis_ref_chirho.clone())
.or_default()
.push(set_idx_chirho);
for verse_chirho in passage_chirho.verse_start_chirho..=passage_chirho.verse_end_chirho {
let single_ref_chirho = format!(
"{}.{}.{}",
passage_chirho.book_chirho, passage_chirho.chapter_chirho, verse_chirho
);
self.ref_to_sets_chirho
.entry(single_ref_chirho)
.or_default()
.push(set_idx_chirho);
}
}
self.parallel_sets_chirho.push(set_chirho);
}
pub fn get_parallels_chirho(&self, osis_ref_chirho: &str) -> Vec<&ParallelSetChirho> {
let normalized_chirho = osis_ref_chirho.replace(' ', ".");
if let Some(indices_chirho) = self.ref_to_sets_chirho.get(&normalized_chirho) {
indices_chirho
.iter()
.filter_map(|&idx_chirho| self.parallel_sets_chirho.get(idx_chirho))
.collect()
} else {
Vec::new()
}
}
pub fn get_by_type_chirho(&self, parallel_type_chirho: ParallelTypeChirho) -> Vec<&ParallelSetChirho> {
self.parallel_sets_chirho
.iter()
.filter(|set_chirho| set_chirho.parallel_type_chirho == parallel_type_chirho)
.collect()
}
pub fn count_chirho(&self) -> usize {
self.parallel_sets_chirho.len()
}
}
impl Default for ParallelManagerChirho {
fn default() -> Self {
Self::new_chirho()
}
}
#[cfg(test)]
mod tests_chirho {
use super::*;
#[test]
fn test_parallel_passage_creation_chirho() {
let passage_chirho = ParallelPassageChirho::new_chirho(
"Matt",
3,
13,
17,
ParallelTypeChirho::SynopticChirho,
);
assert_eq!(passage_chirho.osis_ref_chirho, "Matt.3.13-17");
assert_eq!(passage_chirho.display_ref_chirho(), "Matt 3:13-17");
}
#[test]
fn test_single_verse_parallel_chirho() {
let passage_chirho = ParallelPassageChirho::single_chirho(
"John",
3,
16,
ParallelTypeChirho::QuotationChirho,
);
assert_eq!(passage_chirho.osis_ref_chirho, "John.3.16");
assert_eq!(passage_chirho.display_ref_chirho(), "John 3:16");
}
#[test]
fn test_manager_creation_chirho() {
let manager_chirho = ParallelManagerChirho::new_chirho();
assert!(manager_chirho.count_chirho() > 0);
let synoptics_chirho = manager_chirho.get_by_type_chirho(ParallelTypeChirho::SynopticChirho);
assert!(!synoptics_chirho.is_empty());
let histories_chirho = manager_chirho.get_by_type_chirho(ParallelTypeChirho::HistoryChirho);
assert!(!histories_chirho.is_empty());
}
#[test]
fn test_baptism_parallel_lookup_chirho() {
let manager_chirho = ParallelManagerChirho::new_chirho();
let parallels_chirho = manager_chirho.get_parallels_chirho("Matt.3.16");
assert!(!parallels_chirho.is_empty());
let baptism_set_chirho = parallels_chirho
.iter()
.find(|s_chirho| s_chirho.description_chirho == "Baptism of Jesus");
assert!(baptism_set_chirho.is_some());
let set_chirho = baptism_set_chirho.unwrap();
assert!(set_chirho.passages_chirho.iter().any(|p_chirho| p_chirho.book_chirho == "Mark"));
assert!(set_chirho.passages_chirho.iter().any(|p_chirho| p_chirho.book_chirho == "Luke"));
}
#[test]
fn test_feeding_5000_parallel_chirho() {
let manager_chirho = ParallelManagerChirho::new_chirho();
let parallels_chirho = manager_chirho.get_parallels_chirho("John.6.5");
assert!(!parallels_chirho.is_empty());
let feeding_set_chirho = parallels_chirho
.iter()
.find(|s_chirho| s_chirho.description_chirho == "Feeding of the 5000");
assert!(feeding_set_chirho.is_some());
let set_chirho = feeding_set_chirho.unwrap();
assert_eq!(set_chirho.passages_chirho.len(), 4);
}
#[test]
fn test_history_parallel_chirho() {
let manager_chirho = ParallelManagerChirho::new_chirho();
let parallels_chirho = manager_chirho.get_parallels_chirho("2Sam.5.6");
assert!(!parallels_chirho.is_empty());
let jerusalem_set_chirho = parallels_chirho
.iter()
.find(|s_chirho| s_chirho.description_chirho.contains("Jerusalem"));
assert!(jerusalem_set_chirho.is_some());
}
#[test]
fn test_no_parallels_chirho() {
let manager_chirho = ParallelManagerChirho::new_chirho();
let parallels_chirho = manager_chirho.get_parallels_chirho("Obad.1.1");
assert!(parallels_chirho.is_empty());
}
}