Merge pull request 'Ranked' (#333) from Ranked into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #333 Reviewed-by: Lixfel <lixfel@steamwar.de>
Dieser Commit ist enthalten in:
Commit
e3b9329de0
@ -23,18 +23,29 @@ import com.google.common.io.ByteArrayDataInput;
|
||||
import de.steamwar.bungeecore.ArenaMode;
|
||||
import de.steamwar.bungeecore.comms.SpigotHandler;
|
||||
import de.steamwar.bungeecore.comms.packets.FightEndsPacket;
|
||||
import de.steamwar.bungeecore.sql.SchemElo;
|
||||
import de.steamwar.bungeecore.sql.SchematicNode;
|
||||
import de.steamwar.bungeecore.sql.SchematicType;
|
||||
import de.steamwar.bungeecore.sql.UserElo;
|
||||
import de.steamwar.bungeecore.sql.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class FightEndsHandler implements SpigotHandler {
|
||||
|
||||
private Map<String, LinkedList<Game>> gameModeGames = new HashMap<>();
|
||||
|
||||
private int K = 20;
|
||||
|
||||
private long defaultFightRange = 1000 /* Milliseconds */ * 60 /* Seconds */ * 15L /* Minutes */;
|
||||
private Map<String, Long> fightRanges = new HashMap<>();
|
||||
private long defaultFightCount = 1;
|
||||
private Map<String, Long> fightCounts = new HashMap<>();
|
||||
|
||||
{
|
||||
fightRanges.put("miniwargear", 1000 /* Milliseconds */ * 60 /* Seconds */ * 30L /* Minutes */);
|
||||
fightCounts.put("miniwargear", 3L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(ByteArrayDataInput in, ServerInfo info) {
|
||||
FightEndsPacket fightEndsPacket = new FightEndsPacket(in);
|
||||
@ -66,6 +77,23 @@ public class FightEndsHandler implements SpigotHandler {
|
||||
blueResult = 0;
|
||||
}
|
||||
|
||||
// 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());
|
||||
for (int redPlayer : fightEndsPacket.getRedPlayers()) {
|
||||
if (teamsIds.contains(SteamwarUser.get(redPlayer).getTeam())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (teamComboExistedAlready(fightEndsPacket.getBluePlayers(), fightEndsPacket.getRedPlayers(), fightEndsPacket.getGameMode())) {
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
gameModeGames.computeIfAbsent(fightEndsPacket.getGameMode(), s -> new LinkedList<>()).add(new Game(fightEndsPacket.getBluePlayers(), fightEndsPacket.getRedPlayers()));
|
||||
}
|
||||
|
||||
int blueSchemElo = SchemElo.getElo(fightEndsPacket.getBlueSchem());
|
||||
int redSchemElo = SchemElo.getElo(fightEndsPacket.getRedSchem());
|
||||
|
||||
@ -77,14 +105,55 @@ public class FightEndsHandler implements SpigotHandler {
|
||||
}
|
||||
|
||||
private void calculateEloOfTeam(int schemId, int eloSchemOwn, int eloSchemEnemy, int eloTeamOwn, int eloTeamEnemy, double result, List<Integer> players, String gameMode, boolean noPlayerRank) {
|
||||
double winSchemExpectation = 1 / (1 + Math.pow(10, (eloSchemEnemy - eloSchemOwn) / 600f));
|
||||
double winSchemExpectation = calsWinExpectation(eloSchemOwn, eloSchemEnemy);
|
||||
SchemElo.setElo(schemId, (int) Math.round(eloSchemOwn + K * (result - winSchemExpectation)));
|
||||
|
||||
if (noPlayerRank) return;
|
||||
double winTeamExpectation = 1 / (1 + Math.pow(10, (eloTeamEnemy - eloTeamOwn) / 600f));
|
||||
double winTeamExpectation = calsWinExpectation(eloTeamOwn, eloTeamEnemy);
|
||||
for (int player : players) {
|
||||
int playerElo = UserElo.getEloOrDefault(player, gameMode);
|
||||
UserElo.setElo(player, gameMode, (int) Math.round(playerElo + K * (result - winTeamExpectation)));
|
||||
int fights = UserElo.getFightsOfSeason(player, gameMode);
|
||||
UserElo.setElo(player, gameMode, (int) Math.round(playerElo + getK(fights) * (result - winTeamExpectation)));
|
||||
}
|
||||
}
|
||||
|
||||
private double calsWinExpectation(int eloOwn, int eloEnemy) {
|
||||
return 1 / (1 + Math.pow(10, (eloEnemy - eloOwn) / 600f));
|
||||
}
|
||||
|
||||
private double getK(int fights) {
|
||||
return K * Math.max(1.3 - (fights / 200.0), 0.8);
|
||||
}
|
||||
|
||||
private boolean teamComboExistedAlready(List<Integer> bluePlayers, List<Integer> redPlayers, String gameMode) {
|
||||
if (!gameModeGames.containsKey(gameMode)) {
|
||||
return false;
|
||||
}
|
||||
LinkedList<Game> games = gameModeGames.get(gameMode);
|
||||
long lifetime = fightRanges.getOrDefault(gameMode, defaultFightRange);
|
||||
while (!games.isEmpty()) {
|
||||
Game game = games.getFirst();
|
||||
if (game.livedMillis() > lifetime) {
|
||||
games.removeFirst();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return games.stream().filter(game -> game.isSame(bluePlayers, redPlayers)).count() > fightCounts.getOrDefault(gameMode, defaultFightCount);
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private static class Game {
|
||||
private long time = System.currentTimeMillis();
|
||||
private final List<Integer> bluePlayers;
|
||||
private final List<Integer> redPlayers;
|
||||
|
||||
public long livedMillis() {
|
||||
return System.currentTimeMillis() - time;
|
||||
}
|
||||
|
||||
public boolean isSame(List<Integer> bluePlayers, List<Integer> redPlayers) {
|
||||
return bluePlayers.containsAll(this.bluePlayers) && redPlayers.containsAll(this.redPlayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ public class UserElo {
|
||||
}, userID, gameMode, Season.getSeason()));
|
||||
}
|
||||
|
||||
private static int getFightsOfSeason(int userID, String gameMode) {
|
||||
public static int getFightsOfSeason(int userID, String gameMode) {
|
||||
return fightsOfSeason.select(rs -> {
|
||||
if (rs.next())
|
||||
return rs.getInt("Fights");
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren