Ranked #333
@ -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);
|
||||
}
|
||||
|
||||
Lixfel markierte diese Unterhaltung als gelöst
Veraltet
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
YoyoNow markierte diese Unterhaltung als gelöst
Veraltet
Lixfel
hat
Da hier häufig Einträge zu Beginn der Liste entfernt werden, wäre eine LinkedList wahrscheinlich die bessere Datenstruktur Da hier häufig Einträge zu Beginn der Liste entfernt werden, wäre eine LinkedList wahrscheinlich die bessere Datenstruktur
YoyoNow
hat
Das removeIf sollte ich dann aber auch noch einmal optimieren, weil ich ja die Reihenfolge kenne. Und damit nur immer über den Anfang der List drüber gehen muss. Das removeIf sollte ich dann aber auch noch einmal optimieren, weil ich ja die Reihenfolge kenne. Und damit nur immer über den Anfang der List drüber gehen muss.
|
||||
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) {
|
||||
Lixfel markierte diese Unterhaltung als gelöst
Veraltet
Lixfel
hat
Du dürftest hier möglicherweise (Concurrency) auch den eigenen Fight zurückbekommen... Du dürftest hier möglicherweise (Concurrency) auch den eigenen Fight zurückbekommen...
YoyoNow
hat
Wie kann ich das verhindern bzw rausfiltern? Wie kann ich das verhindern bzw rausfiltern?
|
||||
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);
|
||||
YoyoNow markierte diese Unterhaltung als gelöst
Veraltet
Lixfel
hat
Hier bitte stattdessen verunden. Hier bitte stattdessen verunden.
|
||||
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
Du musst das Processing in einen Task auslagern (dauert zu lange, insbesondere mit dem ganzen Fight-Gedöns).
Machst du das nicht seit dem DB update (da dispatched du doch auch die plugin messages async)