SteamWar/BungeeCore
Archiviert
13
2

Ranked #306

Zusammengeführt
Lixfel hat 25 Commits von Ranked nach master 2022-03-13 20:26:16 +01:00 zusammengeführt
5 geänderte Dateien mit 89 neuen und 149 gelöschten Zeilen
Nur Änderungen aus Commit 4e5bd18ef9 werden angezeigt - Alle Commits anzeigen

Datei anzeigen

@ -24,11 +24,13 @@ 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.SchemNode;
import de.steamwar.bungeecore.sql.SchematicNode;
import de.steamwar.bungeecore.sql.SchematicType;
import de.steamwar.bungeecore.sql.UserElo;
import net.md_5.bungee.api.config.ServerInfo;
import java.util.List;
public class FightEndsHandler implements SpigotHandler {
Lixfel markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Bitte überall mal deine Imports aufräumen! (Warum hast du das nicht autoaktiviert?)

Bitte überall mal deine Imports aufräumen! (Warum hast du das nicht autoaktiviert?)
Veraltet
Review

Keine ahnung

Keine ahnung
private int K = 20;
@ -41,15 +43,17 @@ public class FightEndsHandler implements SpigotHandler {
return;
}
YoyoNow markierte diese Unterhaltung als gelöst
Review

Diese Ratio-Berechnung finde ich komplexer als nötig, sollte sich einfacher formulieren lassen

Diese Ratio-Berechnung finde ich komplexer als nötig, sollte sich einfacher formulieren lassen
Review

Hast du eine Idee, ich wüsste nicht wie außer das ich das 1- rausnehmen kann

Hast du eine Idee, ich wüsste nicht wie außer das ich das 1- rausnehmen kann
Review

ratio = bluePlayerSize > redPlayerSize ? redPlayerSize / bluePlayerSize : bluePlayerSize / redPlayerSize

if ratio < 0.6 return;

ratio = bluePlayerSize > redPlayerSize ? redPlayerSize / bluePlayerSize : bluePlayerSize / redPlayerSize if ratio < 0.6 return;
double playerRatio = 1 - (Math.min(fightEndsPacket.getBluePlayers().size(), fightEndsPacket.getRedPlayers().size()) / (double )Math.max(fightEndsPacket.getBluePlayers().size(), fightEndsPacket.getRedPlayers().size()));
if (playerRatio >= 0.4) {
int bluePlayerSize = fightEndsPacket.getBluePlayers().size();
int redPlayerSize = fightEndsPacket.getRedPlayers().size();
double playerRatio = bluePlayerSize > redPlayerSize ? (double) redPlayerSize / bluePlayerSize : (double) bluePlayerSize / redPlayerSize;
if (playerRatio < 0.6) {
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Statt schemOwner könntest du dir hier direkt bluePublic etc. speichern (weil das brauchst du dann ja mehrfach unten)

Statt schemOwner könntest du dir hier direkt bluePublic etc. speichern (weil das brauchst du dann ja mehrfach unten)
return;
}
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Das müsste ein XOR ^ sein

Das müsste ein XOR ^ sein
int blueSchemOwner = SchemNode.getSchematicOwner(fightEndsPacket.getBlueSchem());
int redSchemOwner = SchemNode.getSchematicOwner(fightEndsPacket.getRedSchem());
boolean bluePublic = SchematicNode.getSchematicNode(fightEndsPacket.getBlueSchem()).getId() == 0;
boolean redPublic = SchematicNode.getSchematicNode(fightEndsPacket.getRedSchem()).getId() == 0;
if ((blueSchemOwner == 0 && redSchemOwner != 0) || (blueSchemOwner != 0 && redSchemOwner == 0)) {
if (bluePublic ^ redPublic) {
return;
}
@ -71,15 +75,16 @@ public class FightEndsHandler implements SpigotHandler {
SchemElo.setElo(fightEndsPacket.getBlueSchem(), (int) Math.round(blueSchemElo + K * (blueResult - blueWinExpectation)));
SchemElo.setElo(fightEndsPacket.getRedSchem(), (int) Math.round(redSchemElo + K * (1 - blueResult - redWinExpectation)));
if (blueSchemOwner != 0 && redSchemOwner != 0) {
for (int bluePlayer : fightEndsPacket.getBluePlayers()) {
int playerElo = UserElo.getElo(bluePlayer, fightEndsPacket.getGameMode()).orElse(1000);
UserElo.setElo(bluePlayer, fightEndsPacket.getGameMode(), (int) Math.round(playerElo + K * (blueResult - blueWinExpectation)));
}
for (int redPlayer : fightEndsPacket.getRedPlayers()) {
int playerElo = UserElo.getElo(redPlayer, fightEndsPacket.getGameMode()).orElse(1000);
UserElo.setElo(redPlayer, fightEndsPacket.getGameMode(), (int) Math.round(playerElo + K * (1 - blueResult - redWinExpectation)));
}
if (!bluePublic) {
calculateEloOfTeam(fightEndsPacket.getBluePlayers(), fightEndsPacket.getGameMode(), blueResult - blueWinExpectation);
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Du hast hier sehr viel Codedopplung drin, würde mir eine teamunabhängige Abstrahierung wünschen.

Du hast hier sehr viel Codedopplung drin, würde mir eine teamunabhängige Abstrahierung wünschen.
calculateEloOfTeam(fightEndsPacket.getRedPlayers(), fightEndsPacket.getGameMode(), 1 - blueResult - blueWinExpectation);
}
}
private void calculateEloOfTeam(List<Integer> team, String gameMode, double factor) {
for (int player : team) {
int playerElo = UserElo.getElo(player, gameMode).orElse(1000);
UserElo.setElo(player, gameMode, (int) Math.round(playerElo + K * factor));
}
}
}

Datei anzeigen

@ -199,7 +199,7 @@ public class ChatListener extends BasicListener {
}
private void publicChat(SteamwarUser user, ProxiedPlayer sender, String message){
String name = getEmblem(user) + sender.getDisplayName();
String name = UserElo.getEmblem(user) + sender.getDisplayName();
String chatcolor = user.getUserGroup().getChatColorCode();
if(user.getUserGroup() != UserGroup.Member || user.getTeam() == 12 || user.getTeam() == 285 || user.getTeam() == 54)
@ -227,35 +227,6 @@ public class ChatListener extends BasicListener {
BungeeCore.log(sender.getServer().getInfo(), msg);
}
private static String getEmblem(SteamwarUser user) {
int maxEloOfPlayer = 0;
ArenaMode arenaMode = null;
for (ArenaMode mode : ArenaMode.getAllModes()) {
if (!mode.isRanked()) continue;
if (UserElo.getFightsOfSeason(user.getId(), mode.getSchemType()) < 10) continue;
Optional<Integer> currentElo = UserElo.getElo(user.getId(), mode.getSchemType());
if (currentElo.isPresent() && currentElo.get() > maxEloOfPlayer) {
maxEloOfPlayer = currentElo.get();
arenaMode = mode;
}
}
if (arenaMode == null) return "";
int maxEloOfGameMode = UserElo.getMaxElo(arenaMode.getSchemType());
return getEmblem(maxEloOfPlayer, maxEloOfGameMode);
}
private static String getEmblem(int maxEloOfPlayer, int maxEloOfGameMode) {
if (maxEloOfPlayer > maxEloOfGameMode * 0.99) return "§5❂ ";
if (maxEloOfPlayer > maxEloOfGameMode * 0.94) return "§c✹ ";
if (maxEloOfPlayer > maxEloOfGameMode * 0.84) return "§b✸ ";
if (maxEloOfPlayer > maxEloOfGameMode * 0.69) return "§a✷ ";
if (maxEloOfPlayer > maxEloOfGameMode * 0.49) return "§e✶ ";
if (maxEloOfPlayer > maxEloOfGameMode * 0.26) return "§f✦ ";
return "§7✧ ";
}
private void localChat(ChatEvent e, String [] command){
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Das hier bei jeder einzelnen Chatnachricht durchzuführen ist sehr wahrscheinlich performanceproblematisch. Besser wäre hier ein Cache und ich würde die Emblemberechnung eher ungerne hier im ChatListener drin haben wollen, eher in UserElo.

Das hier bei jeder einzelnen Chatnachricht durchzuführen ist sehr wahrscheinlich performanceproblematisch. Besser wäre hier ein Cache und ich würde die Emblemberechnung eher ungerne hier im ChatListener drin haben wollen, eher in UserElo.
Veraltet
Review

Ich muss aber alle gecached embleme killen, wenn es einen neuen max gibt und für dich wenn du eine neue elo erhälst richtig?

Ich muss aber alle gecached embleme killen, wenn es einen neuen max gibt und für dich wenn du eine neue elo erhälst richtig?
Veraltet
Review

Es reicht auch, wenn es nach einer Stunde angepasst wird...

Es reicht auch, wenn es nach einer Stunde angepasst wird...
Veraltet
Review

Würde ich lieber nicht machen, ich würde gerne sie so schnell geupdated wie möglich haben.

Würde ich lieber nicht machen, ich würde gerne sie so schnell geupdated wie möglich haben.
Veraltet
Review

Dann kannst du die Embleme dennoch cachen. Und ob sie so schnell geupdatet werden wie möglich oder nicht, dazwischen liegen bis zu 3 Kämpfe (in etwa).... Es ist also ziemlich egal und dafür ein heidenaufwand, das Echtzeit zu halten.

Dann kannst du die Embleme dennoch cachen. Und ob sie so schnell geupdatet werden wie möglich oder nicht, dazwischen liegen bis zu 3 Kämpfe (in etwa).... Es ist also ziemlich egal und dafür ein heidenaufwand, das Echtzeit zu halten.
Veraltet
Review

Ich sehe jetzt nicht unbedingt so viel aufwand darin, guck dir gleich einfach mal meine Lösung an und mecker dann gerne nochmal rum, dann schmeiße ich es gerne weiter raus.

Ich sehe jetzt nicht unbedingt so viel aufwand darin, guck dir gleich einfach mal meine Lösung an und mecker dann gerne nochmal rum, dann schmeiße ich es gerne weiter raus.
ProxiedPlayer sender = (ProxiedPlayer) e.getSender();
BungeeCore.log(sender, e.getMessage());

Datei anzeigen

@ -24,7 +24,6 @@ public class SchemElo {
private static final Statement elo = new Statement("SELECT SchemElo FROM Elo WHERE SchemID = ? AND Season = ?");
private static final Statement setElo = new Statement("UPDATE SchemElo SET Elo = ? WHERE Season = ? AND SchemID = ?");
// private static final Statement place = new Statement("SELECT COUNT(*) AS Place FROM SchemElo WHERE Elo > ? AND Season = ?");
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Wird vorrausichtlich Ingame nie benötigt (MC Chat ist nicht unbedingt praktisch zum Anzeigen von Bestenlisten)

Wird vorrausichtlich Ingame nie benötigt (MC Chat ist nicht unbedingt praktisch zum Anzeigen von Bestenlisten)
public static int getElo(int schemID) {
return getElo(Season.getSeason(), schemID);

Datei anzeigen

@ -1,32 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2020 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.sql;
public class SchemNode {
private SchemNode() {}
private static final Statement getSchemOwner = new Statement("SELECT NodeOwner FROM SchematicNode WHERE NodeId = ?");
public static int getSchematicOwner(int schemId) {
return getSchemOwner.select(rs -> {
return rs.getInt("NodeOwner");
}, schemId);
}
}

Datei anzeigen

@ -19,6 +19,7 @@
package de.steamwar.bungeecore.sql;
import de.steamwar.bungeecore.ArenaMode;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
@ -30,9 +31,9 @@ public class UserElo {
private UserElo() {
}
private static Integer cachedSeason = null;
private static final Map<Key, Optional<Integer>> userEloCache = new HashMap<>();
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Da lieber eine Map<Map<>>, das bläst sich dann weniger auf.

Da lieber eine Map<Map<>>, das bläst sich dann weniger auf.
Veraltet
Review

Wie meinst du das genau?

Wie meinst du das genau?
Veraltet
Review

HashMaps brauchen zur Kollisionsvermeidung immer Freiraum. Je kleiner die HashMaps bleiben, desto besser.

HashMaps brauchen zur Kollisionsvermeidung immer Freiraum. Je kleiner die HashMaps bleiben, desto besser.
Veraltet
Review

Würdest du dann GameMode UserId oder UserId GameMode als reihenfolge wählen?

Würdest du dann GameMode UserId oder UserId GameMode als reihenfolge wählen?
Veraltet
Review

Definitiv Map<GameMode, Map<User, >>

Definitiv Map<GameMode, Map<User, >>
private static final Map<String, Integer> maxEloCache = new HashMap<>();
private static final Map<Integer, String> emblemCache = new HashMap<>();
@AllArgsConstructor
@EqualsAndHashCode
@ -47,38 +48,15 @@ public class UserElo {
private static final Statement maxElo = new Statement("SELECT MAX(Elo) AS MaxElo FROM UserElo WHERE Season = ? AND GameMode = ?");
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(?)");
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Du clearst den Cache eh schon stündlich, das ist häufig genug auch für Seasonänderungen.

Du clearst den Cache eh schon stündlich, das ist häufig genug auch für Seasonänderungen.
private static void clearCacheIfNeeded(int season) {
int currentSeason = Season.getSeason();
if (currentSeason != season) {
return;
}
if (cachedSeason != null && cachedSeason != currentSeason) {
clearCache();
cachedSeason = currentSeason;
}
}
public static Optional<Integer> getElo(int userID, String gameMode) {
return getElo(Season.getSeason(), userID, gameMode);
}
public static Optional<Integer> getElo(int season, int userID, String gameMode) {
clearCacheIfNeeded(season);
if (season == Season.getSeason()) {
Key key = new Key(userID, gameMode);
return userEloCache.computeIfAbsent(key, k -> {
return elo.select(rs -> {
if (rs.next())
return Optional.of(rs.getInt("UserElo"));
return Optional.empty();
});
});
}
return elo.select(rs -> {
if (rs.next())
return Optional.of(rs.getInt("Elo"));
return Optional.empty();
}, userID, gameMode, season);
Key key = new Key(userID, gameMode);
return userEloCache.computeIfAbsent(key, k -> {
return elo.select(rs -> {
if (rs.next())
return Optional.of(rs.getInt("Elo"));
return Optional.empty();
}, userID, gameMode, Season.getSeason());
});
}
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Wenn hier eh schon mit Integer gearbeitet wird, kann man das Optional auch weglassen...

Wenn hier eh schon mit Integer gearbeitet wird, kann man das Optional auch weglassen...
Veraltet
Review

Würde ich ungern, weil so kann man darauf mit .orElse() ziemlich gut einen default direkt auswählen.

Würde ich ungern, weil so kann man darauf mit `.orElse()` ziemlich gut einen default direkt auswählen.
Veraltet
Review

Und halt Optional.empty() als es gibt keinen wert in der db wählen, macht es für die emblem berechnung angenehmer, als mit einem spezial value zu arbeiten.

Und halt Optional.empty() als es gibt keinen wert in der db wählen, macht es für die emblem berechnung angenehmer, als mit einem spezial value zu arbeiten.
public static int getFightsOfSeason(int userID, String gameMode) {
@ -90,59 +68,78 @@ public class UserElo {
}
public static int getMaxElo(String gameMode) {
return getMaxElo(Season.getSeason(), gameMode);
}
public static int getMaxElo(int season, String gameMode) {
clearCacheIfNeeded(season);
if (season == Season.getSeason()) {
return maxEloCache.computeIfAbsent(gameMode, gm -> {
return maxElo.select(rs -> {
if (rs.next())
return rs.getInt("MaxElo");
return -1;
});
});
}
return maxElo.select(rs -> {
if (rs.next())
return rs.getInt("MaxElo");
return -1;
}, season, gameMode);
return maxEloCache.computeIfAbsent(gameMode, gm -> {
return 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) {
setElo(Season.getSeason(), userId, gameMode, elo);
}
public static void setElo(int season, int userId, String gameMode, int elo) {
clearCacheIfNeeded(season);
if (season == Season.getSeason()) {
Key key = new Key(userId, gameMode);
userEloCache.put(key, Optional.of(elo));
maxEloCache.compute(gameMode, (gm, max) -> {
if (max == null || max < elo)
return elo;
return max;
});
}
setElo.update(elo, season, userId, gameMode);
emblemCache.remove(userId);
Key key = new Key(userId, gameMode);
userEloCache.put(key, Optional.of(elo));
maxEloCache.compute(gameMode, (gm, max) -> {
if (max == null || max < elo) {
emblemCache.clear();
return elo;
}
return max;
});
setElo.update(elo, Season.getSeason(), userId, gameMode);
}
public static int getPlacement(int elo, String gameMode) {
return getPlacement(Season.getSeason(), elo, gameMode);
}
public static int getPlacement(int season, int elo, String gameMode) {
return place.select(rs -> {
if (rs.next())
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Wann ist season hier != currentSeason?

Wann ist season hier != currentSeason?
return rs.getInt("Place");
return -1;
}, gameMode, elo, season);
}, gameMode, elo, Season.getSeason());
}
public static String getEmblem(SteamwarUser user) {
if (emblemCache.containsKey(user.getId())) {
return emblemCache.get(user.getId());
}
int maxEloOfPlayer = 0;
ArenaMode arenaMode = null;
for (ArenaMode mode : ArenaMode.getAllModes()) {
if (!mode.isRanked()) continue;
if (UserElo.getFightsOfSeason(user.getId(), mode.getSchemType()) < 10) continue;
Optional<Integer> currentElo = UserElo.getElo(user.getId(), mode.getSchemType());
if (currentElo.isPresent() && currentElo.get() > maxEloOfPlayer) {
maxEloOfPlayer = currentElo.get();
arenaMode = mode;
}
}
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

Selbe Frage

Selbe Frage
if (arenaMode == null) {
emblemCache.put(user.getId(), "");
return "";
}
int maxEloOfGameMode = UserElo.getMaxElo(arenaMode.getSchemType());
String emblem = getEmblem(maxEloOfPlayer, maxEloOfGameMode);
emblemCache.put(user.getId(), emblem);
return emblem;
}
private static String getEmblem(int maxEloOfPlayer, int maxEloOfGameMode) {
if (maxEloOfPlayer > maxEloOfGameMode * 0.99) return "§5❂";
if (maxEloOfPlayer > maxEloOfGameMode * 0.94) return "§c✹";
if (maxEloOfPlayer > maxEloOfGameMode * 0.84) return "§b✸";
if (maxEloOfPlayer > maxEloOfGameMode * 0.69) return "§a✷";
if (maxEloOfPlayer > maxEloOfGameMode * 0.49) return "§e✶";
if (maxEloOfPlayer > maxEloOfGameMode * 0.26) return "§f✦";
YoyoNow markierte diese Unterhaltung als gelöst Veraltet
Veraltet
Review

.

.
return "§7✧";
}
public static void clearCache() {
userEloCache.clear();
maxEloCache.clear();
emblemCache.clear();
}
}