Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<artifactId>mapcode</artifactId>

<packaging>jar</packaging>
<version>2.0.0</version>
<version>2.0.1-SNAPSHOT</version>

<name>Mapcode Java Library</name>
<description>
Expand Down Expand Up @@ -68,7 +68,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<jdk.version>1.7</jdk.version>
<jdk.version>1.8</jdk.version>

<gson.version>2.3.1</gson.version>
<jsr305.version>3.0.0</jsr305.version>
Expand Down Expand Up @@ -160,7 +160,6 @@

<dependencies>

<!-- Logging. -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
Expand All @@ -179,15 +178,13 @@
<version>${slf4j.version}</version>
</dependency>

<!-- Unit testing. -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>

<!-- @Nullable and @Nonnull annotations. -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
Expand All @@ -197,7 +194,6 @@
<optional>true</optional>
</dependency>

<!-- JSON. -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
Expand Down
4 changes: 4 additions & 0 deletions src/site/apt/ReleaseNotes.apt.vm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ Release Notes (Version ${project.version})
In any case, never depend on them for your own non-<<<SNAPSHOT>>> releases.
#end

* 2.0.1

* Use multi-threading for long running test to speed them up (uses all CPU cores now).

* 2.0.0

* Fixes to the data rectangles (primarily intended for ISO proposal).
Expand Down
125 changes: 67 additions & 58 deletions src/test/java/com/mapcode/EncodeDecodeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@

import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
Expand All @@ -37,6 +41,7 @@ public class EncodeDecodeTest {
private static final int NUMBER_OF_POINTS = 5000;
private static final int LOG_LINE_EVERY = 500;


@Test
public void encodeDecodeTestFixedSeed() throws Exception {
final long seed = 1431977987367L;
Expand All @@ -51,13 +56,19 @@ public void encodeDecodeTestRandomSeed() throws Exception {
doEncodeDecode(seed);
}

private static void doEncodeDecode(final long seed) throws UnknownMapcodeException {
private static void doEncodeDecode(final long seed) throws InterruptedException {

// Keep error count and create thread pool.
final AtomicInteger errors = new AtomicInteger(0);
final int threads = Runtime.getRuntime().availableProcessors();
LOG.info("encodeDecodeTest: Starting {} threads...", threads);
final ExecutorService executor = Executors.newFixedThreadPool(threads);

final Random randomGenerator = new Random(seed);
double maxDistancePrecision0Meters = 0.0;
double maxDistancePrecision1Meters = 0.0;
double maxDistancePrecision2Meters = 0.0;
for (int i = 0; i < NUMBER_OF_POINTS; i++) {
boolean showLogLine = ((i % LOG_LINE_EVERY) == 0);
if ((i % LOG_LINE_EVERY) == 0) {
LOG.info("encodeDecodeTest: #{}/{}", i, NUMBER_OF_POINTS);
}

// Encode location.
final Point encode = Point.fromUniformlyDistributedRandomPoints(randomGenerator);
Expand All @@ -73,63 +84,61 @@ private static void doEncodeDecode(final long seed) throws UnknownMapcodeExcepti
assertEquals("encodeToInternational failed, result=" + resultsAll,
resultsAll.get(resultsAll.size() - 1), mapcodeInternational);

// Every point must have a Mapcode.
boolean found = false;

// Walk through the list in reverse order to get International first.
for (final Territory territory : Territory.values()) {
final List<Mapcode> resultsLimited = MapcodeCodec.encode(latDeg, lonDeg, territory);
for (final Mapcode mapcode : resultsLimited) {
found = true;

// Check if the territory matches.
assertEquals(territory, mapcode.getTerritory());

// Check max distance.
final String codePrecision0 = mapcode.getCode(0);
final String codePrecision1 = mapcode.getCode(1);
final String codePrecision2 = mapcode.getCode(2);

final Point decodeLocationPrecision0 = MapcodeCodec.decode(codePrecision0, territory);
final Point decodeLocationPrecision1 = MapcodeCodec.decode(codePrecision1, territory);
final Point decodeLocationPrecision2 = MapcodeCodec.decode(codePrecision2, territory);

final double distancePrecision0Meters = Point.distanceInMeters(encode, decodeLocationPrecision0);
final double distancePrecision1Meters = Point.distanceInMeters(encode, decodeLocationPrecision1);
final double distancePrecision2Meters = Point.distanceInMeters(encode, decodeLocationPrecision2);

maxDistancePrecision0Meters = Math.max(maxDistancePrecision0Meters, distancePrecision0Meters);
maxDistancePrecision1Meters = Math.max(maxDistancePrecision1Meters, distancePrecision1Meters);
maxDistancePrecision2Meters = Math.max(maxDistancePrecision2Meters, distancePrecision2Meters);

assertTrue(mapcode + " distancePrecision0Meters=" + distancePrecision0Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(0),
distancePrecision0Meters < Mapcode.getSafeMaxOffsetInMeters(0));
assertTrue(mapcode + "distancePrecision1Meters=" + distancePrecision1Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(1),
distancePrecision1Meters < Mapcode.getSafeMaxOffsetInMeters(1));
assertTrue(mapcode + "distancePrecision2Meters=" + distancePrecision2Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(2),
distancePrecision2Meters < Mapcode.getSafeMaxOffsetInMeters(2));

// Check conversion from/to alphabets.
for (final Alphabet alphabet : Alphabet.values()) {
final String mapcodeAlphabet = mapcode.getCode(alphabet);
final String mapcodeAscii = Mapcode.convertStringToPlainAscii(mapcodeAlphabet);
assertEquals(mapcode + " alphabet=" + alphabet + ", original=" + codePrecision0 +
", mapcodeAlphabet=" + mapcodeAlphabet + ", mapcodeAscii=" + mapcodeAscii,
codePrecision0, mapcodeAscii);
}

if (showLogLine) {
LOG.info("encodeDecodeTest: #{}/{}, result={}, mapcode={}, territory={} --> " +
"lat={}, lon={}; delta={}", i, NUMBER_OF_POINTS,
mapcode, codePrecision0, territory.getFullName(), decodeLocationPrecision0.getLatDeg(),
decodeLocationPrecision0.getLonDeg(), distancePrecision0Meters);
executor.execute(() -> {
try {
final List<Mapcode> resultsLimited = MapcodeCodec.encode(latDeg, lonDeg, territory);
for (final Mapcode mapcode : resultsLimited) {

// Check if the territory matches.
assertEquals(territory, mapcode.getTerritory());

// Check max distance.
final String codePrecision0 = mapcode.getCode(0);
final String codePrecision1 = mapcode.getCode(1);
final String codePrecision2 = mapcode.getCode(2);

final Point decodeLocationPrecision0 = MapcodeCodec.decode(codePrecision0, territory);
final Point decodeLocationPrecision1 = MapcodeCodec.decode(codePrecision1, territory);
final Point decodeLocationPrecision2 = MapcodeCodec.decode(codePrecision2, territory);

final double distancePrecision0Meters = Point.distanceInMeters(encode, decodeLocationPrecision0);
final double distancePrecision1Meters = Point.distanceInMeters(encode, decodeLocationPrecision1);
final double distancePrecision2Meters = Point.distanceInMeters(encode, decodeLocationPrecision2);

if (distancePrecision0Meters >= Mapcode.getSafeMaxOffsetInMeters(0)) {
LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision0Meters = " + distancePrecision0Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(0));
errors.getAndIncrement();
}
if (distancePrecision1Meters >= Mapcode.getSafeMaxOffsetInMeters(1)) {
LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision1Meters = " + distancePrecision1Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(1));
errors.getAndIncrement();
}
if (distancePrecision2Meters >= Mapcode.getSafeMaxOffsetInMeters(2)) {
LOG.error("encodeDecodeTest: " + mapcode + " distancePrecision2Meters = " + distancePrecision2Meters + " >= " + Mapcode.getSafeMaxOffsetInMeters(2));
errors.getAndIncrement();
}

// Check conversion from/to alphabets.
for (final Alphabet alphabet : Alphabet.values()) {
final String mapcodeAlphabet = mapcode.getCode(alphabet);
final String mapcodeAscii = Mapcode.convertStringToPlainAscii(mapcodeAlphabet);
if (!codePrecision0.equals(mapcodeAscii)) {
LOG.error("encodeDecodeTest: " + mapcode + " alphabet=" + alphabet + ", original=" + codePrecision0 +
", mapcodeAlphabet=" + mapcodeAlphabet + ", mapcodeAscii=" + mapcodeAscii);
}
}
}
} catch (final Exception e) {
LOG.error("encodeDecodeTest: Unexpected exception: ", e);
errors.getAndIncrement();
}
showLogLine = false;
}
});
}
assertTrue(found);
}
LOG.debug("encodeDecodeTest: maximum distances, precision 0, 1, 2: {}, {}, {} meters, ",
maxDistancePrecision0Meters, maxDistancePrecision1Meters, maxDistancePrecision2Meters);
executor.shutdown();
executor.awaitTermination(60, TimeUnit.SECONDS);
assertEquals("Found errors", 0, errors.get());
}
}
Loading