Author: Adam Evyčędo <git@apiote.xyz>
split responses to own files
%!v(PANIC=String method: strings: negative Repeat count)
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 d5f464c24cfb86ce7970768c513624b7a9d16df1..8e241060fe512c6bf1277c7891519edee95a67eb 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 @@ -1,16 +1,12 @@ package xyz.apiote.bimba.czwek.api -import android.graphics.* import android.os.Parcelable import android.util.Log import kotlinx.parcelize.Parcelize import org.yaml.snakeyaml.Yaml +import xyz.apiote.bimba.czwek.api.structs.VehicleStatusV1 import xyz.apiote.fruchtfleisch.Reader import java.io.InputStream -import java.time.ZonedDateTime -import java.time.format.DateTimeFormatter -import java.time.format.FormatStyle -import java.util.* import kotlin.reflect.KClass class TrafficFormatException(override val message: String) : IllegalArgumentException() @@ -110,32 +106,6 @@ } } } -data class FeedInfoV1( - val name: String, - val id: String, - val attribution: String, - val description: String, - val lastUpdate: ZonedDateTime -) { - companion object { - fun unmarshal(stream: InputStream): FeedInfoV1 { - val reader = Reader(stream) - return FeedInfoV1( - reader.readString(), - reader.readString(), - reader.readString(), - reader.readString(), - ZonedDateTime.parse(reader.readString(), DateTimeFormatter.ISO_DATE_TIME) - ) - } - } - - fun formatDate(): String { - return lastUpdate.format( - DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(Locale.getDefault()) - ) - } -} enum class AlertCauseV1 { UNKNOWN, OTHER, TECHNICAL_PROBLEM, STRIKE, DEMONSTRATION, ACCIDENT, HOLIDAY, WEATHER, MAINTENANCE, @@ -447,7 +417,7 @@ data class DepartureV3( val ID: String, val time: Time, - val status: ULong, + val status: VehicleStatusV1, val isRealtime: Boolean, val vehicle: VehicleV3, val boarding: UByte @@ -458,7 +428,7 @@ fun unmarshal(stream: InputStream): DepartureV3 { val reader = Reader(stream) val id = reader.readString() val time = Time.unmarshal(stream) - val status = reader.readUInt().toULong() + val status = VehicleStatusV1.of(reader.readUInt().toULong().toUInt()) val isRealtime = reader.readBoolean() val vehicle = VehicleV3.unmarshal(stream) val boarding = reader.readU8() @@ -575,6 +545,7 @@ ) } } } + data class LineV2( val name: String, val colour: ColourV1, diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Departures.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Departures.kt new file mode 100644 index 0000000000000000000000000000000000000000..c7550c6c654c18366c2268986b7724389bd821f4 --- /dev/null +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Departures.kt @@ -0,0 +1,135 @@ +package xyz.apiote.bimba.czwek.api.responses + +import xyz.apiote.bimba.czwek.api.AlertV1 +import xyz.apiote.bimba.czwek.api.DepartureV1 +import xyz.apiote.bimba.czwek.api.DepartureV2 +import xyz.apiote.bimba.czwek.api.DepartureV3 +import xyz.apiote.bimba.czwek.api.StopV1 +import xyz.apiote.bimba.czwek.api.StopV2 +import xyz.apiote.bimba.czwek.api.UnknownResponseVersion +import xyz.apiote.fruchtfleisch.Reader +import java.io.InputStream + +interface DeparturesResponse { + companion object { + fun unmarshal(stream: InputStream): DeparturesResponse { + val reader = Reader(stream) + return when (val v = reader.readUInt().toULong()) { + 0UL -> DeparturesResponseDev.unmarshal(stream) + 1UL -> DeparturesResponseV1.unmarshal(stream) + 2UL -> DeparturesResponseV2.unmarshal(stream) + 3UL -> DeparturesResponseV3.unmarshal(stream) + else -> throw UnknownResponseVersion("Departures", v) + } + } + } +} + +data class DeparturesResponseDev( + val alerts: List<AlertV1>, + val departures: List<DepartureV3>, + val stop: StopV2 +) : DeparturesResponse { + companion object { + fun unmarshal(stream: InputStream): DeparturesResponseDev { + val alerts = mutableListOf<AlertV1>() + val departures = mutableListOf<DepartureV3>() + + val reader = Reader(stream) + val alertsNum = reader.readUInt().toULong() + for (i in 0UL until alertsNum) { + val alert = AlertV1.unmarshal(stream) + alerts.add(alert) + } + val departuresNum = reader.readUInt().toULong() + for (i in 0UL until departuresNum) { + val departure = DepartureV3.unmarshal(stream) + departures.add(departure) + } + + return DeparturesResponseDev(alerts, departures, StopV2.unmarshal(stream)) + } + } +} + +data class DeparturesResponseV3( + val alerts: List<AlertV1>, + val departures: List<DepartureV3>, + val stop: StopV2 +) : DeparturesResponse { + companion object { + fun unmarshal(stream: InputStream): DeparturesResponseDev { + val alerts = mutableListOf<AlertV1>() + val departures = mutableListOf<DepartureV3>() + + val reader = Reader(stream) + val alertsNum = reader.readUInt().toULong() + for (i in 0UL until alertsNum) { + val alert = AlertV1.unmarshal(stream) + alerts.add(alert) + } + val departuresNum = reader.readUInt().toULong() + for (i in 0UL until departuresNum) { + val departure = DepartureV3.unmarshal(stream) + departures.add(departure) + } + + return DeparturesResponseDev(alerts, departures, StopV2.unmarshal(stream)) + } + } +} + +data class DeparturesResponseV2( + val alerts: List<AlertV1>, + val departures: List<DepartureV2>, + val stop: StopV2 +) : DeparturesResponse { + companion object { + fun unmarshal(stream: InputStream): DeparturesResponseV2 { + val alerts = mutableListOf<AlertV1>() + val departures = mutableListOf<DepartureV2>() + + val reader = Reader(stream) + val alertsNum = reader.readUInt().toULong() + for (i in 0UL until alertsNum) { + val alert = AlertV1.unmarshal(stream) + alerts.add(alert) + } + val departuresNum = reader.readUInt().toULong() + for (i in 0UL until departuresNum) { + val departure = DepartureV2.unmarshal(stream) + departures.add(departure) + } + + return DeparturesResponseV2(alerts, departures, StopV2.unmarshal(stream)) + } + } +} + +data class DeparturesResponseV1( + val alerts: List<AlertV1>, + val departures: List<DepartureV1>, + val stop: StopV1 +) : DeparturesResponse { + companion object { + fun unmarshal(stream: InputStream): DeparturesResponseV1 { + val alerts = mutableListOf<AlertV1>() + val departures = mutableListOf<DepartureV1>() + + val reader = Reader(stream) + val alertsNum = reader.readUInt().toULong() + for (i in 0UL until alertsNum) { + val alert = AlertV1.unmarshal(stream) + alerts.add(alert) + } + val departuresNum = reader.readUInt().toULong() + for (i in 0UL until departuresNum) { + val departure = DepartureV1.unmarshal(stream) + departures.add(departure) + } + + return DeparturesResponseV1(alerts, departures, StopV1.unmarshal(stream)) + } + } +} + diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Error.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Error.kt new file mode 100644 index 0000000000000000000000000000000000000000..a99569153a1cf725565fe7f642aa1c3830629753 --- /dev/null +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Error.kt @@ -0,0 +1,13 @@ +package xyz.apiote.bimba.czwek.api.responses + +import xyz.apiote.fruchtfleisch.Reader +import java.io.InputStream + +data class ErrorResponse(val field: String, val message: String) { + companion object { + fun unmarshal(stream: InputStream): ErrorResponse { + val reader = Reader(stream) + return ErrorResponse(reader.readString(), reader.readString()) + } + } +} diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Feeds.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Feeds.kt new file mode 100644 index 0000000000000000000000000000000000000000..4be8cc6c620b0f7b40124e8449a6c78ee0a1172f --- /dev/null +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Feeds.kt @@ -0,0 +1,69 @@ +package xyz.apiote.bimba.czwek.api.responses + +import xyz.apiote.bimba.czwek.api.UnknownResponseVersion +import xyz.apiote.bimba.czwek.api.structs.FeedInfoV1 +import xyz.apiote.bimba.czwek.api.structs.FeedInfoV2 +import xyz.apiote.fruchtfleisch.Reader +import java.io.InputStream + +interface FeedsResponse { + companion object { + fun unmarshal(stream: InputStream): FeedsResponse { + val reader = Reader(stream) + return when (val v = reader.readUInt().toULong()) { + 0UL -> FeedsResponseDev.unmarshal(stream) + 1UL -> FeedsResponseV1.unmarshal(stream) + 2UL -> FeedsResponseV2.unmarshal(stream) + else -> throw UnknownResponseVersion("Feeds", v) + } + } + } +} + +data class FeedsResponseDev( + val feeds: List<FeedInfoV2> +) : FeedsResponse { + companion object { + fun unmarshal(stream: InputStream): FeedsResponseDev { + val feeds = mutableListOf<FeedInfoV2>() + val reader = Reader(stream) + val n = reader.readUInt().toULong() + for (i in 0UL until n) { + feeds.add(FeedInfoV2.unmarshal(stream)) + } + return FeedsResponseDev(feeds) + } + } +} + +data class FeedsResponseV2( + val feeds: List<FeedInfoV2> +) : FeedsResponse { + companion object { + fun unmarshal(stream: InputStream): FeedsResponseDev { + val feeds = mutableListOf<FeedInfoV2>() + val reader = Reader(stream) + val n = reader.readUInt().toULong() + for (i in 0UL until n) { + feeds.add(FeedInfoV2.unmarshal(stream)) + } + return FeedsResponseDev(feeds) + } + } +} + +data class FeedsResponseV1( + val feeds: List<FeedInfoV1> +) : FeedsResponse { + companion object { + fun unmarshal(stream: InputStream): FeedsResponseV1 { + val feeds = mutableListOf<FeedInfoV1>() + val reader = Reader(stream) + val n = reader.readUInt().toULong() + for (i in 0UL until n) { + feeds.add(FeedInfoV1.unmarshal(stream)) + } + return FeedsResponseV1(feeds) + } + } +} diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Line.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Line.kt new file mode 100644 index 0000000000000000000000000000000000000000..632f3e835cf4e3a7889c5ca883ca33215d2f75f0 --- /dev/null +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Line.kt @@ -0,0 +1,51 @@ +package xyz.apiote.bimba.czwek.api.responses + +import xyz.apiote.bimba.czwek.api.LineV1 +import xyz.apiote.bimba.czwek.api.LineV2 +import xyz.apiote.bimba.czwek.api.UnknownResponseVersion +import xyz.apiote.fruchtfleisch.Reader +import java.io.InputStream + +interface LineResponse { + companion object { + fun unmarshal(stream: InputStream): LineResponse { + val reader = Reader(stream) + return when (val v = reader.readUInt().toULong()) { + 0UL -> LineResponseDev.unmarshal(stream) + 1UL -> LineResponseV1.unmarshal(stream) + 2UL -> LineResponseV2.unmarshal(stream) + else -> throw UnknownResponseVersion("Line", v) + } + } + } +} + +data class LineResponseDev( + val line: LineV2 +) : LineResponse { + companion object { + fun unmarshal(stream: InputStream): LineResponseDev { + return LineResponseDev(LineV2.unmarshal(stream)) + } + } +} + +data class LineResponseV2( + val line: LineV2 +) : LineResponse { + companion object { + fun unmarshal(stream: InputStream): LineResponseDev { + return LineResponseDev(LineV2.unmarshal(stream)) + } + } +} + +data class LineResponseV1( + val line: LineV1 +) : LineResponse { + companion object { + fun unmarshal(stream: InputStream): LineResponseV1 { + return LineResponseV1(LineV1.unmarshal(stream)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Locatables.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Locatables.kt new file mode 100644 index 0000000000000000000000000000000000000000..5a882417b23eb02afae8e45e5523a24c3f7f7923 --- /dev/null +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Locatables.kt @@ -0,0 +1,125 @@ +package xyz.apiote.bimba.czwek.api.responses + +import xyz.apiote.bimba.czwek.api.LocatableV1 +import xyz.apiote.bimba.czwek.api.LocatableV2 +import xyz.apiote.bimba.czwek.api.LocatableV3 +import xyz.apiote.bimba.czwek.api.StopV1 +import xyz.apiote.bimba.czwek.api.StopV2 +import xyz.apiote.bimba.czwek.api.UnknownResourceVersionException +import xyz.apiote.bimba.czwek.api.UnknownResponseVersion +import xyz.apiote.bimba.czwek.api.VehicleV1 +import xyz.apiote.bimba.czwek.api.VehicleV2 +import xyz.apiote.bimba.czwek.api.VehicleV3 +import xyz.apiote.fruchtfleisch.Reader +import java.io.InputStream + +interface LocatablesResponse { + companion object { + fun unmarshal(stream: InputStream): LocatablesResponse { + val reader = Reader(stream) + return when (val v = reader.readUInt().toULong()) { + 0UL -> LocatablesResponseDev.unmarshal(stream) + 1UL -> LocatablesResponseV1.unmarshal(stream) + 2UL -> LocatablesResponseV2.unmarshal(stream) + 3UL -> LocatablesResponseV3.unmarshal(stream) + else -> throw UnknownResponseVersion("Locatables", v) + } + } + } +} + +data class LocatablesResponseDev(val locatables: List<LocatableV3>) : LocatablesResponse { + companion object { + fun unmarshal(stream: InputStream): LocatablesResponseDev { + val locatables = mutableListOf<LocatableV3>() + val reader = Reader(stream) + val n = reader.readUInt().toULong() + for (i in 0UL until n) { + when (val r = reader.readUInt().toULong()) { + 0UL -> { + locatables.add(StopV2.unmarshal(stream)) + } + + 1UL -> { + locatables.add(VehicleV3.unmarshal(stream)) + } + + else -> { + throw UnknownResourceVersionException("Locatable/$r", 0u) + } + } + } + return LocatablesResponseDev(locatables) + } + } +} + +data class LocatablesResponseV3(val locatables: List<LocatableV3>) : LocatablesResponse { + companion object { + fun unmarshal(stream: InputStream): LocatablesResponseDev { + val locatables = mutableListOf<LocatableV3>() + val reader = Reader(stream) + val n = reader.readUInt().toULong() + for (i in 0UL until n) { + when (val r = reader.readUInt().toULong()) { + 0UL -> { + locatables.add(StopV2.unmarshal(stream)) + } + + 1UL -> { + locatables.add(VehicleV3.unmarshal(stream)) + } + + else -> { + throw UnknownResourceVersionException("Locatable/$r", 0u) + } + } + } + return LocatablesResponseDev(locatables) + } + } +} + +data class LocatablesResponseV2(val locatables: List<LocatableV2>) : LocatablesResponse { + companion object { + fun unmarshal(stream: InputStream): LocatablesResponseV2 { + val locatables = mutableListOf<LocatableV2>() + val reader = Reader(stream) + val n = reader.readUInt().toULong() + for (i in 0UL until n) { + when (val r = reader.readUInt().toULong()) { + 0UL -> locatables.add(StopV2.unmarshal(stream)) + 1UL -> locatables.add(VehicleV2.unmarshal(stream)) + else -> throw UnknownResourceVersionException("Locatable/$r", 2u) + } + } + return LocatablesResponseV2(locatables) + } + } +} + +data class LocatablesResponseV1(val locatables: List<LocatableV1>) : LocatablesResponse { + companion object { + fun unmarshal(stream: InputStream): LocatablesResponseV1 { + val locatables = mutableListOf<LocatableV1>() + val reader = Reader(stream) + val n = reader.readUInt().toULong() + for (i in 0UL until n) { + when (val r = reader.readUInt().toULong()) { + 0UL -> { + locatables.add(StopV1.unmarshal(stream)) + } + + 1UL -> { + locatables.add(VehicleV1.unmarshal(stream)) + } + + else -> { + throw UnknownResourceVersionException("Locatable/$r", 1u) + } + } + } + return LocatablesResponseV1(locatables) + } + } +} diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Queryables.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Queryables.kt new file mode 100644 index 0000000000000000000000000000000000000000..a1d7685bab36b61532f1b8cd7a2270ded20402ab --- /dev/null +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/Queryables.kt @@ -0,0 +1,128 @@ +package xyz.apiote.bimba.czwek.api.responses + +import xyz.apiote.bimba.czwek.api.LineV1 +import xyz.apiote.bimba.czwek.api.LineV2 +import xyz.apiote.bimba.czwek.api.QueryableV1 +import xyz.apiote.bimba.czwek.api.QueryableV2 +import xyz.apiote.bimba.czwek.api.QueryableV3 +import xyz.apiote.bimba.czwek.api.StopV1 +import xyz.apiote.bimba.czwek.api.StopV2 +import xyz.apiote.bimba.czwek.api.UnknownResourceVersionException +import xyz.apiote.bimba.czwek.api.UnknownResponseVersion +import xyz.apiote.fruchtfleisch.Reader +import java.io.InputStream + +interface QueryablesResponse { + companion object { + fun unmarshal(stream: InputStream): QueryablesResponse { + val reader = Reader(stream) + return when (val v = reader.readUInt().toULong()) { + 0UL -> QueryablesResponseDev.unmarshal(stream) + 1UL -> QueryablesResponseV1.unmarshal(stream) + 2UL -> QueryablesResponseV2.unmarshal(stream) + 3UL -> QueryablesResponseV3.unmarshal(stream) + else -> throw UnknownResponseVersion("Queryables", v) + } + } + } +} + +data class QueryablesResponseDev(val queryables: List<QueryableV3>) : QueryablesResponse { + companion object { + fun unmarshal(stream: InputStream): QueryablesResponseDev { + val queryables = mutableListOf<QueryableV3>() + val reader = Reader(stream) + val n = reader.readUInt().toULong() + for (i in 0UL until n) { + when (val r = reader.readUInt().toULong()) { + 0UL -> { + queryables.add(StopV2.unmarshal(stream)) + } + + 1UL -> { + queryables.add(LineV2.unmarshal(stream)) + } + + else -> { + throw UnknownResourceVersionException("Queryable/$r", 0u) + } + } + } + return QueryablesResponseDev(queryables) + } + } +} + +data class QueryablesResponseV3(val queryables: List<QueryableV3>) : QueryablesResponse { + companion object { + fun unmarshal(stream: InputStream): QueryablesResponseDev { + val queryables = mutableListOf<QueryableV3>() + val reader = Reader(stream) + val n = reader.readUInt().toULong() + for (i in 0UL until n) { + when (val r = reader.readUInt().toULong()) { + 0UL -> { + queryables.add(StopV2.unmarshal(stream)) + } + + 1UL -> { + queryables.add(LineV2.unmarshal(stream)) + } + + else -> { + throw UnknownResourceVersionException("Queryable/$r", 0u) + } + } + } + return QueryablesResponseDev(queryables) + } + } +} + +data class QueryablesResponseV2(val queryables: List<QueryableV2>) : QueryablesResponse { + companion object { + fun unmarshal(stream: InputStream): QueryablesResponseV2 { + val queryables = mutableListOf<QueryableV2>() + val reader = Reader(stream) + val n = reader.readUInt().toULong() + for (i in 0UL until n) { + when (val r = reader.readUInt().toULong()) { + 0UL -> { + queryables.add(StopV2.unmarshal(stream)) + } + + 1UL -> { + queryables.add(LineV1.unmarshal(stream)) + } + + else -> { + throw UnknownResourceVersionException("Queryable/$r", 2u) + } + } + } + return QueryablesResponseV2(queryables) + } + } +} + +data class QueryablesResponseV1(val queryables: List<QueryableV1>) : QueryablesResponse { + companion object { + fun unmarshal(stream: InputStream): QueryablesResponseV1 { + val queryables = mutableListOf<QueryableV1>() + val reader = Reader(stream) + val n = reader.readUInt().toULong() + for (i in 0UL until n) { + when (val r = reader.readUInt().toULong()) { + 0UL -> { + queryables.add(StopV1.unmarshal(stream)) + } + + else -> { + throw UnknownResourceVersionException("Queryable/$r", 1u) + } + } + } + return QueryablesResponseV1(queryables) + } + } +} diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/UnknownResponseVersion.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/UnknownResponseVersion.kt index 69c025fe2fd34428e9fc83e19518143de890e22a..17bed9db82471ae34057063a788995bbd2bb305c 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/UnknownResponseVersion.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/responses/UnknownResponseVersion.kt @@ -1,17 +1,5 @@ -package xyz.apiote.bimba.czwek.api - -import xyz.apiote.fruchtfleisch.Reader -import java.io.InputStream +package xyz.apiote.bimba.czwek.api.responses class UnknownResponseVersion(resource: String, version: ULong) : Exception("Unknown resource $resource in version $version") - -data class ErrorResponse(val field: String, val message: String) { - companion object { - fun unmarshal(stream: InputStream): ErrorResponse { - val reader = Reader(stream) - return ErrorResponse(reader.readString(), reader.readString()) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/structs/FeedInfo.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/structs/FeedInfo.kt new file mode 100644 index 0000000000000000000000000000000000000000..dbb1d190f1bb13814e43abe7b6fa38192334811b --- /dev/null +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/structs/FeedInfo.kt @@ -0,0 +1,73 @@ +package xyz.apiote.bimba.czwek.api.structs + +import xyz.apiote.fruchtfleisch.Reader +import java.io.InputStream +import java.time.LocalDate +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import java.time.format.FormatStyle +import java.util.Locale + +data class FeedInfoV2( + val name: String, + val id: String, + val attribution: String, + val description: String, + val lastUpdate: LocalDate, + val qrHost: String, + val qrIn: QrLocationV1, + val qrSelector: String, + val validSince: LocalDate, + val validTill: LocalDate +) { + companion object { + fun unmarshal(stream: InputStream): FeedInfoV2 { + val reader = Reader(stream) + return FeedInfoV2( + reader.readString(), + reader.readString(), + reader.readString(), + reader.readString(), + LocalDate.parse(reader.readString(), DateTimeFormatter.ISO_LOCAL_DATE), + reader.readString(), + QrLocationV1.of(reader.readUInt().toULong().toUInt()), + reader.readString(), + LocalDate.parse(reader.readString(), DateTimeFormatter.BASIC_ISO_DATE), + LocalDate.parse(reader.readString(), DateTimeFormatter.BASIC_ISO_DATE) + ) + } + } + + fun formatDate(): String { + return lastUpdate.format( + DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(Locale.getDefault()) + ) + } +} + +data class FeedInfoV1( + val name: String, + val id: String, + val attribution: String, + val description: String, + val lastUpdate: ZonedDateTime +) { + companion object { + fun unmarshal(stream: InputStream): FeedInfoV1 { + val reader = Reader(stream) + return FeedInfoV1( + reader.readString(), + reader.readString(), + reader.readString(), + reader.readString(), + ZonedDateTime.parse(reader.readString(), DateTimeFormatter.ISO_DATE_TIME) + ) + } + } + + fun formatDate(): String { + return lastUpdate.format( + DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(Locale.getDefault()) + ) + } +} diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/structs/QrLocation.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/structs/QrLocation.kt new file mode 100644 index 0000000000000000000000000000000000000000..a5832f576f20dad87c30c9779e61c0668c396535 --- /dev/null +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/structs/QrLocation.kt @@ -0,0 +1,19 @@ +package xyz.apiote.bimba.czwek.api.structs + +import xyz.apiote.bimba.czwek.api.UnknownResourceVersionException + +enum class QrLocationV1 { + UNKNOWN, NONE, PATH, QUERY; + + companion object { + fun of(type: UInt): QrLocationV1 { + return when (type) { + 0u -> UNKNOWN + 1u -> NONE + 2u -> PATH + 3u -> QUERY + else -> throw UnknownResourceVersionException("QrLocation/$type", 1u) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/structs/VehicleStatus.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/structs/VehicleStatus.kt new file mode 100644 index 0000000000000000000000000000000000000000..31786bc674352d1eb844571693af190d0c309557 --- /dev/null +++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/structs/VehicleStatus.kt @@ -0,0 +1,19 @@ +package xyz.apiote.bimba.czwek.api.structs + +import xyz.apiote.bimba.czwek.api.UnknownResourceVersionException + +enum class VehicleStatusV1 { + IN_TRANSIT, INCOMING, AT_STOP, DEPARTED; + + companion object { + fun of(type: UInt): VehicleStatusV1 { + return when (type) { + 0u -> IN_TRANSIT + 1u -> INCOMING + 2u -> AT_STOP + 3u -> DEPARTED + else -> throw UnknownResourceVersionException("VehicleStatus/$type", 1u) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeViewModel.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeViewModel.kt index 4120a5f52b1467770aa4e7fee92f54bbe6c6d5d7..425bc76d6e4fb37baf9542700a0c3ac0dbba6926 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeViewModel.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeViewModel.kt @@ -12,9 +12,9 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch -import xyz.apiote.bimba.czwek.repo.TrafficResponseException import xyz.apiote.bimba.czwek.repo.OnlineRepository import xyz.apiote.bimba.czwek.repo.Queryable +import xyz.apiote.bimba.czwek.repo.TrafficResponseException class HomeViewModel : ViewModel() { private val mutableQueryables = MutableLiveData<List<Queryable>>() diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt index bacd215fbb6a60598adbcc17ffb0d8696b05c5d0..5f7769362b300b79de6ccc2ed96e6da4b93d3194 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt @@ -22,11 +22,11 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment import kotlinx.coroutines.launch import xyz.apiote.bimba.czwek.R import xyz.apiote.bimba.czwek.departures.DeparturesActivity -import xyz.apiote.bimba.czwek.repo.TrafficResponseException import xyz.apiote.bimba.czwek.repo.Locatable import xyz.apiote.bimba.czwek.repo.OnlineRepository import xyz.apiote.bimba.czwek.repo.Position import xyz.apiote.bimba.czwek.repo.Stop +import xyz.apiote.bimba.czwek.repo.TrafficResponseException import xyz.apiote.bimba.czwek.repo.Vehicle class MapViewModel : ViewModel() { diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt index b5d8fa38ecb1f8bd03fc66e5799258041b5cd1d8..b79c2b84160b8eedae05ce6257f669dcbd1736e1 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt @@ -13,14 +13,16 @@ import androidx.appcompat.content.res.AppCompatResources import androidx.core.content.res.ResourcesCompat import androidx.core.view.WindowCompat import androidx.recyclerview.widget.LinearLayoutManager -import kotlinx.coroutines.* +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.Runnable +import kotlinx.coroutines.launch import xyz.apiote.bimba.czwek.R -import xyz.apiote.bimba.czwek.api.* +import xyz.apiote.bimba.czwek.api.Error import xyz.apiote.bimba.czwek.databinding.ActivityDeparturesBinding import xyz.apiote.bimba.czwek.repo.Departure -import xyz.apiote.bimba.czwek.repo.TrafficResponseException import xyz.apiote.bimba.czwek.repo.OnlineRepository import xyz.apiote.bimba.czwek.repo.Stop +import xyz.apiote.bimba.czwek.repo.TrafficResponseException class DeparturesActivity : AppCompatActivity() { private var _binding: ActivityDeparturesBinding? = null diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt index 100c4dd181f5b5324e3567b2a8b78a40b6ee3fb4..3818af899b26a665e8572aca47aedd33e5c30142 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/OnlineRepository.kt @@ -4,25 +4,9 @@ import android.content.Context import android.net.ConnectivityManager import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import xyz.apiote.bimba.czwek.api.DeparturesResponse -import xyz.apiote.bimba.czwek.api.DeparturesResponseDev -import xyz.apiote.bimba.czwek.api.DeparturesResponseV1 -import xyz.apiote.bimba.czwek.api.DeparturesResponseV2 -import xyz.apiote.bimba.czwek.api.ErrorResponse -import xyz.apiote.bimba.czwek.api.LineResponse -import xyz.apiote.bimba.czwek.api.LineResponseDev -import xyz.apiote.bimba.czwek.api.LineResponseV1 import xyz.apiote.bimba.czwek.api.LineV1 import xyz.apiote.bimba.czwek.api.LineV2 -import xyz.apiote.bimba.czwek.api.LocatablesResponse -import xyz.apiote.bimba.czwek.api.LocatablesResponseDev -import xyz.apiote.bimba.czwek.api.LocatablesResponseV1 -import xyz.apiote.bimba.czwek.api.LocatablesResponseV2 import xyz.apiote.bimba.czwek.api.PositionV1 -import xyz.apiote.bimba.czwek.api.QueryablesResponse -import xyz.apiote.bimba.czwek.api.QueryablesResponseDev -import xyz.apiote.bimba.czwek.api.QueryablesResponseV1 -import xyz.apiote.bimba.czwek.api.QueryablesResponseV2 import xyz.apiote.bimba.czwek.api.Server import xyz.apiote.bimba.czwek.api.StopV1 import xyz.apiote.bimba.czwek.api.StopV2 @@ -30,6 +14,26 @@ import xyz.apiote.bimba.czwek.api.UnknownResourceException import xyz.apiote.bimba.czwek.api.VehicleV1 import xyz.apiote.bimba.czwek.api.VehicleV2 import xyz.apiote.bimba.czwek.api.VehicleV3 +import xyz.apiote.bimba.czwek.api.responses.DeparturesResponse +import xyz.apiote.bimba.czwek.api.responses.DeparturesResponseDev +import xyz.apiote.bimba.czwek.api.responses.DeparturesResponseV1 +import xyz.apiote.bimba.czwek.api.responses.DeparturesResponseV2 +import xyz.apiote.bimba.czwek.api.responses.DeparturesResponseV3 +import xyz.apiote.bimba.czwek.api.responses.ErrorResponse +import xyz.apiote.bimba.czwek.api.responses.LineResponse +import xyz.apiote.bimba.czwek.api.responses.LineResponseDev +import xyz.apiote.bimba.czwek.api.responses.LineResponseV1 +import xyz.apiote.bimba.czwek.api.responses.LineResponseV2 +import xyz.apiote.bimba.czwek.api.responses.LocatablesResponse +import xyz.apiote.bimba.czwek.api.responses.LocatablesResponseDev +import xyz.apiote.bimba.czwek.api.responses.LocatablesResponseV1 +import xyz.apiote.bimba.czwek.api.responses.LocatablesResponseV2 +import xyz.apiote.bimba.czwek.api.responses.LocatablesResponseV3 +import xyz.apiote.bimba.czwek.api.responses.QueryablesResponse +import xyz.apiote.bimba.czwek.api.responses.QueryablesResponseDev +import xyz.apiote.bimba.czwek.api.responses.QueryablesResponseV1 +import xyz.apiote.bimba.czwek.api.responses.QueryablesResponseV2 +import xyz.apiote.bimba.czwek.api.responses.QueryablesResponseV3 // todo [3.2] in Repository check if responses are BARE or HTML @@ -58,7 +62,7 @@ response.departures.map { Departure(it) }, Stop(response.stop), response.alerts.map { Alert(it) }) - is DeparturesResponseV1 -> StopDepartures( + is DeparturesResponseV3 -> StopDepartures( response.departures.map { Departure(it) }, Stop(response.stop), response.alerts.map { Alert(it) }) @@ -68,6 +72,11 @@ response.departures.map { Departure(it) }, Stop(response.stop), response.alerts.map { Alert(it) }) + is DeparturesResponseV1 -> StopDepartures( + response.departures.map { Departure(it) }, + Stop(response.stop), + response.alerts.map { Alert(it) }) + else -> null } } @@ -103,10 +112,10 @@ else -> throw UnknownResourceException("locatables", it::class) } } - is LocatablesResponseV1 -> response.locatables.map { + is LocatablesResponseV3 -> response.locatables.map { when (it) { - is StopV1 -> Stop(it) - is VehicleV1 -> Vehicle(it) + is StopV2 -> Stop(it) + is VehicleV3 -> Vehicle(it) else -> throw UnknownResourceException("locatables", it::class) } } @@ -119,6 +128,14 @@ else -> throw UnknownResourceException("locatables", it::class) } } + is LocatablesResponseV1 -> response.locatables.map { + when (it) { + is StopV1 -> Stop(it) + is VehicleV1 -> Vehicle(it) + else -> throw UnknownResourceException("locatables", it::class) + } + } + else -> null } } @@ -140,6 +157,7 @@ return when (val response = withContext(Dispatchers.IO) { LineResponse.unmarshal(result.stream!!) }) { is LineResponseDev -> Line(response.line) is LineResponseV1 -> Line(response.line) + is LineResponseV2 -> Line(response.line) else -> null } } @@ -200,6 +218,14 @@ is QueryablesResponseV2 -> response.queryables.map { when (it) { is StopV2 -> Stop(it) is LineV1 -> Line(it) + else -> throw UnknownResourceException("queryablesV2", it::class) + } + } + + is QueryablesResponseV3 -> response.queryables.map { + when (it) { + is StopV2 -> Stop(it) + is LineV2 -> Line(it) else -> throw UnknownResourceException("queryablesV2", it::class) } } diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/search/ResultsActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/search/ResultsActivity.kt index 32ee74575ac55e9ae63bd0e6fd8f3cd53e78fc95..dac98247e3f28bb2da348941ef7ebaaecf27e4a2 100644 --- a/app/src/main/java/xyz/apiote/bimba/czwek/search/ResultsActivity.kt +++ b/app/src/main/java/xyz/apiote/bimba/czwek/search/ResultsActivity.kt @@ -14,14 +14,16 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.content.res.AppCompatResources import androidx.core.view.WindowCompat import androidx.recyclerview.widget.LinearLayoutManager -import kotlinx.coroutines.* +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.Runnable +import kotlinx.coroutines.launch import xyz.apiote.bimba.czwek.R -import xyz.apiote.bimba.czwek.api.* +import xyz.apiote.bimba.czwek.api.Error import xyz.apiote.bimba.czwek.databinding.ActivityResultsBinding -import xyz.apiote.bimba.czwek.repo.TrafficResponseException import xyz.apiote.bimba.czwek.repo.OnlineRepository import xyz.apiote.bimba.czwek.repo.Position import xyz.apiote.bimba.czwek.repo.Queryable +import xyz.apiote.bimba.czwek.repo.TrafficResponseException class ResultsActivity : AppCompatActivity(), LocationListener { enum class Mode {