diff --git a/src/main/java/com/synops/replayreader/common/comparator/SortingComparators.java b/src/main/java/com/synops/replayreader/common/comparator/SortingComparators.java index acea122..63b6072 100644 --- a/src/main/java/com/synops/replayreader/common/comparator/SortingComparators.java +++ b/src/main/java/com/synops/replayreader/common/comparator/SortingComparators.java @@ -39,6 +39,8 @@ public void initMap() { new SortingHolder(new PlayerListComparatorInt(replayService::getAvgBlocked))); this.map.put(PlayerSort.XP.getResourceBundleName(), new SortingHolder(new PlayerListComparatorInt(replayService::getAvgXp))); + this.map.put(PlayerSort.PRESTIGE_POINTS.getResourceBundleName(), + new SortingHolder(new PlayerListComparatorInt(replayService::getComp7PrestigePoints))); } public Comparator getComparator(String sort) { diff --git a/src/main/java/com/synops/replayreader/common/util/Constants.java b/src/main/java/com/synops/replayreader/common/util/Constants.java index 0cec981..dd06ba4 100644 --- a/src/main/java/com/synops/replayreader/common/util/Constants.java +++ b/src/main/java/com/synops/replayreader/common/util/Constants.java @@ -4,6 +4,7 @@ public class Constants { public static final String APP_NAME = "Replay Reader"; public static final String CLAN_ALL = ""; public static final String CLAN_LESS = ""; + public static final String MAP_ALL = ""; public static final String OVERALL = ""; public static final int JSON_DEPTH = 3; } diff --git a/src/main/java/com/synops/replayreader/maps/comparator/MapListComparator.java b/src/main/java/com/synops/replayreader/maps/comparator/MapListComparator.java new file mode 100644 index 0000000..8e59151 --- /dev/null +++ b/src/main/java/com/synops/replayreader/maps/comparator/MapListComparator.java @@ -0,0 +1,31 @@ +package com.synops.replayreader.maps.comparator; + +import static com.synops.replayreader.common.util.Constants.MAP_ALL; + +import java.util.Comparator; +import java.util.function.Function; +import org.springframework.stereotype.Component; + +@Component +public class MapListComparator implements Comparator { + + private Function function; + + public MapListComparator() { + } + + public void configure(Function function) { + this.function = function; + } + + @Override + public int compare(String map1, String map2) { + int valueMap1 = function.apply(map1); + int valueMap2 = function.apply(map2); + if (MAP_ALL.equals(map1)) { + valueMap1 = Integer.MAX_VALUE; + } + + return Integer.compare(valueMap2, valueMap1); + } +} \ No newline at end of file diff --git a/src/main/java/com/synops/replayreader/maps/util/MapStringConverter.java b/src/main/java/com/synops/replayreader/maps/util/MapStringConverter.java new file mode 100644 index 0000000..28dabec --- /dev/null +++ b/src/main/java/com/synops/replayreader/maps/util/MapStringConverter.java @@ -0,0 +1,55 @@ +package com.synops.replayreader.maps.util; + +import static com.synops.replayreader.common.util.Constants.MAP_ALL; + +import com.synops.replayreader.common.i18n.I18nUtils; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.function.Function; +import javafx.util.StringConverter; +import org.springframework.stereotype.Component; + +@Component +public class MapStringConverter extends StringConverter { + + private final ResourceBundle resourceBundle = I18nUtils.getBundle(); + private Function function; + private int totalGamesCount; + + public MapStringConverter() { + } + + public void configure(Function function, int totalGamesCount) { + this.function = function; + this.totalGamesCount = totalGamesCount; + } + + @Override + public String toString(String mapString) { + if (mapString == null) { + return null; + } + + if (MAP_ALL.equals(mapString)) { + return String.format("%s (%d)", mapString, totalGamesCount); + } + + int gamesCount = function.apply(mapString); + String mapName = getMapName(mapString); + + return String.format("%s (%d)", mapName, gamesCount); + } + + @Override + public String fromString(String mapString) { + return mapString; + } + + private String getMapName(String map) { + try { + return resourceBundle.getString(map); + } catch (MissingResourceException exception) { + return map; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/synops/replayreader/player/model/PlayerSort.java b/src/main/java/com/synops/replayreader/player/model/PlayerSort.java index 80eb309..ad03c08 100644 --- a/src/main/java/com/synops/replayreader/player/model/PlayerSort.java +++ b/src/main/java/com/synops/replayreader/player/model/PlayerSort.java @@ -8,7 +8,8 @@ public enum PlayerSort { "penrate", "textPenRate", "main.toolbar.sort.pen-rate"), TEAMDMG("team dmg", "textTeamDmg", "main.toolbar.sort.team-damage"), ASSIST("assist", "textAssist", "main.toolbar.sort.assist"), BLOCKED("dmg blocked", "textBlocked", - "main.toolbar.sort.damage-blocked"), XP("xp", "textXP", "main.toolbar.sort.damage-xp"); + "main.toolbar.sort.damage-blocked"), XP("xp", "textXP", "main.toolbar.sort.damage-xp"), PRESTIGE_POINTS( + "prestige points", "textPrestigePoints", "main.toolbar.sort.prestige-points"); private final String text; private final String elementId; diff --git a/src/main/java/com/synops/replayreader/replay/dto/StatsVehiclesPOJO.java b/src/main/java/com/synops/replayreader/replay/dto/StatsVehiclesPOJO.java index d9b1c44..013fd80 100644 --- a/src/main/java/com/synops/replayreader/replay/dto/StatsVehiclesPOJO.java +++ b/src/main/java/com/synops/replayreader/replay/dto/StatsVehiclesPOJO.java @@ -13,6 +13,7 @@ public class StatsVehiclesPOJO { public int damageAssistedTrack; public int damageBlockedByArmor; public int damageReceivedFromInvisibles; + public int equipmentDamageDealt; public int spotted; public int capturePoints; public int flagCapture; @@ -25,6 +26,8 @@ public class StatsVehiclesPOJO { public int mileage; public String killerID; public int health; + public int healthRepair; + public int alliedHealthRepair; public String team; public int lifeTime; public int directHits; @@ -34,4 +37,5 @@ public class StatsVehiclesPOJO { public int damageAssistedStun; public int stunNum; public int tkills; + public int comp7PrestigePoints; } diff --git a/src/main/java/com/synops/replayreader/replay/model/ReplayCollection.java b/src/main/java/com/synops/replayreader/replay/model/ReplayCollection.java index 97b05f1..37f7e42 100644 --- a/src/main/java/com/synops/replayreader/replay/model/ReplayCollection.java +++ b/src/main/java/com/synops/replayreader/replay/model/ReplayCollection.java @@ -7,6 +7,8 @@ public interface ReplayCollection { Set getUniquePlayers(); + Set getUniquePlayersIgnoringMapFilter(); + List getUniquePlayersClan(String clanAbbrev); List getVehiclesForPlayer(String player); @@ -15,7 +17,7 @@ public interface ReplayCollection { Player getPlayerInfo(String player); - void updateReplayFilter(ReplayFilter replayFilter); + void setMapFilter(String map); int getNumberOfClanPlayers(String clan); @@ -25,7 +27,9 @@ public interface ReplayCollection { List getMaps(String player, String vehicle); - int getNumberOfMapsPlayed(String player, String vehicle, String map); + int getNumberOfGamesOnMap(String map); + + int getTotalGames(); double getWinRate(String player, String vehicle); @@ -43,6 +47,10 @@ public interface ReplayCollection { int getAvgBlocked(String player, String vehicle); + int getAvgHealthRepair(String player, String vehicle); + + int getAvgAlliedHealthRepair(String player, String vehicle); + int getAvgLifeTime(String player, String vehicle); int getAvgHitsReceived(String player, String vehicle); @@ -51,6 +59,8 @@ public interface ReplayCollection { int getAvgDamageReceivedFromInvisibles(String player, String vehicle); + int getAvgEquipmentDamageDealt(String player, String vehicle); + double getAvgShots(String player, String vehicle); int getAvgTDamageDealt(String player, String vehicle); @@ -72,4 +82,6 @@ public interface ReplayCollection { double getAvgXPRank(String player, String vehicle); double getAvgDamageRank(String player, String vehicle); + + int getComp7PrestigePoints(String player, String vehicle); } diff --git a/src/main/java/com/synops/replayreader/replay/model/ReplayCollectionImpl.java b/src/main/java/com/synops/replayreader/replay/model/ReplayCollectionImpl.java index 11221ef..2e00c03 100644 --- a/src/main/java/com/synops/replayreader/replay/model/ReplayCollectionImpl.java +++ b/src/main/java/com/synops/replayreader/replay/model/ReplayCollectionImpl.java @@ -37,11 +37,14 @@ public List load(@NonNull Triple key) { String player = key.getLeft(); String vehicle = key.getMiddle(); ReplayFilter filter = key.getRight(); - return ReplayCollectionImpl.this.replays.parallelStream().filter( - (r) -> BattleType.ANY.equals(filter.getBattleType()) || filter.getBattleType().getId() - .equals(r.getBattleType())).filter((r) -> r.existPlayer(player)).filter( - (r) -> StringUtils.isEmpty(vehicle) || vehicle.equals( - r.getPlayerVehicleMappingByPlayerName(player).getVehicleType())) + return ReplayCollectionImpl.this.replays.parallelStream() + .filter((r) -> BattleType.ANY.equals(filter.getBattleType()) + || filter.getBattleType().getId().equals(r.getBattleType())) + .filter((r) -> StringUtils.isEmpty(filter.getMap()) + || filter.getMap().equals(r.getMapName())) + .filter((r) -> r.existPlayer(player)) + .filter((r) -> StringUtils.isEmpty(vehicle) + || vehicle.equals(r.getPlayerVehicleMappingByPlayerName(player).getVehicleType())) .collect(Collectors.toList()); } }); @@ -65,14 +68,31 @@ private List filteredReplays(String player, String vehicle) { } } + private List getFilteredReplaysByMap() { + if (StringUtils.isEmpty(replayFilter.getMap())) { + return replays; + } + return replays.parallelStream() + .filter((r) -> replayFilter.getMap().equals(r.getMapName())) + .collect(Collectors.toList()); + } + public Set getUniquePlayers() { - return replays.parallelStream().flatMap((r) -> r.getPlayers().stream()).map(Player::getName) + return getFilteredReplaysByMap().parallelStream() + .flatMap((r) -> r.getPlayers().stream()).map(Player::getName) + .collect(Collectors.toSet()); + } + + public Set getUniquePlayersIgnoringMapFilter() { + return replays.parallelStream() + .flatMap((r) -> r.getPlayers().stream()).map(Player::getName) .collect(Collectors.toSet()); } public Set getUniqueClans() { Set result = Collections.synchronizedSet(new HashSet<>()); - result.addAll(replays.parallelStream().map(Replay::getPlayers).flatMap(Collection::stream) + result.addAll(getFilteredReplaysByMap().parallelStream() + .map(Replay::getPlayers).flatMap(Collection::stream) .map(Player::getClanAbbrev).collect(Collectors.toSet())); return result; } @@ -82,8 +102,9 @@ public int getNumberOfClanPlayers(String clan) { } public List getUniquePlayersClan(String clanAbbrev) { - Set playerNames = replays.parallelStream().map(Replay::getPlayers) - .flatMap(Collection::stream).filter(p -> clanAbbrev.equals(p.getClanAbbrev())) + Set playerNames = getFilteredReplaysByMap().parallelStream() + .map(Replay::getPlayers).flatMap(Collection::stream) + .filter(p -> clanAbbrev.equals(p.getClanAbbrev())) .map(Player::getName).collect(Collectors.toSet()); return new ArrayList<>(Collections.synchronizedSet(playerNames)); @@ -94,7 +115,8 @@ public int getNumberOfGames(String player, String vehicle) { } public List getVehiclesForPlayer(String player) { - var vehicleGroups = replays.parallelStream().filter(r -> r.existPlayer(player)) + var vehicleGroups = getFilteredReplaysByMap().parallelStream() + .filter(r -> r.existPlayer(player)) .map(replay -> replay.getPlayerVehicleMappingByPlayerName(player).getVehicleType()) .collect(Collectors.groupingByConcurrent(vehicleType -> vehicleType)); @@ -117,11 +139,15 @@ public List getMaps(String player, String vehicle) { .collect(Collectors.toList()); } - public int getNumberOfMapsPlayed(String player, String vehicle, String map) { - return (int) filteredReplays(player, vehicle).parallelStream() + public int getNumberOfGamesOnMap(String map) { + return (int) replays.parallelStream() .filter((r) -> map.equals(r.getMapName())).count(); } + public int getTotalGames() { + return replays.size(); + } + public double getWinRate(String player, String vehicle) { List filteredReplays = filteredReplays(player, vehicle); long wins = filteredReplays.parallelStream().filter( @@ -181,6 +207,16 @@ public int getAvgBlocked(String player, String vehicle) { (r) -> (double) r.getPlayerStatsByPlayerName(player).getDamageBlockedByArmor())).intValue(); } + public int getAvgHealthRepair(String player, String vehicle) { + return filteredReplays(player, vehicle).parallelStream().collect(Collectors.averagingInt( + (r) -> r.getPlayerStatsByPlayerName(player).getHealthRepair())).intValue(); + } + + public int getAvgAlliedHealthRepair(String player, String vehicle) { + return filteredReplays(player, vehicle).parallelStream().collect(Collectors.averagingInt( + (r) -> r.getPlayerStatsByPlayerName(player).getAlliedHealthRepair())).intValue(); + } + public int getAvgLifeTime(String player, String vehicle) { return filteredReplays(player, vehicle).parallelStream().collect(Collectors.averagingDouble( (r) -> (double) r.getPlayerStatsByPlayerName(player).getLifeTime())).intValue(); @@ -202,6 +238,11 @@ public int getAvgDamageReceivedFromInvisibles(String player, String vehicle) { .intValue(); } + public int getAvgEquipmentDamageDealt(String player, String vehicle) { + return filteredReplays(player, vehicle).parallelStream().collect(Collectors.averagingDouble( + (r) -> (double) r.getPlayerStatsByPlayerName(player).getEquipmentDamageDealt())).intValue(); + } + public double getAvgShots(String player, String vehicle) { return filteredReplays(player, vehicle).parallelStream().collect(Collectors.averagingDouble( (r) -> (double) r.getPlayerStatsByPlayerName(player).getShots())); @@ -253,8 +294,8 @@ public int getAvgCapReset(String player, String vehicle) { (r) -> r.getPlayerStatsByPlayerName(player).getDroppedCapturePoints())).intValue(); } - public void updateReplayFilter(ReplayFilter replayFilter) { - this.replayFilter = Objects.requireNonNullElseGet(replayFilter, ReplayFilter::createDefault); + public void setMapFilter(String map) { + this.replayFilter.setMap(map); } private void debugGetAllVehicles() { @@ -331,4 +372,9 @@ public double getAvgDamageRank(String player, String vehicle) { return (double) sumRank / (double) filteredReplays.size(); } + + public int getComp7PrestigePoints(String player, String vehicle) { + return filteredReplays(player, vehicle).parallelStream().collect(Collectors.averagingDouble( + (r) -> r.getPlayerStatsByPlayerName(player).getComp7PrestigePoints())).intValue(); + } } diff --git a/src/main/java/com/synops/replayreader/replay/model/ReplayFilter.java b/src/main/java/com/synops/replayreader/replay/model/ReplayFilter.java index d4cf22f..d1c4088 100644 --- a/src/main/java/com/synops/replayreader/replay/model/ReplayFilter.java +++ b/src/main/java/com/synops/replayreader/replay/model/ReplayFilter.java @@ -6,9 +6,11 @@ public class ReplayFilter { private BattleType battleType; + private String map; private ReplayFilter() { this.battleType = BattleType.ANY; + this.map = null; } public static ReplayFilter createDefault() { @@ -24,6 +26,15 @@ public ReplayFilter setBattleType(BattleType battleType) { return this; } + public String getMap() { + return this.map; + } + + public ReplayFilter setMap(String map) { + this.map = map; + return this; + } + public boolean equals(Object obj) { return EqualsBuilder.reflectionEquals(this, obj, false); } diff --git a/src/main/java/com/synops/replayreader/replay/service/ReplayModelBuilder.java b/src/main/java/com/synops/replayreader/replay/service/ReplayModelBuilder.java index 93707cc..6959d18 100644 --- a/src/main/java/com/synops/replayreader/replay/service/ReplayModelBuilder.java +++ b/src/main/java/com/synops/replayreader/replay/service/ReplayModelBuilder.java @@ -144,8 +144,11 @@ private List createVehicleStats() { vehicleStats.setDamageDealt(vehiclePOJO.damageDealt); vehicleStats.setDamageReceived(vehiclePOJO.damageReceived); vehicleStats.setDamageReceivedFromInvisibles(vehiclePOJO.damageReceivedFromInvisibles); + vehicleStats.setEquipmentDamageDealt(vehiclePOJO.equipmentDamageDealt); vehicleStats.setDirectHitsReceived(vehiclePOJO.directHitsReceived); vehicleStats.setHealth(vehiclePOJO.health); + vehicleStats.setHealthRepair(vehiclePOJO.healthRepair); + vehicleStats.setAlliedHealthRepair(vehiclePOJO.alliedHealthRepair); vehicleStats.setKillerID(vehiclePOJO.killerID); vehicleStats.setKills(vehiclePOJO.kills); vehicleStats.setLifeTime(vehiclePOJO.lifeTime); @@ -166,6 +169,7 @@ private List createVehicleStats() { vehicleStats.setDamageAssistedStun(vehiclePOJO.damageAssistedStun); vehicleStats.setTKills(vehiclePOJO.tkills); vehicleStats.setStunNum(vehiclePOJO.stunNum); + vehicleStats.setComp7PrestigePoints(vehiclePOJO.comp7PrestigePoints); result.add(vehicleStats); } diff --git a/src/main/java/com/synops/replayreader/replay/service/ReplayService.java b/src/main/java/com/synops/replayreader/replay/service/ReplayService.java index 7d3a2b1..57cd836 100644 --- a/src/main/java/com/synops/replayreader/replay/service/ReplayService.java +++ b/src/main/java/com/synops/replayreader/replay/service/ReplayService.java @@ -9,12 +9,14 @@ public interface ReplayService { - void load(List files); - void load(List files, Consumer progressListener); + void setMapFilter(String map); + ObservableList getPlayers(); + ObservableList getPlayersIgnoringMapFilter(); + Player getPlayerInfo(String player); ObservableList getVehicles(String player); @@ -25,7 +27,9 @@ public interface ReplayService { double getWinrate(String player, String vehicle); - int getNumberOfMapsPlayed(String player, String vehicle, String map); + int getNumberOfGamesOnMap(String map); + + int getTotalGames(); int getNumberOFClanPlayers(String clan); @@ -47,6 +51,10 @@ public interface ReplayService { int getAvgBlocked(String player, String vehicle); + int getAvgHealthRepair(String player, String vehicle); + + int getAvgAlliedHealthRepair(String player, String vehicle); + int getAvgLifeTime(String player, String vehicle); int getAvgHitsReceived(String player, String vehicle); @@ -55,6 +63,8 @@ public interface ReplayService { int getAvgDamageReceivedFromInvisibles(String player, String vehicle); + int getAvgEquipmentDamageDealt(String player, String vehicle); + int getAvgTdamageDealt(String player, String vehicle); double getAvgTKills(String player, String vehicle); @@ -76,4 +86,6 @@ public interface ReplayService { double getAvgXPRank(String player, String vehicle); double getAvgDamageRank(String player, String vehicle); + + int getComp7PrestigePoints(String player, String vehicle); } diff --git a/src/main/java/com/synops/replayreader/replay/service/ReplayServiceImpl.java b/src/main/java/com/synops/replayreader/replay/service/ReplayServiceImpl.java index 6c3bb63..b6bf749 100644 --- a/src/main/java/com/synops/replayreader/replay/service/ReplayServiceImpl.java +++ b/src/main/java/com/synops/replayreader/replay/service/ReplayServiceImpl.java @@ -24,14 +24,15 @@ public ReplayServiceImpl(ReplayController replayController) { } @Override - public void load(List files) { - this.load(files, (eReplayProgressEvent) -> { - }); + public void load(List files, Consumer progressListener) { + replayCollection = replayController.readReplays(files, BattleType.ANY, progressListener); } @Override - public void load(List files, Consumer progressListener) { - replayCollection = replayController.readReplays(files, BattleType.ANY, progressListener); + public void setMapFilter(String map) { + if (this.replayCollection != null) { + this.replayCollection.setMapFilter(map); + } } @Override @@ -40,6 +41,12 @@ public ObservableList getPlayers() { : FXCollections.observableList(new ArrayList<>(this.replayCollection.getUniquePlayers())); } + @Override + public ObservableList getPlayersIgnoringMapFilter() { + return this.replayCollection == null ? FXCollections.emptyObservableList() + : FXCollections.observableList(new ArrayList<>(this.replayCollection.getUniquePlayersIgnoringMapFilter())); + } + @Override public Player getPlayerInfo(String player) { return this.replayCollection.getPlayerInfo(player); @@ -68,8 +75,13 @@ public double getWinrate(String player, String vehicle) { } @Override - public int getNumberOfMapsPlayed(String player, String vehicle, String map) { - return this.replayCollection.getNumberOfMapsPlayed(player, vehicle, map); + public int getNumberOfGamesOnMap(String map) { + return this.replayCollection.getNumberOfGamesOnMap(map); + } + + @Override + public int getTotalGames() { + return this.replayCollection == null ? 0 : this.replayCollection.getTotalGames(); } @Override @@ -122,6 +134,16 @@ public int getAvgBlocked(String player, String vehicle) { return this.replayCollection.getAvgBlocked(player, vehicle); } + @Override + public int getAvgHealthRepair(String player, String vehicle) { + return this.replayCollection.getAvgHealthRepair(player, vehicle); + } + + @Override + public int getAvgAlliedHealthRepair(String player, String vehicle) { + return this.replayCollection.getAvgAlliedHealthRepair(player, vehicle); + } + @Override public int getAvgLifeTime(String player, String vehicle) { return this.replayCollection.getAvgLifeTime(player, vehicle); @@ -142,6 +164,11 @@ public int getAvgDamageReceivedFromInvisibles(String player, String vehicle) { return this.replayCollection.getAvgDamageReceivedFromInvisibles(player, vehicle); } + @Override + public int getAvgEquipmentDamageDealt(String player, String vehicle) { + return this.replayCollection.getAvgEquipmentDamageDealt(player, vehicle); + } + @Override public int getAvgTdamageDealt(String player, String vehicle) { return this.replayCollection.getAvgTDamageDealt(player, vehicle); @@ -196,4 +223,9 @@ public double getAvgXPRank(String player, String vehicle) { public double getAvgDamageRank(String player, String vehicle) { return this.replayCollection.getAvgDamageRank(player, vehicle); } + + @Override + public int getComp7PrestigePoints(String player, String vehicle) { + return this.replayCollection.getComp7PrestigePoints(player, vehicle); + } } diff --git a/src/main/java/com/synops/replayreader/ui/controller/MainWindowController.java b/src/main/java/com/synops/replayreader/ui/controller/MainWindowController.java index 24e0fa4..4926bc5 100644 --- a/src/main/java/com/synops/replayreader/ui/controller/MainWindowController.java +++ b/src/main/java/com/synops/replayreader/ui/controller/MainWindowController.java @@ -1,6 +1,7 @@ package com.synops.replayreader.ui.controller; import static com.synops.replayreader.common.util.Constants.CLAN_ALL; +import static com.synops.replayreader.common.util.Constants.MAP_ALL; import static com.synops.replayreader.common.util.Constants.OVERALL; import com.synops.replayreader.clan.comparator.ClanListComparator; @@ -11,8 +12,8 @@ import com.synops.replayreader.core.service.NotificationService; import com.synops.replayreader.core.window.WindowController; import com.synops.replayreader.core.window.WindowManager; -import com.synops.replayreader.maps.comparator.MapsComparator; -import com.synops.replayreader.maps.ui.MapListCell; +import com.synops.replayreader.maps.comparator.MapListComparator; +import com.synops.replayreader.maps.util.MapStringConverter; import com.synops.replayreader.player.comparator.PlayerListComparatorLong; import com.synops.replayreader.player.model.PlayerSort; import com.synops.replayreader.player.ui.PlayerListCell; @@ -75,12 +76,14 @@ public class MainWindowController implements WindowController { private final ResourceBundle resourceBundle; private final ClanStringConverter clanStringConverter; private final ClanListComparator clanListComparator; + private final MapStringConverter mapStringConverter; + private final MapListComparator mapListComparator; private final SortingComparators sortingComparators; - private final MapsComparator mapsComparator; private final DragDropSupport dragDropSupport; private final StringProperty selectedPlayer = new SimpleStringProperty(""); private final StringProperty selectedVehicle = new SimpleStringProperty(""); private final StringProperty selectedClan = new SimpleStringProperty(""); + private final StringProperty selectedMap = new SimpleStringProperty(""); private final BuildProperties buildProperties; private final NotificationService notificationService; private final WindowManager windowManager; @@ -95,6 +98,8 @@ public class MainWindowController implements WindowController { @FXML private ChoiceBox clanChoiceBox; @FXML + private ChoiceBox mapChoiceBox; + @FXML private HBox hbox; @FXML private MenuItem showSettingsWindow; @@ -128,12 +133,16 @@ public class MainWindowController implements WindowController { @FXML private TextField textBlocked; @FXML + private TextField textHeal; + @FXML private TextField textLifeTime; @FXML private TextField textHitsReceived; @FXML private TextField textDmgReceived; @FXML + private TextField textStrikesDamage; + @FXML private TextField textDmgReceivedInvisible; @FXML private TextField textTeamDmg; @@ -158,7 +167,7 @@ public class MainWindowController implements WindowController { @FXML private TextField textDamageRank; @FXML - private ListView mapsList; + private TextField textPrestigePoints; @FXML private ProgressBar progressBar; @FXML @@ -169,9 +178,10 @@ public class MainWindowController implements WindowController { public MainWindowController(ReplayService replayService, @Nullable HostServices hostServices, DialogService dialogService, UpdateClient updateClient, ResourceBundle resourceBundle, ClanStringConverter clanStringConverter, ClanListComparator clanListComparator, - SortingComparators sortingComparators, MapsComparator mapsComparator, - DragDropSupport dragDropSupport, BuildProperties buildProperties, - NotificationService notificationService, WindowManager windowManager) { + MapStringConverter mapStringConverter, MapListComparator mapListComparator, + SortingComparators sortingComparators, DragDropSupport dragDropSupport, + BuildProperties buildProperties, NotificationService notificationService, + WindowManager windowManager) { this.replayService = replayService; this.hostServices = hostServices; this.dialogService = dialogService; @@ -179,8 +189,9 @@ public MainWindowController(ReplayService replayService, @Nullable HostServices this.resourceBundle = resourceBundle; this.clanStringConverter = clanStringConverter; this.clanListComparator = clanListComparator; + this.mapStringConverter = mapStringConverter; + this.mapListComparator = mapListComparator; this.sortingComparators = sortingComparators; - this.mapsComparator = mapsComparator; this.dragDropSupport = dragDropSupport; this.buildProperties = buildProperties; this.notificationService = notificationService; @@ -196,6 +207,7 @@ public void initialize() { initDragDrop(); initSortingChoiceBox(); initClanChoiceBox(); + initMapChoiceBox(); bindingSelectedElements(); progressBar.setVisible(false); versionChecker = new VersionChecker(); @@ -208,7 +220,8 @@ public void onShown() { } private void initMenu() { - showSettingsWindow.setOnAction(_ -> LOGGER.info("showSettingsWindow")); + // TODO adding settings + // showSettingsWindow.setOnAction(_ -> LOGGER.info("showSettingsWindow")); exitApplication.setOnAction(_ -> Platform.exit()); reportBug.setOnAction(_ -> openUrl(REPLAY_READER_BUGS_URL)); showAboutWindow.setOnAction(_ -> windowManager.openAbout()); @@ -222,8 +235,6 @@ private void initLists() { vehiclesList.setCellFactory( (_) -> new VehicleListCell(selectedPlayer, replayService::getNumberOfGames)); vehiclesList.getSelectionModel().selectedItemProperty().addListener(this::showVehicleStats); - mapsList.setCellFactory((_) -> new MapListCell(selectedPlayer, selectedVehicle, - replayService::getNumberOfMapsPlayed)); } private void initDragDrop() { @@ -255,10 +266,16 @@ private void initClanChoiceBox() { String.format(resourceBundle.getString("main.toolbar.filter-clan.tooltip"), MAX_CLANS))); } + private void initMapChoiceBox() { + mapChoiceBox.getSelectionModel().selectedItemProperty().addListener(this::onMapChanged); + mapChoiceBox.setTooltip(new Tooltip(resourceBundle.getString("main.toolbar.filter-map.tooltip"))); + } + private void bindingSelectedElements() { selectedPlayer.bind(playersList.getSelectionModel().selectedItemProperty()); selectedVehicle.bind(vehiclesList.getSelectionModel().selectedItemProperty()); selectedClan.bind(clanChoiceBox.getSelectionModel().selectedItemProperty()); + selectedMap.bind(mapChoiceBox.getSelectionModel().selectedItemProperty()); } private void onSelectPlayer(ObservableValue player, String oldValue, @@ -311,6 +328,9 @@ private void showVehicleStats(ObservableValue player, String o textSpots.setText( String.format("%.2f", replayService.getAvgSpots(selectedPlayer.get(), vehicle))); textBlocked.setText(String.valueOf(replayService.getAvgBlocked(selectedPlayer.get(), vehicle))); + var selfHeal = replayService.getAvgHealthRepair(selectedPlayer.get(), vehicle); + var alliesHeal = replayService.getAvgAlliedHealthRepair(selectedPlayer.get(), vehicle); + textHeal.setText(String.format("%d (%d)", selfHeal, alliesHeal)); var lifeTime = replayService.getAvgLifeTime(selectedPlayer.get(), vehicle); var min = lifeTime / 60; var sec = lifeTime % 60; @@ -321,6 +341,7 @@ private void showVehicleStats(ObservableValue player, String o String.valueOf(replayService.getAvgDamageReceived(selectedPlayer.get(), vehicle))); textDmgReceivedInvisible.setText(String.valueOf( replayService.getAvgDamageReceivedFromInvisibles(selectedPlayer.get(), vehicle))); + textStrikesDamage.setText(String.valueOf(replayService.getAvgEquipmentDamageDealt(selectedPlayer.get(), vehicle))); textTeamDmg.setText( String.valueOf(replayService.getAvgTdamageDealt(selectedPlayer.get(), vehicle))); textTeamKills.setText( @@ -340,11 +361,7 @@ private void showVehicleStats(ObservableValue player, String o String.format("%.2f", replayService.getAvgXPRank(selectedPlayer.get(), vehicle))); textDamageRank.setText( String.format("%.2f", replayService.getAvgDamageRank(selectedPlayer.get(), vehicle))); - var maps = replayService.getMaps(selectedPlayer.get(), vehicle); - mapsComparator.configure(selectedPlayer, selectedVehicle, replayService::getNumberOfMapsPlayed); - maps.sort(mapsComparator); - mapsList.setItems(maps); - mapsList.scrollTo(0); + textPrestigePoints.setText(String.valueOf(replayService.getComp7PrestigePoints(selectedPlayer.get(), vehicle))); } private void load(final List files) { @@ -375,9 +392,11 @@ private void onProgressChanged(ReplayProgressEvent event) { private void onLoadSucceeded(WorkerStateEvent event) { updatePlayers(); updateClans(); + updateMaps(); LOGGER.debug("onLoadSucceeded before SelectionModel changes"); playersList.getSelectionModel().selectFirst(); clanChoiceBox.getSelectionModel().selectFirst(); + mapChoiceBox.getSelectionModel().selectFirst(); sortingChoiceBox.getSelectionModel().selectFirst(); progressBar.setVisible(false); } @@ -388,8 +407,8 @@ private void updatePlayers() { var filteredPlayersData = new FilteredList<>(playersRawData); var selectedClanValue = selectedClan.getValue(); if (selectedClanValue != null) { - filteredPlayersData.setPredicate( - (player) -> selectedClanValue.equals(CLAN_ALL) || selectedClanValue.equals( + filteredPlayersData.setPredicate((player) -> + selectedClanValue.equals(CLAN_ALL) || selectedClanValue.equals( replayService.getPlayerInfo(player).getClanAbbrev())); } @@ -422,6 +441,23 @@ private void updateClans() { clanChoiceBox.setItems(sortedClans); } + private void updateMaps() { + var allPlayers = replayService.getPlayersIgnoringMapFilter(); + var allMapsSet = allPlayers.stream() + .flatMap(player -> replayService.getMaps(player, null).stream()) + .collect(Collectors.toSet()); + var mapsList = FXCollections.observableArrayList(allMapsSet); + mapsList.addFirst(MAP_ALL); + var sortedMaps = new SortedList<>(mapsList); + mapListComparator.configure(replayService::getNumberOfGamesOnMap); + sortedMaps.setComparator(mapListComparator); + + int totalGames = replayService.getTotalGames(); + mapStringConverter.configure(replayService::getNumberOfGamesOnMap, totalGames); + mapChoiceBox.setConverter(mapStringConverter); + mapChoiceBox.setItems(sortedMaps); + } + private void onClanChanged(ObservableValue player, String oldValue, String newValue) { if (oldValue != null) { @@ -431,6 +467,28 @@ private void onClanChanged(ObservableValue player, String oldV playersList.getSelectionModel().selectFirst(); } + private void onMapChanged(ObservableValue map, String oldValue, + String newValue) { + if (oldValue != null) { + String mapFilter = (newValue != null && !MAP_ALL.equals(newValue)) ? newValue : null; + replayService.setMapFilter(mapFilter); + + var selectedClanValue = clanChoiceBox.getSelectionModel().getSelectedItem(); + + updateClans(); + + if (selectedClanValue != null && clanChoiceBox.getItems().contains(selectedClanValue)) { + clanChoiceBox.getSelectionModel().select(selectedClanValue); + } else { + clanChoiceBox.getSelectionModel().selectFirst(); + } + + updatePlayers(); + } + + playersList.getSelectionModel().selectFirst(); + } + private MainModel getMainModel() { return mainModel; } diff --git a/src/main/java/com/synops/replayreader/vehicle/model/VehicleStats.java b/src/main/java/com/synops/replayreader/vehicle/model/VehicleStats.java index f2b0b1e..e055a44 100644 --- a/src/main/java/com/synops/replayreader/vehicle/model/VehicleStats.java +++ b/src/main/java/com/synops/replayreader/vehicle/model/VehicleStats.java @@ -23,6 +23,8 @@ public interface VehicleStats { int getDamageReceivedFromInvisibles(); + int getEquipmentDamageDealt(); + int getSpotted(); int getCapturePoints(); @@ -43,6 +45,10 @@ public interface VehicleStats { int getHealth(); + int getHealthRepair(); + + int getAlliedHealthRepair(); + String getTeam(); int getLifeTime(); @@ -64,4 +70,6 @@ public interface VehicleStats { int getDamageAssistedStun(); int getStunNum(); + + int getComp7PrestigePoints(); } diff --git a/src/main/java/com/synops/replayreader/vehicle/model/VehicleStatsImpl.java b/src/main/java/com/synops/replayreader/vehicle/model/VehicleStatsImpl.java index 9375a2a..0e179fb 100644 --- a/src/main/java/com/synops/replayreader/vehicle/model/VehicleStatsImpl.java +++ b/src/main/java/com/synops/replayreader/vehicle/model/VehicleStatsImpl.java @@ -16,6 +16,7 @@ public class VehicleStatsImpl implements VehicleStats { private int damageAssistedTrack; private int damageBlockedByArmor; private int damageReceivedFromInvisibles; + private int equipmentDamageDealt; private int spotted; private int capturePoints; private int shots; @@ -26,6 +27,8 @@ public class VehicleStatsImpl implements VehicleStats { private int mileage; private String killerID; private int health; + private int healthRepair; + private int alliedHealthRepair; private String team; private int lifeTime; private int directHits; @@ -37,6 +40,7 @@ public class VehicleStatsImpl implements VehicleStats { private int damageAssistedStun; private int stunNum; private int tkills; + private int comp7PrestigePoints; public int getDroppedCapturePoints() { return this.droppedCapturePoints; @@ -190,6 +194,14 @@ public void setDamageReceivedFromInvisibles(int damageReceivedFromInvisibles) { this.damageReceivedFromInvisibles = damageReceivedFromInvisibles; } + public int getEquipmentDamageDealt() { + return equipmentDamageDealt; + } + + public void setEquipmentDamageDealt(int equipmentDamageDealt) { + this.equipmentDamageDealt = equipmentDamageDealt; + } + public int getSpotted() { return this.spotted; } @@ -270,6 +282,22 @@ public void setHealth(int health) { this.health = health; } + public int getHealthRepair() { + return healthRepair; + } + + public void setHealthRepair(int healthRepair) { + this.healthRepair = healthRepair; + } + + public int getAlliedHealthRepair() { + return alliedHealthRepair; + } + + public void setAlliedHealthRepair(int alliedHealthRepair) { + this.alliedHealthRepair = alliedHealthRepair; + } + public String getTeam() { return this.team; } @@ -297,4 +325,12 @@ public int getDirectHits() { public void setDirectHits(int directHits) { this.directHits = directHits; } + + public int getComp7PrestigePoints() { + return comp7PrestigePoints; + } + + public void setComp7PrestigePoints(int comp7PrestigePoints) { + this.comp7PrestigePoints = comp7PrestigePoints; + } } diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties index 8c23e6b..cf33a69 100644 --- a/src/main/resources/i18n/messages.properties +++ b/src/main/resources/i18n/messages.properties @@ -19,8 +19,11 @@ main.toolbar.sort.team-damage=Team damage main.toolbar.sort.assist=Assist main.toolbar.sort.damage-blocked=Damage blocked main.toolbar.sort.damage-xp=Experience +main.toolbar.sort.prestige-points=Prestige points main.toolbar.filter-clan=Filter by clan main.toolbar.filter-clan.tooltip=Show the first %d clans sorted by player occurrence +main.toolbar.filter-map=Filter by map +main.toolbar.filter-map.tooltip=Filter players by map ## Vehicle stats main.stats.dmg=Damage (>300m) main.stats.kills=Kills @@ -38,7 +41,9 @@ main.stats.credits-base=Credits (base) main.stats.team-dmg=Team damage main.stats.mileage=Mileage main.stats.shots=Shots -main.stats.maps=Maps +main.stats.strikes-damage=Strikes damage +main.stats.prestige-points=Prestige points +main.stats.heal=Heal (allies) main.stats.winrate=Winrate main.stats.team-kills=Team Kills main.stats.cap=Base capture @@ -56,7 +61,7 @@ update.download=Download # About about.title=About {0} about.powered-by=Powered by -about.copyright=Copyright © 2025 +about.copyright=Copyright � 2025 about.github-repo=GitHub repository about.open-source=open-source software # Software used diff --git a/src/main/resources/i18n/messages_fr.properties b/src/main/resources/i18n/messages_fr.properties index d28a1d5..2e31f3f 100644 --- a/src/main/resources/i18n/messages_fr.properties +++ b/src/main/resources/i18n/messages_fr.properties @@ -2,72 +2,77 @@ author=Synops # Main ## Menu main.menu.file=Fichier -main.menu.file.settings=Paramètres +main.menu.file.settings=Paramètres main.menu.file.exit=Quitter main.menu.help=Aide main.menu.help.about=A propos main.menu.help.report-bug=Signaler un bug -main.menu.help.version-check=Vérifiez les mises à jour... +main.menu.help.version-check=Vérifiez les mises à jour... ## Toolbar main.toolbar.sort=Trier par main.toolbar.sort.tooltip=Afficher les %d premiers joueurs main.toolbar.sort.games=Parties -main.toolbar.sort.damage=Dégâts +main.toolbar.sort.damage=Dégâts main.toolbar.sort.kills=Destruction -main.toolbar.sort.pen-rate=Taux de pénétration -main.toolbar.sort.team-damage=Dégâts alliés +main.toolbar.sort.pen-rate=Taux de pénétration +main.toolbar.sort.team-damage=Dégâts alliés main.toolbar.sort.assist=Assistance -main.toolbar.sort.damage-blocked=Dégâts bloqués -main.toolbar.sort.damage-xp=Expérience +main.toolbar.sort.damage-blocked=Dégâts bloqués +main.toolbar.sort.damage-xp=Expérience +main.toolbar.sort.prestige-points=Points de prestige main.toolbar.filter-clan=Filtrer par clan -main.toolbar.filter-clan.tooltip=Afficher les %d premiers clans triés par occurrence de joueur +main.toolbar.filter-clan.tooltip=Afficher les %d premiers clans triés par occurrence de joueur +main.toolbar.filter-map=Filtrer par carte +main.toolbar.filter-map.tooltip=Filtrer les joueurs par carte ## Vehicle stats -main.stats.dmg=Dégâts (>300m) +main.stats.dmg=Dégâts (>300m) main.stats.kills=Destructions main.stats.assist=Assist (spot/tracks) -main.stats.pen-rate=Taux de pénétration +main.stats.pen-rate=Taux de pénétration main.stats.hit-rate=Taux de coup au but -main.stats.spots=Ennemis repérés -main.stats.life-duration=Durée de vie -main.stats.dmg-blocked=Dégâts bloqués -main.stats.hits-received=Tirs reçus -main.stats.dmg-received=Dégâts reçus -main.stats.dmg-received-invisible=Dégâts reçus invisibles +main.stats.spots=Ennemis repérés +main.stats.life-duration=Durée de vie +main.stats.dmg-blocked=Dégâts bloqués +main.stats.hits-received=Tirs reçus +main.stats.dmg-received=Dégâts reçus +main.stats.dmg-received-invisible=Dégâts reçus invisibles main.stats.xp-base=XP (base) -main.stats.credits-base=Crédits (base) -main.stats.team-dmg=Dégâts alliés -main.stats.mileage=Kilométrage +main.stats.credits-base=Crédits (base) +main.stats.team-dmg=Dégâts alliés +main.stats.mileage=Kilométrage main.stats.shots=Tirs -main.stats.maps=Cartes +main.stats.strikes-damage=Dégâts par frappes +main.stats.prestige-points=Points de prestige +main.stats.heal=Soin (alliés) main.stats.winrate=Taux de victoire -main.stats.team-kills=Destructions alliées +main.stats.team-kills=Destructions alliées main.stats.cap=Capture de base -main.stats.cap-reset=Défense de base -main.stats.dmg-rank=Rang dégâts +main.stats.cap-reset=Défense de base +main.stats.dmg-rank=Rang dégâts main.stats.xp-rank=Rang XP ## Footer -main.footer.drag=Glissez-déposez les fichiers de replay sur cette fenêtre (max. 1500) +main.footer.drag=Glissez-déposez les fichiers de replay sur cette fenêtre (max. 1500) main.footer.corrupted=Corrompu(s) # Update -update.latest-already=Vous disposez déjà de la dernière version. -update.new-version=Une nouvelle version est disponible ({0}). Télécharger ? +update.latest-already=Vous disposez déjà de la dernière version. +update.new-version=Une nouvelle version est disponible ({0}). Télécharger ? update.new-version-latest=Une nouvelle version est disponible ({0}). -update.download=Télécharger +update.download=Télécharger # About about.title=A propos de {0} -about.powered-by=Propulsé par -about.copyright=Copyright © 2025 -about.github-repo=Dépôt GitHub +about.powered-by=Propulsé par +about.copyright=Copyright © 2025 +about.github-repo=Dépôt GitHub about.open-source=logiciels open source -software-used.title=Logiciels tiers utilisés par {0} +software-used.title=Logiciels tiers utilisés par {0} # Maps -01_karelia=Carélie +01_karelia=Carélie 02_malinovka=Malinovka 03_campania_big=Province 04_himmelsdorf=Himmelsdorf 05_prohorovka=Prokhorovka 06_ensk=Ensk -06_ensk_big=Région d'Ensk +06_ensk_big=Région d'Ensk 07_lakeville=Lakeville 08_ruinberg=Ruinberg 08_ruinberg_sm24=Lauerberg @@ -80,24 +85,24 @@ software-used.title=Logiciels tiers utilis 18_cliff=Falaise 19_monastery=Abbaye 23_westfeld=Westfield -28_desert=Rivière de sable +28_desert=Rivière de sable 29_el_hallouf=El Halluf -31_airfield=Aérodrome +31_airfield=Aérodrome 33_fjord=Fjords 34_redshire=Redshire 35_steppes=Steppes -36_fishing_bay=Baie du pêcheur +36_fishing_bay=Baie du pêcheur 37_caucasus=Col de montagne 38_mannerheim_line=Ligne Mannerheim 44_north_america=Live Oaks 45_north_america=Autoroute 47_canada_a=Plage sereine 59_asia_great_wall=Empire's Border -60_asia_miao=Rivière de perles +60_asia_miao=Rivière de perles 63_tundra=Tundra 83_kharkiv=Kharkov 90_minsk=Minsk -95_lost_city_ctf=Ville fantôme +95_lost_city_ctf=Ville fantôme 99_poland=Studzianki 101_dday=Overlord 101_dday_sm24=Omaha Beach @@ -107,7 +112,7 @@ software-used.title=Logiciels tiers utilis 112_eiffel_tower_ctf=Paris 114_czech=Pilsen 115_sweden=Glacier -121_lost_paradise_v=Baie aux Huîtres +121_lost_paradise_v=Baie aux Huîtres 127_japort=Refuge 128_last_frontier_v=Avant-poste 140_fall_tanks=Course de chars diff --git a/src/main/resources/tanks.properties b/src/main/resources/tanks.properties index 5dd7a46..a47658e 100644 --- a/src/main/resources/tanks.properties +++ b/src/main/resources/tanks.properties @@ -1,11 +1,11 @@ usa\:A01_T1_Cunningham=T1 Cunningham -usa\:A02_M2_lt=M2 Light Tank +usa\:A02_M2_lt=M2 Light usa\:A03_M3_Stuart=M3 Stuart usa\:A04_M3_Grant=M3 Lee usa\:A05_M4_Sherman=M4A1 Sherman usa\:A06_M4A3E8_Sherman=M4A3E8 Sherman usa\:A07_T20=T20 -usa\:A09_T1_hvy=T1 Heavy Tank +usa\:A09_T1_hvy=T1 Heavy usa\:A100_T49=T49 usa\:A101_M56=M56 Scorpion usa\:A102_T28_concept=T28 Concept @@ -52,6 +52,8 @@ usa\:A141_M_IV_Y=M-IV-Y usa\:A142_Pawlack_Tank=Pawlack Tank usa\:A143_M_V_Y=M-V-Y usa\:A144_M_VI_Y=M-VI-Y +usa\:A144_M_VI_Y_CFE_R=M-VI-Y (120) +usa\:A144_M_VI_Y_CFE_RC=OCP Peacekeeper usa\:A145_TS_54=TS-54 usa\:A146_TL_7_120=TL-7 usa\:A147_M_II_Y=M-II-Y @@ -71,15 +73,28 @@ usa\:A158_T832=T-832 usa\:A159_Chrysler_MTC_2=Chrysler MTC 2TC usa\:A160_M24_594=M24 Chaffee No. 594 usa\:A161_ARMT=ARMT +usa\:A166_H_3=H3 +usa\:A167_TS_6=TS-6 usa\:A168_XM_57=XM57 usa\:A169_PattonIII_120=Patton the Tank usa\:A16_M7_Priest=M7 Priest +usa\:A171_IMT=IMT usa\:A172_M4A3E8_Sherman_BPXIV=M4A3(76)W Sherman usa\:A174_T57_58_Rush_Ep1=Stinger +usa\:A175_LTC_II=LTC II usa\:A176_M103_110=M103M usa\:A176_M103_110_CFE_R=Rambo +usa\:A178_SPHT=SPHT +usa\:A179_Black_Rock=Black Rock usa\:A17_M37=M37 -usa\:A18_M41=M41 HMC +usa\:A182_T803=T803 +usa\:A183_XM69_Hacker=XM69 Hacker +usa\:A187_Ares_75=Ares 75 +usa\:A189_Ares_90=Ares 90 +usa\:A18_M41=M41 +usa\:A190_Ares_85=Ares 85 +usa\:A191_Ares_90_C=Ares 90 C +usa\:A192_M4A4_Firefly_CFE_A=Sherman Firefly Saunders usa\:A19_T2_lt=T2 Light Tank usa\:A21_T14=T14 usa\:A22_M5_Stuart=M5 Stuart @@ -113,7 +128,7 @@ usa\:A63_M46_Patton_FL=M46 Patton FL usa\:A63_M46_Patton_KR=M46 Patton KR usa\:A64_T25_AT=T25 AT usa\:A66_M103=M103 -usa\:A67_T57_58=T57 Heavy Tank +usa\:A67_T57_58=T57 Heavy usa\:A68_T28_Prototype=T28 Prototype usa\:A69_T110E5=T110E5 usa\:A69_T110E5_cl=T110E5 CL @@ -199,12 +214,18 @@ china\:Ch50_BZ_166=BZ-166 china\:Ch51_BZ_58=BZ-58 china\:Ch52_WZ_122_6_F3=116-F3 china\:Ch54_BZ_72_1=BZ-72-1 +china\:Ch56_BZ_74_1=BZ-74-1 +china\:Ch57_BZT_70=BZT-70 china\:Ch58_111_Vz51=WZ-111 model 6 china\:Ch59_BZ58_2=BZ-58-2 china\:Ch60_Vickers_TypeB=Vickers 6 ton china\:Ch61_DZT_159=DZT-159 +china\:Ch61_DZT_159_CFE_A=DZT-159 Dragon's Soul china\:Ch62_BZ_75_M=Divine Valor +china\:Ch63_Yong_Bing=Yong Bing china\:Ch65_Type59_IC4_3DSt=Type 59 First Warrior +china\:Ch67_BZ_79=BZ-79 +china\:Ch70_PTZ_78=PTZ-78 czech\:Cz01_Skoda_T40=\u0160koda T 40 czech\:Cz02_TVP_T50=\u0160koda T 50 czech\:Cz03_LT_vz35=LT vz. 35 @@ -227,14 +248,19 @@ czech\:Cz18_TNH_105_1000=TNH 105/1000 czech\:Cz19_Vz_44_1=Vz. 44-1 czech\:Cz20_ShPTK_TVP_100_mm=ShPTK-TVP 100 czech\:Cz20_ShPTK_TVP_100_mm_CO=\u0160otek +czech\:Cz21_Vz_60S_Dravec=Vz. 60S Dravec +czech\:Cz22_Skoda_T_15A=\u0160koda T 15A czech\:Cz23_Skoda_T_17=\u0160koda T 17 czech\:Cz24_Vz_64_Blesk=Vz. 64 Blesk czech\:Cz28_LPT_67_Selma=LPT-67 \u0160elma czech\:Cz29_Pzw_39=Panzerwagen 39 +czech\:Cz30_TBT=TBT czech\:Cz32_Vz_58_Koncept=Vz. 58 Medv\u011bd czech\:Cz33_Vz_68_Squall=Vz. 68 Squall czech\:Cz34_Vz_71_Tesak=Vz. 71 Tes\u00e1k czech\:Cz35_T56_G=TT-130M +czech\:Cz37_SDT_58_Vlkodav=SDT-58 Vlkodav +czech\:Cz38_SZDV_vz50=SZDV Vz. 50 czech\:Cz40_DBV_152=DBV-152 france\:F01_RenaultFT=Renault FT france\:F02_D1=D1 @@ -263,14 +289,22 @@ france\:F117_Alt_Proto_AMX_30=AltProto AMX 30 france\:F118_Char_Mle_75=Char Mle. 75 france\:F119_Char_Murat=Char Murat france\:F11_Renault_G1R=Renault G1 +france\:F120_Projet_Louis=Projet Louis france\:F122_VCS_6x6_TS90=VCS 6x6 TS 90 france\:F123_ERAC_105_Proto=ERAC 105 Proto france\:F124_AMX_13FL11=AMX 13 (FL 11) +france\:F127_AMX_ELC_901=AMX ELC 901 france\:F128_SFAC_105=SFAC 105 france\:F129_ARL_44_BPXIV=Char de transition france\:F12_Hotchkiss_H35=Hotchkiss H35 +france\:F130_Sentinelle=Sentinelle +france\:F131_Brennos=Brennos france\:F132_Vercingetorix=Vercing\u00e9torix +france\:F135_AS_XX_40_t=AS-XX 40 t +france\:F136_AMX_67_Imbattable=AMX 67 Imbattable +france\:F138_Renault_R35_FCM_36=Renault R35/FCM 36 france\:F13_AMX38=AMX 38 +france\:F140_Fantome=Fant\u00f4me france\:F14_AMX40=AMX 40 france\:F15_AMX_12t=AMX 12 t france\:F16_AMX_13_75=AMX 13 75 @@ -407,9 +441,20 @@ germany\:G171_E77=E 77 germany\:G172_PzVIB_Tiger_II_DIT=Tiger II Kuromorimine germany\:G173_BT42_DIT=BT-42 Jatkosota HS germany\:G174_Kpz3_GST_Turm=Kpz. 3 GST Turm +germany\:G175_Rheinmetall_Begleitwagen=Rheinmetall Begleitwagen +germany\:G176_Jagdpanzer_E90=Jagdpanzer E 90 +germany\:G177_E65_Zwilling=E 65 Zwilling +germany\:G178_KanJpz_2=Kanonenjagdpanzer 2 germany\:G179_Straussler_V4=Straussler V\u20134/40 germany\:G17_JagdPzIV=Jagdpanzer IV +germany\:G184_Windhund=Windhund +germany\:G185_Leopard_120_Verbessert=Leopard 120 Verbessert +germany\:G186_Schwertwal=Schwertwal +germany\:G187_Taschenratte=Taschenratte +germany\:G188_LeKpz_Borkenkafer=leKpz Borkenk\u00e4fer +germany\:G189_Hirschkafer=Hirschk\u00e4fer germany\:G18_JagdPanther=Jagdpanther +germany\:G191_StuG_IIIF_CFE_A=StuG III Ausf. F Kabasan germany\:G19_Wespe=Wespe germany\:G20_Marder_II=Marder II germany\:G21_PanzerJager_I=Panzerj\u00e4ger I @@ -495,13 +540,14 @@ uk\:GB09_Churchill_VII=Churchill VII uk\:GB100_Manticore=Manticore uk\:GB101_FV1066_Senlac=FV1066 Senlac uk\:GB102_LHMTV=LHMTV -uk\:GB103_GSOR3301_AVR_FS=GSOR3301 AVR FS +uk\:GB103_GSOR3301_AVR_FS=GSOR 3301 AVR FS uk\:GB104_GSR_3301_Setter=GSR 3301 Setter uk\:GB105_Black_Prince_2019=A43 BP prototype uk\:GB106_Cobra=Cobra uk\:GB107_Cavalier=Cavalier uk\:GB108_A46=A46 uk\:GB109_GSOR_1008=GSOR 1008 +uk\:GB109_GSOR_1008_CFE_J=Jade Coil uk\:GB10_Black_Prince=Black Prince uk\:GB110_FV4201_Chieftain_Prototype=FV4201 Chieftain Proto uk\:GB111_Charlemagne=Charlemagne @@ -524,7 +570,9 @@ uk\:GB12_Conqueror=Conqueror uk\:GB12_Conqueror_FL=Conqueror FL uk\:GB131_Crusher=Crusher uk\:GB133_Charioteer_MkVII=Charioteer Nomad +uk\:GB134_Gryphon=Gryphon uk\:GB136_Churchill_BPXIV=Churchill Crocodile +uk\:GB137_Cromwell_Applique=Cromwell Applique uk\:GB139_FV226_Contradictious=FV226 Contradictious uk\:GB13_FV215b=FV215b uk\:GB140_FV224_Chopper=FV224 Chopper @@ -533,10 +581,13 @@ uk\:GB142_FV230_Canopener=FV230 Canopener uk\:GB143_FV229_Contender=FV229 Contender uk\:GB145_Crusher_ASE_4=Nergal uk\:GB146_Gabler_s_Destroyer=Gabler\u2019s Destroyer +uk\:GB147_FV4025_Contriver=FV4025 Contriver uk\:GB148_FV227_Conceiver=FV227 Conceiver uk\:GB149_Centurion_MkI_A=Centurion St. Gloriana uk\:GB14_M2=M2 uk\:GB150_Churchill_VII_A=Churchill St. Gloriana +uk\:GB152_AT_FV230_Breaker=AT-FV230 Breaker +uk\:GB156_Black_Prince_II=Black Prince II uk\:GB15_Stuart_I=Stuart I-IV uk\:GB17_Grant_I=Grant uk\:GB19_Sherman_Firefly=Sherman Firefly @@ -590,6 +641,7 @@ uk\:GB83_FV4005=FV4005 Stage II uk\:GB84_Chieftain_Mk6=Chieftain Mk. 6 uk\:GB85_Cromwell_Berlin=Cromwell B uk\:GB86_Centurion_Action_X=Centurion Action X +uk\:GB86_Centurion_Action_X_CFE_A=Triumphant uk\:GB87_Chieftain_T95_turret=Chieftain/T95 uk\:GB91_Super_Conqueror=Super Conqueror uk\:GB92_FV217=FV217 Badger @@ -632,6 +684,7 @@ italy\:It33_Prototipo_6=Prototipo 6 italy\:It34_Toro=Toro italy\:It35_Felice=Felice italy\:It36_Progetto_C45_mod_71_M=Stone Sentinel +italy\:It39_Coccodrillo=Coccodrillo japan\:J01_NC27=Renault Otsu japan\:J02_Te_Ke=Type 97 Te-Ke japan\:J03_Ha_Go=Type 95 Ha-Go @@ -669,10 +722,16 @@ japan\:J38_Type_95_Ji_Ro=Type 95 Ji-Ro japan\:J39_Type_57=Type 57 japan\:J40_Type_71=Type 71 japan\:J41_Type_68=Type 68 +japan\:J42_Chi_Se=Chi-Se +japan\:J42_Chi_Se_CFE_A=Stitch japan\:J43_Type_4_Ju-To=Type 4 Ju-To japan\:J44_Type_3_Ju_Nu=Type 3 Ju-Nu japan\:J45_Mitsu_108=Mitsu 108 +japan\:J48_Saryuda=Saryuda +japan\:J49_Kame=Kame japan\:J50_Type_1_Ho_Ni_II=Type 1 Ho-Ni II +japan\:J51_Ashigaru=Ashigaru +japan\:J52_STK_2=STK-2 poland\:Pl01_TKS_20mm=TKS z n.k.m. 20 mm poland\:Pl03_PzV_Poland=Pudel poland\:Pl05_50TP_Tyszkiewicza=50TP Tyszkiewicza @@ -687,6 +746,7 @@ poland\:Pl12_25TP_KSUST_II=25TP KSUST II poland\:Pl13_53TP_Markowskiego=53TP Markowskiego poland\:Pl14_4TP=4TP poland\:Pl15_60TP_Lewandowskiego=60TP Lewandowskiego +poland\:Pl15_60TP_Lewandowskiego_CFE_A=Ashbringer poland\:Pl16_T34_85_Rudy=T-34-85 Rudy poland\:Pl17_DS_PZlnz=DS PZIn\u017c poland\:Pl18_BUGI=B.U.G.I. @@ -707,6 +767,7 @@ poland\:Pl31_SDP_Wz_57D=SDP 57 Gowika poland\:Pl32_SDP_Wz_44=SDP 44 Burza poland\:Pl33_SDP_Wz_40=SDP 40 Zadymka poland\:Pl34_Cs53_56_Woitek=CS-53/56 Wojtek +poland\:Pl37_CS_67_Szakal=CS-67 Szakal ussr\:R01_IS=IS ussr\:R02_SU-85=SU-85 ussr\:R03_BT-7=BT-7 @@ -783,6 +844,7 @@ ussr\:R16_SU-18=SU-18 ussr\:R170_IS_2_II=IS-2-II ussr\:R171_IS_3_II=IS-3-II ussr\:R172_Object_752=Object 752 +ussr\:R172_Object_752_CFE_T=Peerless ussr\:R173_K_91_2=K-91 Version II ussr\:R174_BT-5=BT-5 ussr\:R175_IS_2_screen=IS-2 shielded @@ -817,9 +879,13 @@ ussr\:R205_Tank_Rozanova_Obsidian=Obsidian ussr\:R20_T-44=T-44 ussr\:R20_T-44_FL=T-44 FL ussr\:R217_Object_Kust=Object Kust +ussr\:R218_T_115=T-115 ussr\:R219_Object_265T=Object 265T ussr\:R225_SU_100i=SU-100I +ussr\:R228_KR_1=KR-1 ussr\:R22_T-46=T-46 +ussr\:R230_Object_432U=Object 432U +ussr\:R231_Buryan=Buryan ussr\:R23_T-43=T-43 ussr\:R24_SU-76=SU-76M ussr\:R25_GAZ-74b=SU-85B @@ -915,3 +981,6 @@ sweden\:S31_Strv_K=Strv K sweden\:S32_Bofors_Tornvagn=Bofors Tornvagn sweden\:S33_Latt_Stridsfordon_120=L\u00e4tt Stridsfordon 120 sweden\:S34_Lago_M38=Lago M38 +sweden\:S35_Stridsyxa=Stridsyxa +sweden\:S36_Strv_107_12=Strv 107-12 +sweden\:S39_Strv_m31=Strv m/31 diff --git a/src/main/resources/views/main.fxml b/src/main/resources/views/main.fxml index 9aac876..9212a08 100644 --- a/src/main/resources/views/main.fxml +++ b/src/main/resources/views/main.fxml @@ -27,11 +27,12 @@ - - - - - + + + + + + @@ -61,6 +62,12 @@ + + @@ -140,13 +147,12 @@