From 6915315192d30bce01c61866f76895ff7c9d6fe0 Mon Sep 17 00:00:00 2001 From: yenon Date: Fri, 10 Nov 2023 16:57:36 +0100 Subject: [PATCH] More shit. --- src/main/java/Main.kt | 10 +++++++ src/main/java/RaceHolder.kt | 59 ++++++++++++++++++++++++++++++++----- src/main/java/RacePage.kt | 59 ++++++++++++++++++++++++++++++++++--- 3 files changed, 117 insertions(+), 11 deletions(-) diff --git a/src/main/java/Main.kt b/src/main/java/Main.kt index f94b764..76a4a85 100644 --- a/src/main/java/Main.kt +++ b/src/main/java/Main.kt @@ -6,9 +6,19 @@ import io.ktor.server.cio.* import io.ktor.server.engine.* import io.ktor.server.response.* import io.ktor.server.routing.* +import java.nio.file.Files +import kotlin.io.path.Path suspend fun main() { + val path = Path("data.json") + + if (Files.isRegularFile(path)) { + RaceHolder.load(path) + } + Runtime.getRuntime().addShutdownHook(Thread { + RaceHolder.save(path) + }) val kord = Kord("MTE3MTIwODc1MDE5MTg5MDQ4Mw.GOUedL.i3zD6IG5B6fFRvaSOotWwJ5KBRK2whC9xr0vL8") kord.on { diff --git a/src/main/java/RaceHolder.kt b/src/main/java/RaceHolder.kt index b1adb67..e7bbafb 100644 --- a/src/main/java/RaceHolder.kt +++ b/src/main/java/RaceHolder.kt @@ -1,9 +1,15 @@ import kotlinx.serialization.Serializable +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.StandardOpenOption @Serializable data class RaceData(var name: String, var description: String) { - val trackList = arrayListOf() - val leaderboardMap = hashMapOf() + private val trackList = arrayListOf() + private val leaderboardMap = hashMapOf() + private var totalScores = arrayListOf>() fun addTrack(trackId: Long) { trackList.add(trackId) @@ -14,7 +20,7 @@ data class RaceData(var name: String, var description: String) { leaderboardMap.remove(trackId) } - suspend fun rescanLeaderboard(trackId: Long, newLeaderboardCallback: (Velocidrone.Leaderboard) -> Unit) { + private suspend fun rescanLeaderboard(trackId: Long, newLeaderboardCallback: (Velocidrone.Leaderboard) -> Unit) { if (trackList.contains(trackId)) { Velocidrone.getLeaderboardForId(trackId).getOrNull()?.let { newLeaderboard -> if (leaderboardMap[trackId]?.equals(newLeaderboard) == false) { @@ -25,17 +31,56 @@ data class RaceData(var name: String, var description: String) { } } - fun getTotalScores(): List> { + suspend fun rescanAll() { + var changes = false + trackList.forEach { + rescanLeaderboard(it) { + changes = true + } + } + if (changes) { + calculateTotalScores() + } + } + + fun calculateTotalScores() { val scoreMap = hashMapOf() leaderboardMap.forEach { leaderboardEntry -> - val sortedTimes = leaderboardEntry.value.tracktimes.sortedBy { it.lap_time }.forEach { + leaderboardEntry.value.tracktimes.sortedBy { it.lap_time }.forEach { scoreMap[it.playername] = scoreMap.getOrDefault(it.playername, 0L) + 1 } } - return scoreMap.toList().sortedByDescending { it.second } + synchronized(totalScores) { + totalScores.clear() + scoreMap.asIterable().sortedByDescending { it.value }.map { it.toPair() }.toCollection(totalScores) + } } } object RaceHolder { - val races = arrayListOf() + var races = arrayListOf() + + fun save(path: Path) { + val tempSavePath = path.resolveSibling("save.json.tmp") + val stream = Files.newBufferedWriter( + tempSavePath, + StandardOpenOption.TRUNCATE_EXISTING, + StandardOpenOption.WRITE, + StandardOpenOption.CREATE + ).buffered() + stream.write(Json.encodeToString(races)) + stream.flush() + stream.close() + + if (Files.isRegularFile(path)) { + Files.delete(path) + } + Files.move(tempSavePath, path) + } + + fun load(path: Path) { + val stream = Files.newBufferedReader(path) + races = Json.decodeFromString(stream.readText()) + stream.close() + } } \ No newline at end of file diff --git a/src/main/java/RacePage.kt b/src/main/java/RacePage.kt index dab23dc..7794982 100644 --- a/src/main/java/RacePage.kt +++ b/src/main/java/RacePage.kt @@ -1,14 +1,32 @@ import io.ktor.server.application.* +import io.ktor.server.request.* +import io.ktor.server.response.* import io.ktor.server.routing.* import io.ktor.util.pipeline.* -import kotlinx.html.div -import kotlinx.html.h1 -import kotlinx.html.p +import kotlinx.html.* fun Routing.racePage() { - get("/races") { + get("/race/list") { raceOverviewPage(RaceHolder.races) } + get("/race/new") { + newRacePage() + } + post("/race/new") { + val parameters = call.receiveParameters() + val name = parameters["name"] + val description = parameters["description"] + if (name == null || description == null) { + newRacePage("Not all parameters given.", name ?: "", description ?: "") + return@post + } + if (RaceHolder.races.any { it.name == name }) { + newRacePage("Race with the same name already exists.", name, description) + return@post + } + RaceHolder.races.add(RaceData(name, description)) + call.respondRedirect("/race/list") + } } private suspend fun PipelineContext.raceOverviewPage(races: ArrayList) { @@ -22,4 +40,37 @@ private suspend fun PipelineContext.raceOverviewPage(race } } } +} + +private suspend fun PipelineContext.newRacePage( + error: String? = null, + name: String = "", + description: String = "" +) { + respondThemedHtml("Race Overview") { + form("/race/new", encType = FormEncType.applicationXWwwFormUrlEncoded, method = FormMethod.post) { + error?.let { + p(classes = "error") { + +it + } + } + p { + +"Name:" + textInput(name = "name") { + value = name + } + } + p { + +"Description:" + } + p { + TEXTAREA(mapOf("name" to "description", "rows" to "4", "cols" to "40"), consumer).visit { + +description + } + } + p { + submitInput() + } + } + } } \ No newline at end of file