aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo')
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCBase.java179
1 files changed, 144 insertions, 35 deletions
diff --git a/main/src/cgeo/geocaching/connector/gc/GCBase.java b/main/src/cgeo/geocaching/connector/gc/GCBase.java
index 439ff7a..b037366 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCBase.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCBase.java
@@ -1,4 +1,4 @@
-package cgeo.geocaching.connector;
+package cgeo.geocaching.connector.gc;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Settings;
@@ -19,14 +19,23 @@ import org.json.JSONObject;
import android.util.Log;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
+ * GC.com/Groundspeak (GS) specific stuff
*
* @author blafoo
*
*/
-public class GCConnectorImpl {
+public class GCBase {
+
+ protected final static String SEQUENCE_GCID = "0123456789ABCDEFGHJKMNPQRTVWXYZ";
+ protected final static String SEQUENCE_NEWID = "tHpXJR8gyfzCrdV5G0Kb3Y92N47lTBPAhWnvLZkaexmSwq6sojDcEQMFO";
+ protected final static long GC_BASE57 = 57;
+ protected final static long GC_BASE31 = 31;
+ protected final static long GC_BASE16 = 16;
// TODO Valentine remove before merge
/** go online or use mocked data ? */
@@ -60,11 +69,11 @@ public class GCConnectorImpl {
"55_54\":[{\"i\":\"gEaR\",\"n\":\"Spiel & Sport\"}],\"17_25\":[{\"i\":\"Rkzt\",\"n\":\"EDSSW: Rathaus \"}],\"55_53\":[{\"i\":\"gEaR\",\"n\":\"Spiel & Sport\"}],\"17_27\":[{\"i\":\"Rkzt\",\"n\":\"EDSSW: Rathaus \"}],\"17_26\":[{\"i\":\"Rkzt\",\"n\":\"EDSSW: Rathaus \"}],\"57_53\":[{\"i\":\"gEaR\",\"n\":\"Spiel & Sport\"}],\"57_55\":[{\"i\":\"gEaR\",\"n\":\"Spiel & Sport\"}],\"3_62\":[{\"i\":\"gOWz\",\"n\":\"Baumarktserie - Wer Wo Was -\"}],\"3_61\":[{\"i\":\"gOWz\",\"n\":\"Baumarktserie - Wer Wo Was -\"}],\"57_54\":[{\"i\":\"gEaR\",\"n\":\"Spiel & Sport\"}],\"3_60\":[{\"i\":\"gOWz\",\"n\":\"Baumarktserie - Wer Wo Was -\"}],\"15_27\":[{\"i\":\"Rkzt\",\"n\":\"EDSSW: Rathaus \"}],\"15_26\":[{\"i\":\"Rkzt\",\"n\":\"EDSSW: Rathaus \"}],\"15_25\":[{\"i\":\"Rkzt\",\"n\":\"EDSSW: Rathaus \"}],\"4_60\":[{\"i\":\"gOWz\",\"n\":\"Baumarktserie - Wer Wo Was -\"}],\"4_61\":[{\"i\":\"gOWz\",\"n\":\"Baumarktserie - Wer Wo Was -\"}],\"4_62\":[{\"i\":\"gOWz\",\"n\":\"Baumarktserie - Wer Wo Was -\"}],\"16_25\":[{\"i\":\"Rkzt\",\"n\":\"EDSSW: Rathaus \"}],\"16_26\":[{\"i\":\"Rkzt\",\"n\":\"EDSSW: Rathaus \"}],\"16_27\":[{\"i\":\"Rkzt\",\"n\":\"EDSSW: Rathaus \"}],\"2_62\":[{\"i\":\"gOWz\",\"n\":\"Baumarktserie - Wer Wo Was -\"}],\"2_60\":[{\"i\":\"gOWz\",\"n\":\"Baumarktserie - Wer Wo Was -\"}],\"2_61\":[{\"i\":\"gOWz\",\"n\":\"Baumarktserie - Wer Wo Was -\"}],\"56_53\":[{\"i\":\"gEaR\",\"n\":\"Spiel & Sport\"}],\"56_54\":[{\"i\":\"gEaR\",\"n\":\"Spiel & Sport\"}],\"56_55\":[{\"i\":\"gEaR\",\"n\":\"Spiel & Sport\"}]}}";
}
if (StringUtils.isBlank(page)) {
- Log.e(Settings.tag, "GCConnectImpl.searchByViewport: No data from server for tile (" + tile.left + "/" + tile.right + ")");
+ Log.e(Settings.tag, "GCBase.searchByViewport: No data from server for tile (" + tile.left + "/" + tile.right + ")");
}
final SearchResult search = parseMapJSON(url, page);
if (search == null || CollectionUtils.isEmpty(search.getGeocodes())) {
- Log.e(Settings.tag, "GCConnectImpl.searchByViewport: No cache parsed for viewport " + viewport);
+ Log.e(Settings.tag, "GCBase.searchByViewport: No cache parsed for viewport " + viewport);
}
searchResult.addGeocodes(search.getGeocodes());
}
@@ -112,49 +121,65 @@ public class GCConnectorImpl {
throw new JSONException("No data inside JSON");
}
+ // attach all keys with the cache positions in the tile
+ Map<String, ImmutablePair<Integer, Integer>> keyPositions = new HashMap<String, ImmutablePair<Integer, Integer>>(); // JSON key, (x/y) in grid
for (int y = 0; y < grid.length(); y++) {
byte[] row = grid.getString(y).getBytes();
for (int x = 0; x < row.length; x++) {
- byte id = getUTFGridId(row[x]);
- if (id > 0) {
- Log.d(Settings.tag, "(" + x + "/" + y + ") =" + String.valueOf(id));
+ if (row[x] != 32) {
+ byte id = UTFGrid.getUTFGridId(row[x]);
+ keyPositions.put(keys.getString(id), new ImmutablePair<Integer, Integer>(x, y));
}
}
}
- //Map<String, Integer> keyIds = new HashMap<String, Integer>(); // key (55_55), index
- //Map<String, cgCache> caches = new HashMap<String, cgCache>(); // name, cache
- //Map<String, List<String>> positions = new HashMap<String, List<String>>(); // name, keys
-
+ // iterate over the data and construct all caches in this tile
+ Map<String, cgCache> caches = new HashMap<String, cgCache>(); // JSON id, cache
+ Map<String, List<ImmutablePair<Integer, Integer>>> positions = new HashMap<String, List<ImmutablePair<Integer, Integer>>>(); // JSON id as key
for (int i = 0; i < keys.length(); i++) {
String key = keys.getString(i);
- Log.d(Settings.tag, "Key #" + i + "=" + key);
if (StringUtils.isNotBlank(key)) {
JSONArray dataForKey = dataObject.getJSONArray(key);
for (int j = 0; j < dataForKey.length(); j++) {
JSONObject cacheInfo = dataForKey.getJSONObject(j);
- // TODO Valentine How to convert to a geocode ? Or is an extra request needed ?
String id = cacheInfo.getString("i");
- String name = cacheInfo.getString("n");
-
- final cgCache cacheToAdd = new cgCache();
- cacheToAdd.setDetailed(false);
- cacheToAdd.setReliableLatLon(false);
- cacheToAdd.setGeocode(id);
- cacheToAdd.setCoords(getCoordsForUTFGrid(key));
- cacheToAdd.setName(name);
- cacheToAdd.setType(CacheType.GC_LIVE_MAP);
+ cgCache cache = caches.get(id);
+ if (cache == null) {
+ cache = new cgCache();
+ cache.setDetailed(false);
+ cache.setReliableLatLon(false);
+ cache.setGeocode(newidToGeocode(id));
+ cache.setName(cacheInfo.getString("n"));
+ cache.setType(CacheType.GC_LIVE_MAP);
- Log.d(Settings.tag, "key=" + key + " id=" + id + " name=" + name);
+ caches.put(id, cache);
+ }
- //caches.put(id, cacheToAdd);
- searchResult.addCache(cacheToAdd);
+ List<ImmutablePair<Integer, Integer>> pos = positions.get(id);
+ if (pos == null) {
+ pos = new ArrayList<ImmutablePair<Integer, Integer>>();
+ }
+ pos.add(keyPositions.get(key));
+ positions.put(id, pos);
}
}
}
+ for (String id : positions.keySet()) {
+ List<ImmutablePair<Integer, Integer>> pos = positions.get(id);
+ cgCache cache = caches.get(id);
+ cache.setCoords(getCoordsForUTFGrid(pos));
+
+ Log.d(Settings.tag, "id= " + id + " geocode= " + cache.getGeocode());
+ for (ImmutablePair<Integer, Integer> ImmutablePair : pos) {
+ Log.d(Settings.tag, "(" + ImmutablePair.left + "," + ImmutablePair.right + ")");
+ }
+
+ searchResult.addCache(cache);
+ }
+
} catch (Exception e) {
- Log.e(Settings.tag, "cgBase.parseMapJSON", e);
+ Log.e(Settings.tag, "GCBase.parseMapJSON", e);
}
return searchResult;
@@ -175,21 +200,105 @@ public class GCConnectorImpl {
}
- protected static Geopoint getCoordsForUTFGrid(String key) {
+ /** Calculate from a list of positions (x/y) the coords */
+ protected static Geopoint getCoordsForUTFGrid(List<ImmutablePair<Integer, Integer>> positions) {
// TODO Valentine Calculate coords
return new Geopoint("N 52° 24,516 E 009° 42,592");
}
- /** @see https://github.com/mapbox/mbtiles-spec/blob/master/1.1/utfgrid.md */
- protected static byte getUTFGridId(final byte value) {
- byte result = value;
- if (result >= 93) {
- result--;
+ /**
+ * Convert GCCode (geocode) to (old) GCIds
+ *
+ * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40
+ * see http://support.groundspeak.com/index.php?pg=kb.printer.friendly&id=1#p221
+ */
+ public static long gccodeToGCId(final String gccode) {
+ long gcid = 0;
+ long base = GC_BASE31;
+ String geocodeWO = gccode.substring(2).toUpperCase();
+
+ if ((geocodeWO.length() < 4) || (geocodeWO.length() == 4 && SEQUENCE_GCID.indexOf(geocodeWO.charAt(0)) < 16)) {
+ base = GC_BASE16;
+ }
+
+ for (int p = 0; p < geocodeWO.length(); p++) {
+ gcid = base * gcid + SEQUENCE_GCID.indexOf(geocodeWO.charAt(p));
+ }
+
+ if (base == GC_BASE31) {
+ gcid += Math.pow(16, 4) - 16 * Math.pow(31, 3);
+ }
+ return gcid;
+ }
+
+ private static String modulo(final long value, final long base, final String sequence) {
+ String result = "";
+ long rest = 0;
+ long divResult = value;
+ do
+ {
+ rest = divResult % base;
+ divResult = (int) Math.floor(divResult / base);
+ result = sequence.charAt((int) rest) + result;
+ } while (divResult != 0);
+ return result;
+ }
+
+ /**
+ * Convert (old) GCIds to GCCode (geocode)
+ *
+ * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40
+ */
+ public static String gcidToGCCode(final long gcid) {
+ String gccode = modulo(gcid + 411120, GC_BASE31, SEQUENCE_GCID);
+ if ((gccode.length() < 4) || (gccode.length() == 4 && SEQUENCE_GCID.indexOf(gccode.charAt(0)) < 16)) {
+ gccode = modulo(gcid, GC_BASE16, SEQUENCE_GCID);
}
- if (result >= 35) {
- result--;
+ return "GC" + gccode;
+ }
+
+ /**
+ * Convert ids from the live map to (old) GCIds
+ *
+ * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40
+ */
+ public static long newidToGCId(final String newid) {
+ long gcid = 0;
+ for (int p = 0; p < newid.length(); p++) {
+ gcid = GC_BASE57 * gcid + SEQUENCE_NEWID.indexOf(newid.charAt(p));
}
- return (byte) (result - 32);
+ return gcid;
+ }
+
+ /**
+ * Convert (old) GCIds to ids used in the live map
+ *
+ * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40
+ */
+ public static String gcidToNewId(final long gcid) {
+ return modulo(gcid, GC_BASE57, SEQUENCE_NEWID);
+ }
+
+ /**
+ * Convert ids from the live map into GCCode (geocode)
+ */
+ public static String newidToGeocode(final String newid) {
+ long gcid = GCBase.newidToGCId(newid);
+ return GCBase.gcidToGCCode(gcid);
+ }
+
+ /** Request further details in the live mapa for a given id */
+ public void requestDetailsFromMap(@SuppressWarnings("unused") String id) {
+ /**
+ * URL http://www.geocaching.com/map/map.details?i=gEaR
+ * Response: {"status":"success","data":[{"name":"Spiel & Sport","gc":"GC211WG","g":
+ * "872d7eda-7cb9-40d5-890d-5b344bce7302"
+ * ,"disabled":false,"subrOnly":false,"li":false,"fp":"0","difficulty":{"text"
+ * :3.0,"value":"3"},"terrain":{"text"
+ * :2.0,"value":"2"},"hidden":"11/15/2009","container":{"text":"Regular","value"
+ * :"regular.gif"},"type":{"text":"Multi-cache"
+ * ,"value":3},"owner":{"text":"kai2707","value":"5c4b0915-5cec-4fa1-8afd-4b3ca67e004e"}}]}
+ */
}
}