You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

129 lines
4.8 KiB

package net.aiterp.git.ykonsole2
import kotlinx.coroutines.runBlocking
import net.aiterp.git.ykonsole2.application.createServer
import net.aiterp.git.ykonsole2.application.env.optStrEnv
import net.aiterp.git.ykonsole2.application.env.strEnv
import net.aiterp.git.ykonsole2.application.logging.log
import net.aiterp.git.ykonsole2.application.services.DriverStarter
import net.aiterp.git.ykonsole2.domain.models.*
import net.aiterp.git.ykonsole2.domain.runtime.CommandBus
import net.aiterp.git.ykonsole2.domain.runtime.EventBus
import net.aiterp.git.ykonsole2.infrastructure.ExportTarget
import net.aiterp.git.ykonsole2.infrastructure.IConsole
import net.aiterp.git.ykonsole2.infrastructure.WorkoutExporter
import net.aiterp.git.ykonsole2.infrastructure.drivers.MilestoneChecker
import net.aiterp.git.ykonsole2.infrastructure.drivers.ProgramEnforcer
import net.aiterp.git.ykonsole2.infrastructure.drivers.Skipper
import net.aiterp.git.ykonsole2.infrastructure.drivers.WorkoutWriter
import net.aiterp.git.ykonsole2.infrastructure.indigo1.Indigo1
import net.aiterp.git.ykonsole2.infrastructure.indigo2.Indigo2
import net.aiterp.git.ykonsole2.infrastructure.makeDataSource
import net.aiterp.git.ykonsole2.infrastructure.repositories.deviceRepo
import net.aiterp.git.ykonsole2.infrastructure.repositories.programRepo
import net.aiterp.git.ykonsole2.infrastructure.repositories.workoutRepo
import net.aiterp.git.ykonsole2.infrastructure.repositories.workoutStateRepo
import net.aiterp.git.ykonsole2.infrastructure.testing.*
import kotlin.time.Duration.Companion.seconds
fun main(): Unit = runBlocking {
initRepositories().apply {
val commandBus = CommandBus()
val eventBus = EventBus()
workoutRepo.findActive()?.let { active ->
active.status = WorkoutStatus.Disconnected
workoutRepo.save(active)
}
val exporter = workoutExporterOrNull()
val iConsole = IConsole()
val milestoneChecker = MilestoneChecker()
val programEnforcer = ProgramEnforcer(programRepo, workoutRepo)
val skipper = Skipper()
val testDriver = TestDriver(secondLength = 1.seconds)
val workoutWriter = WorkoutWriter(workoutRepo, workoutStateRepo)
createServer(
deviceRepo = deviceRepo,
programRepo = programRepo,
workoutRepo = workoutRepo,
workoutStateRepo = workoutStateRepo,
commandBus = commandBus,
eventBus = eventBus,
).start(wait = false)
DriverStarter(
drivers = listOfNotNull(
exporter,
iConsole,
milestoneChecker,
programEnforcer,
skipper,
testDriver,
workoutWriter,
),
input = commandBus,
output = eventBus,
).startDrivers()
}
}
private fun initRepositories(): RepositorySet = when (val storageType = strEnv("STORAGE_TYPE")) {
"in_memory" -> RepositorySet(
deviceRepo = InMemoryDeviceRepository(),
programRepo = InMemoryProgramRepository(),
workoutRepo = InMemoryWorkoutRepository(),
workoutStateRepo = InMemoryWorkoutStateRepository(),
)
"mysql" -> makeDataSource(
url = strEnv("MYSQL_URL"),
username = strEnv("MYSQL_USERNAME"),
password = strEnv("MYSQL_PASSWORD"),
).run { RepositorySet(deviceRepo, programRepo, workoutRepo, workoutStateRepo) }
else -> error("Invalid storage type: $storageType")
}
private data class RepositorySet(
val deviceRepo: DeviceRepository,
val programRepo: ProgramRepository,
val workoutRepo: WorkoutRepository,
val workoutStateRepo: WorkoutStateRepository,
) {
fun workoutExporterOrNull(): WorkoutExporter? {
val exportTarget = makeExportTarget() ?: return null
log.info("Export target set: ${exportTarget.javaClass.simpleName}")
return WorkoutExporter(workoutRepo, workoutStateRepo, deviceRepo, programRepo, exportTarget)
}
private fun makeExportTarget(): ExportTarget? {
val indigo1Endpoint = optStrEnv("INDIGO1_ENDPOINT")
if (indigo1Endpoint != null) {
val clientId = strEnv("INDIGO1_CLIENT_ID")
val clientSecret = strEnv("INDIGO1_CLIENT_SECRET")
return Indigo1(indigo1Endpoint, clientId, clientSecret)
}
val indigo2Endpoint = optStrEnv("INDIGO2_HOST")
if (indigo2Endpoint != null) {
val tokenEndpoint = strEnv("INDIGO2_OIDC_TOKEN_ENDPOINT")
val clientId = strEnv("INDIGO2_OIDC_CLIENT_ID")
val clientSecret = strEnv("INDIGO2_OIDC_CLIENT_SECRET")
val autoClaim = (optStrEnv("INDIGO2_OIDC_AUTO_CLAIM")?.lowercase() ?: "false") in arrayOf("yes", "1", "true")
val calorieScale = (optStrEnv("INDIGO2_EXPORT_CALORIE_SCALE")?.toDoubleOrNull()) ?: 1.0
return Indigo2(
indigoHost = indigo2Endpoint,
oidcTokenEndpoint = tokenEndpoint,
oidcClientId = clientId,
oidcClientSecret = clientSecret,
autoClaim = autoClaim,
calorieScale = calorieScale,
)
}
return null
}
}