public static NeurologyFormTotals LoadNeurologyFormTotalsFrom(XDocument xmlDocument) { var totalsXml = xmlDocument.Root.Element("NeurologyFormTotals"); var neurologyFormTotals = new NeurologyFormTotals { LeftPrickContainsNt = bool.Parse(totalsXml.Element("LeftPrickContainsNt").Value), LeftPrickTotal = GetIntValueFrom(totalsXml.Element("LeftPrickTotal").Value), LeftPrickTotalHasImpairmentNotDueToSci = DoesTotalHaveImpairmentNotDueToSci(totalsXml.Element("LeftPrickTotal").Value), LeftTouchContainsNt = bool.Parse(totalsXml.Element("LeftTouchContainsNt").Value), LeftTouchTotal = GetIntValueFrom(totalsXml.Element("LeftTouchTotal").Value), LeftTouchTotalHasImpairmentNotDueToSci = DoesTotalHaveImpairmentNotDueToSci(totalsXml.Element("LeftTouchTotal").Value), LeftLowerMotorContainsNt = bool.Parse(totalsXml.Element("LeftLowerMotorContainsNt").Value), LeftLowerMotorTotal = GetIntValueFrom(totalsXml.Element("LeftLowerMotorTotal").Value), LeftLowerMotorTotalHasImpairmentNotDueToSci = DoesTotalHaveImpairmentNotDueToSci(totalsXml.Element("LeftLowerMotorTotal").Value), LeftUpperMotorContainsNt = bool.Parse(totalsXml.Element("LeftUpperMotorContainsNt").Value), LeftUpperMotorTotal = GetIntValueFrom(totalsXml.Element("LeftUpperMotorTotal").Value), LeftUpperMotorTotalHasImpairmentNotDueToSci = DoesTotalHaveImpairmentNotDueToSci(totalsXml.Element("LeftUpperMotorTotal").Value), LowerMotorTotal = GetIntValueFrom(totalsXml.Element("LowerMotorTotal").Value), PrickTotal = GetIntValueFrom(totalsXml.Element("PrickTotal").Value), RightLowerMotorContainsNt = bool.Parse(totalsXml.Element("RightLowerMotorContainsNt").Value), RightLowerMotorTotal = GetIntValueFrom(totalsXml.Element("RightLowerMotorTotal").Value), RightLowerMotorTotalHasImpairmentNotDueToSci = DoesTotalHaveImpairmentNotDueToSci(totalsXml.Element("RightLowerMotorTotal").Value), RightUpperMotorContainsNt = bool.Parse(totalsXml.Element("RightUpperMotorContainsNt").Value), RightUpperMotorTotal = GetIntValueFrom(totalsXml.Element("RightUpperMotorTotal").Value), RightUpperMotorTotalHasImpairmentNotDueToSci = DoesTotalHaveImpairmentNotDueToSci(totalsXml.Element("RightUpperMotorTotal").Value), RightPrickContainsNt = bool.Parse(totalsXml.Element("RightPrickContainsNt").Value), RightPrickTotal = GetIntValueFrom(totalsXml.Element("RightPrickTotal").Value), RightPrickTotalHasImpairmentNotDueToSci = DoesTotalHaveImpairmentNotDueToSci(totalsXml.Element("RightPrickTotal").Value), RightTouchContainsNt = bool.Parse(totalsXml.Element("RightTouchContainsNt").Value), RightTouchTotal = GetIntValueFrom(totalsXml.Element("RightTouchTotal").Value), RightTouchTotalHasImpairmentNotDueToSci = DoesTotalHaveImpairmentNotDueToSci(totalsXml.Element("RightTouchTotal").Value), TouchTotal = GetIntValueFrom(totalsXml.Element("TouchTotal").Value), UpperMotorTotal = GetIntValueFrom(totalsXml.Element("UpperMotorTotal").Value), }; var levelsDictionary = GetLevelsDictionary(); foreach (var value in totalsXml.Element("RightSensory").Value.Split(',').Select(v => v.Trim())) neurologyFormTotals.AddRightSensoryValue(levelsDictionary[value.ToUpper()]); foreach (var value in totalsXml.Element("LeftSensory").Value.Split(',').Select(v => v.Trim())) neurologyFormTotals.AddLeftSensoryValue(levelsDictionary[value.ToUpper()]); foreach (var value in totalsXml.Element("RightMotor").Value.Split(',').Select(v => v.Trim())) neurologyFormTotals.AddRightMotorValue(levelsDictionary[value.ToUpper()]); foreach (var value in totalsXml.Element("LeftMotor").Value.Split(',').Select(v => v.Trim())) neurologyFormTotals.AddLeftMotorValue(levelsDictionary[value.ToUpper()]); foreach (var value in totalsXml.Element("NeurologicalLevelOfInjury").Value.Split(',').Select(v => v.Trim())) neurologyFormTotals.AddNeurologicalLevelOfInjury(levelsDictionary[value.ToUpper()]); foreach (var value in totalsXml.Element("RightSensoryZpp").Value.Split(',').Select(v => v.Trim())) if (!string.IsNullOrEmpty(value)) neurologyFormTotals.AddRightSensoryZppValue(levelsDictionary[value.ToUpper()]); foreach (var value in totalsXml.Element("LeftSensoryZpp").Value.Split(',').Select(v => v.Trim())) if (!string.IsNullOrEmpty(value)) neurologyFormTotals.AddLeftSensoryZppValue(levelsDictionary[value.ToUpper()]); foreach (var value in totalsXml.Element("RightMotorZpp").Value.Split(',').Select(v => v.Trim())) if (!string.IsNullOrEmpty(value)) neurologyFormTotals.AddRightMotorZppValue(levelsDictionary[value.ToUpper()]); foreach (var value in totalsXml.Element("LeftMotorZpp").Value.Split(',').Select(v => v.Trim())) if (!string.IsNullOrEmpty(value)) neurologyFormTotals.AddLeftMotorZppValue(levelsDictionary[value.ToUpper()]); foreach (var value in totalsXml.Element("AsiaImpairmentScale").Value.Split(',').Select(v => v.Trim())) neurologyFormTotals.AddAsiaImpairmentScaleValue(value.ToUpper()); return neurologyFormTotals; }
/// <summary> /// Recursive method which iterates through the values in a nuerology form while it updates the totals generating the results produced by the algorithm. /// </summary> /// <param name="neurologyForm">Form being evaluated.</param> /// <param name="totals">Brand new totals object where the results are to be stored.</param> /// <param name="level">Current neurology level being evaluated</param> /// <param name="nextNonKeyMuscleShouldBeRightMotor">Flag used to evaluate the Kathy Collins condition on the right motor results.</param> /// <param name="nextNonKeyMuscleShouldBeLeftMotor">Flag used to evaluate the Kathy Collins condition on the left motor results.</param> private static void UpdateTotalsWithLevelAt(NeurologyForm neurologyForm, NeurologyFormTotals totals, NeurologyFormLevel level, bool nextNonKeyMuscleShouldBeRightMotor, bool nextNonKeyMuscleShouldBeLeftMotor) { totals.RightTouchTotal += level.RightTouchValue; totals.LeftTouchTotal += level.LeftTouchValue; totals.RightPrickTotal += level.RightPrickValue; totals.LeftPrickTotal += level.LeftPrickValue; if (level.IsKeyMuscle) { if (level.IsLowerMuscle) { if (level.RightMotorImpairmentNotDueToSci && !totals.RightLowerMotorTotalHasImpairmentNotDueToSci) totals.RightLowerMotorTotalHasImpairmentNotDueToSci = true; if (level.LeftMotorImpairmentNotDueToSci && !totals.LeftLowerMotorTotalHasImpairmentNotDueToSci) totals.LeftLowerMotorTotalHasImpairmentNotDueToSci = true; if (NtRegex.IsMatch(level.RightMotorName) && !level.RightMotorImpairmentNotDueToSci) totals.RightLowerMotorContainsNt = true; if (NtRegex.IsMatch(level.LeftMotorName) && !level.LeftMotorImpairmentNotDueToSci) totals.LeftLowerMotorContainsNt = true; } else { if (level.RightMotorImpairmentNotDueToSci && !totals.RightUpperMotorTotalHasImpairmentNotDueToSci) totals.RightUpperMotorTotalHasImpairmentNotDueToSci = true; if (level.LeftMotorImpairmentNotDueToSci && !totals.LeftUpperMotorTotalHasImpairmentNotDueToSci) totals.LeftUpperMotorTotalHasImpairmentNotDueToSci = true; if (NtRegex.IsMatch(level.RightMotorName) && !level.RightMotorImpairmentNotDueToSci) totals.RightUpperMotorContainsNt = true; if (NtRegex.IsMatch(level.LeftMotorName) && !level.LeftMotorImpairmentNotDueToSci) totals.LeftUpperMotorContainsNt = true; } } else { if (nextNonKeyMuscleShouldBeRightMotor) { nextNonKeyMuscleShouldBeRightMotor = false; totals.AddRightMotorValue(level.Previous); if (!totals.RightSensoryHasOnlySoftValues) totals.RightMotorHasOnlySoftValues = false; } if (nextNonKeyMuscleShouldBeLeftMotor) { nextNonKeyMuscleShouldBeLeftMotor = false; totals.AddLeftMotorValue(level.Previous); if (!totals.LeftSensoryHasOnlySoftValues) totals.LeftMotorHasOnlySoftValues = false; } } if (level.RightTouchImpairmentNotDueToSci && !totals.RightTouchTotalHasImpairmentNotDueToSci) totals.RightTouchTotalHasImpairmentNotDueToSci = true; if (level.LeftTouchImpairmentNotDueToSci && !totals.LeftTouchTotalHasImpairmentNotDueToSci) totals.LeftTouchTotalHasImpairmentNotDueToSci = true; if (level.RightPrickImpairmentNotDueToSci && !totals.RightPrickTotalHasImpairmentNotDueToSci) totals.RightPrickTotalHasImpairmentNotDueToSci = true; if (level.LeftPrickImpairmentNotDueToSci && !totals.LeftPrickTotalHasImpairmentNotDueToSci) totals.LeftPrickTotalHasImpairmentNotDueToSci = true; // Check if a column contains any NT value so we can properly format the total presented to the user if (NtRegex.IsMatch(level.RightTouchName) && !level.RightTouchImpairmentNotDueToSci && !totals.RightTouchContainsNt) totals.RightTouchContainsNt = true; if (NtRegex.IsMatch(level.LeftTouchName) && !level.LeftTouchImpairmentNotDueToSci && !totals.LeftTouchContainsNt) totals.LeftTouchContainsNt = true; if (NtRegex.IsMatch(level.RightPrickName) && !level.RightPrickImpairmentNotDueToSci && !totals.RightPrickContainsNt) totals.RightPrickContainsNt = true; if (NtRegex.IsMatch(level.LeftPrickName) && !level.LeftPrickImpairmentNotDueToSci && !totals.LeftPrickContainsNt) totals.LeftPrickContainsNt = true; if (totals.RightSensoryHasOnlySoftValues && ((level.RightTouchValue != 2 && !level.RightTouchImpairmentNotDueToSci) || (level.RightPrickValue != 2 && !level.RightPrickImpairmentNotDueToSci))) { totals.AddRightSensoryValue(level.Previous); if ("S4_5".Equals(level.Name) && (level.RightTouchValue == 2 || NtRegex.IsMatch(level.RightTouchName)) && (level.RightPrickValue == 2 || NtRegex.IsMatch(level.RightPrickName))) { totals.AddRightSensoryValue(level); if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level); } if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level.Previous); if ((level.RightTouchValue != 2 && !NtRegex.IsMatch(level.RightTouchName)) || (level.RightPrickValue != 2 && !NtRegex.IsMatch(level.RightPrickName))) { totals.RightSensoryHasOnlySoftValues = false; totals.NeurologicalLevelOfInjuryHasOnlySoftValues = false; } if (level.IsKeyMuscle) { nextNonKeyMuscleShouldBeRightMotor = true; totals.HasRightCollins = true; } } if (totals.LeftSensoryHasOnlySoftValues && ((level.LeftTouchValue != 2 && !level.LeftTouchImpairmentNotDueToSci) || (level.LeftPrickValue != 2 && !level.LeftPrickImpairmentNotDueToSci))) { totals.AddLeftSensoryValue(level.Previous); if ("S4_5".Equals(level.Name) && (level.LeftTouchValue == 2 || NtRegex.IsMatch(level.LeftTouchName)) && (level.LeftPrickValue == 2 || NtRegex.IsMatch(level.LeftPrickName))) { totals.AddLeftSensoryValue(level); if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level); } if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level.Previous); if ((level.LeftTouchValue != 2 && !NtRegex.IsMatch(level.LeftTouchName)) || (level.LeftPrickValue != 2 && !NtRegex.IsMatch(level.LeftPrickName))) { totals.LeftSensoryHasOnlySoftValues = false; totals.NeurologicalLevelOfInjuryHasOnlySoftValues = false; } if (level.IsKeyMuscle) { nextNonKeyMuscleShouldBeLeftMotor = true; totals.HasLeftCollins = true; } } if (totals.RightMotorHasOnlySoftValues && level.RightMotorValue != 5 && !level.RightMotorImpairmentNotDueToSci) { if (level.IsKeyMuscle && (level.RightMotorValue >= 3 || NtRegex.IsMatch(level.RightMotorName))) { totals.AddRightMotorValue(level); // Check if left won't make the NLI have to be the previous level. // Let the logic for left motor handle the SNL instead if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues && (level.LeftMotorValue > 2 || level.LeftMotorImpairmentNotDueToSci || NtRegex.IsMatch(level.LeftMotorName))) { totals.AddNeurologicalLevelOfInjury(level); if (!NtRegex.IsMatch(level.RightMotorName)) totals.NeurologicalLevelOfInjuryHasOnlySoftValues = false; } } if (level.RightMotorValue < 3 || NtRegex.IsMatch(level.RightMotorName)) { totals.AddRightMotorValue(level.Previous); if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) { totals.AddNeurologicalLevelOfInjury(level.Previous); if (!NtRegex.IsMatch(level.RightMotorName)) totals.NeurologicalLevelOfInjuryHasOnlySoftValues = false; } } if (!NtRegex.IsMatch(level.RightMotorName)) totals.RightMotorHasOnlySoftValues = false; } if (totals.LeftMotorHasOnlySoftValues && level.LeftMotorValue != 5 && !level.LeftMotorImpairmentNotDueToSci) { if (level.IsKeyMuscle && (level.LeftMotorValue >= 3 || NtRegex.IsMatch(level.LeftMotorName))) { totals.AddLeftMotorValue(level); if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level); } if (level.LeftMotorValue < 3 || NtRegex.IsMatch(level.LeftMotorName)) { totals.AddLeftMotorValue(level.Previous); if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level.Previous); } if (!NtRegex.IsMatch(level.LeftMotorName)) { totals.LeftMotorHasOnlySoftValues = false; totals.NeurologicalLevelOfInjuryHasOnlySoftValues = false; } } /* -- RECURSIVE CALL --------------- */ if (level.Next != null) UpdateTotalsWithLevelAt(neurologyForm, totals, level.Next, nextNonKeyMuscleShouldBeRightMotor && totals.RightMotorHasOnlySoftValues, nextNonKeyMuscleShouldBeLeftMotor && totals.LeftMotorHasOnlySoftValues); #region This happens when there are INTACT values ------------------------------------------- if ("S4_5".Equals(level.Name)) { if (totals.RightSensoryHasOnlySoftValues && totals.LeftSensoryHasOnlySoftValues && totals.RightMotorHasOnlySoftValues && totals.LeftMotorHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level); if (totals.RightSensoryHasOnlySoftValues) { totals.AddRightSensoryValue(level); totals.RightSensoryHasOnlySoftValues = false; } if (totals.LeftSensoryHasOnlySoftValues) { totals.AddLeftSensoryValue(level); totals.LeftSensoryHasOnlySoftValues = false; } if (totals.RightMotorHasOnlySoftValues) { totals.AddRightMotorValue(level); totals.RightMotorHasOnlySoftValues = false; } if (totals.LeftMotorHasOnlySoftValues) { totals.AddLeftMotorValue(level); totals.LeftMotorHasOnlySoftValues = false; } } #endregion if (totals.RightSensoryZppHasOnlySoftValues && (!"0".Equals(level.RightTouchName) || !"0".Equals(level.RightPrickName))) { if ((level.RightTouchValue > 0 || level.RightTouchImpairmentNotDueToSci) || (level.RightPrickValue > 0 || level.RightPrickImpairmentNotDueToSci)) totals.RightSensoryZppHasOnlySoftValues = false; totals.AddRightSensoryZppValue(level); } if (totals.LeftSensoryZppHasOnlySoftValues && (!"0".Equals(level.LeftTouchName) || !"0".Equals(level.LeftPrickName))) { if ((level.LeftTouchValue > 0 || level.LeftTouchImpairmentNotDueToSci) || (level.LeftPrickValue > 0 || level.LeftPrickImpairmentNotDueToSci)) totals.LeftSensoryZppHasOnlySoftValues = false; totals.AddLeftSensoryZppValue(level); } if (totals.RightMotorZppHasOnlySoftValues && (level.HasOtherRightMotorFunction || (!"0".Equals(level.RightMotorName) && (level.IsKeyMuscle || totals.RightMotorContains(level.Name))))) { if ((level.RightMotorImpairmentNotDueToSci || level.HasOtherRightMotorFunction || !NtRegex.IsMatch(level.RightMotorName)) && (level.IsKeyMuscle || level.Ordinal < 4 || (level.Ordinal > 25 && !totals.RightUpperMotorContainsNt && !totals.RightLowerMotorContainsNt && !totals.HasRightCollins) || (level.Ordinal > 8 && level.Ordinal < 21 && !totals.RightUpperMotorContainsNt))) totals.RightMotorZppHasOnlySoftValues = false; totals.AddRightMotorZppValue(level); } if (totals.LeftMotorZppHasOnlySoftValues && (level.HasOtherLeftMotorFunction || (!"0".Equals(level.LeftMotorName) && (level.IsKeyMuscle || totals.LeftMotorContains(level.Name))))) { if ((level.LeftMotorImpairmentNotDueToSci || level.HasOtherLeftMotorFunction || !NtRegex.IsMatch(level.LeftMotorName)) && (level.IsKeyMuscle || level.Ordinal < 4 || (level.Ordinal > 25 && !totals.LeftUpperMotorContainsNt && !totals.LeftLowerMotorContainsNt && !totals.HasLeftCollins) || (level.Ordinal > 8 && level.Ordinal < 21 && !totals.LeftUpperMotorContainsNt))) totals.LeftMotorZppHasOnlySoftValues = false; totals.AddLeftMotorZppValue(level); } // Update most Rostral levels with motor function if ((level.IsKeyMuscle || level.HasOtherRightMotorFunction) && totals.MostRostralRightLevelWithMotorFunction == null && (level.RightMotorImpairmentNotDueToSci || level.HasOtherRightMotorFunction || (level.RightMotorValue != 0 && level.IsKeyMuscle))) totals.MostRostralRightLevelWithMotorFunction = level; if ((level.IsKeyMuscle || level.HasOtherLeftMotorFunction) && totals.MostRostralLeftLevelWithMotorFunction == null && (level.LeftMotorImpairmentNotDueToSci || level.HasOtherLeftMotorFunction || (level.LeftMotorValue != 0 && level.IsKeyMuscle))) totals.MostRostralLeftLevelWithMotorFunction = level; // Update most Caudal levels with motor function if ((level.IsKeyMuscle || level.HasOtherRightMotorFunction) && totals.MostCaudalRightLevelWithMotorFunction == null && (!"0".Equals(level.RightMotorName) || level.HasOtherRightMotorFunction)) totals.MostCaudalRightLevelWithMotorFunction = level; if ((level.IsKeyMuscle || level.HasOtherLeftMotorFunction) && totals.MostCaudalLeftLevelWithMotorFunction == null && (!"0".Equals(level.LeftMotorName) || level.HasOtherLeftMotorFunction)) totals.MostCaudalLeftLevelWithMotorFunction = level; if (!level.IsKeyMuscle) return; if (level.IsLowerMuscle) { totals.RightLowerMotorTotal += level.RightMotorValue; totals.LeftLowerMotorTotal += level.LeftMotorValue; } else { totals.RightUpperMotorTotal += level.RightMotorValue; totals.LeftUpperMotorTotal += level.LeftMotorValue; } }