Merge pull request 'Update UserElo for new ranked system' (#53) from NewRankedSystem into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful

Reviewed-on: #53
Reviewed-by: Lixfel <lixfel@steamwar.de>
Dieser Commit ist enthalten in:
Lixfel 2023-05-12 22:54:19 +02:00
Commit e3e1a1cfcd

Datei anzeigen

@ -33,22 +33,20 @@ import java.util.concurrent.ConcurrentHashMap;
@AllArgsConstructor @AllArgsConstructor
public class UserElo { public class UserElo {
private static final int ELO_DEFAULT = 1000;
private static final int ELO_DEFAULT = 0;
private static final Map<String, Map<Integer, Optional<Integer>>> gameModeUserEloCache = new ConcurrentHashMap<>(); private static final Map<String, Map<Integer, Optional<Integer>>> gameModeUserEloCache = new ConcurrentHashMap<>();
private static final Map<String, Integer> maxEloCache = new ConcurrentHashMap<>();
private static final Map<Integer, String> emblemCache = new ConcurrentHashMap<>(); private static final Map<Integer, String> emblemCache = new ConcurrentHashMap<>();
public static void clear() { public static void clear() {
gameModeUserEloCache.clear(); gameModeUserEloCache.clear();
maxEloCache.clear();
emblemCache.clear(); emblemCache.clear();
} }
private static final Table<UserElo> table = new Table<>(UserElo.class); private static final Table<UserElo> table = new Table<>(UserElo.class);
private static final SelectStatement<UserElo> getElo = table.select(Table.PRIMARY); private static final SelectStatement<UserElo> getElo = table.select(Table.PRIMARY);
private static final Statement setElo = table.insertAll(); private static final Statement setElo = table.insertAll();
private static final Statement maxElo = new Statement("SELECT MAX(Elo) AS MaxElo FROM UserElo WHERE Season = ? AND GameMode = ?");
private static final Statement place = new Statement("SELECT COUNT(*) AS Place FROM UserElo WHERE GameMode = ? AND Elo > ? AND Season = ?"); private static final Statement place = new Statement("SELECT COUNT(*) AS Place FROM UserElo WHERE GameMode = ? AND Elo > ? AND Season = ?");
private static final Statement fightsOfSeason = new Statement("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(?)"); private static final Statement fightsOfSeason = new Statement("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(?)");
@ -78,21 +76,13 @@ public class UserElo {
}, userID, gameMode, Season.getSeasonStart()); }, userID, gameMode, Season.getSeasonStart());
} }
private static int getMaxElo(String gameMode) {
return maxEloCache.computeIfAbsent(gameMode, gm -> maxElo.select(rs -> {
if (rs.next())
return rs.getInt("MaxElo");
return 0;
}, Season.getSeason(), gameMode));
}
public static void setElo(int userId, String gameMode, int elo) { public static void setElo(int userId, String gameMode, int elo) {
emblemCache.remove(userId); emblemCache.remove(userId);
Optional<Integer> oldElo = Optional.ofNullable(gameModeUserEloCache.computeIfAbsent(gameMode, gm -> new HashMap<>()).put(userId, Optional.of(elo))).orElse(Optional.empty()); int oldPlacement = getPlacement(getElo(userId, gameMode).orElse(0), gameMode);
int maxElo = getMaxElo(gameMode); int newPlacement = getPlacement(elo, gameMode);
if (elo > maxElo || (oldElo.isPresent() && oldElo.get() == maxElo)) {
maxEloCache.remove(gameMode); if (oldPlacement <= 3 || newPlacement <= 3) {
emblemCache.clear(); emblemCache.clear();
} }
@ -109,70 +99,92 @@ public class UserElo {
public static String getEmblem(SteamwarUser user, List<String> rankedModes) { public static String getEmblem(SteamwarUser user, List<String> rankedModes) {
return emblemCache.computeIfAbsent(user.getId(), userId -> { return emblemCache.computeIfAbsent(user.getId(), userId -> {
switch( int emblemProgression = -1;
rankedModes.stream().filter( for (String mode : rankedModes) {
mode -> UserElo.getFightsOfSeason(user.getId(), mode) >= 10 if (UserElo.getFightsOfSeason(userId, mode) == 0) continue;
).map( int progression = getProgression(userId, mode);
mode -> getProgression(user.getId(), mode) if (progression > emblemProgression) {
).max(Integer::compareTo).orElse(0) emblemProgression = progression;
) {
case 0:
return "";
case 1:
return "§7✧ ";
case 2:
return "§f✦ ";
case 3:
return "§e✶ ";
case 4:
return "§a✷ ";
case 5:
return "§b✸ ";
case 6:
return "§c✹ ";
case 7:
return "§5❂ ";
default:
throw new SecurityException("Progression out of range");
} }
}
return toEmblem(emblemProgression);
}); });
} }
public static String getEmblemProgression(String gameMode, int userId) { public static String getEmblemProgression(String gameMode, int userId) {
switch (getProgression(userId, gameMode)) { switch (getProgression(userId, gameMode)) {
case -1:
return "§f/ §6 ∧ §7 ∧ §e ∧ §5❂ III II I";
case 0: case 0:
return "§8✧ ✦ ✶ ✷ ✸ ✹ ❂"; return "§8/ §6 §8∧ ∧ ❂ III II I";
case 1: case 1:
return "§7✧ §8✦ ✶ ✷ ✸ ✹ ❂"; return "§8/ §6∧ §8 ∧ ❂ III II I";
case 2: case 2:
return "§8✧ §f✦ §8✶ ✷ ✸ ✹ ❂"; return "§8/ ∧ §7 §8∧ ∧ ❂ III II I";
case 3: case 3:
return "§8✧ ✦ §e✶ §8✷ ✸ ✹ ❂"; return "§8/ §7∧ §8 ∧ ❂ III II I";
case 4: case 4:
return "§8✧ ✦ ✶ §a✷ §8✸ ✹ ❂"; return "§8/ ∧ §e §8∧ ❂ III II I";
case 5: case 5:
return "§8✧ ✦ ✶ ✷ §b✸ §8✹ ❂"; return "§8/ §e∧ §8❂ III II I";
case 6: case 6:
return "§8✧ ✦ ✶ ✷ ✸ §c✹ §8❂"; return "§8/ ∧ §5❂ §8III II I";
case 7: case 7:
return "§8✧ ✦ ✶ ✷ ✸ ✹ §5❂"; return "§8/ ∧ ❂ §5III §8II I";
case 8:
return "§8/ ∧ ❂ III §5II §8I";
case 9:
return "§8/ ∧ ❂ III II §5I";
default: default:
throw new SecurityException("Progression is not in range"); throw new SecurityException("Progression is not in range");
} }
} }
private static int getProgression(int userId, String gameMode) { public static int getProgression(int userId, String gameMode) {
int elo = getElo(userId, gameMode).orElse(0); int elo = getElo(userId, gameMode).orElse(-1);
if(elo == 0) if (elo < 0) return -1;
return 0;
int maxElo = getMaxElo(gameMode);
if (elo > maxElo * 0.99) return 7; if (elo <= 100) return 0;
if (elo > maxElo * 0.97) return 6; if (elo <= 200) return 1;
if (elo > maxElo * 0.94) return 5; if (elo <= 400) return 2;
if (elo > maxElo * 0.88) return 4; if (elo <= 600) return 3;
if (elo > maxElo * 0.76) return 3; if (elo <= 900) return 4;
if (elo > maxElo * 0.51) return 2; if (elo <= 1200) return 5;
return 1;
int placement = getPlacement(elo, gameMode);
if (placement == 1) return 9;
if (placement == 2) return 8;
if (placement == 3) return 7;
return 6;
}
public static String toEmblem(int progression) {
switch(progression) {
case -1:
return "";
case 0:
return "§6 ";
case 1:
return "§6∧ ";
case 2:
return "§7 ";
case 3:
return "§7∧ ";
case 4:
return "§e ";
case 5:
return "§e∧ ";
case 6:
return "§5❂ ";
case 7:
return "§5III ";
case 8:
return "§5II ";
case 9:
return "§5I ";
default:
throw new SecurityException("Progression out of range");
}
} }
} }