Refactor: Separate concerns.

This commit is contained in:
Daniel Kraus 2015-07-06 15:48:43 +02:00
parent 2bd9c0e696
commit 2cf31914dd
19 changed files with 492 additions and 259 deletions

View File

@ -1,4 +1,4 @@
/* LabItemTest.cs
/* LaurisItemTest.cs
* part of zaaReloaded2
*
* Copyright 2015 Daniel Kraus
@ -20,12 +20,13 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using zaaReloaded2.Models;
using zaaReloaded2.LabModel;
using zaaReloaded2.Importer.ZaaImporter;
namespace Tests
namespace Tests.Importer.ZaaImporter
{
[TestFixture]
class LabItemTest
class LaurisItemTest
{
[Test]
[TestCase("Natrium: 139 [135 - 145] mmol/l", "Natrium", 139, "mmol/l", 135, 145, true)]
@ -34,7 +35,7 @@ namespace Tests
string laurisString, string name, double value,
string unit, double lowerLimit, double upperLimit, bool isNormal)
{
LabItem i = new LabItem(laurisString);
LaurisItem i = new LaurisItem(laurisString);
Assert.AreEqual(name, i.Name, "Name");
Assert.AreEqual(unit, i.Unit, "Unit");
Assert.IsTrue(i.IsNumerical, "IsNumerical");
@ -52,7 +53,7 @@ namespace Tests
string laurisString, string name, double value,
string unit, double lowerLimit, bool isNormal)
{
LabItem i = new LabItem(laurisString);
LaurisItem i = new LaurisItem(laurisString);
Assert.AreEqual(name, i.Name, "Name");
Assert.AreEqual(unit, i.Unit, "Unit");
Assert.IsTrue(i.IsNumerical, "IsNumerical");
@ -69,7 +70,7 @@ namespace Tests
string laurisString, string name, double value,
string unit, double upperLimit, bool isNormal)
{
LabItem i = new LabItem(laurisString);
LaurisItem i = new LaurisItem(laurisString);
Assert.AreEqual(name, i.Name, "Name");
Assert.AreEqual(unit, i.Unit, "Unit");
Assert.IsTrue(i.IsNumerical, "IsNumerical");
@ -87,7 +88,7 @@ namespace Tests
string laurisString, string name, double value,
string unit)
{
LabItem i = new LabItem(laurisString);
LaurisItem i = new LaurisItem(laurisString);
Assert.AreEqual(name, i.Name, "Name");
Assert.AreEqual(unit, i.Unit, "Unit");
Assert.IsTrue(i.IsNumerical, "IsNumerical");
@ -101,14 +102,14 @@ namespace Tests
public void ParseLaurisNonNumericNoNormal(
string laurisString, string name, string value)
{
LabItem i = new LabItem(laurisString);
LaurisItem i = new LaurisItem(laurisString);
Assert.AreEqual(name, i.Name, "Name");
Assert.AreEqual(value, i.Value, "Value");
Assert.IsTrue(String.IsNullOrEmpty(i.Unit), "Unit should be a null string");
Assert.IsFalse(i.HasLimits, "HasLimits");
Assert.IsFalse(i.HasLowerLimit, "HasLowerLimit");
Assert.IsFalse(i.HasUpperLimit, "HasUpperLimit");
// TODO: Define the behavior of LabItem.IsNormal if no normal value known
// TODO: Define the behavior of LaurisItem.IsNormal if no normal value known
}
[TestCase("Erythrozyten (U): + [negativ]", "Erythrozyten (U)", "+", "negativ", false)]
@ -116,7 +117,7 @@ namespace Tests
public void ParseLaurisNonNumericWithNormal(
string laurisString, string name, string value, string normal, bool isNormal)
{
LabItem i = new LabItem(laurisString);
LaurisItem i = new LaurisItem(laurisString);
Assert.AreEqual(name, i.Name, "Name");
Assert.AreEqual(value, i.Value, "Value");
Assert.AreEqual(normal, i.Normal, "Normal");
@ -124,7 +125,7 @@ namespace Tests
Assert.IsFalse(i.HasLimits, "HasLimits");
Assert.IsFalse(i.HasLowerLimit, "HasLowerLimit");
Assert.IsFalse(i.HasUpperLimit, "HasUpperLimit");
// TODO: Define the behavior of LabItem.IsNormal if no normal value known
// TODO: Define the behavior of LaurisItem.IsNormal if no normal value known
}
[TestCase("Albumin (SU)/die: 149.9 [<= 30] mg/d; ", Material.SU)]
@ -132,7 +133,7 @@ namespace Tests
[TestCase("Cystatin C (N Latex): 2.37 [0.57 - 0.96] mg/l; ", Material.B)]
public void ParseLaurisMaterial(string laurisString, Material expectedMaterial)
{
LabItem i = new LabItem(laurisString);
LaurisItem i = new LaurisItem(laurisString);
Assert.AreEqual(expectedMaterial, i.Material);
}
}

View File

@ -16,9 +16,10 @@
* limitations under the License.
*/
using NUnit.Framework;
using zaaReloaded2.Models;
using zaaReloaded2.LabModel;
using zaaReloaded2.Importer.ZaaImporter;
namespace Tests
namespace Tests.Importer.ZaaImporter
{
[TestFixture]
class LaurisParagraphTest

View File

@ -1,4 +1,4 @@
/* TimePointTest.cs
/* LaurisTimePointTest.cs
* part of zaaReloaded2
*
* Copyright 2015 Daniel Kraus
@ -20,47 +20,48 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using zaaReloaded2.Models;
using zaaReloaded2.LabModel;
using zaaReloaded2.Importer.ZaaImporter;
namespace Tests
namespace Tests.Importer.ZaaImporter
{
[TestFixture]
class TimePointTest
class LaurisTimePointTest
{
[Test]
public void ParseValidTimePoint()
public void ParseValidLaurisTimePoint()
{
TimePoint tp = new TimePoint(
LaurisTimePoint tp = new LaurisTimePoint(
"[22.10.2013 12:30:00]" + Environment.NewLine +
"Klinische Chemie: Natrium: 139 [135 - 145] mmol/l;  Kalium: 5.2 [3.5 - 5] mmol/l;");
Assert.IsTrue(tp.IsValidTimePoint);
}
[Test]
public void ParseInvalidTimePoints()
public void ParseInvalidLaurisTimePoints()
{
TimePoint tp = new TimePoint("Aerobe Kultur: Enterokokken ;  Wachstum: 10 ;");
LaurisTimePoint tp = new LaurisTimePoint("Aerobe Kultur: Enterokokken ;  Wachstum: 10 ;");
Assert.IsFalse(tp.IsValidTimePoint,
"Bogus paragraph should be invalid TimePoint");
"Bogus paragraph should be invalid LaurisTimePoint");
tp.LaurisText = "[22.10.2013 12:30:00]";
Assert.IsFalse(tp.IsValidTimePoint,
"TimePoint should be invalid if it consists of time stamp only.");
"LaurisTimePoint should be invalid if it consists of time stamp only.");
}
[Test]
public void ParseTimePointWithDuplicateItems()
public void ParseLaurisTimePointWithDuplicateItems()
{
TimePoint tp = new TimePoint(
LaurisTimePoint tp = new LaurisTimePoint(
"[22.10.2013 12:30:00]" + Environment.NewLine +
"Klinische Chemie: Natrium: 139 [135 - 145] mmol/l;  Kalium: 5.2 [3.5 - 5] mmol/l;" + Environment.NewLine +
"Klinische Chemie: Natrium: 142 [135 - 145] mmol/l;  Kalium: 3.7 [3.5 - 5] mmol/l;"
);
Assert.IsTrue(tp.Items.ContainsKey("Kalium"),
"TimePoint should contain 'Kalium' item.");
"LaurisTimePoint should contain 'Kalium' item.");
Assert.AreEqual(3.7, tp.Items["Kalium"].NumericalValue,
"TimePoint does not use last occurrence of 'Kalium'.");
"LaurisTimePoint does not use last occurrence of 'Kalium'.");
}
}
}

View File

@ -34,6 +34,12 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>zaaReloaded2.pfx</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@ -58,16 +64,17 @@
</Choose>
<ItemGroup>
<Compile Include="Dictionaries\DictionaryTest.cs" />
<Compile Include="LabItemTest.cs" />
<Compile Include="LaurisParagraphTest.cs" />
<Compile Include="Importer\ZaaImporter\LaurisItemTest.cs" />
<Compile Include="Importer\ZaaImporter\LaurisParagraphTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="LineParserTest.cs" />
<Compile Include="Dictionaries\TestDictionary.cs" />
<Compile Include="TimePointTest.cs" />
<Compile Include="Importer\ZaaImporter\TimePointTest.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Tests.licenseheader" />
<None Include="zaaReloaded2.pfx" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\zaaReloaded2\zaaReloaded2.csproj">

BIN
Tests/zaaReloaded2.pfx Executable file

Binary file not shown.

View File

@ -25,7 +25,7 @@ namespace zaaReloaded2.Dictionaries
/// <summary>
/// A dictionary of <see cref="LabItem"/>s.
/// </summary>
public interface IItemDictionary : IDictionary<string, Models.LabItem>
public interface IItemDictionary : IDictionary<string, LabModel.LabItem>
{
void Merge(IItemDictionary otherItemDictionary);
}

View File

@ -19,7 +19,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using zaaReloaded2.Models;
using zaaReloaded2.LabModel;
namespace zaaReloaded2.Dictionaries
{

View File

@ -21,7 +21,7 @@ using System.Linq;
using System.Reflection;
using System.Text;
using System.IO;
using zaaReloaded2.Models;
using zaaReloaded2.LabModel;
namespace zaaReloaded2.Dictionaries
{
@ -49,7 +49,7 @@ namespace zaaReloaded2.Dictionaries
/// Looks up the material for a given <paramref name="laurisName"/>.
/// </summary>
/// <param name="laurisName">Lauris item name to look up.</param>
/// <returns><see cref="zaaReloaded2.Models.Material"/> enum; if no material is
/// <returns><see cref="zaaReloaded2.LabModel.Material"/> enum; if no material is
/// found in the dictionary, the default material "S" (serum) is returned.</returns>
public Material GetMaterial(string laurisName)
{

View File

@ -0,0 +1,39 @@
/* IImporter.cs
* part of zaaReloaded2
*
* Copyright 2015 Daniel Kraus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using zaaReloaded2.LabModel;
namespace zaaReloaded2.Importer
{
public interface IImporter
{
/// <summary>
/// Gets the Laboratory resulting from the data import.
/// </summary>
Laboratory Laboratory { get; set; }
/// <summary>
/// Imports laboratory data contained in a string.
/// </summary>
/// <param name="text">String with laboratory data.</param>
void Import(string text);
}
}

View File

@ -18,183 +18,26 @@
using System;
using System.Globalization;
using System.Text.RegularExpressions;
using zaaReloaded2.LabModel;
namespace zaaReloaded2.Models
namespace zaaReloaded2.Importer.ZaaImporter
{
/// <summary>
/// Represents a single laboratory item (e.g., sodium or creatinine).
/// </summary>
public class LabItem
public class LaurisItem : LabItem
{
#region Properties
/// <summary>
/// Gets or sets the original name of the item (as known by Lauris).
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the unit of the item (as known by Lauris).
/// </summary>
public string Unit { get; set; }
/// <summary>
/// Gets or sets the value of the item. This may be a number or a string.
/// </summary>
public string Value { get; set; }
public double NumericalValue
{
get
{
if (IsNumerical)
{
return _numericalValue;
}
else
{
throw new InvalidOperationException(
String.Format("Value '{0}' is not numerical.", Value));
}
}
private set
{
_numericalValue = value;
}
}
public bool IsNumerical
{
get
{
return (Double.TryParse(Value,
NumberStyles.Any,
CultureInfo.InvariantCulture,
out _numericalValue));
}
}
/// <summary>
/// Gets or sets the normal value of the item. Need not be set. This is
/// used for items with nominal values (as opposed to numbers).
/// </summary>
public string Normal { get; set; }
/// <summary>
/// Gets or sets the lower limit of normal.
/// </summary>
public double LowerLimit
{
get
{
return _lowerLimit;
}
set
{
_lowerLimit = value;
HasLowerLimit = true;
}
}
/// <summary>
/// Is true if the item has a lower limit of normal.
/// </summary>
public bool HasLowerLimit { get; private set; }
/// <summary>
/// Gets or sets the upper limit of normal.
/// </summary>
public double UpperLimit
{
get
{
return _upperLimit;
}
set
{
_upperLimit = value;
HasUpperLimit = true;
}
}
/// <summary>
/// Is true if the item has an upper limit of normal.
/// </summary>
public bool HasUpperLimit { get; private set; }
/// <summary>
/// Is true if <see cref="Value"/> is normal.
/// </summary>
public bool IsNormal
{
get
{
if (HasLimits)
{
if (HasLowerLimit && HasUpperLimit)
{
return (LowerLimit <= NumericalValue &&
NumericalValue <= UpperLimit);
}
else
{
if (HasLowerLimit)
{
return (LowerLimit <= NumericalValue);
}
return (NumericalValue <= UpperLimit);
}
}
else
{
return (Value == Normal);
}
}
}
/// <summary>
/// Is true if the item has lower and/or upper limits. Is false if the
/// item does not have limits but a <see cref="Normal"/> value.
/// </summary>
public bool HasLimits
{
get { return (HasLowerLimit || HasUpperLimit); }
}
/// <summary>
/// The original Lauris string from which this lab item was created.
/// </summary>
public string Lauris { get; private set; }
public string LaurisText { get; private set; }
/// <summary>
/// The canonical name of this item, or the Lauris <see cref="Name"/>
/// of the item if no canonical name is known.
/// The original name of this item as known by Lauris
/// </summary>
public string CanonicalName { get; private set; }
/// <summary>
/// Returns the canonical name prefixed with the abbreviation
/// for the material, e.g. "U-Na" for sodium in the spot urine,
/// but only if the material is not blood.
/// </summary>
public string QualifiedCanonicalName
{
get
{
if (Material == Models.Material.B)
{
return CanonicalName;
}
else
{
return String.Format("{0}-{1}", Material.ToString(), CanonicalName);
}
}
}
public bool AlwaysPrintLimits { get; private set; }
public Material Material { get; private set; }
public string OriginalName { get; private set; }
#endregion
@ -203,11 +46,12 @@ namespace zaaReloaded2.Models
/// <summary>
/// Creates an empty LabItem object.
/// </summary>
public LabItem() { }
public LaurisItem() : base() { }
public LabItem(string laurisString)
public LaurisItem(string laurisString)
: this()
{
Lauris = laurisString;
LaurisText = laurisString;
ParseLauris();
DetectMaterial();
}
@ -222,20 +66,16 @@ namespace zaaReloaded2.Models
/// <param name="parameterDictionary">ParameterDictionary that is used
/// to look up the canonical name, material type, and whether or
/// not to always print the reference interval</param>
public LabItem(string laurisString,
public LaurisItem(string laurisString,
Dictionaries.ParameterDictionary parameterDictionary,
Dictionaries.UnitDictionary unitDictionary)
: this(laurisString)
{
if (parameterDictionary != null)
{
CanonicalName = parameterDictionary.GetCanonicalName(Name);
Name = parameterDictionary.GetCanonicalName(OriginalName);
AlwaysPrintLimits = parameterDictionary.GetForceReferenceDisplay(Name);
}
else
{
CanonicalName = Name;
}
if (unitDictionary != null)
{
Unit = unitDictionary.TranslateLaurisUnit(Unit);
@ -248,7 +88,7 @@ namespace zaaReloaded2.Models
/// <summary>
/// Parses the original Lauris string contained in
/// <see cref="Lauris"/>.
/// <see cref="LaurisText"/>.
/// </summary>
void ParseLauris()
{
@ -264,19 +104,20 @@ namespace zaaReloaded2.Models
@"(?<name>[^:]+):\s*(?<value>[\d.]+)\s*(?<limits>\[[^\]]+])?\s*(?<unit>[^;]+)?");
Regex categoricalRegex = new Regex(
@"(?<name>[^:]+):\s*(?<value>[^[;]+)\s*(\[(?<normal>[^\]]+)])?");
if (numericalRegex.IsMatch(Lauris))
if (numericalRegex.IsMatch(LaurisText))
{
match = numericalRegex.Match(Lauris);
match = numericalRegex.Match(LaurisText);
ParseLimits(match);
}
else
{
match = categoricalRegex.Match(Lauris);
match = categoricalRegex.Match(LaurisText);
Normal = match.Groups["normal"].Value.Trim();
}
if (match != null)
{
Name = match.Groups["name"].Value.Trim();
OriginalName = match.Groups["name"].Value.Trim();
Name = OriginalName;
Value = match.Groups["value"].Value.Trim();
Unit = match.Groups["unit"].Value.Trim();
}
@ -333,16 +174,19 @@ namespace zaaReloaded2.Models
/// </example>
void DetectMaterial()
{
Match m = _materialRegex.Match(Name);
// The material is encoded in the original name of the item
// that was produced by Lauris (eg. "Natrium (PU)" for spot
// urine).
Match m = _materialRegex.Match(OriginalName);
if (m.Success)
{
switch (m.Groups["material"].Value.ToUpper())
{
case "SU":
Material = Models.Material.SU;
Material = LabModel.Material.SU;
break;
case "PU":
Material = Models.Material.U;
Material = LabModel.Material.U;
break;
}
}
@ -352,9 +196,6 @@ namespace zaaReloaded2.Models
#region Fields
double _numericalValue;
double _lowerLimit;
double _upperLimit;
static readonly Regex _materialRegex = new Regex(@"\((?<material>(SU|PU))\)");
#endregion

View File

@ -22,8 +22,9 @@ using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using zaaReloaded2.Dictionaries;
using zaaReloaded2.LabModel;
namespace zaaReloaded2.Models
namespace zaaReloaded2.Importer.ZaaImporter
{
/// <summary>
/// Parses an entire Lauris paragraph (such as "Klinische Chemie: ...")
@ -106,8 +107,8 @@ namespace zaaReloaded2.Models
foreach (Capture itemCapture in m.Groups["items"].Captures)
{
LabItem i = new LabItem(itemCapture.Value, _parameterDictionary, _unitDictionary);
Items.Add(i.QualifiedCanonicalName, i);
LaurisItem i = new LaurisItem(itemCapture.Value, _parameterDictionary, _unitDictionary);
Items.Add(i.QualifiedName, i);
}
IsLaurisParagraph = Items.Count > 0;
}

View File

@ -1,4 +1,4 @@
/* TimePoint.cs
/* LaurisTimePoint.cs
* part of zaaReloaded2
*
* Copyright 2015 Daniel Kraus
@ -23,16 +23,28 @@ using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using zaaReloaded2.Dictionaries;
using zaaReloaded2.LabModel;
namespace zaaReloaded2.Models
namespace zaaReloaded2.Importer.ZaaImporter
{
/// <summary>
/// Represents all Lauris items for a given time point.
/// Holds all laboratory items for a given time point.
/// </summary>
public class TimePoint
class LaurisTimePoint : TimePoint
{
#region Properties
/// <summary>
/// Gets an array of paragraphs in this LaurisText.
/// </summary>
public string[] Paragraphs { get; private set; }
/// <summary>
/// Is true if the LaurisText has time stamp in the first
/// paragraph and <see cref="LabItem"/>s in the others.
/// </summary>
public bool IsValidTimePoint { get; private set; }
/// <summary>
/// Gets or sets the original Lauris text for this timepoint.
/// </summary>
@ -55,38 +67,13 @@ namespace zaaReloaded2.Models
}
}
/// <summary>
/// Gets an array of paragraphs in this LaurisText.
/// </summary>
public string[] Paragraphs { get; private set; }
/// <summary>
/// Is true if the LaurisText has time stamp in the first
/// paragraph and <see cref="LabItem"/>s in the others.
/// </summary>
public bool IsValidTimePoint { get; private set; }
/// <summary>
/// Gets the date and time information for this TimePoint.
/// If IsValidTimePoint is false, the value of TimeStamp
/// is undefined.
/// </summary>
public DateTime TimeStamp { get; private set; }
/// <summary>
/// Returns a sorted dictionary of all <see cref="LabItem"/>s found in
/// the <see cref="LaurisText"/>. If a laboratory parameter occurs more
/// than once, only the last occurrence is saved.
/// </summary>
public IItemDictionary Items { get; private set; }
#endregion
#region Constructors
public TimePoint() { }
public LaurisTimePoint() { }
public TimePoint(string laurisTest)
public LaurisTimePoint(string laurisTest)
: this()
{
_parameterDictionary = null;
@ -94,7 +81,7 @@ namespace zaaReloaded2.Models
LaurisText = laurisTest;
}
public TimePoint(
public LaurisTimePoint(
string laurisTest,
ParameterDictionary parameterDictionary,
UnitDictionary unitDictionary)

View File

@ -0,0 +1,54 @@
/* ZaaImporter.cs
* part of zaaReloaded2
*
* Copyright 2015 Daniel Kraus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using zaaReloaded2.LabModel;
namespace zaaReloaded2.Importer.ZaaImporter
{
/// <summary>
/// Imports laboratory items by parsing the Lauris data from a
/// physician's letter.
/// </summary>
public class ZaaImporter : IImporter
{
#region IImporter implementation
public Laboratory Laboratory
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public void Import(string text)
{
throw new NotImplementedException();
}
#endregion
}
}

204
zaaReloaded2/LabModel/LabItem.cs Executable file
View File

@ -0,0 +1,204 @@
/* LabItem.cs
* part of zaaReloaded2
*
* Copyright 2015 Daniel Kraus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Globalization;
using System.Text.RegularExpressions;
namespace zaaReloaded2.LabModel
{
/// <summary>
/// Represents a single laboratory item (e.g., sodium or creatinine).
/// </summary>
public class LabItem
{
#region Properties
/// <summary>
/// Gets or sets the original name of the item (as known by Lauris).
/// </summary>
public string Name { get; protected set; }
/// <summary>
/// Gets or sets the unit of the item (as known by Lauris).
/// </summary>
public string Unit { get; protected set; }
/// <summary>
/// Gets or sets the value of the item. This may be a number or a string.
/// </summary>
public string Value { get; protected set; }
public double NumericalValue
{
get
{
if (IsNumerical)
{
return _numericalValue;
}
else
{
throw new InvalidOperationException(
String.Format("Value '{0}' is not numerical.", Value));
}
}
private set
{
_numericalValue = value;
}
}
public bool IsNumerical
{
get
{
return (Double.TryParse(Value,
NumberStyles.Any,
CultureInfo.InvariantCulture,
out _numericalValue));
}
}
/// <summary>
/// Gets the normal value of the item. Need not be set. This is
/// used for items with nominal values (as opposed to numbers).
/// </summary>
public string Normal { get; protected set; }
/// <summary>
/// Gets or sets the lower limit of normal.
/// </summary>
public double LowerLimit
{
get
{
return _lowerLimit;
}
protected set
{
_lowerLimit = value;
HasLowerLimit = true;
}
}
/// <summary>
/// Is true if the item has a lower limit of normal.
/// </summary>
public bool HasLowerLimit { get; protected set; }
/// <summary>
/// Gets or sets the upper limit of normal.
/// </summary>
public double UpperLimit
{
get
{
return _upperLimit;
}
set
{
_upperLimit = value;
HasUpperLimit = true;
}
}
/// <summary>
/// Is true if the item has an upper limit of normal.
/// </summary>
public bool HasUpperLimit { get; protected set; }
/// <summary>
/// Is true if <see cref="Value"/> is normal.
/// </summary>
public bool IsNormal
{
get
{
if (HasLimits)
{
if (HasLowerLimit && HasUpperLimit)
{
return (LowerLimit <= NumericalValue &&
NumericalValue <= UpperLimit);
}
else
{
if (HasLowerLimit)
{
return (LowerLimit <= NumericalValue);
}
return (NumericalValue <= UpperLimit);
}
}
else
{
return (Value == Normal);
}
}
}
/// <summary>
/// Is true if the item has lower and/or upper limits. Is false if the
/// item does not have limits but a <see cref="Normal"/> value.
/// </summary>
public bool HasLimits
{
get { return (HasLowerLimit || HasUpperLimit); }
}
/// <summary>
/// Returns the canonical name prefixed with the abbreviation
/// for the material, e.g. "U-Na" for sodium in the spot urine,
/// but only if the material is not blood.
/// </summary>
public string QualifiedName
{
get
{
if (Material == LabModel.Material.B)
{
return Name;
}
else
{
return String.Format("{0}-{1}", Material.ToString(), Name);
}
}
}
public bool AlwaysPrintLimits { get; protected set; }
public Material Material { get; protected set; }
#endregion
#region Constructor
public LabItem() { }
#endregion
#region Fields
double _numericalValue;
double _lowerLimit;
double _upperLimit;
#endregion
}
}

View File

@ -0,0 +1,36 @@
/* Laboratory.cs
* part of zaaReloaded2
*
* Copyright 2015 Daniel Kraus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace zaaReloaded2.LabModel
{
/// <summary>
/// Holds laboratory items grouped by time points.
/// </summary>
public class Laboratory
{
#region Properties
public SortedDictionary<DateTime, TimePoint> TimePoints { get; set; }
#endregion
}
}

View File

@ -21,7 +21,7 @@ using System.ComponentModel;
using System.Linq;
using System.Text;
namespace zaaReloaded2.Models
namespace zaaReloaded2.LabModel
{
/// <summary>
/// Enumerates the known materials.

View File

@ -0,0 +1,52 @@
/* TimePoint.cs
* part of zaaReloaded2
*
* Copyright 2015 Daniel Kraus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using zaaReloaded2.Dictionaries;
namespace zaaReloaded2.LabModel
{
/// <summary>
/// Holds laboratory items for a given time point.
/// </summary>
public class TimePoint
{
#region Properties
/// <summary>
/// Gets the date and time information for this TimePoint.
/// If IsValidTimePoint is false, the value of TimeStamp
/// is undefined.
/// </summary>
public DateTime TimeStamp { get; set; }
/// <summary>
/// Returns a sorted dictionary of all <see cref="LabItem"/>s found in
/// the <see cref="LaurisText"/>. If a laboratory parameter occurs more
/// than once, only the last occurrence is saved.
/// </summary>
public IItemDictionary Items { get; set; }
#endregion
}
}

View File

@ -14,6 +14,7 @@ using System.Security;
[assembly: AssemblyCopyright("Copyright © Microsoft 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: InternalsVisibleTo("Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010061ecc0718277dee13e7dae2dad33787a981c9883ba80a659bebbdbec76563e201a7a3a6a5852e01bb5eb328d24d5889244b4626da9af9f93db663565441a3120e3985789e6f2a39289f4eed063725b84152cbef472d9dd2f7495f51dad6c91f4dc6fb7c72cb6bd9381335ac9878ec0a6369e880f35b8eca3063e16468d7704eb")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from

View File

@ -166,10 +166,15 @@
<Compile Include="Dictionaries\LineParser.cs" />
<Compile Include="Dictionaries\ParameterDictionary.cs" />
<Compile Include="Dictionaries\UnitDictionary.cs" />
<Compile Include="Models\LabItem.cs" />
<Compile Include="Models\LaurisParagraph.cs" />
<Compile Include="Models\Material.cs" />
<Compile Include="Models\TimePoint.cs" />
<Compile Include="Importer\IImporter.cs" />
<Compile Include="Importer\ZaaImporter\LaurisItem.cs" />
<Compile Include="Importer\ZaaImporter\LaurisTimePoint.cs" />
<Compile Include="Importer\ZaaImporter\ZaaImporter.cs" />
<Compile Include="LabModel\LabItem.cs" />
<Compile Include="LabModel\Laboratory.cs" />
<Compile Include="Importer\ZaaImporter\LaurisParagraph.cs" />
<Compile Include="LabModel\Material.cs" />
<Compile Include="LabModel\TimePoint.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
@ -207,6 +212,9 @@
<Content Include="Defaults\parameters.txt" />
<Content Include="Defaults\units.txt" />
</ItemGroup>
<ItemGroup>
<Folder Include="Formatter\" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>