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 @@ - - + +