feat: stop times/departures reimpl based on gtfs
This commit is contained in:
parent
b5f2ec102d
commit
72b9fb2757
23 changed files with 1630 additions and 128 deletions
|
|
@ -0,0 +1,28 @@
|
||||||
|
package moe.lava.banksia.client.data.stoptime
|
||||||
|
|
||||||
|
import kotlinx.datetime.LocalDate
|
||||||
|
import kotlinx.datetime.TimeZone
|
||||||
|
import kotlinx.datetime.todayIn
|
||||||
|
import moe.lava.banksia.model.StopTimeDated
|
||||||
|
import moe.lava.banksia.model.atDate
|
||||||
|
import moe.lava.banksia.room.dao.StopTimeDao
|
||||||
|
import moe.lava.banksia.util.serialise
|
||||||
|
import kotlin.time.Clock
|
||||||
|
|
||||||
|
class StopTimeLocalDataSource(
|
||||||
|
private val stopTimeDao: StopTimeDao,
|
||||||
|
) {
|
||||||
|
suspend fun getAtStop(
|
||||||
|
stopId: String,
|
||||||
|
date: LocalDate = Clock.System.todayIn(TimeZone.currentSystemDefault()),
|
||||||
|
): List<StopTimeDated> {
|
||||||
|
return stopTimeDao
|
||||||
|
.getForStopDated(
|
||||||
|
stopId,
|
||||||
|
listOf(date.dayOfWeek).serialise(),
|
||||||
|
date.toEpochDays().toInt(),
|
||||||
|
)
|
||||||
|
.map { it.asModel().atDate(date) }
|
||||||
|
.sortedBy { it.departureTime }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
package moe.lava.banksia.client.data.stoptime
|
|
||||||
|
|
||||||
import moe.lava.banksia.data.ptv.PtvService
|
|
||||||
import moe.lava.banksia.model.RouteType
|
|
||||||
import moe.lava.banksia.model.StopTime
|
|
||||||
|
|
||||||
class StopTimePtvDataSource(
|
|
||||||
private val ptvService: PtvService,
|
|
||||||
) {
|
|
||||||
suspend fun getForStop(type: RouteType, stopId: String): List<StopTime> {
|
|
||||||
return listOf()
|
|
||||||
// val res = ptvService.departures(type, stopId)
|
|
||||||
// // Map<
|
|
||||||
// // Pair<DirectionId, RouteId>,
|
|
||||||
// // Pair<DirectionName, List<DepartureTimes>>
|
|
||||||
// // >
|
|
||||||
// val timetable = HashMap<Pair<Int, Int>, Pair<String, MutableList<String>>>()
|
|
||||||
// res.departures.forEach { dep ->
|
|
||||||
// val key = Pair(dep.directionId, dep.routeId)
|
|
||||||
// val direction = ptvService.direction(dep.directionId, dep.routeId)
|
|
||||||
// val route = res.routes[dep.routeId.toString()]
|
|
||||||
// val prefix = route?.let { if (it.routeNumber == "") "" else "${it.routeNumber} - " } ?: ""
|
|
||||||
// val element = timetable.getOrPut(key) { Pair(prefix + direction.directionName, mutableListOf()) }.second
|
|
||||||
// if (element.size >= 5)
|
|
||||||
// return@forEach
|
|
||||||
//
|
|
||||||
// val date = Instant.parse(dep.estimatedDepartureUtc ?: dep.scheduledDepartureUtc)
|
|
||||||
// val min = (date - Clock.System.now()).inWholeMinutes
|
|
||||||
// if (min <= -5)
|
|
||||||
// return@forEach
|
|
||||||
// if (min >= 65)
|
|
||||||
// element.add("${((min + 30.0) / 60.0).toInt()}hr")
|
|
||||||
// else
|
|
||||||
// element.add("${min}mn")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// val departures = timetable.values.sortedBy { it.first }.map { (name, list) ->
|
|
||||||
// if (list.isEmpty())
|
|
||||||
// InfoPanelState.Stop.Departure(name, "No departures")
|
|
||||||
// else
|
|
||||||
// InfoPanelState.Stop.Departure(name, list.joinToString(" | "))
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
package moe.lava.banksia.client.data.stoptime
|
||||||
|
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.call.body
|
||||||
|
import io.ktor.client.request.get
|
||||||
|
import io.ktor.client.request.parameter
|
||||||
|
import kotlinx.datetime.LocalDate
|
||||||
|
import kotlinx.datetime.TimeZone
|
||||||
|
import kotlinx.datetime.todayIn
|
||||||
|
import moe.lava.banksia.model.StopTimeDated
|
||||||
|
import kotlin.time.Clock
|
||||||
|
|
||||||
|
class StopTimeRemoteDataSource(
|
||||||
|
private val client: HttpClient,
|
||||||
|
) {
|
||||||
|
suspend fun getAtStop(
|
||||||
|
stopId: String,
|
||||||
|
date: LocalDate? = Clock.System.todayIn(TimeZone.currentSystemDefault()),
|
||||||
|
): List<StopTimeDated> {
|
||||||
|
return client.get("stoptimes/by_stop/${stopId}") {
|
||||||
|
parameter("date", date)
|
||||||
|
}.body<List<StopTimeDated>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*suspend fun get(
|
||||||
|
stop: String? = null,
|
||||||
|
trip: String? = null,
|
||||||
|
day: DayOfWeek? = Clock.System.todayIn(TimeZone.currentSystemDefault()).dayOfWeek,
|
||||||
|
): List<StopTime> {
|
||||||
|
return client.get("stoptimes") {
|
||||||
|
stop?.let { parameter("stop", it) }
|
||||||
|
trip?.let { parameter("trip", it) }
|
||||||
|
day?.let { parameter("day", it) }
|
||||||
|
}.body<List<StopTime>>()
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package moe.lava.banksia.client.data.trip
|
||||||
|
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import kotlinx.datetime.DayOfWeek
|
||||||
|
import kotlinx.datetime.TimeZone
|
||||||
|
import kotlinx.datetime.todayIn
|
||||||
|
import moe.lava.banksia.model.Trip
|
||||||
|
import kotlin.time.Clock
|
||||||
|
|
||||||
|
class TripRemoteDataSource(
|
||||||
|
private val client: HttpClient,
|
||||||
|
) {
|
||||||
|
suspend fun get(
|
||||||
|
day: DayOfWeek? = Clock.System.todayIn(TimeZone.currentSystemDefault()).dayOfWeek,
|
||||||
|
): List<Trip> {
|
||||||
|
return listOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,7 +12,8 @@ import moe.lava.banksia.client.data.route.RouteLocalDataSource
|
||||||
import moe.lava.banksia.client.data.route.RouteRemoteDataSource
|
import moe.lava.banksia.client.data.route.RouteRemoteDataSource
|
||||||
import moe.lava.banksia.client.data.stop.StopLocalDataSource
|
import moe.lava.banksia.client.data.stop.StopLocalDataSource
|
||||||
import moe.lava.banksia.client.data.stop.StopRemoteDataSource
|
import moe.lava.banksia.client.data.stop.StopRemoteDataSource
|
||||||
import moe.lava.banksia.client.data.stoptime.StopTimePtvDataSource
|
import moe.lava.banksia.client.data.stoptime.StopTimeLocalDataSource
|
||||||
|
import moe.lava.banksia.client.data.stoptime.StopTimeRemoteDataSource
|
||||||
import moe.lava.banksia.client.repository.RouteRepository
|
import moe.lava.banksia.client.repository.RouteRepository
|
||||||
import moe.lava.banksia.client.repository.StopRepository
|
import moe.lava.banksia.client.repository.StopRepository
|
||||||
import moe.lava.banksia.client.repository.StopTimeRepository
|
import moe.lava.banksia.client.repository.StopTimeRepository
|
||||||
|
|
@ -48,7 +49,8 @@ val ClientModule = module {
|
||||||
singleOf(::RouteRemoteDataSource)
|
singleOf(::RouteRemoteDataSource)
|
||||||
singleOf(::StopLocalDataSource)
|
singleOf(::StopLocalDataSource)
|
||||||
singleOf(::StopRemoteDataSource)
|
singleOf(::StopRemoteDataSource)
|
||||||
singleOf(::StopTimePtvDataSource)
|
singleOf(::StopTimeLocalDataSource)
|
||||||
|
singleOf(::StopTimeRemoteDataSource)
|
||||||
|
|
||||||
// Repositories
|
// Repositories
|
||||||
singleOf(::RouteRepository)
|
singleOf(::RouteRepository)
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
package moe.lava.banksia.client.repository
|
package moe.lava.banksia.client.repository
|
||||||
|
|
||||||
import moe.lava.banksia.client.data.stoptime.StopTimePtvDataSource
|
import moe.lava.banksia.client.data.stoptime.StopTimeLocalDataSource
|
||||||
import moe.lava.banksia.model.StopTime
|
import moe.lava.banksia.client.data.stoptime.StopTimeRemoteDataSource
|
||||||
|
import moe.lava.banksia.model.StopTimeDated
|
||||||
|
|
||||||
class StopTimeRepository(
|
class StopTimeRepository(
|
||||||
private val ptv: StopTimePtvDataSource,
|
private val local: StopTimeLocalDataSource,
|
||||||
|
private val remote: StopTimeRemoteDataSource,
|
||||||
) {
|
) {
|
||||||
// TODO
|
suspend fun getForStop(id: String): List<StopTimeDated> {
|
||||||
suspend fun getForStop(id: String): List<StopTime> {
|
return local
|
||||||
return listOf()
|
.getAtStop(id)
|
||||||
|
.ifEmpty { remote.getAtStop(id) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,17 +15,24 @@ import io.ktor.server.routing.routing
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.datetime.LocalDate
|
||||||
|
import kotlinx.datetime.TimeZone
|
||||||
|
import kotlinx.datetime.todayIn
|
||||||
import moe.lava.banksia.Constants
|
import moe.lava.banksia.Constants
|
||||||
import moe.lava.banksia.di.CommonModules
|
import moe.lava.banksia.di.CommonModules
|
||||||
|
import moe.lava.banksia.model.atDate
|
||||||
import moe.lava.banksia.room.dao.RouteDao
|
import moe.lava.banksia.room.dao.RouteDao
|
||||||
import moe.lava.banksia.room.dao.StopDao
|
import moe.lava.banksia.room.dao.StopDao
|
||||||
|
import moe.lava.banksia.room.dao.StopTimeDao
|
||||||
import moe.lava.banksia.room.dao.VersionMetadataDao
|
import moe.lava.banksia.room.dao.VersionMetadataDao
|
||||||
import moe.lava.banksia.server.di.ServerModules
|
import moe.lava.banksia.server.di.ServerModules
|
||||||
import moe.lava.banksia.server.gtfs.GtfsHandler
|
import moe.lava.banksia.server.gtfs.GtfsHandler
|
||||||
import moe.lava.banksia.server.gtfsr.GtfsrService
|
import moe.lava.banksia.server.gtfsr.GtfsrService
|
||||||
|
import moe.lava.banksia.util.serialise
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
import org.koin.ktor.ext.inject
|
import org.koin.ktor.ext.inject
|
||||||
import org.koin.ktor.plugin.Koin
|
import org.koin.ktor.plugin.Koin
|
||||||
|
import kotlin.time.Clock
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module)
|
embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module)
|
||||||
|
|
@ -41,8 +48,11 @@ fun Application.module() {
|
||||||
modules(CommonModules, ServerModules)
|
modules(CommonModules, ServerModules)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("KotlinConstantConditions")
|
||||||
|
if (!Constants.devMode) {
|
||||||
val gtfsr by inject<GtfsrService>()
|
val gtfsr by inject<GtfsrService>()
|
||||||
launch { gtfsr.start() }
|
launch { gtfsr.start() }
|
||||||
|
}
|
||||||
|
|
||||||
routing {
|
routing {
|
||||||
get("/update") {
|
get("/update") {
|
||||||
|
|
@ -137,6 +147,24 @@ fun Application.module() {
|
||||||
// .map { it.asModel() }
|
// .map { it.asModel() }
|
||||||
// }
|
// }
|
||||||
// call.respond(stops)
|
// call.respond(stops)
|
||||||
|
|
||||||
|
}
|
||||||
|
get("/stoptimes/by_stop/{stop_id}") {
|
||||||
|
val stopId = call.parameters["stop_id"]!!
|
||||||
|
val date = call.queryParameters["date"]
|
||||||
|
?.let { LocalDate.parse(it, LocalDate.Formats.ISO) }
|
||||||
|
?: Clock.System.todayIn(TimeZone.currentSystemDefault())
|
||||||
|
val times = withContext(context = Dispatchers.IO) {
|
||||||
|
inject<StopTimeDao>().value
|
||||||
|
.getForStopDated(
|
||||||
|
stopId,
|
||||||
|
listOf(date.dayOfWeek).serialise(),
|
||||||
|
date.toEpochDays().toInt(),
|
||||||
|
)
|
||||||
|
.map { it.asModel().atDate(date) }
|
||||||
|
.sortedBy { it.departureTime }
|
||||||
|
}
|
||||||
|
call.respond(times)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,14 @@ import io.ktor.client.statement.bodyAsChannel
|
||||||
import io.ktor.util.cio.writeChannel
|
import io.ktor.util.cio.writeChannel
|
||||||
import io.ktor.util.logging.Logger
|
import io.ktor.util.logging.Logger
|
||||||
import io.ktor.utils.io.copyAndClose
|
import io.ktor.utils.io.copyAndClose
|
||||||
|
import kotlinx.datetime.DayOfWeek
|
||||||
|
import kotlinx.datetime.LocalDate
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.modules.EmptySerializersModule
|
import kotlinx.serialization.modules.EmptySerializersModule
|
||||||
import kotlinx.serialization.serializer
|
import kotlinx.serialization.serializer
|
||||||
import moe.lava.banksia.Constants
|
import moe.lava.banksia.Constants
|
||||||
import moe.lava.banksia.model.Route
|
import moe.lava.banksia.model.Route
|
||||||
|
import moe.lava.banksia.model.Service
|
||||||
import moe.lava.banksia.model.Shape
|
import moe.lava.banksia.model.Shape
|
||||||
import moe.lava.banksia.model.Stop
|
import moe.lava.banksia.model.Stop
|
||||||
import moe.lava.banksia.model.StopTime
|
import moe.lava.banksia.model.StopTime
|
||||||
|
|
@ -22,6 +25,7 @@ import moe.lava.banksia.room.Database
|
||||||
import moe.lava.banksia.room.converter.RouteTypeConverter
|
import moe.lava.banksia.room.converter.RouteTypeConverter
|
||||||
import moe.lava.banksia.room.entity.asEntity
|
import moe.lava.banksia.room.entity.asEntity
|
||||||
import moe.lava.banksia.server.gtfs.structures.GtfsRoute
|
import moe.lava.banksia.server.gtfs.structures.GtfsRoute
|
||||||
|
import moe.lava.banksia.server.gtfs.structures.GtfsService
|
||||||
import moe.lava.banksia.server.gtfs.structures.GtfsShape
|
import moe.lava.banksia.server.gtfs.structures.GtfsShape
|
||||||
import moe.lava.banksia.server.gtfs.structures.GtfsStop
|
import moe.lava.banksia.server.gtfs.structures.GtfsStop
|
||||||
import moe.lava.banksia.server.gtfs.structures.GtfsStopTime
|
import moe.lava.banksia.server.gtfs.structures.GtfsStopTime
|
||||||
|
|
@ -65,6 +69,7 @@ class GtfsHandler(
|
||||||
.listFiles { it.isDirectory }
|
.listFiles { it.isDirectory }
|
||||||
.flatMap { d -> d.listFiles { f -> f.extension == "txt" }.toList() }
|
.flatMap { d -> d.listFiles { f -> f.extension == "txt" }.toList() }
|
||||||
.ifEmpty { extractAll(datasetPath) }
|
.ifEmpty { extractAll(datasetPath) }
|
||||||
|
.filter { it.parentFile.name == "2" }
|
||||||
} else {
|
} else {
|
||||||
extractAll(datasetPath)
|
extractAll(datasetPath)
|
||||||
}
|
}
|
||||||
|
|
@ -72,8 +77,9 @@ class GtfsHandler(
|
||||||
addRoutes(files)
|
addRoutes(files)
|
||||||
addStops(files)
|
addStops(files)
|
||||||
addShapes(files)
|
addShapes(files)
|
||||||
addTrips(files)
|
val services = addServices(files)
|
||||||
addStopTimes(files)
|
val trips = addTrips(files, services.associateBy { it.id })
|
||||||
|
addStopTimes(files, trips.associateBy { it.id })
|
||||||
|
|
||||||
updateMetadata(date ?: Clock.System.now().epochSeconds)
|
updateMetadata(date ?: Clock.System.now().epochSeconds)
|
||||||
|
|
||||||
|
|
@ -174,7 +180,7 @@ class GtfsHandler(
|
||||||
)
|
)
|
||||||
} }
|
} }
|
||||||
|
|
||||||
private suspend fun addStopTimes(files: List<File>) {
|
private suspend fun addStopTimes(files: List<File>, trips: Map<String, Trip>) {
|
||||||
val dao = db.stopTimeDao
|
val dao = db.stopTimeDao
|
||||||
dao.deleteAll()
|
dao.deleteAll()
|
||||||
log.info("parsing stop times...")
|
log.info("parsing stop times...")
|
||||||
|
|
@ -182,7 +188,7 @@ class GtfsHandler(
|
||||||
.filter { it.name == "stop_times.txt" }
|
.filter { it.name == "stop_times.txt" }
|
||||||
.forEach { fd ->
|
.forEach { fd ->
|
||||||
log.info("parsing stop times for ${fd.parent}...")
|
log.info("parsing stop times for ${fd.parent}...")
|
||||||
parseStopTimes(fd) { seq ->
|
parseStopTimes(fd, trips) { seq ->
|
||||||
seq.chunked(1000000)
|
seq.chunked(1000000)
|
||||||
.forEach { queue ->
|
.forEach { queue ->
|
||||||
log.info("converting stop times (${queue.size}) for ${fd.parent}...")
|
log.info("converting stop times (${queue.size}) for ${fd.parent}...")
|
||||||
|
|
@ -194,7 +200,7 @@ class GtfsHandler(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun parseStopTimes(fd: File, block: (Sequence<StopTime>) -> Unit) =
|
private inline fun parseStopTimes(fd: File, trips: Map<String, Trip>, block: (Sequence<StopTime>) -> Unit) =
|
||||||
fd.parseCsvSequence<GtfsStopTime> { seq ->
|
fd.parseCsvSequence<GtfsStopTime> { seq ->
|
||||||
seq
|
seq
|
||||||
.map { with(it) {
|
.map { with(it) {
|
||||||
|
|
@ -203,7 +209,7 @@ class GtfsHandler(
|
||||||
stopId = stop_id,
|
stopId = stop_id,
|
||||||
arrivalTime = GtfsStopTime.parseGtfsTime(arrival_time),
|
arrivalTime = GtfsStopTime.parseGtfsTime(arrival_time),
|
||||||
departureTime = GtfsStopTime.parseGtfsTime(departure_time),
|
departureTime = GtfsStopTime.parseGtfsTime(departure_time),
|
||||||
headsign = stop_headsign,
|
headsign = stop_headsign.ifEmpty { trips[trip_id]!!.tripHeadsign },
|
||||||
pickupType = pickup_type,
|
pickupType = pickup_type,
|
||||||
dropOffType = drop_off_type,
|
dropOffType = drop_off_type,
|
||||||
)
|
)
|
||||||
|
|
@ -211,25 +217,61 @@ class GtfsHandler(
|
||||||
.let { block(it) }
|
.let { block(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun addTrips(files: List<File>) {
|
private suspend fun addServices(files: List<File>): List<Service> {
|
||||||
|
val dao = db.serviceDao
|
||||||
|
log.info("parsing services...")
|
||||||
|
val services = files
|
||||||
|
.filter { it.name == "calendar.txt" }
|
||||||
|
.flatMap { fd -> parseServices(fd) }
|
||||||
|
|
||||||
|
log.info("inserting services...")
|
||||||
|
dao.deleteAll()
|
||||||
|
dao.insertOrReplaceAll(*services.map { it.asEntity() }.toTypedArray())
|
||||||
|
|
||||||
|
return services
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseServices(fd: File) =
|
||||||
|
fd.parseCsv<GtfsService>()
|
||||||
|
.map { with(it) {
|
||||||
|
val days = buildList {
|
||||||
|
if (monday == 1) add(DayOfWeek.MONDAY)
|
||||||
|
if (tuesday == 1) add(DayOfWeek.TUESDAY)
|
||||||
|
if (wednesday == 1) add(DayOfWeek.WEDNESDAY)
|
||||||
|
if (thursday == 1) add(DayOfWeek.THURSDAY)
|
||||||
|
if (friday == 1) add(DayOfWeek.FRIDAY)
|
||||||
|
if (saturday == 1) add(DayOfWeek.SATURDAY)
|
||||||
|
if (sunday == 1) add(DayOfWeek.SUNDAY)
|
||||||
|
}
|
||||||
|
Service(
|
||||||
|
id = service_id,
|
||||||
|
days = days,
|
||||||
|
start = LocalDate.parse(start_date, LocalDate.Formats.ISO_BASIC),
|
||||||
|
end = LocalDate.parse(end_date, LocalDate.Formats.ISO_BASIC),
|
||||||
|
)
|
||||||
|
} }
|
||||||
|
|
||||||
|
private suspend fun addTrips(files: List<File>, services: Map<String, Service>): List<Trip> {
|
||||||
val dao = db.tripDao
|
val dao = db.tripDao
|
||||||
log.info("parsing trips...")
|
log.info("parsing trips...")
|
||||||
val trips = files
|
val trips = files
|
||||||
.filter { it.name == "trips.txt" }
|
.filter { it.name == "trips.txt" }
|
||||||
.flatMap { fd -> parseTrips(fd) }
|
.flatMap { fd -> parseTrips(fd, services) }
|
||||||
|
|
||||||
log.info("inserting trips...")
|
log.info("inserting trips...")
|
||||||
dao.deleteAll()
|
dao.deleteAll()
|
||||||
dao.insertOrReplaceAll(*trips.map { it.asEntity() }.toTypedArray())
|
dao.insertOrReplaceAll(*trips.map { it.asEntity() }.toTypedArray())
|
||||||
|
|
||||||
|
return trips
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseTrips(fd: File) =
|
private fun parseTrips(fd: File, services: Map<String, Service>) =
|
||||||
fd.parseCsv<GtfsTrip>()
|
fd.parseCsv<GtfsTrip>()
|
||||||
.map { with(it) {
|
.map { with(it) {
|
||||||
Trip(
|
Trip(
|
||||||
id = trip_id,
|
id = trip_id,
|
||||||
routeId = route_id,
|
routeId = route_id,
|
||||||
serviceId = service_id,
|
service = services[service_id]!!,
|
||||||
shapeId = shape_id.ifEmpty { null },
|
shapeId = shape_id.ifEmpty { null },
|
||||||
tripHeadsign = trip_headsign,
|
tripHeadsign = trip_headsign,
|
||||||
directionId = direction_id,
|
directionId = direction_id,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package moe.lava.banksia.server.gtfs.structures
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Suppress("PropertyName")
|
||||||
|
@Serializable
|
||||||
|
data class GtfsService(
|
||||||
|
val service_id: String,
|
||||||
|
val monday: Int,
|
||||||
|
val tuesday: Int,
|
||||||
|
val wednesday: Int,
|
||||||
|
val thursday: Int,
|
||||||
|
val friday: Int,
|
||||||
|
val saturday: Int,
|
||||||
|
val sunday: Int,
|
||||||
|
val start_date: String,
|
||||||
|
val end_date: String,
|
||||||
|
)
|
||||||
415
shared/schemas/moe.lava.banksia.room.Database/7.json
Normal file
415
shared/schemas/moe.lava.banksia.room.Database/7.json
Normal file
|
|
@ -0,0 +1,415 @@
|
||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 7,
|
||||||
|
"identityHash": "15c94df0a62438ff28d451c074c94c59",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "Route",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `type` INTEGER NOT NULL, `number` TEXT, `name` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "number",
|
||||||
|
"columnName": "number",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Service",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `days` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "days",
|
||||||
|
"columnName": "days",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "start",
|
||||||
|
"columnName": "start",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "end",
|
||||||
|
"columnName": "end",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Service_days",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"days"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Service_days` ON `${TABLE_NAME}` (`days`)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Shape",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `path` BLOB NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "path",
|
||||||
|
"columnName": "path",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Stop",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `lat` REAL NOT NULL, `lng` REAL NOT NULL, `parent` TEXT NOT NULL, `hasWheelChairBoarding` INTEGER NOT NULL, `level` TEXT NOT NULL, `platformCode` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lat",
|
||||||
|
"columnName": "lat",
|
||||||
|
"affinity": "REAL",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lng",
|
||||||
|
"columnName": "lng",
|
||||||
|
"affinity": "REAL",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "parent",
|
||||||
|
"columnName": "parent",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasWheelChairBoarding",
|
||||||
|
"columnName": "hasWheelChairBoarding",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "level",
|
||||||
|
"columnName": "level",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "platformCode",
|
||||||
|
"columnName": "platformCode",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Stop_parent",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"parent"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Stop_parent` ON `${TABLE_NAME}` (`parent`)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "StopTime",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tripId` TEXT NOT NULL, `stopId` TEXT NOT NULL, `arrivalTime` INTEGER NOT NULL, `departureTime` INTEGER NOT NULL, `headsign` TEXT, `pickupType` INTEGER NOT NULL, `dropOffType` INTEGER NOT NULL, PRIMARY KEY(`tripId`, `stopId`), FOREIGN KEY(`tripId`) REFERENCES `Trip`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`stopId`) REFERENCES `Stop`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "tripId",
|
||||||
|
"columnName": "tripId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "stopId",
|
||||||
|
"columnName": "stopId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "arrivalTime",
|
||||||
|
"columnName": "arrivalTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "departureTime",
|
||||||
|
"columnName": "departureTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "headsign",
|
||||||
|
"columnName": "headsign",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "pickupType",
|
||||||
|
"columnName": "pickupType",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "dropOffType",
|
||||||
|
"columnName": "dropOffType",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"tripId",
|
||||||
|
"stopId"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_StopTime_tripId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"tripId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_StopTime_tripId` ON `${TABLE_NAME}` (`tripId`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_StopTime_stopId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"stopId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_StopTime_stopId` ON `${TABLE_NAME}` (`stopId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "Trip",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"tripId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "Stop",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"stopId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Trip",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `routeId` TEXT NOT NULL, `serviceId` TEXT NOT NULL, `shapeId` TEXT, `tripHeadsign` TEXT NOT NULL, `directionId` TEXT NOT NULL, `blockId` TEXT NOT NULL, `wheelchairAccessible` TEXT NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`routeId`) REFERENCES `Route`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`shapeId`) REFERENCES `Shape`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "routeId",
|
||||||
|
"columnName": "routeId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serviceId",
|
||||||
|
"columnName": "serviceId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "shapeId",
|
||||||
|
"columnName": "shapeId",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "tripHeadsign",
|
||||||
|
"columnName": "tripHeadsign",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "directionId",
|
||||||
|
"columnName": "directionId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "blockId",
|
||||||
|
"columnName": "blockId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "wheelchairAccessible",
|
||||||
|
"columnName": "wheelchairAccessible",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Trip_shapeId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"shapeId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Trip_shapeId` ON `${TABLE_NAME}` (`shapeId`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_Trip_routeId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"routeId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Trip_routeId` ON `${TABLE_NAME}` (`routeId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "Route",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"routeId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "Shape",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"shapeId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "VersionMetadata",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`type` TEXT NOT NULL, `lastUpdated` INTEGER NOT NULL, PRIMARY KEY(`type`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastUpdated",
|
||||||
|
"columnName": "lastUpdated",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"type"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '15c94df0a62438ff28d451c074c94c59')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
426
shared/schemas/moe.lava.banksia.room.Database/8.json
Normal file
426
shared/schemas/moe.lava.banksia.room.Database/8.json
Normal file
|
|
@ -0,0 +1,426 @@
|
||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 8,
|
||||||
|
"identityHash": "6e0f07bf1af88b2e37b5ad7c38a3fb2a",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "Route",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `type` INTEGER NOT NULL, `number` TEXT, `name` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "number",
|
||||||
|
"columnName": "number",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Service",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `days` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "days",
|
||||||
|
"columnName": "days",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "start",
|
||||||
|
"columnName": "start",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "end",
|
||||||
|
"columnName": "end",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Service_days",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"days"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Service_days` ON `${TABLE_NAME}` (`days`)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Shape",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `path` BLOB NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "path",
|
||||||
|
"columnName": "path",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Stop",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `lat` REAL NOT NULL, `lng` REAL NOT NULL, `parent` TEXT NOT NULL, `hasWheelChairBoarding` INTEGER NOT NULL, `level` TEXT NOT NULL, `platformCode` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lat",
|
||||||
|
"columnName": "lat",
|
||||||
|
"affinity": "REAL",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lng",
|
||||||
|
"columnName": "lng",
|
||||||
|
"affinity": "REAL",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "parent",
|
||||||
|
"columnName": "parent",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasWheelChairBoarding",
|
||||||
|
"columnName": "hasWheelChairBoarding",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "level",
|
||||||
|
"columnName": "level",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "platformCode",
|
||||||
|
"columnName": "platformCode",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Stop_parent",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"parent"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Stop_parent` ON `${TABLE_NAME}` (`parent`)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "StopTime",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tripId` TEXT NOT NULL, `stopId` TEXT NOT NULL, `arrivalTime` INTEGER NOT NULL, `departureTime` INTEGER NOT NULL, `headsign` TEXT, `pickupType` INTEGER NOT NULL, `dropOffType` INTEGER NOT NULL, PRIMARY KEY(`tripId`, `stopId`), FOREIGN KEY(`tripId`) REFERENCES `Trip`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`stopId`) REFERENCES `Stop`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "tripId",
|
||||||
|
"columnName": "tripId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "stopId",
|
||||||
|
"columnName": "stopId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "arrivalTime",
|
||||||
|
"columnName": "arrivalTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "departureTime",
|
||||||
|
"columnName": "departureTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "headsign",
|
||||||
|
"columnName": "headsign",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "pickupType",
|
||||||
|
"columnName": "pickupType",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "dropOffType",
|
||||||
|
"columnName": "dropOffType",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"tripId",
|
||||||
|
"stopId"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_StopTime_tripId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"tripId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_StopTime_tripId` ON `${TABLE_NAME}` (`tripId`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_StopTime_stopId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"stopId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_StopTime_stopId` ON `${TABLE_NAME}` (`stopId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "Trip",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"tripId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "Stop",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"stopId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Trip",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `routeId` TEXT NOT NULL, `serviceId` TEXT NOT NULL, `shapeId` TEXT, `tripHeadsign` TEXT NOT NULL, `directionId` TEXT NOT NULL, `blockId` TEXT NOT NULL, `wheelchairAccessible` TEXT NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`routeId`) REFERENCES `Route`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`serviceId`) REFERENCES `Service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`shapeId`) REFERENCES `Shape`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "routeId",
|
||||||
|
"columnName": "routeId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serviceId",
|
||||||
|
"columnName": "serviceId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "shapeId",
|
||||||
|
"columnName": "shapeId",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "tripHeadsign",
|
||||||
|
"columnName": "tripHeadsign",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "directionId",
|
||||||
|
"columnName": "directionId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "blockId",
|
||||||
|
"columnName": "blockId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "wheelchairAccessible",
|
||||||
|
"columnName": "wheelchairAccessible",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Trip_shapeId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"shapeId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Trip_shapeId` ON `${TABLE_NAME}` (`shapeId`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_Trip_routeId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"routeId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Trip_routeId` ON `${TABLE_NAME}` (`routeId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "Route",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"routeId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "Service",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"serviceId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "Shape",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"shapeId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "VersionMetadata",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`type` TEXT NOT NULL, `lastUpdated` INTEGER NOT NULL, PRIMARY KEY(`type`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastUpdated",
|
||||||
|
"columnName": "lastUpdated",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"type"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6e0f07bf1af88b2e37b5ad7c38a3fb2a')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
426
shared/schemas/moe.lava.banksia.room.Database/9.json
Normal file
426
shared/schemas/moe.lava.banksia.room.Database/9.json
Normal file
|
|
@ -0,0 +1,426 @@
|
||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 9,
|
||||||
|
"identityHash": "6e0f07bf1af88b2e37b5ad7c38a3fb2a",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "Route",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `type` INTEGER NOT NULL, `number` TEXT, `name` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "number",
|
||||||
|
"columnName": "number",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Service",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `days` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "days",
|
||||||
|
"columnName": "days",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "start",
|
||||||
|
"columnName": "start",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "end",
|
||||||
|
"columnName": "end",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Service_days",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"days"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Service_days` ON `${TABLE_NAME}` (`days`)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Shape",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `path` BLOB NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "path",
|
||||||
|
"columnName": "path",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Stop",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `lat` REAL NOT NULL, `lng` REAL NOT NULL, `parent` TEXT NOT NULL, `hasWheelChairBoarding` INTEGER NOT NULL, `level` TEXT NOT NULL, `platformCode` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lat",
|
||||||
|
"columnName": "lat",
|
||||||
|
"affinity": "REAL",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lng",
|
||||||
|
"columnName": "lng",
|
||||||
|
"affinity": "REAL",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "parent",
|
||||||
|
"columnName": "parent",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hasWheelChairBoarding",
|
||||||
|
"columnName": "hasWheelChairBoarding",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "level",
|
||||||
|
"columnName": "level",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "platformCode",
|
||||||
|
"columnName": "platformCode",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Stop_parent",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"parent"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Stop_parent` ON `${TABLE_NAME}` (`parent`)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "StopTime",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tripId` TEXT NOT NULL, `stopId` TEXT NOT NULL, `arrivalTime` INTEGER NOT NULL, `departureTime` INTEGER NOT NULL, `headsign` TEXT, `pickupType` INTEGER NOT NULL, `dropOffType` INTEGER NOT NULL, PRIMARY KEY(`tripId`, `stopId`), FOREIGN KEY(`tripId`) REFERENCES `Trip`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`stopId`) REFERENCES `Stop`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "tripId",
|
||||||
|
"columnName": "tripId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "stopId",
|
||||||
|
"columnName": "stopId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "arrivalTime",
|
||||||
|
"columnName": "arrivalTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "departureTime",
|
||||||
|
"columnName": "departureTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "headsign",
|
||||||
|
"columnName": "headsign",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "pickupType",
|
||||||
|
"columnName": "pickupType",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "dropOffType",
|
||||||
|
"columnName": "dropOffType",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"tripId",
|
||||||
|
"stopId"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_StopTime_tripId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"tripId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_StopTime_tripId` ON `${TABLE_NAME}` (`tripId`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_StopTime_stopId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"stopId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_StopTime_stopId` ON `${TABLE_NAME}` (`stopId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "Trip",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"tripId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "Stop",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"stopId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Trip",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `routeId` TEXT NOT NULL, `serviceId` TEXT NOT NULL, `shapeId` TEXT, `tripHeadsign` TEXT NOT NULL, `directionId` TEXT NOT NULL, `blockId` TEXT NOT NULL, `wheelchairAccessible` TEXT NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`routeId`) REFERENCES `Route`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`serviceId`) REFERENCES `Service`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`shapeId`) REFERENCES `Shape`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "routeId",
|
||||||
|
"columnName": "routeId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "serviceId",
|
||||||
|
"columnName": "serviceId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "shapeId",
|
||||||
|
"columnName": "shapeId",
|
||||||
|
"affinity": "TEXT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "tripHeadsign",
|
||||||
|
"columnName": "tripHeadsign",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "directionId",
|
||||||
|
"columnName": "directionId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "blockId",
|
||||||
|
"columnName": "blockId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "wheelchairAccessible",
|
||||||
|
"columnName": "wheelchairAccessible",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_Trip_shapeId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"shapeId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Trip_shapeId` ON `${TABLE_NAME}` (`shapeId`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_Trip_routeId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"routeId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_Trip_routeId` ON `${TABLE_NAME}` (`routeId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "Route",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"routeId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "Service",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"serviceId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"table": "Shape",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"shapeId"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "VersionMetadata",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`type` TEXT NOT NULL, `lastUpdated` INTEGER NOT NULL, PRIMARY KEY(`type`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "lastUpdated",
|
||||||
|
"columnName": "lastUpdated",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": false,
|
||||||
|
"columnNames": [
|
||||||
|
"type"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6e0f07bf1af88b2e37b5ad7c38a3fb2a')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,6 +9,7 @@ val CommonModules = module {
|
||||||
single { Database.build(get<PlatformDatabaseBuilder>().getBuilder()) }
|
single { Database.build(get<PlatformDatabaseBuilder>().getBuilder()) }
|
||||||
single { get<Database>().versionMetadataDao }
|
single { get<Database>().versionMetadataDao }
|
||||||
single { get<Database>().routeDao }
|
single { get<Database>().routeDao }
|
||||||
|
single { get<Database>().serviceDao }
|
||||||
single { get<Database>().shapeDao }
|
single { get<Database>().shapeDao }
|
||||||
single { get<Database>().stopDao }
|
single { get<Database>().stopDao }
|
||||||
single { get<Database>().stopTimeDao }
|
single { get<Database>().stopTimeDao }
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
package moe.lava.banksia.model
|
package moe.lava.banksia.model
|
||||||
|
|
||||||
|
import kotlinx.datetime.DateTimeUnit
|
||||||
|
import kotlinx.datetime.LocalDate
|
||||||
import kotlinx.datetime.LocalTime
|
import kotlinx.datetime.LocalTime
|
||||||
|
import kotlinx.datetime.atTime
|
||||||
|
import kotlinx.datetime.plus
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.descriptors.PrimitiveKind
|
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||||
|
|
@ -39,6 +43,10 @@ data class FutureTime(
|
||||||
val minute = time.minute
|
val minute = time.minute
|
||||||
val second = time.second
|
val second = time.second
|
||||||
val trueHour = time.hour + (if (dayOffset) 24 else 0)
|
val trueHour = time.hour + (if (dayOffset) 24 else 0)
|
||||||
|
|
||||||
|
fun atDate(date: LocalDate) = date
|
||||||
|
.let { if (dayOffset) date.plus(1, DateTimeUnit.DAY) else date }
|
||||||
|
.atTime(time)
|
||||||
}
|
}
|
||||||
|
|
||||||
object FutureTimeSerialiser: KSerializer<FutureTime> {
|
object FutureTimeSerialiser: KSerializer<FutureTime> {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package moe.lava.banksia.model
|
||||||
|
|
||||||
|
import kotlinx.datetime.LocalDate
|
||||||
|
import kotlinx.datetime.LocalDateTime
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class StopTimeDated(
|
||||||
|
val tripId: String,
|
||||||
|
val stopId: String,
|
||||||
|
val arrivalTime: LocalDateTime,
|
||||||
|
val departureTime: LocalDateTime,
|
||||||
|
val headsign: String?,
|
||||||
|
val pickupType: Int,
|
||||||
|
val dropOffType: Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun StopTime.atDate(date: LocalDate) = StopTimeDated(
|
||||||
|
tripId = tripId,
|
||||||
|
stopId = stopId,
|
||||||
|
arrivalTime = arrivalTime.atDate(date),
|
||||||
|
departureTime = departureTime.atDate(date),
|
||||||
|
headsign = headsign,
|
||||||
|
pickupType = pickupType,
|
||||||
|
dropOffType = dropOffType,
|
||||||
|
)
|
||||||
|
|
@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable
|
||||||
data class Trip(
|
data class Trip(
|
||||||
val id: String,
|
val id: String,
|
||||||
val routeId: String,
|
val routeId: String,
|
||||||
val serviceId: String,
|
val service: Service,
|
||||||
val shapeId: String?,
|
val shapeId: String?,
|
||||||
val tripHeadsign: String,
|
val tripHeadsign: String,
|
||||||
val directionId: String,
|
val directionId: String,
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,14 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.IO
|
import kotlinx.coroutines.IO
|
||||||
import moe.lava.banksia.room.converter.RouteTypeConverter
|
import moe.lava.banksia.room.converter.RouteTypeConverter
|
||||||
import moe.lava.banksia.room.dao.RouteDao
|
import moe.lava.banksia.room.dao.RouteDao
|
||||||
|
import moe.lava.banksia.room.dao.ServiceDao
|
||||||
import moe.lava.banksia.room.dao.ShapeDao
|
import moe.lava.banksia.room.dao.ShapeDao
|
||||||
import moe.lava.banksia.room.dao.StopDao
|
import moe.lava.banksia.room.dao.StopDao
|
||||||
import moe.lava.banksia.room.dao.StopTimeDao
|
import moe.lava.banksia.room.dao.StopTimeDao
|
||||||
import moe.lava.banksia.room.dao.TripDao
|
import moe.lava.banksia.room.dao.TripDao
|
||||||
import moe.lava.banksia.room.dao.VersionMetadataDao
|
import moe.lava.banksia.room.dao.VersionMetadataDao
|
||||||
import moe.lava.banksia.room.entity.RouteEntity
|
import moe.lava.banksia.room.entity.RouteEntity
|
||||||
|
import moe.lava.banksia.room.entity.ServiceEntity
|
||||||
import moe.lava.banksia.room.entity.ShapeEntity
|
import moe.lava.banksia.room.entity.ShapeEntity
|
||||||
import moe.lava.banksia.room.entity.StopEntity
|
import moe.lava.banksia.room.entity.StopEntity
|
||||||
import moe.lava.banksia.room.entity.StopTimeEntity
|
import moe.lava.banksia.room.entity.StopTimeEntity
|
||||||
|
|
@ -22,9 +24,10 @@ import moe.lava.banksia.room.entity.VersionMetadataEntity
|
||||||
import androidx.room.Database as DatabaseAnnotation
|
import androidx.room.Database as DatabaseAnnotation
|
||||||
|
|
||||||
@DatabaseAnnotation(
|
@DatabaseAnnotation(
|
||||||
version = 6,
|
version = 9,
|
||||||
entities = [
|
entities = [
|
||||||
RouteEntity::class,
|
RouteEntity::class,
|
||||||
|
ServiceEntity::class,
|
||||||
ShapeEntity::class,
|
ShapeEntity::class,
|
||||||
StopEntity::class,
|
StopEntity::class,
|
||||||
StopTimeEntity::class,
|
StopTimeEntity::class,
|
||||||
|
|
@ -40,6 +43,7 @@ import androidx.room.Database as DatabaseAnnotation
|
||||||
abstract class Database : RoomDatabase() {
|
abstract class Database : RoomDatabase() {
|
||||||
abstract val versionMetadataDao: VersionMetadataDao
|
abstract val versionMetadataDao: VersionMetadataDao
|
||||||
abstract val routeDao: RouteDao
|
abstract val routeDao: RouteDao
|
||||||
|
abstract val serviceDao: ServiceDao
|
||||||
abstract val shapeDao: ShapeDao
|
abstract val shapeDao: ShapeDao
|
||||||
abstract val stopDao: StopDao
|
abstract val stopDao: StopDao
|
||||||
abstract val stopTimeDao: StopTimeDao
|
abstract val stopTimeDao: StopTimeDao
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package moe.lava.banksia.room.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy.Companion.REPLACE
|
||||||
|
import androidx.room.Query
|
||||||
|
import moe.lava.banksia.room.entity.ServiceEntity
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface ServiceDao {
|
||||||
|
@Query("SELECT * FROM Service")
|
||||||
|
suspend fun getAll(): List<ServiceEntity>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Service WHERE id == :id")
|
||||||
|
suspend fun get(id: String): ServiceEntity?
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
suspend fun insertAll(vararg services: ServiceEntity)
|
||||||
|
|
||||||
|
@Insert(onConflict = REPLACE)
|
||||||
|
suspend fun insertOrReplaceAll(vararg services: ServiceEntity)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(service: ServiceEntity)
|
||||||
|
|
||||||
|
@Query("DELETE FROM Service")
|
||||||
|
suspend fun deleteAll()
|
||||||
|
}
|
||||||
|
|
@ -13,10 +13,22 @@ interface StopTimeDao {
|
||||||
suspend fun getAll(): List<StopTimeEntity>
|
suspend fun getAll(): List<StopTimeEntity>
|
||||||
|
|
||||||
@Query("SELECT * FROM StopTime WHERE tripId == :tripId")
|
@Query("SELECT * FROM StopTime WHERE tripId == :tripId")
|
||||||
suspend fun get(tripId: String): StopTimeEntity?
|
suspend fun getForTrip(tripId: String): StopTimeEntity?
|
||||||
|
|
||||||
@Query("SELECT * FROM StopTime WHERE tripId IN (:tripIds)")
|
@Query("SELECT * FROM StopTime WHERE tripId IN (:tripIds)")
|
||||||
suspend fun get(tripIds: List<String>): List<StopTimeEntity>
|
suspend fun getForTrips(tripIds: List<String>): List<StopTimeEntity>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM StopTime WHERE stopId == :stopId")
|
||||||
|
suspend fun getForStop(stopId: String): List<StopTimeEntity>
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT * FROM StopTime
|
||||||
|
INNER JOIN Service ON Service.days & :days = :days AND :date BETWEEN Service.start AND Service.`end`
|
||||||
|
INNER JOIN Trip ON Trip.serviceId == Service.id
|
||||||
|
WHERE StopTime.tripId == Trip.id
|
||||||
|
AND StopTime.stopId == :stopId
|
||||||
|
""")
|
||||||
|
suspend fun getForStopDated(stopId: String, days: Int, date: Int): List<StopTimeEntity>
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
suspend fun insertAll(vararg stopTimes: StopTimeEntity)
|
suspend fun insertAll(vararg stopTimes: StopTimeEntity)
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,23 @@
|
||||||
package moe.lava.banksia.room.entity
|
package moe.lava.banksia.room.entity
|
||||||
|
|
||||||
import kotlinx.datetime.DayOfWeek
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
import kotlinx.datetime.LocalDate
|
import kotlinx.datetime.LocalDate
|
||||||
import moe.lava.banksia.model.Service
|
import moe.lava.banksia.model.Service
|
||||||
|
import moe.lava.banksia.util.deserialiseDaysBitflag
|
||||||
|
import moe.lava.banksia.util.serialise
|
||||||
|
|
||||||
|
@Entity("Service")
|
||||||
data class ServiceEntity(
|
data class ServiceEntity(
|
||||||
val id: String,
|
@PrimaryKey val id: String,
|
||||||
val days: Int,
|
@ColumnInfo(index = true) val days: Int,
|
||||||
val start: Int,
|
val start: Int,
|
||||||
val end: Int,
|
val end: Int,
|
||||||
) {
|
) {
|
||||||
object Parser {
|
|
||||||
private fun Int.check(other: Int) = (this and other) != 0
|
|
||||||
|
|
||||||
fun deserialiseDays(days: Int): List<DayOfWeek> = buildList {
|
|
||||||
if (days.check(1))
|
|
||||||
add(DayOfWeek.MONDAY)
|
|
||||||
if (days.check(1 shl 1))
|
|
||||||
add(DayOfWeek.TUESDAY)
|
|
||||||
if (days.check(1 shl 2))
|
|
||||||
add(DayOfWeek.WEDNESDAY)
|
|
||||||
if (days.check(1 shl 3))
|
|
||||||
add(DayOfWeek.THURSDAY)
|
|
||||||
if (days.check(1 shl 4))
|
|
||||||
add(DayOfWeek.FRIDAY)
|
|
||||||
if (days.check(1 shl 5))
|
|
||||||
add(DayOfWeek.SATURDAY)
|
|
||||||
if (days.check(1 shl 6))
|
|
||||||
add(DayOfWeek.SUNDAY)
|
|
||||||
}
|
|
||||||
fun serialiseDays(days: List<DayOfWeek>): Int =
|
|
||||||
days.fold(0) { vl, n ->
|
|
||||||
vl + when (n) {
|
|
||||||
DayOfWeek.MONDAY -> 1
|
|
||||||
DayOfWeek.TUESDAY -> 1 shl 1
|
|
||||||
DayOfWeek.WEDNESDAY -> 1 shl 2
|
|
||||||
DayOfWeek.THURSDAY -> 1 shl 3
|
|
||||||
DayOfWeek.FRIDAY -> 1 shl 4
|
|
||||||
DayOfWeek.SATURDAY -> 1 shl 5
|
|
||||||
DayOfWeek.SUNDAY -> 1 shl 6
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun asModel() = Service(
|
fun asModel() = Service(
|
||||||
id,
|
id,
|
||||||
Parser.deserialiseDays(days),
|
days.deserialiseDaysBitflag(),
|
||||||
LocalDate.fromEpochDays(start),
|
LocalDate.fromEpochDays(start),
|
||||||
LocalDate.fromEpochDays(end),
|
LocalDate.fromEpochDays(end),
|
||||||
)
|
)
|
||||||
|
|
@ -52,7 +25,7 @@ data class ServiceEntity(
|
||||||
|
|
||||||
fun Service.asEntity() = ServiceEntity(
|
fun Service.asEntity() = ServiceEntity(
|
||||||
id,
|
id,
|
||||||
ServiceEntity.Parser.serialiseDays(days),
|
days.serialise(),
|
||||||
start.toEpochDays().toInt(),
|
start.toEpochDays().toInt(),
|
||||||
end.toEpochDays().toInt(),
|
end.toEpochDays().toInt(),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import moe.lava.banksia.model.Trip
|
||||||
"Trip",
|
"Trip",
|
||||||
foreignKeys = [
|
foreignKeys = [
|
||||||
ForeignKey(RouteEntity::class, parentColumns = ["id"], childColumns = ["routeId"], onDelete = CASCADE),
|
ForeignKey(RouteEntity::class, parentColumns = ["id"], childColumns = ["routeId"], onDelete = CASCADE),
|
||||||
|
ForeignKey(ServiceEntity::class, parentColumns = ["id"], childColumns = ["serviceId"], onDelete = CASCADE),
|
||||||
ForeignKey(ShapeEntity::class, parentColumns = ["id"], childColumns = ["shapeId"], onDelete = CASCADE),
|
ForeignKey(ShapeEntity::class, parentColumns = ["id"], childColumns = ["shapeId"], onDelete = CASCADE),
|
||||||
],
|
],
|
||||||
indices = [Index("shapeId")],
|
indices = [Index("shapeId")],
|
||||||
|
|
@ -25,8 +26,24 @@ data class TripEntity(
|
||||||
val directionId: String,
|
val directionId: String,
|
||||||
val blockId: String,
|
val blockId: String,
|
||||||
val wheelchairAccessible: String,
|
val wheelchairAccessible: String,
|
||||||
) {
|
)
|
||||||
fun asModel() = Trip(id, routeId, serviceId, shapeId, tripHeadsign, directionId, blockId, wheelchairAccessible)
|
|
||||||
|
fun Trip.Companion.from(tripEntity: TripEntity, serviceEntity: ServiceEntity): Trip {
|
||||||
|
if (tripEntity.serviceId != serviceEntity.id) {
|
||||||
|
throw IllegalArgumentException("trip and service id mismatch (${tripEntity.serviceId} != ${serviceEntity.id})")
|
||||||
|
}
|
||||||
|
return with(tripEntity) {
|
||||||
|
Trip(
|
||||||
|
id = id,
|
||||||
|
routeId = routeId,
|
||||||
|
service = serviceEntity.asModel(),
|
||||||
|
shapeId = shapeId,
|
||||||
|
tripHeadsign = tripHeadsign,
|
||||||
|
directionId = directionId,
|
||||||
|
blockId = blockId,
|
||||||
|
wheelchairAccessible = wheelchairAccessible
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Trip.asEntity() = TripEntity(id, routeId, serviceId, shapeId, tripHeadsign, directionId, blockId, wheelchairAccessible)
|
fun Trip.asEntity() = TripEntity(id, routeId, service.id, shapeId, tripHeadsign, directionId, blockId, wheelchairAccessible)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
package moe.lava.banksia.util
|
||||||
|
|
||||||
|
import kotlinx.datetime.DayOfWeek
|
||||||
|
|
||||||
|
private fun Int.check(other: Int) = (this and other) != 0
|
||||||
|
|
||||||
|
fun Int.deserialiseDaysBitflag(): List<DayOfWeek> = buildList {
|
||||||
|
val days = this@deserialiseDaysBitflag
|
||||||
|
if (days.check(1))
|
||||||
|
add(DayOfWeek.MONDAY)
|
||||||
|
if (days.check(1 shl 1))
|
||||||
|
add(DayOfWeek.TUESDAY)
|
||||||
|
if (days.check(1 shl 2))
|
||||||
|
add(DayOfWeek.WEDNESDAY)
|
||||||
|
if (days.check(1 shl 3))
|
||||||
|
add(DayOfWeek.THURSDAY)
|
||||||
|
if (days.check(1 shl 4))
|
||||||
|
add(DayOfWeek.FRIDAY)
|
||||||
|
if (days.check(1 shl 5))
|
||||||
|
add(DayOfWeek.SATURDAY)
|
||||||
|
if (days.check(1 shl 6))
|
||||||
|
add(DayOfWeek.SUNDAY)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun List<DayOfWeek>.serialise(): Int =
|
||||||
|
this.fold(0) { vl, n ->
|
||||||
|
vl + when (n) {
|
||||||
|
DayOfWeek.MONDAY -> 1
|
||||||
|
DayOfWeek.TUESDAY -> 1 shl 1
|
||||||
|
DayOfWeek.WEDNESDAY -> 1 shl 2
|
||||||
|
DayOfWeek.THURSDAY -> 1 shl 3
|
||||||
|
DayOfWeek.FRIDAY -> 1 shl 4
|
||||||
|
DayOfWeek.SATURDAY -> 1 shl 5
|
||||||
|
DayOfWeek.SUNDAY -> 1 shl 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,8 @@ import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.takeWhile
|
import kotlinx.coroutines.flow.takeWhile
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.datetime.TimeZone
|
||||||
|
import kotlinx.datetime.toInstant
|
||||||
import moe.lava.banksia.client.repository.RouteRepository
|
import moe.lava.banksia.client.repository.RouteRepository
|
||||||
import moe.lava.banksia.client.repository.StopRepository
|
import moe.lava.banksia.client.repository.StopRepository
|
||||||
import moe.lava.banksia.client.repository.StopTimeRepository
|
import moe.lava.banksia.client.repository.StopTimeRepository
|
||||||
|
|
@ -30,6 +32,8 @@ import moe.lava.banksia.util.BoxedValue.Companion.box
|
||||||
import moe.lava.banksia.util.LoopFlow.Companion.waitUntilSubscribed
|
import moe.lava.banksia.util.LoopFlow.Companion.waitUntilSubscribed
|
||||||
import moe.lava.banksia.util.Point
|
import moe.lava.banksia.util.Point
|
||||||
import moe.lava.banksia.util.log
|
import moe.lava.banksia.util.log
|
||||||
|
import kotlin.time.Clock
|
||||||
|
import kotlin.time.Duration.Companion.minutes
|
||||||
|
|
||||||
sealed class MapScreenEvent {
|
sealed class MapScreenEvent {
|
||||||
data object DismissState : MapScreenEvent()
|
data object DismissState : MapScreenEvent()
|
||||||
|
|
@ -223,28 +227,22 @@ class MapScreenViewModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
val departures = stopTimeRepository.getForStop(id)
|
val departures = stopTimeRepository.getForStop(id)
|
||||||
.filter { it.headsign != null }
|
.filter { !it.headsign.isNullOrBlank() }
|
||||||
.groupBy { it.headsign!! }
|
.groupBy { it.headsign!! }
|
||||||
.map { (headsign, stopTimes) ->
|
.map { (headsign, stopTimes) ->
|
||||||
InfoPanelState.Stop.Departure(headsign, "...")
|
val now = Clock.System.now()
|
||||||
// TODO
|
val times = stopTimes
|
||||||
// val tmsF = stopTimes.map { time ->
|
.map { it.arrivalTime.toInstant(TimeZone.currentSystemDefault()) }
|
||||||
// val key = Pair(dep.directionId, dep.routeId)
|
.filter { it >= (now - 1.minutes) }
|
||||||
// val direction = ptvService.direction(dep.directionId, dep.routeId)
|
.joinToString(" | ") {
|
||||||
// val route = res.routes[dep.routeId.toString()]
|
val diff = (it - now).inWholeMinutes.coerceAtLeast(0)
|
||||||
// val prefix = route?.let { if (it.routeNumber == "") "" else "${it.routeNumber} - " } ?: ""
|
if (diff >= 65) {
|
||||||
// val element = timetable.getOrPut(key) { Pair(prefix + direction.directionName, mutableListOf()) }.second
|
"${((diff + 30.0) / 60.0).toInt()}hr"
|
||||||
// if (element.size >= 5)
|
} else {
|
||||||
// return@forEach
|
"${diff}mn"
|
||||||
//
|
}
|
||||||
// val min = (time.departureTime.time - Clock.System.now()).inWholeMinutes
|
}
|
||||||
// if (min <= -5)
|
InfoPanelState.Stop.Departure(headsign, times)
|
||||||
// return@forEach
|
|
||||||
// if (min >= 65)
|
|
||||||
// element.add("${((min + 30.0) / 60.0).toInt()}hr")
|
|
||||||
// else
|
|
||||||
// element.add("${min}mn")
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
iInfoState.update {
|
iInfoState.update {
|
||||||
if (it !is InfoPanelState.Stop)
|
if (it !is InfoPanelState.Stop)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue