aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/connector/gc/GCBase.java
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/connector/gc/GCBase.java')
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCBase.java143
1 files changed, 82 insertions, 61 deletions
diff --git a/main/src/cgeo/geocaching/connector/gc/GCBase.java b/main/src/cgeo/geocaching/connector/gc/GCBase.java
index 05ed9ec..587f81b 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCBase.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCBase.java
@@ -3,13 +3,13 @@ package cgeo.geocaching.connector.gc;
import cgeo.geocaching.GCConstants;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.StoredList;
import cgeo.geocaching.cgBase;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.utils.BaseUtils;
+import cgeo.geocaching.utils.LeastRecentlyUsedCache;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@@ -39,25 +39,26 @@ public class GCBase {
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 ? */
- public static final boolean IS_ONLINE = true;
-
+ private static final LeastRecentlyUsedCache<String, cgCache> liveMapCache = new LeastRecentlyUsedCache<String, cgCache>(2000); // JSON id, cache
// TODO Valentine move to connector before merge
/**
* @param viewport
* @param zoomlevel
* initial zoomlevel
- * @autoAdjust Auto-adjust zoomlevel
+ * @param autoAdjust
+ * Auto-adjust zoomlevel
* @param sessionToken
* @return
*/
@SuppressWarnings("null")
- public static SearchResult searchByViewport(final Viewport viewport, final int zoomlevel, final boolean autoAdjust, final String sessionToken) {
+ public static SearchResult searchByViewport(final Viewport viewport, final int zoomlevel, final boolean autoAdjust, String[] tokens) {
assert zoomlevel >= Tile.ZOOMLEVEL_MIN && zoomlevel <= Tile.ZOOMLEVEL_MAX : "zoomlevel out of bounds.";
+ // TODO Ignore tokens. They are not enough. Also "&_=xxxx" is needed !
+ tokens = null;
+
Geopoint centerOfViewport = new Geopoint((viewport.getLatitudeMin() + viewport.getLatitudeMax()) / 2, (viewport.getLongitudeMin() + viewport.getLongitudeMax()) / 2);
final String referer = GCConstants.URL_LIVE_MAP +
"?ll=" + centerOfViewport.getLatitude() +
@@ -75,35 +76,37 @@ public class GCBase {
* x=8634 --- x-tile
* y=5381 --- y-tile
* z=14 --- zoom
- * _=1329484185663 --- token/filter, not required
+ * k=xxxx --- user session
+ * st=xx...xxx --- session token
+ * ep=1 --- ???
+ * _=1329484185663 --- timestamp (?)
*/
String url = GCConstants.URL_MAP_INFO +
"?x=" + tile.getX() +
"&y=" + tile.getY() +
"&z=" + tile.getZoomlevel();
- if (StringUtils.isNotEmpty(sessionToken)) {
- url += "&st=" + sessionToken;
+ if (tokens != null) {
+ url += "&k=" + tokens[0];
+ url += "&st=" + tokens[1];
}
+ // url += "&ep=1";
+ // url += "&_1329943867982";
- String data = "";
- if (IS_ONLINE) {
- data = cgBase.requestJSON(url, referer);
- } else {
- data = "{\"grid\":[\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" 04$ \",\" /5' \",\" .6& \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" \",\" %:( \",\" #;, \",\" !<) \",\" \",\" \",\" \",\" \",\" 8-1 \",\" 9+2 \",\" 7*3 \",\" \"],\"keys\":[\"\",\"55_55\",\"55_54\",\"17_25\",\"55_53\",\"17_27\",\"17_26\",\"57_53\",\"57_55\",\"3_62\",\"3_61\",\"57_54\",\"3_60\",\"15_27\",\"15_26\",\"15_25\",\"4_60\",\"4_61\",\"4_62\",\"16_25\",\"16_26\",\"16_27\",\"2_62\",\"2_60\",\"2_61\",\"56_53\",\"56_54\",\"56_55\"],\"data\":{\"55_55\":[{\"i\":\"gEaR\",\"n\":\"Spiel & Sport\"}],\"" +
- "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\"}]}}";
- }
+ String data = cgBase.requestJSON(url, referer);
if (StringUtils.isEmpty(data)) {
Log.e(Settings.tag, "GCBase.searchByViewport: No data from server for tile (" + tile.getX() + "/" + tile.getY() + ")");
+ } else {
+ final SearchResult search = parseMapJSON(data, tile);
+ if (search == null || CollectionUtils.isEmpty(search.getGeocodes())) {
+ Log.e(Settings.tag, "GCBase.searchByViewport: No cache parsed for viewport " + viewport);
+ }
+ searchResult.addGeocodes(search.getGeocodes());
}
- final SearchResult search = parseMapJSON(data, tile);
- if (search == null || CollectionUtils.isEmpty(search.getGeocodes())) {
- Log.e(Settings.tag, "GCBase.searchByViewport: No cache parsed for viewport " + viewport);
- }
- searchResult.addGeocodes(search.getGeocodes());
}
- final SearchResult search = searchResult.filterSearchResults(Settings.isExcludeDisabledCaches(), Settings.isExcludeMyCaches(), Settings.getCacheType(), StoredList.TEMPORARY_LIST_ID);
- return search;
+ // we don't have enough informations about the caches to do a filtering
+ // final SearchResult search = searchResult.filterSearchResults(Settings.isExcludeDisabledCaches(), Settings.isExcludeMyCaches(), Settings.getCacheType(), StoredList.TEMPORARY_LIST_ID);
+ return searchResult;
}
/**
@@ -144,37 +147,39 @@ public class GCBase {
throw new JSONException("No data inside JSON");
}
- // attach all keys with the cache positions in the tile
- Map<String, UTFGridPosition> keyPositions = new HashMap<String, UTFGridPosition>(); // JSON key, (x/y) in grid
- for (int y = 0; y < grid.length(); y++) {
- String rowUTF8 = grid.getString(y);
- if (rowUTF8.length() != (UTFGrid.GRID_MAXX + 1)) {
- throw new JSONException("Grid has wrong size");
- }
-
- for (int x = 0; x < UTFGrid.GRID_MAXX; x++) {
- char c = rowUTF8.charAt(x);
- if (c != ' ') {
- short id = UTFGrid.getUTFGridId(c);
- keyPositions.put(keys.getString(id), new UTFGridPosition(x, y));
- }
- }
- }
-
- // Optimization:
- // the grid can get ignored. The keys are the grid position in the format x_y
+ /*
+ * // Optimization: the grid can get ignored. The keys are the grid position in the format x_y
+ *
+ * // attach all keys with the cache positions in the tile
+ * Map<String, UTFGridPosition> keyPositions = new HashMap<String, UTFGridPosition>(); // JSON key, (x/y) in
+ * grid
+ * for (int y = 0; y < grid.length(); y++) {
+ * String rowUTF8 = grid.getString(y);
+ * if (rowUTF8.length() != (UTFGrid.GRID_MAXX + 1)) {
+ * throw new JSONException("Grid has wrong size");
+ * }
+ *
+ * for (int x = 0; x < UTFGrid.GRID_MAXX; x++) {
+ * char c = rowUTF8.charAt(x);
+ * if (c != ' ') {
+ * short id = UTFGrid.getUTFGridId(c);
+ * keyPositions.put(keys.getString(id), new UTFGridPosition(x, y));
+ * }
+ * }
+ * }
+ */
// 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<UTFGridPosition>> positions = new HashMap<String, List<UTFGridPosition>>(); // JSON id as key
for (int i = 1; i < keys.length(); i++) { // index 0 is empty
String key = keys.getString(i);
if (StringUtils.isNotBlank(key)) {
+ int[] xy = splitJSONKey(key);
JSONArray dataForKey = dataObject.getJSONArray(key);
for (int j = 0; j < dataForKey.length(); j++) {
JSONObject cacheInfo = dataForKey.getJSONObject(j);
String id = cacheInfo.getString("i");
- cgCache cache = caches.get(id);
+ cgCache cache = liveMapCache.get(id);
if (cache == null) {
cache = new cgCache();
cache.setDetailed(false);
@@ -182,20 +187,21 @@ public class GCBase {
cache.setGeocode(newidToGeocode(id));
cache.setName(cacheInfo.getString("n"));
cache.setType(CacheType.GC_LIVE_MAP);
+ cache.setZoomlevel(tile.getZoomlevel());
- caches.put(id, cache);
+ liveMapCache.put(id, cache);
}
List<UTFGridPosition> listOfPositions = positions.get(id);
if (listOfPositions == null) {
listOfPositions = new ArrayList<UTFGridPosition>();
}
- UTFGridPosition pos = keyPositions.get(key);
- if (pos == null) {
- Log.e(Settings.tag, "key " + key + " not found in keyPositions");
- } else {
- listOfPositions.add(pos);
- }
+ /*
+ * Optimization
+ * UTFGridPosition pos = keyPositions.get(key);
+ */
+ UTFGridPosition pos = new UTFGridPosition(xy[0], xy[1]);
+ listOfPositions.add(pos);
positions.put(id, listOfPositions);
}
}
@@ -203,12 +209,17 @@ public class GCBase {
for (String id : positions.keySet()) {
List<UTFGridPosition> pos = positions.get(id);
- cgCache cache = caches.get(id);
- cache.setCoords(getCoordsForUTFGrid(tile, pos));
-
- Log.d(Settings.tag, "id=" + id + " geocode=" + cache.getGeocode() + " coords=" + cache.getCoords().toString());
-
- searchResult.addCache(cache);
+ cgCache cache = liveMapCache.get(id);
+ if (cache != null) {
+ // if we have "better" coords from a previous search -> reuse them
+ if (cache.getZoomlevel() < tile.getZoomlevel() ||
+ cache.getCoords() == null) {
+ cache.setCoords(getCoordsForUTFGrid(tile, pos));
+
+ // Log.d(Settings.tag, "id=" + id + " geocode=" + cache.getGeocode() + " coords=" + cache.getCoords().toString());
+ }
+ searchResult.addCache(cache);
+ }
}
Log.d(Settings.tag, "Retrieved " + searchResult.getCount() + " caches for tile " + tile.toString());
@@ -370,11 +381,21 @@ public class GCBase {
*/
}
- /** Get session token from the Live Map. Needed for following requests */
- public static String getSessionToken() {
+ /** Get user session & session token from the Live Map. Needed for following requests */
+ public static String[] getTokens() {
final HttpResponse response = cgBase.request(GCConstants.URL_LIVE_MAP, null, false);
final String data = cgBase.getResponseData(response);
- return BaseUtils.getMatch(data, GCConstants.PATTERN_SESSIONTOKEN, "");
+ String userSession = BaseUtils.getMatch(data, GCConstants.PATTERN_USERSESSION, "");
+ String sessionToken = BaseUtils.getMatch(data, GCConstants.PATTERN_SESSIONTOKEN, "");
+ return new String[] { userSession, sessionToken };
+ }
+
+ private static int[] splitJSONKey(final String key) {
+ // two possible positions for the underscore
+ int underscore = key.charAt(1) == '_' ? 1 : 2;
+ int x = Integer.parseInt(key.substring(0, underscore));
+ int y = Integer.parseInt(key.substring(underscore + 1));
+ return new int[] { x, y };
}
}