Fifa 23 Trading Programm (Hilfe)

Grundsätzliches

Vielleicht ist Ihnen das Videospiel Fifa 23 (Ultimate Team) bekannt. Fifa Ultimate Team ist ein Modus in diesem Spiel, wo man sein eigenes Team aus virtuellen Fussballspielern aufbauen kann. In diesem Modus gibt es auch einen Markt und so hat jeder Spieler seinen eigenen Marktwert, der sich stetig ändert. Die Veränderungen hierbei sind meist willkürlich und nicht vorauszusehen.

Es gibt aber ein paar Anhaltspunkte, bei der man erkennen kann, ob der Wert eines Spielers steigen wird. Wenn der Wert drastisch schnell und auf ein neues Rekordtief fällt, ist die Wahrscheinlichkeit sehr hoch, dass der wert des Spielers - wenn auch nur kurzfristig - wieder nach oben steigt. Und hier steigt mein Programm ein. Es gibt eine Webseite, die hat es sich zur Aufgabe gemacht, neben vielen anderen Modi, Preise der verschiedenen Fifa-Spieler zu dokumentieren.

Funktionsweise

Und von dort scrape ich die benötigten Daten. Das Projekt dient lediglich dem privaten Gebrauch und wird für keinerlei kommerziellen Zwecke verwendet. Mein Problem ist aber, dass so viele HTTP-Requests zu viel sind und dabei taucht die Fehlermeldung 429 („Too many requests“) auf. Ich möchte die Webseite ja auch nicht überfluten und deswegen ist mir in den Sinn gekommen, aus diesen vielen Spielern max. 8 zufällige Spieler herauszusuchen. Bei jedem neuen Run sollen neue 8 zufällige Spieler ermittelt werden. Und da brauche ich Hilfe.
Das ist mein Programm:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;



public class pc {
	
	public static void main(String[] args) throws IOException {
        
    	String[][] spielerTabelle = new String[26][4];
        spielerTabelle[0][0] = "Christopher Nkunku";
        spielerTabelle[0][1] = getPlayerPrice("https://www.futwiz.com/en//fifa23/player/christopher-nkunku/187");
        spielerTabelle[0][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=187&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=187");

        spielerTabelle[1][0] = "Lionel Messi      ";
        spielerTabelle[1][1] = getPlayerPrice("https://www.futwiz.com/en//fifa23/player/lionel-messi/51");
        spielerTabelle[1][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=51&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=51");
        
        spielerTabelle[2][0] = "Cristiano Ronaldo ";
        spielerTabelle[2][1] = getPlayerPrice("https://www.futwiz.com/en//fifa23/player/cristiano-ronaldo/20001");
        spielerTabelle[2][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=20001&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=20001");
        
        spielerTabelle[3][0] = "Neymar Jr          ";
        spielerTabelle[3][1] = getPlayerPrice("https://www.futwiz.com/en//fifa23/player/neymar-jr/46");
        spielerTabelle[3][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=46&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=46");

        spielerTabelle[5][0] = "Robert Lewandowski      ";
        spielerTabelle[5][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/robert-lewandowski/53");
       	spielerTabelle[5][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=53&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=53");

        spielerTabelle[6][0] = "Kevin De Bruyne         ";
        spielerTabelle[6][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/kevin-de-bruyne/52");
       	spielerTabelle[6][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=52&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=52");

       	spielerTabelle[7][0] = "Mohamed Salah           ";
       	spielerTabelle[7][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/mohamed-salah/50");
       	spielerTabelle[7][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=50&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=");

       	spielerTabelle[8][0]= "Thibaut Courtois        ";
       	spielerTabelle[8][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/thibaut-courtois/48");
       	spielerTabelle[8][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=48&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=48");

       	spielerTabelle[9][0] = "Manuel Neuer            ";
       	spielerTabelle[9][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/manuel-neuer/47");
       	spielerTabelle[9][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=47&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=47");

       	spielerTabelle[10][0] = "Virgil van Dijk.        ";
       	spielerTabelle[10][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/virgil-van-dijk/22");
       	spielerTabelle[10][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=22&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=22");

       	spielerTabelle[11][0] = "Sadio Mané              ";
       	spielerTabelle[11][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/sadio-mane/45");
       	spielerTabelle[11][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=45&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=45");

       	spielerTabelle[12][0] = "Joshua Kimmich          ";
       	spielerTabelle[12][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/joshua-kimmich/44");
       	spielerTabelle[12][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=44&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=44");

       	spielerTabelle[13][0] = "Casemiro                ";
       	spielerTabelle[13][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/casemiro/43");
       	spielerTabelle[13][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=43&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=43");

       	spielerTabelle[14][0] = "Alisson                 ";
       	spielerTabelle[14][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/alisson/42");
       	spielerTabelle[14][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=42&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=42");

       	spielerTabelle[15][0] = "Harry Kane              ";
       	spielerTabelle[15][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/harry-kane/41");
       	spielerTabelle[15][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=41&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=41");

       	spielerTabelle[16][0] = "Ederson                 ";
       	spielerTabelle[16][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/ederson/40");
       	spielerTabelle[16][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=40&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=40");

       	spielerTabelle[17][0] = "NGolo Kante             ";
       	spielerTabelle[17][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/ngolo-kante/39");
       	spielerTabelle[17][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=39&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=39");

       	spielerTabelle[18][0] = "Jan Oblak               ";
       	spielerTabelle[18][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/jan-oblak/38");
       	spielerTabelle[18][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=38&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=38");

       	spielerTabelle[19][0] = "Heung Min Son           ";
       	spielerTabelle[19][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/heung-min-son/24");
       	spielerTabelle[19][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=24&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=24");

       	spielerTabelle[20][0] = "Keylor Navas NF         ";
       	spielerTabelle[20][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/keylor-navas/21150");
       	spielerTabelle[20][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=21150&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=21150");

       	spielerTabelle[21][0] = "Joao Cancelo BM         ";
       	spielerTabelle[21][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/joao-cancelo/21149");
       	spielerTabelle[21][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=21149&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=21149");

       	spielerTabelle[22][0] = "Gianni Donnaruma        ";
       	spielerTabelle[22][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/gianluigi-donnarumma/288");
       	spielerTabelle[22][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=288&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=288");

       	spielerTabelle[23][0] = "Keylor Navas PSG        ";
       	spielerTabelle[23][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/keylor-navas/287");
       	spielerTabelle[23][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=287&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=287");

       	spielerTabelle[24][0] = "Luka Modric             ";
       	spielerTabelle[24][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/luka-modric/127");
       	spielerTabelle[24][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=127&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=127");

       	spielerTabelle[25][0] = "Cristiano Ronaldo ManUtd";
       	spielerTabelle[25][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/cristiano-ronaldo/49");
       	spielerTabelle[25][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=49&h","https://www.futwiz.com/en/app/price_history_player23_multi?p=49");

       	spielerTabelle[25][0] = "Karim Benzema           ";
       	spielerTabelle[25][1] = getPlayerPrice("https://www.futwiz.com/en/fifa23/player/karim-benzema/");
       	spielerTabelle[25][2] = getLowestPrice("https://www.futwiz.com/en/app/price_history_player23_multi?p=","https://www.futwiz.com/en/app/price_history_player23_multi?p=");


        
        
        for (int i = 0; i < spielerTabelle.length; i++) {
            int aktuellerPreis = Integer.parseInt(spielerTabelle[i][1]);
            int tiefsterPreis = Integer.parseInt(spielerTabelle[i][2]);
            if (aktuellerPreis > tiefsterPreis) {
                spielerTabelle[i][3] = " Nein";
            } else {
                spielerTabelle[i][3] = " Ja";
            }
        }

        System.out.println("Spieler \t\tAktueller Preis \t        Tiefster Preis \t         Investition?");
        for (String[] row : spielerTabelle) {
            if (row[2].equals("-1")) {
                System.out.printf("%s             \t%s           \tunknown             \t%s%n", row[0], row[1], row[3]);
            } else {
                System.out.printf("%s  \t%s                      \t%s             \t%s%n", row[0], row[1], row[2], row[3]);
            }
        }

        }

        
  
    
    public static String getPlayerPrice(String urlStr) throws IOException {
        URL url = new URL(urlStr);
        InputStream in = url.openStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String s = null;
        String pricePattern = ".*price on the xbox market is (\\d+,\\d+) coins.*";
        Pattern pattern = Pattern.compile(pricePattern);
        while ((s = reader.readLine()) != null) {
            Matcher matcher = pattern.matcher(s);
            if (matcher.matches()) {
                String priceWithComma = matcher.group(1);
                String priceWithoutComma = priceWithComma.replace(",", "");
                return priceWithoutComma;
            }
        }
        return "unknown";
    }


    
    public static String getLowestPrice(String url1Str, String url2Str) throws IOException {
        URL url1 = new URL(url1Str);
        InputStream in1 = url1.openStream();
        BufferedReader reader1 = new BufferedReader(new InputStreamReader(in1));

        URL url2 = new URL(url2Str);
        InputStream in2 = url2.openStream();
        BufferedReader reader2 = new BufferedReader(new InputStreamReader(in2));

        Pattern pattern = Pattern.compile("(?<=,)(\\d+)(?=.*pc\\b)");
        int minNumber = Integer.MAX_VALUE; // initialize minNumber to max value

        // process first source
        String s = null;
        while ((s = reader1.readLine()) != null) {
            Matcher matcher = pattern.matcher(s);
            while (matcher.find()) {
                int currentNumber = Integer.parseInt(matcher.group(1));
                if (currentNumber < minNumber) {
                    minNumber = currentNumber;
                }
            }
        }

        // process second source
        s = null;
        while ((s = reader2.readLine()) != null) {
            Matcher matcher = pattern.matcher(s);
            while (matcher.find()) {
                int currentNumber = Integer.parseInt(matcher.group(1));
                if (currentNumber < minNumber) {
                    minNumber = currentNumber;
                }
            }
        }

        if (minNumber == Integer.MAX_VALUE) {
            return "unknown";
        } else {
            return String.valueOf(minNumber);
        }
    }}

Wenn das Ziel im engeren Sinne ist, aus diesen 26 Einträgen zufällig 8 auszuwählen, gibt’s da viele Möglichkeiten. Man könnte irgendwas frickeln, aber … einige Schritte, um das ganze „etwas elegant(er)“ zu lösen, könnten sein:

Pack’ die relevante Information (name + URL) in eine Liste, z.B. so

        List<String[]> playerInfos = new ArrayList<String[]>(Arrays.asList(new String[][] {
          { "Christopher Nkunku", "https://www.futwiz.com/en//fifa23/player/christopher-nkunku/187" },
          // ...
          { "Casemiro", "https://www.futwiz.com/en/fifa23/player/casemiro/43" }, 
        }));

erstelle eine Methode, die aus so einer Liste das erstellt, was im Moment in der spielerTabelle steht:

    private static String[][] createTable(List<String[]> playerInfos) throws IOException {
        
        String[][] table = new String[playerInfos.size()][];
        for (int i=0; i<playerInfos.size(); i++) {
            String playerInfo[] = playerInfos.get(i);
            String name = playerInfo[0];
            String url = playerInfo[1];
            
            String row[] = new String[3];
            row[0] = name;
            row[1] = getPlayerPrice(url);
            row[2] = getLowestPrice(url + "&h",  url);
            table[i] = row;
        }
        return table;
    }

Dann kannst du in der main eine zufällige Teilmenge der Spieler verwenden, um eine kleinere Tabelle zu erstellen - etwa so

        Collections.shuffle(playerInfos, new Random(0));
        playerInfos = playerInfos.subList(0, 8);
        String[][] table = createTable(playerInfos);

(Die beiden for-Schleifen aus der main sollten besser auch in eine eigene Methode. Und man sollte wohl über Klassen wie PlayerInfo und/oder PlayerPriceInfo nachdenken, wo dann z.B. der Preis gleich als Zahl (und nicht als String) drinstehen könnte, und dann eher mit List als mit Arrays arbeiten, aber das sind erstmal Details…)