diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 60ff0c4..8a3aaa5 100755 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -63,6 +63,7 @@ + diff --git a/Tests/TimePointTest.cs b/Tests/TimePointTest.cs new file mode 100755 index 0000000..cfd3091 --- /dev/null +++ b/Tests/TimePointTest.cs @@ -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'."); + } + } +} diff --git a/zaaReloaded2/Dictionaries/IItemDictionary.cs b/zaaReloaded2/Dictionaries/IItemDictionary.cs new file mode 100755 index 0000000..9d96c1e --- /dev/null +++ b/zaaReloaded2/Dictionaries/IItemDictionary.cs @@ -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 +{ + /// + /// A dictionary of s. + /// + public interface IItemDictionary : IDictionary + { + void Merge(IItemDictionary otherItemDictionary); + } +} diff --git a/zaaReloaded2/Dictionaries/ItemDictionary.cs b/zaaReloaded2/Dictionaries/ItemDictionary.cs new file mode 100755 index 0000000..56d7482 --- /dev/null +++ b/zaaReloaded2/Dictionaries/ItemDictionary.cs @@ -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, IItemDictionary + { + /// + /// Adds all key-value pairs contained in + /// to this dictionary, overwriting existing values. + /// + /// + public void Merge(IItemDictionary otherItemDictionary) + { + foreach (KeyValuePair kvp in otherItemDictionary) + { + this[kvp.Key] = kvp.Value; + } + } + } +} diff --git a/zaaReloaded2/Models/LaurisParagraph.cs b/zaaReloaded2/Models/LaurisParagraph.cs index 3983c0e..01937b9 100755 --- a/zaaReloaded2/Models/LaurisParagraph.cs +++ b/zaaReloaded2/Models/LaurisParagraph.cs @@ -21,6 +21,7 @@ using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Text.RegularExpressions; +using zaaReloaded2.Dictionaries; namespace zaaReloaded2.Models { @@ -35,7 +36,7 @@ namespace zaaReloaded2.Models /// /// Gets a collection of s found in this paragraph. /// - public IDictionary Items { get; private set; } + public IItemDictionary Items { get; private set; } /// /// Gets the caption that was extracted from the , @@ -97,7 +98,7 @@ namespace zaaReloaded2.Models Match m = _expectedFormat.Match(OriginalParagraph); if (m.Success) { - Items = new Dictionary(); + Items = new ItemDictionary(); if (m.Groups["caption"].Success) { Caption = m.Groups["caption"].Value.Trim(new char[] {' ', ':'}); diff --git a/zaaReloaded2/Models/TimePoint.cs b/zaaReloaded2/Models/TimePoint.cs new file mode 100755 index 0000000..f7f2705 --- /dev/null +++ b/zaaReloaded2/Models/TimePoint.cs @@ -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 +{ + /// + /// Represents all Lauris items for a given time point. + /// + public class TimePoint + { + #region Properties + + /// + /// Gets or sets the original Lauris text for this timepoint. + /// + 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(); + } + } + } + + /// + /// Gets an array of paragraphs in this LaurisText. + /// + public string[] Paragraphs { get; private set; } + + /// + /// Is true if the LaurisText has time stamp in the first + /// paragraph and s in the others. + /// + public bool IsValidTimePoint { get; private set; } + + /// + /// Gets the date and time information for this TimePoint. + /// If IsValidTimePoint is false, the value of TimeStamp + /// is undefined. + /// + public DateTime TimeStamp { get; private set; } + + /// + /// Returns a sorted dictionary of all s found in + /// the . If a laboratory parameter occurs more + /// than once, only the last occurrence is saved. + /// + 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 + + /// + /// Analyzes each Lauris paragraph in this time point, sets the date + /// and time, and collects LabItem data. + /// + /// True if the LaurisText has time stamp in the first paragraphs + /// and contains s in the others. + 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; + } + + /// + /// Analyzes the date and time information that is expected to be + /// in the first paragraph. + /// + /// True if the LaurisText contains a time stamp in the + /// first paragraph. + 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 + + /// + /// A regular expression that matches the time stamp in the first + /// paragraph of a LaurisText. + /// + static readonly Regex _dateStampRegex = new Regex( + @"^\s*\[?\s*(?\d\d\.\d\d\.\d\d\d\d\s+\d\d:\d\d)"); + ParameterDictionary _parameterDictionary; + UnitDictionary _unitDictionary; + + #endregion + } +} diff --git a/zaaReloaded2/zaaReloaded2.csproj b/zaaReloaded2/zaaReloaded2.csproj index 0ec9ef0..fdd98af 100755 --- a/zaaReloaded2/zaaReloaded2.csproj +++ b/zaaReloaded2/zaaReloaded2.csproj @@ -161,12 +161,15 @@ --> + + + Code