Implement TimePoint.

This commit is contained in:
Daniel Kraus 2015-07-04 12:09:39 +02:00
parent 5ec85c2237
commit 2bd9c0e696
7 changed files with 338 additions and 2 deletions

View File

@ -63,6 +63,7 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="LineParserTest.cs" /> <Compile Include="LineParserTest.cs" />
<Compile Include="Dictionaries\TestDictionary.cs" /> <Compile Include="Dictionaries\TestDictionary.cs" />
<Compile Include="TimePointTest.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />

66
Tests/TimePointTest.cs Executable file
View File

@ -0,0 +1,66 @@
/* TimePointTest.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 NUnit.Framework;
using zaaReloaded2.Models;
namespace Tests
{
[TestFixture]
class TimePointTest
{
[Test]
public void ParseValidTimePoint()
{
TimePoint tp = new TimePoint(
"[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()
{
TimePoint tp = new TimePoint("Aerobe Kultur: Enterokokken ;  Wachstum: 10 ;");
Assert.IsFalse(tp.IsValidTimePoint,
"Bogus paragraph should be invalid TimePoint");
tp.LaurisText = "[22.10.2013 12:30:00]";
Assert.IsFalse(tp.IsValidTimePoint,
"TimePoint should be invalid if it consists of time stamp only.");
}
[Test]
public void ParseTimePointWithDuplicateItems()
{
TimePoint tp = new TimePoint(
"[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.");
Assert.AreEqual(3.7, tp.Items["Kalium"].NumericalValue,
"TimePoint does not use last occurrence of 'Kalium'.");
}
}
}

View File

@ -0,0 +1,32 @@
/* ItemDictionary.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.Dictionaries
{
/// <summary>
/// A dictionary of <see cref="LabItem"/>s.
/// </summary>
public interface IItemDictionary : IDictionary<string, Models.LabItem>
{
void Merge(IItemDictionary otherItemDictionary);
}
}

View File

@ -0,0 +1,41 @@
/* ItemDictionary.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.Models;
namespace zaaReloaded2.Dictionaries
{
public class ItemDictionary : SortedDictionary<string, LabItem>, IItemDictionary
{
/// <summary>
/// Adds all key-value pairs contained in <paramref name="otherItemDictionary"/>
/// to this dictionary, overwriting existing values.
/// </summary>
/// <param name="otherItemDictionary"></param>
public void Merge(IItemDictionary otherItemDictionary)
{
foreach (KeyValuePair<string, LabItem> kvp in otherItemDictionary)
{
this[kvp.Key] = kvp.Value;
}
}
}
}

View File

@ -21,6 +21,7 @@ using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using zaaReloaded2.Dictionaries;
namespace zaaReloaded2.Models namespace zaaReloaded2.Models
{ {
@ -35,7 +36,7 @@ namespace zaaReloaded2.Models
/// <summary> /// <summary>
/// Gets a collection of <see cref="LabItem"/>s found in this paragraph. /// Gets a collection of <see cref="LabItem"/>s found in this paragraph.
/// </summary> /// </summary>
public IDictionary<string, LabItem> Items { get; private set; } public IItemDictionary Items { get; private set; }
/// <summary> /// <summary>
/// Gets the caption that was extracted from the <see cref="OriginalParagraph"/>, /// Gets the caption that was extracted from the <see cref="OriginalParagraph"/>,
@ -97,7 +98,7 @@ namespace zaaReloaded2.Models
Match m = _expectedFormat.Match(OriginalParagraph); Match m = _expectedFormat.Match(OriginalParagraph);
if (m.Success) if (m.Success)
{ {
Items = new Dictionary<string, LabItem>(); Items = new ItemDictionary();
if (m.Groups["caption"].Success) if (m.Groups["caption"].Success)
{ {
Caption = m.Groups["caption"].Value.Trim(new char[] {' ', ':'}); Caption = m.Groups["caption"].Value.Trim(new char[] {' ', ':'});

192
zaaReloaded2/Models/TimePoint.cs Executable file
View File

@ -0,0 +1,192 @@
/* 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.Models
{
/// <summary>
/// Represents all Lauris items for a given time point.
/// </summary>
public class TimePoint
{
#region Properties
/// <summary>
/// Gets or sets the original Lauris text for this timepoint.
/// </summary>
public string LaurisText
{
[DebuggerStepThrough]
get
{
return String.Join(Environment.NewLine, Paragraphs);
}
set
{
if (!String.IsNullOrEmpty(value))
{
Paragraphs = value.Split(
new string[] { Environment.NewLine },
StringSplitOptions.None);
ParseParagraphs();
}
}
}
/// <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 TimePoint(string laurisTest)
: this()
{
_parameterDictionary = null;
_unitDictionary = null;
LaurisText = laurisTest;
}
public TimePoint(
string laurisTest,
ParameterDictionary parameterDictionary,
UnitDictionary unitDictionary)
: this()
{
_parameterDictionary = parameterDictionary;
_unitDictionary = unitDictionary;
LaurisText = laurisTest;
}
#endregion
#region Private methods
/// <summary>
/// Analyzes each Lauris paragraph in this time point, sets the date
/// and time, and collects LabItem data.
/// </summary>
/// <returns>True if the LaurisText has time stamp in the first paragraphs
/// and contains <see cref="LabItem"/>s in the others.</returns>
bool ParseParagraphs()
{
Items = new ItemDictionary();
if (Paragraphs.Length > 0)
{
if (!ParseTimeStamp()) return false;
LaurisParagraph lp;
if (IsValidTimePoint)
{
for (int i = 1; i < Paragraphs.Length; i++)
{
lp = new LaurisParagraph(
Paragraphs[i],
_parameterDictionary,
_unitDictionary);
if (lp.IsLaurisParagraph)
{
Items.Merge(lp.Items);
}
}
}
IsValidTimePoint = Items.Count > 0;
}
return true;
}
/// <summary>
/// Analyzes the date and time information that is expected to be
/// in the first paragraph.
/// </summary>
/// <returns>True if the LaurisText contains a time stamp in the
/// first paragraph.</returns>
bool ParseTimeStamp()
{
if (Paragraphs.Length == 0)
throw new InvalidOperationException("The time point has no paragraphs.");
Match m = _dateStampRegex.Match(Paragraphs[0]);
bool success = false;
if (m.Success)
{
DateTime dt;
success = DateTime.TryParseExact(
m.Groups["datetime"].Value,
"dd.MM.yyyy HH:mm",
CultureInfo.InvariantCulture,
DateTimeStyles.AllowWhiteSpaces,
out dt);
TimeStamp = dt;
}
IsValidTimePoint = success;
return success;
}
void AddItems(IItemDictionary items)
{
}
#endregion
#region Private fields
/// <summary>
/// A regular expression that matches the time stamp in the first
/// paragraph of a LaurisText.
/// </summary>
static readonly Regex _dateStampRegex = new Regex(
@"^\s*\[?\s*(?<datetime>\d\d\.\d\d\.\d\d\d\d\s+\d\d:\d\d)");
ParameterDictionary _parameterDictionary;
UnitDictionary _unitDictionary;
#endregion
}
}

View File

@ -161,12 +161,15 @@
--> -->
<ItemGroup> <ItemGroup>
<Compile Include="Dictionaries\DictionaryBase.cs" /> <Compile Include="Dictionaries\DictionaryBase.cs" />
<Compile Include="Dictionaries\IItemDictionary.cs" />
<Compile Include="Dictionaries\ItemDictionary.cs" />
<Compile Include="Dictionaries\LineParser.cs" /> <Compile Include="Dictionaries\LineParser.cs" />
<Compile Include="Dictionaries\ParameterDictionary.cs" /> <Compile Include="Dictionaries\ParameterDictionary.cs" />
<Compile Include="Dictionaries\UnitDictionary.cs" /> <Compile Include="Dictionaries\UnitDictionary.cs" />
<Compile Include="Models\LabItem.cs" /> <Compile Include="Models\LabItem.cs" />
<Compile Include="Models\LaurisParagraph.cs" /> <Compile Include="Models\LaurisParagraph.cs" />
<Compile Include="Models\Material.cs" /> <Compile Include="Models\Material.cs" />
<Compile Include="Models\TimePoint.cs" />
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>