summaryrefslogtreecommitdiff
path: root/android-app/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'android-app/app/src/main')
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/ui/aton/AtonData.kt37
-rw-r--r--android-app/app/src/main/kotlin/org/terst/nav/ui/aton/AtonRepository.kt35
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 }
+}