aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main/res/values/strings.xml1
-rw-r--r--main/src/cgeo/geocaching/GCConstants.java1
-rw-r--r--main/src/cgeo/geocaching/cgCache.java9
-rw-r--r--main/src/cgeo/geocaching/cgeopopup.java2
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCBase.java143
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Tile.java40
-rw-r--r--main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java14
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheType.java2
-rw-r--r--main/src/cgeo/geocaching/maps/CGeoMap.java10
-rw-r--r--tests/src/cgeo/geocaching/GCConstantsTest.java7
-rw-r--r--tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java (renamed from tests/src/cgeo/geocaching/connector/GCConnectorTest.java)29
11 files changed, 163 insertions, 95 deletions
diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml
index d5951de..2e29c06 100644
--- a/main/res/values/strings.xml
+++ b/main/res/values/strings.xml
@@ -35,6 +35,7 @@
<string name="ape">Project APE Cache</string>
<string name="gchq">Groundspeak HQ</string>
<string name="gps">GPS Adventures Exhibit</string>
+ <string name="gc_live_map">Live Map</string>
<string name="unknown">Unknown Type</string>
<!-- cache sizes -->
diff --git a/main/src/cgeo/geocaching/GCConstants.java b/main/src/cgeo/geocaching/GCConstants.java
index c28cfcb..7134e24 100644
--- a/main/src/cgeo/geocaching/GCConstants.java
+++ b/main/src/cgeo/geocaching/GCConstants.java
@@ -139,5 +139,6 @@ public final class GCConstants {
public final static Pattern PATTERN_USERTOKEN2 = Pattern.compile("userToken\\s*=\\s*'([^']+)'");
/** Live Map since 14.02.2012 */
+ public final static Pattern PATTERN_USERSESSION = Pattern.compile("UserSession\\('([^']+)'");
public final static Pattern PATTERN_SESSIONTOKEN = Pattern.compile("sessionToken:'([^']+)'");
}
diff --git a/main/src/cgeo/geocaching/cgCache.java b/main/src/cgeo/geocaching/cgCache.java
index 72e12a5..de3680e 100644
--- a/main/src/cgeo/geocaching/cgCache.java
+++ b/main/src/cgeo/geocaching/cgCache.java
@@ -98,6 +98,7 @@ public class cgCache implements ICache {
private String nameForSorting;
private final EnumSet<StorageLocation> storageLocation = EnumSet.of(StorageLocation.HEAP);
private boolean finalDefined = false;
+ private int zoomlevel = -1;
private static final Pattern NUMBER_PATTERN = Pattern.compile("\\d+");
@@ -1314,4 +1315,12 @@ public class cgCache implements ICache {
final int listId = Math.max(getListId(), StoredList.STANDARD_LIST_ID);
cgBase.storeCache(activity, this, null, listId, handler);
}
+
+ public int getZoomlevel() {
+ return this.zoomlevel;
+ }
+
+ public void setZoomlevel(int zoomlevel) {
+ this.zoomlevel = zoomlevel;
+ }
}
diff --git a/main/src/cgeo/geocaching/cgeopopup.java b/main/src/cgeo/geocaching/cgeopopup.java
index e7bf143..0d6195d 100644
--- a/main/src/cgeo/geocaching/cgeopopup.java
+++ b/main/src/cgeo/geocaching/cgeopopup.java
@@ -376,7 +376,7 @@ public class cgeopopup extends AbstractActivity {
final boolean moreDetails = cache.isDetailed();
// more details
- if (moreDetails) {
+ if (moreDetails || cache.getType() == CacheType.GC_LIVE_MAP) {
((LinearLayout) findViewById(R.id.more_details_box)).setVisibility(View.VISIBLE);
Button buttonMore = (Button) findViewById(R.id.more_details);
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 };
}
}
diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java
index 003ff37..e62debb 100644
--- a/main/src/cgeo/geocaching/connector/gc/Tile.java
+++ b/main/src/cgeo/geocaching/connector/gc/Tile.java
@@ -13,30 +13,45 @@ import cgeo.geocaching.geopoint.Geopoint;
*/
public class Tile {
+ public static final double LATITUDE_MIN = -85.05112878;
+ public static final double LATITUDE_MAX = 85.05112878;
+ public static final double LONGITUDE_MIN = -180;
+ public static final double LONGITUDE_MAX = 180;
+
public static final int TILE_SIZE = 256;
public static final int ZOOMLEVEL_MAX = 18;
public static final int ZOOMLEVEL_MIN = 0;
+ public static final int[] NUMBER_OF_TILES = new int[ZOOMLEVEL_MAX - ZOOMLEVEL_MIN + 1];
+ public static final int[] NUMBER_OF_PIXELS = new int[ZOOMLEVEL_MAX - ZOOMLEVEL_MIN + 1];
+ static {
+ for (int z = ZOOMLEVEL_MIN; z <= ZOOMLEVEL_MAX; z++) {
+ NUMBER_OF_TILES[z] = 1 << z;
+ NUMBER_OF_PIXELS[z] = TILE_SIZE * 1 << z;
+ }
+ }
+
private final int tileX;
private final int tileY;
private final int zoomlevel;
- private final int numberOfTiles;
public Tile(Geopoint origin, int zoomlevel) {
+ assert zoomlevel >= ZOOMLEVEL_MIN && zoomlevel <= ZOOMLEVEL_MAX : "zoomlevel out of range";
+
this.zoomlevel = zoomlevel;
- numberOfTiles = 1 << zoomlevel;
tileX = calcX(origin);
tileY = calcY(origin);
}
public Tile(int tileX, int tileY, int zoomlevel) {
+ assert zoomlevel >= ZOOMLEVEL_MIN && zoomlevel <= ZOOMLEVEL_MAX : "zoomlevel out of range";
+
this.zoomlevel = zoomlevel;
- numberOfTiles = 1 << zoomlevel;
this.tileX = tileX;
this.tileY = tileY;
}
- public long getZoomlevel() {
+ public int getZoomlevel() {
return zoomlevel;
}
@@ -46,7 +61,7 @@ public class Tile {
* @see http://developers.cloudmade.com/projects/tiles/examples/convert-coordinates-to-tile-numbers
*/
private int calcX(final Geopoint origin) {
- return (int) ((origin.getLongitude() + 180.0) / 360.0 * numberOfTiles);
+ return (int) ((origin.getLongitude() + 180.0) / 360.0 * NUMBER_OF_TILES[this.zoomlevel]);
}
public int getX() {
@@ -63,9 +78,13 @@ public class Tile {
* @see http://developers.cloudmade.com/projects/tiles/examples/convert-coordinates-to-tile-numbers
*/
private int calcY(final Geopoint origin) {
- double lat_rad = Math.toRadians(origin.getLatitude());
- return (int) ((1 - (Math.log(Math.tan(lat_rad) + (1 / Math.cos(lat_rad))) / Math.PI)) / 2 * numberOfTiles);
+ // double latRad = Math.toRadians(origin.getLatitude());
+ // return (int) ((1 - (Math.log(Math.tan(latRad) + (1 / Math.cos(latRad))) / Math.PI)) / 2 * numberOfTiles);
+
+ // Optimization from Bing
+ double sinLatRad = Math.sin(Math.toRadians(origin.getLatitude()));
+ return (int) ((0.5 - Math.log((1 + sinLatRad) / (1 - sinLatRad)) / (4 * Math.PI)) * NUMBER_OF_TILES[this.zoomlevel]);
}
/**
@@ -77,11 +96,10 @@ public class Tile {
double pixX = tileX * TILE_SIZE + pos.x * 4;
double pixY = tileY * TILE_SIZE + pos.y * 4;
- long numberOfPixels = TILE_SIZE * numberOfTiles;
- double lon = ((360.0 * pixX) / numberOfPixels) - 180.0;
- double latRad = Math.atan(Math.sinh(Math.PI * (1 - 2 * pixY / numberOfPixels)));
- return new Geopoint(latRad * Geopoint.rad2deg, lon);
+ double lonDeg = ((360.0 * pixX) / NUMBER_OF_PIXELS[this.zoomlevel]) - 180.0;
+ double latRad = Math.atan(Math.sinh(Math.PI * (1 - 2 * pixY / NUMBER_OF_PIXELS[this.zoomlevel])));
+ return new Geopoint(Math.toDegrees(latRad), lonDeg);
}
@Override
diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java
index 9d875c5..9121dad 100644
--- a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java
+++ b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java
@@ -1,8 +1,5 @@
package cgeo.geocaching.connector.gc;
-import cgeo.geocaching.Settings;
-
-import android.util.Log;
/**
* Representation of a position inside an UTFGrid
@@ -16,14 +13,9 @@ public final class UTFGridPosition {
public final int y;
UTFGridPosition(final int x, final int y) {
- if (x > UTFGrid.GRID_MAXX) {
- Log.e(Settings.tag, "x outside grid");
- throw new IllegalArgumentException("x outside grid");
- }
- if (y > UTFGrid.GRID_MAXY) {
- Log.e(Settings.tag, "y outside grid");
- throw new IllegalArgumentException("y outside grid");
- }
+ assert x >= 0 && x <= UTFGrid.GRID_MAXX : "x outside bounds";
+ assert y >= 0 && y <= UTFGrid.GRID_MAXY : "y outside bounds";
+
this.x = x;
this.y = y;
}
diff --git a/main/src/cgeo/geocaching/enumerations/CacheType.java b/main/src/cgeo/geocaching/enumerations/CacheType.java
index ea89135..dc4f696 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheType.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheType.java
@@ -30,7 +30,7 @@ public enum CacheType {
GCHQ("gchq", "groundspeak hq", "416f2494-dc17-4b6a-9bab-1a29dd292d8c", R.string.gchq, R.drawable.type_hq),
GPS_EXHIBIT("gps", "gps cache exhibit", "72e69af2-7986-4990-afd9-bc16cbbb4ce3", R.string.gps, R.drawable.type_traditional), // icon missing
// GC Live Map
- GC_LIVE_MAP("live map", "live map", "", R.string.unknown, R.drawable.type_unknown),
+ GC_LIVE_MAP("live map", "live map", "", R.string.gc_live_map, R.drawable.type_unknown),
UNKNOWN("unknown", "unknown", "", R.string.unknown, R.drawable.type_mystery), // icon missing
/** No real cache type -> filter */
ALL("all", "display all caches", "9a79e6ce-3344-409c-bbe9-496530baf758", R.string.all_types, R.drawable.type_mystery);
diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java
index 8221e61..97f5de3 100644
--- a/main/src/cgeo/geocaching/maps/CGeoMap.java
+++ b/main/src/cgeo/geocaching/maps/CGeoMap.java
@@ -114,7 +114,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private int[] mapStateIntent = null;
// status data
private SearchResult search = null;
- private String token = null;
+ private String[] tokens = null;
private boolean noMapTokenShowed = false;
// map status data
private boolean followMyLocation = false;
@@ -1265,9 +1265,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
throw new ThreadDeath();
}
- if (token == null) {
+ if (tokens == null) {
// token = cgBase.getMapUserToken(noMapTokenHandler);
- token = GCBase.getSessionToken();
+ tokens = GCBase.getTokens();
}
if (stop) {
@@ -1276,12 +1276,12 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final Viewport viewport = new Viewport(new Geopoint(latMin, lonMin), new Geopoint(latMax, lonMax));
// search = cgBase.searchByViewport(token, viewport);
- search = GCBase.searchByViewport(viewport, 14, true, token);
+ search = GCBase.searchByViewport(viewport, 14, true, tokens);
if (search != null) {
downloaded = true;
if (search.error == StatusCode.NOT_LOGGED_IN) {
cgBase.login();
- token = null;
+ tokens = null;
} else {
break;
}
diff --git a/tests/src/cgeo/geocaching/GCConstantsTest.java b/tests/src/cgeo/geocaching/GCConstantsTest.java
index 41b7dcb..a05abd9 100644
--- a/tests/src/cgeo/geocaching/GCConstantsTest.java
+++ b/tests/src/cgeo/geocaching/GCConstantsTest.java
@@ -6,6 +6,7 @@ import cgeo.geocaching.utils.BaseUtils;
import android.test.AndroidTestCase;
public class GCConstantsTest extends AndroidTestCase {
+
public static void testLocation() {
// GC37GFJ
assertEquals("Bretagne, France", parseLocation(" <span id=\"ctl00_ContentBody_Location\">In Bretagne, France</span><br />"));
@@ -28,4 +29,10 @@ public class GCConstantsTest extends AndroidTestCase {
private static void assertCacheCount(final int count, final String html) {
assertEquals(count, Integer.parseInt(BaseUtils.getMatch(html, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll(",", "")));
}
+
+ public static void testConstants() {
+ String session = "userSession = new Groundspeak.Map.UserSession('aKWZ', userOptions:'XPTf', sessionToken:'123pNKwdktYGZL0xd-I7yqA6nm_JE1BDUtM4KcOkifin2TRCMutBd_PZE14Ohpffs2ZgkTnxTSnxYpBigK4hBA2', subscriberType: 3, enablePersonalization: true });";
+ assertEquals("aKWZ", BaseUtils.getMatch(session, GCConstants.PATTERN_USERSESSION, ""));
+ assertTrue(BaseUtils.getMatch(session, GCConstants.PATTERN_USERSESSION, "").startsWith("123pNK"));
+ }
}
diff --git a/tests/src/cgeo/geocaching/connector/GCConnectorTest.java b/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java
index f012214..014c578 100644
--- a/tests/src/cgeo/geocaching/connector/GCConnectorTest.java
+++ b/tests/src/cgeo/geocaching/connector/gc/GCConnectorTest.java
@@ -15,11 +15,11 @@ public class GCConnectorTest extends AndroidTestCase {
public static void testGetViewport() {
cgBase.login();
- String sessionToken = GCBase.getSessionToken();
+ String[] tokens = GCBase.getTokens();
{
final Viewport viewport = new Viewport(new Geopoint("N 52° 25.369 E 9° 35.499"), new Geopoint("N 52° 25.371 E 9° 35.501"));
- SearchResult searchResult = GCBase.searchByViewport(viewport, 14, false, sessionToken);
+ SearchResult searchResult = GCBase.searchByViewport(viewport, 14, false, tokens);
assertTrue(searchResult != null);
assertEquals(7, searchResult.getCount());
assertTrue(searchResult.getGeocodes().contains("GC211WG"));
@@ -33,7 +33,7 @@ public class GCConnectorTest extends AndroidTestCase {
{
final Viewport viewport = new Viewport(new Geopoint("N 52° 24.000 E 9° 34.500"), new Geopoint("N 52° 26.000 E 9° 38.500"));
- SearchResult searchResult = GCBase.searchByViewport(viewport, 14, false, sessionToken);
+ SearchResult searchResult = GCBase.searchByViewport(viewport, 14, false, tokens);
assertTrue(searchResult != null);
assertTrue(searchResult.getGeocodes().contains("GC211WG"));
}
@@ -48,6 +48,7 @@ public class GCConnectorTest extends AndroidTestCase {
assertEquals("GC211WG", GCBase.newidToGeocode("gEaR"));
}
+ /** Tile computation with different zoom levels */
public static void testTile() {
{
// http://coord.info/GC2CT8K = N 52° 30.462 E 013° 27.906
@@ -55,16 +56,34 @@ public class GCConnectorTest extends AndroidTestCase {
assertEquals(8804, tile.getX());
assertEquals(5374, tile.getY());
}
-
{
// (8633, 5381); N 52° 24,516 E 009° 42,592
Tile tile = new Tile(new Geopoint("N 52° 24,516 E 009° 42,592"), 14);
assertEquals(8633, tile.getX());
assertEquals(5381, tile.getY());
}
+ {
+ // Hannover, GC22VTB UKM Memorial Tour
+ Tile tile = new Tile(new Geopoint("N 52° 22.177 E 009° 45.385"), 12);
+ assertEquals(2159, tile.getX());
+ assertEquals(1346, tile.getY());
+ }
+ {
+ // Seatle, GCK25B Groundspeak Headquarters
+ Tile tile = new Tile(new Geopoint("N 47° 38.000 W 122° 20.000"), 15);
+ assertEquals(5248, tile.getX());
+ assertEquals(11440, tile.getY());
+ }
+ {
+ // Sydney, GCXT2R Victoria Cross
+ Tile tile = new Tile(new Geopoint("S 33° 50.326 E 151° 12.426"), 13);
+ assertEquals(7536, tile.getX());
+ assertEquals(4915, tile.getY());
+ }
- // TODO Valentine zoomlevel != 14, Seatle, Rio, Sydney
+ // TODO ebenfalls nutzen in searchByViewport und KOs vergleichen
}
+
}