use std::collections::HashMap;
use std::sync::LazyLock;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VerseMappingResultChirho {
DirectChirho {
book_chirho: String,
chapter_chirho: u32,
verse_chirho: u32,
},
SplitChirho {
verses_chirho: Vec<(String, u32, u32)>,
},
MergedChirho {
book_chirho: String,
chapter_chirho: u32,
verse_range_chirho: (u32, u32),
},
NotFoundChirho,
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
struct MappingRuleChirho {
source_book_chirho: String,
source_chapter_chirho: u32,
source_verse_chirho: (u32, u32),
target_book_chirho: String,
target_chapter_chirho: u32,
target_verse_chirho: (u32, u32),
}
#[derive(Debug, Clone)]
pub struct VerseMappingChirho {
rules_chirho: HashMap<String, HashMap<String, Vec<MappingRuleChirho>>>,
}
impl VerseMappingChirho {
pub fn new_chirho() -> Self {
Self {
rules_chirho: build_default_mappings_chirho(),
}
}
pub fn map_verse_chirho(
&self,
book_chirho: &str,
chapter_chirho: u32,
verse_chirho: u32,
from_v11n_chirho: &str,
to_v11n_chirho: &str,
) -> VerseMappingResultChirho {
if from_v11n_chirho.eq_ignore_ascii_case(to_v11n_chirho) {
return VerseMappingResultChirho::DirectChirho {
book_chirho: book_chirho.to_string(),
chapter_chirho,
verse_chirho,
};
}
let key_chirho = format!("{}->{}", from_v11n_chirho.to_uppercase(), to_v11n_chirho.to_uppercase());
if let Some(book_rules_chirho) = self.rules_chirho.get(&key_chirho) {
let book_upper_chirho = book_chirho.to_uppercase();
if let Some(rules_chirho) = book_rules_chirho.get(&book_upper_chirho) {
for rule_chirho in rules_chirho {
if rule_chirho.source_chapter_chirho == chapter_chirho
&& verse_chirho >= rule_chirho.source_verse_chirho.0
&& verse_chirho <= rule_chirho.source_verse_chirho.1
{
return apply_rule_chirho(rule_chirho, verse_chirho);
}
}
}
}
VerseMappingResultChirho::DirectChirho {
book_chirho: book_chirho.to_string(),
chapter_chirho,
verse_chirho,
}
}
pub fn map_range_chirho(
&self,
book_chirho: &str,
chapter_chirho: u32,
start_verse_chirho: u32,
end_verse_chirho: u32,
from_v11n_chirho: &str,
to_v11n_chirho: &str,
) -> Vec<VerseMappingResultChirho> {
let mut results_chirho = Vec::new();
for verse_chirho in start_verse_chirho..=end_verse_chirho {
results_chirho.push(self.map_verse_chirho(
book_chirho,
chapter_chirho,
verse_chirho,
from_v11n_chirho,
to_v11n_chirho,
));
}
results_chirho
}
pub fn has_mapping_chirho(&self, from_v11n_chirho: &str, to_v11n_chirho: &str) -> bool {
let key_chirho = format!("{}->{}", from_v11n_chirho.to_uppercase(), to_v11n_chirho.to_uppercase());
self.rules_chirho.contains_key(&key_chirho)
}
pub fn available_mappings_chirho(&self) -> Vec<(&str, &str)> {
self.rules_chirho
.keys()
.filter_map(|k_chirho| {
let parts_chirho: Vec<&str> = k_chirho.split("->").collect();
if parts_chirho.len() == 2 {
Some((parts_chirho[0], parts_chirho[1]))
} else {
None
}
})
.collect()
}
}
impl Default for VerseMappingChirho {
fn default() -> Self {
Self::new_chirho()
}
}
fn apply_rule_chirho(rule_chirho: &MappingRuleChirho, source_verse_chirho: u32) -> VerseMappingResultChirho {
let source_range_chirho = rule_chirho.source_verse_chirho.1 - rule_chirho.source_verse_chirho.0 + 1;
let target_range_chirho = rule_chirho.target_verse_chirho.1 - rule_chirho.target_verse_chirho.0 + 1;
if source_range_chirho == 1 && target_range_chirho == 1 {
VerseMappingResultChirho::DirectChirho {
book_chirho: rule_chirho.target_book_chirho.clone(),
chapter_chirho: rule_chirho.target_chapter_chirho,
verse_chirho: rule_chirho.target_verse_chirho.0,
}
} else if source_range_chirho == 1 && target_range_chirho > 1 {
let mut verses_chirho = Vec::new();
for v_chirho in rule_chirho.target_verse_chirho.0..=rule_chirho.target_verse_chirho.1 {
verses_chirho.push((
rule_chirho.target_book_chirho.clone(),
rule_chirho.target_chapter_chirho,
v_chirho,
));
}
VerseMappingResultChirho::SplitChirho { verses_chirho }
} else if source_range_chirho > 1 && target_range_chirho == 1 {
VerseMappingResultChirho::MergedChirho {
book_chirho: rule_chirho.target_book_chirho.clone(),
chapter_chirho: rule_chirho.target_chapter_chirho,
verse_range_chirho: (source_verse_chirho, source_verse_chirho),
}
} else {
let offset_chirho = source_verse_chirho - rule_chirho.source_verse_chirho.0;
let target_verse_chirho = rule_chirho.target_verse_chirho.0 + offset_chirho;
VerseMappingResultChirho::DirectChirho {
book_chirho: rule_chirho.target_book_chirho.clone(),
chapter_chirho: rule_chirho.target_chapter_chirho,
verse_chirho: target_verse_chirho,
}
}
}
fn build_default_mappings_chirho() -> HashMap<String, HashMap<String, Vec<MappingRuleChirho>>> {
let mut mappings_chirho: HashMap<String, HashMap<String, Vec<MappingRuleChirho>>> = HashMap::new();
let mut kjv_to_catholic_chirho: HashMap<String, Vec<MappingRuleChirho>> = HashMap::new();
kjv_to_catholic_chirho.insert("PSALM".to_string(), vec![
MappingRuleChirho {
source_book_chirho: "Psalm".to_string(),
source_chapter_chirho: 10,
source_verse_chirho: (1, 18),
target_book_chirho: "Psalm".to_string(),
target_chapter_chirho: 9,
target_verse_chirho: (22, 39),
},
]);
mappings_chirho.insert("KJV->CATHOLIC".to_string(), kjv_to_catholic_chirho);
let mut kjv_to_hebrew_chirho: HashMap<String, Vec<MappingRuleChirho>> = HashMap::new();
kjv_to_hebrew_chirho.insert("PSALM".to_string(), vec![
MappingRuleChirho {
source_book_chirho: "Psalm".to_string(),
source_chapter_chirho: 3,
source_verse_chirho: (1, 8),
target_book_chirho: "Psalm".to_string(),
target_chapter_chirho: 3,
target_verse_chirho: (2, 9),
},
MappingRuleChirho {
source_book_chirho: "Psalm".to_string(),
source_chapter_chirho: 4,
source_verse_chirho: (1, 8),
target_book_chirho: "Psalm".to_string(),
target_chapter_chirho: 4,
target_verse_chirho: (2, 9),
},
]);
mappings_chirho.insert("KJV->LENINGRAD".to_string(), kjv_to_hebrew_chirho.clone());
mappings_chirho.insert("KJV->MT".to_string(), kjv_to_hebrew_chirho.clone());
mappings_chirho.insert("KJV->HEBREW".to_string(), kjv_to_hebrew_chirho);
let mut catholic_to_kjv_chirho: HashMap<String, Vec<MappingRuleChirho>> = HashMap::new();
catholic_to_kjv_chirho.insert("PSALM".to_string(), vec![
MappingRuleChirho {
source_book_chirho: "Psalm".to_string(),
source_chapter_chirho: 9,
source_verse_chirho: (22, 39),
target_book_chirho: "Psalm".to_string(),
target_chapter_chirho: 10,
target_verse_chirho: (1, 18),
},
]);
mappings_chirho.insert("CATHOLIC->KJV".to_string(), catholic_to_kjv_chirho);
mappings_chirho.insert("KJV->LXX".to_string(), mappings_chirho.get("KJV->CATHOLIC").cloned().unwrap_or_default());
mappings_chirho.insert("LXX->KJV".to_string(), mappings_chirho.get("CATHOLIC->KJV").cloned().unwrap_or_default());
mappings_chirho
}
static GLOBAL_MAPPER_CHIRHO: LazyLock<VerseMappingChirho> = LazyLock::new(VerseMappingChirho::new_chirho);
pub fn global_mapper_chirho() -> &'static VerseMappingChirho {
&GLOBAL_MAPPER_CHIRHO
}
#[cfg(test)]
mod tests_chirho {
use super::*;
#[test]
fn test_same_versification_chirho() {
let mapper_chirho = VerseMappingChirho::new_chirho();
let result_chirho = mapper_chirho.map_verse_chirho("Genesis", 1, 1, "KJV", "KJV");
assert_eq!(result_chirho, VerseMappingResultChirho::DirectChirho {
book_chirho: "Genesis".to_string(),
chapter_chirho: 1,
verse_chirho: 1,
});
}
#[test]
fn test_default_mapping_chirho() {
let mapper_chirho = VerseMappingChirho::new_chirho();
let result_chirho = mapper_chirho.map_verse_chirho("Genesis", 1, 1, "KJV", "Catholic");
match result_chirho {
VerseMappingResultChirho::DirectChirho { book_chirho, chapter_chirho, verse_chirho } => {
assert_eq!(book_chirho, "Genesis");
assert_eq!(chapter_chirho, 1);
assert_eq!(verse_chirho, 1);
}
_ => panic!("Expected direct mapping"),
}
}
#[test]
fn test_psalm_kjv_to_hebrew_chirho() {
let mapper_chirho = VerseMappingChirho::new_chirho();
let result_chirho = mapper_chirho.map_verse_chirho("Psalm", 3, 1, "KJV", "Leningrad");
match result_chirho {
VerseMappingResultChirho::DirectChirho { chapter_chirho, verse_chirho, .. } => {
assert_eq!(chapter_chirho, 3);
assert_eq!(verse_chirho, 2);
}
_ => panic!("Expected direct mapping with offset"),
}
}
#[test]
fn test_has_mapping_chirho() {
let mapper_chirho = VerseMappingChirho::new_chirho();
assert!(mapper_chirho.has_mapping_chirho("KJV", "Catholic"));
assert!(mapper_chirho.has_mapping_chirho("KJV", "LXX"));
assert!(mapper_chirho.has_mapping_chirho("KJV", "Leningrad"));
}
#[test]
fn test_map_range_chirho() {
let mapper_chirho = VerseMappingChirho::new_chirho();
let results_chirho = mapper_chirho.map_range_chirho("Genesis", 1, 1, 3, "KJV", "Catholic");
assert_eq!(results_chirho.len(), 3);
}
#[test]
fn test_global_mapper_chirho() {
let mapper_chirho = global_mapper_chirho();
assert!(mapper_chirho.has_mapping_chirho("KJV", "Catholic"));
}
}