///|
pub struct Catalog {
entries : Array[IcdEntry]
} derive(Debug)
///|
pub fn Catalog::from_entries(
entries : Array[IcdEntry],
) -> Catalog raise CatalogError {
let normalized = entries.map(normalize_catalog_entry)
for i in 0..
if !catalog_has_code(normalized, parent) {
raise CatalogError::MissingReference(entry.code, parent)
}
None => ()
}
for excluded in entry.excludes {
if !catalog_has_code(normalized, excluded) {
raise CatalogError::MissingReference(entry.code, excluded)
}
}
}
{ entries: normalized }
}
///|
pub fn Catalog::len(self : Catalog) -> Int {
self.entries.length()
}
///|
pub fn Catalog::all(self : Catalog) -> Array[IcdEntry] {
self.entries.copy()
}
///|
fn catalog_has_code(entries : Array[IcdEntry], code : String) -> Bool {
entries.any(fn(entry) { entry.code == code })
}
///|
fn normalize_catalog_entry(entry : IcdEntry) -> IcdEntry raise CatalogError {
let code = parse_icd10(entry.code) catch {
_ =>
raise CatalogError::InvalidEntry(
entry.code,
"code is not valid ICD-10 syntax",
)
}
let canonical = code.canonical()
let chapter = find_chapter(code)
if chapter is None || chapter.unwrap().id != entry.chapter_id {
raise CatalogError::InvalidEntry(
canonical, "chapter_id does not match the code range",
)
}
let parent = match entry.parent {
Some(raw) => {
let parent_code = parse_icd10(raw) catch {
_ =>
raise CatalogError::InvalidEntry(
canonical, "parent is not valid ICD-10 syntax",
)
}
let normalized_parent = parent_code.canonical()
if normalized_parent == canonical {
raise CatalogError::InvalidEntry(
canonical, "an entry cannot be its own parent",
)
}
Some(normalized_parent)
}
None => None
}
let excludes = []
for raw in entry.excludes {
let excluded = parse_icd10(raw) catch {
_ =>
raise CatalogError::InvalidEntry(
canonical, "exclusion is not valid ICD-10 syntax",
)
}
excludes.push(excluded.canonical())
}
{
code: canonical,
title: entry.title.trim().to_owned(),
chapter_id: entry.chapter_id.trim().to_owned().to_upper(),
parent,
excludes,
note: entry.note.trim().to_owned(),
}
}
///|
pub fn bundled_catalog() -> Catalog {
let entries = sample_entries()
for entry in representative_entries() {
entries.push(entry)
}
Catalog::from_entries(entries) catch {
_ => panic()
}
}