diff --git a/HISTORY.md b/HISTORY.md
index 86786f5..2ebb5a3 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,3 +1,12 @@
+Version 2.4.0 (2017-09-18)
+------------------------------------------------------------------------
+
+- Neu: Laborwerte, die vom Ambulanzsystem ausgegeben wurden, können jetzt auch verarbeitet werden.
+- Repariert: Fehlerberichte konnten nicht gesendet werden.
+
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+
Version 2.3.2 (2017-03-06)
------------------------------------------------------------------------
diff --git a/Tests/Importer/ClinicImporter/ClinicImporterTest.cs b/Tests/Importer/ClinicImporter/ClinicImporterTest.cs
new file mode 100755
index 0000000..4ad5609
--- /dev/null
+++ b/Tests/Importer/ClinicImporter/ClinicImporterTest.cs
@@ -0,0 +1,55 @@
+/* ClinicImporterTest.cs
+ * part of zaaReloaded2
+ *
+ * Copyright 2017 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 System.IO;
+using zaa = zaaReloaded2.Importer.ClinicImporter;
+using NUnit.Framework;
+
+namespace Tests.Importer.ClinicImporter
+{
+ [TestFixture]
+ class ClinicImporterTest
+ {
+ ///
+ /// Parses the demo-output.txt file that is built into the assembly.
+ /// Note that this demo text contains seven time points, only six of
+ /// which are distinct. Thus, the two time points with identical time
+ /// stamps should be merged in the .
+ ///
+ [Test]
+ public void ParseTimePoints()
+ {
+ zaa.ClinicImporter importer = TestHelpers.ClinicImporterFromResource();
+ // Only 6 distinct time points (see method documentation above).
+ Assert.AreEqual(5, importer.Laboratory.TimePoints.Count);
+ }
+
+ [Test]
+ public void ParseInvalidInput()
+ {
+ zaa.ClinicImporter importer = new zaa.ClinicImporter();
+ importer.Import("some arbitrary text\r\nthat does not represent\r\na valid lab");
+ Assert.IsFalse(importer.Success);
+ importer.Import("(03.03.1930 13:30:00)\r\n\tNatrium 135 [135 - 145] mmol/l;");
+ Assert.IsTrue(importer.Success);
+ }
+ }
+}
diff --git a/Tests/Importer/ClinicImporter/ClinicItemTest.cs b/Tests/Importer/ClinicImporter/ClinicItemTest.cs
new file mode 100755
index 0000000..40a06c9
--- /dev/null
+++ b/Tests/Importer/ClinicImporter/ClinicItemTest.cs
@@ -0,0 +1,56 @@
+/* LaurisItemTest.cs
+ * part of zaaReloaded2
+ *
+ * Copyright 2017 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.LabModel;
+using zaaReloaded2.Importer.ZaaImporter;
+
+namespace Tests.Importer.ClinicImporter
+{
+ ///
+ /// The ClinicItemTest really just tests the zaaReloaded2.Importer.ZaaImporter.LaurisItem
+ /// class with text formatted by the outpatient clinic system to make sure LaurisItem works
+ /// with clinic-formatted lab data as well.
+ ///
+ [TestFixture]
+ class ClinicItemTest
+ {
+ [Test]
+ [TestCase(" Natrium: 137 [135 - 145] mmol/l", "Natrium", 137, "mmol/l", 135, 145, true)]
+ public void ParseClinicWithBothLimits(
+ string laurisString, string name, double value,
+ string unit, double lowerLimit, double upperLimit, bool isNormal)
+ {
+ LaurisItem i = new LaurisItem(laurisString);
+ Assert.AreEqual(name, i.Name, "Name");
+ Assert.AreEqual(unit, i.Unit, "Unit");
+ Assert.IsFalse(i.IsExtreme, "IsExtreme");
+ Assert.IsTrue(i.IsNumerical, "IsNumerical");
+ Assert.AreEqual(value, i.NumericalValue, "NumericalValue");
+ Assert.AreEqual(lowerLimit, i.LowerLimit, "Lower limit");
+ Assert.AreEqual(upperLimit, i.UpperLimit, "Upper limit");
+ Assert.AreEqual(isNormal, i.IsNormal, "IsNormal");
+ Assert.IsTrue(i.HasLimits, "HasLimits");
+ Assert.IsTrue(i.HasLowerLimit, "HasLowerLimit");
+ Assert.IsTrue(i.HasUpperLimit, "HasUpperLimit");
+ }
+ }
+}
diff --git a/Tests/Importer/ClinicImporter/ClinicLineTest.cs b/Tests/Importer/ClinicImporter/ClinicLineTest.cs
new file mode 100755
index 0000000..f0bbdd1
--- /dev/null
+++ b/Tests/Importer/ClinicImporter/ClinicLineTest.cs
@@ -0,0 +1,45 @@
+/* ClinicLineTest.cs
+ * part of zaaReloaded2
+ *
+ * Copyright 2017 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 NUnit.Framework;
+using zaaReloaded2.LabModel;
+using zaaReloaded2.Importer.ClinicImporter;
+
+namespace Tests.Importer.ClinicImporter
+{
+ [TestFixture]
+ class ClinicLineTest
+ {
+ [Test]
+ public void ParseLine()
+ {
+ string demo = "\tNatrium:\t137\t[135 - 145]\tmmol/l";
+ ClinicLine line = new ClinicLine(demo);
+ Assert.IsTrue(line.IsClinicLine);
+ Assert.AreEqual(137, line.Item.NumericalValue);
+ }
+
+ [Test]
+ public void ParseInvalidLine()
+ {
+ // Missing leading tab
+ string demo = "Natrium:\t137\t[135 - 145]\tmmol/l";
+ ClinicLine line = new ClinicLine(demo);
+ Assert.IsFalse(line.IsClinicLine);
+ }
+ }
+}
diff --git a/Tests/Importer/ClinicImporter/TimePointTest.cs b/Tests/Importer/ClinicImporter/TimePointTest.cs
new file mode 100755
index 0000000..3569617
--- /dev/null
+++ b/Tests/Importer/ClinicImporter/TimePointTest.cs
@@ -0,0 +1,67 @@
+/* TimePointTest.cs
+ * part of zaaReloaded2
+ *
+ * Copyright 2017 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.LabModel;
+using zaaReloaded2.Importer.ClinicImporter;
+
+namespace Tests.Importer.ClinicImporter
+{
+ [TestFixture]
+ class ClinicTimePointTest
+ {
+ [Test]
+ public void ParseValidClinicTimePoint()
+ {
+ ClinicTimePoint tp = new ClinicTimePoint(
+ "(06.09.2017 09:45:00)" + Environment.NewLine +
+ "\tKalium:\t4.6\t[3.5 - 5]\tmmol/l");
+ Assert.IsTrue(tp.IsValidTimePoint);
+ }
+
+ [Test]
+ public void ParseInvalidClinicTimePoints()
+ {
+ ClinicTimePoint tp = new ClinicTimePoint("Mit freundlichen Grüßen");
+ Assert.IsFalse(tp.IsValidTimePoint,
+ "Bogus paragraph should be invalid LaurisTimePoint");
+
+ tp.ClinicText = "(22.10.2013 12:30:00)";
+ Assert.IsFalse(tp.IsValidTimePoint,
+ "LaurisTimePoint should be invalid if it consists of time stamp only.");
+
+ }
+
+ [Test]
+ public void ParseClinicTimePointWithDuplicateItems()
+ {
+ ClinicTimePoint tp = new ClinicTimePoint(
+ "(22.10.2013 12:30:00)" + Environment.NewLine +
+ "\tNatrium:\t137\t[135 - 145]\tmmol/l" + Environment.NewLine +
+ "\tNatrium:\t140\t[135 - 145]\tmmol/l"
+ );
+ Assert.IsTrue(tp.Items.ContainsKey("Natrium"),
+ "LaurisTimePoint should contain 'Natrium' item.");
+ Assert.AreEqual(140, tp.Items["Natrium"].NumericalValue,
+ "LaurisTimePoint does not use last occurrence of 'Natrium'.");
+ }
+ }
+}
diff --git a/Tests/TestHelpers.cs b/Tests/TestHelpers.cs
index a95db83..fa8fff0 100755
--- a/Tests/TestHelpers.cs
+++ b/Tests/TestHelpers.cs
@@ -21,6 +21,7 @@ using System.IO;
using System.Linq;
using System.Text;
using zaaReloaded2.Importer.ZaaImporter;
+using zaaReloaded2.Importer.ClinicImporter;
namespace Tests
{
@@ -38,5 +39,18 @@ namespace Tests
importer.Import(r.ReadToEnd());
return importer;
}
+
+ ///
+ /// Creates a ClinicImporter object and imports demo-output-clinic.txt.
+ ///
+ ///
+ public static ClinicImporter ClinicImporterFromResource()
+ {
+ Stream s = typeof(TestHelpers).Assembly.GetManifestResourceStream("Tests.demo-output-clinic.txt");
+ StreamReader r = new StreamReader(s);
+ ClinicImporter importer = new ClinicImporter();
+ importer.Import(r.ReadToEnd());
+ return importer;
+ }
}
}
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 4c7e441..8f090f7 100755
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -49,11 +49,11 @@
True
- ..\packages\NLog.4.4.3\lib\net40\NLog.dll
+ ..\packages\NLog.4.4.12\lib\net40\NLog.dll
True
-
- ..\packages\NUnit.3.6.1\lib\net40\nunit.framework.dll
+
+ ..\packages\NUnit.3.8.1\lib\net40\nunit.framework.dll
True
@@ -91,6 +91,10 @@
+
+
+
+
@@ -144,6 +148,10 @@
+
+
+
+
diff --git a/Tests/demo-output-clinic.txt b/Tests/demo-output-clinic.txt
new file mode 100755
index 0000000..c36f1da
--- /dev/null
+++ b/Tests/demo-output-clinic.txt
@@ -0,0 +1,90 @@
+# This file contains 5 distinct time points.
+# This leading text should be ignored.
+# DO NOT CHANGE THE FOLLOWING TEXT, LEST THE TESTS WILL FAIL!
+(06.09.2017 09:54:00)
+ Gesamt-Eiweiss (PU): 54 [<= 120] mg/l
+ Gesamt-Eiweiss/Creatinin (PU): 59 [<= 70] mg/g Crea
+ Albumin (PU): 4 [<= 30] mg/l
+ Albumin/Creatinin (PU): 4.4 [<= 30] mg/g Crea
+ Creatinin (PU): 91.1 [29 - 226] mg/dl
+
+(06.09.2017 09:54:00)
+ Erythrozyten (U): negativ [negativ]
+ Leukozyten (U): + [negativ]
+ Nitrit (U): negativ [negativ]
+ Protein (U): negativ [negativ]
+ Glucose (U): negativ [negativ]
+ Ketonkörper (U): + [negativ]
+ Bilirubin (U): negativ [negativ]
+ Urobilinogen (U): negativ [negativ]
+ pH (U): 6.500 [4.8 - 7.4]
+ spezifisches Gewicht (U): 1.015 [1.00 - 1.04] g/ml
+ Erythrozyten (U): 3 [<= 25] Ery/µl
+ Leukozyten (U): 4 [<= 20] Leu/µl
+ Bakterien (U): 193 Bak/µl
+ Plattenepithelien (U): 25 Epi/µl
+ Übergangsepithelien (U): 0 Uge/µl
+ hyaline Zylinder (U): 0 Zyh/µl
+
+(06.09.2017 09:52:00)
+ Gesamt-Eiweiss (SU): < 40 [<= 120] mg/l
+ Albumin (SU): < 3 mg/l
+ a1-Microglobulin (SU): < 5 mg/l
+ Immunglobulin G (SU): < 4 mg/l
+ Sammelzeit (U): 24 h
+ Sammelmenge (U): 3200 ml
+ Calcium (SU): 0.26 mmol/l
+ Calcium (SU)/die: 0.83 [2.5 - 8] mmol/d
+ Creatinin (SU): 30.2 mg/dl
+ Harnstoff (SU): 674 [900 - 3000] mg/dl
+ Harnstoff (SU)/die: 21.6 [<= 35] g/d
+ Kalium (SU): 45.4 [20 - 80] mmol/l
+ Kalium (SU)/die: 145.28 [25 - 125] mmol/d
+ Natrium (SU): 28.9 [54 - 150] mmol/l
+ Natrium (SU)/die: 92.5 [40 - 220] mmol/d
+
+(06.09.2017 09:50:00)
+ Cystatin C (Latex Gen. 2): 1.04 [0.61 - 0.95] mg/l
+
+(06.09.2017 09:45:00)
+ Natrium: 137 [135 - 145] mmol/l
+ Kalium: 4.6 [3.5 - 5] mmol/l
+ Calcium: 2.4 [2.0 - 2.7] mmol/l
+ anorg. Phosphat: 1.29 [0.87 - 1.45] mmol/l
+ Calcium-Phosphat-Produkt: 3.10 [<= 4.4] mmol²/l²
+ glomerul. Filtrationsr. CKD-EP: 62 ml/min /1,73qm
+ glomerul. Filtrationsr. (MDRD): 59 ml/min /1,73qm
+ Creatinin: 1.06 [0 - 0.95] mg/dl
+ Harnstoff: 52.1 [10 - 50] mg/dl
+ Lactat Dehydrogenase: 175 [<= 250] U/l
+ Cholesterin: 180 [130 - 220] mg/dl
+ Triglyceride: 51 [74 - 172] mg/dl
+ LDL - Cholesterin: 91 [0 - 150] mg/dl
+ HDL - Cholesterin: 79 [>= 35] mg/dl
+ Albumin: 4.5 [3.5 - 5.5] g/dl
+ Leukozyten: 4.7 [5 - 10] n*1000/µl
+ Erythrozyten: 4.09 [4 - 5] n*10E6/µl
+ Hämoglobin: 11.9 [12 - 16] g/dl
+ Hämatokrit: 36.6 [35 - 47] %
+ MCV: 89.5 [82 - 96] fl
+ MCH (HbE): 29.1 [27 - 33] pg
+ MCHC: 32.5 [32 - 36] g/dl
+ Thrombozyten: 302 [150 - 450] n*1000/µl
+ Mittleres Plättchenvolumen: 11.3 [9.6 - 12.0] fl
+ Neutrophile: 2.60 [1.8 - 7.2] n*1000/µl
+ Lymphozyten: 1.35 [1 - 4.05] n*1000/µl
+ Monozyten: 0.47 [0.08 - 0.8] n*1000/µl
+ Eosinophile: 0.2 [0.04 - 0.36] n*1000/µl
+ Basophile: 0.1 [0 - 0.08] n*1000/µl
+ % Neutrophile: 55.1 [41 - 70] %
+ % Lymphozyten: 28.7 [25 - 40] %
+ % Monozyten: 10.0 [2 - 8] %
+ % Eosinophile: 4.7 [0.8 - 6.2] %
+ % Basophile: 1.3 [0 - 1] %
+ Unreife Granulozyten: 0.01 n*1000/µl
+ % Unreife Granulozyten: 0.2 %
+ C-reaktives Protein: 0.02 [0 - 0.5] mg/dl
+
+(06.09.2017 09:15:00)
+ TSH: 1.30 [0.3 - 4.0] mIU/l
+ PTH intakt: 106.0 [12 - 65] ng/l
diff --git a/Tests/packages.config b/Tests/packages.config
index 6ce6096..3ba2bfb 100755
--- a/Tests/packages.config
+++ b/Tests/packages.config
@@ -2,7 +2,7 @@
-
-
-
+
+
+
\ No newline at end of file
diff --git a/deploy/VstoAddinInstaller b/deploy/VstoAddinInstaller
index ad374fa..9537574 160000
--- a/deploy/VstoAddinInstaller
+++ b/deploy/VstoAddinInstaller
@@ -1 +1 @@
-Subproject commit ad374fad7ce765ea28289bc5faaa4dd083b914bd
+Subproject commit 953757454eb3f235d8bdb75be613eae79c21a9f0
diff --git a/www/postreport.php b/www/postreport.php
index 4ec082c..75595fb 100644
--- a/www/postreport.php
+++ b/www/postreport.php
@@ -1,53 +1,52 @@
isSMTP();
-$mail->SMTPAuth = true;
-$mail->Host = 'nephrowiki.de';
-$mail->Username = 'zaareloaded@nephrowiki.de';
-$mail->Password = 'ooZ1eiJa';
-// $mail->SMTPSecure = 'tls';
-$mail->Port = 25;
+function sendMail() {
+ $to = 'dk@doktorkraus.de';
+ $headers = "From: \"zaaReloaded\" ";
+ $reportId = $_POST['report_id'];
+ $info = print_r( $_POST, true ); // this will be a string, not an array!
+ $body = <<From = 'zaareloaded@nephrowiki.de';
-$mail->FromName = 'zaaReloaded';
-$mail->addAddress('dk@doktorkraus.de');
-$mail->Subject = "[zaaReloaded] Exception $reportId";
+-----
-if ( $_POST['ccUser'] ) {
- $validMail = filter_var( $_POST['usersMail'], FILTER_VALIDATE_EMAIL );
- $validUser = filter_var( $_POST['usersName'], FILTER_SANITIZE_STRING );
- if ( $validUser ) {
- $validUser = "\"$validUser\" "; // space character deliberately placed
- };
- if ( $validMail ) {
- $mail->addCC($validMail, $validUser);
- };
-};
+Benutzerkommentar:
-$info = print_r( $_POST, true );
-
-$mail->Body = <<send())
-{
- // Must return the report ID to indicate success
- echo($reportId);
+ if ( $_POST['ccUser'] ) {
+ $validMail = filter_var( $_POST['usersMail'], FILTER_VALIDATE_EMAIL );
+ $validUser = filter_var( $_POST['usersName'], FILTER_SANITIZE_STRING );
+ if ( $validUser ) {
+ $validUser = "\"$validUser\" "; // space character deliberately placed
+ };
+ if ( $validMail ) {
+ $headers .= "\r\nCc: $validUser<$validMail>";
+ };
+ };
+ mail($to, "Exception report [$reportId]", $body, $headers);
}
-else
-{
- echo($mail->ErrorInfo);
+
+// =============================================================
+// Begin main script
+// =============================================================
+
+if (!isset($_POST['report_id'])) {
+ http_response_code(400);
+ exit;
}
+
+sendMail();
+// Return the report ID and the issue URL to signal all is well.
+$reportId = $_POST['report_id'];
+$load = "{\"ReportId\": \"$reportId\", \"IssueUrl\": \"https://www.doktorkraus.de/zaareloaded\"}";
+error_log( __FILE__ . ": Load = $load" );
+header('Content-Type: application/json');
+echo $load;
diff --git a/www/versioninfo.txt b/www/versioninfo.txt
index 603c622..da2ae51 100644
--- a/www/versioninfo.txt
+++ b/www/versioninfo.txt
@@ -1,4 +1,4 @@
-2.3.2
+2.4.0
https://doktorkraus.de/zaareloaded/downloads/zaaReloaded-$VERSION.exe
-49d8383326222a88ce447a7c97eba596ffd5782f307f8730ffac83743821949f deploy/releases/zaaReloaded-2.3.2.exe
+e84d6b542c14220965c61beb9406a5500fe3d6e9d7ee6137e15bb13d337808d6 deploy/releases/zaaReloaded-2.4.0.exe
diff --git a/zaaReloaded2/Commands.cs b/zaaReloaded2/Commands.cs
index c6b34d1..b0db793 100755
--- a/zaaReloaded2/Commands.cs
+++ b/zaaReloaded2/Commands.cs
@@ -203,12 +203,14 @@ namespace zaaReloaded2
Word.Window activeWindow = word.ActiveWindow;
Word.Selection selection = activeWindow.Selection;
Word.Paragraphs paragraphs = selection.Paragraphs;
+ Importer.IImporter importer = null;
+ Importer.AutoDetector autoDetector = new Importer.AutoDetector();
if (!(paragraphs.Count > 1
|| (selection.Text.Length > 1 && selection.Text.EndsWith("\r"))))
{
Logger.Info("DoFormat: Attempting to auto-detect");
Word.Document doc = activeWindow.Document;
- if (!AutoDetect.Detect(doc))
+ if (!autoDetector.Detect(doc))
{
Logger.Info("DoFormat: Automatic detection failed");
NotificationAction a = new NotificationAction();
@@ -220,10 +222,16 @@ namespace zaaReloaded2
}
// Don't release the COM object here
// Bovender.ComHelpers.ReleaseComObject(doc);
+ importer = autoDetector.CreateImporter();
}
+ else if (paragraphs.Count >= 1)
+ {
+ Logger.Info("DoFormat: Detecting mode of selection");
+ autoDetector.Detect(selection);
+ }
+ importer = autoDetector.CreateImporter();
Logger.Info("DoFormat: Importing");
- ZaaImporter importer = new ZaaImporter();
importer.Import(selection.Text);
Formatter.Formatter formatter = new Formatter.Formatter(activeDocument);
diff --git a/zaaReloaded2/Demo/Demo.docx b/zaaReloaded2/Demo/Demo.docx
index 6206475..c54495e 100755
Binary files a/zaaReloaded2/Demo/Demo.docx and b/zaaReloaded2/Demo/Demo.docx differ
diff --git a/zaaReloaded2/ExceptionHandler/ExceptionViewModel.cs b/zaaReloaded2/ExceptionHandler/ExceptionViewModel.cs
index c58c365..c3a8668 100755
--- a/zaaReloaded2/ExceptionHandler/ExceptionViewModel.cs
+++ b/zaaReloaded2/ExceptionHandler/ExceptionViewModel.cs
@@ -83,7 +83,7 @@ namespace zaaReloaded2.ExceptionHandler
protected override string DevPath()
{
- return @"x:\Code\zaaReloaded2\zaaReloaded2\";
+ return @"x:\\Code\\zaaReloaded2\\zaaReloaded2\\";
}
protected override Bovender.UserSettings.UserSettingsBase UserSettings
diff --git a/zaaReloaded2/ExceptionHandler/SubmissionCompletedAction.cs b/zaaReloaded2/ExceptionHandler/SubmissionCompletedAction.cs
index 57ab932..e6696bc 100755
--- a/zaaReloaded2/ExceptionHandler/SubmissionCompletedAction.cs
+++ b/zaaReloaded2/ExceptionHandler/SubmissionCompletedAction.cs
@@ -34,12 +34,12 @@ namespace zaaReloaded2.ExceptionHandler
{
protected override Window CreateSuccessWindow()
{
- return Content.InjectInto();
+ return new SubmissionSuccessView();
}
protected override Window CreateFailureWindow()
{
- return Content.InjectInto();
+ return new SubmissionFailureView();
}
protected override Window CreateCancelledWindow()
diff --git a/zaaReloaded2/ExceptionHandler/SubmissionFailureView.xaml b/zaaReloaded2/ExceptionHandler/SubmissionFailureView.xaml
index 14679f4..95eb934 100755
--- a/zaaReloaded2/ExceptionHandler/SubmissionFailureView.xaml
+++ b/zaaReloaded2/ExceptionHandler/SubmissionFailureView.xaml
@@ -21,14 +21,14 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:zaaReloaded2"
- SizeToContent="WidthAndHeight"
+ SizeToContent="Height" Width="540"
Title="Fehlerbericht versenden"
>
-
-
+
×
@@ -36,11 +36,13 @@
-
-
+
+
-
+
\ No newline at end of file
diff --git a/zaaReloaded2/ExceptionHandler/SubmissionProcessAction.cs b/zaaReloaded2/ExceptionHandler/SubmissionProcessAction.cs
index bd1e021..3d150d9 100755
--- a/zaaReloaded2/ExceptionHandler/SubmissionProcessAction.cs
+++ b/zaaReloaded2/ExceptionHandler/SubmissionProcessAction.cs
@@ -28,7 +28,7 @@ namespace zaaReloaded2.ExceptionHandler
{
protected override System.Windows.Window CreateView()
{
- return Content.InjectInto();
+ return new SubmissionProcessView();
}
}
}
diff --git a/zaaReloaded2/ExceptionHandler/SubmissionSuccessView.xaml b/zaaReloaded2/ExceptionHandler/SubmissionSuccessView.xaml
index f9a7465..3710869 100755
--- a/zaaReloaded2/ExceptionHandler/SubmissionSuccessView.xaml
+++ b/zaaReloaded2/ExceptionHandler/SubmissionSuccessView.xaml
@@ -21,14 +21,15 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:zaaReloaded2"
- SizeToContent="WidthAndHeight"
+ SizeToContent="Height" Width="400"
Title="Fehlerbericht versenden"
>
-
-
+
✔
@@ -36,10 +37,10 @@
-
+
-
+
diff --git a/zaaReloaded2/Importer/AutoDetector.cs b/zaaReloaded2/Importer/AutoDetector.cs
new file mode 100755
index 0000000..17fafac
--- /dev/null
+++ b/zaaReloaded2/Importer/AutoDetector.cs
@@ -0,0 +1,262 @@
+using Microsoft.Office.Interop.Word;
+/* AutoDetect.cs
+ * part of zaaReloaded2
+ *
+ * Copyright 2015-2017 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.Importer.ZaaImporter;
+using zaaReloaded2.Importer.ClinicImporter;
+
+namespace zaaReloaded2.Importer
+{
+ class AutoDetector
+ {
+ #region Properties
+
+ public ImportMode ImportMode { get; private set; }
+
+ #endregion
+
+ #region Public methods
+
+ ///
+ /// Attempts to automatically detect laboratory data in the Word
+ /// document.
+ ///
+ /// Document which to parse for laboratory
+ /// data.
+ /// True if laboratory data was detected, false if not.
+ /// if
+ /// is null.
+ public bool Detect(Document document)
+ {
+ if (document == null)
+ {
+ throw new ArgumentNullException(
+ "Automatic laboratory detection requires a document.");
+ }
+
+ int startParagraph = 1;
+ if (document.Bookmarks.Exists("Labor"))
+ {
+ Logger.Info("Detect: Found lab bookmark");
+ startParagraph = GetParagraphIndex(
+ document,
+ document.Bookmarks["Labor"].Range.Paragraphs[1]);
+ }
+
+ return DetectRange(document, startParagraph, document.Paragraphs.Count);
+ }
+
+ public bool Detect(Selection selection)
+ {
+ if (selection == null)
+ {
+ throw new ArgumentNullException(
+ "Automatic laboratory detection requires a selection.");
+ }
+
+ return DetectRange(selection.Document,
+ GetParagraphIndex(selection.Document, selection.Paragraphs.First),
+ GetParagraphIndex(selection.Document, selection.Paragraphs.Last) + 1);
+ }
+
+ public IImporter CreateImporter()
+ {
+ switch (ImportMode)
+ {
+ case ImportMode.Zaa:
+ return new ZaaImporter.ZaaImporter();
+ case ImportMode.Clinic:
+ return new ClinicImporter.ClinicImporter();
+ default:
+ throw new InvalidOperationException("Cannot create Importer for undefined import mode!");
+ }
+ }
+
+ #endregion
+
+ #region Private methods
+
+ private bool DetectRange(Document document, int startParagraph, int endParagraph)
+ {
+ if (document == null)
+ {
+ throw new ArgumentNullException(
+ "Automatic laboratory detection requires a document.");
+ }
+
+ if (startParagraph < 1 || startParagraph > document.Paragraphs.Count)
+ {
+ Logger.Fatal("Start paragraph index must be between {0} and {1}, was {2}!",
+ 1, document.Paragraphs.Count, startParagraph);
+ throw new ArgumentOutOfRangeException("startParagraph");
+ }
+
+ if (endParagraph < startParagraph || endParagraph > document.Paragraphs.Count)
+ {
+ Logger.Fatal("End paragraph index must be between {0} and {1}, was {2}!",
+ startParagraph, document.Paragraphs.Count, endParagraph);
+ throw new ArgumentOutOfRangeException("endParagraph");
+ }
+
+ Logger.Info("DetectRange: Start paragraph is #{0}, end is #{1}, document has #{2} paragraphs",
+ startParagraph, endParagraph, document.Paragraphs.Count);
+
+ // TODO: Try to make this algorithm more elegant.
+ Paragraph start = null;
+ Paragraph end = null;
+ int i = startParagraph;
+
+ while (i <= endParagraph)
+ {
+ // Expect the first paragraph of a Lauris block to be
+ // a time stamp. This prevents erroneous detection of
+ // lines such as "Tel. (09 31) 201-39432; -39126", which
+ // happen to structurally resemble a paragraph with
+ // laboratory items.
+ if (IsTimeStampParagraph(document.Paragraphs[i]))
+ {
+ start = document.Paragraphs[i];
+ Logger.Info("DetectRange: Found time stamp line in paragraph #{0}", i);
+ break;
+ }
+ i++;
+ }
+
+ if (start != null)
+ {
+ Logger.Info("DetectRange: Determining lab block");
+ while (i <= endParagraph - 1)
+ {
+ Paragraph p = document.Paragraphs[i + 1];
+ if (!IsLabParagraph(p) && !IsEmptyParagraph(p))
+ {
+ Logger.Info("Detect: Last lab paragraph is #{0}", i);
+ end = document.Paragraphs[i];
+ break;
+ }
+ i++;
+ }
+
+ if (end == null)
+ {
+ end = document.Paragraphs[endParagraph];
+ }
+
+ document.Range(start.Range.Start, end.Range.End).Select();
+ return true;
+ }
+ Logger.Warn("DetectRange: Did not find lab block!");
+ return false;
+ }
+
+ ///
+ /// Returns true if a paragraph is a time stamp line.
+ ///
+ private bool IsTimeStampParagraph(Paragraph paragraph)
+ {
+ string text = paragraph.Range.Text;
+ bool isCinicTimePoint = ClinicTimePoint.IsTimeStampLine(text);
+ bool isZaaTimePoint = LaurisTimePoint.IsTimeStampLine(text);
+ // If the line is a ZAA time point, but not a clinic timepoint, we can deduct that
+ // the lab mode *must* be ZAA, because it will be a line in the form
+ // "(17.09.2015-201710:44:00) Cyclosporin-A vor Gabe: 130 µg/l;" which does not
+ // occur in the clinic format.
+ if ((ImportMode == ImportMode.Undefined) && isZaaTimePoint && !isCinicTimePoint)
+ {
+ Logger.Info("IsTimeStampParagraph: Found ZAA time stamp, setting mode to ZAA");
+ ImportMode = ImportMode.Zaa;
+ }
+ return isCinicTimePoint || isZaaTimePoint;
+ }
+
+ ///
+ /// Returns true if a paragraph is either a time stamp line
+ /// or a paragraph with laboratory items.
+ ///
+ ///
+ /// This method determines the mode: either ZAA-generated output or clinic system-generated
+ /// output. ZAA is given priority over clinic. Once a mode is detected, it will stick to
+ /// that mode.
+ ///
+ ///
+ ///
+ private bool IsLabParagraph(Paragraph paragraph)
+ {
+ string text = paragraph.Range.Text;
+ bool isLabParagraph = false;
+ switch (ImportMode)
+ {
+ case ImportMode.Undefined:
+ if (LaurisParagraph.ResemblesLaurisParagraph(text) || LaurisTimePoint.IsTimeStampLine(text))
+ {
+ ImportMode = ImportMode.Zaa;
+ Logger.Info("IsLabParagraph: Setting mode to ZAA");
+ isLabParagraph = true;
+ }
+ else if (ClinicLine.ResemblesClinicLine(text) || ClinicTimePoint.IsTimeStampLine(text))
+ {
+ ImportMode = ImportMode.Clinic;
+ Logger.Info("IsLabParagraph: Setting mode to Clinic");
+ isLabParagraph = true;
+ }
+ break;
+ case ImportMode.Zaa:
+ isLabParagraph = LaurisParagraph.ResemblesLaurisParagraph(text) || LaurisTimePoint.IsTimeStampLine(text);
+ break;
+ case ImportMode.Clinic:
+ isLabParagraph = ClinicLine.ResemblesClinicLine(text) || ClinicTimePoint.IsTimeStampLine(text);
+ break;
+ default:
+ break;
+ }
+ return isLabParagraph;
+ }
+
+ ///
+ /// Returns the index of a paragraph.
+ ///
+ ///
+ /// http://word.mvps.org/faqs/macrosvba/GetIndexNoOfPara.htm
+ ///
+ /// Paragraph whose index to return.
+ /// Index of the paragraph.
+ private int GetParagraphIndex(Document document, Paragraph paragraph)
+ {
+ return document.Range(0, paragraph.Range.Start).Paragraphs.Count;
+ }
+
+ private bool IsEmptyParagraph(Paragraph paragraph)
+ {
+ string text = paragraph.Range.Text;
+ return String.IsNullOrWhiteSpace(text);
+ }
+
+ #endregion
+
+ #region Class logger
+
+ private static NLog.Logger Logger { get { return _logger.Value; } }
+
+ private static readonly Lazy _logger = new Lazy(() => NLog.LogManager.GetCurrentClassLogger());
+
+ #endregion
+ }
+}
diff --git a/zaaReloaded2/Importer/BaseImporter.cs b/zaaReloaded2/Importer/BaseImporter.cs
new file mode 100755
index 0000000..374085f
--- /dev/null
+++ b/zaaReloaded2/Importer/BaseImporter.cs
@@ -0,0 +1,170 @@
+/* ZaaImporter.cs
+ * part of zaaReloaded2
+ *
+ * Copyright 2017 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 Bovender.Extensions;
+using zaaReloaded2.LabModel;
+using zaaReloaded2.Thesaurus;
+
+namespace zaaReloaded2.Importer
+{
+ ///
+ /// Base class for certain importers such as ZaaImporter, ClinicImporter.
+ ///
+ public class BaseImporter : IImporter
+ {
+ #region IImporter implementation
+
+ public Laboratory Laboratory
+ {
+ [DebuggerStepThrough]
+ get
+ {
+ if (_laboratory == null)
+ {
+ _laboratory = new Laboratory();
+ }
+ return _laboratory;
+ }
+ [DebuggerStepThrough]
+ set
+ {
+ _laboratory = value;
+ }
+ }
+
+ public bool Success
+ {
+ get
+ {
+ return Laboratory.TimePoints.Count > 0;
+ }
+ }
+
+ ///
+ /// Splits the into individual time points
+ /// and creates objects from them.
+ ///
+ public void Import(string text)
+ {
+ Logger.Info("Import: \"{0}\"", text.TruncateWithEllipsis(120));
+ string[] paragraphs = Helpers.SplitParagraphs(text);
+ Logger.Info("Import: {0} paragraph(s)", paragraphs.Length);
+ TimePoint timePoint = null;
+
+ foreach (string paragraph in paragraphs)
+ {
+ Logger.Info("Import: \"{0}\"", paragraph.TruncateWithEllipsis(40));
+ // If the current paragraph looks like a time stamp,
+ // create a new time point.
+ if (IsTimeStamp(paragraph))
+ {
+ Logger.Info("Import: Time stamp detected", paragraph);
+ timePoint = CreateTimePoint(paragraph, _parameters, _units);
+ // Add the time point to the laboratory only if none
+ // with the same time stamp exists yet.
+ TimePoint existing = null;
+ if (Laboratory.TryGetTimePoint(timePoint.TimeStamp, ref existing))
+ {
+ timePoint = existing;
+ }
+ else
+ {
+ Laboratory.AddTimePoint(timePoint);
+ }
+ }
+ // If the current paragraph looks like a paragraph with
+ // laboratory items, add it to the current time point;
+ // if no time point exists yet, create one.
+ else if (IsItemsParagraph(paragraph))
+ {
+ Logger.Info("Import: Paragraph with lab items detected");
+ if (timePoint == null)
+ {
+ timePoint = CreateTimePoint(paragraph, _parameters, _units);
+ Laboratory.AddTimePoint(timePoint);
+ }
+ else
+ {
+ timePoint.Parse(paragraph);
+ }
+ }
+ else
+ {
+ Logger.Debug("Import: Neither time stamp, nor Lauris paragraph");
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public BaseImporter()
+ {
+ _parameters = Parameters.Default;
+ _units = Units.Default;
+ }
+
+ #endregion
+
+ #region Virtual methods
+
+ protected virtual TimePoint CreateTimePoint(string paragraph, Parameters parameters, Units units)
+ {
+ NotImplementedException e = new NotImplementedException("Cannot create TimePoint in base class - derived class must override CreateTimePoint");
+ Logger.Fatal(e);
+ throw e;
+ }
+
+ protected virtual bool IsTimeStamp(string paragraph)
+ {
+ NotImplementedException e = new NotImplementedException("Cannot test time stamp in base class - derived class must override IsTimeStamp");
+ Logger.Fatal(e);
+ throw e;
+ }
+
+ protected virtual bool IsItemsParagraph(string paragraph)
+ {
+ NotImplementedException e = new NotImplementedException("Cannot test items in base class - derived class must override IsItemsParagraph");
+ Logger.Fatal(e);
+ throw e;
+ }
+
+ #endregion
+
+ #region Fields
+
+ Laboratory _laboratory;
+ Parameters _parameters;
+ Units _units;
+
+ #endregion
+
+ #region Class logger
+
+ private static NLog.Logger Logger { get { return _logger.Value; } }
+
+ private static readonly Lazy _logger = new Lazy(() => NLog.LogManager.GetCurrentClassLogger());
+
+ #endregion
+ }
+}
diff --git a/zaaReloaded2/Importer/ClinicImporter/ClinicImporter.cs b/zaaReloaded2/Importer/ClinicImporter/ClinicImporter.cs
new file mode 100755
index 0000000..024985e
--- /dev/null
+++ b/zaaReloaded2/Importer/ClinicImporter/ClinicImporter.cs
@@ -0,0 +1,68 @@
+/* ZaaImporter.cs
+ * part of zaaReloaded2
+ *
+ * Copyright 2017 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 Bovender.Extensions;
+using zaaReloaded2.LabModel;
+using zaaReloaded2.Thesaurus;
+
+namespace zaaReloaded2.Importer.ClinicImporter
+{
+ ///
+ /// Imports laboratory items by parsing the Lauris data from a
+ /// physician's letter.
+ ///
+ public class ClinicImporter : BaseImporter
+ {
+ #region Constructor
+
+ public ClinicImporter() : base() { }
+
+ #endregion
+
+ #region Class logger
+
+ private static NLog.Logger Logger { get { return _logger.Value; } }
+
+ private static readonly Lazy _logger = new Lazy(() => NLog.LogManager.GetCurrentClassLogger());
+
+ #endregion
+
+ #region Implementation of BaseImporter
+
+ protected override TimePoint CreateTimePoint(string paragraph, Parameters parameters, Units units)
+ {
+ return new ClinicTimePoint(paragraph, parameters, units);
+ }
+
+ protected override bool IsTimeStamp(string paragraph)
+ {
+ return ClinicTimePoint.IsTimeStampLine(paragraph);
+ }
+
+ protected override bool IsItemsParagraph(string paragraph)
+ {
+ return ClinicLine.ResemblesClinicLine(paragraph);
+ }
+
+ #endregion
+ }
+}
diff --git a/zaaReloaded2/Importer/ClinicImporter/ClinicLine.cs b/zaaReloaded2/Importer/ClinicImporter/ClinicLine.cs
new file mode 100755
index 0000000..3716ce7
--- /dev/null
+++ b/zaaReloaded2/Importer/ClinicImporter/ClinicLine.cs
@@ -0,0 +1,138 @@
+/* ClinicLine.cs
+ * part of zaaReloaded2
+ *
+ * Copyright 2017 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.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using zaaReloaded2.Thesaurus;
+using zaaReloaded2.LabModel;
+using zaaReloaded2.Importer.ZaaImporter;
+using Bovender.Extensions;
+
+namespace zaaReloaded2.Importer.ClinicImporter
+{
+ ///
+ /// Parses a line in a lab section produced by the outpatients clinic system,
+ /// and creates a list of s.
+ ///
+ public class ClinicLine
+ {
+ #region Static methods
+
+ ///
+ /// Investigates a paragraph and determines whether it looks
+ /// like a clinic laboratory items line.
+ ///
+ public static bool ResemblesClinicLine(string line)
+ {
+ return _expectedFormat.IsMatch(line);
+ }
+
+ #endregion
+
+ #region Public properties
+
+ public LaurisItem Item { get; private set; }
+
+ ///
+ /// Gets the original line that this object was constructed from.
+ ///
+ public string OriginalLine{ get; private set; }
+
+ ///
+ /// Is true if the matches the expected
+ /// format and contains s.
+ ///
+ public bool IsClinicLine{ get; private set; }
+
+ #endregion
+
+ #region Constructor
+
+ public ClinicLine(string line)
+ {
+ OriginalLine = line;
+ Parse();
+ }
+
+ ///
+ /// Constructs a object from a given line,
+ /// using a and a
+ /// to translate the individual
+ /// items' properties.
+ ///
+ /// line to parse.
+ /// ParameterDictionary that contains
+ /// canonical names and material types.
+ /// Unit dictionary that contains canonical
+ /// unit names.
+ public ClinicLine(string line,
+ Thesaurus.Parameters parameterDictionary,
+ Thesaurus.Units unitDictionary)
+ {
+ OriginalLine = line;
+ _parameterDictionary = parameterDictionary;
+ _unitDictionary = unitDictionary;
+ Parse();
+ }
+
+ #endregion
+
+ #region Private methods
+
+ ///
+ /// Attempts to parse a line.
+ ///
+ void Parse()
+ {
+ Logger.Info("Parse: \"{0}\"", OriginalLine.TruncateWithEllipsis(40).Replace("\t", " "));
+ Match m = _expectedFormat.Match(OriginalLine);
+ if (m.Success)
+ {
+ Logger.Info("Parse: Matches clinic line format");
+ Item = new LaurisItem(m.Groups["item"].Value, _parameterDictionary, _unitDictionary);
+ IsClinicLine = true;
+ }
+ else
+ {
+ Logger.Info("Parse: Does not match clinic line format");
+ IsClinicLine = false;
+ }
+ }
+
+ #endregion
+
+ #region Fields
+
+ static readonly Regex _expectedFormat = new Regex(@"\t(?- [^:]+:(\t([^\t]+)?){3})");
+ Thesaurus.Parameters _parameterDictionary;
+ Thesaurus.Units _unitDictionary;
+
+ #endregion
+
+ #region Class logger
+
+ private static NLog.Logger Logger { get { return _logger.Value; } }
+
+ private static readonly Lazy _logger = new Lazy(() => NLog.LogManager.GetCurrentClassLogger());
+
+ #endregion
+ }
+}
diff --git a/zaaReloaded2/Importer/ClinicImporter/ClinicTimePoint.cs b/zaaReloaded2/Importer/ClinicImporter/ClinicTimePoint.cs
new file mode 100755
index 0000000..8ca5aeb
--- /dev/null
+++ b/zaaReloaded2/Importer/ClinicImporter/ClinicTimePoint.cs
@@ -0,0 +1,258 @@
+/* ClinicTimePoint.cs
+ * part of zaaReloaded2
+ *
+ * Copyright 2017 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.Thesaurus;
+using zaaReloaded2.LabModel;
+
+namespace zaaReloaded2.Importer.ClinicImporter
+{
+ ///
+ /// Holds all laboratory items for a given time point.
+ ///
+ class ClinicTimePoint : TimePoint
+ {
+ #region Static methods
+
+ ///
+ /// Examines a string and returns true if it resembles
+ /// a time stamp line in the clinic output.
+ ///
+ /// Line to examine.
+ /// True if line resembles a time stamp line
+ /// in the clinic output.
+ static public bool IsTimeStampLine(string line)
+ {
+ return _timeStampRegex.IsMatch(line);
+ }
+
+ ///
+ /// Gets a Regex object that matches a clinic time stamp
+ /// line.
+ ///
+ static public Regex TimeStampRegex
+ {
+ get
+ {
+ return _timeStampRegex;
+ }
+ }
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// Gets an array of lines in this ClinicText.
+ ///
+ public IList Lines
+ {
+ [DebuggerStepThrough]
+ get
+ {
+ if (_lines == null)
+ {
+ _lines = new List();
+ }
+ return _lines;
+ }
+ set
+ {
+ _lines = value;
+ ParseLines();
+ }
+ }
+
+ ///
+ /// Is true if the LaurisText has time stamp in the first
+ /// paragraph and s in the others.
+ ///
+ public bool IsValidTimePoint
+ {
+ get
+ {
+ return Items.Count > 0;
+ }
+ }
+
+ ///
+ /// Gets or sets the original Lauris text for this timepoint.
+ ///
+ public string ClinicText
+ {
+ [DebuggerStepThrough]
+ get
+ {
+ return String.Join(Environment.NewLine, Lines);
+ }
+ set
+ {
+ if (!String.IsNullOrEmpty(value))
+ {
+ Lines = value.Split(
+ new string[] { Environment.NewLine },
+ StringSplitOptions.None).ToList();
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ public ClinicTimePoint() { }
+
+ public ClinicTimePoint(
+ string clinicText,
+ Parameters parameterDictionary,
+ Units unitDictionary)
+ : this()
+ {
+ _parameterDictionary = parameterDictionary;
+ _unitDictionary = unitDictionary;
+ ClinicText = clinicText;
+ }
+
+ public ClinicTimePoint(string clinicText)
+ : this(clinicText, null, null)
+ { }
+
+ public ClinicTimePoint(
+ IList lines,
+ Parameters parameterDictionary,
+ Units unitDictionary)
+ : this(parameterDictionary, unitDictionary)
+ {
+ Lines = lines;
+ }
+
+ public ClinicTimePoint(IList lines)
+ : this(lines, null, null)
+ {
+ }
+
+ public ClinicTimePoint(
+ Parameters parameterDictionary,
+ Units unitDictionary)
+ : this()
+ {
+ _parameterDictionary = parameterDictionary;
+ _unitDictionary = unitDictionary;
+ }
+
+ #endregion
+
+ #region Public methods
+
+ ///
+ /// Adds a new line to this time point by parsing
+ /// the line for a laboratory item.
+ ///
+ /// Line to add.
+ public override void Parse(string paragraph)
+ {
+ Lines.Add(paragraph);
+ ParseLine(paragraph);
+ }
+
+ #endregion
+
+ #region Private methods
+
+ ///
+ /// Analyzes each clinic line in this time point, sets the date
+ /// and time, and collects LabItem data.
+ ///
+ void ParseLines()
+ {
+ if (Lines != null)
+ {
+ foreach (string paragraph in Lines)
+ {
+ ParseLine(paragraph);
+ }
+ }
+ }
+
+ void ParseLine(string line)
+ {
+ Match m = _timeStampRegex.Match(line);
+ if (m.Success)
+ {
+ Logger.Info("ParseLine: Matches time stamp");
+ DateTime dt;
+ if (DateTime.TryParseExact(
+ m.Groups["datetime"].Value,
+ "dd.MM.yyyy HH:mm",
+ CultureInfo.InvariantCulture,
+ DateTimeStyles.AllowWhiteSpaces,
+ out dt))
+ {
+ TimeStamp = dt;
+ }
+ }
+ else
+ {
+ Logger.Info("ParseLine: Not a time stamp");
+ ClinicLine clinicLine = new ClinicLine(
+ line,
+ _parameterDictionary,
+ _unitDictionary);
+ if (clinicLine.IsClinicLine)
+ {
+ Logger.Debug("ParseParagraph: Merging Lauris paragraph");
+ Items[clinicLine.Item.QualifiedName] = clinicLine.Item;
+ }
+ }
+ }
+
+ void AddItems(IItemDictionary items)
+ {
+ Items.Merge(items);
+ }
+
+ #endregion
+
+ #region Private fields
+
+ ///
+ /// A regular expression that matches the time stamp in the first
+ /// paragraph of a LaurisText.
+ ///
+ static readonly Regex _timeStampRegex = new Regex(
+ @"^(Labor:?)?\s*\(?\s*(?\d\d\.\d\d\.\d\d\d\d\s+\d\d:\d\d)(:00)?\)\s*$");
+ IList _lines;
+ Parameters _parameterDictionary;
+ Units _unitDictionary;
+
+ #endregion
+
+ #region Class logger
+
+ private static NLog.Logger Logger { get { return _logger.Value; } }
+
+ private static readonly Lazy _logger = new Lazy(() => NLog.LogManager.GetCurrentClassLogger());
+
+ #endregion
+ }
+}
diff --git a/zaaReloaded2/Importer/ImportMode.cs b/zaaReloaded2/Importer/ImportMode.cs
new file mode 100755
index 0000000..994bc8f
--- /dev/null
+++ b/zaaReloaded2/Importer/ImportMode.cs
@@ -0,0 +1,31 @@
+/* ImportMode.cs
+ * part of zaaReloaded2
+ *
+ * Copyright 2017 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.Importer
+{
+ public enum ImportMode
+ {
+ Undefined,
+ Zaa,
+ Clinic
+ }
+}
diff --git a/zaaReloaded2/Importer/ZaaImporter/AutoDetect.cs b/zaaReloaded2/Importer/ZaaImporter/AutoDetect.cs
deleted file mode 100755
index 3bf9905..0000000
--- a/zaaReloaded2/Importer/ZaaImporter/AutoDetect.cs
+++ /dev/null
@@ -1,118 +0,0 @@
-using Microsoft.Office.Interop.Word;
-/* AutoDetect.cs
- * part of zaaReloaded2
- *
- * Copyright 2015-2017 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.Importer.ZaaImporter
-{
- static class AutoDetect
- {
- ///
- /// Attempts to automatically detect laboratory data in the Word
- /// document.
- ///
- /// Document which to parse for laboratory
- /// data.
- /// True if laboratory data was detected, false if not.
- /// if
- /// is null.
- public static bool Detect(Document document)
- {
- if (document == null)
- {
- throw new ArgumentNullException(
- "Automatic laboratory detection requires a document.");
- }
-
- // TODO: Try to make this algorithm more elegant.
- Paragraph start = null;
- Paragraph end = null;
- int i = 1;
-
- if (document.Bookmarks.Exists("Labor"))
- {
- i = GetParagraphIndex(
- document,
- document.Bookmarks["Labor"].Range.Paragraphs[1]);
- }
-
- while (i <= document.Paragraphs.Count)
- {
- // Expect the first paragraph of a Lauris block to be
- // a time stamp. This prevents erroneous detection of
- // lines such as "Tel. (09 31) 201-39432; -39126", which
- // happen to structurally resemble a paragraph with
- // laboratory items.
- if (LaurisTimePoint.IsTimeStampLine(
- document.Paragraphs[i].Range.Text))
- {
- start = document.Paragraphs[i];
- break;
- }
- i++;
- }
-
- if (start != null)
- {
- end = start;
- while (i <= document.Paragraphs.Count - 1)
- {
- if (!IsLabParagraph(document.Paragraphs[i+1]))
- {
- end = document.Paragraphs[i];
- break;
- }
- i++;
- }
-
- document.Range(start.Range.Start, end.Range.End).Select();
- return true;
- }
- return false;
- }
-
- ///
- /// Returns true if a paragraph is either a time stamp line
- /// or a paragraph with laboratory items.
- ///
- ///
- ///
- private static bool IsLabParagraph(Paragraph paragraph)
- {
- string text = paragraph.Range.Text;
- return (LaurisParagraph.ResemblesLaurisParagraph(text)
- || LaurisTimePoint.IsTimeStampLine(text));
- }
-
- ///
- /// Returns the index of a paragraph.
- ///
- ///
- /// http://word.mvps.org/faqs/macrosvba/GetIndexNoOfPara.htm
- ///
- /// Paragraph whose index to return.
- /// Index of the paragraph.
- private static int GetParagraphIndex(Document document, Paragraph paragraph)
- {
- return document.Range(0, paragraph.Range.Start).Paragraphs.Count;
- }
- }
-}
diff --git a/zaaReloaded2/Importer/ZaaImporter/LaurisTimePoint.cs b/zaaReloaded2/Importer/ZaaImporter/LaurisTimePoint.cs
index 3d5d1ef..27978bd 100755
--- a/zaaReloaded2/Importer/ZaaImporter/LaurisTimePoint.cs
+++ b/zaaReloaded2/Importer/ZaaImporter/LaurisTimePoint.cs
@@ -169,7 +169,7 @@ namespace zaaReloaded2.Importer.ZaaImporter
/// the paragraph for laboratory items.
///
/// Paragraph to add.
- public void AddParagraph(string paragraph)
+ public override void Parse(string paragraph)
{
Paragraphs.Add(paragraph);
ParseParagraph(paragraph);
diff --git a/zaaReloaded2/Importer/ZaaImporter/ZaaImporter.cs b/zaaReloaded2/Importer/ZaaImporter/ZaaImporter.cs
index fdc869f..48f490c 100755
--- a/zaaReloaded2/Importer/ZaaImporter/ZaaImporter.cs
+++ b/zaaReloaded2/Importer/ZaaImporter/ZaaImporter.cs
@@ -30,106 +30,30 @@ namespace zaaReloaded2.Importer.ZaaImporter
/// Imports laboratory items by parsing the Lauris data from a
/// physician's letter.
///
- public class ZaaImporter : IImporter
+ public class ZaaImporter : BaseImporter
{
- #region IImporter implementation
-
- public Laboratory Laboratory
- {
- [DebuggerStepThrough]
- get
- {
- if (_laboratory == null)
- {
- _laboratory = new Laboratory();
- }
- return _laboratory;
- }
- [DebuggerStepThrough]
- set
- {
- _laboratory = value;
- }
- }
-
- public bool Success
- {
- get
- {
- return Laboratory.TimePoints.Count > 0;
- }
- }
-
- ///
- /// Splits the into individual time points
- /// and creates objects from them.
- ///
- /// ZAA-formatted Lauris output to import.
- public void Import(string text)
- {
- Logger.Info("Import: \"{0}\"", text.TruncateWithEllipsis(120));
- string[] paragraphs = Helpers.SplitParagraphs(text);
- Logger.Info("Import: {0} paragraph(s)", paragraphs.Length);
- LaurisTimePoint timePoint = null;
-
- foreach (string paragraph in paragraphs)
- {
- Logger.Info("Import: \"{0}\"", paragraph.TruncateWithEllipsis(40));
- // If the current paragraph looks like a Lauris time stamp,
- // create a new time point.
- if (LaurisTimePoint.IsTimeStampLine(paragraph))
- {
- Logger.Info("Import: Time stamp detected", paragraph);
- timePoint = new LaurisTimePoint(paragraph, _parameters, _units);
- // Add the time point to the laboratory only if none
- // with the same time stamp exists yet.
- TimePoint existing = null;
- if (Laboratory.TryGetTimePoint(timePoint.TimeStamp, ref existing))
- {
- timePoint = existing as LaurisTimePoint;
- }
- else
- {
- Laboratory.AddTimePoint(timePoint);
- }
- }
- // If the current paragraph looks like a paragraph with
- // laboratory items, add it to the current time point;
- // if no time point exists yet, create one.
- else if (LaurisParagraph.ResemblesLaurisParagraph(paragraph))
- {
- Logger.Info("Import: Lauris paragraph detected");
- if (timePoint == null)
- {
- timePoint = new LaurisTimePoint(_parameters, _units);
- Laboratory.AddTimePoint(timePoint);
- }
- timePoint.AddParagraph(paragraph);
- }
- else
- {
- Logger.Debug("Import: Neither time stamp, nor Lauris paragraph");
- }
- }
- }
-
- #endregion
-
#region Constructor
- public ZaaImporter()
- {
- _parameters = Parameters.Default;
- _units = Units.Default;
- }
+ public ZaaImporter() : base() { }
#endregion
- #region Fields
+ #region Implementation of BaseImporter
- Laboratory _laboratory;
- Parameters _parameters;
- Units _units;
+ protected override TimePoint CreateTimePoint(string paragraph, Parameters parameters, Units units)
+ {
+ return new LaurisTimePoint(paragraph, parameters, units);
+ }
+
+ protected override bool IsTimeStamp(string paragraph)
+ {
+ return LaurisTimePoint.IsTimeStampLine(paragraph);
+ }
+
+ protected override bool IsItemsParagraph(string paragraph)
+ {
+ return LaurisParagraph.ResemblesLaurisParagraph(paragraph);
+ }
#endregion
diff --git a/zaaReloaded2/LabModel/TimePoint.cs b/zaaReloaded2/LabModel/TimePoint.cs
index a96ffb7..f5c65fe 100755
--- a/zaaReloaded2/LabModel/TimePoint.cs
+++ b/zaaReloaded2/LabModel/TimePoint.cs
@@ -68,6 +68,7 @@ namespace zaaReloaded2.LabModel
{
if (String.IsNullOrEmpty(item.QualifiedName))
{
+ Logger.Fatal("Cannot add item without QualifiedName!");
throw new ArgumentException("Cannot add item that has no qualified name.");
}
Items.Add(item.QualifiedName, item);
@@ -84,8 +85,10 @@ namespace zaaReloaded2.LabModel
public void MergeItems(TimePoint otherTimePoint)
{
if (otherTimePoint == null)
+ {
+ Logger.Fatal("Cannot merge null!");
throw new ArgumentNullException("otherTimePoint");
-
+ }
Items.Merge(otherTimePoint.Items);
}
@@ -101,6 +104,21 @@ namespace zaaReloaded2.LabModel
return Items.ContainsKey(item);
}
+ public virtual void Parse(string paragraph)
+ {
+ NotImplementedException e = new NotImplementedException("Cannot parse paragraph in base class - derived class must override Parse");
+ Logger.Fatal(e);
+ throw e;
+ }
+
+ #endregion
+
+ #region Class logger
+
+ private static NLog.Logger Logger { get { return _logger.Value; } }
+
+ private static readonly Lazy _logger = new Lazy(() => NLog.LogManager.GetCurrentClassLogger());
+
#endregion
}
}
diff --git a/zaaReloaded2/Properties/Settings.Designer.cs b/zaaReloaded2/Properties/Settings.Designer.cs
index 7fcffcd..6c306a1 100755
--- a/zaaReloaded2/Properties/Settings.Designer.cs
+++ b/zaaReloaded2/Properties/Settings.Designer.cs
@@ -34,7 +34,7 @@ namespace zaaReloaded2.Properties {
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("2015-2017")]
+ [global::System.Configuration.DefaultSettingValueAttribute("2017")]
public string PubYear {
get {
return ((string)(this["PubYear"]));
diff --git a/zaaReloaded2/Properties/Settings.settings b/zaaReloaded2/Properties/Settings.settings
index 47770ad..6796af9 100755
--- a/zaaReloaded2/Properties/Settings.settings
+++ b/zaaReloaded2/Properties/Settings.settings
@@ -6,7 +6,7 @@
zaaReloaded2
- 2015-2017
+ 2017
Daniel Kraus
diff --git a/zaaReloaded2/VERSION b/zaaReloaded2/VERSION
index 7e5c979..076dbb3 100755
--- a/zaaReloaded2/VERSION
+++ b/zaaReloaded2/VERSION
@@ -1,2 +1,2 @@
-2.3.2
-2.3.2.0
+2.4.0
+2.4.0.0
diff --git a/zaaReloaded2/app.config b/zaaReloaded2/app.config
index 42952af..f8db0e3 100755
--- a/zaaReloaded2/app.config
+++ b/zaaReloaded2/app.config
@@ -30,7 +30,7 @@
zaaReloaded2
- 2015-2017
+ 2017
Daniel Kraus
diff --git a/zaaReloaded2/packages.config b/zaaReloaded2/packages.config
index 981621f..9d45393 100755
--- a/zaaReloaded2/packages.config
+++ b/zaaReloaded2/packages.config
@@ -21,6 +21,6 @@
-
+
\ No newline at end of file
diff --git a/zaaReloaded2/zaaReloaded2.csproj b/zaaReloaded2/zaaReloaded2.csproj
index fd33e25..7ad0e63 100755
--- a/zaaReloaded2/zaaReloaded2.csproj
+++ b/zaaReloaded2/zaaReloaded2.csproj
@@ -140,7 +140,7 @@
- ..\packages\NLog.4.4.3\lib\net40\NLog.dll
+ ..\packages\NLog.4.4.12\lib\net40\NLog.dll
True
@@ -204,7 +204,11 @@
-
+
+
+
+
+
@@ -231,6 +235,7 @@
+
@@ -466,6 +471,7 @@
+
10.0
$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)