diff --git a/lib/rugreefer.dart b/lib/rugreefer.dart index 8e383b4..27e3681 100644 --- a/lib/rugreefer.dart +++ b/lib/rugreefer.dart @@ -35,26 +35,52 @@ class RugReefer { } } - Future>> lookup(double latitude, double longitude, {double distanceThreshold = 10.0}) async { - final String geohash = GeoHasher().encode(latitude, longitude, precision: 4); + Future>>> lookup(double latitude, double longitude, {double distanceThreshold = 10.0}) async { + final String geohash = GeoHasher().encode(longitude, latitude, precision: 4); + print("Generated geohash: $geohash"); + final jsonMap = await loadJsonFromAssets(categoryMap); + print("Loaded JSON Map from Assets"); - List> rawData = kIsWeb - ? await _lookupWeb(geohash, latitude, longitude, distanceThreshold) - : await _lookupFile(geohash, latitude, longitude, distanceThreshold); + try { + List> rawData = kIsWeb + ? await _lookupWeb(geohash, latitude, longitude, distanceThreshold) + : await _lookupFile(geohash, latitude, longitude, distanceThreshold); - return _processMetadata(rawData, jsonMap, latitude, longitude, distanceThreshold); + print("Raw Data from lookup: ${jsonEncode(rawData)}"); + + final processedData = _processMetadata(rawData, jsonMap, latitude, longitude, distanceThreshold); + print("Processed Data: ${jsonEncode(processedData)}"); + + return processedData; + } catch (e, stackTrace) { + print("Error in lookup: $e"); + print("StackTrace: $stackTrace"); + return {}; + } } + Future>> _lookupFile(String geohash, double latitude, double longitude, double distanceThreshold) async { + await _initCacheDir(); final File cacheFile = File('${cacheDir?.path}/$geohash.geojson.gz'); + + print("Checking cache file: ${cacheFile.path}"); + if (!cacheFile.existsSync() || await _isCacheExpired(geohash)) { + print("Cache file missing or expired, downloading..."); await _downloadGeoJson(geohash, cacheFile); } else { + print("Cache file found, updating last access time"); await _updateLastAccessTime(geohash); } + final String geoJsonStr = utf8.decode(GZipCodec().decode(cacheFile.readAsBytesSync())); - return jsonDecode(geoJsonStr)['features']; + print("Read from cache: ${geoJsonStr.length} characters"); + + // ✅ Explicitly cast to List> + final List decodedJson = jsonDecode(geoJsonStr)['features']; + return decodedJson.cast>(); } Future>> _lookupWeb(String geohash, double latitude, double longitude, double distanceThreshold) async { @@ -114,22 +140,29 @@ class RugReefer { return jsonDecode(jsonString); } - List> _processMetadata(List> features, Map jsonMap, double latitude, double longitude, double distanceThreshold) { + Map>> _processMetadata( + List> features, + Map jsonMap, + double latitude, + double longitude, + double distanceThreshold) { + final Position point = Position(longitude, latitude); - Map>> groupedObjects = {}; + Map>> groupedObjects = {"in": {}, "by": {}}; for (var feature in features) { final geometry = feature['geometry']; final metadata = Map.from(feature['properties']['tags'] ?? {})..removeWhere((_, v) => v == null); String? mainKey; + // Determine spatial category: "in" (Polygon) or "by" (LineString) switch (geometry['type']) { case 'Polygon': final polygon = Polygon( coordinates: (geometry['coordinates'] as List) .map((ring) => (ring as List) - .map((p) => Position(p[0].toDouble(), p[1].toDouble())) - .toList()) + .map((p) => Position(p[0].toDouble(), p[1].toDouble())) + .toList()) .toList(), ); if (booleanPointInPolygon(point, polygon)) mainKey = 'in'; @@ -143,25 +176,38 @@ class RugReefer { if (_isPointNearLine(Point(coordinates: point), line, distanceThreshold)) mainKey = 'by'; break; } + if (mainKey == null) continue; - groupedObjects.putIfAbsent(mainKey, () => {}); for (var key in metadata.keys) { + var value = metadata[key]; + for (var category in jsonMap.keys) { var categoryMap = jsonMap[category]; + if (categoryMap is Map && categoryMap.containsKey(key)) { var rule = categoryMap[key]; - if (rule is String || (rule is List && rule.contains(metadata[key])) || rule == true) { + + if (rule is String && rule == value) { groupedObjects[mainKey]!.putIfAbsent(category, () => []); - groupedObjects[mainKey]![category]!.add(metadata[key]); + groupedObjects[mainKey]![category]!.add(value); + } else if (rule is List && rule.contains(value)) { + groupedObjects[mainKey]!.putIfAbsent(category, () => []); + groupedObjects[mainKey]![category]!.add(value); + } else if (rule == true) { + groupedObjects[mainKey]!.putIfAbsent(category, () => []); + groupedObjects[mainKey]![category]!.add(value); } } } } } - return groupedObjects.entries.map((entry) => {entry.key: entry.value}).toList(); + + return groupedObjects; } + + bool _isPointNearLine(Point point, LineString line, double distanceThreshold) { for (final Position p in line.coordinates) { if (distance(point, Point(coordinates: p), Unit.meters) <= distanceThreshold) {