Hotfix (the last one hopefully) for the Elo handling
Dieser Commit ist enthalten in:
Ursprung
fbcb043d1c
Commit
618c4d24a2
@ -25,8 +25,9 @@ import lombok.experimental.UtilityClass;
|
|||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class BungeeNetworkHandler {
|
public class BungeeNetworkHandler {
|
||||||
public static void register() {
|
public static void register() {
|
||||||
|
new EloPlayerHandler().register();
|
||||||
|
new EloSchemHandler().register();
|
||||||
new ExecuteCommandHandler().register();
|
new ExecuteCommandHandler().register();
|
||||||
new FightEndsHandler().register();
|
|
||||||
new FightInfoHandler().register();
|
new FightInfoHandler().register();
|
||||||
new ImALobbyHandler().register();
|
new ImALobbyHandler().register();
|
||||||
new InventoryCallbackHandler().register();
|
new InventoryCallbackHandler().register();
|
||||||
|
@ -38,7 +38,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import java.util.function.IntFunction;
|
import java.util.function.IntFunction;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class FightEndsHandler extends PacketHandler {
|
public class EloPlayerHandler extends PacketHandler {
|
||||||
|
|
||||||
private static final int MEDIAN_ELO_GAIN = 20;
|
private static final int MEDIAN_ELO_GAIN = 20;
|
||||||
private static final double WIN_FACTOR = 1.0;
|
private static final double WIN_FACTOR = 1.0;
|
||||||
@ -47,8 +47,6 @@ public class FightEndsHandler extends PacketHandler {
|
|||||||
private static final double DRAW_LOSE_FACTOR = -0.2;
|
private static final double DRAW_LOSE_FACTOR = -0.2;
|
||||||
private static final long REMATCH_LIFETIME = 1L * 60 * 60 * 1000;
|
private static final long REMATCH_LIFETIME = 1L * 60 * 60 * 1000;
|
||||||
|
|
||||||
private int K = 20;
|
|
||||||
|
|
||||||
private Map<String, LinkedList<Game>> gameModeGames = new HashMap<>();
|
private Map<String, LinkedList<Game>> gameModeGames = new HashMap<>();
|
||||||
|
|
||||||
@Handler
|
@Handler
|
||||||
@ -56,7 +54,6 @@ public class FightEndsHandler extends PacketHandler {
|
|||||||
if (!ArenaMode.getBySchemType(SchematicType.fromDB(fightEndsPacket.getGameMode())).isRanked()) {
|
if (!ArenaMode.getBySchemType(SchematicType.fromDB(fightEndsPacket.getGameMode())).isRanked()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// BungeeCore.get().getLogger().log(Level.INFO, fightEndsPacket.getWin() + " " + fightEndsPacket.getBlueSchem() + " " + fightEndsPacket.getRedSchem() + " " + fightEndsPacket.getBluePlayers() + " " + fightEndsPacket.getRedPlayers() + " " + fightEndsPacket.getGameMode() + " " + fightEndsPacket.getDuration());
|
|
||||||
|
|
||||||
boolean bluePublic = SchematicNode.getSchematicNode(fightEndsPacket.getBlueSchem()).getOwner() == 0;
|
boolean bluePublic = SchematicNode.getSchematicNode(fightEndsPacket.getBlueSchem()).getOwner() == 0;
|
||||||
boolean redPublic = SchematicNode.getSchematicNode(fightEndsPacket.getRedSchem()).getOwner() == 0;
|
boolean redPublic = SchematicNode.getSchematicNode(fightEndsPacket.getRedSchem()).getOwner() == 0;
|
||||||
@ -65,8 +62,6 @@ public class FightEndsHandler extends PacketHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BungeeCore.get().getLogger().log(Level.INFO, "After schematic public check");
|
|
||||||
|
|
||||||
// Die nächsten Zeilen filtern ein Fight innerhalb eines Teams nicht gewertet wird, bzw auch wenn nur Teile beider Teams im
|
// 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.
|
// gleichen Team sind dieser ungewertet ist.
|
||||||
Set<Integer> teamsIds = fightEndsPacket.getBluePlayers().stream().map(SteamwarUser::get).map(SteamwarUser::getTeam).collect(Collectors.toSet());
|
Set<Integer> teamsIds = fightEndsPacket.getBluePlayers().stream().map(SteamwarUser::get).map(SteamwarUser::getTeam).collect(Collectors.toSet());
|
||||||
@ -76,50 +71,68 @@ public class FightEndsHandler extends PacketHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BungeeCore.get().getLogger().log(Level.INFO, "After Team check");
|
// Get sizes of both teams
|
||||||
|
|
||||||
calcSchemElo(fightEndsPacket);
|
|
||||||
calcUserElo(fightEndsPacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calcUserElo(FightEndsPacket fightEndsPacket) {
|
|
||||||
int blueTeamSize = fightEndsPacket.getBluePlayers().size();
|
int blueTeamSize = fightEndsPacket.getBluePlayers().size();
|
||||||
int redTeamSize = fightEndsPacket.getRedPlayers().size();
|
int redTeamSize = fightEndsPacket.getRedPlayers().size();
|
||||||
|
|
||||||
|
// Calculate the favored team
|
||||||
|
double bluePlayerFactor = 1 / (1 + Math.exp(-(fightEndsPacket.getWin() == 2 ? (double) redTeamSize / blueTeamSize : (double) blueTeamSize / redTeamSize) * 3 + 3)) * 2;
|
||||||
|
double redPlayerFactor = 1 / (1 + Math.exp(-(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 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();
|
int redTeamElo = fightEndsPacket.getRedPlayers().stream().mapToInt(player -> UserElo.getEloOrDefault(player, fightEndsPacket.getGameMode())).sum();
|
||||||
|
|
||||||
double blueFactor = getBluePlayerFactor(blueTeamSize, redTeamSize) * getTimeFactor(fightEndsPacket.getDuration()) * getBlueEloFactor(blueTeamElo, redTeamElo) * getRematchFactor(fightEndsPacket);
|
// Calculate the elo factor
|
||||||
double redFactor = getRedPlayerFactor(blueTeamSize, redTeamSize) * getTimeFactor(fightEndsPacket.getDuration()) * getRedEloFactor(blueTeamElo, redTeamElo) * getRematchFactor(fightEndsPacket);
|
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))) * 4;
|
||||||
|
double redEloFactor = blueEloFactor * -1;
|
||||||
|
|
||||||
if (fightEndsPacket.getWin() == 1) {
|
// Calculate favoured team on draw
|
||||||
blueFactor *= WIN_FACTOR;
|
if (fightEndsPacket.getWin() == 0) {
|
||||||
redFactor *= LOSE_FACTOR;
|
if (bluePlayerFactor > 1) {
|
||||||
} else if (fightEndsPacket.getWin() == 2) {
|
blueEloFactor = Math.abs(blueEloFactor) * -1;
|
||||||
blueFactor *= LOSE_FACTOR;
|
redEloFactor = Math.abs(redEloFactor);
|
||||||
redFactor *= WIN_FACTOR;
|
} else if (bluePlayerFactor < 1) {
|
||||||
} else {
|
blueEloFactor = Math.abs(blueEloFactor);
|
||||||
if (redFactor == blueFactor) {
|
redEloFactor = Math.abs(redEloFactor) * -1;
|
||||||
blueFactor *= 0;
|
|
||||||
redFactor *= 0;
|
|
||||||
} else if (blueFactor > redFactor) {
|
|
||||||
blueFactor *= DRAW_WIN_FACTOR;
|
|
||||||
redFactor *= DRAW_LOSE_FACTOR;
|
|
||||||
} else {
|
} else {
|
||||||
blueFactor *= DRAW_LOSE_FACTOR;
|
if (Math.abs(blueEloFactor) > 1) {
|
||||||
redFactor *= DRAW_WIN_FACTOR;
|
// Do nothing
|
||||||
|
} else if (Math.abs(blueEloFactor) < 1) {
|
||||||
|
blueEloFactor = ((fightEndsPacket.getWin() == 1 ? 1 : 0) - 1 / (1 + Math.pow(10, (blueTeamElo - redTeamElo) / 600.0))) * (1 / (1 + Math.exp(-Math.abs(redTeamElo - blueTeamElo) / 1200))) * -4;
|
||||||
|
redEloFactor = blueEloFactor * -1;
|
||||||
|
} else {
|
||||||
|
blueEloFactor = 0;
|
||||||
|
redEloFactor = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update(fightEndsPacket.getBluePlayers(), fightEndsPacket.getGameMode(), blueFactor);
|
// Calculate the rematch factor
|
||||||
update(fightEndsPacket.getRedPlayers(), fightEndsPacket.getGameMode(), redFactor);
|
double rematchFactor = getRematchFactor(fightEndsPacket);
|
||||||
|
|
||||||
|
// Calculate the win factor
|
||||||
|
double blueWinFactor = (fightEndsPacket.getWin() == 1 ? 1 : 0.9);
|
||||||
|
double redWinFactor = (fightEndsPacket.getWin() == 2 ? 1 : 0.9);
|
||||||
|
|
||||||
|
// Calculate division factor
|
||||||
|
double divisionFactor = 1/(fightEndsPacket.getWin() == 1 ? Math.max(blueTeamSize, redTeamSize) : Math.min(blueTeamSize, redTeamSize));
|
||||||
|
|
||||||
|
// Calculate the elo gain for each player
|
||||||
|
int blueEloGain = (int) Math.round(MEDIAN_ELO_GAIN * bluePlayerFactor * timeFactor * blueEloFactor * rematchFactor * blueWinFactor * divisionFactor);
|
||||||
|
int redEloGain = (int) Math.round(MEDIAN_ELO_GAIN * redPlayerFactor * timeFactor * redEloFactor * rematchFactor * redWinFactor * divisionFactor);
|
||||||
|
|
||||||
|
update(fightEndsPacket.getBluePlayers(), fightEndsPacket.getGameMode(), blueEloGain);
|
||||||
|
update(fightEndsPacket.getBluePlayers(), fightEndsPacket.getGameMode(), redEloGain);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update(List<Integer> players, String gameMode, double factor) {
|
private void update(List<Integer> players, String gameMode, int eloGain) {
|
||||||
for (int player : players) {
|
for (int player : players) {
|
||||||
// BungeeCore.get().getLogger().log(Level.INFO, "Player: " + player + " Elo: " + UserElo.getEloOrDefault(player, gameMode) + " Factor: " + factor);
|
// BungeeCore.get().getLogger().log(Level.INFO, "Player: " + player + " Elo: " + UserElo.getEloOrDefault(player, gameMode) + " Factor: " + factor);
|
||||||
int playerElo = UserElo.getEloOrDefault(player, gameMode);
|
int playerElo = UserElo.getEloOrDefault(player, gameMode);
|
||||||
int eloGain = (int) Math.round(MEDIAN_ELO_GAIN * factor);
|
|
||||||
playerElo += eloGain;
|
playerElo += eloGain;
|
||||||
if (playerElo < 0) playerElo = 0;
|
if (playerElo < 0) playerElo = 0;
|
||||||
|
|
||||||
@ -154,11 +167,7 @@ public class FightEndsHandler extends PacketHandler {
|
|||||||
scheduler.schedule(BungeeCore.get(), () -> {
|
scheduler.schedule(BungeeCore.get(), () -> {
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
if (!player.isConnected()) return;
|
if (!player.isConnected()) return;
|
||||||
Title title = new BungeeTitle().title(TextComponent.fromLegacyText(getRankup.apply(finalI)))
|
Title title = new BungeeTitle().title(TextComponent.fromLegacyText(getRankup.apply(finalI))).subTitle(eloGainComponent).fadeIn(finalI == 0 ? 5 : 0).stay(40).fadeOut(finalI == 39 ? 5 : 0);
|
||||||
.subTitle(eloGainComponent)
|
|
||||||
.fadeIn(finalI == 0 ? 5 : 0)
|
|
||||||
.stay(40)
|
|
||||||
.fadeOut(finalI == 39 ? 5 : 0);
|
|
||||||
title.send(player);
|
title.send(player);
|
||||||
}, i * 50L, TimeUnit.MILLISECONDS);
|
}, i * 50L, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
@ -168,39 +177,6 @@ public class FightEndsHandler extends PacketHandler {
|
|||||||
return ProxyServer.getInstance().getPlayer(SteamwarUser.get(userId).getUUID());
|
return ProxyServer.getInstance().getPlayer(SteamwarUser.get(userId).getUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
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(fightEndsPacket.getBlueSchem(), blueSchemElo, redSchemElo, blueResult);
|
|
||||||
calcSchemElo(fightEndsPacket.getRedSchem(), redSchemElo, blueSchemElo, 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
private double getBluePlayerFactor(int blueTeam, int redTeam) {
|
|
||||||
return 2 - calcWinExpectation(blueTeam, redTeam) * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private double getRedPlayerFactor(int blueTeam, int redTeam) {
|
|
||||||
return 2 - calcWinExpectation(redTeam, blueTeam) * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private double getTimeFactor(int duration) {
|
private double getTimeFactor(int duration) {
|
||||||
if (duration <= 10) {
|
if (duration <= 10) {
|
||||||
return 0.5;
|
return 0.5;
|
||||||
@ -211,14 +187,6 @@ public class FightEndsHandler extends PacketHandler {
|
|||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getBlueEloFactor(int blueElo, int redElo) {
|
|
||||||
return 2 - calcWinExpectation(blueElo, redElo) * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private double getRedEloFactor(int blueElo, int redElo) {
|
|
||||||
return 2 - calcWinExpectation(redElo, blueElo) * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private double getRematchFactor(FightEndsPacket fightEndsPacket) {
|
private double getRematchFactor(FightEndsPacket fightEndsPacket) {
|
||||||
gameModeGames.computeIfAbsent(fightEndsPacket.getGameMode(), s -> new LinkedList<>()).add(new Game(fightEndsPacket.getBluePlayers(), fightEndsPacket.getRedPlayers()));
|
gameModeGames.computeIfAbsent(fightEndsPacket.getGameMode(), s -> new LinkedList<>()).add(new Game(fightEndsPacket.getBluePlayers(), fightEndsPacket.getRedPlayers()));
|
||||||
|
|
73
src/de/steamwar/bungeecore/network/handlers/EloSchemHandler.java
Normale Datei
73
src/de/steamwar/bungeecore/network/handlers/EloSchemHandler.java
Normale Datei
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 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.bungeecore.network.handlers;
|
||||||
|
|
||||||
|
import de.steamwar.bungeecore.ArenaMode;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class EloSchemHandler extends PacketHandler {
|
||||||
|
|
||||||
|
private final int K = 20;
|
||||||
|
|
||||||
|
@Handler
|
||||||
|
public void handle(FightEndsPacket fightEndsPacket) {
|
||||||
|
if (!ArenaMode.getBySchemType(SchematicType.fromDB(fightEndsPacket.getGameMode())).isRanked()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean bluePublic = SchematicNode.getSchematicNode(fightEndsPacket.getBlueSchem()).getOwner() == 0;
|
||||||
|
boolean redPublic = SchematicNode.getSchematicNode(fightEndsPacket.getRedSchem()).getOwner() == 0;
|
||||||
|
|
||||||
|
if (bluePublic ^ redPublic) {
|
||||||
|
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(fightEndsPacket.getBlueSchem(), blueSchemElo, redSchemElo, blueResult);
|
||||||
|
calcSchemElo(fightEndsPacket.getRedSchem(), redSchemElo, blueSchemElo, 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));
|
||||||
|
}
|
||||||
|
}
|
In neuem Issue referenzieren
Einen Benutzer sperren