Migrate Event class to Kotlin and update references across modules

Signed-off-by: Chaoscaot <max@maxsp.de>
This commit is contained in:
2025-10-29 23:17:17 +01:00
parent 702aa1cfa6
commit eea1073892
10 changed files with 134 additions and 136 deletions
@@ -1,125 +0,0 @@
/*
* 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.sql;
import de.steamwar.sql.internal.Field;
import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.List;
@AllArgsConstructor
public class Event {
static {
SchematicType.Normal.name(); // Ensure SchematicType is loaded.
}
private static final Table<Event> table = new Table<>(Event.class);
private static final SelectStatement<Event> byCurrent = new SelectStatement<>(table, "SELECT * FROM Event WHERE Start < now() AND End > now()");
private static final SelectStatement<Event> byId = table.select(Table.PRIMARY);
private static final SelectStatement<Event> byName = table.select("eventName");
private static final SelectStatement<Event> byComing = new SelectStatement<>(table, "SELECT * FROM Event WHERE Start > now()");
private static final SelectStatement<Event> all = new SelectStatement<>(table, "SELECT * FROM Event");
private static final Statement create = table.insertFields(true, "eventName", "deadline", "start", "end", "maximumTeamMembers", "publicSchemsOnly");
private static final Statement update = table.update(Table.PRIMARY, "eventName", "deadline", "start", "end", "schemType", "maximumTeamMembers", "publicSchemsOnly");
private static final Statement delete = table.delete(Table.PRIMARY);
private static Event current = null;
public static Event get(){
if(current != null && current.now())
return current;
current = byCurrent.select();
return current;
}
public static List<Event> getAll(){
return all.listSelect();
}
public static Event create(String eventName, Timestamp start, Timestamp end){
return get(create.insertGetKey(eventName, start, start, end, 5, false));
}
public static Event get(int eventID){
return byId.select(eventID);
}
public static Event get(String eventName) {
return byName.select(eventName);
}
public static List<Event> getComing() {
return byComing.listSelect();
}
@Getter
@Field(keys = {Table.PRIMARY}, autoincrement = true)
private final int eventID;
@Getter
@Field(keys = {"eventName"})
private final String eventName;
@Getter
@Field
private final Timestamp deadline;
@Getter
@Field
private final Timestamp start;
@Getter
@Field
private final Timestamp end;
@Getter
@Field
private final int maximumTeamMembers;
@Field(nullable = true)
private final SchematicType schemType;
@Field
private final boolean publicSchemsOnly;
public boolean publicSchemsOnly() {
return publicSchemsOnly;
}
public SchematicType getSchematicType() {
return schemType;
}
private boolean now() {
Instant now = Instant.now();
return now.isAfter(start.toInstant()) && now.isBefore(end.toInstant());
}
public void update(String eventName, Timestamp deadline, Timestamp start, Timestamp end, SchematicType schemType, int maximumTeamMembers, boolean publicSchemsOnly) {
update.update(eventName, deadline, start, end, schemType, maximumTeamMembers, publicSchemsOnly, eventID);
}
public void delete() {
delete.update(eventID);
}
}
+123
View File
@@ -0,0 +1,123 @@
/*
* 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.sql
import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.greater
import org.jetbrains.exposed.v1.core.lessEq
import org.jetbrains.exposed.v1.dao.IntEntity
import org.jetbrains.exposed.v1.dao.IntEntityClass
import org.jetbrains.exposed.v1.javatime.timestamp
import org.jetbrains.exposed.v1.jdbc.insertAndGetId
import org.jetbrains.exposed.v1.jdbc.update
import java.sql.Timestamp
import java.time.Instant
import kotlin.math.max
object EventTable : IntIdTable("Event", "EventId") {
val name = varchar("EventName", 100).uniqueIndex()
val deadline = timestamp("Deadline")
val start = timestamp("Start")
val end = timestamp("End")
val maxPlayers = integer("MaximumTeamMembers")
val schemType = varchar("SchemType", 16).nullable()
val publicsOnly = bool("PublicSchemsOnly")
}
class Event(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<Event>(EventTable) {
private var current: Event? = null
@JvmStatic
fun get(): Event? = if (current?.now() == true) {
current
} else useDb {
find { EventTable.start.lessEq(Instant.now()) and EventTable.end.greater(Instant.now()) }.firstOrNull()
?.also { current == it }
}
@JvmStatic
fun getAll() = useDb { all().toList() }
@JvmStatic
fun create(name: String, start: Timestamp, end: Timestamp) = useDb {
EventTable.insertAndGetId {
it[this.name] = name
it[this.deadline] = start.toInstant()
it[this.start] = start.toInstant()
it[this.end] = end.toInstant()
it[this.maxPlayers] = 5
it[this.publicsOnly] = false
}.let { get(it) }
}
@JvmStatic
fun byId(id: Int) = useDb { findById(id) }
@JvmStatic
fun get(name: String) = useDb { find { EventTable.name eq name }.firstOrNull() }
@JvmStatic
fun getComing() = useDb { find { EventTable.start greater Instant.now() }.toList() }
}
val eventID by EventTable.id.transform({ EntityID(it, EventTable) }, { it.value })
var eventName by EventTable.name
private set
var deadline: Timestamp by EventTable.deadline.transform({ it.toInstant() }, { Timestamp.from(it) })
private set
var start: Timestamp by EventTable.start.transform({ it.toInstant() }, { Timestamp.from(it) })
private set
var end: Timestamp by EventTable.end.transform({ it.toInstant() }, { Timestamp.from(it) })
private set
var maximumTeamMembers by EventTable.maxPlayers
private set
var schematicType by EventTable.schemType.transform({ it?.toDB() }, { it?.let { SchematicType.fromDB(it) } })
private set
var publicSchemsOnly by EventTable.publicsOnly
private set
fun publicSchemsOnly() = publicSchemsOnly
fun now() = Instant.now().let { it.isAfter(start.toInstant()) && it.isBefore(end.toInstant()) }
fun update(
name: String,
deadline: Timestamp,
start: Timestamp,
end: Timestamp,
schematicType: SchematicType?,
maxPlayers: Int,
publicSchemsOnly: Boolean
) = useDb {
this@Event.eventName = name
this@Event.deadline = deadline
this@Event.start = start
this@Event.end = end
this@Event.maximumTeamMembers = maxPlayers
this@Event.schematicType = schematicType
this@Event.publicSchemsOnly = publicSchemsOnly
}
override fun delete() = useDb { super.delete() }
}
@@ -65,6 +65,6 @@ public class TeamTeilnahme {
} }
public static Set<Event> getEvents(int teamID){ public static Set<Event> getEvents(int teamID){
return selectEvents.listSelect(teamID).stream().map(tt -> Event.get(tt.eventId)).collect(Collectors.toSet()); // suboptimal performance (O(n) database queries) return selectEvents.listSelect(teamID).stream().map(tt -> Event.byId(tt.eventId)).collect(Collectors.toSet()); // suboptimal performance (O(n) database queries)
} }
} }
@@ -239,7 +239,7 @@ public class Config {
LiveReplay = SpectatePort != 0; LiveReplay = SpectatePort != 0;
Referees = Referee.get(Config.EventKampf.getEventID()); Referees = Referee.get(Config.EventKampf.getEventID());
Event event = Event.get(EventKampf.getEventID()); Event event = Event.byId(EventKampf.getEventID());
if(BothTeamsPublic) { if(BothTeamsPublic) {
OnlyPublicSchematics = true; OnlyPublicSchematics = true;
MaximumTeamMembers = Integer.MAX_VALUE; MaximumTeamMembers = Integer.MAX_VALUE;
@@ -123,7 +123,7 @@ public interface ParticleRequirement {
} }
static ParticleRequirement eventParticipation(int eventId) { static ParticleRequirement eventParticipation(int eventId) {
String eventName = Event.get(eventId).getEventName(); String eventName = Event.byId(eventId).getEventName();
return new ParticleRequirement() { return new ParticleRequirement() {
@Override @Override
public String getRequirementName(Player player) { public String getRequirementName(Player player) {
@@ -138,7 +138,7 @@ public interface ParticleRequirement {
} }
static ParticleRequirement eventPlacement(int eventId, int... placementTeams) { static ParticleRequirement eventPlacement(int eventId, int... placementTeams) {
String eventName = Event.get(eventId).getEventName(); String eventName = Event.byId(eventId).getEventName();
Set<Integer> teams = new HashSet<>(); Set<Integer> teams = new HashSet<>();
for (int i : placementTeams) teams.add(i); for (int i : placementTeams) teams.add(i);
return new ParticleRequirement() { return new ParticleRequirement() {
@@ -148,7 +148,7 @@ public class Config {
EventTeamBlueID = team1.getTeamId(); EventTeamBlueID = team1.getTeamId();
EventTeamRedID = team2.getTeamId(); EventTeamRedID = team2.getTeamId();
Event event = Event.get(EventKampf.getEventID()); Event event = Event.byId(EventKampf.getEventID());
if (EventTeamBlueID == 0 && EventTeamRedID == 0) { if (EventTeamBlueID == 0 && EventTeamRedID == 0) {
MaximumTeamMembers = Integer.MAX_VALUE; MaximumTeamMembers = Integer.MAX_VALUE;
} else { } else {
@@ -55,7 +55,7 @@ data class TNTLeagueConfig(
if (eventFightId != null && eventFightId > 0) { if (eventFightId != null && eventFightId > 0) {
eventFight = EventFight.get(eventFightId) ?: throw IllegalArgumentException("EventFight with ID $eventFightId not found") eventFight = EventFight.get(eventFightId) ?: throw IllegalArgumentException("EventFight with ID $eventFightId not found")
event = Event.get(eventFight.eventID) event = Event.byId(eventFight.eventID)!!
eventTeamBlue = Team.get(eventFight.teamBlue) eventTeamBlue = Team.get(eventFight.teamBlue)
eventTeamRed = Team.get(eventFight.teamRed) eventTeamRed = Team.get(eventFight.teamRed)
@@ -74,7 +74,7 @@ public class Config {
throw new IllegalStateException("Event not found"); throw new IllegalStateException("Event not found");
} }
Event event = Event.get(EVENT_FIGHT.getEventID()); Event event = Event.byId(EVENT_FIGHT.getEventID());
EVENT_TEAM_BLUE_ID = EVENT_FIGHT.getTeamBlue(); EVENT_TEAM_BLUE_ID = EVENT_FIGHT.getTeamBlue();
EVENT_TEAM_RED_ID = EVENT_FIGHT.getTeamRed(); EVENT_TEAM_RED_ID = EVENT_FIGHT.getTeamRed();
@@ -55,7 +55,7 @@ public class DiscordTeamEvent extends ListenerAdapter {
return; return;
} }
Event tournament = Event.get(eventId); Event tournament = Event.byId(eventId);
if(tournament == null){ if(tournament == null){
reply.system("UNKNOWN_EVENT"); reply.system("UNKNOWN_EVENT");
return; return;
@@ -231,7 +231,7 @@ fun Route.configureEventsRoute() {
} }
} }
event.update(eventName, deadline, start, end, schemType, maxTeamMembers, publicSchemsOnly) event.update(eventName, deadline, start, end, schemType, maxTeamMembers, publicSchemsOnly)
call.respond(ResponseEvent(Event.get(event.eventID))) call.respond(ResponseEvent(Event.byId(event.eventID)!!))
} }
delete { delete {
val id = call.parameters["id"]?.toIntOrNull() val id = call.parameters["id"]?.toIntOrNull()
@@ -239,7 +239,7 @@ fun Route.configureEventsRoute() {
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid ID")) call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid ID"))
return@delete return@delete
} }
val event = Event.get(id) val event = Event.byId(id)
if (event == null) { if (event == null) {
call.respond(HttpStatusCode.NotFound, ResponseError("Event not found")) call.respond(HttpStatusCode.NotFound, ResponseError("Event not found"))
return@delete return@delete
@@ -263,7 +263,7 @@ suspend fun ApplicationCall.receiveEvent(fieldName: String = "id"): Event? {
return null return null
} }
val event = Event.get(eventId) val event = Event.byId(eventId)
if (event == null) { if (event == null) {
respond(HttpStatusCode.NotFound, ResponseError("Event not found")) respond(HttpStatusCode.NotFound, ResponseError("Event not found"))
return null return null