diff --git a/CommonCore/SQL/src/de/steamwar/sql/Event.java b/CommonCore/SQL/src/de/steamwar/sql/Event.java
deleted file mode 100644
index e65a1533..00000000
--- a/CommonCore/SQL/src/de/steamwar/sql/Event.java
+++ /dev/null
@@ -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 .
- */
-
-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 table = new Table<>(Event.class);
-
- private static final SelectStatement byCurrent = new SelectStatement<>(table, "SELECT * FROM Event WHERE Start < now() AND End > now()");
- private static final SelectStatement byId = table.select(Table.PRIMARY);
- private static final SelectStatement byName = table.select("eventName");
- private static final SelectStatement byComing = new SelectStatement<>(table, "SELECT * FROM Event WHERE Start > now()");
- private static final SelectStatement 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 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 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);
- }
-}
diff --git a/CommonCore/SQL/src/de/steamwar/sql/Event.kt b/CommonCore/SQL/src/de/steamwar/sql/Event.kt
new file mode 100644
index 00000000..5ca83078
--- /dev/null
+++ b/CommonCore/SQL/src/de/steamwar/sql/Event.kt
@@ -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 .
+ */
+
+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) : IntEntity(id) {
+ companion object : IntEntityClass(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() }
+}
\ No newline at end of file
diff --git a/CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java b/CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java
index 499a1a66..620710ff 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java
+++ b/CommonCore/SQL/src/de/steamwar/sql/TeamTeilnahme.java
@@ -65,6 +65,6 @@ public class TeamTeilnahme {
}
public static Set 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)
}
}
diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/Config.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/Config.java
index a5c89bca..8d2b722d 100644
--- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/Config.java
+++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/Config.java
@@ -239,7 +239,7 @@ public class Config {
LiveReplay = SpectatePort != 0;
Referees = Referee.get(Config.EventKampf.getEventID());
- Event event = Event.get(EventKampf.getEventID());
+ Event event = Event.byId(EventKampf.getEventID());
if(BothTeamsPublic) {
OnlyPublicSchematics = true;
MaximumTeamMembers = Integer.MAX_VALUE;
diff --git a/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java b/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java
index 1ac5679a..754f5d2b 100644
--- a/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java
+++ b/LobbySystem/src/de/steamwar/lobby/particle/ParticleRequirement.java
@@ -123,7 +123,7 @@ public interface ParticleRequirement {
}
static ParticleRequirement eventParticipation(int eventId) {
- String eventName = Event.get(eventId).getEventName();
+ String eventName = Event.byId(eventId).getEventName();
return new ParticleRequirement() {
@Override
public String getRequirementName(Player player) {
@@ -138,7 +138,7 @@ public interface ParticleRequirement {
}
static ParticleRequirement eventPlacement(int eventId, int... placementTeams) {
- String eventName = Event.get(eventId).getEventName();
+ String eventName = Event.byId(eventId).getEventName();
Set teams = new HashSet<>();
for (int i : placementTeams) teams.add(i);
return new ParticleRequirement() {
diff --git a/MissileWars/src/de/steamwar/misslewars/Config.java b/MissileWars/src/de/steamwar/misslewars/Config.java
index b9ebc688..eb223c5d 100644
--- a/MissileWars/src/de/steamwar/misslewars/Config.java
+++ b/MissileWars/src/de/steamwar/misslewars/Config.java
@@ -148,7 +148,7 @@ public class Config {
EventTeamBlueID = team1.getTeamId();
EventTeamRedID = team2.getTeamId();
- Event event = Event.get(EventKampf.getEventID());
+ Event event = Event.byId(EventKampf.getEventID());
if (EventTeamBlueID == 0 && EventTeamRedID == 0) {
MaximumTeamMembers = Integer.MAX_VALUE;
} else {
diff --git a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt
index 3f51d535..7f0e7526 100644
--- a/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt
+++ b/TNTLeague/src/de/steamwar/tntleague/config/TNTLeagueConfig.kt
@@ -55,7 +55,7 @@ data class TNTLeagueConfig(
if (eventFightId != null && eventFightId > 0) {
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)
eventTeamRed = Team.get(eventFight.teamRed)
diff --git a/TowerRun/src/de/steamwar/towerrun/config/Config.java b/TowerRun/src/de/steamwar/towerrun/config/Config.java
index 1d262066..7a7b6795 100644
--- a/TowerRun/src/de/steamwar/towerrun/config/Config.java
+++ b/TowerRun/src/de/steamwar/towerrun/config/Config.java
@@ -74,7 +74,7 @@ public class Config {
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_RED_ID = EVENT_FIGHT.getTeamRed();
diff --git a/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordTeamEvent.java b/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordTeamEvent.java
index 146c06d0..8e0f3955 100644
--- a/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordTeamEvent.java
+++ b/VelocityCore/src/de/steamwar/velocitycore/discord/listeners/DiscordTeamEvent.java
@@ -55,7 +55,7 @@ public class DiscordTeamEvent extends ListenerAdapter {
return;
}
- Event tournament = Event.get(eventId);
+ Event tournament = Event.byId(eventId);
if(tournament == null){
reply.system("UNKNOWN_EVENT");
return;
diff --git a/WebsiteBackend/src/de/steamwar/routes/Events.kt b/WebsiteBackend/src/de/steamwar/routes/Events.kt
index ed5ad9ef..faeae862 100644
--- a/WebsiteBackend/src/de/steamwar/routes/Events.kt
+++ b/WebsiteBackend/src/de/steamwar/routes/Events.kt
@@ -231,7 +231,7 @@ fun Route.configureEventsRoute() {
}
}
event.update(eventName, deadline, start, end, schemType, maxTeamMembers, publicSchemsOnly)
- call.respond(ResponseEvent(Event.get(event.eventID)))
+ call.respond(ResponseEvent(Event.byId(event.eventID)!!))
}
delete {
val id = call.parameters["id"]?.toIntOrNull()
@@ -239,7 +239,7 @@ fun Route.configureEventsRoute() {
call.respond(HttpStatusCode.BadRequest, ResponseError("Invalid ID"))
return@delete
}
- val event = Event.get(id)
+ val event = Event.byId(id)
if (event == null) {
call.respond(HttpStatusCode.NotFound, ResponseError("Event not found"))
return@delete
@@ -263,7 +263,7 @@ suspend fun ApplicationCall.receiveEvent(fieldName: String = "id"): Event? {
return null
}
- val event = Event.get(eventId)
+ val event = Event.byId(eventId)
if (event == null) {
respond(HttpStatusCode.NotFound, ResponseError("Event not found"))
return null