///|
pub(all) struct NihssInput {
consciousness : Int
questions : Int
commands : Int
gaze : Int
visual : Int
facial : Int
left_arm : Int
right_arm : Int
left_leg : Int
right_leg : Int
ataxia : Int
sensory : Int
language : Int
dysarthria : Int
neglect : Int
} derive(Debug, Eq)
///|
fn validate_nihss_field(
field : String,
value : Int,
high : Int,
) -> ValidationError? {
validate_range(field, value, 0, high)
}
///|
pub fn validate_nihss(input : NihssInput) -> ValidationError? {
match validate_nihss_field("consciousness", input.consciousness, 3) {
Some(err) => Some(err)
None =>
match validate_nihss_field("questions", input.questions, 2) {
Some(err) => Some(err)
None =>
match validate_nihss_field("commands", input.commands, 2) {
Some(err) => Some(err)
None =>
match validate_nihss_field("gaze", input.gaze, 2) {
Some(err) => Some(err)
None =>
match validate_nihss_field("visual", input.visual, 3) {
Some(err) => Some(err)
None =>
match validate_nihss_field("facial", input.facial, 3) {
Some(err) => Some(err)
None =>
match
validate_nihss_field("left_arm", input.left_arm, 4) {
Some(err) => Some(err)
None =>
match
validate_nihss_field(
"right_arm",
input.right_arm,
4,
) {
Some(err) => Some(err)
None =>
match
validate_nihss_field(
"left_leg",
input.left_leg,
4,
) {
Some(err) => Some(err)
None =>
match
validate_nihss_field(
"right_leg",
input.right_leg,
4,
) {
Some(err) => Some(err)
None =>
match
validate_nihss_field(
"ataxia",
input.ataxia,
2,
) {
Some(err) => Some(err)
None =>
match
validate_nihss_field(
"sensory",
input.sensory,
2,
) {
Some(err) => Some(err)
None =>
match
validate_nihss_field(
"language",
input.language,
3,
) {
Some(err) => Some(err)
None =>
match
validate_nihss_field(
"dysarthria",
input.dysarthria,
2,
) {
Some(err) => Some(err)
None =>
validate_nihss_field(
"neglect",
input.neglect,
2,
)
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
///|
pub fn nihss_total(input : NihssInput) -> Int {
input.consciousness +
input.questions +
input.commands +
input.gaze +
input.visual +
input.facial +
input.left_arm +
input.right_arm +
input.left_leg +
input.right_leg +
input.ataxia +
input.sensory +
input.language +
input.dysarthria +
input.neglect
}
///|
pub fn nihss_severity(score : Int) -> Severity {
if score == 0 {
Low
} else if score <= 4 {
Medium
} else if score <= 15 {
High
} else {
Critical
}
}
///|
pub fn score_nihss(input : NihssInput) -> ScoreReport {
let score = nihss_total(input)
report(
"NIHSS",
score,
nihss_severity(score),
"NIHSS quantifies observed neurologic deficit and should be administered with the official instructions.",
[
explanation(
"Consciousness",
input.consciousness,
"Level of consciousness",
),
explanation("Questions", input.questions, "Orientation questions"),
explanation("Commands", input.commands, "Response to commands"),
explanation("Gaze", input.gaze, "Best gaze"),
explanation("Visual", input.visual, "Visual fields"),
explanation("Facial", input.facial, "Facial palsy"),
explanation("Left arm", input.left_arm, "Left arm motor"),
explanation("Right arm", input.right_arm, "Right arm motor"),
explanation("Left leg", input.left_leg, "Left leg motor"),
explanation("Right leg", input.right_leg, "Right leg motor"),
explanation("Ataxia", input.ataxia, "Limb ataxia"),
explanation("Sensory", input.sensory, "Sensory loss"),
explanation("Language", input.language, "Best language"),
explanation("Dysarthria", input.dysarthria, "Dysarthria"),
explanation("Neglect", input.neglect, "Extinction and inattention"),
],
)
}
///|
pub(all) struct FourScoreInput {
eye_response : Int
motor_response : Int
brainstem_reflexes : Int
respiration : Int
} derive(Debug, Eq)
///|
pub fn validate_four_score(input : FourScoreInput) -> ValidationError? {
match validate_range("eye_response", input.eye_response, 0, 4) {
Some(err) => Some(err)
None =>
match validate_range("motor_response", input.motor_response, 0, 4) {
Some(err) => Some(err)
None =>
match
validate_range("brainstem_reflexes", input.brainstem_reflexes, 0, 4) {
Some(err) => Some(err)
None => validate_range("respiration", input.respiration, 0, 4)
}
}
}
}
///|
pub fn four_score_total(input : FourScoreInput) -> Int {
input.eye_response +
input.motor_response +
input.brainstem_reflexes +
input.respiration
}
///|
pub fn four_score_severity(score : Int) -> Severity {
if score <= 4 {
Critical
} else if score <= 8 {
High
} else if score <= 12 {
Medium
} else {
Low
}
}
///|
pub fn score_four(input : FourScoreInput) -> ScoreReport {
let score = four_score_total(input)
report(
"FOUR",
score,
four_score_severity(score),
"FOUR evaluates eye, motor, brainstem, and respiration domains when verbal assessment is limited.",
[
explanation("Eye", input.eye_response, "Eye response domain"),
explanation("Motor", input.motor_response, "Motor response domain"),
explanation(
"Brainstem",
input.brainstem_reflexes,
"Brainstem reflex domain",
),
explanation("Respiration", input.respiration, "Respiration domain"),
],
)
}
///|
pub(all) struct Abcd2Input {
age : Int
systolic_bp : Int
diastolic_bp : Int
unilateral_weakness : Bool
speech_impairment_without_weakness : Bool
symptom_duration_minutes : Int
diabetes : Bool
} derive(Debug, Eq)
///|
pub fn validate_abcd2(input : Abcd2Input) -> ValidationError? {
match validate_range("age", input.age, 0, 150) {
Some(err) => Some(err)
None =>
match validate_range("systolic_bp", input.systolic_bp, 0, 300) {
Some(err) => Some(err)
None =>
match validate_range("diastolic_bp", input.diastolic_bp, 0, 200) {
Some(err) => Some(err)
None =>
validate_range(
"symptom_duration_minutes",
input.symptom_duration_minutes,
0,
10000,
)
}
}
}
}
///|
pub fn abcd2_age_points(value : Int) -> Int {
if value >= 60 {
1
} else {
0
}
}
///|
pub fn abcd2_pressure_points(systolic : Int, diastolic : Int) -> Int {
if systolic >= 140 || diastolic >= 90 {
1
} else {
0
}
}
///|
pub fn abcd2_clinical_points(unilateral : Bool, speech_only : Bool) -> Int {
if unilateral {
2
} else if speech_only {
1
} else {
0
}
}
///|
pub fn abcd2_duration_points(minutes : Int) -> Int {
if minutes >= 60 {
2
} else if minutes >= 10 {
1
} else {
0
}
}
///|
pub fn abcd2_diabetes_points(value : Bool) -> Int {
if value {
1
} else {
0
}
}
///|
pub fn abcd2_severity(score : Int) -> Severity {
if score >= 6 {
Critical
} else if score >= 4 {
High
} else if score >= 2 {
Medium
} else {
Low
}
}
///|
pub fn score_abcd2(input : Abcd2Input) -> ScoreReport {
let age = abcd2_age_points(input.age)
let pressure = abcd2_pressure_points(input.systolic_bp, input.diastolic_bp)
let clinical = abcd2_clinical_points(
input.unilateral_weakness,
input.speech_impairment_without_weakness,
)
let duration = abcd2_duration_points(input.symptom_duration_minutes)
let diabetes = abcd2_diabetes_points(input.diabetes)
let score = age + pressure + clinical + duration + diabetes
report(
"ABCD2",
score,
abcd2_severity(score),
"ABCD2 summarizes early stroke risk domains after a transient ischemic attack; it does not replace evaluation.",
[
explanation("Age", age, "Age at least 60 years"),
explanation(
"Blood pressure", pressure, "Blood pressure at or above 140/90",
),
explanation(
"Clinical features", clinical, "Weakness or isolated speech impairment",
),
explanation("Duration", duration, "Focal symptom duration"),
explanation("Diabetes", diabetes, "Known diabetes"),
],
)
}
///|
pub(all) struct CanadianCtHeadInput {
age : Int
gcs_less_than_15_at_two_hours : Bool
suspected_open_skull_fracture : Bool
signs_of_basal_skull_fracture : Bool
vomiting_episodes : Int
age_at_least_65 : Bool
retrograde_amnesia_minutes : Int
dangerous_mechanism : Bool
anticoagulant_or_antiplatelet : Bool
} derive(Debug, Eq)
///|
pub fn validate_canadian_ct_head(
input : CanadianCtHeadInput,
) -> ValidationError? {
match validate_range("age", input.age, 0, 150) {
Some(err) => Some(err)
None =>
match
validate_range("vomiting_episodes", input.vomiting_episodes, 0, 100) {
Some(err) => Some(err)
None =>
validate_range(
"retrograde_amnesia_minutes",
input.retrograde_amnesia_minutes,
0,
100000,
)
}
}
}
///|
pub fn canadian_ct_head_high_risk_count(input : CanadianCtHeadInput) -> Int {
let skull = if input.suspected_open_skull_fracture { 1 } else { 0 }
let basal = if input.signs_of_basal_skull_fracture { 1 } else { 0 }
let gcs = if input.gcs_less_than_15_at_two_hours { 1 } else { 0 }
skull + basal + gcs
}
///|
pub fn canadian_ct_head_medium_risk_count(input : CanadianCtHeadInput) -> Int {
let vomiting = if input.vomiting_episodes >= 2 { 1 } else { 0 }
let age = if input.age_at_least_65 { 1 } else { 0 }
let memory = if input.retrograde_amnesia_minutes > 30 { 1 } else { 0 }
let mechanism = if input.dangerous_mechanism { 1 } else { 0 }
vomiting + age + memory + mechanism
}
///|
pub fn canadian_ct_head_positive(input : CanadianCtHeadInput) -> Bool {
canadian_ct_head_high_risk_count(input) > 0 ||
canadian_ct_head_medium_risk_count(input) > 0 ||
input.anticoagulant_or_antiplatelet
}
///|
pub fn score_canadian_ct_head(input : CanadianCtHeadInput) -> ScoreReport {
let high = canadian_ct_head_high_risk_count(input)
let medium = canadian_ct_head_medium_risk_count(input)
let medication = if input.anticoagulant_or_antiplatelet { 1 } else { 0 }
let score = high + medium + medication
let severity = if canadian_ct_head_positive(input) { High } else { Low }
report(
"Canadian CT Head Rule",
score,
severity,
"This rule exposes high- and medium-risk criteria for adult minor head injury review; confirm inclusion criteria before use.",
[
explanation("High-risk criteria", high, "High-risk rule count"),
explanation("Medium-risk criteria", medium, "Medium-risk rule count"),
explanation(
"Medication modifier", medication, "Anticoagulant or antiplatelet flag",
),
],
)
}