Bimba.git

commit 61a0f8900f36204fc1f8f173fdde875181a2a251

Author: Adam <git@apiote.xyz>

Enums in Vehicle and Alert

 app/src/main/java/xyz/apiote/bimba/czwek/Bimba.kt | 6 
 app/src/main/java/xyz/apiote/bimba/czwek/api/Structs.kt | 119 ++++++-
 app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt | 55 +++
 app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt | 121 +++++--


diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/Bimba.kt b/app/src/main/java/xyz/apiote/bimba/czwek/Bimba.kt
index dfa1fb1659a435ec02e450071088b1b5b8233f97..f32fbfbb49ce718e677036fbd07d223fb01f1f35 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/Bimba.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/Bimba.kt
@@ -3,12 +3,6 @@
 import org.osmdroid.config.Configuration
 import java.io.File
 
-/* todo
- api.AlertV1 enums (Structs.kt)
- repo.Alert enums (Departure.kt)
- ErrorResponseError
- repo.Vehicle enums (Vehicle.kt)
-*/
 class Bimba : android.app.Application() {
 	override fun onCreate() {
 		super.onCreate()




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/Structs.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/Structs.kt
index ad2f2ca2147befaa516f905eb052878bfa4293e7..2761f6ac89092ffcc5218e8b2efcabfe2f249297 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/api/Structs.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/Structs.kt
@@ -135,22 +135,72 @@ 		)
 	}
 }
 
+enum class AlertCauseV1 {
+	UNKNOWN, OTHER, TECHNICAL_PROBLEM, STRIKE, DEMONSTRATION, ACCIDENT, HOLIDAY, WEATHER, MAINTENANCE,
+	CONSTRUCTION, POLICE_ACTIVITY, MEDICAL_EMERGENCY;
+
+	companion object {
+		fun of(type: UInt): AlertCauseV1 {
+			return when (type) {
+				0u -> valueOf("UNKNOWN")
+				1u -> valueOf("OTHER")
+				2u -> valueOf("TECHNICAL_PROBLEM")
+				3u -> valueOf("STRIKE")
+				4u -> valueOf("DEMONSTRATION")
+				5u -> valueOf("ACCIDENT")
+				6u -> valueOf("HOLIDAY")
+				7u -> valueOf("WEATHER")
+				8u -> valueOf("MAINTENANCE")
+				9u -> valueOf("CONSTRUCTION")
+				10u -> valueOf("POLICE_ACTIVITY")
+				11u -> valueOf("MEDICAL_EMERGENCY")
+				else -> throw UnknownResourceVersionException("AlertCause/$type", 1u)
+			}
+		}
+	}
+}
+
+enum class AlertEffectV1 {
+	UNKNOWN, OTHER, NO_SERVICE, REDUCED_SERVICE, SIGNIFICANT_DELAYS, DETOUR, ADDITIONAL_SERVICE,
+	MODIFIED_SERVICE, STOP_MOVED, NONE, ACCESSIBILITY_ISSUE;
+
+	companion object {
+		fun of(type: UInt): AlertEffectV1 {
+			return when (type) {
+				0u -> valueOf("UNKNOWN")
+				1u -> valueOf("OTHER")
+				2u -> valueOf("NO_SERVICE")
+				3u -> valueOf("REDUCED_SERVICE")
+				4u -> valueOf("SIGNIFICANT_DELAYS")
+				5u -> valueOf("DETOUR")
+				6u -> valueOf("ADDITIONAL_SERVICE")
+				7u -> valueOf("MODIFIED_SERVICE")
+				8u -> valueOf("STOP_MOVED")
+				9u -> valueOf("NONE")
+				10u -> valueOf("ACCESSIBILITY_ISSUE")
+				else -> throw UnknownResourceVersionException("AlertEffect/$type", 1u)
+			}
+		}
+	}
+}
+
 data class AlertV1(
 	val header: String,
 	val Description: String,
 	val Url: String,
-	val Cause: ULong,  // todo [3.1] enum
-	val Effect: ULong  // todo [3.1] enum
+	val Cause: AlertCauseV1,
+	val Effect: AlertEffectV1
 ) {
 	companion object {
 		fun unmarshal(stream: InputStream): AlertV1 {
 			val reader = Reader(stream)
-			val header = reader.readString()
-			val description = reader.readString()
-			val url = reader.readString()
-			val cause = reader.readUInt().toULong()
-			val effect = reader.readUInt().toULong()
-			return AlertV1(header, description, url, cause, effect)
+			return AlertV1(
+				reader.readString(),
+				reader.readString(),
+				reader.readString(),
+				AlertCauseV1.of(reader.readUInt().toULong().toUInt()),
+				AlertEffectV1.of(reader.readUInt().toULong().toUInt())
+			)
 		}
 	}
 }
@@ -183,6 +233,43 @@ 		}
 	}
 }
 
+enum class CongestionLevelV1 {
+	UNKNOWN, SMOOTH, STOP_AND_GO, SIGNIFICANT, SEVERE;
+
+	companion object {
+		fun of(type: UInt): CongestionLevelV1 {
+			return when (type) {
+				0u -> valueOf("UNKNOWN")
+				1u -> valueOf("SMOOTH")
+				2u -> valueOf("STOP_AND_GO")
+				3u -> valueOf("SIGNIFICANT")
+				4u -> valueOf("SEVERE")
+				else -> throw UnknownResourceVersionException("CongestionLevel/$type", 1u)
+			}
+		}
+	}
+}
+
+enum class OccupancyStatusV1 {
+	UNKNOWN, EMPTY, MANY_AVAILABLE, FEW_AVAILABLE, STANDING_ONLY, CRUSHED, FULL, NOT_ACCEPTING;
+
+	companion object {
+		fun of(type: UInt): OccupancyStatusV1 {
+			return when (type) {
+				0u -> valueOf("UNKNOWN")
+				1u -> valueOf("EMPTY")
+				2u -> valueOf("MANY_AVAILABLE")
+				3u -> valueOf("FEW_AVAILABLE")
+				4u -> valueOf("STANDING_ONLY")
+				5u -> valueOf("CRUSHED")
+				6u -> valueOf("FULL")
+				7u -> valueOf("NOT_ACCEPTING")
+				else -> throw UnknownResourceVersionException("OccupancyStatus/$type", 1u)
+			}
+		}
+	}
+}
+
 data class VehicleV1(
 	val ID: String,
 	val Position: PositionV1,
@@ -190,8 +277,8 @@ 	val Capabilities: UShort,
 	val Speed: Float,
 	val Line: LineStubV1,
 	val Headsign: String,
-	val CongestionLevel: ULong,
-	val OccupancyStatus: ULong
+	val CongestionLevel: CongestionLevelV1,
+	val OccupancyStatus: OccupancyStatusV1
 ) : LocatableV1 {
 	companion object {
 		fun unmarshal(stream: InputStream): VehicleV1 {
@@ -203,8 +290,8 @@ 				reader.readU16(),
 				reader.readFloat32(),
 				LineStubV1.unmarshal(stream),
 				reader.readString(),
-				reader.readUInt().toULong(),
-				reader.readUInt().toULong()
+				CongestionLevelV1.of(reader.readUInt().toULong().toUInt()),
+				OccupancyStatusV1.of(reader.readUInt().toULong().toUInt())
 			)
 		}
 	}
@@ -217,8 +304,8 @@ 	val Capabilities: UShort,
 	val Speed: Float,
 	val Line: LineStubV2,
 	val Headsign: String,
-	val CongestionLevel: ULong,
-	val OccupancyStatus: ULong
+	val CongestionLevel: CongestionLevelV1,
+	val OccupancyStatus: OccupancyStatusV1
 ) : LocatableV2 {
 	companion object {
 		fun unmarshal(stream: InputStream): VehicleV2 {
@@ -230,8 +317,8 @@ 				reader.readU16(),
 				reader.readFloat32(),
 				LineStubV2.unmarshal(stream),
 				reader.readString(),
-				reader.readUInt().toULong(),
-				reader.readUInt().toULong()
+				CongestionLevelV1.of(reader.readUInt().toULong().toUInt()),
+				OccupancyStatusV1.of(reader.readUInt().toULong().toUInt())
 			)
 		}
 	}




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt
index d3259e6e5df6c5c5e0755f12ca47d48ede9e0c18..92cee3af3c4ee80616516019a22c6818e07d17b9 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt
@@ -3,6 +3,8 @@
 import android.content.Context
 import android.text.format.DateUtils
 import xyz.apiote.bimba.czwek.R
+import xyz.apiote.bimba.czwek.api.AlertCauseV1
+import xyz.apiote.bimba.czwek.api.AlertEffectV1
 import xyz.apiote.bimba.czwek.api.AlertV1
 import xyz.apiote.bimba.czwek.api.DepartureV1
 import xyz.apiote.bimba.czwek.api.DepartureV2
@@ -13,14 +15,61 @@ import java.time.ZoneId
 import java.time.ZonedDateTime
 import java.time.temporal.ChronoUnit
 
+enum class AlertCause {
+	UNKNOWN, OTHER, TECHNICAL_PROBLEM, STRIKE, DEMONSTRATION, ACCIDENT, HOLIDAY, WEATHER, MAINTENANCE,
+	CONSTRUCTION, POLICE_ACTIVITY, MEDICAL_EMERGENCY;
+
+	companion object {
+		fun of(type: AlertCauseV1): AlertCause {
+			return when (type) {
+				AlertCauseV1.UNKNOWN -> valueOf("UNKNOWN")
+				AlertCauseV1.OTHER -> valueOf("OTHER")
+				AlertCauseV1.TECHNICAL_PROBLEM -> valueOf("TECHNICAL_PROBLEM")
+				AlertCauseV1.STRIKE -> valueOf("STRIKE")
+				AlertCauseV1.DEMONSTRATION -> valueOf("DEMONSTRATION")
+				AlertCauseV1.ACCIDENT -> valueOf("ACCIDENT")
+				AlertCauseV1.HOLIDAY -> valueOf("HOLIDAY")
+				AlertCauseV1.WEATHER -> valueOf("WEATHER")
+				AlertCauseV1.MAINTENANCE -> valueOf("MAINTENANCE")
+				AlertCauseV1.CONSTRUCTION -> valueOf("CONSTRUCTION")
+				AlertCauseV1.POLICE_ACTIVITY -> valueOf("POLICE_ACTIVITY")
+				AlertCauseV1.MEDICAL_EMERGENCY -> valueOf("MEDICAL_EMERGENCY")
+			}
+		}
+	}
+}
+
+enum class AlertEffect {
+	UNKNOWN, OTHER, NO_SERVICE, REDUCED_SERVICE, SIGNIFICANT_DELAYS, DETOUR, ADDITIONAL_SERVICE,
+	MODIFIED_SERVICE, STOP_MOVED, NONE, ACCESSIBILITY_ISSUE;
+
+	companion object {
+		fun of(type: AlertEffectV1): AlertEffect {
+			return when (type) {
+				AlertEffectV1.UNKNOWN -> valueOf("UNKNOWN")
+				AlertEffectV1.OTHER -> valueOf("OTHER")
+				AlertEffectV1.NO_SERVICE -> valueOf("NO_SERVICE")
+				AlertEffectV1.REDUCED_SERVICE -> valueOf("REDUCED_SERVICE")
+				AlertEffectV1.SIGNIFICANT_DELAYS -> valueOf("SIGNIFICANT_DELAYS")
+				AlertEffectV1.DETOUR -> valueOf("DETOUR")
+				AlertEffectV1.ADDITIONAL_SERVICE -> valueOf("ADDITIONAL_SERVICE")
+				AlertEffectV1.MODIFIED_SERVICE -> valueOf("MODIFIED_SERVICE")
+				AlertEffectV1.STOP_MOVED  -> valueOf("STOP_MOVED")
+				AlertEffectV1.NONE -> valueOf("NONE")
+				AlertEffectV1.ACCESSIBILITY_ISSUE -> valueOf("ACCESSIBILITY_ISSUE")
+			}
+		}
+	}
+}
+
 data class Alert(
 	val header: String,
 	val description: String,
 	val url: String,
-	val cause: ULong,  // todo [3.1] enum
-	val effect: ULong  // todo [3.1] enum
+	val cause: AlertCause,
+	val effect: AlertEffect
 ) {
-	constructor(a: AlertV1) : this(a.header, a.Description, a.Url, a.Cause, a.Effect)
+	constructor(a: AlertV1) : this(a.header, a.Description, a.Url, AlertCause.of(a.Cause), AlertEffect.of(a.Effect))
 }
 
 data class StopDepartures(




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt
index 4e7e795de8c92c2fdc69f1d3b01bbd391433ae37..509e4819d6b6826c07323c71425f0f1928549319 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt
@@ -1,11 +1,68 @@
 package xyz.apiote.bimba.czwek.repo
 
 import android.content.Context
-import android.graphics.drawable.Drawable
 import xyz.apiote.bimba.czwek.R
-import xyz.apiote.bimba.czwek.api.UnknownResourceVersion
+import xyz.apiote.bimba.czwek.api.CongestionLevelV1
+import xyz.apiote.bimba.czwek.api.OccupancyStatusV1
 import xyz.apiote.bimba.czwek.api.VehicleV1
 import xyz.apiote.bimba.czwek.api.VehicleV2
+
+enum class CongestionLevel {
+	UNKNOWN, SMOOTH, STOP_AND_GO, SIGNIFICANT, SEVERE;
+
+	fun toString(context: Context): String {
+		return when (this) {
+			UNKNOWN -> context.getString(R.string.congestion_unknown)
+			SMOOTH -> context.getString(R.string.congestion_smooth)
+			STOP_AND_GO -> context.getString(R.string.congestion_stop_and_go)
+			SIGNIFICANT -> context.getString(R.string.congestion_congestion)
+			SEVERE -> context.getString(R.string.congestion_jams)
+		}
+	}
+
+	companion object {
+		fun of(type: CongestionLevelV1): CongestionLevel {
+			return when (type) {
+				CongestionLevelV1.UNKNOWN -> valueOf("UNKNOWN")
+				CongestionLevelV1.SMOOTH -> valueOf("SMOOTH")
+				CongestionLevelV1.STOP_AND_GO -> valueOf("STOP_AND_GO")
+				CongestionLevelV1.SIGNIFICANT -> valueOf("SIGNIFICANT")
+				CongestionLevelV1.SEVERE -> valueOf("SEVERE")
+			}
+		}
+	}
+}
+
+enum class OccupancyStatus {
+	UNKNOWN, EMPTY, MANY_AVAILABLE, FEW_AVAILABLE, STANDING_ONLY, CRUSHED, FULL, NOT_ACCEPTING;
+
+	fun toString(context: Context):String {
+		return when (this) {
+			UNKNOWN -> context.getString(R.string.occupancy_unknown)
+			EMPTY -> context.getString(R.string.occupancy_empty)
+			MANY_AVAILABLE -> context.getString(R.string.occupancy_many_seats)
+			FEW_AVAILABLE -> context.getString(R.string.occupancy_few_seats)
+			STANDING_ONLY -> context.getString(R.string.occupancy_standing_only)
+			CRUSHED -> context.getString(R.string.occupancy_crowded)
+			FULL -> context.getString(R.string.occupancy_full)
+			NOT_ACCEPTING -> context.getString(R.string.occupancy_wont_let)
+		}
+	}
+	companion object {
+		fun of(type: OccupancyStatusV1): OccupancyStatus {
+			return when (type) {
+				OccupancyStatusV1.UNKNOWN -> valueOf("UNKNOWN")
+				OccupancyStatusV1.EMPTY -> valueOf("EMPTY")
+				OccupancyStatusV1.MANY_AVAILABLE -> valueOf("MANY_AVAILABLE")
+				OccupancyStatusV1.FEW_AVAILABLE -> valueOf("FEW_AVAILABLE")
+				OccupancyStatusV1.STANDING_ONLY -> valueOf("STANDING_ONLY")
+				OccupancyStatusV1.CRUSHED -> valueOf("CRUSHED")
+				OccupancyStatusV1.FULL -> valueOf("FULL")
+				OccupancyStatusV1.NOT_ACCEPTING -> valueOf("NOT_ACCEPTING")
+			}
+		}
+	}
+}
 
 data class Vehicle(
 	val ID: String,
@@ -14,15 +71,31 @@ 	val Capabilities: UShort,
 	val Speed: Float,
 	val Line: LineStub,
 	val Headsign: String,
-	val CongestionLevel: ULong,
-	val OccupancyStatus: ULong
+	val congestionLevel: CongestionLevel,
+	val occupancyStatus: OccupancyStatus
 ) : Locatable {
-	constructor(v: VehicleV1):this(v.ID,
-		Position(v.Position), v.Capabilities, v.Speed,
-		LineStub(v.Line), v.Headsign, v.CongestionLevel, v.OccupancyStatus)
-	constructor(v: VehicleV2):this(v.ID,
-		Position(v.Position), v.Capabilities, v.Speed,
-		LineStub(v.Line), v.Headsign, v.CongestionLevel, v.OccupancyStatus)
+	constructor(v: VehicleV1) : this(
+		v.ID,
+		Position(v.Position),
+		v.Capabilities,
+		v.Speed,
+		LineStub(v.Line),
+		v.Headsign,
+		CongestionLevel.of(v.CongestionLevel),
+		OccupancyStatus.of(v.OccupancyStatus)
+	)
+
+	constructor(v: VehicleV2) : this(
+		v.ID,
+		Position(v.Position),
+		v.Capabilities,
+		v.Speed,
+		LineStub(v.Line),
+		v.Headsign,
+		CongestionLevel.of(v.CongestionLevel),
+		OccupancyStatus.of(v.OccupancyStatus)
+	)
+
 	enum class Capability(val bit: UShort) {
 		RAMP(0b0001u), LOW_FLOOR(0b0010u), LOW_ENTRY(0b0001_0000_0000u), AC(0b0100u), BIKE(0b1000u), VOICE(
 			0b0001_0000u
@@ -30,37 +103,15 @@ 		),
 		TICKET_MACHINE(0b0010_0000u), TICKET_DRIVER(0b0100_0000u), USB_CHARGING(0b1000_0000u)
 	}
 
-	override fun icon(context: Context, scale: Float): Drawable = Line.icon(context, scale)
+	override fun icon(context: Context, scale: Float) = Line.icon(context, scale)
 
 	override fun location(): Position = Position
 
 	override fun id(): String = ID
 
-	fun congestion(context: Context): String {
-		return when (val r = CongestionLevel.toUInt()) { // todo [3.1] enum
-			0u -> context.getString(R.string.congestion_unknown)
-			1u -> context.getString(R.string.congestion_smooth)
-			2u -> context.getString(R.string.congestion_stop_and_go)
-			3u -> context.getString(R.string.congestion_congestion)
-			4u -> context.getString(R.string.congestion_jams)
-			else -> throw UnknownResourceVersion("Congestion/$r", 1u)
-		}
-	}
-
-	fun occupancy(context: Context): String {
-		return when (val r = OccupancyStatus.toUInt()) { // todo [3.1] enum
-			0u -> context.getString(R.string.occupancy_unknown)
-			1u -> context.getString(R.string.occupancy_empty)
-			2u -> context.getString(R.string.occupancy_many_seats)
-			3u -> context.getString(R.string.occupancy_few_seats)
-			4u -> context.getString(R.string.occupancy_standing_only)
-			5u -> context.getString(R.string.occupancy_crowded)
-			6u -> context.getString(R.string.occupancy_full)
-			7u -> context.getString(R.string.occupancy_wont_let)
-			else -> throw UnknownResourceVersion("Occupancy/$r", 1u)
+	fun congestion(context: Context) = congestionLevel.toString(context)
 
-		}
-	}
+	fun occupancy(context: Context)= occupancyStatus.toString(context)
 
 	fun getCapability(field: Capability): Boolean {
 		return Capabilities.and(field.bit) != (0).toUShort()