mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-26 07:26:41 +00:00
Merge branch 'master' into bug4380
Change-Id: I37ab1f953eb87b2abdc7f18f73a1b3aa030f0bb0
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
source.. = src/
|
||||
source.. = src/,\
|
||||
resources/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<commandResult>
|
||||
<MAGGRIDRESULT>
|
||||
<VERSION>
|
||||
0.5.0.7
|
||||
</VERSION>
|
||||
<RESULT>
|
||||
<DATE>
|
||||
2018.06027
|
||||
</DATE>
|
||||
<LATITUDE units = "Degree">
|
||||
10.00000
|
||||
</LATITUDE>
|
||||
<LONGITUDE units="Degree">
|
||||
20.00000
|
||||
</LONGITUDE>
|
||||
<ELEVATION units="km">
|
||||
0.00000
|
||||
</ELEVATION>
|
||||
<DECLINATION units="Degree">
|
||||
1.89255
|
||||
</DECLINATION>
|
||||
<INCLINATION units="Degree">
|
||||
-1.78053
|
||||
</INCLINATION>
|
||||
<HORINTENSITY units="nanoTesla (nT)">
|
||||
34687.2
|
||||
</HORINTENSITY>
|
||||
<TOTALINTENSITY units="nanoTesla (nT)">
|
||||
34704.0
|
||||
</TOTALINTENSITY>
|
||||
<XCOMPONENT units="nanoTesla (nT)">
|
||||
34668.3
|
||||
</XCOMPONENT>
|
||||
<YCOMPONENT units="nanoTesla (nT)">
|
||||
1145.5
|
||||
</YCOMPONENT>
|
||||
<ZCOMPONENT units="nanoTesla (nT)">
|
||||
-1078.3
|
||||
</ZCOMPONENT>
|
||||
<DECLINATION_SV units="Degree">
|
||||
0.10649
|
||||
</DECLINATION_SV>
|
||||
<INCLINATION_SV units="Degree">
|
||||
-0.01038
|
||||
</INCLINATION_SV>
|
||||
<HORINTENSITY_SV units="nanoTesla (nT)">
|
||||
11.3
|
||||
</HORINTENSITY_SV>
|
||||
<TOTALINTENSITY_SV units="nanoTesla (nT)">
|
||||
11.5
|
||||
</TOTALINTENSITY_SV>
|
||||
<XCOMPONENT_SV units="nanoTesla (nT)">
|
||||
9.2
|
||||
</XCOMPONENT_SV>
|
||||
<YCOMPONENT_SV units="nanoTesla (nT)">
|
||||
64.8
|
||||
</YCOMPONENT_SV>
|
||||
<ZCOMPONENT_SV units="nanoTesla (nT)">
|
||||
-6.6
|
||||
</ZCOMPONENT_SV>
|
||||
<DECLINATION_UNCERTAINTY units="Degree">
|
||||
0.29
|
||||
</DECLINATION_UNCERTAINTY>
|
||||
<INCLINATION_UNCERTAINTY units="Degree">
|
||||
0.22
|
||||
</INCLINATION_UNCERTAINTY>
|
||||
<HORINTENSITY_UNCERTAINTY units="nanoTesla (nT)">
|
||||
133
|
||||
</HORINTENSITY_UNCERTAINTY>
|
||||
<TOTALINTENSITY_UNCERTAINTY units="nanoTesla (nT)">
|
||||
152
|
||||
</TOTALINTENSITY_UNCERTAINTY>
|
||||
<YCOMPONENT_UNCERTAINTY units="nanoTesla (nT)">
|
||||
89
|
||||
</YCOMPONENT_UNCERTAINTY>
|
||||
<XCOMPONENT_UNCERTAINTY units="nanoTesla (nT)">
|
||||
138
|
||||
</XCOMPONENT_UNCERTAINTY>
|
||||
<ZCOMPONENT_UNCERTAINTY units="nanoTesla (nT)">
|
||||
165
|
||||
</ZCOMPONENT_UNCERTAINTY>
|
||||
</RESULT>
|
||||
</MAGGRIDRESULT>
|
||||
<version_number>
|
||||
1.1
|
||||
</version_number>
|
||||
</commandResult>
|
||||
+3
-11
@@ -2,17 +2,9 @@ package com.sap.sailing.declination.test;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import org.junit.Before;
|
||||
import com.sap.sailing.declination.impl.DeclinationImporter;
|
||||
|
||||
import com.sap.sailing.declination.impl.NOAAImporterForTesting;
|
||||
|
||||
public abstract class AbstractDeclinationTest {
|
||||
protected NOAAImporterForTesting importer;
|
||||
public abstract class AbstractDeclinationTest<I extends DeclinationImporter> {
|
||||
protected I importer;
|
||||
protected final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
importer = new NOAAImporterForTesting();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.sap.sailing.declination.test;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
import com.sap.sailing.declination.impl.ColoradoImporter;
|
||||
|
||||
public class ColoradoDeclinationImportTest extends DeclinationImportTest<ColoradoImporter> {
|
||||
@Before
|
||||
public void setUp() {
|
||||
importer = new ColoradoImporter();
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.sap.sailing.declination.test;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
import com.sap.sailing.declination.impl.ColoradoImporter;
|
||||
|
||||
public class ColoradoDeclinationServiceTest extends DeclinationServiceTest<ColoradoImporter> {
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
importer = new ColoradoImporter();
|
||||
super.setUp();
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.sap.sailing.declination.test;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
import com.sap.sailing.declination.impl.ColoradoImporter;
|
||||
|
||||
public class ColoradoDeclinationStoreTest extends DeclinationStoreTest<ColoradoImporter> {
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
importer = new ColoradoImporter();
|
||||
super.setUp();
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.sap.sailing.declination.test;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
import com.sap.sailing.declination.impl.ColoradoImporter;
|
||||
|
||||
public class ColoradoSimpleDeclinationTest extends SimpleDeclinationTest<ColoradoImporter> {
|
||||
@Before
|
||||
public void setUp() {
|
||||
importer = new ColoradoImporter();
|
||||
}
|
||||
}
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
package com.sap.sailing.declination.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.sap.sailing.declination.Declination;
|
||||
import com.sap.sailing.declination.impl.ColoradoImporter;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class ColoradoTest {
|
||||
@Test
|
||||
public void simpleDocumentParsingTest() throws SAXException, IOException, ParserConfigurationException {
|
||||
final Declination declination = new ColoradoImporter().getDeclinationFromXml(getClass().getResourceAsStream("/colorado.xml"));
|
||||
validateSomeDeclinationInJanuary2018(declination);
|
||||
}
|
||||
|
||||
private void validateSomeDeclinationInJanuary2018(final Declination declination) {
|
||||
assertEquals(10.0, declination.getPosition().getLatDeg(), 0.000001);
|
||||
assertEquals(20.0, declination.getPosition().getLngDeg(), 0.000001);
|
||||
assertEquals(1.89255, declination.getBearing().getDegrees(), 0.000001);
|
||||
assertEquals(0.10649, declination.getAnnualChange().getDegrees(), 0.000001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleOnlineTest() throws IOException, ParseException {
|
||||
final GregorianCalendar cal = new GregorianCalendar(2018, 0, 23);
|
||||
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
final Declination declination = new ColoradoImporter().getDeclination(new DegreePosition(10, 20),
|
||||
new MillisecondsTimePoint(cal.getTime()),
|
||||
/* timeoutForOnlineFetchInMilliseconds */ 5000);
|
||||
validateSomeDeclinationInJanuary2018(declination);
|
||||
}
|
||||
}
|
||||
+6
-24
@@ -2,11 +2,9 @@ package com.sap.sailing.declination.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
@@ -14,34 +12,18 @@ import org.junit.Test;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.sap.sailing.declination.Declination;
|
||||
import com.sap.sailing.declination.impl.DeclinationImporter;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class DeclinationImportTest extends AbstractDeclinationTest {
|
||||
@Test
|
||||
public void testRegexpDeclination() {
|
||||
Matcher declinationMatcher = importer.getDeclinationPattern().matcher(" <p class=\"indent\"><b>Declination</b> = 12° 41' W");
|
||||
assertTrue(declinationMatcher.find());
|
||||
assertEquals("12", declinationMatcher.group(1));
|
||||
assertEquals("41", declinationMatcher.group(2));
|
||||
assertEquals("W", declinationMatcher.group(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegexpAnnualChange() {
|
||||
Matcher annualChangeMatcher = importer.getAnnualChangePattern().matcher(" changing by 0° 11' E/year </p>");
|
||||
assertTrue(annualChangeMatcher.find());
|
||||
assertEquals("0", annualChangeMatcher.group(1));
|
||||
assertEquals("11", annualChangeMatcher.group(2));
|
||||
assertEquals("E", annualChangeMatcher.group(3));
|
||||
}
|
||||
public abstract class DeclinationImportTest<I extends DeclinationImporter> extends AbstractDeclinationTest<I> {
|
||||
|
||||
@Test
|
||||
public void importSimpleDeclination() throws IOException, ParseException, ParserConfigurationException, SAXException {
|
||||
Declination record = importer.importRecord(new DegreePosition(53, 3),
|
||||
new MillisecondsTimePoint(simpleDateFormat.parse("2016-05-27").getTime()));
|
||||
assertEquals(0.26307, record.getBearing().getDegrees(), 0.0001);
|
||||
assertEquals(0.14795, record.getAnnualChange().getDegrees(), 0.0001);
|
||||
assertEquals(0.26307, record.getBearing().getDegrees(), 0.001);
|
||||
assertEquals(0.14795, record.getAnnualChange().getDegrees(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -50,8 +32,8 @@ public class DeclinationImportTest extends AbstractDeclinationTest {
|
||||
Declination record = importer.importRecord(new DegreePosition(-10, 3),
|
||||
new MillisecondsTimePoint(simpleDateFormat.parse("2017-05-27").getTime()));
|
||||
System.out.println("took "+(System.currentTimeMillis()-start)+"ms");
|
||||
assertEquals(-8.44581, record.getBearing().getDegrees(), 0.0001);
|
||||
assertEquals(0.17712, record.getAnnualChange().getDegrees(), 0.0001);
|
||||
assertEquals(-8.44581, record.getBearing().getDegrees(), 0.001);
|
||||
assertEquals(0.17712, record.getAnnualChange().getDegrees(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+6
-5
@@ -12,17 +12,18 @@ import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.declination.Declination;
|
||||
import com.sap.sailing.declination.DeclinationService;
|
||||
import com.sap.sailing.declination.impl.DeclinationImporter;
|
||||
import com.sap.sailing.declination.impl.DeclinationServiceImpl;
|
||||
import com.sap.sailing.domain.common.impl.CentralAngleDistance;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class DeclinationServiceTest extends AbstractDeclinationTest {
|
||||
public abstract class DeclinationServiceTest<I extends DeclinationImporter> extends AbstractDeclinationTest<I> {
|
||||
private DeclinationService service;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
service = new DeclinationServiceImpl(new CentralAngleDistance(1./180.*Math.PI));
|
||||
service = new DeclinationServiceImpl(new CentralAngleDistance(1./180.*Math.PI), importer);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -36,10 +37,10 @@ public class DeclinationServiceTest extends AbstractDeclinationTest {
|
||||
@Test
|
||||
public void testDeclinationQueryNotMatchedInStore() throws IOException, ClassNotFoundException, ParseException {
|
||||
Declination result = service.getDeclination(new MillisecondsTimePoint(simpleDateFormat.parse("2019-02-03").getTime()),
|
||||
new DegreePosition(51, -5), /* timeoutForOnlineFetchInMilliseconds */ 30000);
|
||||
new DegreePosition(51, -5), /* timeoutForOnlineFetchInMilliseconds */ 5000);
|
||||
assertNotNull(result);
|
||||
assertEquals(-1.9565, result.getBearing().getDegrees(), 0.0001);
|
||||
assertEquals(0.15244, result.getAnnualChange().getDegrees(), 0.0001);
|
||||
assertEquals(-1.9565, result.getBearing().getDegrees(), 0.001);
|
||||
assertEquals(0.15244, result.getAnnualChange().getDegrees(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+4
-3
@@ -28,6 +28,7 @@ import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.declination.Declination;
|
||||
import com.sap.sailing.declination.impl.DeclinationImporter;
|
||||
import com.sap.sailing.declination.impl.DeclinationRecordImpl;
|
||||
import com.sap.sailing.declination.impl.DeclinationStore;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
@@ -38,13 +39,13 @@ import com.sap.sailing.domain.common.quadtree.QuadTree;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class DeclinationStoreTest extends AbstractDeclinationTest {
|
||||
public abstract class DeclinationStoreTest<I extends DeclinationImporter> extends AbstractDeclinationTest<I> {
|
||||
private DeclinationStore store;
|
||||
private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
store = new DeclinationStore();
|
||||
store = new DeclinationStore(importer);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -325,7 +326,7 @@ public class DeclinationStoreTest extends AbstractDeclinationTest {
|
||||
@Test
|
||||
public void copyExistingDeclinationsToNewFormat() throws IOException, ClassNotFoundException, ParseException {
|
||||
File resourcesDir = new File("../com.sap.sailing.declination/resources/");
|
||||
DeclinationStore store = new DeclinationStore();
|
||||
DeclinationStore store = new DeclinationStore(importer);
|
||||
assertTrue(resourcesDir.isDirectory());
|
||||
for (File f : resourcesDir.listFiles()) {
|
||||
if (f.getName().startsWith("declination-") && f.getName().endsWith(".txt") &&
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.sap.sailing.declination.test;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
|
||||
import com.sap.sailing.declination.impl.NOAAImporterForTesting;
|
||||
|
||||
@Ignore("US Government Shutdown around 2018-01-22")
|
||||
public class NOAADeclinationImportTest extends DeclinationImportTest<NOAAImporterForTesting> {
|
||||
@Before
|
||||
public void setUp() {
|
||||
importer = new NOAAImporterForTesting();
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.sap.sailing.declination.test;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
|
||||
import com.sap.sailing.declination.impl.NOAAImporter;
|
||||
|
||||
@Ignore("US Government Shutdown around 2018-01-22")
|
||||
public class NOAADeclinationServiceTest extends DeclinationServiceTest<NOAAImporter> {
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
importer = new NOAAImporter();
|
||||
super.setUp();
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.sap.sailing.declination.test;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
|
||||
import com.sap.sailing.declination.impl.NOAAImporter;
|
||||
|
||||
@Ignore("US Government Shutdown around 2018-01-22")
|
||||
public class NOAADeclinationStoreTest extends DeclinationStoreTest<NOAAImporter> {
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
importer = new NOAAImporter();
|
||||
super.setUp();
|
||||
}
|
||||
}
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
package com.sap.sailing.declination.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.declination.impl.NOAAImporterForTesting;
|
||||
|
||||
public class NOAARegexpTest extends AbstractDeclinationTest<NOAAImporterForTesting> {
|
||||
@Before
|
||||
public void setUp() {
|
||||
importer = new NOAAImporterForTesting();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegexpDeclination() {
|
||||
Matcher declinationMatcher = importer.getDeclinationPattern().matcher(" <p class=\"indent\"><b>Declination</b> = 12° 41' W");
|
||||
assertTrue(declinationMatcher.find());
|
||||
assertEquals("12", declinationMatcher.group(1));
|
||||
assertEquals("41", declinationMatcher.group(2));
|
||||
assertEquals("W", declinationMatcher.group(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegexpAnnualChange() {
|
||||
Matcher annualChangeMatcher = importer.getAnnualChangePattern().matcher(" changing by 0° 11' E/year </p>");
|
||||
assertTrue(annualChangeMatcher.find());
|
||||
assertEquals("0", annualChangeMatcher.group(1));
|
||||
assertEquals("11", annualChangeMatcher.group(2));
|
||||
assertEquals("E", annualChangeMatcher.group(3));
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.sap.sailing.declination.test;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
|
||||
import com.sap.sailing.declination.impl.NOAAImporter;
|
||||
|
||||
@Ignore("US Government Shutdown around 2018-01-22")
|
||||
public class NOAASimpleDeclinationTest extends SimpleDeclinationTest<NOAAImporter> {
|
||||
@Before
|
||||
public void setUp() {
|
||||
importer = new NOAAImporter();
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -11,33 +11,33 @@ import org.junit.Test;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.sap.sailing.declination.Declination;
|
||||
import com.sap.sailing.declination.impl.DeclinationImporter;
|
||||
import com.sap.sailing.domain.common.Bearing;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
public class SimpleDeclinationTest extends AbstractDeclinationTest {
|
||||
public abstract class SimpleDeclinationTest<I extends DeclinationImporter> extends AbstractDeclinationTest<I> {
|
||||
@Test
|
||||
public void testSimpleCorrection() throws IOException, ParseException, ParserConfigurationException, SAXException {
|
||||
final MillisecondsTimePoint timePoint = new MillisecondsTimePoint(simpleDateFormat.parse("2019-05-27").getTime());
|
||||
Declination record = importer.importRecord(new DegreePosition(53, 3), timePoint);
|
||||
assertEquals(0.70594, record.getBearing().getDegrees(), 0.0001);
|
||||
assertEquals(0.14745, record.getAnnualChange().getDegrees(), 0.0001);
|
||||
assertEquals(0.70594, record.getBearing().getDegrees(), 0.001);
|
||||
assertEquals(0.14745, record.getAnnualChange().getDegrees(), 0.001);
|
||||
TimePoint oneYearLater = timePoint.plus(Duration.ONE_YEAR);
|
||||
Bearing bearing = record.getBearingCorrectedTo(oneYearLater);
|
||||
assertEquals(0.70594+0.14745, bearing.getDegrees(), 0.0001);
|
||||
assertEquals(0.70594+0.14745, bearing.getDegrees(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBackwardCorrection() throws IOException, ParseException, ParserConfigurationException, SAXException {
|
||||
final MillisecondsTimePoint timePoint = new MillisecondsTimePoint(simpleDateFormat.parse("2019-05-27").getTime());
|
||||
Declination record = importer.importRecord(new DegreePosition(53, 3), timePoint);
|
||||
assertEquals(0.70594, record.getBearing().getDegrees(), 0.0001);
|
||||
assertEquals(0.14745, record.getAnnualChange().getDegrees(), 0.0001);
|
||||
assertEquals(0.70594, record.getBearing().getDegrees(), 0.001);
|
||||
assertEquals(0.14745, record.getAnnualChange().getDegrees(), 0.001);
|
||||
TimePoint oneYearEarlier = timePoint.minus(Duration.ONE_YEAR);
|
||||
Bearing bearing = record.getBearingCorrectedTo(oneYearEarlier);
|
||||
assertEquals(0.70594-0.14745, bearing.getDegrees(), 0.0001);
|
||||
assertEquals(0.70594-0.14745, bearing.getDegrees(), 0.01);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -3,6 +3,7 @@ package com.sap.sailing.declination;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import com.sap.sailing.declination.impl.ColoradoImporter;
|
||||
import com.sap.sailing.declination.impl.DeclinationServiceImpl;
|
||||
import com.sap.sailing.declination.impl.NOAAImporter;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
@@ -16,7 +17,7 @@ public interface DeclinationService {
|
||||
* A default implementation with a spatial default precision of 1 {@link Mile#METERS_PER_GEOGRAPHICAL_MILE
|
||||
* geographical mile} which equals the length of an arc with one degree on a meridian.
|
||||
*/
|
||||
DeclinationService INSTANCE = new DeclinationServiceImpl(new CentralAngleDistance(1./180.*Math.PI));
|
||||
DeclinationService INSTANCE = new DeclinationServiceImpl(new CentralAngleDistance(1./180.*Math.PI), new ColoradoImporter());
|
||||
|
||||
/**
|
||||
* Obtains declination information with the default precision of this declination service in time and space
|
||||
|
||||
Executable
+124
@@ -0,0 +1,124 @@
|
||||
package com.sap.sailing.declination.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import com.sap.sailing.declination.Declination;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
/**
|
||||
* A typical request for the Geomag service looks like this:
|
||||
* <pre>
|
||||
* http://magcalc.geomag.info/?model=WMM2015&sourcePage=oldCalc&decimalLatitude=10&decimalLongitude=20&minYear=2018&minMonth=1&minDay=23
|
||||
* </pre>
|
||||
* The response serves an XML document that has elements like this:
|
||||
* <pre>
|
||||
* <DATE>
|
||||
* 2018.06027
|
||||
* </DATE>
|
||||
* <LATITUDE units = "Degree">
|
||||
* 10.00000
|
||||
* </LATITUDE>
|
||||
* <LONGITUDE units="Degree">
|
||||
* 20.00000
|
||||
* </LONGITUDE>
|
||||
* <DECLINATION units="Degree">
|
||||
* 1.89255
|
||||
* </DECLINATION>
|
||||
* <DECLINATION_SV units="Degree">
|
||||
* 0.10649
|
||||
* </DECLINATION_SV>
|
||||
* </pre>
|
||||
* representing the declination in degrees, as well as its annual change.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public class ColoradoImporter extends DeclinationImporter {
|
||||
private static final String URL_PATTERN = "http://magcalc.geomag.info/?model=WMM2015&sourcePage=oldCalc&decimalLatitude=%f&decimalLongitude=%f&minYear=%d&minMonth=%d&minDay=%d";
|
||||
|
||||
private static class XmlElementHandler extends DefaultHandler {
|
||||
private double dateAsDecimalYear;
|
||||
private double latDeg;
|
||||
private double lngDeg;
|
||||
private double declinationDeg;
|
||||
private double annualDeclinationChangeDeg;
|
||||
|
||||
private StringBuilder elementContent;
|
||||
|
||||
public XmlElementHandler() {
|
||||
elementContent = new StringBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
||||
throws SAXException {
|
||||
elementContent.delete(0, elementContent.length());
|
||||
super.startElement(uri, localName, qName, attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
elementContent.append(ch, start, length);
|
||||
super.characters(ch, start, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
final String content = elementContent.toString();
|
||||
switch (qName) {
|
||||
case "DATE":
|
||||
dateAsDecimalYear = Double.valueOf(content);
|
||||
break;
|
||||
case "LATITUDE":
|
||||
latDeg = Double.valueOf(content);
|
||||
break;
|
||||
case "LONGITUDE":
|
||||
lngDeg = Double.valueOf(content);
|
||||
break;
|
||||
case "DECLINATION":
|
||||
declinationDeg = Double.valueOf(content);
|
||||
break;
|
||||
case "DECLINATION_SV":
|
||||
annualDeclinationChangeDeg = Double.valueOf(content);
|
||||
break;
|
||||
}
|
||||
super.endElement(uri, localName, qName);
|
||||
}
|
||||
|
||||
Declination getDeclination() {
|
||||
return new DeclinationRecordImpl(new DegreePosition(latDeg, lngDeg), new MillisecondsTimePoint((long) ((dateAsDecimalYear-1970.)*365.0*24.0*3600.0*1000.0)),
|
||||
new DegreeBearingImpl(declinationDeg), new DegreeBearingImpl(annualDeclinationChangeDeg));
|
||||
}
|
||||
}
|
||||
|
||||
public Declination getDeclinationFromXml(InputStream is) throws SAXException, IOException, ParserConfigurationException {
|
||||
XmlElementHandler handler = new XmlElementHandler();
|
||||
SAXParserFactory.newInstance().newSAXParser().parse(is, handler);
|
||||
return handler.getDeclination();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Declination importRecord(Position position, TimePoint timePoint)
|
||||
throws IOException, ParserConfigurationException, SAXException {
|
||||
final Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
|
||||
cal.setTime(timePoint.asDate());
|
||||
final URL url = new URL(String.format(URL_PATTERN, position.getLatDeg(), position.getLngDeg(), cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH)));
|
||||
return getDeclinationFromXml(url.openStream());
|
||||
}
|
||||
}
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
package com.sap.sailing.declination.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.sap.sailing.declination.Declination;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public abstract class DeclinationImporter {
|
||||
private static final Logger logger = Logger.getLogger(DeclinationImporter.class.getName());
|
||||
|
||||
public abstract Declination importRecord(Position position, TimePoint timePoint)
|
||||
throws IOException, ParserConfigurationException, SAXException;
|
||||
|
||||
/**
|
||||
* Tries two things in parallel: fetch a more or less precise response from the online service and load
|
||||
* the requested year's declination values from a stored resource to look up a value that comes close.
|
||||
* The online lookup will be given preference. However, should it take longer than
|
||||
* <code>timeoutForOnlineFetchInMilliseconds</code>, then the method will return whatever it found
|
||||
* in the stored file, or <code>null</code> if no file exists for the year of <code>timePoint</code>.
|
||||
*
|
||||
* @param timeoutForOnlineFetchInMilliseconds if 0, this means wait forever for the online result
|
||||
* @throws ParseException
|
||||
* @throws ClassNotFoundException
|
||||
* @throws IOException
|
||||
*/
|
||||
public Declination getDeclination(final Position position, final TimePoint timePoint,
|
||||
long timeoutForOnlineFetchInMilliseconds) throws IOException, ParseException {
|
||||
final Declination[] result = new Declination[1];
|
||||
Thread fetcher = new Thread("Declination fetcher for "+position+"@"+timePoint) {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Declination fetched = importRecord(position, timePoint);
|
||||
synchronized (result) {
|
||||
result[0] = fetched;
|
||||
result.notifyAll();
|
||||
}
|
||||
} catch (IOException | ParserConfigurationException | SAXException e) {
|
||||
logger.log(Level.FINE, "Exception while trying to load magnetic declination online", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
fetcher.start();
|
||||
synchronized (result) {
|
||||
if (result[0] == null) {
|
||||
try {
|
||||
result.wait(timeoutForOnlineFetchInMilliseconds);
|
||||
} catch (InterruptedException e) {
|
||||
// ignore; simply use value from file in this case
|
||||
}
|
||||
}
|
||||
}
|
||||
return result[0];
|
||||
}
|
||||
}
|
||||
+8
-4
@@ -17,7 +17,7 @@ import com.sap.sse.common.TimePoint;
|
||||
public class DeclinationServiceImpl implements DeclinationService {
|
||||
private final Distance defaultMaxDistance;
|
||||
private final DeclinationStore persistentStore;
|
||||
private final NOAAImporter noaaImporter;
|
||||
private final DeclinationImporter declinationImporter;
|
||||
|
||||
/**
|
||||
* Keys are years
|
||||
@@ -33,10 +33,14 @@ public class DeclinationServiceImpl implements DeclinationService {
|
||||
* Constructs a service that has a default position tolerance of <code>defaultMaxDistance</code>.
|
||||
*/
|
||||
public DeclinationServiceImpl(Distance defaultMaxDistance) {
|
||||
this(defaultMaxDistance, new NOAAImporter());
|
||||
}
|
||||
|
||||
public DeclinationServiceImpl(Distance defaultMaxDistance, DeclinationImporter declinationImporter) {
|
||||
this.declinationImporter = declinationImporter;
|
||||
this.defaultMaxDistance = defaultMaxDistance;
|
||||
this.yearStore = new HashMap<Integer, QuadTree<Declination>>();
|
||||
this.persistentStore = new DeclinationStore();
|
||||
this.noaaImporter = new NOAAImporter();
|
||||
this.persistentStore = new DeclinationStore(declinationImporter);
|
||||
this.importerCache = new HashMap<Integer, QuadTree<Declination>>();
|
||||
}
|
||||
|
||||
@@ -84,7 +88,7 @@ public class DeclinationServiceImpl implements DeclinationService {
|
||||
// else it's further away from the requested position as demanded by maxDistance
|
||||
}
|
||||
}
|
||||
result = noaaImporter.getDeclination(position, timePoint, timeoutForOnlineFetchInMilliseconds);
|
||||
result = declinationImporter.getDeclination(position, timePoint, timeoutForOnlineFetchInMilliseconds);
|
||||
if (result != null) {
|
||||
if (importerCacheForYear == null) {
|
||||
importerCacheForYear = new QuadTree<Declination>();
|
||||
|
||||
+15
-7
@@ -38,6 +38,12 @@ import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
public class DeclinationStore {
|
||||
private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
private final DeclinationImporter importer;
|
||||
|
||||
public DeclinationStore(DeclinationImporter importer) {
|
||||
this.importer = importer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>null</code> if no stored declinations exist for the <code>year</code> requested.
|
||||
*/
|
||||
@@ -122,7 +128,7 @@ public class DeclinationStore {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void fetchAndAppendDeclination(TimePoint timePoint, Position position, NOAAImporter importer,
|
||||
private void fetchAndAppendDeclination(TimePoint timePoint, Position position, DeclinationImporter importer,
|
||||
Writer out) throws IOException {
|
||||
Declination declination = null;
|
||||
// re-try three times
|
||||
@@ -153,7 +159,6 @@ public class DeclinationStore {
|
||||
usage();
|
||||
} else {
|
||||
double grid = Double.valueOf(args[2]);
|
||||
NOAAImporter importer = new NOAAImporter();
|
||||
for (int year = fromYear; year <= toYear; year++) {
|
||||
QuadTree<Declination> storedDeclinations = getStoredDeclinations(year);
|
||||
if (storedDeclinations == null) {
|
||||
@@ -182,7 +187,7 @@ public class DeclinationStore {
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchAndAppendDeclinationForLatitude(double grid, NOAAImporter importer, int year,
|
||||
private void fetchAndAppendDeclinationForLatitude(double grid, DeclinationImporter importer, int year,
|
||||
QuadTree<Declination> storedDeclinations, Writer out, int month, TimePoint timePoint, double lat)
|
||||
throws IOException {
|
||||
System.out.println("Date: " + year + "/" + (month + 1) + ", Latitude: " + lat);
|
||||
@@ -194,7 +199,7 @@ public class DeclinationStore {
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchAndAppendDeclination(NOAAImporter importer, QuadTree<Declination> storedDeclinations, Writer out,
|
||||
private void fetchAndAppendDeclination(DeclinationImporter importer, QuadTree<Declination> storedDeclinations, Writer out,
|
||||
TimePoint timePoint, double lat, double lng) throws IOException {
|
||||
Position point = new DegreePosition(lat, lng);
|
||||
final Declination existingDeclinationRecord;
|
||||
@@ -213,16 +218,19 @@ public class DeclinationStore {
|
||||
* Launches the importer, writing to resources/declination-year.txt (where "year" represents the year for which the
|
||||
* values are stored in the file) the declinations downloaded online for the years <code>args[0]</code> to
|
||||
* <code>args[1]</code> (inclusive) for all positions with a grid of <code>args[2]</code> degrees each, starting at
|
||||
* 0°0.0'N and 0°0.0'E.
|
||||
* 0°0.0'N and 0°0.0'E. <code>args[3]</code> can optionally be used to select a non-default declination
|
||||
* importer. By default, the {@link NOAAImporter} will be used. Using "c" here will use the {@link ColoradoImporter}
|
||||
* instead.
|
||||
*
|
||||
* @throws ParseException
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public static void main(String[] args) throws IOException, ClassNotFoundException, ParseException {
|
||||
DeclinationStore store = new DeclinationStore();
|
||||
DeclinationStore store = new DeclinationStore(args.length > 3 && args[3].equals("c") ? new ColoradoImporter() : new NOAAImporter());
|
||||
store.run(args);
|
||||
}
|
||||
|
||||
private void usage() {
|
||||
System.out.println("java " + NOAAImporter.class.getName() + " <fromYear> <toYear> <gridSizeInDegrees>");
|
||||
System.out.println("java " + getClass().getName() + " <fromYear> <toYear> <gridSizeInDegrees>");
|
||||
}
|
||||
}
|
||||
|
||||
+2
-47
@@ -4,12 +4,9 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.text.ParseException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
@@ -31,8 +28,7 @@ import com.sap.sse.common.TimePoint;
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class NOAAImporter {
|
||||
private static final Logger logger = Logger.getLogger(NOAAImporter.class.getName());
|
||||
public class NOAAImporter extends DeclinationImporter {
|
||||
private static final String QUERY_URL = "https://www.ngdc.noaa.gov/geomag-web/calculators/calculateDeclination";
|
||||
private static final String REGEXP_DECLINATION = "<p class=\"indent\"><b>Declination</b> = ([0-9]*)° ([0-9]*)' *([EW])";
|
||||
private static final String REGEXP_ANNUAL_CHANGE = "changing by *([0-9]*)° *([0-9]*)' ([EW])/year *</p>";
|
||||
@@ -54,6 +50,7 @@ public class NOAAImporter {
|
||||
return annualChangePattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Declination importRecord(Position position, TimePoint timePoint) throws IOException, ParserConfigurationException, SAXException {
|
||||
Declination result = null;
|
||||
Date date = timePoint.asDate();
|
||||
@@ -80,46 +77,4 @@ public class NOAAImporter {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries two things in parallel: fetch a more or less precise response from the online service and load
|
||||
* the requested year's declination values from a stored resource to look up a value that comes close.
|
||||
* The online lookup will be given preference. However, should it take longer than
|
||||
* <code>timeoutForOnlineFetchInMilliseconds</code>, then the method will return whatever it found
|
||||
* in the stored file, or <code>null</code> if no file exists for the year of <code>timePoint</code>.
|
||||
*
|
||||
* @param timeoutForOnlineFetchInMilliseconds if 0, this means wait forever for the online result
|
||||
* @throws ParseException
|
||||
* @throws ClassNotFoundException
|
||||
* @throws IOException
|
||||
*/
|
||||
public Declination getDeclination(final Position position, final TimePoint timePoint,
|
||||
long timeoutForOnlineFetchInMilliseconds) throws IOException, ParseException {
|
||||
final Declination[] result = new Declination[1];
|
||||
Thread fetcher = new Thread("Declination fetcher for "+position+"@"+timePoint) {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Declination fetched = importRecord(position, timePoint);
|
||||
synchronized (result) {
|
||||
result[0] = fetched;
|
||||
result.notifyAll();
|
||||
}
|
||||
} catch (IOException | ParserConfigurationException | SAXException e) {
|
||||
logger.log(Level.FINE, "Exception while trying to load magnetic declination online", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
fetcher.start();
|
||||
synchronized (result) {
|
||||
if (result[0] == null) {
|
||||
try {
|
||||
result.wait(timeoutForOnlineFetchInMilliseconds);
|
||||
} catch (InterruptedException e) {
|
||||
// ignore; simply use value from file in this case
|
||||
}
|
||||
}
|
||||
}
|
||||
return result[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -2030,7 +2030,7 @@ totalDistanceFoiledInMetersTooltip=Total distance foiled, across the entire lead
|
||||
threeSixtyVideoHint=This is a 360° video, the camera can be turned
|
||||
processingMP4=Mp4 is analyzed (this will take a few Seconds)
|
||||
resetStartTimeToDefault=Set to default
|
||||
importFullExpeditionData=Import full expedition data
|
||||
importFullExpeditionData=Import full Expedition data
|
||||
importCanceledNoCompetitorAdded=No competitor was added! Import will be canceled.
|
||||
importCanceledByUser=Import canceled!
|
||||
importFinished=Finished importing data
|
||||
|
||||
Reference in New Issue
Block a user