Merge branch 'release-2.4.0'
This commit is contained in:
commit
8b1525efbb
@ -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)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
|
55
Tests/Importer/ClinicImporter/ClinicImporterTest.cs
Executable file
55
Tests/Importer/ClinicImporter/ClinicImporterTest.cs
Executable file
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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 <see cref="Laboratory"/>.
|
||||
/// </summary>
|
||||
[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);
|
||||
}
|
||||
}
|
||||
}
|
56
Tests/Importer/ClinicImporter/ClinicItemTest.cs
Executable file
56
Tests/Importer/ClinicImporter/ClinicItemTest.cs
Executable file
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[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");
|
||||
}
|
||||
}
|
||||
}
|
45
Tests/Importer/ClinicImporter/ClinicLineTest.cs
Executable file
45
Tests/Importer/ClinicImporter/ClinicLineTest.cs
Executable file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
67
Tests/Importer/ClinicImporter/TimePointTest.cs
Executable file
67
Tests/Importer/ClinicImporter/TimePointTest.cs
Executable file
@ -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'.");
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a ClinicImporter object and imports demo-output-clinic.txt.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,11 +49,11 @@
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.3\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.4.4.12\lib\net40\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=3.6.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.6.1\lib\net40\nunit.framework.dll</HintPath>
|
||||
<Reference Include="nunit.framework, Version=3.8.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.8.1\lib\net40\nunit.framework.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
@ -91,6 +91,10 @@
|
||||
<Compile Include="Controller\Comments\CommentPoolTest.cs" />
|
||||
<Compile Include="Controller\Comments\ItemCommentTest.cs" />
|
||||
<Compile Include="Controller\Elements\CloneTest.cs" />
|
||||
<Compile Include="Importer\ClinicImporter\ClinicItemTest.cs" />
|
||||
<Compile Include="Importer\ClinicImporter\ClinicLineTest.cs" />
|
||||
<Compile Include="Importer\ClinicImporter\TimePointTest.cs" />
|
||||
<Compile Include="Importer\ClinicImporter\ClinicImporterTest.cs" />
|
||||
<Compile Include="Medication\ImporterTest.cs" />
|
||||
<Compile Include="Medication\PrescriptionTest.cs" />
|
||||
<Compile Include="SerializationTest.cs" />
|
||||
@ -144,6 +148,10 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Formatter\FormatterTest-all.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="demo-output-clinic.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
|
90
Tests/demo-output-clinic.txt
Executable file
90
Tests/demo-output-clinic.txt
Executable file
@ -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
|
@ -2,7 +2,7 @@
|
||||
<packages>
|
||||
<package id="Bovender" version="0.17.0.0" targetFramework="net40" />
|
||||
<package id="Expression.Blend.Sdk" version="1.0.2" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.3" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.6.1" targetFramework="net40" />
|
||||
<package id="YamlDotNet.Signed" version="4.1.0" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.12" targetFramework="net40" />
|
||||
<package id="NUnit" version="3.8.1" targetFramework="net40" />
|
||||
<package id="YamlDotNet.Signed" version="4.2.1" targetFramework="net40" />
|
||||
</packages>
|
@ -1 +1 @@
|
||||
Subproject commit ad374fad7ce765ea28289bc5faaa4dd083b914bd
|
||||
Subproject commit 953757454eb3f235d8bdb75be613eae79c21a9f0
|
@ -1,53 +1,52 @@
|
||||
<?php
|
||||
require(__DIR__ . '/PHPMailer/PHPMailerAutoload.php');
|
||||
$reportId = $_POST['report_id'];
|
||||
$mail = new PHPMailer;
|
||||
$mail->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\" <dk@doktorkraus.de>";
|
||||
$reportId = $_POST['report_id'];
|
||||
$info = print_r( $_POST, true ); // this will be a string, not an array!
|
||||
$body = <<<EOF
|
||||
zaaReloaded hat einen Fehler ausgelöst.
|
||||
|
||||
$mail->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 = <<<EOF
|
||||
zaaReloaded exception
|
||||
|
||||
User's comment on submission:
|
||||
{$_POST['comment']}
|
||||
|
||||
***
|
||||
-----
|
||||
|
||||
Technical details: $info
|
||||
Technische Info: $info
|
||||
|
||||
--
|
||||
http://zaa.nephrowiki.de
|
||||
--
|
||||
www.doktorkraus.de/zaareloaded
|
||||
EOF;
|
||||
|
||||
if ($mail->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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Binary file not shown.
@ -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
|
||||
|
@ -34,12 +34,12 @@ namespace zaaReloaded2.ExceptionHandler
|
||||
{
|
||||
protected override Window CreateSuccessWindow()
|
||||
{
|
||||
return Content.InjectInto<SubmissionSuccessView>();
|
||||
return new SubmissionSuccessView();
|
||||
}
|
||||
|
||||
protected override Window CreateFailureWindow()
|
||||
{
|
||||
return Content.InjectInto<SubmissionFailureView>();
|
||||
return new SubmissionFailureView();
|
||||
}
|
||||
|
||||
protected override Window CreateCancelledWindow()
|
||||
|
@ -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"
|
||||
>
|
||||
<Window.Resources>
|
||||
<ResourceDictionary Source="/Bovender;component/Style.xaml" />
|
||||
</Window.Resources>
|
||||
<StackPanel Margin="10" Orientation="Horizontal">
|
||||
<TextBlock FontSize="72" FontWeight="Bold" Foreground="Red" Margin="0,0,10,0"
|
||||
<DockPanel Margin="10">
|
||||
<TextBlock DockPanel.Dock="Left" FontSize="72" FontWeight="Bold" Foreground="Red" Margin="0,0,10,0"
|
||||
LineHeight="48" LineStackingStrategy="BlockLineHeight">
|
||||
×
|
||||
<TextBlock.Effect>
|
||||
@ -36,11 +36,13 @@
|
||||
</TextBlock.Effect>
|
||||
</TextBlock>
|
||||
<StackPanel>
|
||||
<TextBlock Text="Beim Senden des Fehlerberichtes ist wiederum leider ein Fehler aufgetreten... (Funktioniert das Netzwerk?)" />
|
||||
<TextBlock Text="{Binding Exception}" Margin="0,10,0,0" Foreground="LightSlateGray" />
|
||||
<TextBlock TextWrapping="Wrap"
|
||||
Text="Beim Senden des Fehlerberichtes ist wiederum leider ein Fehler aufgetreten... (Funktioniert das Netzwerk?)" />
|
||||
<TextBlock TextWrapping="Wrap"
|
||||
Text="{Binding Exception}" Margin="0,10,0,0" Foreground="LightSlateGray" />
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0">
|
||||
<Button Command="{Binding CloseViewCommand}" Content="Schließen" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Window>
|
@ -28,7 +28,7 @@ namespace zaaReloaded2.ExceptionHandler
|
||||
{
|
||||
protected override System.Windows.Window CreateView()
|
||||
{
|
||||
return Content.InjectInto<SubmissionProcessView>();
|
||||
return new SubmissionProcessView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
>
|
||||
<Window.Resources>
|
||||
<ResourceDictionary Source="/Bovender;component/Style.xaml" />
|
||||
</Window.Resources>
|
||||
<StackPanel Margin="10" Orientation="Horizontal">
|
||||
<TextBlock FontSize="48" FontWeight="Bold" Foreground="GreenYellow" Margin="0,0,10,0"
|
||||
<DockPanel Margin="10">
|
||||
<TextBlock DockPanel.Dock="Left"
|
||||
FontSize="48" FontWeight="Bold" Foreground="GreenYellow" Margin="0,0,10,0"
|
||||
LineHeight="48" LineStackingStrategy="BlockLineHeight">
|
||||
✔
|
||||
<TextBlock.Effect>
|
||||
@ -36,10 +37,10 @@
|
||||
</TextBlock.Effect>
|
||||
</TextBlock>
|
||||
<StackPanel>
|
||||
<TextBlock Text="Der Fehlerbericht wurde erfolgreich versandt." />
|
||||
<TextBlock TextWrapping="Wrap" Text="Der Fehlerbericht wurde erfolgreich versandt." />
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0 10 0 0">
|
||||
<Button Command="{Binding CloseViewCommand}" Content="Schließen" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
|
262
zaaReloaded2/Importer/AutoDetector.cs
Executable file
262
zaaReloaded2/Importer/AutoDetector.cs
Executable file
@ -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
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to automatically detect laboratory data in the Word
|
||||
/// document.
|
||||
/// </summary>
|
||||
/// <param name="document">Document which to parse for laboratory
|
||||
/// data.</param>
|
||||
/// <returns>True if laboratory data was detected, false if not.</returns>
|
||||
/// <exception cref="ArgumentNullException">if <paramref name="document"/>
|
||||
/// is null.</exception>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a paragraph is a time stamp line.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a paragraph is either a time stamp line
|
||||
/// or a paragraph with laboratory items.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
/// <param name="paragraph"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the index of a paragraph.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://word.mvps.org/faqs/macrosvba/GetIndexNoOfPara.htm
|
||||
/// </remarks>
|
||||
/// <param name="paragraph">Paragraph whose index to return.</param>
|
||||
/// <returns>Index of the paragraph.</returns>
|
||||
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<NLog.Logger> _logger = new Lazy<NLog.Logger>(() => NLog.LogManager.GetCurrentClassLogger());
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
170
zaaReloaded2/Importer/BaseImporter.cs
Executable file
170
zaaReloaded2/Importer/BaseImporter.cs
Executable file
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for certain importers such as ZaaImporter, ClinicImporter.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits the <paramref name="text"/> into individual time points
|
||||
/// and creates <see cref="TimePoint"/> objects from them.
|
||||
/// </summary>
|
||||
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<NLog.Logger> _logger = new Lazy<NLog.Logger>(() => NLog.LogManager.GetCurrentClassLogger());
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
68
zaaReloaded2/Importer/ClinicImporter/ClinicImporter.cs
Executable file
68
zaaReloaded2/Importer/ClinicImporter/ClinicImporter.cs
Executable file
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Imports laboratory items by parsing the Lauris data from a
|
||||
/// physician's letter.
|
||||
/// </summary>
|
||||
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<NLog.Logger> _logger = new Lazy<NLog.Logger>(() => 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
|
||||
}
|
||||
}
|
138
zaaReloaded2/Importer/ClinicImporter/ClinicLine.cs
Executable file
138
zaaReloaded2/Importer/ClinicImporter/ClinicLine.cs
Executable file
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses a line in a lab section produced by the outpatients clinic system,
|
||||
/// and creates a list of <see cref="zaaReloaded2.Importer.BaseImporter.LabItem"/>s.
|
||||
/// </summary>
|
||||
public class ClinicLine
|
||||
{
|
||||
#region Static methods
|
||||
|
||||
/// <summary>
|
||||
/// Investigates a paragraph and determines whether it looks
|
||||
/// like a clinic laboratory items line.
|
||||
/// </summary>
|
||||
public static bool ResemblesClinicLine(string line)
|
||||
{
|
||||
return _expectedFormat.IsMatch(line);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public properties
|
||||
|
||||
public LaurisItem Item { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original line that this object was constructed from.
|
||||
/// </summary>
|
||||
public string OriginalLine{ get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is true if the <see cref="OriginalLine"/> matches the expected
|
||||
/// format and contains <see cref="LabItem"/>s.
|
||||
/// </summary>
|
||||
public bool IsClinicLine{ get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public ClinicLine(string line)
|
||||
{
|
||||
OriginalLine = line;
|
||||
Parse();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a <see cref="ClinicLine"/> object from a given line,
|
||||
/// using a <paramref name="parameterDictionary"/> and a
|
||||
/// <paramref name="unitDictionary"/> to translate the individual
|
||||
/// items' properties.
|
||||
/// </summary>
|
||||
/// <param name="line">line to parse.</param>
|
||||
/// <param name="parameterDictionary">ParameterDictionary that contains
|
||||
/// canonical names and material types.</param>
|
||||
/// <param name="unitDictionary">Unit dictionary that contains canonical
|
||||
/// unit names.</param>
|
||||
public ClinicLine(string line,
|
||||
Thesaurus.Parameters parameterDictionary,
|
||||
Thesaurus.Units unitDictionary)
|
||||
{
|
||||
OriginalLine = line;
|
||||
_parameterDictionary = parameterDictionary;
|
||||
_unitDictionary = unitDictionary;
|
||||
Parse();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to parse a line.
|
||||
/// </summary>
|
||||
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(?<item>[^:]+:(\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<NLog.Logger> _logger = new Lazy<NLog.Logger>(() => NLog.LogManager.GetCurrentClassLogger());
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
258
zaaReloaded2/Importer/ClinicImporter/ClinicTimePoint.cs
Executable file
258
zaaReloaded2/Importer/ClinicImporter/ClinicTimePoint.cs
Executable file
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds all laboratory items for a given time point.
|
||||
/// </summary>
|
||||
class ClinicTimePoint : TimePoint
|
||||
{
|
||||
#region Static methods
|
||||
|
||||
/// <summary>
|
||||
/// Examines a string and returns true if it resembles
|
||||
/// a time stamp line in the clinic output.
|
||||
/// </summary>
|
||||
/// <param name="line">Line to examine.</param>
|
||||
/// <returns>True if line resembles a time stamp line
|
||||
/// in the clinic output.</returns>
|
||||
static public bool IsTimeStampLine(string line)
|
||||
{
|
||||
return _timeStampRegex.IsMatch(line);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a Regex object that matches a clinic time stamp
|
||||
/// line.
|
||||
/// </summary>
|
||||
static public Regex TimeStampRegex
|
||||
{
|
||||
get
|
||||
{
|
||||
return _timeStampRegex;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array of lines in this ClinicText.
|
||||
/// </summary>
|
||||
public IList<String> Lines
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get
|
||||
{
|
||||
if (_lines == null)
|
||||
{
|
||||
_lines = new List<String>();
|
||||
}
|
||||
return _lines;
|
||||
}
|
||||
set
|
||||
{
|
||||
_lines = value;
|
||||
ParseLines();
|
||||
}
|
||||
}
|
||||
|
||||
/// <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
|
||||
{
|
||||
return Items.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the original Lauris text for this timepoint.
|
||||
/// </summary>
|
||||
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<String> lines,
|
||||
Parameters parameterDictionary,
|
||||
Units unitDictionary)
|
||||
: this(parameterDictionary, unitDictionary)
|
||||
{
|
||||
Lines = lines;
|
||||
}
|
||||
|
||||
public ClinicTimePoint(IList<String> lines)
|
||||
: this(lines, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ClinicTimePoint(
|
||||
Parameters parameterDictionary,
|
||||
Units unitDictionary)
|
||||
: this()
|
||||
{
|
||||
_parameterDictionary = parameterDictionary;
|
||||
_unitDictionary = unitDictionary;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public methods
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new line to this time point by parsing
|
||||
/// the line for a laboratory item.
|
||||
/// </summary>
|
||||
/// <param name="paragraph">Line to add.</param>
|
||||
public override void Parse(string paragraph)
|
||||
{
|
||||
Lines.Add(paragraph);
|
||||
ParseLine(paragraph);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
|
||||
/// <summary>
|
||||
/// Analyzes each clinic line in this time point, sets the date
|
||||
/// and time, and collects LabItem data.
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// A regular expression that matches the time stamp in the first
|
||||
/// paragraph of a LaurisText.
|
||||
/// </summary>
|
||||
static readonly Regex _timeStampRegex = new Regex(
|
||||
@"^(Labor:?)?\s*\(?\s*(?<datetime>\d\d\.\d\d\.\d\d\d\d\s+\d\d:\d\d)(:00)?\)\s*$");
|
||||
IList<String> _lines;
|
||||
Parameters _parameterDictionary;
|
||||
Units _unitDictionary;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Class logger
|
||||
|
||||
private static NLog.Logger Logger { get { return _logger.Value; } }
|
||||
|
||||
private static readonly Lazy<NLog.Logger> _logger = new Lazy<NLog.Logger>(() => NLog.LogManager.GetCurrentClassLogger());
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
31
zaaReloaded2/Importer/ImportMode.cs
Executable file
31
zaaReloaded2/Importer/ImportMode.cs
Executable file
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Attempts to automatically detect laboratory data in the Word
|
||||
/// document.
|
||||
/// </summary>
|
||||
/// <param name="document">Document which to parse for laboratory
|
||||
/// data.</param>
|
||||
/// <returns>True if laboratory data was detected, false if not.</returns>
|
||||
/// <exception cref="ArgumentNullException">if <paramref name="document"/>
|
||||
/// is null.</exception>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a paragraph is either a time stamp line
|
||||
/// or a paragraph with laboratory items.
|
||||
/// </summary>
|
||||
/// <param name="paragraph"></param>
|
||||
/// <returns></returns>
|
||||
private static bool IsLabParagraph(Paragraph paragraph)
|
||||
{
|
||||
string text = paragraph.Range.Text;
|
||||
return (LaurisParagraph.ResemblesLaurisParagraph(text)
|
||||
|| LaurisTimePoint.IsTimeStampLine(text));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the index of a paragraph.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://word.mvps.org/faqs/macrosvba/GetIndexNoOfPara.htm
|
||||
/// </remarks>
|
||||
/// <param name="paragraph">Paragraph whose index to return.</param>
|
||||
/// <returns>Index of the paragraph.</returns>
|
||||
private static int GetParagraphIndex(Document document, Paragraph paragraph)
|
||||
{
|
||||
return document.Range(0, paragraph.Range.Start).Paragraphs.Count;
|
||||
}
|
||||
}
|
||||
}
|
@ -169,7 +169,7 @@ namespace zaaReloaded2.Importer.ZaaImporter
|
||||
/// the paragraph for laboratory items.
|
||||
/// </summary>
|
||||
/// <param name="paragraph">Paragraph to add.</param>
|
||||
public void AddParagraph(string paragraph)
|
||||
public override void Parse(string paragraph)
|
||||
{
|
||||
Paragraphs.Add(paragraph);
|
||||
ParseParagraph(paragraph);
|
||||
|
@ -30,106 +30,30 @@ namespace zaaReloaded2.Importer.ZaaImporter
|
||||
/// Imports laboratory items by parsing the Lauris data from a
|
||||
/// physician's letter.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits the <paramref name="text"/> into individual time points
|
||||
/// and creates <see cref="LaurisTimePoint"/> objects from them.
|
||||
/// </summary>
|
||||
/// <param name="text">ZAA-formatted Lauris output to import.</param>
|
||||
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
|
||||
|
||||
|
@ -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<NLog.Logger> _logger = new Lazy<NLog.Logger>(() => NLog.LogManager.GetCurrentClassLogger());
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
2
zaaReloaded2/Properties/Settings.Designer.cs
generated
2
zaaReloaded2/Properties/Settings.Designer.cs
generated
@ -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"]));
|
||||
|
@ -6,7 +6,7 @@
|
||||
<Value Profile="(Default)">zaaReloaded2</Value>
|
||||
</Setting>
|
||||
<Setting Name="PubYear" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">2015-2017</Value>
|
||||
<Value Profile="(Default)">2017</Value>
|
||||
</Setting>
|
||||
<Setting Name="Authors" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">Daniel Kraus</Value>
|
||||
|
@ -1,2 +1,2 @@
|
||||
2.3.2
|
||||
2.3.2.0
|
||||
2.4.0
|
||||
2.4.0.0
|
||||
|
@ -30,7 +30,7 @@
|
||||
<value>zaaReloaded2</value>
|
||||
</setting>
|
||||
<setting name="PubYear" serializeAs="String">
|
||||
<value>2015-2017</value>
|
||||
<value>2017</value>
|
||||
</setting>
|
||||
<setting name="Authors" serializeAs="String">
|
||||
<value>Daniel Kraus</value>
|
||||
|
@ -21,6 +21,6 @@
|
||||
<packages>
|
||||
<package id="Bovender" version="0.17.0.0" targetFramework="net40" />
|
||||
<package id="Expression.Blend.Sdk" version="1.0.2" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.3" targetFramework="net40" />
|
||||
<package id="YamlDotNet.Signed" version="4.1.0" targetFramework="net40" />
|
||||
<package id="NLog" version="4.4.12" targetFramework="net40" />
|
||||
</packages>
|
@ -140,7 +140,7 @@
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Expression.Interactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.4.3\lib\net40\NLog.dll</HintPath>
|
||||
<HintPath>..\packages\NLog.4.4.12\lib\net40\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
@ -204,7 +204,11 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Commands.cs" />
|
||||
<Compile Include="Helpers.cs" />
|
||||
<Compile Include="Importer\ZaaImporter\AutoDetect.cs" />
|
||||
<Compile Include="Importer\ClinicImporter\ClinicLine.cs" />
|
||||
<Compile Include="Importer\ClinicImporter\ClinicTimePoint.cs" />
|
||||
<Compile Include="Importer\ClinicImporter\ClinicImporter.cs" />
|
||||
<Compile Include="Importer\BaseImporter.cs" />
|
||||
<Compile Include="Importer\AutoDetector.cs" />
|
||||
<Compile Include="Controller\Comments\CommentPool.cs" />
|
||||
<Compile Include="Controller\Elements\ControlElementBase.cs" />
|
||||
<Compile Include="Controller\Elements\FormatElementBase.cs" />
|
||||
@ -231,6 +235,7 @@
|
||||
<Compile Include="Formatter\DanielsStyle.cs" />
|
||||
<Compile Include="Formatter\DocumentWriter.cs" />
|
||||
<Compile Include="Formatter\NoLaboratoryDataException.cs" />
|
||||
<Compile Include="Importer\ImportMode.cs" />
|
||||
<Compile Include="LogFile.cs" />
|
||||
<Compile Include="Medication\Formatter.cs" />
|
||||
<Compile Include="Medication\Importer.cs" />
|
||||
@ -466,6 +471,7 @@
|
||||
<ItemGroup>
|
||||
<Resource Include="Icons\mm.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
|
Loading…
Reference in New Issue
Block a user