forked from SteamWar/SteamWar
209 lines
6.8 KiB
Kotlin
209 lines
6.8 KiB
Kotlin
/*
|
|
* This file is a part of the SteamWar software.
|
|
*
|
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package de.steamwar.routes
|
|
|
|
import de.steamwar.ResponseError
|
|
import de.steamwar.data.EventCache
|
|
import de.steamwar.sql.*
|
|
import de.steamwar.sql.internal.useDb
|
|
import io.ktor.http.*
|
|
import io.ktor.server.application.*
|
|
import io.ktor.server.request.*
|
|
import io.ktor.server.response.*
|
|
import io.ktor.server.routing.*
|
|
import kotlinx.serialization.Serializable
|
|
import java.sql.Timestamp
|
|
import java.time.Instant
|
|
|
|
@Serializable
|
|
data class ResponseEventFight(
|
|
val id: Int,
|
|
val spielmodus: String,
|
|
val map: String,
|
|
val blueTeam: ResponseTeam,
|
|
val redTeam: ResponseTeam,
|
|
val start: Long,
|
|
val ergebnis: Int,
|
|
val spectatePort: Int?,
|
|
val group: ResponseGroups?,
|
|
val hasFinished: Boolean,
|
|
val fightData: FightData? = null
|
|
) {
|
|
constructor(eventFight: EventFight, cache: EventCache = EventCache()) : this(
|
|
eventFight.fightID,
|
|
eventFight.spielmodus,
|
|
eventFight.map,
|
|
cache.getTeam(eventFight.teamBlue),
|
|
cache.getTeam(eventFight.teamRed),
|
|
eventFight.startTime.time,
|
|
eventFight.ergebnis,
|
|
eventFight.spectatePort,
|
|
eventFight.groupId?.let { cache.getGroup(it.value) },
|
|
eventFight.hasFinished(),
|
|
eventFight.fight?.let { FightData(Fight.getById(it)) }
|
|
)
|
|
}
|
|
|
|
@Serializable
|
|
data class FightData(
|
|
val id: Int,
|
|
val gamemode: String,
|
|
val server: String,
|
|
val start: Long,
|
|
val duration: Int,
|
|
val blueLeader: ResponseUser,
|
|
val redLeader: ResponseUser,
|
|
val blueSchem: String?,
|
|
val redSchem: String?,
|
|
val win: String,
|
|
val winCondition: String,
|
|
|
|
val bluePlayers: List<ResponseUser>,
|
|
val redPlayers: List<ResponseUser>,
|
|
) {
|
|
constructor(fight: Fight) : this(
|
|
fight.id.value,
|
|
fight.gameMode,
|
|
fight.server,
|
|
fight.startTime.time,
|
|
fight.duration,
|
|
ResponseUser.get(fight.blueLeader),
|
|
ResponseUser.get(fight.redLeader),
|
|
fight.blueSchem?.let { SchematicNode.getSchematicNode(it.value)?.name },
|
|
fight.redSchem?.let { SchematicNode.getSchematicNode(it.value)?.name },
|
|
fight.winner.name,
|
|
fight.winCondition,
|
|
fight.bluePlayers.map { ResponseUser.get(it.userID) },
|
|
fight.redPlayers.map { ResponseUser.get(it.userID) },
|
|
)
|
|
}
|
|
|
|
@Serializable
|
|
data class ResponseTeam(val id: Int, val name: String, val kuerzel: String, val color: String) {
|
|
constructor(team: Team) : this(team.teamId, team.teamName, team.teamKuerzel, team.teamColor)
|
|
}
|
|
|
|
@Serializable
|
|
data class UpdateEventFight(
|
|
val blueTeam: Int? = null,
|
|
val redTeam: Int? = null,
|
|
val start: Long? = null,
|
|
val spielmodus: String? = null,
|
|
val map: String? = null,
|
|
val group: Int? = null,
|
|
val spectatePort: Int? = null,
|
|
val ergebnis: Int? = null,
|
|
)
|
|
|
|
@Serializable
|
|
data class CreateEventFight(
|
|
val spielmodus: String,
|
|
val map: String,
|
|
val blueTeam: Int,
|
|
val redTeam: Int,
|
|
val start: Long,
|
|
val spectatePort: Int? = null,
|
|
val group: Int? = null
|
|
)
|
|
|
|
fun Route.configureEventFightRoutes() {
|
|
route("/fights") {
|
|
get {
|
|
val event = call.receiveEvent() ?: return@get
|
|
call.respond(EventFight.getEvent(event.eventID).map { ResponseEventFight(it) })
|
|
}
|
|
post {
|
|
val event = call.receiveEvent() ?: return@post
|
|
|
|
val fight = call.receiveNullable<CreateEventFight>()
|
|
if (fight == null) {
|
|
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid body"))
|
|
return@post
|
|
}
|
|
|
|
val eventFight = EventFight.create(
|
|
event.eventID,
|
|
Timestamp.from(Instant.ofEpochMilli(fight.start)),
|
|
fight.spielmodus,
|
|
fight.map,
|
|
fight.blueTeam,
|
|
fight.redTeam,
|
|
fight.spectatePort
|
|
)
|
|
if (fight.group != null) {
|
|
eventFight.setGroup(fight.group)
|
|
}
|
|
call.respond(HttpStatusCode.Created, ResponseEventFight(eventFight))
|
|
}
|
|
route("/{fight}") {
|
|
put {
|
|
val fight = call.receiveFight() ?: return@put
|
|
val updateFight = call.receiveNullable<UpdateEventFight>()
|
|
if (updateFight == null) {
|
|
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid body"))
|
|
return@put
|
|
}
|
|
|
|
val teamBlue = updateFight.blueTeam ?: fight.teamBlue
|
|
val teamRed = updateFight.redTeam ?: fight.teamRed
|
|
val start = updateFight.start?.let { Timestamp.from(Instant.ofEpochMilli(it)) } ?: fight.startTime
|
|
val spielmodus = updateFight.spielmodus ?: fight.spielmodus
|
|
val map = updateFight.map ?: fight.map
|
|
val spectatePort = updateFight.spectatePort ?: fight.spectatePort
|
|
|
|
if (updateFight.group != null) {
|
|
if (updateFight.group == -1) {
|
|
fight.setGroup(null)
|
|
} else {
|
|
fight.setGroup(updateFight.group)
|
|
}
|
|
}
|
|
|
|
if (updateFight.ergebnis != null) {
|
|
fight.ergebnis = updateFight.ergebnis
|
|
}
|
|
|
|
fight.update(start, spielmodus, map, teamBlue, teamRed, spectatePort)
|
|
call.respond(HttpStatusCode.OK, ResponseEventFight(fight))
|
|
}
|
|
delete {
|
|
val fight = call.receiveFight() ?: return@delete
|
|
fight.delete()
|
|
call.respond(HttpStatusCode.OK)
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
suspend fun ApplicationCall.receiveFight(fieldName: String = "fight"): EventFight? {
|
|
val fightId = parameters[fieldName]?.toIntOrNull()
|
|
if (fightId == null) {
|
|
respond(HttpStatusCode.BadRequest, ResponseError("Invalid fight ID"))
|
|
return null
|
|
}
|
|
|
|
val fight = EventFight.byId(fightId)
|
|
if (fight == null) {
|
|
respond(HttpStatusCode.NotFound, ResponseError("Fight not found"))
|
|
return null
|
|
}
|
|
return fight
|
|
} |