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;
        }
예제 #2
0
        /// <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;
            }
        }