From 9d035bea4060694ee58c88fc376f5fa144ecd36f Mon Sep 17 00:00:00 2001 From: Alix Lourme Date: Sun, 9 Jan 2022 18:58:03 +0100 Subject: [PATCH] Fix #139 : Use "auctions" (turn 1) for Mercatos proposal --- README.md | 2 +- pom.xml | 18 ++--- src/main/java/org/blondin/mpg/Main.java | 67 ++++++++++++------- .../org/blondin/mpg/root/model/Player.java | 9 +++ .../org/blondin/mpg/stats/model/Auction.java | 34 ++++++++++ .../org/blondin/mpg/stats/model/Player.java | 6 ++ src/test/java/org/blondin/mpg/MainTest.java | 4 +- .../blondin/mpg/stats/MpgStatsClientTest.java | 15 +++++ src/test/resources/__files/README.md | 17 +++++ 9 files changed, 135 insertions(+), 37 deletions(-) create mode 100644 src/main/java/org/blondin/mpg/stats/model/Auction.java diff --git a/README.md b/README.md index ef078b1..18d857a 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Automate and optimize your [MPG](http://mpg.football/) weekly league actions, us * Displaying your teams, line by line, ordered by players efficiency (with injured players) * Updating your team * Proposing some players to buy, better than the one you have (if option `transactions.proposal` is enabled and *MPG* expert mode is bought) -* When league not started (aka: *mercato*), the best players to buy for your incoming team +* When league not started (aka: *mercato*), the best players to buy with good turn 1 auction (since v1.9) for your incoming team **NB:** Your tactical organization and selected bonus are not updated and let as configured (but selected if some will be lost or no captain). diff --git a/pom.xml b/pom.xml index da685ff..0b2eeef 100644 --- a/pom.xml +++ b/pom.xml @@ -1,17 +1,19 @@ - + + 4.0.0 org.blondin mpg-coach-bot jar - 1.8.4-SNAPSHOT + 1.9-SNAPSHOT MPG Coach Bot package UTF-8 org.blondin.mpg.Main 1.8 - 2.34 - 2.12.4 + 2.35 + 2.13.1 1.7.32 2.17.1 @@ -32,7 +34,7 @@ maven-jar-plugin - 3.2.0 + 3.2.1 maven-shade-plugin @@ -48,7 +50,7 @@ maven-release-plugin - 3.0.0-M4 + 3.0.0-M5 @@ -171,7 +173,7 @@ org.jsoup jsoup - 1.14.2 + 1.14.3 org.apache.commons @@ -202,7 +204,7 @@ org.mockito mockito-core - 3.11.2 + 4.2.0 test diff --git a/src/main/java/org/blondin/mpg/Main.java b/src/main/java/org/blondin/mpg/Main.java index 7ca8bb8..1589d79 100644 --- a/src/main/java/org/blondin/mpg/Main.java +++ b/src/main/java/org/blondin/mpg/Main.java @@ -124,7 +124,8 @@ static void processMercatoLeague(League league, ApiClients apiClients, Config co LOG.info("\nProposal for your mercato:\n"); List players = apiClients.getMpg().getAvailablePlayers(league.getDivisionId()).getList(); completePlayersClub(players, apiClients.getMpg().getClubs()); - calculateEfficiency(players, apiClients.getStats(), ChampionshipTypeWrapper.toStats(league.getChampionship()), config, false, true); + completeAuctionAndcalculateEfficiency(players, apiClients.getStats(), ChampionshipTypeWrapper.toStats(league.getChampionship()), config, + false, true); processMercato(players, apiClients.getOutPlayers(), ChampionshipTypeWrapper.toOut(league.getChampionship())); } @@ -132,7 +133,8 @@ static void processMercatoChampionship(League league, ApiClients apiClients, Con LOG.info("\nProposal for your coming soon mercato:\n"); List players = apiClients.getMpg().getPoolPlayers(league.getChampionship()).getPlayers(); completePlayersClub(players, apiClients.getMpg().getClubs()); - calculateEfficiency(players, apiClients.getStats(), ChampionshipTypeWrapper.toStats(league.getChampionship()), config, false, true); + completeAuctionAndcalculateEfficiency(players, apiClients.getStats(), ChampionshipTypeWrapper.toStats(league.getChampionship()), config, + false, true); processMercato(players, apiClients.getOutPlayers(), ChampionshipTypeWrapper.toOut(league.getChampionship())); } @@ -144,7 +146,7 @@ static void processMercato(List players, InjuredSuspendedWrapperClient o List midfielders = players.stream().filter(p -> p.getPosition().equals(Position.M)).collect(Collectors.toList()).subList(0, 10); List attackers = players.stream().filter(p -> p.getPosition().equals(Position.A)).collect(Collectors.toList()).subList(0, 10); - AsciiTable at = getTable(TABLE_POSITION, TABLE_PLAYER_NAME, TABLE_EFFICIENCY, TABLE_QUOTE, "Out info"); + AsciiTable at = getTable(TABLE_POSITION, TABLE_PLAYER_NAME, TABLE_EFFICIENCY, TABLE_QUOTE, "Auct.", "Out info"); for (List line : Arrays.asList(goals, defenders, midfielders, attackers)) { for (Player player : line) { org.blondin.mpg.out.model.Player outPlayer = outPlayersClient.getPlayer(championship, player.getName(), @@ -154,10 +156,11 @@ static void processMercato(List players, InjuredSuspendedWrapperClient o outInfos = String.format("%s - %s - %s", outPlayer.getOutType(), outPlayer.getDescription(), outPlayer.getLength()); } AT_Row row = at.addRow(player.getPosition(), player.getName(), FORMAT_DECIMAL_DOUBLE.format(player.getEfficiency()), - player.getQuotation(), outInfos); + player.getQuotation(), player.getAuction(), outInfos); setTableFormatRowPaddingSpace(row); row.getCells().get(2).getContext().setTextAlignment(TextAlignment.RIGHT); row.getCells().get(3).getContext().setTextAlignment(TextAlignment.RIGHT); + row.getCells().get(4).getContext().setTextAlignment(TextAlignment.RIGHT); } at.addRule(); } @@ -179,8 +182,9 @@ static void processGames(League league, ApiClients apiClients, Config config) { completePlayersTeam(team.getSquad(), pool); List players = team.getSquad().values().stream().collect(Collectors.toList()); - // Calculate efficiency (notes should be in injured players display), and save for transactions proposal - calculateEfficiency(players, apiClients.getStats(), ChampionshipTypeWrapper.toStats(league.getChampionship()), config, false, true); + // Complete auction and calculate efficiency (notes should be in injured players display), and save for transactions proposal + completeAuctionAndcalculateEfficiency(players, apiClients.getStats(), ChampionshipTypeWrapper.toStats(league.getChampionship()), config, + false, true); List playersTeam = players.stream().collect(Collectors.toList()); // Remove out players (and write them) @@ -212,8 +216,8 @@ static void processGames(League league, ApiClients apiClients, Config config) { List playersAvailable = apiClients.getMpg().getAvailablePlayers(league.getDivisionId()).getList(); completePlayersClub(playersAvailable, apiClients.getMpg().getClubs()); removeOutPlayers(playersAvailable, apiClients.getOutPlayers(), ChampionshipTypeWrapper.toOut(league.getChampionship()), false); - calculateEfficiency(playersAvailable, apiClients.getStats(), ChampionshipTypeWrapper.toStats(league.getChampionship()), config, - false, false); + completeAuctionAndcalculateEfficiency(playersAvailable, apiClients.getStats(), + ChampionshipTypeWrapper.toStats(league.getChampionship()), config, false, false); Integer currentPlayersBuy = team.getBids().stream().map(Player::getPricePaid).collect(Collectors.summingInt(Integer::intValue)); writeTransactionsProposal(playersTeam, playersAvailable, team.getBudget() - currentPlayersBuy, apiClients.getOutPlayers(), @@ -424,8 +428,35 @@ private static void writeTeamOptimized(List players, boolean isDebug) { LOG.info(render); } - private static List calculateEfficiency(List players, MpgStatsClient stats, ChampionshipStatsType championship, Config config, - boolean failIfPlayerNotFound, boolean logWarnIfPlayerNotFound) { + private static List completeAuctionAndcalculateEfficiency(List players, MpgStatsClient stats, ChampionshipStatsType championship, + Config config, boolean failIfPlayerNotFound, boolean logWarnIfPlayerNotFound) { + + // Pre-process efficiencies + calculateEfficiencies(stats, championship, config); + + // Fill MPG model + for (Player player : players) { + try { + org.blondin.mpg.stats.model.Player p = stats.getStats(championship).getPlayer(player.getName()); + if (p.getAuction() != null) { + // Feature in API only since 2021-11 + player.setAuction(p.getAuction().getAverage()); + } + player.setEfficiency(p.getEfficiency()); + } catch (PlayerNotFoundException e) { + if (failIfPlayerNotFound) { + throw e; + } + if (logWarnIfPlayerNotFound) { + LOG.warn("WARN: Player can't be found in statistics: {}", player.getName()); + } + player.setEfficiency(0); + } + } + return players; + } + + private static void calculateEfficiencies(MpgStatsClient stats, ChampionshipStatsType championship, Config config) { int daysPeriod = getCurrentDay(stats, championship); int days4efficiency = 0; if (config.isEfficiencyRecentFocus() && stats.getStats(championship).getInfos().getAnnualStats().getCurrentDay().getDayReached() > 0) { @@ -443,22 +474,6 @@ private static List calculateEfficiency(List players, MpgStatsCl // round efficiency to 2 decimals p.setEfficiency(efficiency); } - - // Fill MPG model - for (Player player : players) { - try { - player.setEfficiency(stats.getStats(championship).getPlayer(player.getName()).getEfficiency()); - } catch (PlayerNotFoundException e) { - if (failIfPlayerNotFound) { - throw e; - } - if (logWarnIfPlayerNotFound) { - LOG.warn("WARN: Player can't be found in statistics: {}", player.getName()); - } - player.setEfficiency(0); - } - } - return players; } private static int getCurrentDay(MpgStatsClient stats, ChampionshipStatsType championship) { diff --git a/src/main/java/org/blondin/mpg/root/model/Player.java b/src/main/java/org/blondin/mpg/root/model/Player.java index 0dea00b..c54a26a 100644 --- a/src/main/java/org/blondin/mpg/root/model/Player.java +++ b/src/main/java/org/blondin/mpg/root/model/Player.java @@ -18,6 +18,7 @@ public class Player { private String clubId; private String clubName; private double efficiency; + private int auction; public String getId() { return id; @@ -47,6 +48,14 @@ public int getPricePaid() { return pricePaid; } + public int getAuction() { + return auction; + } + + public void setAuction(int auction) { + this.auction = auction; + } + public void setPricePaid(int pricePaid) { this.pricePaid = pricePaid; } diff --git a/src/main/java/org/blondin/mpg/stats/model/Auction.java b/src/main/java/org/blondin/mpg/stats/model/Auction.java new file mode 100644 index 0000000..927c06a --- /dev/null +++ b/src/main/java/org/blondin/mpg/stats/model/Auction.java @@ -0,0 +1,34 @@ +package org.blondin.mpg.stats.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Auction { + + @JsonProperty("m") + private int min; + @JsonProperty("a") + private int average; + @JsonProperty("M") + private int max; + @JsonProperty("n") + private int number; + + public int getMin() { + return min; + } + + public int getAverage() { + return average; + } + + public int getMax() { + return max; + } + + public int getNumber() { + return number; + } + +} diff --git a/src/main/java/org/blondin/mpg/stats/model/Player.java b/src/main/java/org/blondin/mpg/stats/model/Player.java index 14c9521..d4c6d62 100644 --- a/src/main/java/org/blondin/mpg/stats/model/Player.java +++ b/src/main/java/org/blondin/mpg/stats/model/Player.java @@ -27,6 +27,8 @@ public class Player { private Stats stats; @JsonProperty("r") private int price; + @JsonProperty("a") + private Auction auction; private double efficiency; @@ -50,6 +52,10 @@ public int getPrice() { return price; } + public Auction getAuction() { + return auction; + } + public Stats getStats() { if (stats == null) { stats = new Stats(); diff --git a/src/test/java/org/blondin/mpg/MainTest.java b/src/test/java/org/blondin/mpg/MainTest.java index ac094ca..d2a2d54 100644 --- a/src/test/java/org/blondin/mpg/MainTest.java +++ b/src/test/java/org/blondin/mpg/MainTest.java @@ -305,10 +305,10 @@ public void testPrepareMercatoTurn0Day0Ligue1() throws Exception { Assert.assertTrue(getLogOut(), getLogOut().contains("Proposal for your coming soon mercato")); // When championship not started (incoming day 1 in statistics), the previous year should be taken - Assert.assertTrue(getLogOut(), getLogOut().contains("| A | Mbappé Kylian | 166.21 | 40 | |")); + Assert.assertTrue(getLogOut(), getLogOut().contains("| A | Mbappé Kylian | 166.21 | 40 | 0 | |")); // Test some injuries - Assert.assertTrue(getLogOut(), getLogOut().contains("| D | Maripán Guillermo | 24.19 | 18 | INJURY_RED - Leg injury - Mid July |")); + Assert.assertTrue(getLogOut(), getLogOut().contains("| D | Maripán Guillermo | 24.19 | 18 | 0 | INJURY_RED - Leg injury - Mid July |")); } @Test diff --git a/src/test/java/org/blondin/mpg/stats/MpgStatsClientTest.java b/src/test/java/org/blondin/mpg/stats/MpgStatsClientTest.java index 129d941..597c6a1 100644 --- a/src/test/java/org/blondin/mpg/stats/MpgStatsClientTest.java +++ b/src/test/java/org/blondin/mpg/stats/MpgStatsClientTest.java @@ -18,6 +18,21 @@ public class MpgStatsClientTest extends AbstractMockTestClient { + // + + @Test + public void testAuction() { + stubFor(get("/builds").willReturn(aResponse().withHeader("Content-Type", "application/json").withBodyFile("mlnstats.builds.20211122.json"))); + stubFor(get("/leagues/Ligue-1") + .willReturn(aResponse().withHeader("Content-Type", "application/json").withBodyFile("mlnstats.ligue-1.20211122.json"))); + MpgStatsClient mpgStatsClient = MpgStatsClient.build(getConfig(), "http://localhost:" + getServer().port()); + Player p = mpgStatsClient.getStats(ChampionshipStatsType.LIGUE_1).getPlayer("Mbappé"); + Assert.assertEquals(43, p.getAuction().getMin()); + Assert.assertEquals(103, p.getAuction().getAverage()); + Assert.assertEquals(199, p.getAuction().getMax()); + Assert.assertEquals(106, p.getAuction().getNumber()); + } + @Test public void testPlayersWithSameName() { stubFor(get("/builds").willReturn(aResponse().withHeader("Content-Type", "application/json").withBodyFile("mlnstats.builds.20210804.json"))); diff --git a/src/test/resources/__files/README.md b/src/test/resources/__files/README.md index 94ecfc4..c8fb4ec 100644 --- a/src/test/resources/__files/README.md +++ b/src/test/resources/__files/README.md @@ -48,6 +48,23 @@ The `XXX` should be replaced by a use case scenario (like date, some league, dat | `equipeactu.serie-a.XXX.html` | | **Deprecated since October 20, 2020** ([#169](https://github.com/axel3rd/mpg-coach-bot/issues/169)). Injury / Suspended players for **Seria A (Italia)** | | `equipeactu.ligue-2.XXX.html` | | **Not used**, see below and [#99](https://github.com/axel3rd/mpg-coach-bot/issues/99), EquipeActu Website doesn't contain Ligue 2 (France) | +### Mpg Mobile App (complement, if needed) + +Mercato history: + +* GET +* GET + +User leagues: + +* GET ; use info, see `hiddenLeaguesIds` field in addition +* GET ; Leagues details + +Enable/disable one league: + +* PATCH +* PATCH + ### Mpg WebSite (deprecated since 19 July 2021) | **File** | **URL** | **Description** |