geforkt von SteamWar/BungeeCore
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
|
||||
public class BungeeNetworkHandler {
|
||||
public static void register() {
|
||||
new EloPlayerHandler().register();
|
||||
new EloSchemHandler().register();
|
||||
new ExecuteCommandHandler().register();
|
||||
new FightEndsHandler().register();
|
||||
new FightInfoHandler().register();
|
||||
new ImALobbyHandler().register();
|
||||
new InventoryCallbackHandler().register();
|
||||
|
@ -38,7 +38,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.IntFunction;
|
||||
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 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 long REMATCH_LIFETIME = 1L * 60 * 60 * 1000;
|
||||
|
||||
private int K = 20;
|
||||
|
||||
private Map<String, LinkedList<Game>> gameModeGames = new HashMap<>();
|
||||
|
||||
@Handler
|
||||
@ -56,7 +54,6 @@ public class FightEndsHandler extends PacketHandler {
|
||||
if (!ArenaMode.getBySchemType(SchematicType.fromDB(fightEndsPacket.getGameMode())).isRanked()) {
|
||||
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 redPublic = SchematicNode.getSchematicNode(fightEndsPacket.getRedSchem()).getOwner() == 0;
|
||||
@ -65,8 +62,6 @@ public class FightEndsHandler extends PacketHandler {
|
||||
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
|
||||
// gleichen Team sind dieser ungewertet ist.
|
||||
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");
|
||||
|
||||
calcSchemElo(fightEndsPacket);
|
||||
calcUserElo(fightEndsPacket);
|
||||
}
|
||||
|
||||
private void calcUserElo(FightEndsPacket fightEndsPacket) {
|
||||
// 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(-(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 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);
|
||||
double redFactor = getRedPlayerFactor(blueTeamSize, redTeamSize) * getTimeFactor(fightEndsPacket.getDuration()) * getRedEloFactor(blueTeamElo, redTeamElo) * getRematchFactor(fightEndsPacket);
|
||||
// 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))) * 4;
|
||||
double redEloFactor = blueEloFactor * -1;
|
||||
|
||||
if (fightEndsPacket.getWin() == 1) {
|
||||
blueFactor *= WIN_FACTOR;
|
||||
redFactor *= LOSE_FACTOR;
|
||||
} else if (fightEndsPacket.getWin() == 2) {
|
||||
blueFactor *= LOSE_FACTOR;
|
||||
redFactor *= WIN_FACTOR;
|
||||
// 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 (redFactor == blueFactor) {
|
||||
blueFactor *= 0;
|
||||
redFactor *= 0;
|
||||
} else if (blueFactor > redFactor) {
|
||||
blueFactor *= DRAW_WIN_FACTOR;
|
||||
redFactor *= DRAW_LOSE_FACTOR;
|
||||
if (Math.abs(blueEloFactor) > 1) {
|
||||
// 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 {
|
||||
blueFactor *= DRAW_LOSE_FACTOR;
|
||||
redFactor *= DRAW_WIN_FACTOR;
|
||||
blueEloFactor = 0;
|
||||
redEloFactor = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update(fightEndsPacket.getBluePlayers(), fightEndsPacket.getGameMode(), blueFactor);
|
||||
update(fightEndsPacket.getRedPlayers(), fightEndsPacket.getGameMode(), redFactor);
|
||||
// Calculate the rematch factor
|
||||
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) {
|
||||
// BungeeCore.get().getLogger().log(Level.INFO, "Player: " + player + " Elo: " + UserElo.getEloOrDefault(player, gameMode) + " Factor: " + factor);
|
||||
int playerElo = UserElo.getEloOrDefault(player, gameMode);
|
||||
int eloGain = (int) Math.round(MEDIAN_ELO_GAIN * factor);
|
||||
playerElo += eloGain;
|
||||
if (playerElo < 0) playerElo = 0;
|
||||
|
||||
@ -154,11 +167,7 @@ public class FightEndsHandler extends PacketHandler {
|
||||
scheduler.schedule(BungeeCore.get(), () -> {
|
||||
if (player == null) return;
|
||||
if (!player.isConnected()) return;
|
||||
Title title = new BungeeTitle().title(TextComponent.fromLegacyText(getRankup.apply(finalI)))
|
||||
.subTitle(eloGainComponent)
|
||||
.fadeIn(finalI == 0 ? 5 : 0)
|
||||
.stay(40)
|
||||
.fadeOut(finalI == 39 ? 5 : 0);
|
||||
Title title = new BungeeTitle().title(TextComponent.fromLegacyText(getRankup.apply(finalI))).subTitle(eloGainComponent).fadeIn(finalI == 0 ? 5 : 0).stay(40).fadeOut(finalI == 39 ? 5 : 0);
|
||||
title.send(player);
|
||||
}, i * 50L, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
@ -168,39 +177,6 @@ public class FightEndsHandler extends PacketHandler {
|
||||
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) {
|
||||
if (duration <= 10) {
|
||||
return 0.5;
|
||||
@ -211,14 +187,6 @@ public class FightEndsHandler extends PacketHandler {
|
||||
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) {
|
||||
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