/* * 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 . */ package de.steamwar.routes import de.steamwar.ResponseError import de.steamwar.sql.* 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 ) { constructor(eventFight: EventFight) : this( eventFight.fightID, eventFight.spielmodus, eventFight.map, ResponseTeam(Team.get(eventFight.teamBlue)), ResponseTeam(Team.get(eventFight.teamRed)), eventFight.startTime.time, eventFight.ergebnis, eventFight.spectatePort, eventFight.group.orElse(null)?.let { ResponseGroups(it, short = true) }, eventFight.hasFinished() ) } @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() 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() 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.get(fightId) if (fight == null) { respond(HttpStatusCode.NotFound, ResponseError("Fight not found")) return null } return fight }