forked from Minecraft/Stonks
150 lines
4.9 KiB
Kotlin
150 lines
4.9 KiB
Kotlin
package xyz.etztech.stonks
|
|
|
|
import com.natpryce.konfig.*
|
|
import java.io.FileInputStream
|
|
import java.util.*
|
|
import kotlinx.coroutines.*
|
|
import kotlinx.serialization.*
|
|
import org.h2.tools.Server
|
|
import org.jetbrains.exposed.exceptions.ExposedSQLException
|
|
import org.jetbrains.exposed.sql.*
|
|
import org.jetbrains.exposed.sql.transactions.TransactionManager
|
|
import org.jetbrains.exposed.sql.transactions.transaction
|
|
import xyz.etztech.stonks.api.initApiServer
|
|
import xyz.etztech.stonks.dsl.AggregateStatistics
|
|
import xyz.etztech.stonks.dsl.KeyValue
|
|
import xyz.etztech.stonks.dsl.LiveStatistics
|
|
import xyz.etztech.stonks.dsl.Players
|
|
import xyz.etztech.stonks.dsl.Statistics
|
|
import xyz.etztech.stonks.statisticsimporter.StatisticsImporter
|
|
|
|
fun main() = runBlocking {
|
|
println("Starting Stonks...")
|
|
|
|
val fis = FileInputStream("./stonks.config")
|
|
val config = Properties()
|
|
|
|
config.load(fis)
|
|
|
|
val databaseBaseDir = config.getProperty("databaseBaseDir")
|
|
val databaseName = config.getProperty("databaseName")
|
|
val h2StartWebServer = config.getProperty("h2StartWebServer").toBoolean()
|
|
val h2tWebServerPort = config.getProperty("h2tWebServerPort").toInt()
|
|
val h2TcpServerPort = config.getProperty("h2TcpServerPort").toInt()
|
|
val apiServerPort = config.getProperty("apiServerPort").toInt()
|
|
val statisticsUpdateInterval = config.getProperty("statisticsUpdateInterval").toLong()
|
|
val minecraftStatsFolder = config.getProperty("minecraftStatsFolder")
|
|
|
|
val database =
|
|
initH2Server(
|
|
databaseBaseDir,
|
|
databaseName,
|
|
h2TcpServerPort,
|
|
h2StartWebServer,
|
|
h2tWebServerPort
|
|
)
|
|
|
|
initApiServer(apiServerPort, database)
|
|
|
|
initPeriodicFetching(statisticsUpdateInterval, minecraftStatsFolder, database)
|
|
|
|
delay(60 * 1000L)
|
|
|
|
println("END")
|
|
}
|
|
|
|
fun initH2Server(
|
|
databaseBaseDir: String,
|
|
databaseName: String,
|
|
h2TcpServerPort: Int,
|
|
h2StartWebServer: Boolean,
|
|
h2WebServerPort: Int
|
|
): Database {
|
|
val webServer =
|
|
Server.createWebServer(
|
|
"-baseDir",
|
|
databaseBaseDir,
|
|
"-webPort",
|
|
h2WebServerPort.toString()
|
|
)
|
|
|
|
val tcpServer =
|
|
Server.createTcpServer(
|
|
"-trace",
|
|
"-baseDir",
|
|
databaseBaseDir,
|
|
"-webPort",
|
|
h2TcpServerPort.toString()
|
|
)
|
|
|
|
if (h2StartWebServer) {
|
|
webServer.start()
|
|
println("H2 web interface started: ${webServer.getURL()}")
|
|
}
|
|
|
|
tcpServer.start()
|
|
println("H2 TCP endpoint started: ${tcpServer.getURL()}")
|
|
|
|
val database = Database.connect("jdbc:h2:$databaseBaseDir/$databaseName", "org.h2.Driver")
|
|
|
|
transaction {
|
|
addLogger(StdOutSqlLogger)
|
|
SchemaUtils.create(Statistics)
|
|
SchemaUtils.create(LiveStatistics)
|
|
SchemaUtils.create(AggregateStatistics)
|
|
SchemaUtils.create(Players)
|
|
SchemaUtils.create(KeyValue)
|
|
|
|
// Create indexes with explicit SQL because I can't figure out how to do it with exposed
|
|
// Wrap it in a try block because it throws an exception if index already exists
|
|
try {
|
|
TransactionManager.current()
|
|
.exec("CREATE INDEX idx_playerid ON Statistics (\"PlayerId\")")
|
|
} catch (e: ExposedSQLException) {}
|
|
|
|
try {
|
|
TransactionManager.current()
|
|
.exec("CREATE INDEX idx_type_name ON Statistics (\"Type\", \"Name\")")
|
|
} catch (e: ExposedSQLException) {}
|
|
|
|
try {
|
|
TransactionManager.current()
|
|
.exec("CREATE INDEX idx_playerid ON LiveStatistics (\"PlayerId\")")
|
|
} catch (e: ExposedSQLException) {}
|
|
|
|
try {
|
|
TransactionManager.current()
|
|
.exec("CREATE INDEX idx_type_name ON LiveStatistics (\"Type\", \"Name\")")
|
|
} catch (e: ExposedSQLException) {}
|
|
|
|
val schemaVersions =
|
|
KeyValue.slice(KeyValue.value).select { KeyValue.key.eq("SchemaVersion") }.map {
|
|
it[KeyValue.value]
|
|
}
|
|
val schemaVersion = if (schemaVersions.count() > 0) schemaVersions.single() else 0
|
|
println("Database schemaVersion = ${schemaVersion}")
|
|
|
|
if (schemaVersion < 1) {
|
|
println("Migrating database to schemaVersion 1.")
|
|
|
|
TransactionManager.current().exec("TRUNCATE TABLE AGGREGATESTATISTICS")
|
|
|
|
KeyValue.insert {
|
|
it[KeyValue.key] = "SchemaVersion"
|
|
it[KeyValue.value] = 1
|
|
}
|
|
}
|
|
}
|
|
|
|
return database
|
|
}
|
|
|
|
suspend fun initPeriodicFetching(interval: Long, folder: String, db: Database) = coroutineScope {
|
|
launch {
|
|
while (true) {
|
|
StatisticsImporter.importStatistics(folder, db)
|
|
delay(interval)
|
|
}
|
|
}
|
|
}
|