From a2796abe1a60784871f9982cb0e3d47479977cf0 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 20 Feb 2025 17:05:08 +0100 Subject: [PATCH 01/10] bug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result providerbug6096: first compilable version of sailwave.html result provider --- .../raceanalysis.product | 1 + java/com.sap.sailing.feature/feature.xml | 4 + .../.classpath | 16 + .../.project | 28 + .../org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 7 + .../.settings/org.eclipse.pde.core.prefs | 3 + .../META-INF/MANIFEST.MF | 10 + .../build.properties | 4 + .../pom.xml | 12 + .../resources/29er.html | 542 +++++++++ .../resources/ILCA4.html | 1016 +++++++++++++++++ .../resources/ILCA6.html | 422 +++++++ .../resources/ILCA7.html | 188 +++ .../test/SimpleHtmlParsingTest.java | 146 +++ .../.classpath | 7 + .../.project | 28 + .../org.eclipse.core.resources.prefs | 2 + .../.settings/org.eclipse.jdt.core.prefs | 7 + .../.settings/org.eclipse.pde.core.prefs | 3 + .../META-INF/MANIFEST.MF | 16 + .../build.properties | 4 + .../pom.xml | 12 + .../html/resultimport/impl/Activator.java | 30 + .../resultimport/impl/SailwaveHtmlParser.java | 258 +++++ .../impl/ScoreCorrectionProviderImpl.java | 98 ++ java/pom.xml | 2 + 27 files changed, 2868 insertions(+) create mode 100644 java/com.sap.sailing.sailwave.html.resultimport.test/.classpath create mode 100644 java/com.sap.sailing.sailwave.html.resultimport.test/.project create mode 100644 java/com.sap.sailing.sailwave.html.resultimport.test/.settings/org.eclipse.core.resources.prefs create mode 100644 java/com.sap.sailing.sailwave.html.resultimport.test/.settings/org.eclipse.jdt.core.prefs create mode 100644 java/com.sap.sailing.sailwave.html.resultimport.test/.settings/org.eclipse.pde.core.prefs create mode 100644 java/com.sap.sailing.sailwave.html.resultimport.test/META-INF/MANIFEST.MF create mode 100644 java/com.sap.sailing.sailwave.html.resultimport.test/build.properties create mode 100644 java/com.sap.sailing.sailwave.html.resultimport.test/pom.xml create mode 100644 java/com.sap.sailing.sailwave.html.resultimport.test/resources/29er.html create mode 100644 java/com.sap.sailing.sailwave.html.resultimport.test/resources/ILCA4.html create mode 100644 java/com.sap.sailing.sailwave.html.resultimport.test/resources/ILCA6.html create mode 100644 java/com.sap.sailing.sailwave.html.resultimport.test/resources/ILCA7.html create mode 100755 java/com.sap.sailing.sailwave.html.resultimport.test/src/com/sap/sailing/sailwave/html/resultimport/test/SimpleHtmlParsingTest.java create mode 100644 java/com.sap.sailing.sailwave.html.resultimport/.classpath create mode 100644 java/com.sap.sailing.sailwave.html.resultimport/.project create mode 100644 java/com.sap.sailing.sailwave.html.resultimport/.settings/org.eclipse.core.resources.prefs create mode 100644 java/com.sap.sailing.sailwave.html.resultimport/.settings/org.eclipse.jdt.core.prefs create mode 100644 java/com.sap.sailing.sailwave.html.resultimport/.settings/org.eclipse.pde.core.prefs create mode 100644 java/com.sap.sailing.sailwave.html.resultimport/META-INF/MANIFEST.MF create mode 100644 java/com.sap.sailing.sailwave.html.resultimport/build.properties create mode 100644 java/com.sap.sailing.sailwave.html.resultimport/pom.xml create mode 100755 java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/Activator.java create mode 100755 java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/SailwaveHtmlParser.java create mode 100755 java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/ScoreCorrectionProviderImpl.java diff --git a/java/com.sap.sailing.feature.p2build/raceanalysis.product b/java/com.sap.sailing.feature.p2build/raceanalysis.product index 788b713684c..d5ed9bd5409 100755 --- a/java/com.sap.sailing.feature.p2build/raceanalysis.product +++ b/java/com.sap.sailing.feature.p2build/raceanalysis.product @@ -68,6 +68,7 @@ + diff --git a/java/com.sap.sailing.feature/feature.xml b/java/com.sap.sailing.feature/feature.xml index f61d03f5c38..e8e2a3338c3 100755 --- a/java/com.sap.sailing.feature/feature.xml +++ b/java/com.sap.sailing.feature/feature.xml @@ -133,6 +133,10 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al id="com.sap.sailing.sailwave.resultimport" version="0.0.0"/> + + diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/.classpath b/java/com.sap.sailing.sailwave.html.resultimport.test/.classpath new file mode 100644 index 00000000000..f04af4e1861 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/.classpath @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/.project b/java/com.sap.sailing.sailwave.html.resultimport.test/.project new file mode 100644 index 00000000000..ff164044fc2 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/.project @@ -0,0 +1,28 @@ + + + com.sap.sailing.sailwave.html.resultimport.test + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/.settings/org.eclipse.core.resources.prefs b/java/com.sap.sailing.sailwave.html.resultimport.test/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..99f26c0203a --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/.settings/org.eclipse.jdt.core.prefs b/java/com.sap.sailing.sailwave.html.resultimport.test/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0869a9baf86 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/.settings/org.eclipse.pde.core.prefs b/java/com.sap.sailing.sailwave.html.resultimport.test/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000000..f29e940a005 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.sailwave.html.resultimport.test/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..39d9e3a68f0 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/META-INF/MANIFEST.MF @@ -0,0 +1,10 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Test +Bundle-SymbolicName: com.sap.sailing.sailwave.html.resultimport.test +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: SAP +Fragment-Host: com.sap.sailing.sailwave.html.resultimport +Require-Bundle: org.junit +Automatic-Module-Name: com.sap.sailing.sailwave.html.resultimport.test +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/build.properties b/java/com.sap.sailing.sailwave.html.resultimport.test/build.properties new file mode 100644 index 00000000000..34d2e4d2dad --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/pom.xml b/java/com.sap.sailing.sailwave.html.resultimport.test/pom.xml new file mode 100644 index 00000000000..cb07245128e --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + root + com.sap.sailing + 1.0.0-SNAPSHOT + + com.sap.sailing.sailwave.html.resultimport.test + eclipse-test-plugin + diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/resources/29er.html b/java/com.sap.sailing.sailwave.html.resultimport.test/resources/29er.html new file mode 100644 index 00000000000..4dd55fd8698 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/resources/29er.html @@ -0,0 +1,542 @@ + + + + + + + + +Sailwave results for 2025 29er Asian Championship at 2025 + + + + + + + + + +
+
+ +
+ + +

2025 29er Asian Championship

+

+ +
+ + +

Results are provisional as of 19:09 on February 15, 2025

+

Overall

+
Sailed: 12, Discards: 2, To count: 10, Entries: 19, Scoring system: Appendix A
+ ++++++++++++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RankClassDivisionsNatSail NoSailorsR1R2R3R4R5R6R7R8R9R10R11R12TotalNett
1st29erMixed3356Raphael Mak, Tiffany Mak1.01.01.02.0(3.0)3.02.01.0(6.0)1.02.02.025.016.0
2nd29erMen20Kevin Cason, Holland Vierling(7.0)(6.0)3.01.02.01.05.03.02.02.01.03.036.023.0
3rd29erMixed621Patcharaphan Ongkaloy, Kan Kachachuen4.03.0(6.0)3.05.02.06.02.04.0(7.0)5.04.051.038.0
4th29erJunior , Men3354Ethan Kiu, Louis Polson2.0(8.0)2.07.0(9.0)7.01.06.03.08.04.01.058.041.0
5th29erWomen2840Sienne Thiry, Tomoe Thiry3.05.07.04.04.04.04.0(20.0 DSQ)5.0(9.0)8.05.078.049.0
6th29erMen3398Ayden Pang, Xu Peng CHEN6.04.04.0(11.0)6.011.0(20.0 DSQ)5.07.05.03.07.089.058.0
7th29erMixed2566Chloe Kong, Ethan Kong5.011.05.05.08.06.0(20.0 SCP50)(20.0 DSQ)9.06.06.06.0107.067.0
8th29erJunior , Women3355ZiHan Liu, Bernice Pang8.0(12.0)10.0(12.0)11.09.03.04.01.03.010.09.092.068.0
9th29erJunior , Men3405Nicholas Hon, Kaden Chan(12.0)2.08.010.0(15.0)12.012.07.010.04.07.08.0107.080.0
10th29erWomen3393Kristen Hwang, McCarley Wong9.07.012.08.07.05.07.010.08.0(14.0)(13.0)10.0110.083.0
11th29erMen3055Yan Cheuk NG, Kam Hing HU11.09.09.06.0(13.0)10.09.0(20.0 DSQ)12.011.09.011.0130.097.0
12th29erJunior , Men3383James Ashwood, Conrad Lumsden(13.0)10.011.09.012.0(20.0 RET)8.09.013.012.011.012.0140.0107.0
13th29erMen3056Kyle Lee, Brandon Liu10.0(14.0)(13.0)13.010.013.010.08.011.010.012.013.0137.0110.0
14th29erMixed2750Hins Law, Daisy Chan14.013.014.014.0(16.0)14.013.0(20.0 UFD)15.013.014.014.0174.0138.0
15th29erJunior , Women2846Alexandra Yam, Keira Slaughter15.015.0(20.0 RET)(20.0 DNF)20.0 RET15.014.012.014.016.015.015.0191.0151.0
16th29erMen3053Cameron Law, Christopher Lam(20.0 DNC)(20.0 DNC)20.0 DNC20.0 DNC1.08.04.5 RDG20.0 DNS20.0 DNC20.0 DNC20.0 DNC20.0 DNC193.5153.5
17th29erJunior, Mixed2531Belmira Iong, Alfred Fong(20.0 NSC)(20.0 NSC)20.0 DNS20.0 RET17.020.0 DNF20.0 DNF13.016.015.016.016.0213.0173.0
18th29erMixed2521Jade Zirah, Alfred Yip16.0(20.0 DNF)(20.0 DNF)20.0 RET14.020.0 RET15.011.020.0 DNC20.0 DNC20.0 DNC20.0 DNC216.0176.0
19th29erJunior , Men2411Sebastian Chun, Ambrose Chan(20.0 DNC)(20.0 DNC)20.0 DNC20.0 DNC20.0 DNC20.0 DNC20.0 DNC20.0 DNC20.0 DNC20.0 DNC20.0 DNC20.0 DNC240.0200.0
+ +


+


+

Sailwave Scoring Software 2.37.00
www.sailwave.com

+ +
+ +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/resources/ILCA4.html b/java/com.sap.sailing.sailwave.html.resultimport.test/resources/ILCA4.html new file mode 100644 index 00000000000..6bcb8fb5169 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/resources/ILCA4.html @@ -0,0 +1,1016 @@ + + + + + + + + +Sailwave results for Sun Hung Kai & Co. Hong Kong Race Week 2025 at 2025 + + + + + + + + + +
+
+ +
+ + +

Sun Hung Kai & Co. Hong Kong Race Week 2025

+

+ +
+ + +

Results are provisional as of 19:07 on February 15, 2025

+

ILCA 4 Class

+
Sailed: 9, Discards: 2, To count: 7, Entries: 50, Scoring system: Appendix A
+ ++++++++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RankClassNatSail NoHelm NameR1R2R3R4R5R6R7R8R9TotalNett
1stILCA 4220790Charalampos VELIANITIS1.01.01.0(3.0)1.01.03.0(6.0)1.018.09.0
2ndILCA 4221947Torn RATTANA3.02.04.0(51.0 DSQ)4.03.0(8.0)1.02.078.019.0
3rdILCA 4221400Zixi Huang4.03.0(6.0)2.02.05.01.0(10.0)5.038.022.0
4thILCA 4215277Cyrus Yung5.04.03.0(6.0)3.0(15.0)4.02.03.045.024.0
5thILCA 4216831Che LIU2.0(10.0)2.01.0(10.0)2.07.07.04.045.025.0
6thILCA 4215482Jorge Wong11.07.0(24.0)11.07.0(12.0)6.03.06.087.051.0
7thILCA 4210425Howan Luo7.011.010.0(14.0 RDG)5.011.02.0(24.0)8.092.054.0
8thILCA 4210325Jason Lin15.06.05.04.09.0(18.0)5.0(21.0)10.093.054.0
9thILCA 4214494Yinran Chen8.013.0(15.0)5.013.04.012.04.0(14.0)88.059.0
10thILCA 4225502CONGGUO Huang6.05.012.09.0(30.0)14.011.0(22.0)13.0122.070.0
11thILCA 4209902Avelino SHIN10.08.07.07.0(25.0)9.014.0(33.0)16.0129.071.0
12thILCA 4211709Thomas Ko13.0(17.0)9.08.015.010.010.0(16.0)12.0110.077.0
13thILCA 4229200Guo Chen(20.0)(26.0)17.013.06.07.015.014.07.0125.079.0
14thILCA 4209310Ivy So9.016.016.0(21.0)17.06.09.020.0(21.0)135.093.0
15thILCA 4210816Yufei Chen(43.0)12.08.014.0(31.0)8.017.018.019.0170.096.0
16thILCA 4214493Joe Cai(21.0)9.018.015.0(24.0)16.013.09.018.0143.098.0
17thILCA 4213348Marcus LI14.014.013.012.021.013.022.0(29.0)(25.0)163.0109.0
18thILCA 4223620Boxuan Yu(24.0)18.011.018.016.0(28.0)19.023.09.0166.0114.0
19thILCA 4214251Reyes Jit Eng Tan(26.0)21.020.010.012.021.020.012.0(32.0)174.0116.0
20thILCA 4221551Wang Nina12.022.019.0(31.0)8.020.021.0(27.0)15.0175.0117.0
21stILCA 4205828Ela Murat19.0(25.0)14.019.018.0(24.0)16.019.017.0171.0122.0
22ndILCA 4221877Xu Xiaorong16.020.025.017.026.0(51.0 UFD)(51.0 RET)8.024.0238.0136.0
23rdILCA 4214467Qinghua Hu22.027.023.022.011.0(29.0)29.0(34.0)22.0219.0156.0
24thILCA 4221313Yifan Han18.0(28.0)26.023.020.0(32.0)18.026.026.0217.0157.0
25thILCA 4223600Jin Song Zhang27.019.022.016.0(28.0)27.025.0(38.0)23.0225.0159.0
26thILCA 4211688Yilin Elaine DONG(31.0)(36.0)28.027.022.030.023.015.020.0232.0165.0
27thILCA 4220808JiaLe Yang25.015.021.026.032.019.032.0(36.0)(33.0)239.0170.0
28thILCA 4214466Cheryl Shen23.023.029.020.014.0(35.0)31.032.0(38.0)245.0172.0
29thILCA 4191718Zhuowen Sophie Shao29.0(31.0)27.025.0(35.0)25.024.017.030.0243.0177.0
30thILCA 4211703Wong Tsz Lung28.024.030.024.027.017.0(51.0 DSQ)28.0(31.0)260.0178.0
31stILCA 4213350Charlie Cheung32.0(34.0)(34.0)33.019.031.027.011.028.0249.0181.0
32ndILCA 4206799John Raphael Lim(33.0)32.031.030.023.0(34.0)30.013.029.0255.0188.0
33rdILCA 4221094YONG LIANG Chuang17.030.033.0(51.0 DNS)(51.0 DNC)51.0 DNC51.0 DNC5.011.0300.0198.0
34thILCA 4221204ShaYue WU(39.0)29.037.028.029.036.028.0(41.0)27.0294.0214.0
35thILCA 4211740Sai Kit Tse(36.0)(37.0)35.032.033.022.033.030.035.0293.0220.0
36thILCA 4213329Cyrus Chan34.0(38.0)(40.0)34.034.033.026.025.034.0298.0220.0
37thILCA 4209318Ryan Cheung35.033.032.029.0(37.0)26.036.0(37.0)36.0301.0227.0
38thILCA 4220078ZhiRen LUO30.035.0(51.0 DNF)(51.0 DNF)38.023.034.035.037.0334.0232.0
39thILCA 4220428ShengXuan CHENG38.039.036.037.039.037.037.0(43.0)(40.0)346.0263.0
40thILCA 4226328YaKun XU37.040.0(41.0)36.036.0(51.0 DNF)39.040.039.0359.0267.0
41stILCA 4211722Yuxuan Liu40.0(51.0 RET)38.035.041.038.040.0(42.0)41.0366.0273.0
42ndILCA 4220821YiFan LIU41.041.039.0(51.0 DNC)40.039.038.039.0(51.0 NSC)379.0277.0
43rdILCA 4211727Yeuk Tung Heather Fang44.0(51.0 DNF)42.0(51.0 DNF)51.0 DNC51.0 DNC51.0 DNC31.042.0414.0312.0
44thILCA 4220819ZeAn LI42.042.0(51.0 DNF)(51.0 DNS)42.051.0 DNF51.0 DNF44.044.0418.0316.0
45thILCA 4220409YuLe SHI(51.0 DNF)43.0(51.0 DNF)51.0 DNF51.0 DNF51.0 DNF35.045.043.0421.0319.0
46thILCA 4121111Kellen Quek(51.0 DNC)(51.0 DNC)51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC459.0357.0
46thILCA 4187010Kai Storey(51.0 DNC)(51.0 DNC)51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC459.0357.0
46thILCA 4TBDZiRui FAN(51.0 DNC)(51.0 DNC)51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC459.0357.0
46thILCA 4TBDXi WEI(51.0 DNC)(51.0 DNC)51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC459.0357.0
46thILCA 4222437Tiago Cheng De Villemor Salgado(51.0 DNC)(51.0 DNC)51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC51.0 DNC459.0357.0
+ +


+


+

Sailwave Scoring Software 2.37.00
www.sailwave.com

+ +
+ +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/resources/ILCA6.html b/java/com.sap.sailing.sailwave.html.resultimport.test/resources/ILCA6.html new file mode 100644 index 00000000000..7de296f1a08 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/resources/ILCA6.html @@ -0,0 +1,422 @@ + + + + + + + + +Sailwave results for Sun Hung Kai & Co. Hong Kong Race Week 2025 at 2025 + + + + + + + + + +
+
+ +
+ + +

Sun Hung Kai & Co. Hong Kong Race Week 2025

+

+ +
+ + +

Results are provisional as of 9:43 on February 16, 2025

+

ILCA 6 Class

+
Sailed: 9, Discards: 2, To count: 7, Entries: 17, Scoring system: Appendix A
+ ++++++++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RankClassNatSail NoHelm NameR1R2R3R4R5R6R7R8R9TotalNett
1stILCA 6191713Stephanie Norton1.01.0(2.0)1.0(2.0)1.01.01.01.011.07.0
2ndILCA 6211717Nancy Highfield(2.0)2.01.02.01.02.02.0(11.0)2.025.012.0
3rdILCA 6208625NANA Funazawa3.04.05.03.03.03.04.0(7.0)(6.0)38.025.0
4thILCA 6223750Daniel Kin Chung Chan(10.0)3.03.04.0(5.0)4.03.04.04.040.025.0
5thILCA 6217702Haruka Hattori4.06.08.08.07.0(9.0)5.0(10.0)3.060.041.0
6thILCA 6209319Seb Van Ommeren5.0(8.0)7.07.0(13.0)8.06.02.08.064.043.0
7thILCA 6223276Xinran Chen7.07.0(11.0)(9.0)4.06.08.06.09.067.047.0
8thILCA 6210199Haolun Xia(11.0 SCP30%)5.06.05.06.0(11.0)10.08.07.069.047.0
9thILCA 6213211Xavier Wilde8.0(11.0)4.06.09.07.0(11.0)9.05.070.048.0
10thILCA 6221934Samuel Tan-Hardy9.09.010.0(12.0)8.05.09.03.0(11.0)76.053.0
11thILCA 6221401Ziyan Huang11.010.09.010.011.010.07.0(17.0)(15.0 SCP30%)100.068.0
12thILCA 6225262John Gabriel LIM(12.0)12.012.011.010.012.012.0(13.9 SCP5%)12.0106.981.0
13thILCA 6225505Yan Duo Pu(15.0)(16.0)14.015.014.014.013.05.014.0120.089.0
14thILCA 6213316Adam Kan(13.0)13.013.013.012.013.0(14.0)12.013.0116.089.0
15thILCA 6213251Nick Akov14.0(15.0)(15.0)14.015.015.015.014.015.0132.0102.0
16thILCA 6211730Jeremy Chan(16.0)14.016.016.016.016.0(18.0 DNF)16.016.0144.0110.0
17thILCA 6213343Marcello Giamporcaro(18.0 DNC)(18.0 DNC)18.0 DNC18.0 DNC18.0 DNC18.0 DNC18.0 DNC15.017.0158.0122.0
+ +


+


+

Sailwave Scoring Software 2.37.00
www.sailwave.com

+ +
+ +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/resources/ILCA7.html b/java/com.sap.sailing.sailwave.html.resultimport.test/resources/ILCA7.html new file mode 100644 index 00000000000..d7bd996ba3c --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/resources/ILCA7.html @@ -0,0 +1,188 @@ + + + + + + + + +Sailwave results for Sun Hung Kai & Co. Hong Kong Race Week 2025 at 2025 + + + + + + + + + +
+
+ +
+ + +

Sun Hung Kai & Co. Hong Kong Race Week 2025

+

+ +
+ + +

Results are provisional as of 19:08 on February 15, 2025

+

ILCA 7 Class

+
Sailed: 9, Discards: 2, To count: 7, Entries: 4, Scoring system: Appendix A
+ ++++++++++++++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RankClassNatSail NoHelm NameR1R2R3R4R5R6R7R8R9TotalNett
1stILCA 7171979Nicholas Halliday(1.0)1.01.01.0(2.0)1.01.01.01.010.07.0
2ndILCA 7215313Peter Jessop(2.0)(2.0)2.02.01.02.02.02.02.017.013.0
3rdILCA 7150109Michael Wilson(5.0 DNF)(5.0 DNF)5.0 DNF5.0 DNC5.0 DNC5.0 DNC5.0 DNC3.03.041.031.0
4thILCA 7221751Axel Wieland3.03.0(5.0 DNC)(5.0 DNC)5.0 DNC5.0 DNC5.0 DNC5.0 DNC5.0 DNC41.031.0
+ +


+


+

Sailwave Scoring Software 2.37.00
www.sailwave.com

+ +
+ +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/src/com/sap/sailing/sailwave/html/resultimport/test/SimpleHtmlParsingTest.java b/java/com.sap.sailing.sailwave.html.resultimport.test/src/com/sap/sailing/sailwave/html/resultimport/test/SimpleHtmlParsingTest.java new file mode 100755 index 00000000000..889fa87af39 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/src/com/sap/sailing/sailwave/html/resultimport/test/SimpleHtmlParsingTest.java @@ -0,0 +1,146 @@ +package com.sap.sailing.sailwave.html.resultimport.test; + + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.List; + +import org.junit.Test; + +import com.sap.sailing.resultimport.CompetitorRow; +import com.sap.sailing.resultimport.RegattaResults; +import com.sap.sailing.sailwave.html.resultimport.impl.SailwaveHtmlParser; +import com.sap.sse.common.Util; + +public class SimpleHtmlParsingTest { + @Test + public void testOpenSampleHtml() throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("ILCA4.html"))); + final String readLine = br.readLine(); + assertNotNull(readLine); + br.close(); + } + + @Test + public void testMultiLineTD() throws IOException { + final InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("ILCA6.html"); + SailwaveHtmlParser parser = new SailwaveHtmlParser(); + final RegattaResults regattaResults = parser.getRegattaResults(resourceAsStream); + List result = regattaResults.getCompetitorResults(); + assertFalse(result.isEmpty()); + assertEquals(17, result.size()); + assertTrue(regattaResults.getMetadata().get("seriestitle").contains("Results are provisional as of 9:43 on February 16, 2025")); + for (CompetitorRow row : result) { + if (Util.contains(row.getNames(), "Daniel Kin Chung Chan")) { + assertEquals("HKG 223750", row.getSailID()); + assertEquals(25.0, row.getScoreAfterDiscarding(), 0.000000001); + assertEquals(40.0, row.getTotalPointsBeforeDiscarding(), 0.000000001); + } + } + } + + @Test + public void testEmptyAndDashedScores() throws IOException { + final InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("ILCA7.html"); + SailwaveHtmlParser parser = new SailwaveHtmlParser(); + List result = parser.getRegattaResults(resourceAsStream).getCompetitorResults(); + assertFalse(result.isEmpty()); + assertEquals(117, result.size()); + for (CompetitorRow row : result) { + if (Util.contains(row.getNames(), "Nicholas Halliday")) { + assertEquals("HKG 171979", row.getSailID()); + assertEquals(7.0, row.getScoreAfterDiscarding(), 0.000000001); + assertEquals(10.0, row.getTotalPointsBeforeDiscarding(), 0.000000001); + assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getRank()); + assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getScore()); + assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).isDiscarded()); + assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getRank()); + assertEquals((double) 118.00, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getScore(), 0.000000001); + assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).isDiscarded()); + } else if (Util.contains(row.getNames(), "HAGAN Douglas")) { + assertEquals("AUS 8817", row.getSailID()); + assertEquals(235.00, row.getScoreAfterDiscarding(), 0.000000001); + assertEquals(235.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); + assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getRank()); + assertEquals("DNF", Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getMaxPointsReason()); + assertEquals((double) 117.00, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getScore(), 0.000000001); + assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).isDiscarded()); + assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getRank()); + assertEquals("DNF", Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getMaxPointsReason()); + assertEquals((double) 118.00, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getScore(), 0.000000001); + assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).isDiscarded()); + } + } + } + + @Test + public void testGetCompetitorRows505() throws IOException { + SailwaveHtmlParser parser = new SailwaveHtmlParser(); + final InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("29er.html"); + List result = parser.getRegattaResults(resourceAsStream).getCompetitorResults(); + assertFalse(result.isEmpty()); + assertEquals(75, result.size()); + for (CompetitorRow row : result) { + if (Util.contains(row.getNames(), "HOLZAPFEL Alexander")) { + assertEquals("GER 8975", row.getSailID()); + assertEquals(60.00, row.getScoreAfterDiscarding(), 0.000000001); + assertEquals(74.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); + assertEquals((int) 11, (int) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getRank()); + assertEquals((double) 11, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getScore(), 0.000000001); + assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).isDiscarded()); + } else if (Util.contains(row.getNames(), "BART Cedric")) { + assertEquals("SUI 8543", row.getSailID()); + assertEquals(55.00, row.getScoreAfterDiscarding(), 0.000000001); + assertEquals(74.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); + assertEquals((int) 2, (int) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 2).getRank()); + assertEquals((double) 2, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 2).getScore(), 0.000000001); + assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 2).isDiscarded()); + assertEquals((int) 19, (int) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 3).getRank()); + assertEquals((double) 19, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 3).getScore(), 0.000000001); + assertEquals(true, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 3).isDiscarded()); + } else if (Util.contains(row.getNames(), "LEWNS Chris")) { + assertEquals("GBR 9057", row.getSailID()); + assertEquals(64.00, row.getScoreAfterDiscarding(), 0.000000001); + assertEquals(140.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); + assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 7).getRank()); + assertEquals("DNF", Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 7).getMaxPointsReason()); + assertEquals((double) 76, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 7).getScore(), 0.000000001); + assertEquals(true, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 7).isDiscarded()); + } + } + } + + @Test + public void testGetCompetitorRows29er() throws IOException { + SailwaveHtmlParser parser = new SailwaveHtmlParser(); + final InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("29er.html"); + List result = parser.getRegattaResults(resourceAsStream).getCompetitorResults(); + assertFalse(result.isEmpty()); + assertEquals(62, result.size()); + for (CompetitorRow row : result) { + if (Util.contains(row.getNames(), "HOLSTE Kim (M1993)")) { + assertEquals("GER 1864", row.getSailID()); + assertEquals(58.00, row.getScoreAfterDiscarding(), 0.000000001); + assertEquals(169.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); + assertEquals((int) 25, (int) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getRank()); + assertEquals((double) 25, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getScore(), 0.000000001); + assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).isDiscarded()); + assertEquals((int) 38, (int) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getRank()); + assertEquals((double) 38, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getScore(), 0.000000001); + assertEquals(true, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).isDiscarded()); + assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).getRank()); + assertEquals("DSQ", Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).getMaxPointsReason()); + assertEquals((double) 63, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).getScore(), 0.000000001); + assertEquals(true, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).isDiscarded()); + } + } + } +} diff --git a/java/com.sap.sailing.sailwave.html.resultimport/.classpath b/java/com.sap.sailing.sailwave.html.resultimport/.classpath new file mode 100644 index 00000000000..eca7bdba8f0 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/java/com.sap.sailing.sailwave.html.resultimport/.project b/java/com.sap.sailing.sailwave.html.resultimport/.project new file mode 100644 index 00000000000..ac13c2dfaff --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport/.project @@ -0,0 +1,28 @@ + + + com.sap.sailing.sailwave.html.resultimport + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/java/com.sap.sailing.sailwave.html.resultimport/.settings/org.eclipse.core.resources.prefs b/java/com.sap.sailing.sailwave.html.resultimport/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..99f26c0203a --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/java/com.sap.sailing.sailwave.html.resultimport/.settings/org.eclipse.jdt.core.prefs b/java/com.sap.sailing.sailwave.html.resultimport/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0869a9baf86 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/java/com.sap.sailing.sailwave.html.resultimport/.settings/org.eclipse.pde.core.prefs b/java/com.sap.sailing.sailwave.html.resultimport/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000000..f29e940a005 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/java/com.sap.sailing.sailwave.html.resultimport/META-INF/MANIFEST.MF b/java/com.sap.sailing.sailwave.html.resultimport/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..2887cf86934 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport/META-INF/MANIFEST.MF @@ -0,0 +1,16 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Resultimport +Bundle-SymbolicName: com.sap.sailing.sailwave.html.resultimport +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: com.sap.sailing.sailwave.html.resultimport.impl.Activator +Bundle-Vendor: SAP +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Automatic-Module-Name: com.sap.sailing.sailwave.html.resultimport +Import-Package: org.osgi.framework;version="1.3.0", + org.osgi.util.tracker;version="[1.5.0,2.0.0)" +Require-Bundle: com.sap.sailing.resultimport, + com.sap.sailing.domain.common, + com.sap.sailing.domain.shared.android, + com.sap.sse.common +Bundle-ActivationPolicy: lazy diff --git a/java/com.sap.sailing.sailwave.html.resultimport/build.properties b/java/com.sap.sailing.sailwave.html.resultimport/build.properties new file mode 100644 index 00000000000..34d2e4d2dad --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/java/com.sap.sailing.sailwave.html.resultimport/pom.xml b/java/com.sap.sailing.sailwave.html.resultimport/pom.xml new file mode 100644 index 00000000000..aac8281e502 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + root + com.sap.sailing + 1.0.0-SNAPSHOT + + com.sap.sailing.sailwave.html.resultimport + eclipse-plugin + diff --git a/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/Activator.java b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/Activator.java new file mode 100755 index 00000000000..3736af6591e --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/Activator.java @@ -0,0 +1,30 @@ +package com.sap.sailing.sailwave.html.resultimport.impl; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.util.tracker.ServiceTracker; + +import com.sap.sailing.domain.common.ScoreCorrectionProvider; +import com.sap.sailing.resultimport.ResultUrlRegistry; +import com.sap.sailing.resultimport.impl.ResultUrlRegistryServiceTrackerCustomizer; + +public class Activator implements BundleActivator { + private ServiceTracker resultUrlRegistryServiceTracker; + + public void start(BundleContext bundleContext) throws Exception { + resultUrlRegistryServiceTracker = new ServiceTracker<>(bundleContext, ResultUrlRegistry.class, + new ResultUrlRegistryServiceTrackerCustomizer(bundleContext) { + @Override + protected ScoreCorrectionProvider configureScoreCorrectionProvider( + ResultUrlRegistry resultUrlRegistry) { + final ScoreCorrectionProviderImpl service = new ScoreCorrectionProviderImpl(resultUrlRegistry); + return service; + } + }); + resultUrlRegistryServiceTracker.open(); + } + + public void stop(BundleContext bundleContext) throws Exception { + resultUrlRegistryServiceTracker.close(); + } +} diff --git a/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/SailwaveHtmlParser.java b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/SailwaveHtmlParser.java new file mode 100755 index 00000000000..57f97dd29c5 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/SailwaveHtmlParser.java @@ -0,0 +1,258 @@ +package com.sap.sailing.sailwave.html.resultimport.impl; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.sap.sailing.resultimport.CompetitorEntry; +import com.sap.sailing.resultimport.CompetitorRow; +import com.sap.sailing.resultimport.RegattaResults; +import com.sap.sailing.resultimport.impl.CompetitorRowImpl; +import com.sap.sailing.resultimport.impl.DefaultCompetitorEntryImpl; + +public class SailwaveHtmlParser { + private static final Logger logger = Logger.getLogger(SailwaveHtmlParser.class.getName()); + + public List getRowContents(BufferedReader br) throws IOException { + Pattern tr = Pattern.compile("<(tr|TR)([^<>]*)>"); + Pattern slashTr = Pattern.compile("]*)>"); + boolean inTr = false; + final StringBuilder trContents = new StringBuilder(); + final List tableRows = new ArrayList(); // the contents of the tags found + String readLine = br.readLine(); + int start = 0; + int end = 0; + while (readLine != null && !readLine.contains("")) { + if (!inTr) { + final Matcher trMatcher = tr.matcher(readLine); + boolean foundTr = trMatcher.find(end); + if (foundTr) { + start = trMatcher.end(0); + inTr = true; + } else { + readLine = br.readLine(); + end = 0; + } + } else { // we are within the contents of a tag here + final Matcher slashTrMatcher = slashTr.matcher(readLine); + boolean foundSlashTr = slashTrMatcher.find(start); + if (foundSlashTr) { + end = slashTrMatcher.start(); + inTr = false; + } else { + end = readLine.length(); + } + trContents.append(readLine.substring(start, end)); + if (!foundSlashTr) { + trContents.append('\n'); + readLine = br.readLine(); + start = 0; + } else { + tableRows.add(trContents.toString()); + trContents.delete(0, trContents.length()); + } + } + } + return tableRows; + } + + public List getTagContents(String s, String tag) throws UnsupportedEncodingException { + Pattern tagPattern = Pattern.compile("<("+tag.toLowerCase()+"|"+tag.toUpperCase()+")([^<>]*)>"); + Pattern slashTag = Pattern.compile("]*)>"); + boolean inTag = false; + List result = new ArrayList(); // the contents of the tags found + int start = 0; + int end = 0; + boolean finished = false; + while (!finished) { + if (!inTag) { + final Matcher tagMatcher = tagPattern.matcher(s); + boolean foundTag = tagMatcher.find(end); + if (foundTag) { + start = tagMatcher.end(0); + inTag = true; + } else { + finished = true; + } + } else { // we are within the contents of a tag here + final Matcher slashTagMatcher = slashTag.matcher(s); + boolean foundSlashTag = slashTagMatcher.find(start); + if (foundSlashTag) { + end = slashTagMatcher.start(); + inTag = false; + result.add(URLDecoder.decode(s.substring(start, end).trim(), "UTF-8")); + } else { + result.add(URLDecoder.decode(s.substring(start).trim(), "UTF-8")); + finished = true; + logger.warning("unclosed "+tag+" tag in string \""+s+"\""); + } + } + } + return result; + } + + /** + * @param is closed before the method returns, also in case of exception + */ + public RegattaResults getRegattaResults(InputStream is) throws IOException { + try { + Map classesCounts = new HashMap<>(); // counts the occurrences of boat class names + final List result = new ArrayList(); + final BufferedReader br = new BufferedReader(new InputStreamReader(is)); + final Map metadata = readMetadataBeforeTable(br); + final LinkedHashMap columnStylesAndNames = readTableHeader(br); + findTableBody(br); + final List rowContents = getRowContents(br); + for (final String row : rowContents) { + final List tdContent = getTagContents(row, "td"); + result.add(createCompetitorRow(tdContent, columnStylesAndNames, classesCounts)); + } + return new RegattaResults() { + @Override + public Map getMetadata() { + return metadata; + } + @Override + public List getCompetitorResults() { + return result; + } + }; + } finally { + is.close(); + } + } + + private void findTableBody(BufferedReader br) throws IOException { + String line; + while ((line=br.readLine()) != null && !line.contains("")) + ; + } + + private LinkedHashMap readTableHeader(BufferedReader br) throws IOException { + final LinkedHashMap result = new LinkedHashMap<>(); + final List classes = new ArrayList<>(); + final Pattern colClassPattern = Pattern.compile(""); + final Pattern colTitlePattern = Pattern.compile("([^<]*)"); + String line; + while ((line=br.readLine()) != null && !line.contains("")) + ; + final Iterator classIter = classes.iterator(); + while (line != null && !line.contains(" readMetadataBeforeTable(BufferedReader br) throws IOException { + final Pattern h3MetadataElementPattern = Pattern.compile("

([^<]*)

"); + final Pattern divMetadataElementPattern = Pattern.compile("
([^<]*)
"); + final Map result = new HashMap<>(); + String line; + while ((line=br.readLine()) != null && !line.contains(""); + final Matcher h3Matcher = h3MetadataElementPattern.matcher(line); + if (h3Matcher.matches()) { + result.put(h3Matcher.group(1), h3Matcher.group(2)); + } + final Matcher divMatcher = divMetadataElementPattern.matcher(line); + if (divMatcher.matches()) { + result.put(divMatcher.group(1), divMatcher.group(2)); + } + line = br.readLine(); + } + return result; + } + + private CompetitorRow createCompetitorRow(List trContent, LinkedHashMap columnStylesAndNames, Map classesCounts) throws UnsupportedEncodingException { + final List columnValues = getTagContents(trContent.get(0), "td"); + final Iterator columnValueIterator = columnValues.iterator(); + String nationality = null; + String sailNumber = null; + Integer totalRank = null; + List names = null; + List rankAndMaxPointsReasonAndPointsAndDiscarded = new ArrayList(); + Double scoreAfterDiscarding = null; + Double totalPointsBeforeDiscarding = null; + for (final Entry columnStyleAndName : columnStylesAndNames.entrySet()) { + final String columnValue = columnValueIterator.next(); + switch (columnStyleAndName.getKey()) { + case "rank": + totalRank = Integer.parseInt(columnValue); + break; + case "class": + if (classesCounts.containsKey(columnValue)) { + classesCounts.put(columnValue, classesCounts.get(columnValue)+1); + } else { + classesCounts.put(columnValue, 1); + } + break; + case "nat": + nationality = columnValue; + break; + case "sailno": + sailNumber = columnValue; + break; + case "helmname": + names = getNames(columnValue); + break; + case "race": + CompetitorEntry rankAndMaxPointsReasonAndPointsAndDiscardedForOnceRace = getRankAndMaxPointsReasonAndPointsAndDiscardedForOnceRace(columnValue.trim()); + rankAndMaxPointsReasonAndPointsAndDiscarded.add(rankAndMaxPointsReasonAndPointsAndDiscardedForOnceRace); + break; + case "total": + scoreAfterDiscarding = Double.parseDouble(columnValue); + break; + case "nett": + totalPointsBeforeDiscarding = Double.parseDouble(columnValue); + } + } + return new CompetitorRowImpl(totalRank, nationality+" "+sailNumber, names, scoreAfterDiscarding, totalPointsBeforeDiscarding, + rankAndMaxPointsReasonAndPointsAndDiscarded); + } + + private CompetitorEntry getRankAndMaxPointsReasonAndPointsAndDiscardedForOnceRace(String cell) { + final Pattern oneRaceScorePattern = Pattern.compile("^\\(?([0-9]+\\.[0-9]+)( ([A-Z][A-Z][A-Z]))?.*$"); + boolean isDiscarded = cell.trim().startsWith("(") && cell.trim().endsWith(")"); + final Matcher matcher = oneRaceScorePattern.matcher(cell); + final CompetitorEntry result; + if (matcher.matches()) { + final String maxPointsReason = matcher.group(3); + final Double points = Double.parseDouble(matcher.group(1)); + result = new DefaultCompetitorEntryImpl(/* rank */ null, maxPointsReason, points, isDiscarded); + } else { + result = null; + } + return result; + } + + private List getNames(String cell) { + return Arrays.asList(cell.split(", *")); + } +} diff --git a/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/ScoreCorrectionProviderImpl.java b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/ScoreCorrectionProviderImpl.java new file mode 100755 index 00000000000..cd0510695b8 --- /dev/null +++ b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/ScoreCorrectionProviderImpl.java @@ -0,0 +1,98 @@ +package com.sap.sailing.sailwave.html.resultimport.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.sap.sailing.domain.common.RegattaScoreCorrections; +import com.sap.sailing.domain.common.ScoreCorrectionProvider; +import com.sap.sailing.domain.resultimport.ResultUrlProvider; +import com.sap.sailing.resultimport.AbstractResultUrlProvider; +import com.sap.sailing.resultimport.RegattaResults; +import com.sap.sailing.resultimport.ResultUrlRegistry; +import com.sap.sailing.resultimport.impl.RegattaScoreCorrectionsImpl; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; +import com.sap.sse.common.impl.MillisecondsTimePoint; + +public class ScoreCorrectionProviderImpl extends AbstractResultUrlProvider implements ScoreCorrectionProvider, ResultUrlProvider { + private static final long serialVersionUID = 5853404150107387702L; + public static final String PROVIDER_NAME = "SailWave HTML Score Importer"; + + public ScoreCorrectionProviderImpl(ResultUrlRegistry resultUrlRegistry) { + super(resultUrlRegistry); + } + + @Override + public String getName() { + return PROVIDER_NAME; + } + + @Override + public Map>> getHasResultsForBoatClassFromDateByEventName() { + Map>> result = new HashMap>>(); + SailwaveHtmlParser parser = new SailwaveHtmlParser(); + for (URL url : getReadableUrls()) { + URLConnection conn; + try { + conn = url.openConnection(); + TimePoint lastModified = new MillisecondsTimePoint(conn.getLastModified()); + RegattaResults regattaResult = parser.getRegattaResults((InputStream) conn.getContent()); + final String boatClassName = getBoatClassName(regattaResult); + result.put(boatClassName, Collections.singleton(new Util.Pair(boatClassName, lastModified))); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + return result; + } + + /** + * @return the first non-empty string of the list of metadata, hoping it's something pointing at the boat class at least... + */ + private String getBoatClassName(RegattaResults regattaResult) { + Map metadata = regattaResult.getMetadata(); + for (String metadatum : metadata.values()) { + if (metadatum != null && metadatum.length() > 0) { + return metadatum; + } + } + return null; + } + + @Override + public URL resolveUrl(String url) throws MalformedURLException { + return new URL(url); + } + + @Override + public RegattaScoreCorrections getScoreCorrections(String eventName, String boatClassName, + TimePoint timePoint) throws Exception { + final SailwaveHtmlParser parser = new SailwaveHtmlParser(); + for (URL url : getReadableUrls()) { + final URLConnection conn = url.openConnection(); + final RegattaResults regattaResult = parser.getRegattaResults((InputStream) conn.getContent()); + if ((boatClassName == null && getBoatClassName(regattaResult) == null) || + boatClassName.equals(getBoatClassName(regattaResult))) { + return new RegattaScoreCorrectionsImpl(this, regattaResult); + } + } + return null; + } + + @Override + public RegattaScoreCorrections getScoreCorrections(InputStream inputStream) throws Exception { + return new RegattaScoreCorrectionsImpl(this, new SailwaveHtmlParser().getRegattaResults(inputStream)); + } + + @Override + public String getOptionalSampleURL() { + return null; + } +} diff --git a/java/pom.xml b/java/pom.xml index 5ee260d11a2..4f748a93b67 100755 --- a/java/pom.xml +++ b/java/pom.xml @@ -249,6 +249,8 @@ com.sap.sailing.velum.resultimport.test com.sap.sailing.sailwave.resultimport com.sap.sailing.sailwave.resultimport.test + com.sap.sailing.sailwave.html.resultimport + com.sap.sailing.sailwave.html.resultimport.test com.sap.sailing.manage2sail com.sap.sailing.manage2sail.resultimport com.sap.sailing.manage2sail.resultimport.test From 9b6691f4383a1a1a4e7d85e35259ac1efa519748 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 20 Feb 2025 17:37:57 +0100 Subject: [PATCH 02/10] bug6096: first test case green --- .../META-INF/MANIFEST.MF | 3 +- .../resultimport/impl/SailwaveHtmlParser.java | 55 ++++++++++++------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/java/com.sap.sailing.sailwave.html.resultimport/META-INF/MANIFEST.MF b/java/com.sap.sailing.sailwave.html.resultimport/META-INF/MANIFEST.MF index 2887cf86934..e6f9ba4239e 100644 --- a/java/com.sap.sailing.sailwave.html.resultimport/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.sailwave.html.resultimport/META-INF/MANIFEST.MF @@ -7,7 +7,8 @@ Bundle-Activator: com.sap.sailing.sailwave.html.resultimport.impl.Activator Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Automatic-Module-Name: com.sap.sailing.sailwave.html.resultimport -Import-Package: org.osgi.framework;version="1.3.0", +Import-Package: org.apache.commons.lang;version="[2.6.0,3.0.0)", + org.osgi.framework;version="1.3.0", org.osgi.util.tracker;version="[1.5.0,2.0.0)" Require-Bundle: com.sap.sailing.resultimport, com.sap.sailing.domain.common, diff --git a/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/SailwaveHtmlParser.java b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/SailwaveHtmlParser.java index 57f97dd29c5..52edcfb40f8 100755 --- a/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/SailwaveHtmlParser.java +++ b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/SailwaveHtmlParser.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -18,6 +17,8 @@ import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.lang.StringEscapeUtils; + import com.sap.sailing.resultimport.CompetitorEntry; import com.sap.sailing.resultimport.CompetitorRow; import com.sap.sailing.resultimport.RegattaResults; @@ -70,7 +71,7 @@ public class SailwaveHtmlParser { return tableRows; } - public List getTagContents(String s, String tag) throws UnsupportedEncodingException { + public List getTagContents(String s, String tag) { Pattern tagPattern = Pattern.compile("<("+tag.toLowerCase()+"|"+tag.toUpperCase()+")([^<>]*)>"); Pattern slashTag = Pattern.compile("]*)>"); boolean inTag = false; @@ -94,9 +95,9 @@ public class SailwaveHtmlParser { if (foundSlashTag) { end = slashTagMatcher.start(); inTag = false; - result.add(URLDecoder.decode(s.substring(start, end).trim(), "UTF-8")); + result.add(StringEscapeUtils.unescapeHtml(s.substring(start, end).trim())); } else { - result.add(URLDecoder.decode(s.substring(start).trim(), "UTF-8")); + result.add(StringEscapeUtils.unescapeHtml(s.substring(start).trim())); finished = true; logger.warning("unclosed "+tag+" tag in string \""+s+"\""); } @@ -114,12 +115,12 @@ public class SailwaveHtmlParser { final List result = new ArrayList(); final BufferedReader br = new BufferedReader(new InputStreamReader(is)); final Map metadata = readMetadataBeforeTable(br); - final LinkedHashMap columnStylesAndNames = readTableHeader(br); + final LinkedHashMap columnNamesAndStyles = readTableHeader(br); findTableBody(br); final List rowContents = getRowContents(br); for (final String row : rowContents) { final List tdContent = getTagContents(row, "td"); - result.add(createCompetitorRow(tdContent, columnStylesAndNames, classesCounts)); + result.add(createCompetitorRow(tdContent, columnNamesAndStyles, classesCounts)); } return new RegattaResults() { @Override @@ -145,7 +146,7 @@ public class SailwaveHtmlParser { private LinkedHashMap readTableHeader(BufferedReader br) throws IOException { final LinkedHashMap result = new LinkedHashMap<>(); final List classes = new ArrayList<>(); - final Pattern colClassPattern = Pattern.compile(""); + final Pattern colClassPattern = Pattern.compile(""); final Pattern colTitlePattern = Pattern.compile("([^<]*)"); String line; while ((line=br.readLine()) != null && !line.contains("")) ; final Iterator classIter = classes.iterator(); - while (line != null && !line.contains(" readMetadataBeforeTable(BufferedReader br) throws IOException { - final Pattern h3MetadataElementPattern = Pattern.compile("

([^<]*)

"); - final Pattern divMetadataElementPattern = Pattern.compile("
([^<]*)
"); + final Pattern h3MetadataElementPattern = Pattern.compile("

]*>([^<]*)

"); + final Pattern divMetadataElementPattern = Pattern.compile("
]*>([^<]*)
"); final Map result = new HashMap<>(); String line; while ((line=br.readLine()) != null && !line.contains(""); final Matcher h3Matcher = h3MetadataElementPattern.matcher(line); if (h3Matcher.matches()) { result.put(h3Matcher.group(1), h3Matcher.group(2)); @@ -190,9 +192,10 @@ public class SailwaveHtmlParser { return result; } - private CompetitorRow createCompetitorRow(List trContent, LinkedHashMap columnStylesAndNames, Map classesCounts) throws UnsupportedEncodingException { - final List columnValues = getTagContents(trContent.get(0), "td"); - final Iterator columnValueIterator = columnValues.iterator(); + private CompetitorRow createCompetitorRow(List trContent, LinkedHashMap columnNamesAndStyles, Map classesCounts) throws UnsupportedEncodingException { + final Pattern rankPattern = Pattern.compile("([0-9]+)[A-Za-z]*"); // captures the 3 in "3rd" + final Pattern nationalityPattern = Pattern.compile("^()?$"); // captures the 3 in "3rd" + final Iterator columnValueIterator = trContent.iterator(); String nationality = null; String sailNumber = null; Integer totalRank = null; @@ -200,11 +203,14 @@ public class SailwaveHtmlParser { List rankAndMaxPointsReasonAndPointsAndDiscarded = new ArrayList(); Double scoreAfterDiscarding = null; Double totalPointsBeforeDiscarding = null; - for (final Entry columnStyleAndName : columnStylesAndNames.entrySet()) { + for (final Entry columnNameAndStyle : columnNamesAndStyles.entrySet()) { final String columnValue = columnValueIterator.next(); - switch (columnStyleAndName.getKey()) { + switch (columnNameAndStyle.getValue()) { case "rank": - totalRank = Integer.parseInt(columnValue); + final Matcher rankMatcher = rankPattern.matcher(columnValue); + if (rankMatcher.matches()) { + totalRank = Integer.parseInt(rankMatcher.group(1)); + } break; case "class": if (classesCounts.containsKey(columnValue)) { @@ -214,7 +220,14 @@ public class SailwaveHtmlParser { } break; case "nat": - nationality = columnValue; + // example value: + // but we should also be prepared for just the nationality string, such as "HKG" + final Matcher natMatcher = nationalityPattern.matcher(columnValue); + if (natMatcher.matches()) { + nationality = natMatcher.group(2); + } else { + nationality = columnValue; + } break; case "sailno": sailNumber = columnValue; @@ -227,10 +240,10 @@ public class SailwaveHtmlParser { rankAndMaxPointsReasonAndPointsAndDiscarded.add(rankAndMaxPointsReasonAndPointsAndDiscardedForOnceRace); break; case "total": - scoreAfterDiscarding = Double.parseDouble(columnValue); + totalPointsBeforeDiscarding = Double.parseDouble(columnValue); break; case "nett": - totalPointsBeforeDiscarding = Double.parseDouble(columnValue); + scoreAfterDiscarding = Double.parseDouble(columnValue); } } return new CompetitorRowImpl(totalRank, nationality+" "+sailNumber, names, scoreAfterDiscarding, totalPointsBeforeDiscarding, From 6888709c30479bf077f7e3a570cd6e5141410b48 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 20 Feb 2025 17:48:59 +0100 Subject: [PATCH 03/10] bug6096: four test cases, all green --- .../test/SimpleHtmlParsingTest.java | 146 ++++++++---------- 1 file changed, 62 insertions(+), 84 deletions(-) diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/src/com/sap/sailing/sailwave/html/resultimport/test/SimpleHtmlParsingTest.java b/java/com.sap.sailing.sailwave.html.resultimport.test/src/com/sap/sailing/sailwave/html/resultimport/test/SimpleHtmlParsingTest.java index 889fa87af39..4cf303c0792 100755 --- a/java/com.sap.sailing.sailwave.html.resultimport.test/src/com/sap/sailing/sailwave/html/resultimport/test/SimpleHtmlParsingTest.java +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/src/com/sap/sailing/sailwave/html/resultimport/test/SimpleHtmlParsingTest.java @@ -4,7 +4,6 @@ package com.sap.sailing.sailwave.html.resultimport.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.BufferedReader; @@ -38,109 +37,88 @@ public class SimpleHtmlParsingTest { assertFalse(result.isEmpty()); assertEquals(17, result.size()); assertTrue(regattaResults.getMetadata().get("seriestitle").contains("Results are provisional as of 9:43 on February 16, 2025")); + int competitorsChecked = 0; for (CompetitorRow row : result) { if (Util.contains(row.getNames(), "Daniel Kin Chung Chan")) { + competitorsChecked++; assertEquals("HKG 223750", row.getSailID()); assertEquals(25.0, row.getScoreAfterDiscarding(), 0.000000001); assertEquals(40.0, row.getTotalPointsBeforeDiscarding(), 0.000000001); } - } - } - - @Test - public void testEmptyAndDashedScores() throws IOException { - final InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("ILCA7.html"); - SailwaveHtmlParser parser = new SailwaveHtmlParser(); - List result = parser.getRegattaResults(resourceAsStream).getCompetitorResults(); - assertFalse(result.isEmpty()); - assertEquals(117, result.size()); - for (CompetitorRow row : result) { - if (Util.contains(row.getNames(), "Nicholas Halliday")) { - assertEquals("HKG 171979", row.getSailID()); - assertEquals(7.0, row.getScoreAfterDiscarding(), 0.000000001); - assertEquals(10.0, row.getTotalPointsBeforeDiscarding(), 0.000000001); - assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getRank()); - assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getScore()); - assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).isDiscarded()); - assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getRank()); - assertEquals((double) 118.00, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getScore(), 0.000000001); - assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).isDiscarded()); - } else if (Util.contains(row.getNames(), "HAGAN Douglas")) { - assertEquals("AUS 8817", row.getSailID()); - assertEquals(235.00, row.getScoreAfterDiscarding(), 0.000000001); - assertEquals(235.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); - assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getRank()); - assertEquals("DNF", Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getMaxPointsReason()); - assertEquals((double) 117.00, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getScore(), 0.000000001); - assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).isDiscarded()); - assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getRank()); - assertEquals("DNF", Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getMaxPointsReason()); - assertEquals((double) 118.00, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getScore(), 0.000000001); - assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).isDiscarded()); + if (Util.contains(row.getNames(), "Haolun Xia")) { + competitorsChecked++; + assertEquals("CHN 210199", row.getSailID()); + assertEquals(47.0, row.getScoreAfterDiscarding(), 0.000000001); + assertEquals(69.0, row.getTotalPointsBeforeDiscarding(), 0.000000001); + assertEquals((double) 11.00, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getScore(), 0.000000001); + assertEquals("SCP", Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getMaxPointsReason()); + assertEquals(true, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).isDiscarded()); } } + assertEquals(2, competitorsChecked); } - @Test - public void testGetCompetitorRows505() throws IOException { - SailwaveHtmlParser parser = new SailwaveHtmlParser(); - final InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("29er.html"); - List result = parser.getRegattaResults(resourceAsStream).getCompetitorResults(); - assertFalse(result.isEmpty()); - assertEquals(75, result.size()); - for (CompetitorRow row : result) { - if (Util.contains(row.getNames(), "HOLZAPFEL Alexander")) { - assertEquals("GER 8975", row.getSailID()); - assertEquals(60.00, row.getScoreAfterDiscarding(), 0.000000001); - assertEquals(74.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); - assertEquals((int) 11, (int) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getRank()); - assertEquals((double) 11, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getScore(), 0.000000001); - assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).isDiscarded()); - } else if (Util.contains(row.getNames(), "BART Cedric")) { - assertEquals("SUI 8543", row.getSailID()); - assertEquals(55.00, row.getScoreAfterDiscarding(), 0.000000001); - assertEquals(74.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); - assertEquals((int) 2, (int) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 2).getRank()); - assertEquals((double) 2, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 2).getScore(), 0.000000001); - assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 2).isDiscarded()); - assertEquals((int) 19, (int) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 3).getRank()); - assertEquals((double) 19, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 3).getScore(), 0.000000001); - assertEquals(true, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 3).isDiscarded()); - } else if (Util.contains(row.getNames(), "LEWNS Chris")) { - assertEquals("GBR 9057", row.getSailID()); - assertEquals(64.00, row.getScoreAfterDiscarding(), 0.000000001); - assertEquals(140.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); - assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 7).getRank()); - assertEquals("DNF", Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 7).getMaxPointsReason()); - assertEquals((double) 76, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 7).getScore(), 0.000000001); - assertEquals(true, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 7).isDiscarded()); - } - } - } - @Test public void testGetCompetitorRows29er() throws IOException { SailwaveHtmlParser parser = new SailwaveHtmlParser(); final InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("29er.html"); List result = parser.getRegattaResults(resourceAsStream).getCompetitorResults(); assertFalse(result.isEmpty()); - assertEquals(62, result.size()); + assertEquals(19, result.size()); + int competitorsChecked = 0; for (CompetitorRow row : result) { - if (Util.contains(row.getNames(), "HOLSTE Kim (M1993)")) { - assertEquals("GER 1864", row.getSailID()); - assertEquals(58.00, row.getScoreAfterDiscarding(), 0.000000001); - assertEquals(169.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); - assertEquals((int) 25, (int) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getRank()); - assertEquals((double) 25, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getScore(), 0.000000001); + if (Util.contains(row.getNames(), "Ethan Kiu")) { + competitorsChecked++; + assertEquals("HKG 3354", row.getSailID()); + assertEquals(41.00, row.getScoreAfterDiscarding(), 0.000000001); + assertEquals(58.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); + assertEquals((double) 2, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getScore(), 0.000000001); assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).isDiscarded()); - assertEquals((int) 38, (int) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getRank()); - assertEquals((double) 38, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getScore(), 0.000000001); - assertEquals(true, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).isDiscarded()); - assertNull(Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).getRank()); - assertEquals("DSQ", Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).getMaxPointsReason()); - assertEquals((double) 63, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).getScore(), 0.000000001); + } else if (Util.contains(row.getNames(), "Kaden Chan")) { + competitorsChecked++; + assertEquals("HKG 3405", row.getSailID()); + assertEquals(80.00, row.getScoreAfterDiscarding(), 0.000000001); + assertEquals(107.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); + assertEquals((double) 8, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 2).getScore(), 0.000000001); + assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 2).isDiscarded()); + assertEquals((double) 15, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 4).getScore(), 0.000000001); + assertEquals(true, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 4).isDiscarded()); + } else if (Util.contains(row.getNames(), "Chloe Kong")) { + competitorsChecked++; + assertEquals("HKG 2566", row.getSailID()); + assertEquals(67.00, row.getScoreAfterDiscarding(), 0.000000001); + assertEquals(107.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); + assertEquals("SCP", Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).getMaxPointsReason()); + assertEquals((double) 20, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).getScore(), 0.000000001); assertEquals(true, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).isDiscarded()); } } + assertEquals(3, competitorsChecked); + } + + @Test + public void testGetCompetitorRowsILCA4() throws IOException { + SailwaveHtmlParser parser = new SailwaveHtmlParser(); + final InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("ILCA4.html"); + List result = parser.getRegattaResults(resourceAsStream).getCompetitorResults(); + assertFalse(result.isEmpty()); + assertEquals(50, result.size()); + int competitorsChecked = 0; + for (CompetitorRow row : result) { + if (Util.contains(row.getNames(), "YONG LIANG Chuang")) { + competitorsChecked++; + assertEquals("TPE 221094", row.getSailID()); + assertEquals(198.00, row.getScoreAfterDiscarding(), 0.000000001); + assertEquals(300.00, row.getTotalPointsBeforeDiscarding(), 0.000000001); + assertEquals((double) 17, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).getScore(), 0.000000001); + assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 0).isDiscarded()); + assertEquals((double) 30, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).getScore(), 0.000000001); + assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 1).isDiscarded()); + assertEquals("DNC", Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).getMaxPointsReason()); + assertEquals((double) 51, (double) Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).getScore(), 0.000000001); + assertEquals(false, Util.get(row.getRankAndMaxPointsReasonAndPointsAndDiscarded(), 6).isDiscarded()); + } + } + assertEquals(1, competitorsChecked); } } From 04c96c8f0d40e538d075f2ffafd50ad8d7c0eb1b Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 20 Feb 2025 17:49:51 +0100 Subject: [PATCH 04/10] bug6096: updated all launch configurations and selenium pom.xml for new bundle --- java/com.sap.sailing.selenium.test/pom.xml | 5 +++++ .../SailingServer (No Proxy OSX).launch | 5 +++++ java/com.sap.sailing.server/SailingServer (No Proxy).launch | 5 +++++ .../SailingServer (No Proxy, Axel).launch | 5 +++++ .../SailingServer (No Proxy, Cached MTB).launch | 5 +++++ .../SailingServer (No Proxy, Java11).launch | 5 +++++ .../SailingServer (No Proxy, Java11, JFR Recording).launch | 5 +++++ .../SailingServer (No Proxy, Jetty on 8889).launch | 5 +++++ ...ailingServer (No Proxy, Jetty on 8889, Cached MTB).launch | 5 +++++ ...o Proxy, Jetty on 8889, auto-replicate SS and SSD).launch | 5 +++++ ...rver (No Proxy, Jetty on 8889, auto-replicate dev).launch | 5 +++++ ...ngServer (No Proxy, Jetty on 8889, auto-replicate).launch | 5 +++++ .../SailingServer (No Proxy, Jetty on 8890).launch | 5 +++++ ...etty on 8890, auto-replicate from replica at 8889).launch | 5 +++++ .../SailingServer (No Proxy, Remote Debug SAP VM).launch | 5 +++++ .../SailingServer (No Proxy, debranding active).launch | 5 +++++ .../SailingServer (No Proxy, winddb Axel).launch | 5 +++++ .../SailingServer (No Proxy, winddbTest Axel).launch | 5 +++++ .../SailingServer (No Proxy, winddbTest).launch | 5 +++++ ...on 8889, Polar & Wind estimation Import from 8888).launch | 5 +++++ 20 files changed, 100 insertions(+) diff --git a/java/com.sap.sailing.selenium.test/pom.xml b/java/com.sap.sailing.selenium.test/pom.xml index a4bd1b591d6..eec2a23503b 100755 --- a/java/com.sap.sailing.selenium.test/pom.xml +++ b/java/com.sap.sailing.selenium.test/pom.xml @@ -180,6 +180,11 @@ 4 true + + com.sap.sailing.sailwave.html.resultimport + 4 + true + com.sap.sailing.manage2sail.resultimport 4 diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy OSX).launch b/java/com.sap.sailing.server/SailingServer (No Proxy OSX).launch index 84454924540..6c121d6fd34 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy OSX).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy OSX).launch @@ -241,6 +241,10 @@ + + + + @@ -270,6 +274,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy).launch b/java/com.sap.sailing.server/SailingServer (No Proxy).launch index cc5aa7860d2..3603e197587 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy).launch @@ -247,6 +247,10 @@ + + + + @@ -276,6 +280,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Axel).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Axel).launch index 7925c231824..6500617b05c 100644 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Axel).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Axel).launch @@ -247,6 +247,10 @@ + + + + @@ -276,6 +280,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch index 114a4576ab3..9e5a4ada066 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch @@ -239,6 +239,10 @@ + + + + @@ -268,6 +272,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Java11).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Java11).launch index 0abf4f4c3d4..3b41415994c 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Java11).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Java11).launch @@ -245,6 +245,10 @@ + + + + @@ -274,6 +278,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Java11, JFR Recording).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Java11, JFR Recording).launch index 557a8b1a38b..26a3c616cc8 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Java11, JFR Recording).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Java11, JFR Recording).launch @@ -244,6 +244,10 @@ + + + + @@ -273,6 +277,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch index 1788e8fee07..b27ff5d322a 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch @@ -238,6 +238,10 @@ + + + + @@ -267,6 +271,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch index 886382d328a..b6c59b57350 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch @@ -234,6 +234,10 @@ + + + + @@ -263,6 +267,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate SS and SSD).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate SS and SSD).launch index 0bfd64a91a8..c573014d9ce 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate SS and SSD).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate SS and SSD).launch @@ -240,6 +240,10 @@ + + + + @@ -269,6 +273,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate dev).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate dev).launch index 4a64b2053b8..652f9af93d4 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate dev).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate dev).launch @@ -238,6 +238,10 @@ + + + + @@ -267,6 +271,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate).launch index a47246595a7..1fb5fa5b66d 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate).launch @@ -240,6 +240,10 @@ + + + + @@ -269,6 +273,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch index 279c156a4ff..dd7af5ed3b4 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch @@ -238,6 +238,10 @@ + + + + @@ -267,6 +271,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890, auto-replicate from replica at 8889).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890, auto-replicate from replica at 8889).launch index 71ee256b71f..f076f50ba8d 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890, auto-replicate from replica at 8889).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890, auto-replicate from replica at 8889).launch @@ -238,6 +238,10 @@ + + + + @@ -267,6 +271,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch index 5f2589e4b38..9331862fb61 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch @@ -234,6 +234,10 @@ + + + + @@ -263,6 +267,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, debranding active).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, debranding active).launch index 4b7c1e33755..adc8fee5d22 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, debranding active).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, debranding active).launch @@ -242,6 +242,10 @@ + + + + @@ -271,6 +275,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, winddb Axel).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, winddb Axel).launch index 2d4df64bedd..991955bdf9a 100644 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, winddb Axel).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, winddb Axel).launch @@ -240,6 +240,10 @@ + + + + @@ -269,6 +273,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest Axel).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest Axel).launch index aa25d78b8d5..86245d6e993 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest Axel).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest Axel).launch @@ -240,6 +240,10 @@ + + + + @@ -269,6 +273,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch index 948808219e5..b0104b798d3 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch @@ -245,6 +245,10 @@ + + + + @@ -274,6 +278,7 @@ + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889, Polar & Wind estimation Import from 8888).launch b/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889, Polar & Wind estimation Import from 8888).launch index aa4bc27dde4..f71705c3c67 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889, Polar & Wind estimation Import from 8888).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889, Polar & Wind estimation Import from 8888).launch @@ -241,6 +241,10 @@ + + + + @@ -270,6 +274,7 @@ + From 20d464069a88ec590796763212fbe6ac6b45b037 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Thu, 20 Feb 2025 18:06:05 +0100 Subject: [PATCH 05/10] bug6096: extract class name --- .../html/resultimport/impl/SailwaveHtmlParser.java | 10 ++++++++++ .../impl/ScoreCorrectionProviderImpl.java | 12 ++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/SailwaveHtmlParser.java b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/SailwaveHtmlParser.java index 52edcfb40f8..4e23afa2258 100755 --- a/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/SailwaveHtmlParser.java +++ b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/SailwaveHtmlParser.java @@ -26,6 +26,8 @@ import com.sap.sailing.resultimport.impl.CompetitorRowImpl; import com.sap.sailing.resultimport.impl.DefaultCompetitorEntryImpl; public class SailwaveHtmlParser { + static final String CLASS_METADATA = "class"; + private static final Logger logger = Logger.getLogger(SailwaveHtmlParser.class.getName()); public List getRowContents(BufferedReader br) throws IOException { @@ -122,6 +124,7 @@ public class SailwaveHtmlParser { final List tdContent = getTagContents(row, "td"); result.add(createCompetitorRow(tdContent, columnNamesAndStyles, classesCounts)); } + addMostLikelyClassToMetadata(classesCounts, metadata); return new RegattaResults() { @Override public Map getMetadata() { @@ -137,6 +140,13 @@ public class SailwaveHtmlParser { } } + private void addMostLikelyClassToMetadata(Map classesCounts, Map metadata) { + if (!classesCounts.isEmpty()) { + // sort descending and pick first: + metadata.put(CLASS_METADATA, classesCounts.entrySet().stream().sorted((e1, e2)->Integer.compare(e2.getValue(), e1.getValue())).findFirst().get().getKey()); + } + } + private void findTableBody(BufferedReader br) throws IOException { String line; while ((line=br.readLine()) != null && !line.contains("")) diff --git a/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/ScoreCorrectionProviderImpl.java b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/ScoreCorrectionProviderImpl.java index cd0510695b8..31dd2d0854c 100755 --- a/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/ScoreCorrectionProviderImpl.java +++ b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/ScoreCorrectionProviderImpl.java @@ -58,12 +58,16 @@ public class ScoreCorrectionProviderImpl extends AbstractResultUrlProvider imple */ private String getBoatClassName(RegattaResults regattaResult) { Map metadata = regattaResult.getMetadata(); - for (String metadatum : metadata.values()) { - if (metadatum != null && metadatum.length() > 0) { - return metadatum; + if (metadata.containsKey(SailwaveHtmlParser.CLASS_METADATA)) { + return metadata.get(SailwaveHtmlParser.CLASS_METADATA); + } else { + for (String metadatum : metadata.values()) { + if (metadatum != null && metadatum.length() > 0) { + return metadatum; + } } + return null; } - return null; } @Override From a275fe34196828ec21acec2fd8ec9e0b886e5b84 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 21 Feb 2025 00:00:54 +0100 Subject: [PATCH 06/10] bug6096: added resources/ to build.properties of test fragment --- .../build.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/build.properties b/java/com.sap.sailing.sailwave.html.resultimport.test/build.properties index 34d2e4d2dad..f11210d3f2c 100644 --- a/java/com.sap.sailing.sailwave.html.resultimport.test/build.properties +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/build.properties @@ -1,4 +1,5 @@ -source.. = src/ +source.. = src/,\ + resources/ output.. = bin/ bin.includes = META-INF/,\ . From 313de6be53de2bca76a5f35742c6e2f386a9cb21 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 21 Feb 2025 00:04:03 +0100 Subject: [PATCH 07/10] bug6096: added resources also to bin.includes --- .../build.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/com.sap.sailing.sailwave.html.resultimport.test/build.properties b/java/com.sap.sailing.sailwave.html.resultimport.test/build.properties index f11210d3f2c..0a97af7a804 100644 --- a/java/com.sap.sailing.sailwave.html.resultimport.test/build.properties +++ b/java/com.sap.sailing.sailwave.html.resultimport.test/build.properties @@ -2,4 +2,5 @@ source.. = src/,\ resources/ output.. = bin/ bin.includes = META-INF/,\ - . + .,\ + resources/ From a0ead173e973a558fdaa937961398fd4c40e88b4 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 21 Feb 2025 13:24:32 +0100 Subject: [PATCH 08/10] bug6096: use lowercase name for Sailwave HTML importer to sort consistently with other Sailwave result importer --- .../html/resultimport/impl/ScoreCorrectionProviderImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/ScoreCorrectionProviderImpl.java b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/ScoreCorrectionProviderImpl.java index 31dd2d0854c..39f2e75893c 100755 --- a/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/ScoreCorrectionProviderImpl.java +++ b/java/com.sap.sailing.sailwave.html.resultimport/src/com/sap/sailing/sailwave/html/resultimport/impl/ScoreCorrectionProviderImpl.java @@ -23,7 +23,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public class ScoreCorrectionProviderImpl extends AbstractResultUrlProvider implements ScoreCorrectionProvider, ResultUrlProvider { private static final long serialVersionUID = 5853404150107387702L; - public static final String PROVIDER_NAME = "SailWave HTML Score Importer"; + public static final String PROVIDER_NAME = "Sailwave HTML Score Importer"; public ScoreCorrectionProviderImpl(ResultUrlRegistry resultUrlRegistry) { super(resultUrlRegistry); From fc15f61d63b62bd341c21fce11957259869c8216 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 21 Feb 2025 13:25:18 +0100 Subject: [PATCH 09/10] bug6096: sort result list providers in drop-down list --- .../gwt/ui/adminconsole/ResultImportUrlsListComposite.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsListComposite.java index 5105e22c688..098b6d68dd4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsListComposite.java @@ -1,5 +1,6 @@ package com.sap.sailing.gwt.ui.adminconsole; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -82,6 +83,7 @@ public class ResultImportUrlsListComposite extends Composite { sailingServiceWrite.getUrlResultProviderNamesAndOptionalSampleURL(new AsyncCallback>>() { @Override public void onSuccess(List> urlProviderNamesAndOptionalSampleURL) { + Collections.sort(urlProviderNamesAndOptionalSampleURL, (u1, u2)->u1.getA().compareTo(u2.getA())); urlProviderListBox.clear(); urlProviderListBox.addItem(stringMessages.pleaseSelectAURLProvider()); for (Pair urlProviderNameAndSampleURL : urlProviderNamesAndOptionalSampleURL) { From e19b80467631310f43625b64b617fa0e2e89c917 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 21 Feb 2025 13:25:32 +0100 Subject: [PATCH 10/10] bug6096: properly handle nationality from competitor in result import now; see https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=6096#c2; The regular expression demanded a three-letter acronym at the beginning of the sail ID; this has been relaxed now, and now the "default nationality" coming from the competitor is finally being used for match-making when the sail ID only has the number. --- .../common/AbstractSailNumberCanonicalizerAndMatcher.java | 8 ++++---- java/com.sap.sailing.www/release_notes_admin.html | 4 ++++ java/com.sap.sse.common/src/com/sap/sse/common/Util.java | 4 +++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractSailNumberCanonicalizerAndMatcher.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractSailNumberCanonicalizerAndMatcher.java index d85f3d71e7b..63f63374c64 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractSailNumberCanonicalizerAndMatcher.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/AbstractSailNumberCanonicalizerAndMatcher.java @@ -24,7 +24,7 @@ import java.util.Map; * */ public abstract class AbstractSailNumberCanonicalizerAndMatcher { - protected static final String sailIdRegexpPattern = "^([A-Z][A-Z][A-Z])\\s*[^0-9]*([0-9]*)$"; + protected static final String sailIdRegexpPattern = "^([A-Z][A-Z][A-Z])?\\s*[^0-9]*([0-9]*)$"; public static class SailNumberMatch { private final String iocCode; @@ -43,7 +43,7 @@ public abstract class AbstractSailNumberCanonicalizerAndMatcher } /** - * Parses a sail number into a nationality code expected at the beginning of the string, + * Parses a sail number into a nationality code expected at the beginning of the string but possibly empty, * and a numeric part assumed to be at the end of the string. Before matching, the {@code sailId} * string will be {@link String#trim() trimmed}, removing leading and trailing whitespace. If * the parameter matches the {@link #sailIdRegexpPattern} then a valid {@link SailNumberMatch} @@ -102,10 +102,10 @@ public abstract class AbstractSailNumberCanonicalizerAndMatcher } public Map canonicalizeLeaderboardSailIDs(final Iterable competitors) { - Map result = new HashMap<>(); + final Map result = new HashMap<>(); for (final CompetitorType competitor : competitors) { final String competitorIdentifyingText = getCompetitorIdentifyingText(competitor); - String canonicalizedSailID = canonicalizeSailID(competitorIdentifyingText.trim(), getThreeLetterIocCountryCode(competitor).trim()); + final String canonicalizedSailID = canonicalizeSailID(competitorIdentifyingText.trim(), getThreeLetterIocCountryCode(competitor).trim()); if (canonicalizedSailID != null) { result.put(canonicalizedSailID, competitor); } diff --git a/java/com.sap.sailing.www/release_notes_admin.html b/java/com.sap.sailing.www/release_notes_admin.html index 1e83cb3485d..46daf1ad379 100755 --- a/java/com.sap.sailing.www/release_notes_admin.html +++ b/java/com.sap.sailing.www/release_notes_admin.html @@ -36,6 +36,10 @@
  • When upgrading an application replica set through the Landscape Management panel, other target groups such as those from an NLB will be considered correctly for adding and removing temporary upgrade replicas and the primary/master node.
  • +
  • Added a result importer for the typical Sailwave HTML output, such as + https://www.rhkyc.org.hk/storage/app/media/Sailing/result/HONG-KONG-RACE-WEEK/2025/ILCA4.htm. + You can add these types of URLs now in the Result import URLs tab + of the Connectors category in the administration console.
  • January 2025

      diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/Util.java b/java/com.sap.sse.common/src/com/sap/sse/common/Util.java index 9b82ea83dd4..a4599cf87ec 100755 --- a/java/com.sap.sse.common/src/com/sap/sse/common/Util.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/Util.java @@ -1101,7 +1101,9 @@ public class Util { } /** - * Checks whether a given String is null or empty. + * Checks whether a given String is null or empty. Note that the string is not trimmed + * before performing the "empty" check, so for example " " (three spaces) will be considered + * having a length and true would be returned in this case. * * @param str * String to check