From f69984dd2cffc2332f0ecdcfbce65b9b6e6d076f Mon Sep 17 00:00:00 2001 From: synopss Date: Sat, 14 Mar 2026 15:43:17 +0100 Subject: [PATCH 1/9] feat: adding a maps' filter --- .../replayreader/common/util/Constants.java | 1 + .../replay/model/ReplayCollection.java | 6 +- .../replay/model/ReplayCollectionImpl.java | 48 +++++++--- .../replay/model/ReplayFilter.java | 11 +++ .../replay/service/ReplayService.java | 8 +- .../replay/service/ReplayServiceImpl.java | 20 +++-- .../ui/controller/MainWindowController.java | 90 +++++++++++++++---- src/main/resources/i18n/messages.properties | 4 +- .../resources/i18n/messages_fr.properties | 78 ++++++++-------- src/main/resources/views/main.fxml | 13 ++- 10 files changed, 189 insertions(+), 90 deletions(-) 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/replay/model/ReplayCollection.java b/src/main/java/com/synops/replayreader/replay/model/ReplayCollection.java index 97b05f1..76a6e44 100644 --- a/src/main/java/com/synops/replayreader/replay/model/ReplayCollection.java +++ b/src/main/java/com/synops/replayreader/replay/model/ReplayCollection.java @@ -15,7 +15,7 @@ public interface ReplayCollection { Player getPlayerInfo(String player); - void updateReplayFilter(ReplayFilter replayFilter); + void setMapFilter(String map); int getNumberOfClanPlayers(String clan); @@ -25,7 +25,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); 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..885d8e4 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,25 @@ 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 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 +96,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 +109,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 +133,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( @@ -253,8 +273,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() { 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/ReplayService.java b/src/main/java/com/synops/replayreader/replay/service/ReplayService.java index 7d3a2b1..54c403f 100644 --- a/src/main/java/com/synops/replayreader/replay/service/ReplayService.java +++ b/src/main/java/com/synops/replayreader/replay/service/ReplayService.java @@ -9,10 +9,10 @@ public interface ReplayService { - void load(List files); - void load(List files, Consumer progressListener); + void setMapFilter(String map); + ObservableList getPlayers(); Player getPlayerInfo(String player); @@ -25,7 +25,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); 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..7bd4161 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 @@ -68,8 +69,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 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..df7c56d 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; @@ -158,8 +163,6 @@ public class MainWindowController implements WindowController { @FXML private TextField textDamageRank; @FXML - private ListView mapsList; - @FXML private ProgressBar progressBar; @FXML private Label progressLabel; @@ -169,9 +172,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 +183,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 +201,7 @@ public void initialize() { initDragDrop(); initSortingChoiceBox(); initClanChoiceBox(); + initMapChoiceBox(); bindingSelectedElements(); progressBar.setVisible(false); versionChecker = new VersionChecker(); @@ -222,8 +228,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 +259,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, @@ -340,11 +350,6 @@ 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); } private void load(final List files) { @@ -373,11 +378,14 @@ private void onProgressChanged(ReplayProgressEvent event) { } private void onLoadSucceeded(WorkerStateEvent event) { + replayService.setMapFilter(null); 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 +396,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 +430,30 @@ private void updateClans() { clanChoiceBox.setItems(sortedClans); } + private void updateMaps() { + String currentMapFilter = selectedMap.getValue(); + replayService.setMapFilter(null); + + var allPlayers = replayService.getPlayers(); + 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); + + if (currentMapFilter != null && !MAP_ALL.equals(currentMapFilter)) { + replayService.setMapFilter(currentMapFilter); + } + } + private void onClanChanged(ObservableValue player, String oldValue, String newValue) { if (oldValue != null) { @@ -431,6 +463,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/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties index 8c23e6b..c9764ef 100644 --- a/src/main/resources/i18n/messages.properties +++ b/src/main/resources/i18n/messages.properties @@ -21,6 +21,8 @@ main.toolbar.sort.damage-blocked=Damage blocked main.toolbar.sort.damage-xp=Experience 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 @@ -56,7 +58,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..d61d061 100644 --- a/src/main/resources/i18n/messages_fr.properties +++ b/src/main/resources/i18n/messages_fr.properties @@ -2,72 +2,74 @@ 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.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.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 +82,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 +109,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/views/main.fxml b/src/main/resources/views/main.fxml index 9aac876..d456153 100644 --- a/src/main/resources/views/main.fxml +++ b/src/main/resources/views/main.fxml @@ -61,6 +61,12 @@ + + @@ -140,13 +146,6 @@