package xyz.etztech.stonks import com.natpryce.konfig.* import java.io.FileInputStream import java.util.* import kotlinx.coroutines.* 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.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 periodicFetchingInterval = config.getProperty("periodicFetchingInterval").toLong() val minecraftStatsFolder = config.getProperty("minecraftStatsFolder") val database = initH2Server( databaseBaseDir, databaseName, h2TcpServerPort, h2StartWebServer, h2tWebServerPort) initApiServer(apiServerPort, database) initPeriodicFetching(periodicFetchingInterval, minecraftStatsFolder, database) delay(60 * 1000L) println("END") } fun initH2Server( databaseBaseDir: String, databaseName: String, h2TcpServerPort: Int, h2StartWebServer: Boolean, h2WebServerPort: Int ): Database { val webServer = Server.createWebServer( "-trace", "-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) // 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) {} } return database } suspend fun initPeriodicFetching(interval: Long, folder: String, db: Database) = coroutineScope { launch { while (true) { StatisticsImporter.importStatistics(folder, db) delay(interval) } } }