Compare commits
7 commits
4cdb9a305c
...
415ce8d88f
| Author | SHA1 | Date | |
|---|---|---|---|
| 415ce8d88f | |||
| 29a804b0fb | |||
| 27f2a08d77 | |||
| 38bcdc54bc | |||
| 0524eda5d2 | |||
| 959b022cf9 | |||
| e7caeca356 |
35 changed files with 344 additions and 217 deletions
|
|
@ -2,9 +2,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.kotlinMultiplatform)
|
alias(libs.plugins.kotlinMultiplatform)
|
||||||
alias(libs.plugins.kotlinSerialization)
|
|
||||||
alias(libs.plugins.androidMultiplatformLibrary)
|
alias(libs.plugins.androidMultiplatformLibrary)
|
||||||
alias(libs.plugins.ksp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
|
@ -27,26 +25,8 @@ kotlin {
|
||||||
jvm()
|
jvm()
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
androidMain.dependencies {
|
|
||||||
implementation(libs.koin.compose)
|
|
||||||
implementation(libs.ktor.client.okhttp)
|
|
||||||
}
|
|
||||||
commonMain.dependencies {
|
commonMain.dependencies {
|
||||||
implementation(libs.okio)
|
|
||||||
implementation(libs.koin.core)
|
|
||||||
implementation(libs.ktor.client.core)
|
|
||||||
implementation(libs.ktor.client.contentnegotiation)
|
|
||||||
implementation(libs.ktor.serialization.kotlinx.json)
|
|
||||||
implementation(libs.kotlinx.coroutines.core)
|
|
||||||
implementation(libs.kotlinx.datetime)
|
|
||||||
implementation(libs.kotlinx.serialization.json)
|
|
||||||
implementation(libs.kotlinx.serialization.protobuf)
|
|
||||||
|
|
||||||
implementation(projects.core)
|
implementation(projects.core)
|
||||||
implementation(projects.core.room)
|
|
||||||
}
|
|
||||||
iosMain.dependencies {
|
|
||||||
implementation(libs.ktor.client.darwin)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
54
core/data/client/build.gradle.kts
Normal file
54
core/data/client/build.gradle.kts
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.kotlinMultiplatform)
|
||||||
|
alias(libs.plugins.kotlinSerialization)
|
||||||
|
alias(libs.plugins.androidMultiplatformLibrary)
|
||||||
|
alias(libs.plugins.ksp)
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
android {
|
||||||
|
namespace = "moe.lava.banksia.core.data.client"
|
||||||
|
compileSdk = libs.versions.android.compileSdk.get().toInt()
|
||||||
|
|
||||||
|
compilerOptions {
|
||||||
|
jvmTarget.set(JvmTarget.JVM_11)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compilerOptions {
|
||||||
|
freeCompilerArgs.add("-opt-in=kotlin.time.ExperimentalTime")
|
||||||
|
}
|
||||||
|
|
||||||
|
iosArm64()
|
||||||
|
iosSimulatorArm64()
|
||||||
|
|
||||||
|
jvm()
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
androidMain.dependencies {
|
||||||
|
implementation(libs.koin.compose)
|
||||||
|
implementation(libs.ktor.client.okhttp)
|
||||||
|
}
|
||||||
|
commonMain.dependencies {
|
||||||
|
api(projects.core.data)
|
||||||
|
|
||||||
|
implementation(libs.okio)
|
||||||
|
implementation(libs.koin.core)
|
||||||
|
implementation(libs.ktor.client.core)
|
||||||
|
implementation(libs.ktor.client.contentnegotiation)
|
||||||
|
implementation(libs.ktor.serialization.kotlinx.json)
|
||||||
|
implementation(libs.kotlinx.coroutines.core)
|
||||||
|
implementation(libs.kotlinx.datetime)
|
||||||
|
implementation(libs.kotlinx.serialization.json)
|
||||||
|
implementation(libs.kotlinx.serialization.protobuf)
|
||||||
|
|
||||||
|
implementation(projects.core)
|
||||||
|
implementation(projects.core.room)
|
||||||
|
}
|
||||||
|
iosMain.dependencies {
|
||||||
|
implementation(libs.ktor.client.darwin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,9 @@ import io.ktor.client.plugins.plugin
|
||||||
import io.ktor.serialization.kotlinx.json.json
|
import io.ktor.serialization.kotlinx.json.json
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import moe.lava.banksia.core.Constants
|
import moe.lava.banksia.core.Constants
|
||||||
|
import moe.lava.banksia.core.data.repositories.ClientRouteRepository
|
||||||
|
import moe.lava.banksia.core.data.repositories.ClientStopRepository
|
||||||
|
import moe.lava.banksia.core.data.repositories.ClientStopTimeRepository
|
||||||
import moe.lava.banksia.core.data.repositories.RouteRepository
|
import moe.lava.banksia.core.data.repositories.RouteRepository
|
||||||
import moe.lava.banksia.core.data.repositories.StopRepository
|
import moe.lava.banksia.core.data.repositories.StopRepository
|
||||||
import moe.lava.banksia.core.data.repositories.StopTimeRepository
|
import moe.lava.banksia.core.data.repositories.StopTimeRepository
|
||||||
|
|
@ -21,9 +24,10 @@ import moe.lava.banksia.core.room.roomDiModule
|
||||||
import moe.lava.banksia.core.util.log
|
import moe.lava.banksia.core.util.log
|
||||||
import moe.lava.banksia.data.ptv.PtvService
|
import moe.lava.banksia.data.ptv.PtvService
|
||||||
import org.koin.core.module.dsl.singleOf
|
import org.koin.core.module.dsl.singleOf
|
||||||
|
import org.koin.dsl.bind
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val dataDiModule = module {
|
val clientDataDiModule = module {
|
||||||
includes(roomDiModule)
|
includes(roomDiModule)
|
||||||
|
|
||||||
// HTTP Clients
|
// HTTP Clients
|
||||||
|
|
@ -56,7 +60,7 @@ val dataDiModule = module {
|
||||||
singleOf(::StopTimeRemoteDataSource)
|
singleOf(::StopTimeRemoteDataSource)
|
||||||
|
|
||||||
// Repositories
|
// Repositories
|
||||||
singleOf(::RouteRepository)
|
singleOf(::ClientRouteRepository) bind RouteRepository::class
|
||||||
singleOf(::StopRepository)
|
singleOf(::ClientStopRepository) bind StopRepository::class
|
||||||
singleOf(::StopTimeRepository)
|
singleOf(::ClientStopTimeRepository) bind StopTimeRepository::class
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package moe.lava.banksia.core.data.repositories
|
||||||
|
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
import moe.lava.banksia.core.data.sources.route.RouteLocalDataSource
|
||||||
|
import moe.lava.banksia.core.data.sources.route.RouteRemoteDataSource
|
||||||
|
|
||||||
|
internal class ClientRouteRepository internal constructor(
|
||||||
|
private val local: RouteLocalDataSource,
|
||||||
|
private val remote: RouteRemoteDataSource,
|
||||||
|
) : RouteRepository {
|
||||||
|
private val mutex = Mutex()
|
||||||
|
override suspend fun getAll() = mutex.withLock {
|
||||||
|
local
|
||||||
|
.getAll()
|
||||||
|
.map { it.asModel() }
|
||||||
|
.ifEmpty {
|
||||||
|
remote
|
||||||
|
.getAll()
|
||||||
|
.also { local.save(*it.toTypedArray()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun get(id: String) = mutex.withLock { local.get(id)?.asModel() ?: remote.get(id) }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package moe.lava.banksia.core.data.repositories
|
||||||
|
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
import moe.lava.banksia.core.data.sources.stop.StopLocalDataSource
|
||||||
|
import moe.lava.banksia.core.data.sources.stop.StopRemoteDataSource
|
||||||
|
|
||||||
|
internal class ClientStopRepository internal constructor(
|
||||||
|
private val local: StopLocalDataSource,
|
||||||
|
private val remote: StopRemoteDataSource,
|
||||||
|
) : StopRepository {
|
||||||
|
private val mutex = Mutex()
|
||||||
|
|
||||||
|
override suspend fun get(id: String) = mutex.withLock { local.get(id)?.asModel() ?: remote.get(id) }
|
||||||
|
override suspend fun getByRoute(id: String) = mutex.withLock {
|
||||||
|
local
|
||||||
|
.getByRoute(id)
|
||||||
|
.map { it.asModel() }
|
||||||
|
.ifEmpty { null }
|
||||||
|
?: remote.getByRoute(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package moe.lava.banksia.core.data.repositories
|
||||||
|
|
||||||
|
import moe.lava.banksia.core.data.sources.stoptime.StopTimeLocalDataSource
|
||||||
|
import moe.lava.banksia.core.data.sources.stoptime.StopTimeRemoteDataSource
|
||||||
|
import moe.lava.banksia.core.model.StopTimeDated
|
||||||
|
|
||||||
|
internal class ClientStopTimeRepository internal constructor(
|
||||||
|
private val local: StopTimeLocalDataSource,
|
||||||
|
private val remote: StopTimeRemoteDataSource,
|
||||||
|
) : StopTimeRepository {
|
||||||
|
override suspend fun getForStop(id: String): List<StopTimeDated> {
|
||||||
|
return local
|
||||||
|
.getAtStop(id)
|
||||||
|
.ifEmpty { remote.getAtStop(id) }
|
||||||
|
}
|
||||||
|
}
|
||||||
21
core/data/server/build.gradle.kts
Normal file
21
core/data/server/build.gradle.kts
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.kotlinJvm)
|
||||||
|
alias(libs.plugins.kotlinSerialization)
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
compilerOptions {
|
||||||
|
freeCompilerArgs.add("-opt-in=kotlin.time.ExperimentalTime")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.okio)
|
||||||
|
implementation(libs.koin.core)
|
||||||
|
implementation(libs.kotlinx.coroutines.core)
|
||||||
|
implementation(libs.kotlinx.datetime)
|
||||||
|
|
||||||
|
api(projects.core.data)
|
||||||
|
implementation(projects.core)
|
||||||
|
implementation(projects.core.room)
|
||||||
|
}
|
||||||
|
|
@ -1,25 +1,8 @@
|
||||||
package moe.lava.banksia.core.data.repositories
|
package moe.lava.banksia.core.data.repositories
|
||||||
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import moe.lava.banksia.core.model.Route
|
||||||
import kotlinx.coroutines.sync.withLock
|
|
||||||
import moe.lava.banksia.core.data.sources.route.RouteLocalDataSource
|
|
||||||
import moe.lava.banksia.core.data.sources.route.RouteRemoteDataSource
|
|
||||||
|
|
||||||
class RouteRepository internal constructor(
|
interface RouteRepository {
|
||||||
private val local: RouteLocalDataSource,
|
suspend fun get(id: String): Route
|
||||||
private val remote: RouteRemoteDataSource,
|
suspend fun getAll(): List<Route>
|
||||||
) {
|
|
||||||
private val mutex = Mutex()
|
|
||||||
suspend fun getAll() = mutex.withLock {
|
|
||||||
local
|
|
||||||
.getAll()
|
|
||||||
.map { it.asModel() }
|
|
||||||
.ifEmpty {
|
|
||||||
remote
|
|
||||||
.getAll()
|
|
||||||
.also { local.save(*it.toTypedArray()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun get(id: String) = mutex.withLock { local.get(id)?.asModel() ?: remote.get(id) }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,8 @@
|
||||||
package moe.lava.banksia.core.data.repositories
|
package moe.lava.banksia.core.data.repositories
|
||||||
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import moe.lava.banksia.core.model.Stop
|
||||||
import kotlinx.coroutines.sync.withLock
|
|
||||||
import moe.lava.banksia.core.data.sources.stop.StopLocalDataSource
|
|
||||||
import moe.lava.banksia.core.data.sources.stop.StopRemoteDataSource
|
|
||||||
|
|
||||||
class StopRepository internal constructor(
|
interface StopRepository {
|
||||||
private val local: StopLocalDataSource,
|
suspend fun get(id: String): Stop
|
||||||
private val remote: StopRemoteDataSource,
|
suspend fun getByRoute(id: String): List<Stop>
|
||||||
) {
|
|
||||||
private val mutex = Mutex()
|
|
||||||
|
|
||||||
suspend fun get(id: String) = mutex.withLock { local.get(id)?.asModel() ?: remote.get(id) }
|
|
||||||
suspend fun getByRoute(id: String) = mutex.withLock {
|
|
||||||
local
|
|
||||||
.getByRoute(id)
|
|
||||||
.map { it.asModel() }
|
|
||||||
.ifEmpty { null }
|
|
||||||
?: remote.getByRoute(id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,7 @@
|
||||||
package moe.lava.banksia.core.data.repositories
|
package moe.lava.banksia.core.data.repositories
|
||||||
|
|
||||||
import moe.lava.banksia.core.data.sources.stoptime.StopTimeLocalDataSource
|
|
||||||
import moe.lava.banksia.core.data.sources.stoptime.StopTimeRemoteDataSource
|
|
||||||
import moe.lava.banksia.core.model.StopTimeDated
|
import moe.lava.banksia.core.model.StopTimeDated
|
||||||
|
|
||||||
class StopTimeRepository internal constructor(
|
interface StopTimeRepository {
|
||||||
private val local: StopTimeLocalDataSource,
|
suspend fun getForStop(id: String): List<StopTimeDated>
|
||||||
private val remote: StopTimeRemoteDataSource,
|
|
||||||
) {
|
|
||||||
suspend fun getForStop(id: String): List<StopTimeDated> {
|
|
||||||
return local
|
|
||||||
.getAtStop(id)
|
|
||||||
.ifEmpty { remote.getAtStop(id) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package moe.lava.banksia.core.room
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.room.Room
|
||||||
|
import org.koin.core.component.KoinComponent
|
||||||
|
import org.koin.core.component.get
|
||||||
|
import org.koin.core.component.inject
|
||||||
|
|
||||||
|
actual class DatabaseManager actual constructor() : KoinComponent {
|
||||||
|
private val ctx by inject<Context>()
|
||||||
|
|
||||||
|
actual val database by lazy {
|
||||||
|
val ctx = get<Context>().applicationContext
|
||||||
|
val dbFile = ctx.getDatabasePath("room.db")
|
||||||
|
val builder = Room.databaseBuilder<Database>(
|
||||||
|
context = ctx,
|
||||||
|
name = dbFile.absolutePath,
|
||||||
|
)
|
||||||
|
|
||||||
|
Database.build(builder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
package moe.lava.banksia.core.room
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.room.Room
|
|
||||||
import androidx.room.RoomDatabase
|
|
||||||
import org.koin.core.parameter.ParametersHolder
|
|
||||||
import org.koin.core.scope.Scope
|
|
||||||
|
|
||||||
class AndroidDatabaseBuilder(val ctx: Context) : PlatformDatabaseBuilder {
|
|
||||||
override fun getBuilder(): RoomDatabase.Builder<Database> {
|
|
||||||
val appContext = ctx.applicationContext
|
|
||||||
val dbFile = appContext.getDatabasePath("room.db")
|
|
||||||
return Room.databaseBuilder<Database>(
|
|
||||||
context = appContext,
|
|
||||||
name = dbFile.absolutePath
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal actual fun Scope.provideDatabaseBuilder(p: ParametersHolder): PlatformDatabaseBuilder =
|
|
||||||
AndroidDatabaseBuilder(get())
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package moe.lava.banksia.core.room
|
||||||
|
|
||||||
|
import org.koin.core.component.KoinComponent
|
||||||
|
|
||||||
|
expect class DatabaseManager() : KoinComponent {
|
||||||
|
val database: Database
|
||||||
|
}
|
||||||
|
|
@ -1,26 +1,18 @@
|
||||||
package moe.lava.banksia.core.room
|
package moe.lava.banksia.core.room
|
||||||
|
|
||||||
import androidx.room.RoomDatabase
|
import org.koin.core.module.dsl.singleOf
|
||||||
import org.koin.core.parameter.ParametersHolder
|
|
||||||
import org.koin.core.scope.Scope
|
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val roomDiModule = module {
|
val roomDiModule = module {
|
||||||
single { provideDatabaseBuilder(it) }
|
singleOf(::DatabaseManager)
|
||||||
single { Database.build(get<PlatformDatabaseBuilder>().getBuilder()) }
|
factory { get<DatabaseManager>().database }
|
||||||
|
|
||||||
single { get<Database>().versionMetadataDao }
|
factory { get<Database>().versionMetadataDao }
|
||||||
single { get<Database>().routeDao }
|
factory { get<Database>().routeDao }
|
||||||
single { get<Database>().serviceDao }
|
factory { get<Database>().serviceDao }
|
||||||
single { get<Database>().serviceExceptionDao }
|
factory { get<Database>().serviceExceptionDao }
|
||||||
single { get<Database>().shapeDao }
|
factory { get<Database>().shapeDao }
|
||||||
single { get<Database>().stopDao }
|
factory { get<Database>().stopDao }
|
||||||
single { get<Database>().stopTimeDao }
|
factory { get<Database>().stopTimeDao }
|
||||||
single { get<Database>().tripDao }
|
factory { get<Database>().tripDao }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal interface PlatformDatabaseBuilder {
|
|
||||||
fun getBuilder(): RoomDatabase.Builder<Database>
|
|
||||||
}
|
|
||||||
|
|
||||||
internal expect fun Scope.provideDatabaseBuilder(p: ParametersHolder): PlatformDatabaseBuilder
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ interface StopDao {
|
||||||
@Query("""
|
@Query("""
|
||||||
SELECT * FROM Stop
|
SELECT * FROM Stop
|
||||||
WHERE platformCode <> ""
|
WHERE platformCode <> ""
|
||||||
AND parent == ""
|
AND parent IS NULL
|
||||||
""")
|
""")
|
||||||
suspend fun getAllParentless(): List<StopEntity>
|
suspend fun getAllParentless(): List<StopEntity>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package moe.lava.banksia.core.room
|
||||||
|
|
||||||
|
import org.koin.core.component.KoinComponent
|
||||||
|
|
||||||
|
actual class DatabaseManager actual constructor() : KoinComponent {
|
||||||
|
actual val database: Database
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
package moe.lava.banksia.core.room
|
|
||||||
|
|
||||||
import androidx.room.RoomDatabase
|
|
||||||
import org.koin.core.parameter.ParametersHolder
|
|
||||||
import org.koin.core.scope.Scope
|
|
||||||
|
|
||||||
class IosDatabaseBuilder() : PlatformDatabaseBuilder {
|
|
||||||
override fun getBuilder(): RoomDatabase.Builder<Database> {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal actual fun Scope.provideDatabaseBuilder(p: ParametersHolder): PlatformDatabaseBuilder =
|
|
||||||
IosDatabaseBuilder()
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
package moe.lava.banksia.core.room
|
||||||
|
|
||||||
|
import androidx.room.Room
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import moe.lava.banksia.core.util.error
|
||||||
|
import org.koin.core.component.KoinComponent
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
actual class DatabaseManager : KoinComponent {
|
||||||
|
private var liveDatabase: Database = Database.build(getBuilder())
|
||||||
|
actual val database get() = liveDatabase
|
||||||
|
|
||||||
|
private fun getBuilder(path: String = "./data/room.db"): RoomDatabase.Builder<Database> {
|
||||||
|
val dbFile = File(path)
|
||||||
|
return Room.databaseBuilder<Database>(
|
||||||
|
name = dbFile.absolutePath,
|
||||||
|
).setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun makeAlt() = Database.build(getBuilder("./data/room_alt.db"))
|
||||||
|
|
||||||
|
private fun deleteAll(file: File): Boolean {
|
||||||
|
val r1 = file.takeIf { it.exists() }?.delete()
|
||||||
|
val r2 = File(file.parentFile, file.name + ".lck").takeIf { it.exists() }?.delete()
|
||||||
|
val r3 = File(file.parentFile, file.name + "-journal").takeIf { it.exists() }?.delete()
|
||||||
|
return r1 != false && r2 != false && r3 != false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renameAll(from: File, to: File): Boolean {
|
||||||
|
val r1 = from.takeIf { it.exists() }?.renameTo(to)
|
||||||
|
val r2 = File(from.parentFile, from.name + ".lck").takeIf { it.exists() }?.renameTo(File(to.parentFile, to.name + ".lck"))
|
||||||
|
val r3 = File(from.parentFile, from.name + "-journal").takeIf { it.exists() }?.renameTo(File(to.parentFile, to.name + "-journal"))
|
||||||
|
return r1 != false && r2 != false && r3 != false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun swap(scope: CoroutineScope = CoroutineScope(Dispatchers.IO)) {
|
||||||
|
val live = File("./data/room.db")
|
||||||
|
val alt = File("./data/room_alt.db")
|
||||||
|
val old = File("./data/room_old.db")
|
||||||
|
|
||||||
|
if (!renameAll(live, old)) {
|
||||||
|
error("DatabaseManager", "Failed to rename database from live to old (${live.absolutePath} -> ${old.absolutePath})")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!renameAll(alt, live)) {
|
||||||
|
error("DatabaseManager", "Failed to rename database from alt to live, trying to undo.. (${alt.absolutePath} -> ${live.absolutePath})")
|
||||||
|
if (!live.renameTo(old)) {
|
||||||
|
error("DatabaseManager", "Failed to undo, critical failure, exiting..")
|
||||||
|
exitProcess(1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val oldDatabase = liveDatabase
|
||||||
|
liveDatabase = Database.build(getBuilder())
|
||||||
|
|
||||||
|
scope.launch {
|
||||||
|
delay(5000)
|
||||||
|
if (!deleteAll(old)) {
|
||||||
|
error("DatabaseManager", "Failed to unlink old database, stray files! (${old.absolutePath})")
|
||||||
|
}
|
||||||
|
oldDatabase.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
package moe.lava.banksia.core.room
|
|
||||||
|
|
||||||
import androidx.room.Room
|
|
||||||
import androidx.room.RoomDatabase
|
|
||||||
import org.koin.core.parameter.ParametersHolder
|
|
||||||
import org.koin.core.scope.Scope
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class JvmDatabaseBuilder() : PlatformDatabaseBuilder {
|
|
||||||
override fun getBuilder(): RoomDatabase.Builder<Database> {
|
|
||||||
val dbFile = File("./data/room.db")
|
|
||||||
return Room.databaseBuilder<Database>(
|
|
||||||
name = dbFile.absolutePath,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal actual fun Scope.provideDatabaseBuilder(p: ParametersHolder): PlatformDatabaseBuilder =
|
|
||||||
JvmDatabaseBuilder()
|
|
||||||
|
|
@ -5,7 +5,7 @@ plugins {
|
||||||
application
|
application
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "moe.lava.banksia"
|
group = "moe.lava.banksia.server"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
application {
|
application {
|
||||||
mainClass.set("moe.lava.banksia.server.ApplicationKt")
|
mainClass.set("moe.lava.banksia.server.ApplicationKt")
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ class GtfsParser(
|
||||||
.forEach { fd ->
|
.forEach { fd ->
|
||||||
log.info("parsing stop times for ${fd.parent}...")
|
log.info("parsing stop times for ${fd.parent}...")
|
||||||
parseStopTimes(fd, trips) { seq ->
|
parseStopTimes(fd, trips) { seq ->
|
||||||
seq.chunked(10000)
|
seq.chunked(1000000)
|
||||||
.forEach { emit(GtfsData.StopTimeChunk(it)) }
|
.forEach { emit(GtfsData.StopTimeChunk(it)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -170,7 +170,7 @@ class GtfsParser(
|
||||||
id = stop_id,
|
id = stop_id,
|
||||||
name = stop_name,
|
name = stop_name,
|
||||||
pos = Point(stop_lat, stop_lon),
|
pos = Point(stop_lat, stop_lon),
|
||||||
parent = parent_station,
|
parent = parent_station.ifEmpty { null },
|
||||||
hasWheelChairBoarding = wheelchair_boarding == "1",
|
hasWheelChairBoarding = wheelchair_boarding == "1",
|
||||||
level = level_id,
|
level = level_id,
|
||||||
platformCode = platform_code,
|
platformCode = platform_code,
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import moe.lava.banksia.core.util.serialise
|
||||||
import moe.lava.banksia.server.di.ServerModules
|
import moe.lava.banksia.server.di.ServerModules
|
||||||
import moe.lava.banksia.server.gtfsrt.GtfsrtService
|
import moe.lava.banksia.server.gtfsrt.GtfsrtService
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
import org.koin.ktor.ext.inject
|
import org.koin.ktor.ext.get
|
||||||
import org.koin.ktor.plugin.Koin
|
import org.koin.ktor.plugin.Koin
|
||||||
import kotlin.time.Clock
|
import kotlin.time.Clock
|
||||||
|
|
||||||
|
|
@ -46,19 +46,29 @@ fun Application.module() {
|
||||||
modules(ServerModules)
|
modules(ServerModules)
|
||||||
}
|
}
|
||||||
|
|
||||||
val gtfsr by inject<GtfsrtService>()
|
|
||||||
@Suppress("KotlinConstantConditions")
|
@Suppress("KotlinConstantConditions")
|
||||||
launch { gtfsr.start(this, !Constants.devMode) }
|
launch { get<GtfsrtService>().start(this, !Constants.devMode) }
|
||||||
|
|
||||||
routing {
|
routing {
|
||||||
if (Constants.devMode) {
|
if (Constants.devMode) {
|
||||||
get("/fixup") {
|
get("/fixup") {
|
||||||
call.respondText("received")
|
call.respondText("received")
|
||||||
val fixer by inject<GtfsDataFixer>()
|
get<GtfsDataFixer>().addParentsToStops()
|
||||||
fixer.addParentsToStops()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
get("/update") {
|
get("/manage/fixup") {
|
||||||
|
val key = call.parameters["key"]
|
||||||
|
if (key != Constants.updateKey) {
|
||||||
|
call.respond(HttpStatusCode.Forbidden)
|
||||||
|
return@get
|
||||||
|
}
|
||||||
|
|
||||||
|
call.respondText("fixing")
|
||||||
|
launch(context = Dispatchers.IO) {
|
||||||
|
get<GtfsDataFixer>().addParentsToStops()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get("/manage/update") {
|
||||||
val key = call.parameters["key"]
|
val key = call.parameters["key"]
|
||||||
if (key != Constants.updateKey) {
|
if (key != Constants.updateKey) {
|
||||||
call.respond(HttpStatusCode.Forbidden)
|
call.respond(HttpStatusCode.Forbidden)
|
||||||
|
|
@ -70,16 +80,13 @@ fun Application.module() {
|
||||||
?: "https://opendata.transport.vic.gov.au/dataset/3f4e292e-7f8a-4ffe-831f-1953be0fe448/resource/${datasetUuid}/download/gtfs.zip"
|
?: "https://opendata.transport.vic.gov.au/dataset/3f4e292e-7f8a-4ffe-831f-1953be0fe448/resource/${datasetUuid}/download/gtfs.zip"
|
||||||
call.respondText("received")
|
call.respondText("received")
|
||||||
launch(context = Dispatchers.IO) {
|
launch(context = Dispatchers.IO) {
|
||||||
val fixer by inject<GtfsDataFixer>()
|
get<GtfsImporter>().import(datasetUrl)
|
||||||
val importer by inject<GtfsImporter>()
|
get<GtfsDataFixer>().addParentsToStops()
|
||||||
importer.import(datasetUrl)
|
|
||||||
|
|
||||||
fixer.addParentsToStops()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get("/metadata/{type?}") {
|
get("/metadata/{type?}") {
|
||||||
val dao by inject<VersionMetadataDao>()
|
val dao = get<VersionMetadataDao>()
|
||||||
val type = call.parameters["type"]
|
val type = call.parameters["type"]
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
call.respond(dao.getAll().map { it.asModel() })
|
call.respond(dao.getAll().map { it.asModel() })
|
||||||
|
|
@ -96,7 +103,7 @@ fun Application.module() {
|
||||||
|
|
||||||
get("/routes") {
|
get("/routes") {
|
||||||
val routes = withContext(context = Dispatchers.IO) {
|
val routes = withContext(context = Dispatchers.IO) {
|
||||||
inject<RouteDao>().value.getAll()
|
get<RouteDao>().getAll()
|
||||||
}
|
}
|
||||||
val res = routes.map { it.asModel() }
|
val res = routes.map { it.asModel() }
|
||||||
call.respond(res)
|
call.respond(res)
|
||||||
|
|
@ -104,7 +111,7 @@ fun Application.module() {
|
||||||
get("/routes/{route_id}") {
|
get("/routes/{route_id}") {
|
||||||
val routeId = call.parameters["route_id"]!!
|
val routeId = call.parameters["route_id"]!!
|
||||||
val route = withContext(context = Dispatchers.IO) {
|
val route = withContext(context = Dispatchers.IO) {
|
||||||
inject<RouteDao>().value.get(routeId)
|
get<RouteDao>().get(routeId)
|
||||||
}
|
}
|
||||||
if (route != null)
|
if (route != null)
|
||||||
call.respond(route.asModel())
|
call.respond(route.asModel())
|
||||||
|
|
@ -113,7 +120,7 @@ fun Application.module() {
|
||||||
}
|
}
|
||||||
get("/stops") {
|
get("/stops") {
|
||||||
val routes = withContext(context = Dispatchers.IO) {
|
val routes = withContext(context = Dispatchers.IO) {
|
||||||
inject<StopDao>().value.getAll()
|
get<StopDao>().getAll()
|
||||||
}
|
}
|
||||||
val res = routes.map { it.asModel() }
|
val res = routes.map { it.asModel() }
|
||||||
call.respond(res)
|
call.respond(res)
|
||||||
|
|
@ -121,7 +128,7 @@ fun Application.module() {
|
||||||
get("/stops/{stop_id}") {
|
get("/stops/{stop_id}") {
|
||||||
val stopId = call.parameters["stop_id"]!!
|
val stopId = call.parameters["stop_id"]!!
|
||||||
val stop = withContext(context = Dispatchers.IO) {
|
val stop = withContext(context = Dispatchers.IO) {
|
||||||
inject<StopDao>().value.get(stopId)
|
get<StopDao>().get(stopId)
|
||||||
}
|
}
|
||||||
if (stop != null)
|
if (stop != null)
|
||||||
call.respond(stop.asModel())
|
call.respond(stop.asModel())
|
||||||
|
|
@ -132,7 +139,7 @@ fun Application.module() {
|
||||||
val routeId = call.parameters["route_id"]!!
|
val routeId = call.parameters["route_id"]!!
|
||||||
val useParent = call.queryParameters["parent"] !in listOf("false", "0")
|
val useParent = call.queryParameters["parent"] !in listOf("false", "0")
|
||||||
val stops = withContext(Dispatchers.IO) {
|
val stops = withContext(Dispatchers.IO) {
|
||||||
val routeDao by inject<RouteDao>()
|
val routeDao = get<RouteDao>()
|
||||||
if (useParent)
|
if (useParent)
|
||||||
routeDao.stopsParent(routeId)
|
routeDao.stopsParent(routeId)
|
||||||
else
|
else
|
||||||
|
|
@ -146,7 +153,7 @@ fun Application.module() {
|
||||||
?.let { LocalDate.parse(it, LocalDate.Formats.ISO) }
|
?.let { LocalDate.parse(it, LocalDate.Formats.ISO) }
|
||||||
?: Clock.System.todayIn(TimeZone.currentSystemDefault())
|
?: Clock.System.todayIn(TimeZone.currentSystemDefault())
|
||||||
val times = withContext(context = Dispatchers.IO) {
|
val times = withContext(context = Dispatchers.IO) {
|
||||||
inject<StopTimeDao>().value
|
get<StopTimeDao>()
|
||||||
.getForStopDated(
|
.getForStopDated(
|
||||||
stopId,
|
stopId,
|
||||||
listOf(date.dayOfWeek).serialise(),
|
listOf(date.dayOfWeek).serialise(),
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,14 @@ class GtfsDataFixer(
|
||||||
name = name,
|
name = name,
|
||||||
lat = avgLat,
|
lat = avgLat,
|
||||||
lng = avgLng,
|
lng = avgLng,
|
||||||
parent = "",
|
parent = null,
|
||||||
hasWheelChairBoarding = stops.all { it.hasWheelChairBoarding },
|
hasWheelChairBoarding = stops.all { it.hasWheelChairBoarding },
|
||||||
level = "",
|
level = "",
|
||||||
platformCode = "",
|
platformCode = "",
|
||||||
)
|
)
|
||||||
log("datafixer", "inserting ${parentId} for ${stops.size} children")
|
log("datafixer", "inserting ${parentId} for ${stops.size} children")
|
||||||
dao.insertAll(parent)
|
dao.insertAll(parent)
|
||||||
database.stopDao.updateParents(stops.map { it.id }, parentId)
|
dao.updateParents(stops.map { it.id }, parentId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
package moe.lava.banksia.server
|
package moe.lava.banksia.server
|
||||||
|
|
||||||
import androidx.room.immediateTransaction
|
|
||||||
import androidx.room.useWriterConnection
|
|
||||||
import io.ktor.util.logging.Logger
|
import io.ktor.util.logging.Logger
|
||||||
import moe.lava.banksia.core.model.Route
|
import moe.lava.banksia.core.model.Route
|
||||||
import moe.lava.banksia.core.model.Service
|
import moe.lava.banksia.core.model.Service
|
||||||
|
|
@ -11,6 +9,7 @@ import moe.lava.banksia.core.model.Stop
|
||||||
import moe.lava.banksia.core.model.StopTime
|
import moe.lava.banksia.core.model.StopTime
|
||||||
import moe.lava.banksia.core.model.Trip
|
import moe.lava.banksia.core.model.Trip
|
||||||
import moe.lava.banksia.core.room.Database
|
import moe.lava.banksia.core.room.Database
|
||||||
|
import moe.lava.banksia.core.room.DatabaseManager
|
||||||
import moe.lava.banksia.core.room.entity.asEntity
|
import moe.lava.banksia.core.room.entity.asEntity
|
||||||
import moe.lava.banksia.server.gtfs.GtfsData
|
import moe.lava.banksia.server.gtfs.GtfsData
|
||||||
import moe.lava.banksia.server.gtfs.GtfsParser
|
import moe.lava.banksia.server.gtfs.GtfsParser
|
||||||
|
|
@ -18,74 +17,66 @@ import kotlin.time.Clock
|
||||||
|
|
||||||
class GtfsImporter(
|
class GtfsImporter(
|
||||||
private val parser: GtfsParser,
|
private val parser: GtfsParser,
|
||||||
private val database: Database,
|
private val dbm: DatabaseManager,
|
||||||
private val log: Logger,
|
private val log: Logger,
|
||||||
) {
|
) {
|
||||||
suspend fun import(url: String, date: Long = Clock.System.now().epochSeconds) {
|
suspend fun import(url: String, date: Long = Clock.System.now().epochSeconds) {
|
||||||
database.useWriterConnection { transactor ->
|
val database = dbm.makeAlt()
|
||||||
transactor.immediateTransaction {
|
|
||||||
database.routeDao.deleteAll()
|
|
||||||
database.serviceDao.deleteAll()
|
|
||||||
database.serviceExceptionDao.deleteAll()
|
|
||||||
database.shapeDao.deleteAll()
|
|
||||||
database.stopDao.deleteAll()
|
|
||||||
database.stopTimeDao.deleteAll()
|
|
||||||
database.tripDao.deleteAll()
|
|
||||||
|
|
||||||
parser.update(url).collect { chunk ->
|
parser.update(url).collect { chunk ->
|
||||||
when (chunk) {
|
when (chunk) {
|
||||||
is GtfsData.RouteChunk -> addRoutes(chunk.routes)
|
is GtfsData.RouteChunk -> database.addRoutes(chunk.routes)
|
||||||
is GtfsData.ServiceChunk -> addServices(chunk.services)
|
is GtfsData.ServiceChunk -> database.addServices(chunk.services)
|
||||||
is GtfsData.ServiceExceptionChunk -> addServiceExceptions(chunk.exceptions)
|
is GtfsData.ServiceExceptionChunk -> database.addServiceExceptions(chunk.exceptions)
|
||||||
is GtfsData.ShapeChunk -> addShapes(chunk.shapes)
|
is GtfsData.ShapeChunk -> database.addShapes(chunk.shapes)
|
||||||
is GtfsData.StopChunk -> addStops(chunk.stops)
|
is GtfsData.StopChunk -> database.addStops(chunk.stops)
|
||||||
is GtfsData.StopTimeChunk -> addStopTimes(chunk.stopTimes)
|
is GtfsData.StopTimeChunk -> database.addStopTimes(chunk.stopTimes)
|
||||||
is GtfsData.TripChunk -> addTrips(chunk.trips)
|
is GtfsData.TripChunk -> database.addTrips(chunk.trips)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateMetadata(date)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
database.updateMetadata(date)
|
||||||
|
database.close()
|
||||||
|
dbm.swap()
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun updateMetadata(date: Long) {
|
private suspend fun Database.updateMetadata(date: Long) {
|
||||||
val dao = database.versionMetadataDao
|
val dao = versionMetadataDao
|
||||||
log.info("updating metadata...")
|
log.info("updating metadata...")
|
||||||
dao.update(date, listOf("routes", "stops", "shapes", "trips", "stop_times"))
|
dao.update(date, listOf("routes", "stops", "shapes", "trips", "stop_times"))
|
||||||
log.info("done")
|
log.info("done")
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun addRoutes(routes: List<Route>) {
|
private suspend fun Database.addRoutes(routes: List<Route>) {
|
||||||
val dao = database.routeDao
|
val dao = routeDao
|
||||||
log.info("inserting routes...")
|
log.info("inserting routes...")
|
||||||
dao.insertOrReplaceAll(*routes.map { it.asEntity() }.toTypedArray())
|
dao.insertOrReplaceAll(*routes.map { it.asEntity() }.toTypedArray())
|
||||||
log.info("done")
|
log.info("done")
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun addServices(services: List<Service>) {
|
private suspend fun Database.addServices(services: List<Service>) {
|
||||||
val dao = database.serviceDao
|
val dao = serviceDao
|
||||||
log.info("inserting services...")
|
log.info("inserting services...")
|
||||||
dao.insertOrReplaceAll(*services.map { it.asEntity() }.toTypedArray())
|
dao.insertOrReplaceAll(*services.map { it.asEntity() }.toTypedArray())
|
||||||
log.info("done")
|
log.info("done")
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun addServiceExceptions(exceptions: List<ServiceException>) {
|
private suspend fun Database.addServiceExceptions(exceptions: List<ServiceException>) {
|
||||||
val dao = database.serviceExceptionDao
|
val dao = serviceExceptionDao
|
||||||
log.info("inserting exceptions...")
|
log.info("inserting exceptions...")
|
||||||
dao.insertOrReplaceAll(*exceptions.map { it.asEntity() }.toTypedArray())
|
dao.insertOrReplaceAll(*exceptions.map { it.asEntity() }.toTypedArray())
|
||||||
log.info("done")
|
log.info("done")
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun addShapes(shapes: List<Shape>) {
|
private suspend fun Database.addShapes(shapes: List<Shape>) {
|
||||||
val dao = database.shapeDao
|
val dao = shapeDao
|
||||||
log.info("inserting shapes...")
|
log.info("inserting shapes...")
|
||||||
dao.insertOrReplaceAll(*shapes.map { it.asEntity() }.toTypedArray())
|
dao.insertOrReplaceAll(*shapes.map { it.asEntity() }.toTypedArray())
|
||||||
log.info("done")
|
log.info("done")
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun addStops(stops: List<Stop>) {
|
private suspend fun Database.addStops(stops: List<Stop>) {
|
||||||
val dao = database.stopDao
|
val dao = stopDao
|
||||||
log.info("inserting stops...")
|
log.info("inserting stops...")
|
||||||
stops
|
stops
|
||||||
.groupBy { it.id }
|
.groupBy { it.id }
|
||||||
|
|
@ -102,15 +93,15 @@ class GtfsImporter(
|
||||||
log.info("done")
|
log.info("done")
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun addStopTimes(stopTimes: List<StopTime>) {
|
private suspend fun Database.addStopTimes(stopTimes: List<StopTime>) {
|
||||||
val dao = database.stopTimeDao
|
val dao = stopTimeDao
|
||||||
log.info("inserting ${stopTimes.size} stoptimes...")
|
log.info("inserting ${stopTimes.size} stoptimes...")
|
||||||
dao.insertOrReplaceAll(*stopTimes.map { it.asEntity() }.toTypedArray())
|
dao.insertOrReplaceAll(*stopTimes.map { it.asEntity() }.toTypedArray())
|
||||||
log.info("done")
|
log.info("done")
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun addTrips(trips: List<Trip>) {
|
private suspend fun Database.addTrips(trips: List<Trip>) {
|
||||||
val dao = database.tripDao
|
val dao = tripDao
|
||||||
log.info("inserting ${trips.size} trips...")
|
log.info("inserting ${trips.size} trips...")
|
||||||
dao.insertOrReplaceAll(*trips.map { it.asEntity() }.toTypedArray())
|
dao.insertOrReplaceAll(*trips.map { it.asEntity() }.toTypedArray())
|
||||||
log.info("done")
|
log.info("done")
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import moe.lava.banksia.server.GtfsDataFixer
|
||||||
import moe.lava.banksia.server.GtfsImporter
|
import moe.lava.banksia.server.GtfsImporter
|
||||||
import moe.lava.banksia.server.gtfs.GtfsParser
|
import moe.lava.banksia.server.gtfs.GtfsParser
|
||||||
import moe.lava.banksia.server.gtfsrt.GtfsrtService
|
import moe.lava.banksia.server.gtfsrt.GtfsrtService
|
||||||
|
import org.koin.core.module.dsl.factoryOf
|
||||||
import org.koin.core.module.dsl.singleOf
|
import org.koin.core.module.dsl.singleOf
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
|
|
@ -16,6 +17,6 @@ val ServerModules = module {
|
||||||
singleOf(::GtfsParser)
|
singleOf(::GtfsParser)
|
||||||
singleOf(::GtfsrtService)
|
singleOf(::GtfsrtService)
|
||||||
|
|
||||||
singleOf(::GtfsDataFixer)
|
factoryOf(::GtfsDataFixer)
|
||||||
singleOf(::GtfsImporter)
|
factoryOf(::GtfsImporter)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ include(":server:gtfs")
|
||||||
include(":server:gtfs_rt")
|
include(":server:gtfs_rt")
|
||||||
include(":core")
|
include(":core")
|
||||||
include(":core:data")
|
include(":core:data")
|
||||||
|
include(":core:data:client")
|
||||||
|
include(":core:data:server")
|
||||||
include(":core:room")
|
include(":core:room")
|
||||||
include(":ui")
|
include(":ui")
|
||||||
include(":ui:maps")
|
include(":ui:maps")
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ kotlin {
|
||||||
implementation(libs.ui.backhandler)
|
implementation(libs.ui.backhandler)
|
||||||
|
|
||||||
implementation(projects.core)
|
implementation(projects.core)
|
||||||
implementation(projects.core.data)
|
implementation(projects.core.data.client)
|
||||||
implementation(projects.ui.maps)
|
implementation(projects.ui.maps)
|
||||||
implementation(projects.ui.shared)
|
implementation(projects.ui.shared)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package moe.lava.banksia.ui.di
|
package moe.lava.banksia.ui.di
|
||||||
|
|
||||||
import moe.lava.banksia.core.data.dataDiModule
|
import moe.lava.banksia.core.data.clientDataDiModule
|
||||||
import moe.lava.banksia.ui.screens.map.MapScreenViewModel
|
import moe.lava.banksia.ui.screens.map.MapScreenViewModel
|
||||||
import org.koin.core.module.dsl.viewModelOf
|
import org.koin.core.module.dsl.viewModelOf
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val AppModule = module {
|
val AppModule = module {
|
||||||
includes(dataDiModule)
|
includes(clientDataDiModule)
|
||||||
|
|
||||||
// ViewModel
|
// ViewModel
|
||||||
viewModelOf(::MapScreenViewModel)
|
viewModelOf(::MapScreenViewModel)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue