Refactor Leaderboard to Kotlin, leveraging Exposed library for database operations, and update LeaderboardManager for compatibility.
All checks were successful
SteamWarCI Build successful

Signed-off-by: Chaoscaot <max@maxsp.de>
This commit is contained in:
2025-11-11 17:39:39 +01:00
parent 5f7c5f0a18
commit d0c1413ea6
3 changed files with 98 additions and 75 deletions

View File

@@ -1,73 +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.util.List;
@AllArgsConstructor
@Getter
public class Leaderboard {
private static final Table<Leaderboard> table = new Table<>(Leaderboard.class);
private static final SelectStatement<Leaderboard> LEADERBOARD = new SelectStatement<>(table, "SELECT * from Leaderboard WHERE LeaderboardName = ? ORDER BY Time ASC LIMIT 5");
private static final SelectStatement<Leaderboard> PLAYER_TIME = new SelectStatement<>(table, "SELECT * FROM Leaderboard WHERE LeaderboardName = ? AND UserId = ?");
private static final Statement PLAYER_PLACEMENT = new Statement("SELECT COUNT(*) AS Placement FROM Leaderboard WHERE LeaderboardName = ? AND time < (SELECT time FROM UserConfig WHERE WHERE = ? AND LeaderboardName = ?)");
private static final Statement INSERT = new Statement("INSERT INTO Leaderboard (UserId, LeaderboardName, Time, BestTime) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE Time = VALUES(Time), BestTime = VALUES(BestTime)");
public static List<Leaderboard> getLeaderboard(String leaderboardName) {
return LEADERBOARD.listSelect(leaderboardName);
}
public static Leaderboard getPlayerTime(SteamwarUser user, String leaderboardName) {
return PLAYER_TIME.select(leaderboardName, user);
}
public static int getPlayerPlacement(SteamwarUser user, String leaderboardName) {
return PLAYER_PLACEMENT.select(rs -> {
if(!rs.next())
return Integer.MAX_VALUE;
return rs.getInt("Placement");
}, leaderboardName, user, leaderboardName);
}
public static void upsert(int userId, String leaderboardName, long time, boolean bestTime) {
INSERT.update(userId, leaderboardName, time, bestTime);
}
@Field(keys = Table.PRIMARY)
private final int userId;
@Field(keys = Table.PRIMARY)
private final String leaderboardName;
@Field
private final long time;
@Field
private final Timestamp updatedAt;
@Field
private final boolean bestTime;
}

View File

@@ -0,0 +1,96 @@
/*
* 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.SortOrder
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.count
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.lessSubQuery
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
import org.jetbrains.exposed.v1.javatime.CurrentTimestamp
import org.jetbrains.exposed.v1.javatime.timestamp
import org.jetbrains.exposed.v1.jdbc.select
object LeaderboardTable : CompositeIdTable("Leaderboard") {
val userId = reference("UserId", SteamwarUserTable)
val name = varchar("Name", 64).entityId()
val time = long("Time")
val updatedAt = timestamp("UpdatedAt").defaultExpression(CurrentTimestamp)
val bestTime = bool("BestTime")
}
class Leaderboard(id: EntityID<CompositeID>) : CompositeEntity(id) {
companion object : CompositeEntityClass<Leaderboard>(LeaderboardTable) {
@JvmStatic
fun getLeaderboard(name: String) = useDb {
find { LeaderboardTable.name eq name }.orderBy(LeaderboardTable.time to SortOrder.ASC).limit(5).toList()
}
@JvmStatic
fun getPlayerTime(user: SteamwarUser, name: String) = useDb {
findById(CompositeID {
it[LeaderboardTable.userId] = user.id.value
it[LeaderboardTable.name] = name
})
}
@JvmStatic
fun getPlayerPlacement(user: SteamwarUser, name: String) = useDb {
LeaderboardTable.select(LeaderboardTable.time.count())
.where {
(LeaderboardTable.name eq name) and (LeaderboardTable.time lessSubQuery LeaderboardTable.select(
LeaderboardTable.time
).where { (LeaderboardTable.userId eq user.id.value) and (LeaderboardTable.name eq name) })
}
.firstOrNull()?.get(LeaderboardTable.time.count())?.toInt() ?: Int.MAX_VALUE
}
@JvmStatic
fun upsert(userId: Int, name: String, time: Long, bestTime: Boolean) = useDb {
findByIdAndUpdate(CompositeID {
it[LeaderboardTable.userId] = userId
it[LeaderboardTable.name] = name
}) {
it.time = time
it.bestTime = bestTime
} ?: new(
CompositeID {
it[LeaderboardTable.userId] = userId
it[LeaderboardTable.name] = name
}
) {
this.time = time
this.bestTime = bestTime
}
}
}
val user by LeaderboardTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
val name by LeaderboardTable.name
var time by LeaderboardTable.time
var updatedAt by LeaderboardTable.updatedAt
var bestTime by LeaderboardTable.bestTime
}

View File

@@ -50,7 +50,7 @@ public class LeaderboardManager implements Listener {
this.server = server;
this.configKey = configKey;
this.location = location;
Bukkit.getPluginManager().registerEvents(this, LobbySystem.getPlugin());
Bukkit.getPluginManager().registerEvents(this, LobbySystem.getInstance());
update();
}
@@ -63,7 +63,7 @@ public class LeaderboardManager implements Listener {
for (int i = 0; i < leaderboard.size(); i++) {
Leaderboard entry = leaderboard.get(i);
RArmorStand entity = new RArmorStand(server, location.clone().add(0, (leaderboard.size() - i - 1) * 0.32, 0), RArmorStand.Size.MARKER);
SteamwarUser user = SteamwarUser.byId(entry.user);
SteamwarUser user = SteamwarUser.byId(entry.getUser());
String color = "§7";
if (i == 0) {
color = "§6§l";