diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchemElo.kt b/CommonCore/SQL/src/de/steamwar/sql/SchemElo.kt
deleted file mode 100644
index b187186b..00000000
--- a/CommonCore/SQL/src/de/steamwar/sql/SchemElo.kt
+++ /dev/null
@@ -1,74 +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.useDb
-import org.jetbrains.exposed.v1.core.and
-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.dao.CompositeEntity
-import org.jetbrains.exposed.v1.dao.CompositeEntityClass
-import org.jetbrains.exposed.v1.jdbc.insertIgnore
-
-object SchemEloTable: CompositeIdTable("SchemElo") {
- val schemId = reference("SchemId", SchematicNodeTable)
- val season = integer("Season").entityId()
- val elo = integer("Elo")
-
- override val primaryKey = PrimaryKey(schemId, season)
-
- init {
- addIdColumn(schemId)
- }
-}
-
-class SchemElo(id: EntityID): CompositeEntity(id) {
- companion object: CompositeEntityClass(SchemEloTable) {
- @JvmStatic
- fun getElo(node: SchematicNode, season: Int, defaultElo: Int = 0) = useDb {
- find { (SchemEloTable.schemId eq node.id) and (SchemEloTable.season eq season) }.firstOrNull()?.elo ?: defaultElo
- }
-
- @JvmStatic
- fun getCurrentElo(schemId: Int) = getElo(SchematicNode.byId(schemId)!!, Season.getSeason())
-
- @JvmStatic
- fun setElo(node: Int, elo: Int) = useDb {
- findByIdAndUpdate(CompositeID {
- it[SchemEloTable.schemId] = node
- it[SchemEloTable.season] = Season.getSeason()
- }) {
- it.elo = elo
- } ?: SchemEloTable.insertIgnore {
- it[SchemEloTable.schemId] = node
- it[SchemEloTable.season] = Season.getSeason()
- it[SchemEloTable.elo] = elo
- }
-
- return@useDb
- }
- }
-
- var node by SchemEloTable.schemId
- var season by SchemEloTable.season
- var elo by SchemEloTable.elo
-}
\ No newline at end of file
diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt
index 96fd0901..8cc0363f 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt
+++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt
@@ -365,8 +365,6 @@ class SchematicNode(id: EntityID) : IntEntity(id) {
}
}
- fun getElo(season: Int) = SchemElo.getElo(this, season)
-
override fun delete() = useDb {
super.delete()
}
diff --git a/CommonCore/SQL/src/de/steamwar/sql/UserElo.kt b/CommonCore/SQL/src/de/steamwar/sql/UserElo.kt
deleted file mode 100644
index 84441f46..00000000
--- a/CommonCore/SQL/src/de/steamwar/sql/UserElo.kt
+++ /dev/null
@@ -1,170 +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.useDb
-import org.jetbrains.exposed.v1.core.*
-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.dao.CompositeEntity
-import org.jetbrains.exposed.v1.dao.CompositeEntityClass
-import org.jetbrains.exposed.v1.jdbc.insertIgnore
-import org.jetbrains.exposed.v1.jdbc.select
-import java.util.concurrent.ConcurrentHashMap
-
-object UserEloTable : CompositeIdTable("UserElo") {
- val season = integer("Season").entityId()
- val gameMode = varchar("GameMode", 16).entityId()
- val userId = reference("UserID", SteamwarUserTable)
- val elo = integer("Elo")
-
- override val primaryKey = PrimaryKey(season, gameMode, userId)
-
- init {
- addIdColumn(season)
- addIdColumn(gameMode)
- }
-}
-
-class UserElo(id: EntityID) : CompositeEntity(id) {
- companion object : CompositeEntityClass(UserEloTable) {
- private const val ELO_DEFAULT = 0
-
- private val gameModeUserEloCache: MutableMap> = ConcurrentHashMap()
- private val emblemCache: MutableMap = ConcurrentHashMap()
-
- @JvmStatic
- fun clear() {
- gameModeUserEloCache.clear()
- emblemCache.clear()
- }
-
- @JvmStatic
- fun getEloOrDefault(userId: Int, gameMode: String) =
- getElo(userId, gameMode) ?: ELO_DEFAULT
-
- @JvmStatic
- fun getElo(userId: Int, gameMode: String) =
- gameModeUserEloCache.getOrPut(gameMode) { mutableMapOf() }
- .getOrPut(userId) { getEloFromDb(userId, gameMode)?.elo }
-
- private fun getEloFromDb(userId: Int, gameMode: String) = useDb {
- find { (UserEloTable.userId eq userId) and (UserEloTable.gameMode eq gameMode) and (UserEloTable.season eq Season.getSeason()) }.firstOrNull()
- }
-
- @JvmStatic
- fun getFightsOfSeason(userId: Int, gamemode: String) = useDb {
- exec(
- "SELECT COUNT(*) AS Fights FROM FightPlayer INNER JOIN Fight F on FightPlayer.FightID = F.FightID WHERE UserID = ? AND GameMode = ? AND UNIX_TIMESTAMP(StartTime) + Duration >= UNIX_TIMESTAMP(?)",
- args = listOf(
- IntegerColumnType() to userId,
- VarCharColumnType() to gamemode,
- VarCharColumnType() to Season.getSeasonStart()
- )
- ) {
- return@exec if (it.next()) {
- it.getInt("Fights")
- } else {
- 0
- }
- } ?: 0
- }
-
- @JvmStatic
- fun setElo(userId: Int, gameMode: String, elo: Int) {
- emblemCache.remove(userId)
- gameModeUserEloCache.getOrDefault(gameMode, mutableMapOf()).remove(userId)
- useDb {
- findByIdAndUpdate(CompositeID {
- it[UserEloTable.userId] = userId
- it[UserEloTable.gameMode] = gameMode
- it[UserEloTable.season] = Season.getSeason()
- }) {
- it.elo = elo
- } ?: UserEloTable.insertIgnore {
- it[UserEloTable.userId] = userId
- it[UserEloTable.gameMode] = gameMode
- it[UserEloTable.season] = Season.getSeason()
- it[UserEloTable.elo] = elo
- }
- }
- }
-
- @JvmStatic
- fun getPlacement(elo: Int, gamemode: String) = useDb {
- UserEloTable.select(UserEloTable.userId.count()).where {
- (UserEloTable.gameMode eq gamemode) and (UserEloTable.elo greater elo) and (UserEloTable.season eq Season.getSeason())
- }.firstOrNull()?.get(UserEloTable.userId.count())?.let { it + 1 }?.toInt() ?: -1
- }
-
- @JvmStatic
- fun getEmblem(user: SteamwarUser, rankedModes: List) =
- emblemCache.getOrPut(user.id.value) {
- var emblemProgression = -1
- for (mode in rankedModes) {
- if (getFightsOfSeason(user.id.value, mode) == 0) continue
- val progression = getProgression(user.id.value, mode)
- if (progression > emblemProgression) {
- emblemProgression = progression
- }
- }
- return toEmblem(emblemProgression)
- }
-
- @JvmStatic
- fun getEmblemProgression(gameMode: String, userId: Int): String =
- when (getProgression(userId, gameMode)) {
- -1 -> "§8❱❱❱❱ ❂"
- 0 -> "§e❱§8❱❱❱ ❂"
- 1 -> "§e❱❱§8❱❱ ❂"
- 2 -> "§e❱❱❱§8❱ ❂"
- 3 -> "§e❱❱❱❱§8 ❂"
- 4 -> "§8❱❱❱❱ §5❂"
- else -> throw SecurityException("Progression is not in range")
- }
-
-
- @JvmStatic
- fun getProgression(userId: Int, gameMode: String) = useDb { getElo(userId, gameMode) ?: -1 }.let {
- when {
- it < 0 -> -1
- it < 150 -> 0
- it < 350 -> 1
- it < 600 -> 2
- it < 900 -> 3
- else -> 4
- }
- }
-
- @JvmStatic
- fun toEmblem(progression: Int) = when (progression) {
- -1 -> ""
- 0 -> "§e❱ "
- 1 -> "§e❱❱ "
- 2 -> "§e❱❱❱ "
- 3 -> "§e❱❱❱❱ "
- 4 -> "§5❂ "
- else -> throw SecurityException("Progression out of range")
- }
- }
-
- var elo by UserEloTable.elo
-}
\ No newline at end of file
diff --git a/SchematicSystem/SchematicSystem_Core/src/SchematicSystem.properties b/SchematicSystem/SchematicSystem_Core/src/SchematicSystem.properties
index 6115198f..0ff05daa 100644
--- a/SchematicSystem/SchematicSystem_Core/src/SchematicSystem.properties
+++ b/SchematicSystem/SchematicSystem_Core/src/SchematicSystem.properties
@@ -59,7 +59,6 @@ UTIL_INFO_TYPE_DIR=§eDIR
UTIL_INFO_RANK=§7Rank: §e{0}
UTIL_INFO_COLOR=§7Color translation: {0}
UTIL_INFO_REPLAY=§7Replay playback: {0}
-UTIL_INFO_ELO=§7Elo: §e{0}
UTIL_INFO_FORMAT=§7Format: §e{0}
UTIL_INFO_STATUS=§cState: §c{0}: {1}
UTIL_INFO_MEMBER=§7Members: §e{0}
diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicCommandUtils.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicCommandUtils.java
index fa9ccb42..d52a5569 100644
--- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicCommandUtils.java
+++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/commands/schematiccommand/SchematicCommandUtils.java
@@ -248,7 +248,6 @@ public class SchematicCommandUtils {
if (node.getSchemtype().fightType()) {
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_COLOR", player, SchematicSystem.MESSAGE.parse(node.replaceColor() ? "ON" : "OFF", player));
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_REPLAY", player, SchematicSystem.MESSAGE.parse(node.allowReplay() ? "ON" : "OFF", player));
- SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_ELO", player, node.getElo(Season.getSeason()));
}
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_FORMAT", player, node.getFileEnding());
diff --git a/VelocityCore/src/de/steamwar/velocitycore/VelocityCore.java b/VelocityCore/src/de/steamwar/velocitycore/VelocityCore.java
index ed3f9ade..b38ff66e 100644
--- a/VelocityCore/src/de/steamwar/velocitycore/VelocityCore.java
+++ b/VelocityCore/src/de/steamwar/velocitycore/VelocityCore.java
@@ -38,7 +38,6 @@ import de.steamwar.persistent.ReloadablePlugin;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Team;
-import de.steamwar.sql.UserElo;
import de.steamwar.sql.internal.Statement;
import de.steamwar.velocitycore.commands.PunishmentCommand;
import de.steamwar.velocitycore.commands.ServerSwitchCommand;
@@ -184,7 +183,6 @@ public class VelocityCore implements ReloadablePlugin {
schedule(() -> {
SteamwarUser.clear();
- UserElo.clear();
Team.clear();
}).repeat(1, TimeUnit.HOURS).schedule();
diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/RankCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/RankCommand.java
deleted file mode 100644
index fc96c478..00000000
--- a/VelocityCore/src/de/steamwar/velocitycore/commands/RankCommand.java
+++ /dev/null
@@ -1,68 +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.velocitycore.commands;
-
-import de.steamwar.command.SWCommand;
-import de.steamwar.linkage.Linked;
-import de.steamwar.messages.Chatter;
-import de.steamwar.messages.Message;
-import de.steamwar.sql.GameModeConfig;
-import de.steamwar.sql.Season;
-import de.steamwar.sql.SteamwarUser;
-import de.steamwar.sql.UserElo;
-import de.steamwar.velocitycore.ArenaMode;
-
-@Linked
-public class RankCommand extends SWCommand {
-
- public RankCommand() {
- super("rank");
- }
-
- @Register
- public void ownRank(Chatter sender) {
- rank(sender, sender.user());
- }
-
- @Register
- public void rank(Chatter sender, @ErrorMessage("RANK_PLAYER_NOT_FOUND") SteamwarUser user) {
- if (!sender.user().equals(user)) {
- sender.prefixless("RANK_PLAYER_FOUND", user, Season.convertSeasonToString(Season.getSeason()));
- } else {
- sender.prefixless("RANK_PLAYER_SELF", Season.convertSeasonToString(Season.getSeason()));
- }
-
- for(GameModeConfig mode : ArenaMode.getAllModes()) {
- if (!mode.Server.Ranked)
- continue;
-
- Integer elo = UserElo.getElo(user.getId(), mode.getSchemTypeOrInternalName());
- Message eloMsg;
- if (elo != null) {
- int placement = UserElo.getPlacement(elo, mode.getSchemTypeOrInternalName());
- eloMsg = new Message("RANK_PLACED", placement, elo);
- } else {
- eloMsg = new Message("RANK_UNPLACED");
- }
-
- sender.prefixless("RANK_DATA", UserElo.getEmblemProgression(mode.getChatName(), user.getId()), mode.getChatName(), eloMsg);
- }
- }
-}
diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java
index 95a65761..93a376cf 100644
--- a/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java
+++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/ChatListener.java
@@ -248,7 +248,7 @@ public class ChatListener extends BasicListener {
msgReceiver == null ? receiver : msgReceiver,
highlightMentions(message, chatColorCode, receiver),
sender.getTeam() == 0 ? "" : "§" + Team.byId(sender.getTeam()).getTeamColor() + Team.byId(sender.getTeam()).getTeamKuerzel() + " ",
- UserElo.getEmblem(sender, rankedModes),
+ "",
prefix.getColorCode(),
prefix.getChatPrefix().length() == 0 ? "§f" : prefix.getChatPrefix() + " ",
chatColorCode);
diff --git a/VelocityCore/src/de/steamwar/velocitycore/network/handlers/EloPlayerHandler.java b/VelocityCore/src/de/steamwar/velocitycore/network/handlers/EloPlayerHandler.java
deleted file mode 100644
index 2925ee34..00000000
--- a/VelocityCore/src/de/steamwar/velocitycore/network/handlers/EloPlayerHandler.java
+++ /dev/null
@@ -1,261 +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.velocitycore.network.handlers;
-
-import com.velocitypowered.api.proxy.Player;
-import de.steamwar.sql.GameModeConfig;
-import de.steamwar.linkage.Linked;
-import de.steamwar.messages.Chatter;
-import de.steamwar.network.packets.PacketHandler;
-import de.steamwar.network.packets.common.FightEndsPacket;
-import de.steamwar.sql.SchematicType;
-import de.steamwar.sql.SteamwarUser;
-import de.steamwar.sql.UserElo;
-import de.steamwar.velocitycore.ArenaMode;
-import de.steamwar.velocitycore.VelocityCore;
-import lombok.RequiredArgsConstructor;
-import net.kyori.adventure.text.Component;
-import net.kyori.adventure.title.Title;
-
-import java.time.Duration;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.function.IntFunction;
-import java.util.stream.Collectors;
-
-@Linked
-public class EloPlayerHandler extends PacketHandler {
-
- private static final int MEDIAN_ELO_GAIN = 40;
- private static final int MEDIAN_ELO_LOSE = 20;
- private static final long REMATCH_LIFETIME = (long) 60 * 60 * 1000;
-
- private final Map> gameModeGames = new HashMap<>();
-
- /**
- * {@link FightEndsPacket#getWin()} == 1 -> Blue won
- * {@link FightEndsPacket#getWin()} == 2 -> Red won
- */
- @Handler
- public void handle(FightEndsPacket fightEndsPacket) {
- SchematicType schematicType = SchematicType.fromDB(fightEndsPacket.getGameMode());
- GameModeConfig arenaMode;
- if (schematicType == null) {
- arenaMode = ArenaMode.getByInternal(fightEndsPacket.getGameMode());
- } else {
- arenaMode = ArenaMode.getBySchemType(schematicType);
- }
- if (arenaMode == null) return;
- if (!arenaMode.Server.Ranked) return;
-
- if (EloSchemHandler.publicVsPrivate(fightEndsPacket))
- return;
-
- // Die nächsten Zeilen filtern ein Fight innerhalb eines Teams nicht gewertet wird, bzw auch wenn nur Teile beider Teams im
- // gleichen Team sind dieser ungewertet ist.
- Set teamsIds = fightEndsPacket.getBluePlayers().stream().map(SteamwarUser::byId).map(SteamwarUser::getTeam).collect(Collectors.toSet());
- for (int redPlayer : fightEndsPacket.getRedPlayers()) {
- int team = SteamwarUser.byId(redPlayer).getTeam();
- if (team != 0 && teamsIds.contains(team)) {
- return;
- }
- }
-
- // Get sizes of both teams
- int blueTeamSize = fightEndsPacket.getBluePlayers().size();
- int redTeamSize = fightEndsPacket.getRedPlayers().size();
-
- // Calculate the favored team
- double bluePlayerFactor = 1 / (1 + Math.exp(0 - (fightEndsPacket.getWin() == 2 ? (double) redTeamSize / blueTeamSize : (double) blueTeamSize / redTeamSize) * 3 + 3)) * 2;
- double redPlayerFactor = 1 / (1 + Math.exp(0 - (fightEndsPacket.getWin() == 1 ? (double) blueTeamSize / redTeamSize : (double) redTeamSize / blueTeamSize) * 3 + 3)) * 2;
-
- // Calculate the time factor
- double timeFactor = getTimeFactor(fightEndsPacket.getDuration());
-
- // Get total elo of both teams
- int blueTeamElo = fightEndsPacket.getBluePlayers().stream().mapToInt(player -> UserElo.getEloOrDefault(player, fightEndsPacket.getGameMode())).sum();
- int redTeamElo = fightEndsPacket.getRedPlayers().stream().mapToInt(player -> UserElo.getEloOrDefault(player, fightEndsPacket.getGameMode())).sum();
-
- // Adaptive elo bonus
- int blueTeamEloBonus = 0;
- int redTeamEloBonus = 0;
- if (Math.abs(blueTeamElo / (double) fightEndsPacket.getBluePlayers().size() - redTeamElo / (double) fightEndsPacket.getRedPlayers().size()) > 400) {
- int outlivedDuration = Math.max(fightEndsPacket.getDuration() - 60, 0);
- if (fightEndsPacket.getWin() == 1 && blueTeamElo < redTeamElo) {
- blueTeamEloBonus = outlivedDuration / 20;
- redTeamEloBonus = -(blueTeamEloBonus / 2);
- } else if (fightEndsPacket.getWin() == 2 && redTeamElo < blueTeamElo) {
- redTeamEloBonus = outlivedDuration / 20;
- blueTeamEloBonus = -(redTeamEloBonus / 2);
- } else if (fightEndsPacket.getWin() == 0) {
- if (redTeamElo < blueTeamElo) {
- blueTeamEloBonus = outlivedDuration / 20;
- redTeamEloBonus = -(blueTeamEloBonus / 2);
- } else if (blueTeamElo < redTeamElo) {
- redTeamEloBonus = outlivedDuration / 20;
- blueTeamEloBonus = -(redTeamEloBonus / 2);
- }
- }
- }
-
- // Calculate the elo factor
- double blueEloFactor = ((fightEndsPacket.getWin() == 1 ? 1 : 0) - 1 / (1 + Math.pow(10, (redTeamElo - blueTeamElo) / 600.0))) * (1 / (1 + Math.exp(-Math.abs(blueTeamElo - redTeamElo) / 1200.0))) * 4;
- double redEloFactor = blueEloFactor * -1;
-
- // Calculate favoured team on draw
- if (fightEndsPacket.getWin() == 0) {
- if (bluePlayerFactor > 1) {
- blueEloFactor = Math.abs(blueEloFactor) * -1;
- redEloFactor = Math.abs(redEloFactor);
- } else if (bluePlayerFactor < 1) {
- blueEloFactor = Math.abs(blueEloFactor);
- redEloFactor = Math.abs(redEloFactor) * -1;
- } else {
- if (Math.abs(blueEloFactor) > 1) {
- // Do nothing
- } else if (Math.abs(blueEloFactor) < 1) {
- blueEloFactor = -blueEloFactor;
- redEloFactor = -blueEloFactor;
- } else {
- blueEloFactor = 0;
- redEloFactor = 0;
- }
- }
- }
-
- // Calculate the rematch factor
- double rematchFactor = getRematchFactor(fightEndsPacket);
-
- // Calculate the win factor
- double blueWinFactor = (fightEndsPacket.getWin() == 1 ? 1 : 0.7);
- double redWinFactor = (fightEndsPacket.getWin() == 2 ? 1 : 0.7);
-
- // Calculate division factor
- double divisionFactor = 1D / Math.max(blueTeamSize, redTeamSize);
-
- double blueFactor = bluePlayerFactor * timeFactor * blueEloFactor * rematchFactor * blueWinFactor * divisionFactor;
- double redFactor = redPlayerFactor * timeFactor * redEloFactor * rematchFactor * redWinFactor * divisionFactor;
-
- // Calculate the elo gain for each player
- int blueEloGain = (int) Math.round((blueFactor < 0 ? MEDIAN_ELO_LOSE : MEDIAN_ELO_GAIN) * blueFactor) + blueTeamEloBonus;
- int redEloGain = (int) Math.round((redFactor < 0 ? MEDIAN_ELO_LOSE : MEDIAN_ELO_GAIN) * redFactor) + redTeamEloBonus;
-
- // BungeeCore.get().getLogger().info("Blue: " + fightEndsPacket.getBluePlayers() + " " + blueTeamSize + " " + bluePlayerFactor + " " + timeFactor + " " + blueEloFactor + " " + rematchFactor + " " + blueWinFactor + " " + divisionFactor + " " + blueEloGain);
- // BungeeCore.get().getLogger().info("Red: " + fightEndsPacket.getRedPlayers() + " " + redTeamSize + " " + redPlayerFactor + " " + timeFactor + " " + redEloFactor + " " + rematchFactor + " " + redWinFactor + " " + divisionFactor + " " + redEloGain);
-
- update(fightEndsPacket.getBluePlayers(), fightEndsPacket.getGameMode(), blueEloGain);
- update(fightEndsPacket.getRedPlayers(), fightEndsPacket.getGameMode(), redEloGain);
- }
-
- private void update(List players, String gameMode, int eloGain) {
- for (int player : players) {
- // BungeeCore.get().getLogger().log(Level.INFO, "Player: " + player + " Elo: " + UserElo.getEloOrDefault(player, gameMode) + " Factor: " + factor);
- int playerElo = UserElo.getEloOrDefault(player, gameMode);
- playerElo += eloGain;
- if (playerElo < 0) playerElo = 0;
-
- int oldProgression = UserElo.getProgression(player, gameMode);
- UserElo.setElo(player, gameMode, playerElo);
- int newProgression = UserElo.getProgression(player, gameMode);
-
- animate(player(player), UserElo.toEmblem(oldProgression).trim(), UserElo.toEmblem(newProgression).trim(), (oldProgression < newProgression) ? "§a" : "§c", eloGain);
- }
- }
-
- private void animate(Player player, String oldEmblem, String newEmblem, String arrowColor, int eloGain) {
- if (player == null)
- return;
-
- IntFunction getRankup = getEmblemTransition(oldEmblem, newEmblem, arrowColor);
-
- String color = ((eloGain > 0) ? "§a+" : (eloGain == 0 ? "§7" : "§c"));
-
- double eloStep = eloGain / 40.0;
- for (int i = 0; i < 40; i++) {
- Component eloGainComponent = Chatter.SERIALIZER.deserialize(color + (int) (eloStep * (i + 1)));
- int finalI = i;
- VelocityCore.schedule(() -> player.showTitle(Title.title(
- Chatter.SERIALIZER.deserialize(getRankup.apply(finalI)),
- eloGainComponent,
- Title.Times.times(Duration.ofMillis(finalI == 0 ? 250 : 0), Duration.ofSeconds(2), Duration.ofMillis(finalI == 39 ? 250 : 0))
- ))).delay(i * 50L, TimeUnit.MILLISECONDS).schedule();
- }
- }
-
- private static IntFunction getEmblemTransition(String oldEmblem, String newEmblem, String arrowColor) {
- String finalOldEmblem = (oldEmblem.isEmpty() ? "/" : oldEmblem).trim();
- String finalNewEmblem = (newEmblem.isEmpty() ? "/" : newEmblem).trim();
-
- return i -> {
- if (oldEmblem.equals(newEmblem)) return "§8" + finalOldEmblem;
- if (i < 8) return "§8" + finalOldEmblem;
- if (i < 16) return "§8" + finalOldEmblem + arrowColor + " >";
- if (i < 24) return "§8" + finalOldEmblem + arrowColor + " >>";
- if (i < 32) return "§8" + finalOldEmblem + arrowColor + " >>>";
- return "§8" + finalOldEmblem + arrowColor + " >>> §8" + finalNewEmblem;
- };
- }
-
- private Player player(int userId) {
- return VelocityCore.getProxy().getPlayer(SteamwarUser.byId(userId).getUUID()).orElse(null);
- }
-
- private double getTimeFactor(int duration) {
- if (duration <= 10) {
- return 0.5;
- }
- if (duration <= 60) {
- return 0.8;
- }
- return 1.0;
- }
-
- private double getRematchFactor(FightEndsPacket fightEndsPacket) {
- gameModeGames.computeIfAbsent(fightEndsPacket.getGameMode(), s -> new LinkedList<>()).add(new Game(fightEndsPacket.getBluePlayers(), fightEndsPacket.getRedPlayers()));
-
- LinkedList games = gameModeGames.get(fightEndsPacket.getGameMode());
- while (!games.isEmpty()) {
- Game game = games.getFirst();
- if (game.livedMillis() > REMATCH_LIFETIME) {
- games.removeFirst();
- } else {
- break;
- }
- }
-
- long rematchCount = games.stream().filter(game -> game.isSame(fightEndsPacket.getBluePlayers(), fightEndsPacket.getRedPlayers())).count();
- return 1.0 / rematchCount;
- }
-
- @RequiredArgsConstructor
- private static class Game {
- private long time = System.currentTimeMillis();
- private final List bluePlayers;
- private final List redPlayers;
-
- public long livedMillis() {
- return System.currentTimeMillis() - time;
- }
-
- public boolean isSame(List bluePlayers, List redPlayers) {
- return bluePlayers.containsAll(this.bluePlayers) && redPlayers.containsAll(this.redPlayers);
- }
- }
-}
diff --git a/VelocityCore/src/de/steamwar/velocitycore/network/handlers/EloSchemHandler.java b/VelocityCore/src/de/steamwar/velocitycore/network/handlers/EloSchemHandler.java
deleted file mode 100644
index cd291de7..00000000
--- a/VelocityCore/src/de/steamwar/velocitycore/network/handlers/EloSchemHandler.java
+++ /dev/null
@@ -1,82 +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.velocitycore.network.handlers;
-
-import de.steamwar.sql.GameModeConfig;
-import de.steamwar.linkage.Linked;
-import de.steamwar.network.packets.PacketHandler;
-import de.steamwar.network.packets.common.FightEndsPacket;
-import de.steamwar.sql.SchemElo;
-import de.steamwar.sql.SchematicNode;
-import de.steamwar.sql.SchematicType;
-import de.steamwar.velocitycore.ArenaMode;
-
-@Linked
-public class EloSchemHandler extends PacketHandler {
-
- private static final int K = 20;
-
- public static boolean publicVsPrivate(FightEndsPacket packet) {
- if (packet.getRedSchem() == -1 && packet.getBlueSchem() == -1) {
- return false;
- }
- SchematicNode blueSchem = SchematicNode.getSchematicNode(packet.getBlueSchem());
- SchematicNode redSchem = SchematicNode.getSchematicNode(packet.getRedSchem());
- return (blueSchem.getOwner() == 0) != (redSchem.getOwner() == 0);
- }
-
- @Handler
- public void handle(FightEndsPacket fightEndsPacket) {
- SchematicType type = SchematicType.fromDB(fightEndsPacket.getGameMode());
- if (type == null) return;
- GameModeConfig arenaMode = ArenaMode.getBySchemType(type);
- if (!arenaMode.Server.Ranked) return;
-
- if (publicVsPrivate(fightEndsPacket))
- return;
-
- calcSchemElo(fightEndsPacket);
- }
-
- private void calcSchemElo(FightEndsPacket fightEndsPacket) {
- double blueResult;
- if (fightEndsPacket.getWin() == 0) {
- blueResult = 0.5;
- } else if (fightEndsPacket.getWin() == 1) {
- blueResult = 1;
- } else {
- blueResult = 0;
- }
-
- int blueSchemElo = SchemElo.getCurrentElo(fightEndsPacket.getBlueSchem());
- int redSchemElo = SchemElo.getCurrentElo(fightEndsPacket.getRedSchem());
- calcSchemElo(redSchemElo, blueSchemElo, fightEndsPacket.getRedSchem(), blueResult);
- calcSchemElo(blueSchemElo, redSchemElo, fightEndsPacket.getBlueSchem(), 1 - blueResult);
- }
-
- private void calcSchemElo(int eloSchemOwn, int eloSchemEnemy, int schemId, double result) {
- double winSchemExpectation = calcWinExpectation(eloSchemOwn, eloSchemEnemy);
- SchemElo.setElo(schemId, (int) Math.round(eloSchemOwn + K * (result - winSchemExpectation)));
- }
-
- private double calcWinExpectation(int eloOwn, int eloEnemy) {
- return 1 / (1 + Math.pow(10, (eloEnemy - eloOwn) / 600f));
- }
-}