diff options
Diffstat (limited to 'android-app/app/src/main')
| -rw-r--r-- | android-app/app/src/main/kotlin/org/terst/nav/ui/aton/AtonData.kt | 37 | ||||
| -rw-r--r-- | android-app/app/src/main/kotlin/org/terst/nav/ui/aton/AtonRepository.kt | 35 |
2 files changed, 72 insertions, 0 deletions
diff --git a/android-app/app/src/main/kotlin/org/terst/nav/ui/aton/AtonData.kt b/android-app/app/src/main/kotlin/org/terst/nav/ui/aton/AtonData.kt new file mode 100644 index 0000000..2ff59cd --- /dev/null +++ b/android-app/app/src/main/kotlin/org/terst/nav/ui/aton/AtonData.kt @@ -0,0 +1,37 @@ +package org.terst.nav.ui.aton + +import com.google.gson.JsonObject +import com.google.gson.JsonParser +import org.maplibre.geojson.Feature +import org.maplibre.geojson.Point + +object AtonData { + fun colorFor(type: String): String = when (type) { + "Light" -> "#FF0000" + "Float", "Buoy" -> "#00AA00" + "Daybeacon", "Range" -> "#FFDD00" + else -> "#FFFFFF" + } + + fun parseStation(json: String): Feature? = try { + val obj = JsonParser.parseString(json).asJsonObject + val lat = obj.get("lat").asDouble + val lng = obj.get("lng").asDouble + val type = obj.get("type")?.asString ?: "" + val id = obj.get("id")?.asString ?: "" + val name = obj.get("name")?.asString ?: "" + val props = JsonObject().apply { + addProperty("id", id) + addProperty("name", name) + addProperty("type", type) + addProperty("color", colorFor(type)) + } + Feature.fromGeometry(Point.fromLngLat(lng, lat), props) + } catch (_: Exception) { null } + + fun parseResponse(json: String): List<Feature> = try { + val arr = JsonParser.parseString(json).asJsonObject + .getAsJsonArray("stations") + arr.mapNotNull { parseStation(it.toString()) } + } catch (_: Exception) { emptyList() } +} diff --git a/android-app/app/src/main/kotlin/org/terst/nav/ui/aton/AtonRepository.kt b/android-app/app/src/main/kotlin/org/terst/nav/ui/aton/AtonRepository.kt new file mode 100644 index 0000000..b5472b3 --- /dev/null +++ b/android-app/app/src/main/kotlin/org/terst/nav/ui/aton/AtonRepository.kt @@ -0,0 +1,35 @@ +package org.terst.nav.ui.aton + +import android.content.Context +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.maplibre.geojson.Feature +import java.io.File +import java.net.URL + +class AtonRepository(private val context: Context) { + + private val cacheFile = File(context.filesDir, "aton_cache.json") + private val maxAgeMs = 24 * 60 * 60 * 1000L + + private val apiUrl = + "https://api.tidesandcurrents.noaa.gov/mdapi/prod/webapi/stations.json?type=aton&units=english" + + suspend fun getFeatures(): List<Feature> = withContext(Dispatchers.IO) { + val cached = readCache() + if (cached != null) return@withContext AtonData.parseResponse(cached) + val fresh = fetchFromApi() ?: return@withContext emptyList() + cacheFile.writeText(fresh) + AtonData.parseResponse(fresh) + } + + private fun readCache(): String? { + if (!cacheFile.exists()) return null + if (System.currentTimeMillis() - cacheFile.lastModified() > maxAgeMs) return null + return cacheFile.readText() + } + + private fun fetchFromApi(): String? = try { + URL(apiUrl).openStream().bufferedReader().readText() + } catch (_: Exception) { null } +} |
