Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
25 changes: 11 additions & 14 deletions IsncsciAlgorithm.sln
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30110.0
# Visual Studio Version 16
VisualStudioVersion = 16.0.30804.86
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rhi.Isncsci", "Rhi.Isncsci\Rhi.Isncsci.csproj", "{CFD110C1-CE77-40FD-932B-3EF70F8F56EE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rhi.Isncsci.Tests", "Rhi.Isncsci.Tests\Rhi.Isncsci.Tests.csproj", "{A354D889-1BE4-4439-9FD9-E4DB9E470B7D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rhi.Isncsci.Core", "Rhi.Isncsci.Core\Rhi.Isncsci.Core.csproj", "{98729432-48E7-424C-9A0D-3487A4F16B90}"
EndProject
Global
GlobalSection(TeamFoundationVersionControl) = preSolution
SccNumberOfProjects = 3
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
SccTeamFoundationServer = https://eddiemachete.visualstudio.com/defaultcollection
SccLocalPath0 = .
SccProjectUniqueName1 = Rhi.Isncsci\\Rhi.Isncsci.csproj
SccProjectName1 = Rhi.Isncsci
SccLocalPath1 = Rhi.Isncsci
SccProjectUniqueName2 = Rhi.Isncsci.Tests\\Rhi.Isncsci.Tests.csproj
SccProjectName2 = Rhi.Isncsci.Tests
SccLocalPath2 = Rhi.Isncsci.Tests
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Expand All @@ -33,8 +23,15 @@ Global
{A354D889-1BE4-4439-9FD9-E4DB9E470B7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A354D889-1BE4-4439-9FD9-E4DB9E470B7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A354D889-1BE4-4439-9FD9-E4DB9E470B7D}.Release|Any CPU.Build.0 = Release|Any CPU
{98729432-48E7-424C-9A0D-3487A4F16B90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98729432-48E7-424C-9A0D-3487A4F16B90}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98729432-48E7-424C-9A0D-3487A4F16B90}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98729432-48E7-424C-9A0D-3487A4F16B90}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {80A3FAA5-1BCF-4618-9B21-FFE1B06C7D7D}
EndGlobalSection
EndGlobal
762 changes: 762 additions & 0 deletions Rhi.Isncsci.Core/Algorithm.cs

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions Rhi.Isncsci.Core/BinaryObservation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;

namespace Rhi.Isncsci.Core
{
[Flags]
public enum BinaryObservation
{
None = 0x0,
Yes = 0x1,
No = 0x2,
NT = 0x4
}
}
233 changes: 233 additions & 0 deletions Rhi.Isncsci.Core/NeurologyForm.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rhi.Isncsci.Core
{
public class NeurologyForm
{
private static readonly string[] LevelNames = new[]
{
"C2", "C3", "C4", "C5", "C6", "C7", "C8", "T1", "T2", "T3"
, "T4", "T5", "T6", "T7", "T8", "T9", "T10", "T11", "T12",
"L1", "L2", "L3", "L4", "L5", "S1", "S2", "S3", "S4_5"
};

private readonly static string[] KeyMuscles = new[] { "C5", "C6", "C7", "C8", "T1", "L2", "L3", "L4", "L5", "S1" };
private readonly Dictionary<string, NeurologyFormLevel> _levels;
private static readonly Regex NtRegex = new Regex(@"\bNT\b", RegexOptions.IgnoreCase);
private static readonly Regex NonSciImpairmentRegex = new Regex(".+[!]");
private static readonly Regex NonSciImpairmentFlagsRegex = new Regex("[\\*!]");

private const int NormalMotorValue = 5;
private const int NormalSensoryValue = 2;

public NeurologyFormLevel C1 { get; protected set; }

public BinaryObservation AnalContraction { get; set; }
public BinaryObservation AnalSensation { get; set; }
public NeurologyFormLevel RightLowestNonKeyMuscleWithMotorFunction { get; protected set; }
public NeurologyFormLevel LeftLowestNonKeyMuscleWithMotorFunction { get; protected set; }

public NeurologyForm()
{
C1 = new NeurologyFormLevel
{
Ordinal = 0,
IsKeyMuscle = false,
IsLowerMuscle = false,
Name = "C1",
Previous = null,
RightMotorName = "5",
RightMotorValue = 5,
LeftMotorName = "5",
LeftMotorValue = 5,
RightTouchName = "2",
RightTouchValue = 2,
LeftTouchName = "2",
LeftTouchValue = 2,
RightPrickName = "2",
RightPrickValue = 2,
LeftPrickName = "2",
LeftPrickValue = 2
};

_levels = new Dictionary<string, NeurologyFormLevel>();

var previousLevel = C1;

for (var i = 0; i < LevelNames.Length; i++)
{
var name = LevelNames[i];

var currentLevel = new NeurologyFormLevel
{
IsKeyMuscle = KeyMuscles.Contains(name),
IsLowerMuscle = (i >= 20 && i <= 24),
Name = name,
Ordinal = i + 1,
Previous = previousLevel
};

previousLevel.Next = currentLevel;
previousLevel = currentLevel;
_levels.Add(name, currentLevel);
}
}

public void SetRightLowestNonKeyMuscleWithMotorFunction(string levelName)
{
if (string.IsNullOrEmpty(levelName))
return;

var key = levelName.ToUpper();

if (!_levels.ContainsKey(key))
return;

if (RightLowestNonKeyMuscleWithMotorFunction != null)
RightLowestNonKeyMuscleWithMotorFunction.HasOtherRightMotorFunction = false;

RightLowestNonKeyMuscleWithMotorFunction = _levels[key];
RightLowestNonKeyMuscleWithMotorFunction.HasOtherRightMotorFunction = true;
}

public void SetLeftLowestNonKeyMuscleWithMotorFunction(string levelName)
{
if (string.IsNullOrEmpty(levelName))
return;

var key = levelName.ToUpper();

if (!_levels.ContainsKey(key))
return;

if (LeftLowestNonKeyMuscleWithMotorFunction != null)
LeftLowestNonKeyMuscleWithMotorFunction.HasOtherLeftMotorFunction = false;

LeftLowestNonKeyMuscleWithMotorFunction = _levels[key];
LeftLowestNonKeyMuscleWithMotorFunction.HasOtherLeftMotorFunction = true;
}

/// <summary>
///
/// </summary>
/// <param name="index"></param>
/// <returns>Neurology level at the specified index.</returns>
public NeurologyFormLevel GetLevelAt(int index)
{
return index >= 0 && index < _levels.Count ? _levels.ElementAt(index).Value : null;
}

/// <summary>
/// Returns the neurology level based on a level name. E.g. C2,C3,C4...S1,S2,S3,S4_5
/// </summary>
/// <param name="levelName">Lavel name being searched.</param>
/// <returns>Neurology level that matches the specified level name.</returns>
public NeurologyFormLevel GetLevelWithName(string levelName)
{
var key = levelName.ToUpper();

return _levels.ContainsKey(key) ? _levels[key] : null;
}

/// <summary>
/// Updates the values of the neurology level with the specified name.
/// You can pass strings containing values between 0-2 for touch and prick and 0-5 for motor.
/// You can also use the exclamation mark and asterisk at the end of the string to indicate impairment not due to a spinal cord injury.
/// Finally, you can also pass NT to indicate that a value was not testable.
/// </summary>
/// <param name="levelName">Name of the respective neurology level.</param>
/// <param name="rightTouchName">Right touch</param>
/// <param name="leftTouchName">Left touch</param>
/// <param name="rightPrickName">Right Prick</param>
/// <param name="leftPrickName">Left prick</param>
/// <param name="rightMotorName">Right motor</param>
/// <param name="leftMotorName">Left motor</param>
/// <returns></returns>
public NeurologyForm UpdateLevelAt(string levelName, string rightTouchName, string leftTouchName,
string rightPrickName, string leftPrickName, string rightMotorName, string leftMotorName)
{
var level = GetLevelWithName(levelName);

if (level != null)
UpdateLevel(level, rightTouchName, leftTouchName, rightPrickName, leftPrickName, rightMotorName, leftMotorName);

return this;
}

private static int GetDermatomeValue(string text, int normalValue)
{
if (text.ToUpper() == "NT*")
return normalValue;

int value;
int.TryParse(NonSciImpairmentFlagsRegex.Replace(text, string.Empty), out value);

return value;
}

private static void UpdateLevel(NeurologyFormLevel level, string rightTouchName, string leftTouchName,
string rightPrickName, string leftPrickName, string rightMotorName, string leftMotorName)
{
// Right Touch
level.RightTouchName = rightTouchName;
level.RightTouchValue = GetDermatomeValue(rightTouchName, NormalSensoryValue);
level.RightTouchImpairmentNotDueToSci = NonSciImpairmentRegex.IsMatch(rightTouchName);

// Left Touch
level.LeftTouchName = leftTouchName;
level.LeftTouchValue = GetDermatomeValue(leftTouchName, NormalSensoryValue);
level.LeftTouchImpairmentNotDueToSci = NonSciImpairmentRegex.IsMatch(leftTouchName);

// Right Prick
level.RightPrickName = rightPrickName;
level.RightPrickValue = GetDermatomeValue(rightPrickName, NormalSensoryValue);
level.RightPrickImpairmentNotDueToSci = NonSciImpairmentRegex.IsMatch(rightPrickName);

// Left Prick
level.LeftPrickName = leftPrickName;
level.LeftPrickValue = GetDermatomeValue(leftPrickName, NormalSensoryValue);
level.LeftPrickImpairmentNotDueToSci = NonSciImpairmentRegex.IsMatch(leftPrickName);

// Right Motor
level.RightMotorName = rightMotorName;
level.RightMotorValue = GetDermatomeValue(rightMotorName, NormalMotorValue);
level.RightMotorImpairmentNotDueToSci = NonSciImpairmentRegex.IsMatch(rightMotorName);

// Left Motor
level.LeftMotorName = leftMotorName;
level.LeftMotorValue = GetDermatomeValue(leftMotorName, NormalMotorValue);
level.LeftMotorImpairmentNotDueToSci = NonSciImpairmentRegex.IsMatch(leftMotorName);

if (!level.IsKeyMuscle)
{
if ((level.RightTouchValue == 2 || level.RightTouchImpairmentNotDueToSci)
&& (level.RightPrickValue == 2 || level.RightPrickImpairmentNotDueToSci))
{
level.RightMotorName = "5";
level.RightMotorValue = 5;
}
else
{
level.RightMotorName = (NtRegex.IsMatch(level.RightTouchName) || level.RightTouchValue == 2)
&& (NtRegex.IsMatch(level.RightPrickName) || level.RightPrickValue == 2) ? "NT" : "0";
level.RightMotorValue = 0;
}

if ((level.LeftTouchValue == 2 || level.LeftTouchImpairmentNotDueToSci)
&& (level.LeftPrickValue == 2 || level.LeftPrickImpairmentNotDueToSci))
{
level.LeftMotorName = "5";
level.LeftMotorValue = 5;
}
else
{
level.LeftMotorName = (NtRegex.IsMatch(level.LeftTouchName) || level.LeftTouchValue == 2)
&& (NtRegex.IsMatch(level.LeftPrickName) || level.LeftPrickValue == 2) ? "NT" : "0";
level.LeftMotorValue = 0;
}
}
}
}
}
72 changes: 72 additions & 0 deletions Rhi.Isncsci.Core/NeurologyFormLevel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
namespace Rhi.Isncsci.Core
{
public class NeurologyFormLevel
{
public virtual bool IsKeyMuscle { get; set; }
public virtual bool IsLowerMuscle { get; set; }
public virtual bool LeftTouchImpairmentNotDueToSci { get; set; }
public virtual string LeftTouchName { get; set; }
public virtual int LeftTouchValue { get; set; }
public virtual bool LeftPrickImpairmentNotDueToSci { get; set; }
public virtual string LeftPrickName { get; set; }
public virtual int LeftPrickValue { get; set; }
public virtual bool LeftMotorImpairmentNotDueToSci { get; set; }
public virtual bool HasOtherLeftMotorFunction { get; set; }
public virtual string LeftMotorName { get; set; }
public virtual int LeftMotorValue { get; set; }
public virtual string Name { get; set; }
public virtual NeurologyFormLevel Next { get; set; }
//public virtual NeurologyTest NeurologyTest { get; set; }
public virtual int Ordinal { get; set; }
public virtual NeurologyFormLevel Previous { get; set; }
public virtual bool RightTouchImpairmentNotDueToSci { get; set; }
public virtual string RightTouchName { get; set; }
public virtual int RightTouchValue { get; set; }
public virtual bool RightPrickImpairmentNotDueToSci { get; set; }
public virtual string RightPrickName { get; set; }
public virtual int RightPrickValue { get; set; }
public virtual bool RightMotorImpairmentNotDueToSci { get; set; }
public bool HasOtherRightMotorFunction { get; set; }
public virtual string RightMotorName { get; set; }
public virtual int RightMotorValue { get; set; }

public virtual NeurologyFormLevel SetValues(int ordinal, bool isKeyMuscle, bool isLowerMuscle,
string rightTouchName, int rightTouchValue, bool rightTouchImpairmentNotDueToSci,
string leftTouchName, int leftTouchValue, bool leftTouchImpairmentNotDueToSci,
string rightPrickName, int rightPrickValue, bool rightPrickImpairmentNotDueToSci,
string leftPrickName, int leftPrickValue, bool leftPrickImpairmentNotDueToSci,
string rightMotorName, int rightMotorValue, bool rightMotorImpairmentNotDueToSci,
string leftMotorName, int leftMotorValue, bool leftMotorImpairmentNotDueToSci)
{
IsKeyMuscle = isKeyMuscle;
IsLowerMuscle = isLowerMuscle;
Ordinal = ordinal;

RightTouchName = rightPrickName;
RightTouchValue = rightPrickValue;
RightTouchImpairmentNotDueToSci = rightTouchImpairmentNotDueToSci;

LeftTouchName = leftTouchName;
LeftTouchValue = leftTouchValue;
LeftTouchImpairmentNotDueToSci = leftTouchImpairmentNotDueToSci;

RightPrickName = rightPrickName;
RightPrickValue = rightPrickValue;
RightPrickImpairmentNotDueToSci = rightPrickImpairmentNotDueToSci;

LeftPrickName = leftPrickName;
LeftPrickValue = leftPrickValue;
LeftPrickImpairmentNotDueToSci = leftPrickImpairmentNotDueToSci;

RightMotorName = rightMotorName;
RightMotorValue = rightMotorValue;
RightMotorImpairmentNotDueToSci = rightMotorImpairmentNotDueToSci;

LeftMotorName = leftMotorName;
LeftMotorValue = leftMotorValue;
LeftMotorImpairmentNotDueToSci = leftMotorImpairmentNotDueToSci;

return this;
}
}
}
Loading