ref: 3dc642a878cddf6ffa50a59e992a3f0945447d84
app/src/main/java/xyz/apiote/bimba/czwek/api/transitousJourney.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
// SPDX-FileCopyrightText: Adam Evyčędo // // SPDX-License-Identifier: GPL-3.0-or-later package xyz.apiote.bimba.czwek.api import android.content.Context import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import okhttp3.OkHttpClient import xyz.apiote.bimba.czwek.R import xyz.apiote.bimba.czwek.api.transitous.api.RoutingApi import xyz.apiote.bimba.czwek.api.transitous.model.PedestrianProfile import xyz.apiote.bimba.czwek.repo.Colour import xyz.apiote.bimba.czwek.repo.CongestionLevel import xyz.apiote.bimba.czwek.repo.Event import xyz.apiote.bimba.czwek.repo.Journey import xyz.apiote.bimba.czwek.repo.JourneyParams import xyz.apiote.bimba.czwek.repo.Leg import xyz.apiote.bimba.czwek.repo.LineStub import xyz.apiote.bimba.czwek.repo.LineType import xyz.apiote.bimba.czwek.repo.OccupancyStatus import xyz.apiote.bimba.czwek.repo.Place import xyz.apiote.bimba.czwek.repo.Position import xyz.apiote.bimba.czwek.repo.TimeReference import xyz.apiote.bimba.czwek.repo.TrafficResponseException import xyz.apiote.bimba.czwek.repo.Vehicle import xyz.apiote.bimba.czwek.units.Metre import xyz.apiote.bimba.czwek.units.Mps import xyz.apiote.bimba.czwek.units.Second import java.time.Duration import java.time.ZoneId import java.time.ZonedDateTime suspend fun getJourney( from: Place, to: Place, params: JourneyParams, context: Context ): List<Journey> { if (!isNetworkAvailable(context)) { throw TrafficResponseException(0, "", Error(0, R.string.error_offline, R.drawable.error_net)) } // FIXME arrive-by shows wierd results return withContext(Dispatchers.IO) { val client = OkHttpClient.Builder() .callTimeout(Duration.ofSeconds(60)) .readTimeout(Duration.ofSeconds(60)) .writeTimeout(Duration.ofSeconds(60)) .connectTimeout(Duration.ofSeconds(60)).build() val response = RoutingApi(client = client).plan( from.planString(), to.planString(), maxTransfers = null, maxTravelTime = null, time = ZonedDateTime.of(params.getSafeDate(), params.getSafeTime(), ZoneId.systemDefault()) .toOffsetDateTime(), arriveBy = params.timeReference == TimeReference.ARRIVE_BY, requireBikeTransport = params.bicycle, pedestrianProfile = if (params.wheelchairAccessible) PedestrianProfile.WHEELCHAIR else PedestrianProfile.FOOT, ) response.itineraries.map { val legs: List<Leg> = it.legs.map { Leg( Event( it.tripId ?: "", null, Time.fromOffsetTime(it.startTime, ZoneId.systemDefault()), 0u, it.realTime, Vehicle( it.tripId ?: "", Position(0.0, 0.0), 0u, Mps(0), LineStub( it.routeShortName ?: "", LineType.fromTransitous2(it.mode), Colour.fromHex(it.routeColor) ), it.headsign ?: "", CongestionLevel.UNKNOWN, OccupancyStatus.UNKNOWN ), boarding = 0xffu, alerts = emptyList(), exact = true, terminusArrival = false ), Event( it.tripId ?: "", Time.fromOffsetTime(it.endTime, ZoneId.systemDefault()), null, 0u, it.realTime, Vehicle( it.tripId ?: "", Position(0.0, 0.0), 0u, Mps(0), LineStub( it.routeShortName ?: "", LineType.fromTransitous2(it.mode), Colour.fromHex(it.routeColor) ), it.headsign ?: "", CongestionLevel.UNKNOWN, OccupancyStatus.UNKNOWN ), boarding = 0xffu, alerts = emptyList(), exact = true, terminusArrival = false ), Place(it.from), Place(it.to), it.agencyName, it.distance?.toDouble()?.let { Metre(it) }, Second(it.duration), (it.intermediateStops ?: emptyList()).map { Place(it) }, decode(it.legGeometry.points) /*it.rental, it.steps,*/ ) } Journey( it.startTime.atZoneSameInstant(ZoneId.systemDefault()), it.endTime.atZoneSameInstant( ZoneId.systemDefault() ), legs ) } } } /* The following piece of code © Google, Apache License, Version 2.0 from https://github.com/googlemaps/android-maps-utils/blob/main/library/src/main/java/com/google/maps/android/PolyUtil.java with changes to decode with precision 7 */ fun decode(encodedPath: String): MutableList<Position> { val len = encodedPath.length val path: MutableList<Position> = ArrayList<Position>() var index = 0 var lat = 0 var lng = 0 while (index < len) { var result = 1 var shift = 0 var b: Int do { b = encodedPath[index++].code - 63 - 1 result += b shl shift shift += 5 } while (b >= 0x1f) lat += if ((result and 1) != 0) (result shr 1).inv() else (result shr 1) result = 1 shift = 0 do { b = encodedPath[index++].code - 63 - 1 result += b shl shift shift += 5 } while (b >= 0x1f) lng += if ((result and 1) != 0) (result shr 1).inv() else (result shr 1) path.add(Position(lat * 1e-7, lng * 1e-7)) } return path } |