Ver Fonte

A new commi

Axel Nordh há 1 ano atrás
pai
commit
f6bb2364ba
83 ficheiros alterados com 4051 adições e 1049 exclusões
  1. 13 2
      OddsJavaFx/pom.xml
  2. 17 7
      OddsJavaFx/src/components/FloatStatRow.java
  3. 35 29
      OddsJavaFx/src/components/IntTableStatRow.java
  4. 26 1
      OddsJavaFx/src/components/MatchSummaryPanelRow.java
  5. 51 2
      OddsJavaFx/src/components/NumberStatRow.java
  6. 4 4
      OddsJavaFx/src/controllers/AnalysisTestController.java
  7. 254 0
      OddsJavaFx/src/controllers/CommingMatches.java
  8. 368 113
      OddsJavaFx/src/controllers/MatchStatisticsController.java
  9. 15 31
      OddsJavaFx/src/controllers/PastResultsController.java
  10. 82 316
      OddsJavaFx/src/controllers/StrategyTesterController.java
  11. 24 24
      OddsJavaFx/src/controllers/StryktipsetController.java
  12. 22 40
      OddsJavaFx/src/controllers/TestsController.java
  13. 234 1
      OddsJavaFx/src/controllers/strategytest/FibonacciStrategy.java
  14. 110 144
      OddsJavaFx/src/controllers/strategytest/KellyFormulaStrategy.java
  15. 607 1
      OddsJavaFx/src/controllers/strategytest/OneThreeTwoSixStrategy.java
  16. 69 34
      OddsJavaFx/src/controllers/strategytest/OneXStrategy.java
  17. 6 4
      OddsJavaFx/src/cronjob/updateStatistics.java
  18. 108 1
      OddsJavaFx/src/data/BetStrategyMysql/BetStrategyMysql.java
  19. 76 1
      OddsJavaFx/src/data/DTO/FibonacciDTO/FibonacciDTO.java
  20. 115 37
      OddsJavaFx/src/data/GuiMysql.java
  21. 256 1
      OddsJavaFx/src/data/MatchStatSql.java
  22. 24 10
      OddsJavaFx/src/fxml/MatchStatistics.fxml
  23. 17 25
      OddsJavaFx/src/fxml/OddsFxBuilder.fxml
  24. 64 15
      OddsJavaFx/src/fxml/StrategyTester.fxml
  25. 4 9
      OddsJavaFx/src/fxml/Testing.fxml
  26. 34 0
      OddsJavaFx/src/fxml/TodaysMatches.fxml
  27. 64 22
      OddsJavaFx/src/fxml/UpcommingMatches.fxml
  28. 8 2
      OddsJavaFx/src/fxml/css/StrategyStyles.css
  29. 65 1
      OddsJavaFx/src/interfaces/strategytest/BettingStrategyInterface.java
  30. 125 1
      OddsJavaFx/src/objects/MatchViewDTO.java
  31. 82 1
      OddsJavaFx/src/objects/OddsStat.java
  32. 49 12
      OddsJavaFx/src/objects/Percentages.java
  33. 52 2
      OddsJavaFx/src/objects/SoccerMatch.java
  34. 101 19
      OddsJavaFx/src/objects/SoccerMatchAnalysis.java
  35. 176 1
      OddsJavaFx/src/objects/visual/FibonacciBets.java
  36. 6 6
      OddsJavaFx/src/tests/AnalysisBettDrawTest.java
  37. 12 12
      OddsJavaFx/src/tests/AnalysisBettTest.java
  38. 4 4
      OddsJavaFx/src/tests/Away2Test.java
  39. 6 6
      OddsJavaFx/src/tests/AwayTest.java
  40. 7 7
      OddsJavaFx/src/tests/BetOnDifferenceTest.java
  41. 4 4
      OddsJavaFx/src/tests/Draw2Tests.java
  42. 6 6
      OddsJavaFx/src/tests/DrawTest.java
  43. 4 4
      OddsJavaFx/src/tests/Home2Test.java
  44. 6 6
      OddsJavaFx/src/tests/HomeTest.java
  45. 7 8
      OddsJavaFx/src/tests/PrioCountriesAllTest.java
  46. 7 13
      OddsJavaFx/src/tests/RelevanceTest.java
  47. 160 7
      OddsJavaFx/src/tests/XBestRatedGamesBettingTest.java
  48. 73 1
      OddsJavaFx/src/tests/objects/GamePercentages.java
  49. 114 1
      OddsJavaFx/src/tests/objects/XBestGamesDTO.java
  50. 248 1
      OddsJavaFx/src/tests/objects/XBestGamesWinPercentageStatistics.java
  51. 7 1
      OddsJavaFx/src/tests/objects/XGamesPercentages.java
  52. 0 5
      OddsStrategyWeb/src/main/java/Main.html
  53. 5 0
      OddsStrategyWeb/src/main/java/MainPage.html
  54. 3 2
      OddsStrategyWeb/src/main/java/MainPage.java
  55. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT.war
  56. 0 5
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/classes/Main.html
  57. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/classes/main/java/Main.class
  58. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/classes/main/java/MainApplication.class
  59. 5 0
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/classes/main/java/MainPage.html
  60. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/commons-collections4-4.4.jar
  61. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/commons-fileupload2-core-2.0.0-M2.jar
  62. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/commons-fileupload2-jakarta-servlet5-2.0.0-M2.jar
  63. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/commons-io-2.16.1.jar
  64. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/jdk-serializable-functional-1.9.0.jar
  65. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/openjson-1.0.13.jar
  66. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/slf4j-api-2.0.16.jar
  67. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/slf4j-simple-2.0.16.jar
  68. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/wicket-core-10.2.0.jar
  69. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/wicket-native-websocket-core-10.2.0.jar
  70. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/wicket-native-websocket-javax-10.2.0.jar
  71. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/wicket-request-10.2.0.jar
  72. BIN
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/wicket-util-10.2.0.jar
  73. 0 25
      OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/web.xml
  74. 0 5
      OddsStrategyWeb/target/classes/Main.html
  75. BIN
      OddsStrategyWeb/target/classes/main/java/Main.class
  76. 5 0
      OddsStrategyWeb/target/classes/main/java/Main.html
  77. BIN
      OddsStrategyWeb/target/classes/main/java/MainApplication.class
  78. 5 0
      OddsStrategyWeb/target/classes/main/java/MainPage.html
  79. 0 3
      OddsStrategyWeb/target/maven-archiver/pom.properties
  80. 0 2
      OddsStrategyWeb/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
  81. 0 2
      OddsStrategyWeb/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
  82. 0 0
      OddsStrategyWeb/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
  83. 0 0
      OddsStrategyWeb/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst

+ 13 - 2
OddsJavaFx/pom.xml

@@ -1,5 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>Odds</groupId>
     <artifactId>OddsFx</artifactId>
@@ -36,6 +36,16 @@
                             <mainClass>application.Main</mainClass>
                         </configuration>
                     </execution>
+                    <execution>
+                        <!-- Configuration for debugging -->
+                        <id>debug</id>
+                        <configuration>
+                            <options>
+                                <option>-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:8000</option>
+                            </options>
+                            <mainClass>application.Main</mainClass>
+                        </configuration>
+                    </execution>
                 </executions>
             </plugin>
         </plugins>
@@ -44,6 +54,7 @@
                 <directory>src/fxml/</directory>
                 <includes>
                     <include>**/*.fxml</include>
+                    <include>**/*.css</include>
                 </includes>
             </resource>
         </resources>

+ 17 - 7
OddsJavaFx/src/components/FloatStatRow.java

@@ -1,16 +1,16 @@
 package components;
 
 import javafx.scene.control.Label;
-import javafx.scene.layout.VBox;
+import javafx.scene.layout.HBox;
 
-public class NumberStatRow extends VBox {
+public class FloatStatRow extends HBox {
     String text;
-    int value;
+    float value;
 
-    Label textLabel;
-    Label valueLabel;
+    Label textLabel = new Label();
+    Label valueLabel = new Label();
 
-    public NumberStatRow(String text, int value) {
+    public FloatStatRow(String text, float value) {
         this.text = text;
         this.value = value;
 
@@ -30,12 +30,22 @@ public class NumberStatRow extends VBox {
         updateValueLabel();
     }
 
+    public void increaseValue(float valueToAdd) {
+        value += valueToAdd;
+        updateValueLabel();
+    }
+
+    public void decreaseValue(float valueToSubtract) {
+        value -= valueToSubtract;
+        updateValueLabel();
+    }
+
     private void updateValueLabel() {
         valueLabel.setText(String.valueOf(value));
     }
 
 
-    public int getValue() {
+    public float getValue() {
         return value;
     }
 }

+ 35 - 29
OddsJavaFx/src/components/IntTableStatRow.java

@@ -2,50 +2,56 @@ package components;
 
 import javafx.scene.control.Label;
 import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
 
-public class FloatStatRow extends HBox {
-    String text;
-    float value;
+import java.util.HashMap;
+import java.util.Map;
 
-    Label textLabel = new Label();
-    Label valueLabel = new Label();
+public class IntTableStatRow extends VBox {
+    String title;
 
-    public FloatStatRow(String text, float value) {
-        this.text = text;
-        this.value = value;
+    Label titleLabel = new Label();
+    HBox keys = new HBox(5);
+    HBox values = new HBox(5);
 
-        textLabel.setText(text);
-        valueLabel.setText(String.valueOf(value));
-        this.getChildren().add(textLabel);
-        this.getChildren().add(valueLabel);
-    }
+    Map<Integer, Integer> valueMap = new HashMap<>();
+
+    public IntTableStatRow(String title) {
+        this.title = title;
 
-    public void increaseValue() {
-        value++;
-        updateValueLabel();
+        titleLabel.setText(this.title);
+        this.getChildren().add(titleLabel);
+        this.getChildren().add(keys);
+        this.getChildren().add(values);
+        updateValueGui();
     }
 
-    public void decreaseValue() {
-        value--;
-        updateValueLabel();
+    public void increaseValue(int value) {
+        valueMap.put(value, valueMap.getOrDefault(value, 0) + 1);
+        updateValueGui();
     }
 
-    public void increaseValue(float valueToAdd) {
-        value += valueToAdd;
-        updateValueLabel();
+    public void decreaseValue(int value) {
+        valueMap.put(value, valueMap.getOrDefault(value, 0) - 1);
+        updateValueGui();
     }
 
-    public void decreaseValue(float valueToSubtract) {
-        value -= valueToSubtract;
-        updateValueLabel();
+    public void setValue(int key, int value) {
+        valueMap.put(key, value);
+        updateValueGui();
     }
 
-    private void updateValueLabel() {
-        valueLabel.setText(String.valueOf(value));
+    private void updateValueGui() {
+        keys.getChildren().clear();
+        values.getChildren().clear();
+        valueMap.forEach((key, value) -> {
+            keys.getChildren().add(new Label(String.valueOf(key)));
+            values.getChildren().add(new Label(String.valueOf(value)));
+        });
     }
 
 
-    public float getValue() {
-        return value;
+    public int getValue(int key) {
+        return valueMap.getOrDefault(key, 0);
     }
 }

+ 26 - 1
OddsJavaFx/src/components/MatchSummaryPanelRow.java

@@ -1,2 +1,27 @@
-package components;public class MatchSummaryPanelRow {
+package components;
+
+import javafx.scene.control.Label;
+import javafx.scene.layout.HBox;
+import objects.SoccerMatch;
+
+public class MatchSummaryPanelRow extends HBox {
+    public MatchSummaryPanelRow(SoccerMatch match, float bank, float odds, float betAmount) {
+        String matchTeams = match.getHomeTeam().getTeamName() + " vs " + match.getAwayTeam().getTeamName();
+        String matchResult = match.getHomeScore() + " : " + match.getAwayScore();
+        String matchOdds = String.format("%.2f", odds);
+
+        this.setSpacing(5d);
+
+        this.getChildren().add(new Label(matchTeams));
+        this.getChildren().add(new Label(matchOdds));
+        this.getChildren().add(new Label(matchResult));
+
+        if(match.getHomeScore() >= match.getAwayScore()) {
+            this.getChildren().add(new Label(String.valueOf(bank + (betAmount * odds) - betAmount)));
+            this.setStyle("-fx-background-color: green");
+        } else {
+            this.getChildren().add(new Label(String.valueOf(bank - betAmount)));
+            this.setStyle("-fx-background-color: red");
+        }
+    }
 }

+ 51 - 2
OddsJavaFx/src/components/NumberStatRow.java

@@ -1,2 +1,51 @@
-package components;public class NumberStatRow {
-}
+package components;
+
+import javafx.scene.control.Label;
+import javafx.scene.layout.HBox;
+
+public class NumberStatRow extends HBox {
+    String text;
+    int value;
+
+    Label textLabel = new Label();
+    Label valueLabel = new Label();
+
+    public NumberStatRow(String text, int value) {
+        this.text = text;
+        this.value = value;
+
+        textLabel.setText(text);
+        valueLabel.setText(String.valueOf(value));
+        this.getChildren().add(textLabel);
+        this.getChildren().add(valueLabel);
+    }
+
+    public void increaseValue(int valueToAdd) {
+        value += valueToAdd;
+        updateValueLabel();
+    }
+
+    public void decreaseValue(int valueToSubtract) {
+        value -= valueToSubtract;
+        updateValueLabel();
+    }
+
+    public void increaseValue() {
+        value++;
+        updateValueLabel();
+    }
+
+    public void decreaseValue() {
+        value--;
+        updateValueLabel();
+    }
+
+    private void updateValueLabel() {
+        valueLabel.setText(String.valueOf(value));
+    }
+
+
+    public int getValue() {
+        return value;
+    }
+}

+ 4 - 4
OddsJavaFx/src/controllers/AnalysisTestController.java

@@ -312,8 +312,8 @@ public class AnalysisTestController implements Initializable {
             int homeWins = analysis.winLossRatio(league.getWinLossRatio(), true);
             int awayWins = analysis.winLossRatio(league.getWinLossRatio(), false);
 
-            int homeWinLossRatio = analysis.winLossRatioHomeAndAway(true, league.getWinLossRatioHomeAndAway());
-            int awayWinLossRatio = analysis.winLossRatioHomeAndAway(false, league.getWinLossRatioHomeAndAway());
+            int homeWinLossRatio = analysis.winLossRatioHomeAndAway(league.getWinLossRatioHomeAndAway(), true);
+            int awayWinLossRatio = analysis.winLossRatioHomeAndAway(league.getWinLossRatioHomeAndAway(), false);
 
             int homeScoringTotal = analysis.scoringTotal(league.getScoringTotal(), true);
             int awayScoringTotal = analysis.scoringTotal(league.getScoringTotal(), false);
@@ -323,8 +323,8 @@ public class AnalysisTestController implements Initializable {
             int winLossRatioDiff = homeWinLossRatio - awayWinLossRatio;
             int scoringTotalDiff = homeScoringTotal - awayScoringTotal;
 
-            if (scoringDiffLastGames < 0 && winsCountDiff < 0 && winLossRatioDiff < 0 && scoringTotalDiff < 0 ||
-                    scoringDiffLastGames > 0 && winsCountDiff > 0 && winLossRatioDiff > 0 && scoringTotalDiff > 0) {
+            if ((scoringDiffLastGames < 0 && winsCountDiff < 0 && winLossRatioDiff < 0 && scoringTotalDiff < 0) ||
+                    (scoringDiffLastGames > 0 && winsCountDiff > 0 && winLossRatioDiff > 0 && scoringTotalDiff > 0)) {
                 result = (scoringDiffLastGames + winsCountDiff + winLossRatioDiff + scoringTotalDiff) / 4;
             }
         }

+ 254 - 0
OddsJavaFx/src/controllers/CommingMatches.java

@@ -0,0 +1,254 @@
+package controllers;
+
+import controllers.strategytest.FibonacciStrategy;
+import data.DTO.FibonacciDTO.FibonacciDTO;
+import data.GuiMysql;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.*;
+import javafx.scene.control.cell.PropertyValueFactory;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.VBox;
+import objects.MatchViewDTO;
+import objects.SoccerMatch;
+import objects.visual.FibonacciBets;
+
+import java.net.URL;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.ResourceBundle;
+
+public class CommingMatches implements Initializable {
+
+    @FXML
+    public TableView<MatchViewDTO> todaysMatchesTableView;
+    @FXML
+    public TableView<MatchViewDTO> tomorrowsMatchesTableView;
+    public VBox betsPanel;
+    public VBox actionsPanel;
+    public VBox betsContentPanel;
+    Label errorLabel = new Label();
+
+
+    TableColumn<MatchViewDTO, String> homeTeamColumn = new TableColumn<>("Home Team");
+    TableColumn<MatchViewDTO, String> awayTeamColumn = new TableColumn<>("Away Team");
+    TableColumn<MatchViewDTO, String> leagueColumn = new TableColumn<>("Country");
+    TableColumn<MatchViewDTO, String> countryColumn = new TableColumn<>("League");
+    TableColumn<MatchViewDTO, Float> odds1Column = new TableColumn<>("Odds 1");
+    TableColumn<MatchViewDTO, Float> oddsXColumn = new TableColumn<>("Odds X");
+    TableColumn<MatchViewDTO, Float> odds2Column = new TableColumn<>("Odds 2");
+
+    TableColumn<MatchViewDTO, Float> calculatedOdds1Column = new TableColumn<>("Calculated Odds 1");
+    TableColumn<MatchViewDTO, Float> calculatedOddsXColumn = new TableColumn<>("Calculated Odds X");
+    TableColumn<MatchViewDTO, Float> calculatedOdds2Column = new TableColumn<>("Calculated Odds 2");
+
+    TableColumn<MatchViewDTO, Float> calculatedOddsOneXColumn = new TableColumn<>("Calculated Odds 1X");
+    TableColumn<MatchViewDTO, Float> calculatedOddsX2Column = new TableColumn<>("Calculated Odds X2");
+    TableColumn<MatchViewDTO, Float> calculatedOdds12Column = new TableColumn<>("Calculated Odds 12");
+
+    TableColumn<MatchViewDTO, Float> calculatedHomeWinColumn = new TableColumn<>("Calculated Home Win");
+    TableColumn<MatchViewDTO, Float> calculatedDrawColumn = new TableColumn<>("Calculated Draw");
+    TableColumn<MatchViewDTO, Float> calculatedAwayWinColumn = new TableColumn<>("Calculated Away Win");
+
+    TableColumn<MatchViewDTO, String> tomorrowHomeTeamColumn = new TableColumn<>("Home Team");
+    TableColumn<MatchViewDTO, String> tomorrowAwayTeamColumn = new TableColumn<>("Away Team");
+    TableColumn<MatchViewDTO, String> tomorrowLeagueColumn = new TableColumn<>("Country");
+    TableColumn<MatchViewDTO, String> tomorrowCountryColumn = new TableColumn<>("League");
+    TableColumn<MatchViewDTO, Float> tomorrowOdds1Column = new TableColumn<>("Odds 1");
+    TableColumn<MatchViewDTO, Float> tomorrowOddsXColumn = new TableColumn<>("Odds X");
+    TableColumn<MatchViewDTO, Float> tomorrowOdds2Column = new TableColumn<>("Odds 2");
+
+    TableColumn<MatchViewDTO, Float> tomorrowCalculatedOdds1Column = new TableColumn<>("Calculated Odds 1");
+    TableColumn<MatchViewDTO, Float> tomorrowCalculatedOddsXColumn = new TableColumn<>("Calculated Odds X");
+    TableColumn<MatchViewDTO, Float> tomorrowCalculatedOdds2Column = new TableColumn<>("Calculated Odds 2");
+
+    TableColumn<MatchViewDTO, Float> tomorrowCalculatedOddsOneXColumn = new TableColumn<>("Calculated Odds 1X");
+    TableColumn<MatchViewDTO, Float> tomorrowCalculatedOddsX2Column = new TableColumn<>("Calculated Odds X2");
+    TableColumn<MatchViewDTO, Float> tomorrowCalculatedOdds12Column = new TableColumn<>("Calculated Odds 12");
+
+    TableColumn<MatchViewDTO, Float> tomorrowCalculatedHomeWinColumn = new TableColumn<>("Calculated Home Win");
+    TableColumn<MatchViewDTO, Float> tomorrowCalculatedDrawColumn = new TableColumn<>("Calculated Draw");
+    TableColumn<MatchViewDTO, Float> tomorrowCalculatedAwayWinColumn = new TableColumn<>("Calculated Away Win");
+    private MatchViewDTO selectedMatch;
+
+    FibonacciBets fibonacciBets = new FibonacciBets();
+    private FibonacciDTO currentActiveFibonacciSequence;
+
+    Button addBetButton = new Button("Add Bet");
+
+
+    @Override
+    public void initialize(URL location, ResourceBundle resources) {
+        prepareColumns();
+        buildTodaysMatchesTableView();
+        buildTomorrowsMatchesTableView();
+
+        buildBetsPanel();
+
+        AnchorPane.setBottomAnchor(todaysMatchesTableView, 0.0);
+        AnchorPane.setTopAnchor(todaysMatchesTableView, 0.0);
+        AnchorPane.setLeftAnchor(todaysMatchesTableView, 0.0);
+        AnchorPane.setRightAnchor(todaysMatchesTableView, 0.0);
+
+        AnchorPane.setBottomAnchor(tomorrowsMatchesTableView, 0.0);
+        AnchorPane.setTopAnchor(tomorrowsMatchesTableView, 0.0);
+        AnchorPane.setLeftAnchor(tomorrowsMatchesTableView, 0.0);
+        AnchorPane.setRightAnchor(tomorrowsMatchesTableView, 0.0);
+
+        todaysMatchesTableView.getColumns().addAll(homeTeamColumn, awayTeamColumn, leagueColumn, countryColumn,
+                odds1Column, oddsXColumn, odds2Column, calculatedOdds1Column, calculatedOddsXColumn,
+                calculatedOdds2Column, calculatedOddsOneXColumn, calculatedOddsX2Column, calculatedOdds12Column,
+                calculatedHomeWinColumn, calculatedDrawColumn, calculatedAwayWinColumn);
+
+        tomorrowsMatchesTableView.getColumns().addAll(tomorrowHomeTeamColumn, tomorrowAwayTeamColumn, tomorrowLeagueColumn, tomorrowCountryColumn,
+                tomorrowOdds1Column, tomorrowOddsXColumn, tomorrowOdds2Column, tomorrowCalculatedOdds1Column, tomorrowCalculatedOddsXColumn,
+                tomorrowCalculatedOdds2Column, tomorrowCalculatedOddsOneXColumn, tomorrowCalculatedOddsX2Column, tomorrowCalculatedOdds12Column,
+                tomorrowCalculatedHomeWinColumn, tomorrowCalculatedDrawColumn, tomorrowCalculatedAwayWinColumn);
+
+
+        todaysMatchesTableView.getSelectionModel().selectedItemProperty().addListener((obs, oldValue, newValue) -> matchesTableSelectionChange(newValue));
+        tomorrowsMatchesTableView.getSelectionModel().selectedItemProperty().addListener((obs, oldValue, newValue) -> matchesTableSelectionChange(newValue));
+
+        addBetButton.setOnAction(this::addBetAction);
+        errorLabel.setStyle("fx-text-fill: red");
+    }
+
+    private void addBetAction(ActionEvent event) {
+        if (selectedMatch == null) {
+            errorLabel.setText("No match selected");
+        } else {
+            if (fibonacciBets.validBetSettings()) {
+                errorLabel.setText("");
+                fibonacciBets.addBet(fibonacciBets.getSequenceNumber(), fibonacciBets.getOddsFieldFloat(), selectedMatch);
+
+                fibonacciBets = new FibonacciBets();
+
+                updateBetsContentPanel();
+            } else {
+                errorLabel.setText("Bet Settings are not valid");
+            }
+        }
+    }
+
+    private void matchesTableSelectionChange(MatchViewDTO newValue) {
+        // TODO implement
+        System.out.println("Selected item: " + newValue);
+        selectedMatch = newValue;
+
+        fibonacciBets.setCurrentMatch(newValue);
+    }
+
+    private void prepareColumns() {
+        homeTeamColumn.setCellValueFactory(new PropertyValueFactory<>("homeTeamName"));
+        awayTeamColumn.setCellValueFactory(new PropertyValueFactory<>("awayTeamName"));
+        leagueColumn.setCellValueFactory(new PropertyValueFactory<>("leagueName"));
+        countryColumn.setCellValueFactory(new PropertyValueFactory<>("countryName"));
+        odds1Column.setCellValueFactory(new PropertyValueFactory<>("odds1"));
+        oddsXColumn.setCellValueFactory(new PropertyValueFactory<>("oddsX"));
+        odds2Column.setCellValueFactory(new PropertyValueFactory<>("odds2"));
+        calculatedOdds1Column.setCellValueFactory(new PropertyValueFactory<>("calculatedOdds1"));
+        calculatedOddsXColumn.setCellValueFactory(new PropertyValueFactory<>("calculatedOddsX"));
+        calculatedOdds2Column.setCellValueFactory(new PropertyValueFactory<>("calculatedOdds2"));
+        calculatedOddsOneXColumn.setCellValueFactory(new PropertyValueFactory<>("calculatedOddsOneX"));
+        calculatedOddsX2Column.setCellValueFactory(new PropertyValueFactory<>("calculatedOddsX2"));
+        calculatedOdds12Column.setCellValueFactory(new PropertyValueFactory<>("calculatedOdds12"));
+        calculatedHomeWinColumn.setCellValueFactory(new PropertyValueFactory<>("homeWinPercent"));
+        calculatedDrawColumn.setCellValueFactory(new PropertyValueFactory<>("drawPercent"));
+        calculatedAwayWinColumn.setCellValueFactory(new PropertyValueFactory<>("awayWinPercent"));
+
+        tomorrowHomeTeamColumn.setCellValueFactory(new PropertyValueFactory<>("homeTeamName"));
+        tomorrowAwayTeamColumn.setCellValueFactory(new PropertyValueFactory<>("awayTeamName"));
+        tomorrowLeagueColumn.setCellValueFactory(new PropertyValueFactory<>("leagueName"));
+        tomorrowCountryColumn.setCellValueFactory(new PropertyValueFactory<>("countryName"));
+        tomorrowOdds1Column.setCellValueFactory(new PropertyValueFactory<>("odds1"));
+        tomorrowOddsXColumn.setCellValueFactory(new PropertyValueFactory<>("oddsX"));
+        tomorrowOdds2Column.setCellValueFactory(new PropertyValueFactory<>("odds2"));
+        tomorrowCalculatedOdds1Column.setCellValueFactory(new PropertyValueFactory<>("calculatedOdds1"));
+        tomorrowCalculatedOddsXColumn.setCellValueFactory(new PropertyValueFactory<>("calculatedOddsX"));
+        tomorrowCalculatedOdds2Column.setCellValueFactory(new PropertyValueFactory<>("calculatedOdds2"));
+        tomorrowCalculatedOddsOneXColumn.setCellValueFactory(new PropertyValueFactory<>("calculatedOddsOneX"));
+        tomorrowCalculatedOddsX2Column.setCellValueFactory(new PropertyValueFactory<>("calculatedOddsX2"));
+        tomorrowCalculatedOdds12Column.setCellValueFactory(new PropertyValueFactory<>("calculatedOdds12"));
+        tomorrowCalculatedHomeWinColumn.setCellValueFactory(new PropertyValueFactory<>("homeWinPercent"));
+        tomorrowCalculatedDrawColumn.setCellValueFactory(new PropertyValueFactory<>("drawPercent"));
+        tomorrowCalculatedAwayWinColumn.setCellValueFactory(new PropertyValueFactory<>("awayWinPercent"));
+    }
+
+    private void buildTodaysMatchesTableView() {
+        List<SoccerMatch> todaysMatches = getTodaysMatches();
+
+        ObservableList<MatchViewDTO> todaysMatchesViewDTO = FXCollections.<MatchViewDTO>observableArrayList();
+
+        for (SoccerMatch match : todaysMatches) {
+            match.setLeagueName(match.getHomeTeam().getTeamLeague());
+            match.setCountryName(match.getHomeTeam().getCountryName());
+
+            MatchViewDTO matchViewDTO = new MatchViewDTO(match);
+            todaysMatchesViewDTO.add(matchViewDTO);
+        }
+
+        todaysMatchesTableView.getItems().addAll(todaysMatchesViewDTO);
+    }
+
+    private List<SoccerMatch> getTodaysMatches() {
+        return GuiMysql.getInstance().getPrioMatchesOfDate(LocalDateTime.now().toLocalDate().toString());
+    }
+
+    private void buildTomorrowsMatchesTableView() {
+        List<SoccerMatch> tomorrowsMatches = getTomorrowsMatches();
+        ObservableList<MatchViewDTO> tomorrowsMatchesViewDTO = FXCollections.<MatchViewDTO>observableArrayList();
+
+        for (SoccerMatch match : tomorrowsMatches) {
+            match.setLeagueName(match.getHomeTeam().getTeamLeague());
+            match.setCountryName(match.getHomeTeam().getCountryName());
+
+            MatchViewDTO matchViewDTO = new MatchViewDTO(match);
+            tomorrowsMatchesViewDTO.add(matchViewDTO);
+        }
+
+        tomorrowsMatchesTableView.getItems().addAll(tomorrowsMatchesViewDTO);
+    }
+
+    private List<SoccerMatch> getTomorrowsMatches() {
+        return GuiMysql.getInstance().getPrioMatchesOfDate(LocalDateTime.now().plusDays(1).toLocalDate().toString());
+    }
+
+    private void buildBetsPanel() {
+        //if (selectedMatch != null) {
+        actionsPanel.getChildren().clear();
+        actionsPanel.getChildren().add(getBettingStrategyComboBox());
+
+        //}
+    }
+
+    private ComboBox<String> getBettingStrategyComboBox() {
+        ComboBox<String> bettingStrategyComboBox = new ComboBox<>();
+        bettingStrategyComboBox.getItems().add("");
+        bettingStrategyComboBox.getItems().add(FibonacciStrategy.NAME);
+
+        bettingStrategyComboBox.getSelectionModel().selectedItemProperty().addListener((obs, oldValue, newValue) -> betStrategyChangeListener(newValue));
+        return bettingStrategyComboBox;
+    }
+
+    private void betStrategyChangeListener(String newValue) {
+
+        betsPanel.getChildren().clear();
+        // TODO implement
+        if (FibonacciStrategy.NAME.equals(newValue)) {
+            betsPanel.getChildren().add(fibonacciBets.getNewBetGui());
+        }
+
+        updateBetsContentPanel();
+
+        betsPanel.getChildren().add(addBetButton);
+        betsPanel.getChildren().add(errorLabel);
+    }
+
+    private void updateBetsContentPanel() {
+        betsContentPanel.getChildren().clear();
+        betsContentPanel.getChildren().add(fibonacciBets);
+    }
+}

+ 368 - 113
OddsJavaFx/src/controllers/MatchStatisticsController.java

@@ -1,122 +1,377 @@
 package controllers;
 
+import data.GuiMysql;
+import data.MatchStatSql;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.DatePicker;
+import javafx.scene.control.Label;
+import javafx.scene.control.ListView;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Pane;
+import javafx.scene.layout.VBox;
+import objects.OddsStat;
+import objects.SoccerMatch;
+import objects.Team;
+
 import java.net.URL;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Optional;
 import java.util.ResourceBundle;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
-import com.google.common.collect.Maps;
+public class MatchStatisticsController implements Initializable {
 
-import data.GuiMysql;
-import javafx.fxml.FXML;
-import javafx.fxml.Initializable;
-import javafx.scene.control.SelectionMode;
-import javafx.scene.control.TableColumn;
-import javafx.scene.control.TableView;
-import javafx.scene.control.TableView.TableViewSelectionModel;
-import javafx.scene.control.cell.MapValueFactory;
-import objects.TeamStanding;
-
-@SuppressWarnings("rawtypes") public class MatchStatTabController implements Initializable {
-
-	private static final String GOALS_CONCEDED = "goalsConceded";
-
-	private static final String GOALS_SCORED = "goalsScored";
-
-	private static final String POINTS_STRING = "points";
-
-	private static final String GAMES_PLAYED = "gamesPlayed";
-
-	private static MatchStatTabController instance;
-
-	@FXML TableView<Map<String, Object>> matchStatTable;
-
-	@FXML TableColumn<Map, String> team = new TableColumn<>("team");
-	@FXML TableColumn<Map, Integer> gamesPlayed = new TableColumn<>(GAMES_PLAYED);
-	@FXML TableColumn<Map, Integer> win = new TableColumn<>("win");
-	@FXML TableColumn<Map, Integer> draw = new TableColumn<>("draw");
-	@FXML TableColumn<Map, Integer> loss = new TableColumn<>("loss");
-	@FXML TableColumn<Map, Integer> points = new TableColumn<>(POINTS_STRING);
-	@FXML TableColumn<Map, Float> goalsScored = new TableColumn<>(GOALS_SCORED);
-	@FXML TableColumn<Map, Float> goalsConceded = new TableColumn<>(GOALS_CONCEDED);
-	@FXML TableColumn<Map, Float> diff = new TableColumn<>("diff");
-
-	public static MatchStatTabController getInstance() {
-		if (instance == null) {
-			synchronized (MatchStatTabController.class) {
-				if (instance == null) {
-					instance = new MatchStatTabController();
-				}
-			}
-		}
-		return instance;
-	}
-
-	@Override public void initialize(URL arg0, ResourceBundle arg1) {
-		team.setCellValueFactory(new MapValueFactory<>("team"));
-		gamesPlayed.setCellValueFactory(new MapValueFactory<>(GAMES_PLAYED));
-		win.setCellValueFactory(new MapValueFactory<>("win"));
-		draw.setCellValueFactory(new MapValueFactory<>("draw"));
-		loss.setCellValueFactory(new MapValueFactory<>("loss"));
-		points.setCellValueFactory(new MapValueFactory<>(POINTS_STRING));
-		goalsScored.setCellValueFactory(new MapValueFactory<>(GOALS_SCORED));
-		goalsConceded.setCellValueFactory(new MapValueFactory<>(GOALS_CONCEDED));
-		diff.setCellValueFactory(new MapValueFactory<>("diff"));
-
-		instance = this;
-	}
-
-	public void setLeagueStandingsTable(int leagueId, String season, int countryId, String date) {
-		final List<TeamStanding> res = GuiMysql.getInstance().getLeagueTable(leagueId, season, countryId, date);
-		matchStatTable.getItems().clear();
-		for (final TeamStanding ts : res) {
-			final Map<String, Object> line = Maps.newHashMap();
-			final int numGamesPlayed = ts.getWins() + ts.getDraws() + ts.getLosses();
-			line.put("team", ts.getTeamName());
-			line.put(GAMES_PLAYED, numGamesPlayed);
-			line.put("win", ts.getWins());
-			line.put("draw", ts.getDraws());
-			line.put("loss", ts.getLosses());
-			line.put(POINTS_STRING, ts.getPoints());
-			line.put(GOALS_SCORED, ts.getGoalsScored() / numGamesPlayed);
-			line.put(GOALS_CONCEDED, ts.getGoalsConceded() / numGamesPlayed);
-
-			matchStatTable.getItems().add(line);
-		}
-	}
-
-	public void setTeamSelected(String teamName, boolean homeTeam) {
-		TableViewSelectionModel<Map<String, Object>> selectionModel = matchStatTable.getSelectionModel();
-		java.util.Optional<Map<String, Object>> optional = matchStatTable.getItems().stream().filter(p -> p.get("team").equals(teamName)).findFirst();
-		if (optional.isPresent()) {
-			selectionModel.setSelectionMode(SelectionMode.MULTIPLE);
-			int indexOf = matchStatTable.getItems().indexOf(optional.get());
-			selectionModel.select(indexOf);
-		}
-	}
-
-	public void clearSelection() {
-		TableViewSelectionModel<Map<String, Object>> selectionModel = matchStatTable.getSelectionModel();
-		selectionModel.clearSelection();
-	}
-
-	public int getTeamPositionDiff(String homeTeamName, String awayTeamName) {
-		int result = 0;
-		Optional<Map<String, Object>> homeTeamOptional = matchStatTable.getItems().stream().filter(p -> p.get("team").equals(homeTeamName))
-				.findFirst();
-		Optional<Map<String, Object>> awayTeamOptional = matchStatTable.getItems().stream().filter(p -> p.get("team").equals(awayTeamName))
-				.findFirst();
-
-		if (homeTeamOptional.isPresent() && awayTeamOptional.isPresent()) {
-			Map<String, Object> homeTeam = homeTeamOptional.get();
-			Map<String, Object> awayTeam = awayTeamOptional.get();
-
-			int homeTeamPos = matchStatTable.getItems().indexOf(homeTeam);
-			int awayTeamPos = matchStatTable.getItems().indexOf(awayTeam);
-			result = Math.abs(homeTeamPos - awayTeamPos);
-		}
-
-		return result;
-	}
+    private static MatchStatisticsController instance;
+    @FXML
+    public DatePicker datePicker;
+    @FXML
+    public ListView<SoccerMatch> MatchesListView;
+
+    private SoccerMatch selectedMatch = null;
+    public Pane MatchPanel;
+    Map<Integer, List<SoccerMatch>> allMatches = new HashMap<>();
+    int currentLeagueId = -1;
+
+    private MatchStatSql database = new MatchStatSql();
+
+    public static MatchStatisticsController getInstance() {
+        if (instance == null) {
+            synchronized (MatchStatisticsController.class) {
+                if (instance == null) {
+                    instance = new MatchStatisticsController();
+                }
+            }
+        }
+        return instance;
+    }
+
+    @Override
+    public void initialize(URL arg0, ResourceBundle arg1) {
+        instance = this;
+
+        MatchesListView.getSelectionModel().selectedItemProperty().addListener((ov, oldValue, newValue) -> {
+            if (newValue != null && !newValue.equals(oldValue)) {
+                ClearSelectedSoccerMatch();
+                UpdateSelectedSoccerMatch(newValue);
+            }
+        });
+
+        datePicker.valueProperty().addListener((ov, oldValue, newValue) -> {
+            if (oldValue != null && !newValue.isEqual(oldValue)) {
+                populateGamesList(newValue);
+            } else if (oldValue == null && newValue != null) {
+                populateGamesList(newValue);
+            }
+        });
+    }
+
+    private void populateGamesList(LocalDate date) {
+        List<SoccerMatch> matches = GuiMysql.getInstance().getPrioMatchesByDate(date.toString());
+
+        MatchesListView.getItems().clear();
+        for (SoccerMatch match : matches) {
+            MatchesListView.getItems().add(match);
+        }
+    }
+
+    private void UpdateSelectedSoccerMatch(SoccerMatch soccerMatch) {
+        selectedMatch = soccerMatch;
+
+        buildSoccerMatchAnalysisPanel(selectedMatch);
+    }
+
+    private void buildSoccerMatchAnalysisPanel(SoccerMatch match) {
+        VBox baseBox = new VBox();
+        int limitNumerOfGames = 10;
+        //baseBox.setBackground(new Background(new BackgroundFill(Color.LIGHTGRAY, CornerRadii.EMPTY, Insets.EMPTY)));
+        HBox topRow = new HBox(10d);
+        HBox bottomRow = new HBox(10d);
+        baseBox.getChildren().add(topRow);
+        baseBox.getChildren().add(bottomRow);
+
+        MatchPanel.getChildren().add(baseBox);
+
+        VBox scoringTotalBoxHome = new VBox();
+        topRow.getChildren().add(scoringTotalBoxHome);
+        scoringTotalBoxHome.getChildren().add(new Label("Result Home - Away goals"));
+        VBox scoringTotalBoxAway = new VBox();
+        topRow.getChildren().add(scoringTotalBoxAway);
+        scoringTotalBoxAway.getChildren().add(new Label("Result Away - Home goals"));
+        VBox resultBoxTotalScore = new VBox();
+        Label resultingLabel = new Label("Result Compare Value");
+        resultBoxTotalScore.getChildren().add(resultingLabel);
+        topRow.getChildren().add(resultBoxTotalScore);
+
+        for (int i = 1; i <= limitNumerOfGames; i++) {
+            HBox box = new HBox(5d);
+            box.getChildren().add(new Label(String.valueOf(i)));
+            int totalGoalResultHome = database.totalGoalResult(match.getHomeTeam().getTeamId(), match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), true, i);
+            box.getChildren().add(new Label(String.valueOf(totalGoalResultHome)));
+            scoringTotalBoxHome.getChildren().add(box);
+
+            HBox boxAway = new HBox(5d);
+            boxAway.getChildren().add(new Label(String.valueOf(i)));
+            int totalGoalResultAway = database.totalGoalResult(match.getAwayTeam().getTeamId(), match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), false, i);
+            boxAway.getChildren().add(new Label(String.valueOf(totalGoalResultAway)));
+            scoringTotalBoxAway.getChildren().add(boxAway);
+
+            OddsStat totalGoalStat = statTotalGoalResult((totalGoalResultHome - totalGoalResultAway), match.getHomeTeam().getTeamLeagueId(), i, match.getGameDate());
+            resultBoxTotalScore.getChildren().add(new Label(String.valueOf(totalGoalResultHome - totalGoalResultAway) +
+                    totalGoalStat.toString() + " (" + totalGoalStat.getAvgGoalsScores() + ")"));
+        }
+
+        VBox goalsScoredHomeAndAwayHome = new VBox();
+        topRow.getChildren().add(goalsScoredHomeAndAwayHome);
+        goalsScoredHomeAndAwayHome.getChildren().add(new Label("Goals Scored Total Home"));
+        VBox goalsScoredHomeAndAwayAway = new VBox();
+        topRow.getChildren().add(goalsScoredHomeAndAwayAway);
+        goalsScoredHomeAndAwayAway.getChildren().add(new Label("Goals Scored Total Away"));
+
+        VBox resultHomeAway = new VBox();
+        resultHomeAway.getChildren().add(new Label("HomeVsAway Compare value"));
+
+        topRow.getChildren().add(resultHomeAway);
+        for (int i = 1; i <= limitNumerOfGames; i++) {
+            HBox box = new HBox(5d);
+            box.getChildren().add(new Label(String.valueOf(i)));
+            float totalGoalResultHomeANDAwayHome = database.totalGoalResultHomeANDAway(match.getHomeTeam().getTeamId(), match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), i);
+            box.getChildren().add(new Label(String.valueOf(totalGoalResultHomeANDAwayHome)));
+            goalsScoredHomeAndAwayHome.getChildren().add(box);
+
+            HBox boxAway = new HBox(5d);
+            boxAway.getChildren().add(new Label(String.valueOf(i)));
+            float totalGoalResultHomeANDAwayAway = database.totalGoalResultHomeANDAway(match.getAwayTeam().getTeamId(), match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), i);
+            boxAway.getChildren().add(new Label(String.valueOf(totalGoalResultHomeANDAwayAway)));
+            goalsScoredHomeAndAwayAway.getChildren().add(boxAway);
+
+            resultHomeAway.getChildren().add(new Label(String.format("%.2f",
+                    totalGoalResultHomeANDAwayHome - totalGoalResultHomeANDAwayAway) + " " +
+                    statSplitGoalResultHomeAndAway(Math.round(totalGoalResultHomeANDAwayHome - totalGoalResultHomeANDAwayAway),
+                            match.getHomeTeam().getTeamLeagueId(), i, match.getGameDate()).toString()));
+        }
+
+        VBox goalsScoredLastXGamesHome = new VBox();
+        bottomRow.getChildren().add(goalsScoredLastXGamesHome);
+        goalsScoredLastXGamesHome.getChildren().add(new Label("Goals Scored Home"));
+        VBox goalsScoredLastXGamesAway = new VBox();
+        bottomRow.getChildren().add(goalsScoredLastXGamesAway);
+        goalsScoredLastXGamesAway.getChildren().add(new Label("Goals Scored Away"));
+
+        VBox goalsScoredLastXGamesCV = new VBox();
+        goalsScoredLastXGamesCV.getChildren().add(new Label("Goals Scored Compare value"));
+
+        bottomRow.getChildren().add(goalsScoredLastXGamesCV);
+        for (int i = 1; i <= limitNumerOfGames; i++) {
+            HBox box = new HBox(5d);
+            box.getChildren().add(new Label(String.valueOf(i)));
+            float goalsScoredLastXGamesHomeValue = database.goalsScoredLastXGames(match.getHomeTeam().getTeamId(), true, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), i);
+            box.getChildren().add(new Label(String.valueOf(goalsScoredLastXGamesHomeValue)));
+            goalsScoredLastXGamesHome.getChildren().add(box);
+
+            HBox boxAway = new HBox(5d);
+            boxAway.getChildren().add(new Label(String.valueOf(i)));
+            float goalsScoredLastXGamesAwayValue = database.goalsScoredLastXGames(match.getAwayTeam().getTeamId(), false, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), i);
+            boxAway.getChildren().add(new Label(String.valueOf(goalsScoredLastXGamesAwayValue)));
+            goalsScoredLastXGamesAway.getChildren().add(boxAway);
+
+            OddsStat oddsStat = statGoalsScoredLastXGames((goalsScoredLastXGamesHomeValue - goalsScoredLastXGamesAwayValue), match.getHomeTeam().getTeamLeagueId(), i, match.getGameDate());
+            goalsScoredLastXGamesCV.getChildren().add(new Label(String.format("%.2f",
+                    goalsScoredLastXGamesHomeValue - goalsScoredLastXGamesAwayValue) + oddsStat.toString()
+                    + " (" + oddsStat.getAvgGoalsScores() + ")"
+            ));
+        }
+
+
+        VBox goalsScoreLastXGamesHomeANDAwayHome = new VBox();
+        bottomRow.getChildren().add(goalsScoreLastXGamesHomeANDAwayHome);
+        goalsScoreLastXGamesHomeANDAwayHome.getChildren().add(new Label("Goals Scored Home/Away Home"));
+        VBox goalsScoreLastXGamesHomeANDAwayAway = new VBox();
+        bottomRow.getChildren().add(goalsScoreLastXGamesHomeANDAwayAway);
+        goalsScoreLastXGamesHomeANDAwayAway.getChildren().add(new Label("Goals Scored Home/Away Away"));
+
+        VBox goalsScoreLastXGamesHomeANDAwayCV = new VBox();
+        goalsScoreLastXGamesHomeANDAwayCV.getChildren().add(new Label("Goals Scored Home/Away Compare value"));
+
+        bottomRow.getChildren().add(goalsScoreLastXGamesHomeANDAwayCV);
+        for (int i = 1; i <= limitNumerOfGames; i++) {
+            HBox box = new HBox(5d);
+            box.getChildren().add(new Label(String.valueOf(i)));
+            float goalsScoreLastXGamesHomeANDAwayHomeValue = database.goalsScoreLastXGamesHomeANDAway(match.getHomeTeam().getTeamId(), match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), i);
+            box.getChildren().add(new Label(String.valueOf(goalsScoreLastXGamesHomeANDAwayHomeValue)));
+            goalsScoreLastXGamesHomeANDAwayHome.getChildren().add(box);
+
+            HBox boxAway = new HBox(5d);
+            boxAway.getChildren().add(new Label(String.valueOf(i)));
+            float goalsScoreLastXGamesHomeANDAwayAwayValue = database.goalsScoreLastXGamesHomeANDAway(match.getAwayTeam().getTeamId(), match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), i);
+            boxAway.getChildren().add(new Label(String.valueOf(goalsScoreLastXGamesHomeANDAwayAwayValue)));
+            goalsScoreLastXGamesHomeANDAwayAway.getChildren().add(boxAway);
+
+            OddsStat statGoalsScoredLastXGamesHomeAndAway = statGoalsScoredLastXGamesHomeAndAway((goalsScoreLastXGamesHomeANDAwayHomeValue - goalsScoreLastXGamesHomeANDAwayAwayValue), match.getHomeTeam().getTeamLeagueId(), i, match.getGameDate());
+            goalsScoreLastXGamesHomeANDAwayCV.getChildren().add(new Label(String.format("%.2f",
+                    goalsScoreLastXGamesHomeANDAwayHomeValue - goalsScoreLastXGamesHomeANDAwayAwayValue) + " " + statGoalsScoredLastXGamesHomeAndAway.toString() + "(" + statGoalsScoredLastXGamesHomeAndAway.getAvgGoalsScores() + ")"));
+        }
+    }
+
+
+    private List<SoccerMatch> getAllMatchesFromLeauge(int leagueId) {
+        if (allMatches.get(leagueId) == null || allMatches.get(leagueId).isEmpty()) {
+            allMatches.put(leagueId, database.getAllMatchesForLeague(leagueId));
+        }
+        return allMatches.get(leagueId);
+    }
+
+    private int getTotalGoalResultsHomeAndAway(int teamId, int leagueId, int limit, String currentDate) {
+        List<SoccerMatch> matches = getAllMatchesFromLeauge(leagueId);
+
+        List<SoccerMatch> matchesBefore = matches.stream().filter(m -> m.getGameDate().isBefore(LocalDateTime.parse(currentDate))).collect(Collectors.toList());
+
+        List<SoccerMatch> teamMatches = matchesBefore.stream().filter(m -> m.getHomeTeam().getTeamId() == teamId || m.getAwayTeam().getTeamId() == teamId).limit(limit).collect(Collectors.toList());
+
+        return calculateTotalGoalResultHomeAndAway(teamId, teamMatches);
+    }
+
+    private static int calculateTotalGoalResultHomeAndAway(int teamId, List<SoccerMatch> teamMatches) {
+        int result = 0;
+        for (SoccerMatch tm : teamMatches) {
+            if (tm.getHomeTeam().getTeamId() == teamId) {
+                result += tm.getHomeScore() - tm.getAwayScore();
+            } else if (tm.getAwayTeam().getTeamId() == teamId) {
+                result += tm.getAwayScore() - tm.getHomeScore();
+            }
+        }
+        return result;
+    }
+
+    private OddsStat statSplitGoalResultHomeAndAway(int value, int league, int limit, LocalDateTime currentDate) {
+        OddsStat stat = new OddsStat();
+
+        for (SoccerMatch sm : getAllMatchesFromLeauge(league)) {
+            List<SoccerMatch> homeTeamMatches = filterSoccerMatchesByTeam(league, currentDate, sm.getHomeTeam(), limit);
+            List<SoccerMatch> awayTeamMatches = filterSoccerMatchesByTeam(league, currentDate, sm.getAwayTeam(), limit);
+
+            int homeTeamValue = calculateTotalGoalResultHomeAndAway(sm.getHomeTeam().getTeamId(), homeTeamMatches);
+            int awayTeamValue = calculateTotalGoalResultHomeAndAway(sm.getAwayTeam().getTeamId(), awayTeamMatches);
+
+            if (homeTeamValue - awayTeamValue == value) {
+                if (sm.getHomeScore() > sm.getAwayScore()) {
+                    stat.addHomeWin();
+                } else if (sm.getHomeScore() == sm.getAwayScore()) {
+                    stat.addDraw();
+                } else if (sm.getAwayScore() > sm.getHomeScore()) {
+                    stat.addAwayWin();
+                }
+            }
+        }
+        return stat;
+    }
+
+    private OddsStat statGoalsScoredLastXGames(float value, int leagueId, int limit, LocalDateTime currentDate) {
+        OddsStat stat = new OddsStat();
+        for (SoccerMatch sm : getAllMatchesFromLeauge(leagueId)) {
+            List<SoccerMatch> homeTeamMatches = filterSoccerMatchesByTeamHomeOrAway(leagueId, currentDate, sm.getHomeTeam(), limit, true);
+            List<SoccerMatch> awayTeamMatches = filterSoccerMatchesByTeamHomeOrAway(leagueId, currentDate, sm.getAwayTeam(), limit, false);
+
+            int goalsScoredHome = homeTeamMatches.stream().mapToInt(SoccerMatch::getHomeScore).sum();
+            int goalsScoredAway = awayTeamMatches.stream().mapToInt(SoccerMatch::getAwayScore).sum();
+
+            if (((float) goalsScoredHome - (float) goalsScoredAway) == value) {
+                if (sm.getHomeScore() > sm.getAwayScore()) {
+                    stat.addHomeWin();
+                } else if (sm.getHomeScore() == sm.getAwayScore()) {
+                    stat.addDraw();
+                } else if (sm.getAwayScore() > sm.getHomeScore()) {
+                    stat.addAwayWin();
+                }
+                stat.addGoalsScored(sm.getHomeScore() + sm.getAwayScore());
+            }
+        }
+        return stat;
+    }
+
+    private OddsStat statGoalsScoredLastXGamesHomeAndAway(float value, int leagueId, int limit, LocalDateTime currentDate) {
+        OddsStat stat = new OddsStat();
+        for (SoccerMatch sm : getAllMatchesFromLeauge(leagueId)) {
+            List<SoccerMatch> homeTeamMatches = filterSoccerMatchesByTeam(leagueId, currentDate, sm.getHomeTeam(), limit);
+            List<SoccerMatch> awayTeamMatches = filterSoccerMatchesByTeam(leagueId, currentDate, sm.getAwayTeam(), limit);
+
+            int homeTeamRes = calculateScoreLastXGamesHomeAndAway(homeTeamMatches, sm.getHomeTeam().getTeamId());
+            int awayTeamRes = calculateScoreLastXGamesHomeAndAway(awayTeamMatches, sm.getAwayTeam().getTeamId());
+            if (((float) homeTeamRes - (float) awayTeamRes) == value) {
+                if (sm.getHomeScore() > sm.getAwayScore()) {
+                    stat.addHomeWin();
+                } else if (sm.getHomeScore() == sm.getAwayScore()) {
+                    stat.addDraw();
+                } else if (sm.getAwayScore() > sm.getHomeScore()) {
+                    stat.addAwayWin();
+                }
+                stat.addGoalsScored(sm.getHomeScore() + sm.getAwayScore());
+            }
+        }
+        return stat;
+    }
+
+    private int calculateScoreLastXGamesHomeAndAway(List<SoccerMatch> teamMatches, int teamId) {
+        int res = 0;
+        for (SoccerMatch sm : teamMatches) {
+            if (sm.getHomeTeam().getTeamId() == teamId) {
+                res += sm.getHomeScore();
+            } else if (sm.getAwayTeam().getTeamId() == teamId) {
+                res += sm.getAwayScore();
+            }
+        }
+
+        return res;
+    }
+
+
+    private OddsStat statTotalGoalResult(int value, int leagueId, int limit, LocalDateTime currentDate) {
+        OddsStat stat = new OddsStat();
+        for (SoccerMatch sm : getAllMatchesFromLeauge(leagueId)) {
+            List<SoccerMatch> homeTeamMatches = filterSoccerMatchesByTeamHomeOrAway(leagueId, currentDate, sm.getHomeTeam(), limit, true);
+            List<SoccerMatch> awayTeamMatches = filterSoccerMatchesByTeamHomeOrAway(leagueId, currentDate, sm.getAwayTeam(), limit, false);
+
+            int homeValue = homeTeamMatches.stream().mapToInt(match -> match.getHomeScore() - match.getAwayScore()).sum();
+            int awayValue = awayTeamMatches.stream().mapToInt(match -> match.getAwayScore() - match.getHomeScore()).sum();
+
+            if ((homeValue - awayValue) == value) {
+                if (sm.getHomeScore() > sm.getAwayScore()) {
+                    stat.addHomeWin();
+                } else if (sm.getHomeScore() == sm.getAwayScore()) {
+                    stat.addDraw();
+                } else if (sm.getAwayScore() > sm.getHomeScore()) {
+                    stat.addAwayWin();
+                }
+                stat.addGoalsScored(sm.getHomeScore() + sm.getAwayScore());
+            }
+        }
+        return stat;
+    }
+
+    private List<SoccerMatch> filterSoccerMatchesByTeamHomeOrAway(int league, LocalDateTime currentDate, Team sm, int limit, boolean homeTeam) {
+        Stream<SoccerMatch> stream = getAllMatchesFromLeauge(league).stream().filter(f -> f.getGameDate().isBefore(currentDate));
+        if (homeTeam) {
+            stream = stream.filter(f -> f.getHomeTeam().getTeamId() == sm.getTeamId());
+        } else {
+            stream = stream.filter(f -> f.getAwayTeam().getTeamId() == sm.getTeamId());
+        }
+        return stream.limit(limit).toList();
+    }
+
+    private List<SoccerMatch> filterSoccerMatchesByTeam(int league, LocalDateTime currentDate, Team sm, int limit) {
+        return getAllMatchesFromLeauge(league).stream()
+                .filter(f -> f.getGameDate().isBefore(currentDate) &&
+                        (f.getHomeTeam().getTeamId() == sm.getTeamId() ||
+                                f.getAwayTeam().getTeamId() == sm.getTeamId()))
+                .limit(limit).toList();
+    }
+
+    private void ClearSelectedSoccerMatch() {
+        MatchPanel.getChildren().clear();
+    }
 }

+ 15 - 31
OddsJavaFx/src/controllers/PastResultsController.java

@@ -1,40 +1,14 @@
 package controllers;
 
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.net.URL;
-import java.text.DecimalFormat;
-import java.time.format.DateTimeFormatter;
-import java.util.AbstractMap.SimpleEntry;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.ResourceBundle;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import org.apache.commons.lang3.NotImplementedException;
-
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
-
 import data.GuiMysql;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.fxml.Initializable;
-import javafx.scene.control.Button;
-import javafx.scene.control.ComboBox;
-import javafx.scene.control.DatePicker;
-import javafx.scene.control.Label;
-import javafx.scene.control.TableCell;
-import javafx.scene.control.TableColumn;
-import javafx.scene.control.TableView;
-import javafx.scene.control.TextArea;
+import javafx.scene.control.*;
 import javafx.scene.control.cell.MapValueFactory;
 import javafx.scene.layout.AnchorPane;
 import javafx.scene.text.Text;
@@ -43,8 +17,18 @@ import objects.Constants;
 import objects.League;
 import objects.SoccerMatch;
 import objects.SoccerMatchAnalysis;
+import org.apache.commons.lang3.NotImplementedException;
 import tests.objects.Standing;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.net.URL;
+import java.text.DecimalFormat;
+import java.time.format.DateTimeFormatter;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.*;
+import java.util.stream.Collectors;
+
 @SuppressWarnings("rawtypes")
 public class PastResultsController implements Initializable {
 
@@ -513,10 +497,10 @@ public class PastResultsController implements Initializable {
                 int homeWinsCount = analysis.winLossRatio(leagueInfo.getWinLossRatio(), true);
                 int awayWindCount = analysis.winLossRatio(leagueInfo.getWinLossRatio(), false);
 
-                int homeWinLossRatioCount = analysis.winLossRatioHomeAndAway(true,
-                        leagueInfo.getWinLossRatioHomeAndAway());
-                int awayWinLossRatioCount = analysis.winLossRatioHomeAndAway(false,
-                        leagueInfo.getWinLossRatioHomeAndAway());
+                int homeWinLossRatioCount = analysis.winLossRatioHomeAndAway(
+                        leagueInfo.getWinLossRatioHomeAndAway(), true);
+                int awayWinLossRatioCount = analysis.winLossRatioHomeAndAway(
+                        leagueInfo.getWinLossRatioHomeAndAway(), false);
 
                 int homeScoringTotal = analysis.scoringTotal(leagueInfo.getScoringTotal(), true);
                 int awayScoringTotal = analysis.scoringTotal(leagueInfo.getScoringTotal(), false);

+ 82 - 316
OddsJavaFx/src/controllers/StrategyTesterController.java

@@ -1,50 +1,65 @@
 package controllers;
 
+import controllers.strategytest.FibonacciStrategy;
+import controllers.strategytest.OneThreeTwoSixStrategy;
+import controllers.strategytest.OneXStrategy;
 import data.GuiMysql;
 import data.MatchStatSql;
+import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.fxml.Initializable;
+import javafx.scene.control.Button;
 import javafx.scene.control.DatePicker;
 import javafx.scene.control.Label;
 import javafx.scene.control.ListView;
 import javafx.scene.layout.HBox;
 import javafx.scene.layout.Pane;
 import javafx.scene.layout.VBox;
-import objects.OddsStat;
 import objects.SoccerMatch;
-import objects.Team;
 
 import java.net.URL;
 import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.ResourceBundle;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
-public class MatchStatisticsController implements Initializable {
+public class StrategyTesterController implements Initializable {
 
-    private static MatchStatisticsController instance;
+    private static StrategyTesterController instance;
     @FXML
     public DatePicker datePicker;
     @FXML
     public ListView<SoccerMatch> MatchesListView;
+    public DatePicker DP_StartDate;
+    public DatePicker DP_EndDate;
+    public Label L_InfoText;
+    public Pane centerPane;
 
-    private SoccerMatch selectedMatch = null;
-    public Pane MatchPanel;
-    Map<Integer, List<SoccerMatch>> allMatches = new HashMap<>();
-    int currentLeagueId = -1;
-
+    @FXML
+    public HBox HBox_testsPanel;
+    public Button btn_go;
+    public VBox oneXStatPanel;
+    public VBox allInPanel;
+    public VBox oneThreeTwoSixPanel;
+    public VBox FibonacciPanel;
+    public VBox KellyFormulaPanel;
+    public VBox DutchingPanel;
+    public VBox MoneyRacePanel;
+    public VBox BetOnDrawPanel;
+    public Label Label_LoadedMatches;
+
+    boolean b_startDateOk = false;
+    boolean b_endDateOk = false;
     private MatchStatSql database = new MatchStatSql();
+    OneXStrategy oneXStrategy = new OneXStrategy();
+    FibonacciStrategy fibonacciStrategy = new FibonacciStrategy();
+
+    private OneThreeTwoSixStrategy oneThreeTwoSixStrategy = new OneThreeTwoSixStrategy();
 
-    public static MatchStatisticsController getInstance() {
+    public static StrategyTesterController getInstance() {
         if (instance == null) {
-            synchronized (MatchStatisticsController.class) {
+            synchronized (StrategyTesterController.class) {
                 if (instance == null) {
-                    instance = new MatchStatisticsController();
+                    instance = new StrategyTesterController();
                 }
             }
         }
@@ -55,323 +70,74 @@ public class MatchStatisticsController implements Initializable {
     public void initialize(URL arg0, ResourceBundle arg1) {
         instance = this;
 
-        MatchesListView.getSelectionModel().selectedItemProperty().addListener((ov, oldValue, newValue) -> {
-            if (newValue != null && !newValue.equals(oldValue)) {
-                ClearSelectedSoccerMatch();
-                UpdateSelectedSoccerMatch(newValue);
-            }
+        DP_StartDate.valueProperty().addListener((observable, oldValue, newValue) -> {
+            checkDatesOk();
         });
 
-        datePicker.valueProperty().addListener((ov, oldValue, newValue) -> {
-            if (oldValue != null && !newValue.isEqual(oldValue)) {
-                populateGamesList(newValue);
-            } else if (oldValue == null && newValue != null) {
-                populateGamesList(newValue);
-            }
+        DP_EndDate.valueProperty().addListener((observable, oldValue, newValue) -> {
+            checkDatesOk();
         });
-    }
-
-    private void populateGamesList(LocalDate date) {
-        List<SoccerMatch> matches = GuiMysql.getInstance().getPrioMatchesByDate(date.toString());
-
-        MatchesListView.getItems().clear();
-        for (SoccerMatch match : matches) {
-            MatchesListView.getItems().add(match);
-        }
-    }
-
-    private void UpdateSelectedSoccerMatch(SoccerMatch soccerMatch) {
-        selectedMatch = soccerMatch;
-
-        buildSoccerMatchAnalysisPanel(selectedMatch);
-    }
-
-    private void buildSoccerMatchAnalysisPanel(SoccerMatch match) {
-        VBox baseBox = new VBox();
-        int limitNumerOfGames = 10;
-        //baseBox.setBackground(new Background(new BackgroundFill(Color.LIGHTGRAY, CornerRadii.EMPTY, Insets.EMPTY)));
-        HBox topRow = new HBox(10d);
-        HBox bottomRow = new HBox(10d);
-        baseBox.getChildren().add(topRow);
-        baseBox.getChildren().add(bottomRow);
-
-        MatchPanel.getChildren().add(baseBox);
-
-        VBox scoringTotalBoxHome = new VBox();
-        topRow.getChildren().add(scoringTotalBoxHome);
-        scoringTotalBoxHome.getChildren().add(new Label("Result Home - Away goals"));
-        VBox scoringTotalBoxAway = new VBox();
-        topRow.getChildren().add(scoringTotalBoxAway);
-        scoringTotalBoxAway.getChildren().add(new Label("Result Away - Home goals"));
-        VBox resultBoxTotalScore = new VBox();
-        Label resultingLabel = new Label("Result Compare Value");
-        resultBoxTotalScore.getChildren().add(resultingLabel);
-        topRow.getChildren().add(resultBoxTotalScore);
-
-        for (int i = 1; i <= limitNumerOfGames; i++) {
-            HBox box = new HBox(5d);
-            box.getChildren().add(new Label(String.valueOf(i)));
-            int totalGoalResultHome = database.totalGoalResult(match.getHomeTeam().getTeamId(), match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), true, i);
-            box.getChildren().add(new Label(String.valueOf(totalGoalResultHome)));
-            scoringTotalBoxHome.getChildren().add(box);
-
-            HBox boxAway = new HBox(5d);
-            boxAway.getChildren().add(new Label(String.valueOf(i)));
-            int totalGoalResultAway = database.totalGoalResult(match.getAwayTeam().getTeamId(), match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), false, i);
-            boxAway.getChildren().add(new Label(String.valueOf(totalGoalResultAway)));
-            scoringTotalBoxAway.getChildren().add(boxAway);
-
-            OddsStat totalGoalStat = statTotalGoalResult((totalGoalResultHome - totalGoalResultAway), match.getHomeTeam().getTeamLeagueId(), i, match.getGameDate());
-            resultBoxTotalScore.getChildren().add(new Label(String.valueOf(totalGoalResultHome - totalGoalResultAway) +
-                    totalGoalStat.toString() + " (" + totalGoalStat.getAvgGoalsScores() + ")"));
-        }
-
-        VBox goalsScoredHomeAndAwayHome = new VBox();
-        topRow.getChildren().add(goalsScoredHomeAndAwayHome);
-        goalsScoredHomeAndAwayHome.getChildren().add(new Label("Goals Scored Total Home"));
-        VBox goalsScoredHomeAndAwayAway = new VBox();
-        topRow.getChildren().add(goalsScoredHomeAndAwayAway);
-        goalsScoredHomeAndAwayAway.getChildren().add(new Label("Goals Scored Total Away"));
-
-        VBox resultHomeAway = new VBox();
-        resultHomeAway.getChildren().add(new Label("HomeVsAway Compare value"));
-
-        topRow.getChildren().add(resultHomeAway);
-        for (int i = 1; i <= limitNumerOfGames; i++) {
-            HBox box = new HBox(5d);
-            box.getChildren().add(new Label(String.valueOf(i)));
-            float totalGoalResultHomeANDAwayHome = database.totalGoalResultHomeANDAway(match.getHomeTeam().getTeamId(), match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), i);
-            box.getChildren().add(new Label(String.valueOf(totalGoalResultHomeANDAwayHome)));
-            goalsScoredHomeAndAwayHome.getChildren().add(box);
-
-            HBox boxAway = new HBox(5d);
-            boxAway.getChildren().add(new Label(String.valueOf(i)));
-            float totalGoalResultHomeANDAwayAway = database.totalGoalResultHomeANDAway(match.getAwayTeam().getTeamId(), match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), i);
-            boxAway.getChildren().add(new Label(String.valueOf(totalGoalResultHomeANDAwayAway)));
-            goalsScoredHomeAndAwayAway.getChildren().add(boxAway);
-
-            resultHomeAway.getChildren().add(new Label(String.format("%.2f",
-                    totalGoalResultHomeANDAwayHome - totalGoalResultHomeANDAwayAway) + " " +
-                    statSplitGoalResultHomeAndAway(Math.round(totalGoalResultHomeANDAwayHome - totalGoalResultHomeANDAwayAway),
-                            match.getHomeTeam().getTeamLeagueId(), i, match.getGameDate()).toString()));
-        }
-
-        VBox goalsScoredLastXGamesHome = new VBox();
-        bottomRow.getChildren().add(goalsScoredLastXGamesHome);
-        goalsScoredLastXGamesHome.getChildren().add(new Label("Goals Scored Home"));
-        VBox goalsScoredLastXGamesAway = new VBox();
-        bottomRow.getChildren().add(goalsScoredLastXGamesAway);
-        goalsScoredLastXGamesAway.getChildren().add(new Label("Goals Scored Away"));
-
-        VBox goalsScoredLastXGamesCV = new VBox();
-        goalsScoredLastXGamesCV.getChildren().add(new Label("Goals Scored Compare value"));
-
-        bottomRow.getChildren().add(goalsScoredLastXGamesCV);
-        for (int i = 1; i <= limitNumerOfGames; i++) {
-            HBox box = new HBox(5d);
-            box.getChildren().add(new Label(String.valueOf(i)));
-            float goalsScoredLastXGamesHomeValue = database.goalsScoredLastXGames(match.getHomeTeam().getTeamId(), true, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), i);
-            box.getChildren().add(new Label(String.valueOf(goalsScoredLastXGamesHomeValue)));
-            goalsScoredLastXGamesHome.getChildren().add(box);
-
-            HBox boxAway = new HBox(5d);
-            boxAway.getChildren().add(new Label(String.valueOf(i)));
-            float goalsScoredLastXGamesAwayValue = database.goalsScoredLastXGames(match.getAwayTeam().getTeamId(), false, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), i);
-            boxAway.getChildren().add(new Label(String.valueOf(goalsScoredLastXGamesAwayValue)));
-            goalsScoredLastXGamesAway.getChildren().add(boxAway);
-
-            OddsStat oddsStat = statGoalsScoredLastXGames((goalsScoredLastXGamesHomeValue - goalsScoredLastXGamesAwayValue), match.getHomeTeam().getTeamLeagueId(), i, match.getGameDate());
-            goalsScoredLastXGamesCV.getChildren().add(new Label(String.format("%.2f",
-                    goalsScoredLastXGamesHomeValue - goalsScoredLastXGamesAwayValue) + oddsStat.toString()
-                    + " (" + oddsStat.getAvgGoalsScores() + ")"
-            ));
-        }
-
-
-        VBox goalsScoreLastXGamesHomeANDAwayHome = new VBox();
-        bottomRow.getChildren().add(goalsScoreLastXGamesHomeANDAwayHome);
-        goalsScoreLastXGamesHomeANDAwayHome.getChildren().add(new Label("Goals Scored Home/Away Home"));
-        VBox goalsScoreLastXGamesHomeANDAwayAway = new VBox();
-        bottomRow.getChildren().add(goalsScoreLastXGamesHomeANDAwayAway);
-        goalsScoreLastXGamesHomeANDAwayAway.getChildren().add(new Label("Goals Scored Home/Away Away"));
-
-        VBox goalsScoreLastXGamesHomeANDAwayCV = new VBox();
-        goalsScoreLastXGamesHomeANDAwayCV.getChildren().add(new Label("Goals Scored Home/Away Compare value"));
-
-        bottomRow.getChildren().add(goalsScoreLastXGamesHomeANDAwayCV);
-        for (int i = 1; i <= limitNumerOfGames; i++) {
-            HBox box = new HBox(5d);
-            box.getChildren().add(new Label(String.valueOf(i)));
-            float goalsScoreLastXGamesHomeANDAwayHomeValue = database.goalsScoreLastXGamesHomeANDAway(match.getHomeTeam().getTeamId(), match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), i);
-            box.getChildren().add(new Label(String.valueOf(goalsScoreLastXGamesHomeANDAwayHomeValue)));
-            goalsScoreLastXGamesHomeANDAwayHome.getChildren().add(box);
-
-            HBox boxAway = new HBox(5d);
-            boxAway.getChildren().add(new Label(String.valueOf(i)));
-            float goalsScoreLastXGamesHomeANDAwayAwayValue = database.goalsScoreLastXGamesHomeANDAway(match.getAwayTeam().getTeamId(), match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE), i);
-            boxAway.getChildren().add(new Label(String.valueOf(goalsScoreLastXGamesHomeANDAwayAwayValue)));
-            goalsScoreLastXGamesHomeANDAwayAway.getChildren().add(boxAway);
-
-            OddsStat statGoalsScoredLastXGamesHomeAndAway = statGoalsScoredLastXGamesHomeAndAway((goalsScoreLastXGamesHomeANDAwayHomeValue - goalsScoreLastXGamesHomeANDAwayAwayValue), match.getHomeTeam().getTeamLeagueId(), i, match.getGameDate());
-            goalsScoreLastXGamesHomeANDAwayCV.getChildren().add(new Label(String.format("%.2f",
-                    goalsScoreLastXGamesHomeANDAwayHomeValue - goalsScoreLastXGamesHomeANDAwayAwayValue) + " " + statGoalsScoredLastXGamesHomeAndAway.toString() + "(" + statGoalsScoredLastXGamesHomeAndAway.getAvgGoalsScores() + ")"));
-        }
-    }
-
-
-    private List<SoccerMatch> getAllMatchesFromLeauge(int leagueId) {
-        if (allMatches.get(leagueId) == null || allMatches.get(leagueId).isEmpty()) {
-            allMatches.put(leagueId, database.getAllMatchesForLeague(leagueId));
-        }
-        return allMatches.get(leagueId);
-    }
 
-    private int getTotalGoalResultsHomeAndAway(int teamId, int leagueId, int limit, String currentDate) {
-        List<SoccerMatch> matches = getAllMatchesFromLeauge(leagueId);
+        DP_EndDate.setValue(LocalDate.now());
 
-        List<SoccerMatch> matchesBefore = matches.stream().filter(m -> m.getGameDate().isBefore(LocalDateTime.parse(currentDate))).collect(Collectors.toList());
-
-        List<SoccerMatch> teamMatches = matchesBefore.stream().filter(m -> m.getHomeTeam().getTeamId() == teamId || m.getAwayTeam().getTeamId() == teamId).limit(limit).collect(Collectors.toList());
-
-        return calculateTotalGoalResultHomeAndAway(teamId, teamMatches);
+        oneXStatPanel.getChildren().add(oneXStrategy);
+        oneThreeTwoSixPanel.getChildren().add(oneThreeTwoSixStrategy);
+        FibonacciPanel.getChildren().add(fibonacciStrategy);
     }
 
-    private static int calculateTotalGoalResultHomeAndAway(int teamId, List<SoccerMatch> teamMatches) {
-        int result = 0;
-        for (SoccerMatch tm : teamMatches) {
-            if (tm.getHomeTeam().getTeamId() == teamId) {
-                result += tm.getHomeScore() - tm.getAwayScore();
-            } else if (tm.getAwayTeam().getTeamId() == teamId) {
-                result += tm.getAwayScore() - tm.getHomeScore();
-            }
+    private void checkDatesOk() {
+        b_startDateOk = true;
+        b_endDateOk = true;
+        if (DP_StartDate.getValue() == null) {
+            b_startDateOk = false;
+            L_InfoText.setText("Start date cannot be empty");
+            return;
         }
-        return result;
-    }
-
-    private OddsStat statSplitGoalResultHomeAndAway(int value, int league, int limit, LocalDateTime currentDate) {
-        OddsStat stat = new OddsStat();
-
-        for (SoccerMatch sm : getAllMatchesFromLeauge(league)) {
-            List<SoccerMatch> homeTeamMatches = filterSoccerMatchesByTeam(league, currentDate, sm.getHomeTeam(), limit);
-            List<SoccerMatch> awayTeamMatches = filterSoccerMatchesByTeam(league, currentDate, sm.getAwayTeam(), limit);
-
-            int homeTeamValue = calculateTotalGoalResultHomeAndAway(sm.getHomeTeam().getTeamId(), homeTeamMatches);
-            int awayTeamValue = calculateTotalGoalResultHomeAndAway(sm.getAwayTeam().getTeamId(), awayTeamMatches);
-
-            if (homeTeamValue - awayTeamValue == value) {
-                if (sm.getHomeScore() > sm.getAwayScore()) {
-                    stat.addHomeWin();
-                } else if (sm.getHomeScore() == sm.getAwayScore()) {
-                    stat.addDraw();
-                } else if (sm.getAwayScore() > sm.getHomeScore()) {
-                    stat.addAwayWin();
-                }
-            }
+        if (DP_EndDate.getValue() == null) {
+            b_endDateOk = false;
+            L_InfoText.setText("End date cannot be empty");
+            return;
         }
-        return stat;
-    }
-
-    private OddsStat statGoalsScoredLastXGames(float value, int leagueId, int limit, LocalDateTime currentDate) {
-        OddsStat stat = new OddsStat();
-        for (SoccerMatch sm : getAllMatchesFromLeauge(leagueId)) {
-            List<SoccerMatch> homeTeamMatches = filterSoccerMatchesByTeamHomeOrAway(leagueId, currentDate, sm.getHomeTeam(), limit, true);
-            List<SoccerMatch> awayTeamMatches = filterSoccerMatchesByTeamHomeOrAway(leagueId, currentDate, sm.getAwayTeam(), limit, false);
-
-            int goalsScoredHome = homeTeamMatches.stream().mapToInt(SoccerMatch::getHomeScore).sum();
-            int goalsScoredAway = awayTeamMatches.stream().mapToInt(SoccerMatch::getAwayScore).sum();
 
-            if (((float) goalsScoredHome - (float) goalsScoredAway) == value) {
-                if (sm.getHomeScore() > sm.getAwayScore()) {
-                    stat.addHomeWin();
-                } else if (sm.getHomeScore() == sm.getAwayScore()) {
-                    stat.addDraw();
-                } else if (sm.getAwayScore() > sm.getHomeScore()) {
-                    stat.addAwayWin();
-                }
-                stat.addGoalsScored(sm.getHomeScore() + sm.getAwayScore());
-            }
+        if (DP_StartDate.getValue().isAfter(DP_EndDate.getValue())) {
+            L_InfoText.setText("Start date cannot be after end date");
+            b_startDateOk = false;
+            b_endDateOk = false;
         }
-        return stat;
-    }
-
-    private OddsStat statGoalsScoredLastXGamesHomeAndAway(float value, int leagueId, int limit, LocalDateTime currentDate) {
-        OddsStat stat = new OddsStat();
-        for (SoccerMatch sm : getAllMatchesFromLeauge(leagueId)) {
-            List<SoccerMatch> homeTeamMatches = filterSoccerMatchesByTeam(leagueId, currentDate, sm.getHomeTeam(), limit);
-            List<SoccerMatch> awayTeamMatches = filterSoccerMatchesByTeam(leagueId, currentDate, sm.getAwayTeam(), limit);
-
-            int homeTeamRes = calculateScoreLastXGamesHomeAndAway(homeTeamMatches, sm.getHomeTeam().getTeamId());
-            int awayTeamRes = calculateScoreLastXGamesHomeAndAway(awayTeamMatches, sm.getAwayTeam().getTeamId());
-            if (((float) homeTeamRes - (float) awayTeamRes) == value) {
-                if (sm.getHomeScore() > sm.getAwayScore()) {
-                    stat.addHomeWin();
-                } else if (sm.getHomeScore() == sm.getAwayScore()) {
-                    stat.addDraw();
-                } else if (sm.getAwayScore() > sm.getHomeScore()) {
-                    stat.addAwayWin();
-                }
-                stat.addGoalsScored(sm.getHomeScore() + sm.getAwayScore());
-            }
-        }
-        return stat;
-    }
 
-    private int calculateScoreLastXGamesHomeAndAway(List<SoccerMatch> teamMatches, int teamId) {
-        int res = 0;
-        for (SoccerMatch sm : teamMatches) {
-            if (sm.getHomeTeam().getTeamId() == teamId) {
-                res += sm.getHomeScore();
-            } else if (sm.getAwayTeam().getTeamId() == teamId) {
-                res += sm.getAwayScore();
-            }
-        }
+        if (b_startDateOk && b_endDateOk) {
+            L_InfoText.setDisable(true);
+            L_InfoText.setVisible(false);
+            HBox_testsPanel.setDisable(false);
+            HBox_testsPanel.setVisible(true);
+            btn_go.setDisable(false);
+            btn_go.setVisible(true);
 
-        return res;
-    }
-
-
-    private OddsStat statTotalGoalResult(int value, int leagueId, int limit, LocalDateTime currentDate) {
-        OddsStat stat = new OddsStat();
-        for (SoccerMatch sm : getAllMatchesFromLeauge(leagueId)) {
-            List<SoccerMatch> homeTeamMatches = filterSoccerMatchesByTeamHomeOrAway(leagueId, currentDate, sm.getHomeTeam(), limit, true);
-            List<SoccerMatch> awayTeamMatches = filterSoccerMatchesByTeamHomeOrAway(leagueId, currentDate, sm.getAwayTeam(), limit, false);
+            getMatches();
+        } else {
+            L_InfoText.setDisable(false);
+            L_InfoText.setVisible(true);
 
-            int homeValue = homeTeamMatches.stream().mapToInt(match -> match.getHomeScore() - match.getAwayScore()).sum();
-            int awayValue = awayTeamMatches.stream().mapToInt(match -> match.getAwayScore() - match.getHomeScore()).sum();
+            HBox_testsPanel.setDisable(true);
+            HBox_testsPanel.setVisible(false);
 
-            if ((homeValue - awayValue) == value) {
-                if (sm.getHomeScore() > sm.getAwayScore()) {
-                    stat.addHomeWin();
-                } else if (sm.getHomeScore() == sm.getAwayScore()) {
-                    stat.addDraw();
-                } else if (sm.getAwayScore() > sm.getHomeScore()) {
-                    stat.addAwayWin();
-                }
-                stat.addGoalsScored(sm.getHomeScore() + sm.getAwayScore());
-            }
-        }
-        return stat;
-    }
-
-    private List<SoccerMatch> filterSoccerMatchesByTeamHomeOrAway(int league, LocalDateTime currentDate, Team sm, int limit, boolean homeTeam) {
-        Stream<SoccerMatch> stream = getAllMatchesFromLeauge(league).stream().filter(f -> f.getGameDate().isBefore(currentDate));
-        if (homeTeam) {
-            stream = stream.filter(f -> f.getHomeTeam().getTeamId() == sm.getTeamId());
-        } else {
-            stream = stream.filter(f -> f.getAwayTeam().getTeamId() == sm.getTeamId());
+            btn_go.setDisable(true);
+            btn_go.setVisible(false);
         }
-        return stream.limit(limit).toList();
     }
 
-    private List<SoccerMatch> filterSoccerMatchesByTeam(int league, LocalDateTime currentDate, Team sm, int limit) {
-        return getAllMatchesFromLeauge(league).stream()
-                .filter(f -> f.getGameDate().isBefore(currentDate) &&
-                        (f.getHomeTeam().getTeamId() == sm.getTeamId() ||
-                                f.getAwayTeam().getTeamId() == sm.getTeamId()))
-                .limit(limit).toList();
+    private void getMatches() {
+        List<SoccerMatch> matches = GuiMysql.getInstance().getPrioMatches(DP_StartDate.getValue().toString(), DP_EndDate.getValue().toString());
+        Label_LoadedMatches.setText( String.valueOf(matches.size()) );
+        oneXStrategy.setMatches(matches);
+        oneThreeTwoSixStrategy.setMatches(matches);
+        fibonacciStrategy.setMatches(matches);
     }
 
-    private void ClearSelectedSoccerMatch() {
-        MatchPanel.getChildren().clear();
+    public void runTests(ActionEvent actionEvent) {
+        fibonacciStrategy.reset();
+        //oneXStrategy.runTest();
+        //oneThreeTwoSixStrategy.runTest();
+        fibonacciStrategy.runTest();
     }
 }

+ 24 - 24
OddsJavaFx/src/controllers/StryktipsetController.java

@@ -20,6 +20,7 @@ import java.net.URL;
 import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 
 @SuppressWarnings("rawtypes")
@@ -125,26 +126,26 @@ public class StryktipsetController implements Initializable {
 
         GuiMysql db = GuiMysql.getInstance();
         for (SoccerMatchAnalysis match : matches) {
-            League l = db.getLeagueInfo(match.getHomeTeam().getTeamLeagueId());
+            League leagueInfo = db.getLeagueInfo(match.getHomeTeam().getTeamLeagueId());
             Percentages percentages = new Percentages();
-            int homeScore = match.scoringTotal(l.getScoringTotal(), true);
-            int awayScore = match.scoringTotal(l.getScoringTotal(), false);
+            int homeScore = match.scoringTotal(leagueInfo.getScoringTotal(), true);
+            int awayScore = match.scoringTotal(leagueInfo.getScoringTotal(), false);
 
-            db.getTotalGoalStat(percentages, l.getLeagueId(),l.getScoringTotal(),
+            db.getTotalGoalStat(percentages, leagueInfo.getLeagueId(), leagueInfo.getScoringTotal(),
                     homeScore - awayScore);
 
-            db.getScoringDiffLastGames(percentages, l.getLeagueId(), l.getScoringDiffLastGame(),
-                    match.getScoringDiffLastGames(l.getScoringDiffLastGame()));
+            db.getScoringDiffLastGames(percentages, leagueInfo.getLeagueId(), leagueInfo.getScoringDiffLastGame(),
+                    match.getScoringDiffLastGames(leagueInfo.getScoringDiffLastGame()));
 
-            int winLossHAHome = match.winLossRatioHomeAndAway(true, l.getWinLossRatioHomeAndAway());
-            int winLossHAAway = match.winLossRatioHomeAndAway(false, l.getWinLossRatioHomeAndAway());
-            db.getWinLossRatioHomeAndAwayStatistics(percentages, l.getLeagueId(), l.getWinLossRatioHomeAndAway(),
-                    winLossHAHome-winLossHAAway);
+            int winLossHAHome = match.winLossRatioHomeAndAway(leagueInfo.getWinLossRatioHomeAndAway(), true);
+            int winLossHAAway = match.winLossRatioHomeAndAway(leagueInfo.getWinLossRatioHomeAndAway(), false);
+            db.getWinLossRatioHomeAndAwayStatistics(percentages, leagueInfo.getLeagueId(), leagueInfo.getWinLossRatioHomeAndAway(),
+                    winLossHAHome - winLossHAAway);
 
-            int winLossHome = match.winLossRatio(l.getWinLossRatio(), true);
-            int winLossAway = match.winLossRatio(l.getWinLossRatio(), false);
-            match.winLossRatio(l.getWinLossRatio(), false);
-            db.getWinLossRatioStatisticsGames(percentages,l.getLeagueId(),l.getWinLossRatio(),winLossHome-winLossAway);
+            int winLossHome = match.winLossRatio(leagueInfo.getWinLossRatio(), true);
+            int winLossAway = match.winLossRatio(leagueInfo.getWinLossRatio(), false);
+            match.winLossRatio(leagueInfo.getWinLossRatio(), false);
+            db.getWinLossRatioStatisticsGames(percentages, leagueInfo.getLeagueId(), leagueInfo.getWinLossRatio(), winLossHome - winLossAway);
 
             match.setPercentages(percentages.getCalculation());
         }
@@ -169,7 +170,7 @@ public class StryktipsetController implements Initializable {
             match.setScoringDiffValue(match.getScoringDiffLastGames(info.getScoringDiffLastGame()));
             match.setScoringTotal(match.scoringTotal(info.getScoringTotal(), true) - match.scoringTotal(info.getScoringTotal(), false));
             match.setWinCount(match.winLossRatio(info.getWinLossRatio(), true) - match.winLossRatio(info.getWinLossRatio(), false));
-            match.setWinLossRatio(match.winLossRatioHomeAndAway(true, info.getWinLossRatioHomeAndAway()) - match.winLossRatioHomeAndAway(false, info.getWinLossRatioHomeAndAway()));
+            match.setWinLossRatio(match.winLossRatioHomeAndAway(info.getWinLossRatioHomeAndAway(), true) - match.winLossRatioHomeAndAway(info.getWinLossRatioHomeAndAway(), false));
         }
 
         addMatchesToTable(matches);
@@ -194,19 +195,18 @@ public class StryktipsetController implements Initializable {
 
             System.out.println("Starting " + i++ + "/" + prioLeagues.size() + " " + LocalDateTime.now() + " with " +
                     l.getLeagueName());
-/*            GuiMysql.getInstance().calculateWinLossRatioHomeAndAwayStat(l.getLeagueId(),
-                    l.getWinLossRatioHomeAndAway()); */
-GuiMysql.getInstance().addScoringDiffStatistics(l.getLeagueId(), l.getScoringDiffLastGame());
-/*
-                GuiMysql.getInstance().calculateWinLossRatioStat(l.getLeagueId(),
+            GuiMysql.getInstance().calculateWinLossRatioHomeAndAwayStat(l.getLeagueId(),
                     l.getWinLossRatioHomeAndAway());
-                    */
+            GuiMysql.getInstance().addScoringDiffStatistics(l.getLeagueId(), l.getScoringDiffLastGame());
+
+            GuiMysql.getInstance().calculateWinLossRatioStat(l.getLeagueId(),
+                    l.getWinLossRatioHomeAndAway());
+
 
-            /*
             List<SoccerMatchAnalysis> matches = GuiMysql.getInstance().getSoccerMatchesWithGoalStats(l.getLeagueId(),
                     LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE), l.getScoringTotal());
-            System.out.println("Finished " + LocalDateTime.now()+ " with " + l.getLeagueName());
-            */
+            System.out.println("Finished " + LocalDateTime.now() + " with " + l.getLeagueName());
+
         }
     }
 }

+ 22 - 40
OddsJavaFx/src/controllers/TestsController.java

@@ -1,18 +1,7 @@
 package controllers;
 
-import java.net.URL;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.AbstractMap.SimpleEntry;
-import java.util.List;
-import java.util.Optional;
-import java.util.ResourceBundle;
-
-import org.eclipse.jetty.util.log.Log;
-
 import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
-
 import data.GuiMysql;
 import javafx.application.Platform;
 import javafx.collections.FXCollections;
@@ -20,33 +9,21 @@ import javafx.collections.ObservableList;
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.fxml.Initializable;
-import javafx.scene.control.Button;
-import javafx.scene.control.ComboBox;
-import javafx.scene.control.DatePicker;
-import javafx.scene.control.ScrollPane;
-import javafx.scene.control.TextField;
+import javafx.scene.control.*;
 import javafx.scene.layout.AnchorPane;
 import javafx.scene.layout.Priority;
 import javafx.scene.layout.VBox;
 import objects.League;
+import org.eclipse.jetty.util.log.Log;
 import parser.OddsPortal;
-import tests.AddedScoringTest;
-import tests.AnalysisBettDrawTester;
-import tests.AnalysisBettTester;
-import tests.AwayTeamWinTest;
-import tests.AwayTests2;
-import tests.BetOnDifference;
-import tests.DrawTests2;
-import tests.FibonacciDrawTest;
-import tests.HomeDrawAwayTest;
-import tests.HomeTeamWinTest;
-import tests.HomeTests2;
-import tests.LastResultsTest;
-import tests.LeagueTablePositionTest;
-import tests.PrioCountriesAll;
-import tests.RelevanceTest;
-import tests.TestClass;
-import tests.recalcTest;
+import tests.*;
+
+import java.net.URL;
+import java.time.LocalDate;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.List;
+import java.util.Optional;
+import java.util.ResourceBundle;
 
 public class TestsController implements Initializable {
 
@@ -148,7 +125,7 @@ public class TestsController implements Initializable {
 
     @FXML
     private void analysisDrawTests() {
-        final TestClass test = new AnalysisBettDrawTester();
+        final TestClass test = new AnalysisBettDrawTest();
         test.setup(date.getValue().toString(), Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), -1.0f,
                 -1, GuiMysql.getInstance().getSportId("soccer"),
                 getCountryIdFromSelector(), getLeagueIdFromSelector());
@@ -158,7 +135,7 @@ public class TestsController implements Initializable {
 
     @FXML
     private void analysisTets() {
-        final TestClass test = new AnalysisBettTester();
+        final TestClass test = new AnalysisBettTest();
 
         test.setup(date.getValue().toString(), Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), -1.0f,
                 -1, GuiMysql.getInstance().getSportId("soccer"),
@@ -180,7 +157,7 @@ public class TestsController implements Initializable {
 
     @FXML
     private void awayTestAction() {
-        final AwayTests2 test = new AwayTests2();
+        final Away2Test test = new Away2Test();
 
         test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()),
                 Integer.valueOf(getLookback()),
@@ -221,7 +198,7 @@ public class TestsController implements Initializable {
 
     @FXML
     private void drawTestAction() {
-        final DrawTests2 test = new DrawTests2();
+        final Draw2Tests test = new Draw2Tests();
 
         test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()),
                 Integer.valueOf(getLookback()),
@@ -319,7 +296,7 @@ public class TestsController implements Initializable {
 
     @FXML
     private void goalDiffTest() {
-        final TestClass test = new BetOnDifference();
+        final TestClass test = new BetOnDifferenceTest();
 
         test.setup(date.getValue().toString(), Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), -1.0f,
                 -1, GuiMysql.getInstance().getSportId("soccer"),
@@ -352,7 +329,7 @@ public class TestsController implements Initializable {
 
     @FXML
     private void homeTestAction() {
-        final HomeTests2 test = new HomeTests2();
+        final Home2Test test = new Home2Test();
 
         test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()),
                 Integer.valueOf(getLookback()),
@@ -430,7 +407,7 @@ public class TestsController implements Initializable {
 
     @FXML
     private void topLeaguesTestAction() {
-        final PrioCountriesAll prioCountriesAll = new PrioCountriesAll();
+        final PrioCountriesAllTest prioCountriesAll = new PrioCountriesAllTest();
         prioCountriesAll.runTest();
     }
 
@@ -450,4 +427,9 @@ public class TestsController implements Initializable {
                     + " took " + new java.util.Date(System.currentTimeMillis() + (endTime - startTime)));
         }
     }
+
+    public void runXBestGamesTest(ActionEvent actionEvent) {
+        XBestRatedGamesBettingTest xBestRatedGamesBettingTest = new XBestRatedGamesBettingTest();
+        xBestRatedGamesBettingTest.runTest();
+    }
 }

+ 234 - 1
OddsJavaFx/src/controllers/strategytest/FibonacciStrategy.java

@@ -1,2 +1,235 @@
-package controllers.strategytest;public class FibonacciStrategy {
+package controllers.strategytest;
+
+import components.FloatStatRow;
+import components.IntTableStatRow;
+import components.NumberStatRow;
+import interfaces.strategytest.BettingStrategyInterface;
+import javafx.scene.layout.VBox;
+import objects.SoccerMatch;
+import objects.SoccerMatchAnalysis;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * The basic concept of betting according to the Fibonacci sequence is simple: bet on a tie.
+ If you lose, just bet on the next tie according to a certain key and start increasing your stake.
+
+ *
+ * It is important that the odds for the tie are above 2.62 (more precisely: 2.618);
+ * luckily for those who want to employ this strategy, there are many tie bets for this minimum odds.
+ The higher the rate, the better.
+
+ *
+ * Fibonacci Betting Strategy
+ * Betting after Fibonacci
+ * If you lose, you simply bet the next tie after a Fibonacci sequence.
+ It is a sequence of numbers in which the sum of two consecutive numbers results in the next number, making the Fibonacci sequence an infinite sequence of natural numbers.
+ You can find more information about the Fibonacci sequence on Wikipedia.
+
+ *
+ * Fibonacci numbers
+ * The Fibonacci sequence
+ * So if you start betting with 1 € on the first draw with odds> 2.
+62 and lose, then the next time you bet 1 € again, then 2 €, then 3 €, then 5 €, then 8 €, then 13 € and so on.
+
+ *
+ * It is mathematically understandable that every profit that you will achieve with this bet will offset the previous losses and you will even make a net profit.
+
+ *
+ * An example of the Fibonacci bet
+ *
+ * Let’s take the example of the situation where you lose ten times in a row and win your bet the eleventh time.
+ In this case, you have already gambled away 143 € and finally successfully placed the eleventh number in the Fibonacci sequence, 144, on a bet.
+ If we now assume that the successful bet had odds of @ 2.
+80, you win 403.
+20 €.
+ You have wagered a total of 287 €, making your net profit 116.
+20 €.
+
+ *
+ * The disadvantage of this strategy is also obvious.
+ Assuming you lose not ten bets in a row, but twenty, then you would have already lost 16,910 € in stakes.
+ This is a huge bankroll, which you should of course never risk for such a betting sequence.
+ You can find more about this in our explanations on bankroll management.
+
+ */
+public class FibonacciStrategy extends VBox implements BettingStrategyInterface {
+
+    public static final String NAME = "Fibonacci";
+    List<SoccerMatch> matches;
+    private FloatStatRow betAmount;
+    private FloatStatRow wonLossBankStatRow;
+    private NumberStatRow sequencesPlayedStatRow;
+    private IntTableStatRow resultStatRow;
+
+    private final int maxActiveFibonacciSequences = 4;
+    private final List<FibonacciSequence> fibonacciSequences = new ArrayList<>();
+    private NumberStatRow sequencesWonStatRow;
+
+    public FibonacciStrategy() {
+        super();
+        buildSettingsGuiPanel();
+        buildStatGuiPanel();
+        buildMatchSummaryPanel();
+    }
+
+    @Override
+    public void setMatches(List<SoccerMatch> matches) {
+        this.matches = matches;
+    }
+
+    @Override
+    public void buildSettingsGuiPanel() {
+        betAmount = new FloatStatRow("Bet Amount", 10f);
+        this.getChildren().add(betAmount);
+    }
+
+    @Override
+    public void buildStatGuiPanel() {
+        sequencesPlayedStatRow = new NumberStatRow("Number of sequences played", 0);
+        sequencesWonStatRow = new NumberStatRow("Number of sequences won", 0);
+        resultStatRow = new IntTableStatRow("Longest sequence without win");
+
+        wonLossBankStatRow = new FloatStatRow("Amount won or lost", 0f);
+
+        this.getChildren().add(sequencesPlayedStatRow);
+        this.getChildren().add(sequencesWonStatRow);
+        this.getChildren().add(resultStatRow);
+        this.getChildren().add(wonLossBankStatRow);
+    }
+
+    @Override
+    public void buildMatchSummaryPanel() {
+        // Empty for now
+    }
+
+    @Override
+    public void runTest() {
+
+        float lowestBankAmount = 0f;
+
+        for (int i = 0; i < matches.size(); i++) {
+            SoccerMatch m = matches.get(i);
+            List<SoccerMatch> soccerMatches = filterTodaysMatches(matches, m);
+
+            List<SoccerMatch> sortedMatchList = sortMatchesOnBetPotential(soccerMatches);
+
+            for (SoccerMatch match : sortedMatchList) {
+                boolean removeSequence = false;
+                String shouldBetOn = shouldBetOn(match);
+                FibonacciSequence activeSequence = null;
+                if (shouldBetOn.equals("X")) {
+                    Optional<FibonacciSequence> fibSeq = fibonacciSequences.stream().filter(fs -> !fs.containsMatchFromSameDate(match)).findFirst();
+                    if (fibSeq.isPresent()) {
+                        // Add to current sequence
+                        activeSequence = fibSeq.get();
+                        if (activeSequence.bets.size() + 1 > FibonacciSequence.fibonacciSequence.size()) {
+                            System.out.println("System FAILED " + match.getGameDate() + " lost " + activeSequence.totalBetValue + " current bank " + wonLossBankStatRow.getValue());
+                            System.out.println("Lowest bank amount " + lowestBankAmount);
+                            removeSequence = true;
+                        } else {
+                            activeSequence.addBet(match);
+                            wonLossBankStatRow.decreaseValue(activeSequence.currentBetValue);
+                            if (wonLossBankStatRow.getValue() < lowestBankAmount) {
+                                lowestBankAmount = wonLossBankStatRow.getValue();
+                            }
+                        }
+                    } else {
+                        // Start new if not at max active sequences
+                        if (fibonacciSequences.size() < maxActiveFibonacciSequences) {
+                            activeSequence = new FibonacciSequence(match);
+                            sequencesPlayedStatRow.increaseValue();
+                            wonLossBankStatRow.decreaseValue(activeSequence.currentBetValue);
+                            fibonacciSequences.add(activeSequence);
+                            if (wonLossBankStatRow.getValue() < lowestBankAmount) {
+                                lowestBankAmount = wonLossBankStatRow.getValue();
+                            }
+                        } else {
+                            // Should not add more sequences, break loop
+                            break;
+                        }
+                    }
+                }
+
+                if (activeSequence != null) {
+                    if (removeSequence) {
+                        // Sequence reached max size
+                        fibonacciSequences.remove(activeSequence);
+                    } else if (match.getMatchResult().equals("X")) {
+                        // WON
+                        resultStatRow.increaseValue(activeSequence.bets.size());
+                        sequencesWonStatRow.increaseValue();
+
+                        final float wonAmount = activeSequence.currentBetValue * match.getOddsX();
+                        wonLossBankStatRow.increaseValue(wonAmount);
+                        // Sequence won, remove sequence
+                        fibonacciSequences.remove(activeSequence);
+                    }
+                }
+            }
+            i += sortedMatchList.size();
+        }
+        System.out.println("FibonacciStrategy.runTest() lest unresolved sequences: ");
+        fibonacciSequences.forEach(fs -> System.out.println("Sequence: " + fs.bets.size() + " outstanding bets value: " + fs.totalBetValue));
+    }
+
+    /**
+     * Matchen måste ha ett odds på X på minst 2.618
+     */
+    @Override
+    public String shouldBetOn(SoccerMatch match) {
+        return match.getOddsX() >= 2.618 ? "X" : "";
+    }
+
+    @Override
+    public List<SoccerMatch> sortMatchesOnBetPotential(List<SoccerMatch> matches) {
+        matches.sort((m2, m1) -> Float.compare(new SoccerMatchAnalysis(m1).calculateWinPercentages().getDrawPercentage(),
+                new SoccerMatchAnalysis(m2).calculateWinPercentages().getDrawPercentage()));
+        return matches;
+    }
+
+    public void reset() {
+        fibonacciSequences.clear();
+        sequencesPlayedStatRow.getChildren().clear();
+        sequencesWonStatRow.getChildren().clear();
+        resultStatRow.getChildren().clear();
+        wonLossBankStatRow.getChildren().clear();
+
+        buildStatGuiPanel();
+        buildMatchSummaryPanel();
+    }
+
+
+    private class FibonacciSequence {
+
+        public static final List<Integer> fibonacciSequence = Arrays.asList(1, 1, 2, 3, 5, 8, 13, 21, 34, 55); //, 89, 144, 233, 377, 610);
+        List<SoccerMatch> bets = new ArrayList<>();
+        float totalBetValue = 0f;
+
+        float currentBetValue = 0f;
+
+        FibonacciSequence(SoccerMatch match) {
+            bets.add(match);
+            totalBetValue += betAmount.getValue();
+            currentBetValue = betAmount.getValue();
+        }
+
+        public void addBet(SoccerMatch match) {
+            totalBetValue += betAmount.getValue() * fibonacciSequence.get(bets.size());
+            currentBetValue = betAmount.getValue() * fibonacciSequence.get(bets.size());
+
+            bets.add(match);
+        }
+
+        public boolean containsBet(SoccerMatch match) {
+            return bets.contains(match);
+        }
+
+        public boolean containsMatchFromSameDate(SoccerMatch match) {
+            return bets.stream().anyMatch(b -> b.getGameDate().toLocalDate().isEqual(match.getGameDate().toLocalDate()));
+        }
+    }
 }

+ 110 - 144
OddsJavaFx/src/controllers/strategytest/KellyFormulaStrategy.java

@@ -1,75 +1,66 @@
 package controllers.strategytest;
 
 import components.FloatStatRow;
-import components.IntTableStatRow;
 import components.NumberStatRow;
 import interfaces.strategytest.BettingStrategyInterface;
 import javafx.scene.layout.VBox;
 import objects.SoccerMatch;
 import objects.SoccerMatchAnalysis;
 
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
-import java.util.Optional;
+import java.util.stream.Collectors;
 
 /**
- * The basic concept of betting according to the Fibonacci sequence is simple: bet on a tie.
- If you lose, just bet on the next tie according to a certain key and start increasing your stake.
-
+ * <p>There are of course numerous ideas, concepts and formulas that can help you calculate the ideal stake on a bet.
+ * One of them is the Kelly formula. </p>
  *
- * It is important that the odds for the tie are above 2.62 (more precisely: 2.618);
- * luckily for those who want to employ this strategy, there are many tie bets for this minimum odds.
- The higher the rate, the better.
-
+ * <p>Of course, this is no guarantee that you will always bet correctly and the assessment of how likely the outcome of a game is, does still remain up to you.
+ But the Kelly formula can help you choose the size of your bet.</p>
  *
- * Fibonacci Betting Strategy
- * Betting after Fibonacci
- * If you lose, you simply bet the next tie after a Fibonacci sequence.
- It is a sequence of numbers in which the sum of two consecutive numbers results in the next number, making the Fibonacci sequence an infinite sequence of natural numbers.
- You can find more information about the Fibonacci sequence on Wikipedia.
-
+ * <p>This is how the Kelly formula works</p>
  *
- * Fibonacci numbers
- * The Fibonacci sequence
- * So if you start betting with 1 € on the first draw with odds> 2.
-62 and lose, then the next time you bet 1 € again, then 2 €, then 3 €, then 5 €, then 8 €, then 13 € and so on.
-
+ * <p>You choose a game or an event and rate the outcome as a percentage
+ * Example: Austria defeats Germany – you rate this outcome with a probability of 20%
+ * Now, you are looking for an odd for this event that seems fair to you
+ * Then, you put the probability and the odds in the Kelly formula and get a value from it
+ * Let us take as an example the 20% probability of winning with odds of @ 5.50.</p>
+ * <p>First we do the math, where the probability of 100% is 1:</p>
  *
- * It is mathematically understandable that every profit that you will achieve with this bet will offset the previous losses and you will even make a net profit.
-
+ * <p>Kelly value calculation sportsbetting
+ * Value calculation after Kelly
+ * Now we can continue to calculate and find the best possible stake for this bet.
+ * </p>
+ * <p>The formula used to choose a reasonable stake looks like this:
  *
- * An example of the Fibonacci bet
+ * Percentage of bankroll to be set = value / (odds – 1)
+ *</p>
+ * <p>In our case this means:
  *
- * Let’s take the example of the situation where you lose ten times in a row and win your bet the eleventh time.
- In this case, you have already gambled away 143 € and finally successfully placed the eleventh number in the Fibonacci sequence, 144, on a bet.
- If we now assume that the successful bet had odds of @ 2.
-80, you win 403.
-20 €.
- You have wagered a total of 287 €, making your net profit 116.
-20 €.
-
+ * Kelly bankroll calculation sportsbetting
+ * Bankroll calculation after Kelly
+ * The Kelly Formula hereby recommends that, given the probability that you have determined yourself and the odds you have chosen, you should bet 2.
+ * 22% of your bankroll on this event.</p>
  *
- * The disadvantage of this strategy is also obvious.
- Assuming you lose not ten bets in a row, but twenty, then you would have already lost 16,910 € in stakes.
- This is a huge bankroll, which you should of course never risk for such a betting sequence.
- You can find more about this in our explanations on bankroll management.
-
+ * <p>Now, of course, the use of this formula also depends heavily on your assessment of the probability.
+ * And if you consider a game outcome to be very likely and thus increase the value considerably, then it can happen that you get 30% or even more of your bankroll as a result.
+ * Of course, caution is advised here because your bankroll can slide down very quickly this way.</p>
+ *
+ * <p>It is also possible that you will get a negative result when calculating the first value.
+ * This happens if you bet too low with an expected probability of winning on an event with too low odds.
+ * The result is that your value is negative, which means nothing else than: if you are unsure about this, then this bet just doesn’t pay off …
+ * </p>
  */
-public class FibonacciStrategy extends VBox implements BettingStrategyInterface {
+public class KellyFormulaStrategy extends VBox implements BettingStrategyInterface {
 
-    public static final String NAME = "Fibonacci";
+    public static final String NAME = "Kelly Formula";
     List<SoccerMatch> matches;
-    private FloatStatRow betAmount;
+    private float startingBank = 1000f;
     private FloatStatRow wonLossBankStatRow;
     private NumberStatRow sequencesPlayedStatRow;
-    private IntTableStatRow resultStatRow;
 
-    private final int maxActiveFibonacciSequences = 4;
-    private final List<FibonacciSequence> fibonacciSequences = new ArrayList<>();
     private NumberStatRow sequencesWonStatRow;
 
-    public FibonacciStrategy() {
+    public KellyFormulaStrategy() {
         super();
         buildSettingsGuiPanel();
         buildStatGuiPanel();
@@ -83,21 +74,18 @@ public class FibonacciStrategy extends VBox implements BettingStrategyInterface
 
     @Override
     public void buildSettingsGuiPanel() {
-        betAmount = new FloatStatRow("Bet Amount", 10f);
-        this.getChildren().add(betAmount);
+        // Empty for now
     }
 
     @Override
     public void buildStatGuiPanel() {
-        sequencesPlayedStatRow = new NumberStatRow("Number of sequences played", 0);
-        sequencesWonStatRow = new NumberStatRow("Number of sequences won", 0);
-        resultStatRow = new IntTableStatRow("Longest sequence without win");
+        sequencesPlayedStatRow = new NumberStatRow("Number of matches played", 0);
+        sequencesWonStatRow = new NumberStatRow("Number of matches won", 0);
 
         wonLossBankStatRow = new FloatStatRow("Amount won or lost", 0f);
 
         this.getChildren().add(sequencesPlayedStatRow);
         this.getChildren().add(sequencesWonStatRow);
-        this.getChildren().add(resultStatRow);
         this.getChildren().add(wonLossBankStatRow);
     }
 
@@ -108,130 +96,108 @@ public class FibonacciStrategy extends VBox implements BettingStrategyInterface
 
     @Override
     public void runTest() {
-
-        float lowestBankAmount = 0f;
-
-        for (int i = 0; i < matches.size(); i++) {
-            SoccerMatch m = matches.get(i);
-            List<SoccerMatch> soccerMatches = filterTodaysMatches(matches, m);
-
-            List<SoccerMatch> sortedMatchList = sortMatchesOnBetPotential(soccerMatches);
-
-            for (SoccerMatch match : sortedMatchList) {
-                boolean removeSequence = false;
-                String shouldBetOn = shouldBetOn(match);
-                FibonacciSequence activeSequence = null;
-                if (shouldBetOn.equals("X")) {
-                    Optional<FibonacciSequence> fibSeq = fibonacciSequences.stream().filter(fs -> !fs.containsMatchFromSameDate(match)).findFirst();
-                    if (fibSeq.isPresent()) {
-                        // Add to current sequence
-                        activeSequence = fibSeq.get();
-                        if (activeSequence.bets.size() + 1 > FibonacciSequence.fibonacciSequence.size()) {
-                            System.out.println("System FAILED " + match.getGameDate() + " lost " + activeSequence.totalBetValue + " current bank " + wonLossBankStatRow.getValue());
-                            System.out.println("Lowest bank amount " + lowestBankAmount);
-                            removeSequence = true;
-                        } else {
-                            activeSequence.addBet(match);
-                            wonLossBankStatRow.decreaseValue(activeSequence.currentBetValue);
-                            if (wonLossBankStatRow.getValue() < lowestBankAmount) {
-                                lowestBankAmount = wonLossBankStatRow.getValue();
-                            }
-                        }
-                    } else {
-                        // Start new if not at max active sequences
-                        if (fibonacciSequences.size() < maxActiveFibonacciSequences) {
-                            activeSequence = new FibonacciSequence(match);
-                            sequencesPlayedStatRow.increaseValue();
-                            wonLossBankStatRow.decreaseValue(activeSequence.currentBetValue);
-                            fibonacciSequences.add(activeSequence);
-                            if (wonLossBankStatRow.getValue() < lowestBankAmount) {
-                                lowestBankAmount = wonLossBankStatRow.getValue();
-                            }
-                        } else {
-                            // Should not add more sequences, break loop
-                            break;
-                        }
-                    }
-                }
-
-                if (activeSequence != null) {
-                    if (removeSequence) {
-                        // Sequence reached max size
-                        fibonacciSequences.remove(activeSequence);
-                    } else if (match.getMatchResult().equals("X")) {
-                        // WON
-                        resultStatRow.increaseValue(activeSequence.bets.size());
-                        sequencesWonStatRow.increaseValue();
-
-                        final float wonAmount = activeSequence.currentBetValue * match.getOddsX();
-                        wonLossBankStatRow.increaseValue(wonAmount);
-                        // Sequence won, remove sequence
-                        fibonacciSequences.remove(activeSequence);
-                    }
-                }
+        for (SoccerMatch match : matches) {
+            List<SoccerMatchAnalysis> todaysMatches = filterTodaysMatches(matches, match).stream().map(SoccerMatchAnalysis::new).collect(Collectors.toList());
+            todaysMatches.forEach(SoccerMatchAnalysis::calculateWinPercentages);
+            //todaysMatches= sortMatchesOnBetPotential(todaysMatches);
+            String bet = shouldBetOn(match);
+            if (bet != null) {
+                // TODO: Implement betting
             }
-            i += sortedMatchList.size();
         }
-        System.out.println("FibonacciStrategy.runTest() lest unresolved sequences: ");
-        fibonacciSequences.forEach(fs -> System.out.println("Sequence: " + fs.bets.size() + " outstanding bets value: " + fs.totalBetValue));
+
     }
 
-    /**
-     * Matchen måste ha ett odds på X på minst 2.618
-     */
     @Override
     public String shouldBetOn(SoccerMatch match) {
-        return match.getOddsX() >= 2.618 ? "X" : "";
+        return "1X2";
     }
 
     @Override
-    public List<SoccerMatch> sortMatchesOnBetPotential(List<SoccerMatch> matches) {
-        //matches.sort((m1, m2) -> Float.compare(m1.getOddsX(), m2.getOddsX()));
-
-        matches.sort((m2, m1) -> Float.compare(new SoccerMatchAnalysis(m1).calculateWinPercentages().getDrawPercentage(),
-                new SoccerMatchAnalysis(m2).calculateWinPercentages().getDrawPercentage()));
-        return matches;
+    public List<?> sortMatchesOnBetPotential(List<SoccerMatch> matches) {
+        return null;
     }
 
+//    @Override
+//    public List<SoccerMatchAnalysis> sortMatchesOnBetPotential(List<SoccerMatchAnalysis> matches) {
+//
+//        matches.sort((SoccerMatchAnalysis match1, SoccerMatchAnalysis match2) -> {
+//            KellyFormulaBet kellyFormulaBet1 = new KellyFormulaBet(match1);
+//            KellyFormulaBet kellyFormulaBet2 = new KellyFormulaBet(match2);
+//            kellyFormulaBet1.compareTo(kellyFormulaBet2);
+//
+//            return
+//        }
+//        return matches;
+//    }
+
+
     public void reset() {
-        fibonacciSequences.clear();
         sequencesPlayedStatRow.getChildren().clear();
         sequencesWonStatRow.getChildren().clear();
-        resultStatRow.getChildren().clear();
         wonLossBankStatRow.getChildren().clear();
 
         buildStatGuiPanel();
         buildMatchSummaryPanel();
     }
 
+    private class KellyFormulaBet {
 
-    private class FibonacciSequence {
+        private String toBetOn;
+        private float diffOdds1Calculated;
+        private float diffOddsXCalculated;
+        private float diffOdds2Calculated;
 
-        public static final List<Integer> fibonacciSequence = Arrays.asList(1, 1, 2, 3, 5, 8, 13, 21, 34, 55); //, 89, 144, 233, 377, 610);
-        List<SoccerMatch> bets = new ArrayList<>();
-        float totalBetValue = 0f;
+        public KellyFormulaBet(SoccerMatchAnalysis match) {
+            bestBetValue(match);
+            setDiffOdds1Calculated(match);
+            setDiffOddsXCalculated(match);
+            setDiffOdds2Calculated(match);
+        }
+        private void bestBetValue(SoccerMatchAnalysis match) {
+            float diffOdds1Calculated = getDiffOdds1Calculated(match);
+            float diffOddsXCalculated = getDiffOddsXCalculated(match);
+            float diffOdds2Calculated = getDiffOdds2Calculated(match);
+
+            if (diffOdds1Calculated > diffOddsXCalculated && diffOdds1Calculated > diffOdds2Calculated) {
+                toBetOn =  "1";
+            } else if (diffOddsXCalculated > diffOdds1Calculated && diffOddsXCalculated > diffOdds2Calculated) {
+                toBetOn = "X";
+            } else if (diffOdds2Calculated > diffOdds1Calculated && diffOdds2Calculated > diffOddsXCalculated) {
+                toBetOn = "2";
+            }
+        }
 
-        float currentBetValue = 0f;
+        private float getDiffOdds1Calculated(SoccerMatchAnalysis match) {
+            return diffOdds1Calculated;
+        }
 
-        FibonacciSequence(SoccerMatch match) {
-            bets.add(match);
-            totalBetValue += betAmount.getValue();
-            currentBetValue = betAmount.getValue();
+        private float getDiffOddsXCalculated(SoccerMatchAnalysis match) {
+            return diffOddsXCalculated;
         }
 
-        public void addBet(SoccerMatch match) {
-            totalBetValue += betAmount.getValue() * fibonacciSequence.get(bets.size());
-            currentBetValue = betAmount.getValue() * fibonacciSequence.get(bets.size());
+        private float getDiffOdds2Calculated(SoccerMatchAnalysis match) {
+            return diffOdds2Calculated;
+        }
 
-            bets.add(match);
+        private void setDiffOdds1Calculated(SoccerMatchAnalysis match) {
+            float winOddsCalculated = convertPercentageToOdds(match.getCalculatedPercentages().getHomeWinPercentage());
+            diffOdds1Calculated = match.getOdds1() - winOddsCalculated;
         }
 
-        public boolean containsBet(SoccerMatch match) {
-            return bets.contains(match);
+        private void setDiffOddsXCalculated(SoccerMatchAnalysis match) {
+            float drawOddsCalculated = convertPercentageToOdds(match.getCalculatedPercentages().getDrawPercentage());
+            diffOddsXCalculated = match.getOddsX() - drawOddsCalculated;
         }
 
-        public boolean containsMatchFromSameDate(SoccerMatch match) {
-            return bets.stream().anyMatch(b -> b.getGameDate().toLocalDate().isEqual(match.getGameDate().toLocalDate()));
+        private void setDiffOdds2Calculated(SoccerMatchAnalysis match) {
+            float loseOddsCalculated = convertPercentageToOdds(match.getCalculatedPercentages().getAwayWinPercentage());
+            diffOdds2Calculated = match.getOdds2() - loseOddsCalculated;
+        }
+
+        public void compareTo(KellyFormulaBet kellyFormulaBet2) {
+            
         }
     }
+
 }

+ 607 - 1
OddsJavaFx/src/controllers/strategytest/OneThreeTwoSixStrategy.java

@@ -1,2 +1,608 @@
-package controllers.strategytest;public class OneThreeTwoSixStrategy {
+package controllers.strategytest;
+
+import components.FloatStatRow;
+import components.NumberStatRow;
+import interfaces.strategytest.BettingStrategyInterface;
+import javafx.scene.control.Label;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.layout.VBox;
+import objects.Percentages;
+import objects.SoccerMatch;
+import objects.SoccerMatchAnalysis;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+
+/**
+ * The 1-3-2-6 system is similar to another positive progression betting system known as a Paroli.
+ * Both involve increased stakes after a win, and both involve a cycle of bets ending at a fixed point.
+ * The only real difference is the actual betting sequence.
+ *
+ * <p>
+ * There are not many systems that are easier to understand than 1-3-2-6 and its simplicity is very appealing to many players.
+ * There are also a number of other benefits that contribute to its popularity.
+ *
+ * <p>
+ * Of course, as in any betting system, there are also disadvantages.
+ * We explore the positive and negative aspects of the 1-3-2-6 below, along with the details and how it is used.
+ *
+ * <p>
+ * Use of the 1-3-2-6 system
+ * <p>
+ * Like many betting systems, the 1-3-2-6 was designed for bets that pay out an even sum, like the red-black bets in roulette.
+ * In fact, it is widely used on the roulette table and in other casino games such as baccarat, dice games and blackjack.
+ * Basically, it doesn’t matter what you use it for, provided you are playing with even sums.
+ *
+ * <p>
+ * As mentioned earlier, this is a very simple system.
+ * All you have to do is adjust your bets based on a few simple rules.
+ * First of all, you have to decide how high your betting unit should be.
+ * As a guide, once you’ve set the amount you’re willing to lose in one session, your betting unit should be around 2% to 5% of that.
+ *
+ * <p>
+ * For example, if you wanted to play with a total of 500 €, 10 € would be a reasonable number.
+ * A bet unit is the amount you wager on the first bet in the sequence.
+ * After every lost bet, the sequence ends and you start a new one – and again you insert a betting unit.
+ *
+ * <p>
+ * If you win a bet, you adjust your stake according to the sequence 1-3-2-6.
+ * So, if you win your first bet, the next time you increase your stake to € 30 (three betting units).
+ * If you win this too, you will place € 20 on your next bet.
+ * If you win this too, the next time you wager € 60.
+ * And already we have the 1-3-2-6 sequence.
+ *
+ * <p>
+ * If you win the fourth, consecutive bet then the sequence is completed and you start all over again.
+ * Don’t forget, as soon as you lose, your stake will also reset to a betting unit.
+ *
+ * <p>
+ * This is basically what the 1-3-2-6 betting system is all about.
+ * As long as you keep the simple set of rules in mind, you shouldn’t have any problems using this system successfully.
+ *
+ * <p>
+ * Possible outcomes of 1-3-2-6
+ * <p>
+ * Since this system is only a short cycle, there are few possible outcomes.
+ * These are the following:
+ * <p>
+ * Loss of the first bet (total loss of one betting unit)
+ * First bet won, second bet lost (total loss of two betting units)
+ * First two bets won, third bet lost (total win of two betting units)
+ * Won the first three bets, lose the fourth bet (breakeven)
+ * Win all four bets (total win of 12 units)
+ * So, as you can see, only two of the possible outcomes of a cycle involve loss.
+ * A loss will only occur if the first or second bet is lost.
+ * So, every time you win the first two bets, you cannot lose again in the same cycle.
+ *
+ * <p>
+ * It may seem like the 1-3-2-6 system makes it more likely to make money than to lose.
+ * But unfortunately, this is not true.
+ * Unfortunately, while the system has some advantages, the guaranteed profit isn’t one.
+ *
+ * <p>
+ * Advantages and disadvantages of the 1-3-2-6 betting strategy
+ * <p>
+ * Perhaps the greatest advantage of 1-3-2-6 is that it is very simple and easy to learn.
+ * If you want to use a betting system that you don’t want to be overly complicated, this is a good option.
+ * In addition, your stake is not increased after a loss – this prevents the rapid loss of money, especially if you choose the size of your betting units sensitively.
+ *
+ * <p>
+ * Another notable advantage is that after stopping the sequence after four consecutive wins and then going back to one unit, you are facing the possibility of a small winning streak.
+ * There is a chance that you will win all four times in a row – and if you are lucky, your winnings will exceed the losses on bets you lost before.
+ *
+ * <p>
+ * The system does not come without its disadvantages; the most striking is that there is nothing to beat the house edge that exists in any casino.
+ * No betting system can do this.
+ * But it helps you to maintain discipline with a set of rules to be followed, because ultimately you still have to rely on your luck to win.
+ * If you get the wrong sequence of results, you will lose.
+ *
+ * <p>
+ * The 1-3-2-6 isn’t a bad betting system compared to any of the other systems available, provided you accept it for what it is.
+ * This system doesn’t guarantee that you will win, but it can help you get the most out of your luck.
+ */
+public class OneThreeTwoSixStrategy extends VBox implements BettingStrategyInterface {
+
+    List<SoccerMatch> matches = new ArrayList<>();
+    private FloatStatRow betAmount;
+    private NumberStatRow sequencesPlayedStatRow;
+    private NumberStatRow sequencesWonStatRow;
+    private NumberStatRow sequenceLostFirstStatRow;
+    private NumberStatRow sequenceLostSecondStatRow;
+    private NumberStatRow sequenceLostThirdStatRow;
+    private FloatStatRow wonLossBankStatRow;
+    private ScrollPane matchesSummaryScrollPane;
+
+    public OneThreeTwoSixStrategy() {
+        buildSettingsGuiPanel();
+        buildStatGuiPanel();
+        buildMatchSummaryPanel();
+    }
+
+    public OneThreeTwoSixStrategy(List<SoccerMatch> matches) {
+        setMatches(matches);
+
+        buildSettingsGuiPanel();
+        buildStatGuiPanel();
+        buildMatchSummaryPanel();
+    }
+
+    @Override
+    public void setMatches(List<SoccerMatch> matches) {
+        this.matches.clear();
+        this.matches.addAll(matches);
+    }
+
+    @Override
+    public void buildSettingsGuiPanel() {
+        betAmount = new FloatStatRow("Bet Amount", 10f);
+        this.getChildren().add(betAmount);
+    }
+
+    @Override
+    public void buildStatGuiPanel() {
+        sequencesPlayedStatRow = new NumberStatRow("Number of matches played", 0);
+        sequencesWonStatRow = new NumberStatRow("Number of Sequences won", 0);
+        sequenceLostFirstStatRow = new NumberStatRow("Number of Secuences lost first", 0);
+        sequenceLostSecondStatRow = new NumberStatRow("Number of Secuences lost Second", 0);
+        sequenceLostThirdStatRow = new NumberStatRow("Number of Secuences lost Third", 0);
+
+        wonLossBankStatRow = new FloatStatRow("Amount won or lost", 0f);
+
+        this.getChildren().add(sequencesPlayedStatRow);
+        this.getChildren().add(sequencesWonStatRow);
+        this.getChildren().add(sequenceLostFirstStatRow);
+        this.getChildren().add(sequenceLostSecondStatRow);
+        this.getChildren().add(sequenceLostThirdStatRow);
+        this.getChildren().add(wonLossBankStatRow);
+    }
+
+    @Override
+    public void buildMatchSummaryPanel() {
+        matchesSummaryScrollPane = new ScrollPane();
+        matchesSummaryScrollPane.setContent(new VBox());
+        matchesSummaryScrollPane.setMaxHeight(200d);
+
+        this.getChildren().add(matchesSummaryScrollPane);
+    }
+
+    // Saker att bestämma sig för.. Hur många sekvenser ska vara igång samtidigt?
+    @Override
+    public void runTest() {
+
+        List<List<betSequenceDTO>> sequences = new ArrayList<>();
+        int sequenceLimit = 5;
+
+        for (int i = 0; i < matches.size(); i++) {
+            SoccerMatch match = matches.get(i);
+            sequencesPlayedStatRow.increaseValue();
+
+            // Decide what to bet on.. If it is close to 2.0 it will be easier to calculate the bet sequence
+            // If it is the first in a new sequence then use betAmount
+            // If it is the second in a new sequence then use 3 * betAmount /* adjusted for odds and so on */
+            // The bet amount should always conform to the strategy
+
+            List<SoccerMatch> todaysMatches = filterTodaysMatches(matches, match);
+
+            List<MatchPercentDTO> listOfPotentialMatchesOrdered = sortMatchesOnBetPotential(todaysMatches);
+
+            List<List<betSequenceDTO>> sequencesToRemove = new ArrayList<>();
+            for (MatchPercentDTO matchPercentDTO : listOfPotentialMatchesOrdered) {
+                String betOn = shouldBetOn(matchPercentDTO.match);
+
+                boolean addingToSequence = false;
+                // find all sequences that are active and not containing a match with the same gameDate
+                float currentBetAmount;
+                float odds = getCurrentMatchOdds(matchPercentDTO.match, betOn);
+                List<betSequenceDTO> currentSequence = new ArrayList<>();
+                for (List<betSequenceDTO> sequence : sequences) {
+                    if (sequence.stream().noneMatch(m -> m.match.getGameDate().toLocalDate().isEqual(match.getGameDate().toLocalDate()))) {
+                        currentSequence = sequence;
+                        addingToSequence = true;
+                        break;
+                    }
+                }
+
+                currentBetAmount = getBetAmout(currentSequence);
+                wonLossBankStatRow.decreaseValue(currentBetAmount);
+                currentSequence.add(new betSequenceDTO(matchPercentDTO.match, currentBetAmount, odds, betOn));
+
+                if (!addingToSequence && sequences.size() < sequenceLimit) {
+                    sequences.add(currentSequence);
+                }
+
+                if (betOn.contains(matchPercentDTO.match.getMatchResult())) {
+                    wonLossBankStatRow.increaseValue(currentBetAmount * odds);
+                    if (currentSequence.size() == 4) {
+                        sequencesWonStatRow.increaseValue();
+                        sequencesToRemove.add(currentSequence);
+                    }
+                } else {
+                    switch (currentSequence.size()) {
+                        case 1:
+                            sequenceLostFirstStatRow.increaseValue();
+                            sequencesToRemove.add(currentSequence);
+                            break;
+                        case 2:
+                            sequenceLostSecondStatRow.increaseValue();
+                            sequencesToRemove.add(currentSequence);
+                            break;
+                        case 3:
+                            sequenceLostThirdStatRow.increaseValue();
+                            sequencesToRemove.add(currentSequence);
+                            break;
+                        default:
+                            break;
+                    }
+                }
+            }
+
+            for (List<betSequenceDTO> toRemove : sequencesToRemove) {
+                addSequenceToStat(toRemove);
+            }
+
+            sequences.removeAll(sequencesToRemove);
+            sequencesToRemove.clear();
+
+            i += todaysMatches.size();
+        }
+    }
+
+    private void addSequenceToStat(List<betSequenceDTO> toRemove) {
+        VBox sequenceStat = new VBox();
+        Label sequenceLengthLabel = new Label("Sequence length: " + toRemove.size());
+        sequenceStat.getChildren().add(sequenceLengthLabel);
+        for (betSequenceDTO seq : toRemove) {
+            Label label = new Label(seq.match.getHomeTeam().getTeamName() + " " + seq.match.getAwayTeam().getTeamName() + " " + seq.match.getMatchResult());
+            Label resultLabel = new Label(" Bet on: " + seq.bet.betOn + " " + seq.bet.betAmount + " " + seq.bet.odds);
+            sequenceStat.getChildren().add(label);
+            sequenceStat.getChildren().add(resultLabel);
+        }
+        Double sum = calculateSequenceSum(toRemove);
+        Label sumLabel = new Label("Sum: " + sum);
+        sequenceStat.getChildren().add(sumLabel);
+
+        switch (toRemove.size()) {
+            case 2:
+                sequenceStat.setStyle("-fx-background-color: red");
+                break;
+            case 3:
+                sequenceStat.setStyle("-fx-background-color: firebrick");
+                break;
+            case 4:
+                if (toRemove.get(3).isWin()) {
+                    sequenceStat.setStyle("-fx-background-color: green");
+                } else {
+                    sequenceStat.setStyle("-fx-background-color: aquamarine");
+                }
+                break;
+            default:
+                sequenceStat.setStyle("-fx-background-color: darkred");
+                break;
+        }
+
+        ((VBox) matchesSummaryScrollPane.getContent()).getChildren().add(sequenceStat);
+    }
+
+    private Double calculateSequenceSum(List<betSequenceDTO> toRemove) {
+        if (toRemove.size() == 1) {
+            return (double) -toRemove.get(0).bet.betAmount;
+        } else if (toRemove.size() == 2) {
+            double sum = 0d;
+            sum += toRemove.get(0).bet.betAmount * toRemove.get(0).bet.odds - toRemove.get(0).bet.betAmount;
+            sum -= toRemove.get(1).bet.betAmount;
+            return sum;
+        } else if (toRemove.size() == 3) {
+            double sum = 0d;
+            sum += toRemove.get(0).bet.betAmount * toRemove.get(0).bet.odds - toRemove.get(0).bet.betAmount;
+            sum += toRemove.get(1).bet.betAmount * toRemove.get(1).bet.odds - toRemove.get(1).bet.betAmount;
+            sum -= toRemove.get(2).bet.betAmount;
+            return sum;
+        } else if (toRemove.size() == 4) {
+            if (toRemove.get(3).isWin()) {
+                double sum = 0d;
+                sum += toRemove.get(0).bet.betAmount * toRemove.get(0).bet.odds - toRemove.get(0).bet.betAmount;
+                sum += toRemove.get(1).bet.betAmount * toRemove.get(1).bet.odds - toRemove.get(1).bet.betAmount;
+                sum += toRemove.get(2).bet.betAmount * toRemove.get(2).bet.odds - toRemove.get(2).bet.betAmount;
+                sum += toRemove.get(3).bet.betAmount * toRemove.get(3).bet.odds - toRemove.get(3).bet.betAmount;
+                return sum;
+            } else {
+                double sum = 0d;
+                sum += toRemove.get(0).bet.betAmount * toRemove.get(0).bet.odds - toRemove.get(0).bet.betAmount;
+                sum += toRemove.get(1).bet.betAmount * toRemove.get(1).bet.odds - toRemove.get(1).bet.betAmount;
+                sum += toRemove.get(2).bet.betAmount * toRemove.get(2).bet.odds - toRemove.get(2).bet.betAmount;
+                sum -= toRemove.get(3).bet.betAmount;
+                return sum;
+            }
+        } else {
+            return 0d;
+        }
+    }
+
+    private float getCurrentMatchOdds(SoccerMatch match, String betOn) {
+        return switch (betOn) {
+            case "1" -> match.getOdds1();
+            case "X" -> match.getOddsX();
+            case "2" -> match.getOdds2();
+            case "1X" -> calculate1XOdds(match);
+            case "X2" -> calculateX2Odds(match);
+            case "12" -> calculate12Odds(match);
+            default -> 0;
+        };
+    }
+
+    private float getBetAmout(List<betSequenceDTO> sequence) {
+        int sequenceStep = sequence.size();
+        if (sequenceStep == 1) {
+            return 3 * betAmount.getValue();
+        } else if (sequenceStep == 2) {
+            return 2 * betAmount.getValue();
+        } else if (sequenceStep == 3) {
+            return 6 * betAmount.getValue();
+        } else {
+            return betAmount.getValue();
+        }
+    }
+
+    @Override
+    public String shouldBetOn(SoccerMatch match) {
+        final String returnValue;
+        float lowerLimit = 1.9f;
+        float upperLimit = 2.1f;
+
+        if (match.getOdds1() > lowerLimit && match.getOdds1() < upperLimit) {
+            returnValue = "1";
+        } else if (match.getOddsX() > lowerLimit && match.getOddsX() < upperLimit) {
+            returnValue = "X";
+        } else if (match.getOdds2() > lowerLimit && match.getOdds2() < upperLimit) {
+            returnValue = "2";
+        } else if (calculate1XOdds(match) > lowerLimit && calculate1XOdds(match) < upperLimit) {
+            returnValue = "1X";
+        } else if (calculateX2Odds(match) > lowerLimit && calculateX2Odds(match) < upperLimit) {
+            returnValue = "X2";
+        } else if (calculate12Odds(match) > lowerLimit && calculate12Odds(match) < upperLimit) {
+            returnValue = "12";
+        } else {
+            returnValue = "";
+        }
+
+        return returnValue;
+    }
+
+    // Något odds måste vara när 2.0 för att spelas på
+    @Override
+    public List<MatchPercentDTO> sortMatchesOnBetPotential(List<SoccerMatch> matches) {
+        List<SoccerMatch> filteredGames = new ArrayList<>();
+        for (SoccerMatch sm : matches) {
+            if (!shouldBetOn(sm).equals("")) {
+                filteredGames.add(sm);
+            }
+        }
+
+        return sortMatches(filteredGames);
+    }
+
+    private class betSequenceDTO {
+
+        Bet bet;
+        SoccerMatch match;
+
+        betSequenceDTO(SoccerMatch match, float betAmount, float odds, String betOn) {
+            this.match = match;
+            bet = new Bet(betAmount, odds, betOn);
+        }
+
+        public boolean isWin() {
+            if (match != null && bet.betOn.contains(match.getMatchResult())) {
+                return true;
+            }
+            return false;
+        }
+    }
+
+    private class Bet {
+        private float betAmount;
+        private float odds;
+        String betOn;
+
+        Bet(float betAmount, float odds, String betOn) {
+            this.betAmount = betAmount;
+            this.odds = odds;
+            this.betOn = betOn;
+        }
+    }
+
+    private List<MatchPercentDTO> sortMatches(List<SoccerMatch> matches) {
+
+        List<MatchPercentDTO> dtoList = new ArrayList<>();
+        for (SoccerMatch match : matches) {
+            dtoList.add(new MatchPercentDTO(match));
+        }
+
+        return dtoList.stream().sorted().collect(Collectors.toList());
+    }
+
+    private class MatchPercentDTO implements Comparable<MatchPercentDTO> {
+        SoccerMatch match;
+        Percentages percentages;
+        float calculatedOdds1;
+        float calculatedOddsX;
+        float calculatedOdds2;
+        float diffOdds1;
+        float diffOddsX;
+        float diffOdds2;
+        private final float diff1X;
+        private final float diffX2;
+        private final float diff12;
+
+        public MatchPercentDTO(SoccerMatch match) {
+            this.match = match;
+            SoccerMatchAnalysis sma = new SoccerMatchAnalysis(match);
+            percentages = sma.calculateWinPercentages();
+            calculatedOdds1 = convertPercentageToOdds(percentages.getHomeWinPercentage());
+            calculatedOddsX = convertPercentageToOdds(percentages.getDrawPercentage());
+            calculatedOdds2 = convertPercentageToOdds(percentages.getAwayWinPercentage());
+
+            diffOdds1 = calculatedOdds1 - match.getOdds1();
+            diffOddsX = calculatedOddsX - match.getOddsX();
+            diffOdds2 = calculatedOdds2 - match.getOdds2();
+
+            diff1X = calculate1XOdds(match) - calculate1XOdds(calculatedOdds1, calculatedOddsX);
+            diffX2 = calculate1XOdds(match) - calculateX2Odds(calculatedOddsX, calculatedOdds2);
+            diff12 = calculate1XOdds(match) - calculate12Odds(calculatedOdds1, calculatedOdds2);
+
+        }
+
+        public Percentages getPercentages() {
+            return percentages;
+        }
+
+        public float getCalculatedOdds1() {
+            return calculatedOdds1;
+        }
+
+        public float getCalculatedOddsX() {
+            return calculatedOddsX;
+        }
+
+        public float getCalculatedOdds2() {
+            return calculatedOdds2;
+        }
+
+        public float getDiffOdds1() {
+            return diffOdds1;
+        }
+
+        public float getDiffOddsX() {
+            return diffOddsX;
+        }
+
+        public float getDiffOdds2() {
+            return diffOdds2;
+        }
+
+        public float getDiff1X() {
+            return diff1X;
+        }
+
+        public float getDiffX2() {
+            return diffX2;
+        }
+
+        public float getDiff12() {
+            return diff12;
+        }
+
+        @Override
+        public int compareTo(MatchPercentDTO matchPercentDTO) {
+            String betOn1 = shouldBetOn(match);
+            String betOn2 = shouldBetOn(matchPercentDTO.match);
+
+            if (betOn1.equals("1")) {
+                if (betOn2.equals("1")) {
+                    return Float.compare(diffOdds1, matchPercentDTO.getDiffOdds1());
+                } else if (betOn2.equals("X")) {
+                    return Float.compare(diffOdds1, matchPercentDTO.getDiffOddsX());
+                } else if (betOn2.equals("2")) {
+                    return Float.compare(diffOdds1, matchPercentDTO.getDiffOdds2());
+                } else if (betOn2.equals("1X")) {
+                    return Float.compare(diffOdds1, matchPercentDTO.getDiff1X());
+                } else if (betOn2.equals("X2")) {
+                    return Float.compare(diffOdds1, matchPercentDTO.getDiffX2());
+                } else if (betOn2.equals("12")) {
+                    return Float.compare(diffOdds1, matchPercentDTO.getDiff12());
+                }
+            } else if (betOn1.equals("X")) {
+                if (betOn2.equals("1")) {
+                    return Float.compare(diffOddsX, matchPercentDTO.getDiffOdds1());
+                } else if (betOn2.equals("X")) {
+                    return Float.compare(diffOddsX, matchPercentDTO.getDiffOddsX());
+                } else if (betOn2.equals("2")) {
+                    return Float.compare(diffOddsX, matchPercentDTO.getDiffOdds2());
+                } else if (betOn2.equals("1X")) {
+                    return Float.compare(diffOddsX, matchPercentDTO.getDiff1X());
+                } else if (betOn2.equals("X2")) {
+                    return Float.compare(diffOddsX, matchPercentDTO.getDiffX2());
+                } else if (betOn2.equals("12")) {
+                    return Float.compare(diffOddsX, matchPercentDTO.getDiff12());
+                }
+            } else if (betOn1.equals("2")) {
+                if (betOn2.equals("1")) {
+                    return Float.compare(diffOdds2, matchPercentDTO.getDiffOdds1());
+                } else if (betOn2.equals("X")) {
+                    return Float.compare(diffOdds2, matchPercentDTO.getDiffOddsX());
+                } else if (betOn2.equals("2")) {
+                    return Float.compare(diffOdds2, matchPercentDTO.getDiffOdds2());
+                } else if (betOn2.equals("1X")) {
+                    return Float.compare(diffOdds2, matchPercentDTO.getDiff1X());
+                } else if (betOn2.equals("X2")) {
+                    return Float.compare(diffOdds2, matchPercentDTO.getDiffX2());
+                } else if (betOn2.equals("12")) {
+                    return Float.compare(diffOdds2, matchPercentDTO.getDiff12());
+                }
+            } else if (betOn1.equals("1X")) {
+                if (betOn2.equals("1")) {
+                    return Float.compare(diff1X, matchPercentDTO.getDiffOdds1());
+                } else if (betOn2.equals("X")) {
+                    return Float.compare(diff1X, matchPercentDTO.getDiffOddsX());
+                } else if (betOn2.equals("2")) {
+                    return Float.compare(diff1X, matchPercentDTO.getDiffOdds2());
+                } else if (betOn2.equals("1X")) {
+                    return Float.compare(diff1X, matchPercentDTO.getDiff1X());
+                } else if (betOn2.equals("X2")) {
+                    return Float.compare(diff1X, matchPercentDTO.getDiffX2());
+                } else if (betOn2.equals("12")) {
+                    return Float.compare(diff1X, matchPercentDTO.getDiff12());
+                }
+            } else if (betOn1.equals("X2")) {
+                if (betOn2.equals("1")) {
+                    return Float.compare(diffX2, matchPercentDTO.getDiffOdds1());
+                } else if (betOn2.equals("X")) {
+                    return Float.compare(diffX2, matchPercentDTO.getDiffOddsX());
+                } else if (betOn2.equals("2")) {
+                    return Float.compare(diffX2, matchPercentDTO.getDiffOdds2());
+                } else if (betOn2.equals("1X")) {
+                    return Float.compare(diffX2, matchPercentDTO.getDiff1X());
+                } else if (betOn2.equals("X2")) {
+                    return Float.compare(diffX2, matchPercentDTO.getDiffX2());
+                } else if (betOn2.equals("12")) {
+                    return Float.compare(diffX2, matchPercentDTO.getDiff12());
+                }
+            } else if (betOn1.equals("12")) {
+                if (betOn2.equals("1")) {
+                    return Float.compare(diff12, matchPercentDTO.getDiffOdds1());
+                } else if (betOn2.equals("X")) {
+                    return Float.compare(diff12, matchPercentDTO.getDiffOddsX());
+                } else if (betOn2.equals("2")) {
+                    return Float.compare(diff12, matchPercentDTO.getDiffOdds2());
+                } else if (betOn2.equals("1X")) {
+                    return Float.compare(diff12, matchPercentDTO.getDiff1X());
+                } else if (betOn2.equals("X2")) {
+                    return Float.compare(diff12, matchPercentDTO.getDiffX2());
+                } else if (betOn2.equals("12")) {
+                    return Float.compare(diff12, matchPercentDTO.getDiff12());
+                }
+            }
+
+            return 0;
+        }
+
+        private float getDiffToBetOn(String whatToBetOn) {
+            if (whatToBetOn.equals("1")) {
+                return diffOdds1;
+            } else if (whatToBetOn.equals("X")) {
+                return diffOddsX;
+            } else if (whatToBetOn.equals("2")) {
+                return diffOdds2;
+            } else if (whatToBetOn.equals("1X")) {
+                return diff1X;
+            } else if (whatToBetOn.equals("X2")) {
+                return diffX2;
+            } else if (whatToBetOn.equals("12")) {
+                return diff12;
+            }
+            return 0;
+        }
+    }
 }

+ 69 - 34
OddsJavaFx/src/controllers/strategytest/OneXStrategy.java

@@ -2,79 +2,73 @@ package controllers.strategytest;
 
 
 import components.FloatStatRow;
+import components.MatchSummaryPanelRow;
 import components.NumberStatRow;
+import interfaces.strategytest.BettingStrategyInterface;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.layout.VBox;
 import objects.SoccerMatch;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
  * <p>1X on home outsiders strategy</p>
- * <p>A betting strategy that has been successful in the past is the bet on the “double chance” 1X if an outsider plays against a favorite at home.
- * In this case, the “1X” bet brings respectable odds and very interesting profit opportunities.</p>
+ * <p>A betting strategy that has been successful in the past is the bet on the "double chance" 1X if an outsider plays against a favorite at home.
+ * In this case, the "1X" bet brings respectable odds and very interesting profit opportunities.</p>
  *
  * <p>Home win or draw betting strategy</p>
  *
- * <p>You dont even have to choose and analyze games that contain absolute extremes and obvious class differences with this strategy.
- * So, you dont necessarily have to bet against Barcelona, Bayern or Juventus as an away team.
+ * <p>You don't even have to choose and analyze games that contain absolute extremes and obvious class differences with this strategy.
+ * So, you don't necessarily have to bet against Barcelona, Bayern or Juventus as an away team.
  * Here, we would probably move away from the value bets.
  * Even if we opt for teams that are not big outsiders, but are still outsiders according to the odds, we find highly interesting odds between 1.60 and 2.50.</p>
  *
  * <p>As with all bets, it is important to analyze in advance and not blindly going for any team.
  * You should of course take statistics into account, advance information about injuries and suspensions, as well as the current shape of the teams.
- * The home advantage of the outsider, for whom games in front of their own audience against a “bigger one” also represent a special motivation,
+ * The home advantage of the outsider, for whom games in front of their own audience against a "bigger one" also represent a special motivation,
  * should not be underestimated as it brings another small advantage for the home team.
- * Especially when the respective favorite has recently shown itself shaky against “smaller ones”,
+ * Especially when the respective favorite has recently shown itself shaky against "smaller ones",
  * you can definitely find value in such an outsider bet with double chances.</p>
  *
  * <p>If you also accept lower odds, you can of course also use this 1X strategy for games that have balanced odds.</p>
  */
-public class OneXStatPanel extends javafx.scene.layout.VBox {
+public class OneXStrategy extends VBox implements BettingStrategyInterface {
     private final List<SoccerMatch> matches = new ArrayList<>();
     private NumberStatRow matchesPlayedStatRow;
     private NumberStatRow matchesWonStatRow;
     private NumberStatRow matchesLostStatRow;
     private FloatStatRow wonLossBank;
     private FloatStatRow betAmount;
-    public OneXStatPanel() {
+    ScrollPane matchesSummaryScrollPane;
+
+    public OneXStrategy() {
         super();
         buildSettingsGuiPanel();
         buildStatGuiPanel();
+        buildMatchSummaryPanel();
 
-        System.out.println(this.getWidth() + " " + this.getHeight());
         this.setStyle("-fx-background-color: orange");
     }
 
-    public OneXStatPanel(List<SoccerMatch> matches) {
+    public OneXStrategy(List<SoccerMatch> matches) {
         super();
         buildSettingsGuiPanel();
         buildStatGuiPanel();
+        buildMatchSummaryPanel();
 
         setMatches(matches);
     }
 
-    public void setMatches(List<SoccerMatch> matches) {
-        this.matches.clear();
-        this.matches.addAll(matches);
-    }
-
-    public void runTest() {
-        for (SoccerMatch match : matches) {
-            float OneXOdds = calculate1XOdds(match);
-            if ( OneXOdds > 1.60 && OneXOdds < 2.50) {
-                // bet on home win or draw
-
-            }
-        }
-    }
-
-    private void buildSettingsGuiPanel() {
+    @Override
+    public void buildSettingsGuiPanel() {
         betAmount = new FloatStatRow("Bet Amount", 10f);
-
         this.getChildren().add(betAmount);
     }
 
-    private void buildStatGuiPanel() {
+    @Override
+    public void buildStatGuiPanel() {
         matchesPlayedStatRow = new NumberStatRow("Number of matches played", 0);
         matchesWonStatRow = new NumberStatRow("Number of matches won", 0);
         matchesLostStatRow = new NumberStatRow("Number of matches lost", 0);
@@ -87,16 +81,57 @@ public class OneXStatPanel extends javafx.scene.layout.VBox {
         this.getChildren().add(wonLossBank);
     }
 
-    private float calculate1XOdds(SoccerMatch match) {
-        return match.getOddsX() * match.getOdds1() / (match.getOddsX() + match.getOdds1());
+    @Override
+    public void buildMatchSummaryPanel() {
+        matchesSummaryScrollPane = new ScrollPane();
+        matchesSummaryScrollPane.setContent(new VBox());
+        matchesSummaryScrollPane.setMaxHeight(200d);
+
+        this.getChildren().add(matchesSummaryScrollPane);
     }
 
-    private float calculateX2Odds(SoccerMatch match) {
-        return match.getOddsX() * match.getOdds2() / (match.getOddsX() + match.getOdds2());
+    /**
+     * Sets the list of soccer matches to be used by this strategy.
+     *
+     * @param matches The list of soccer matches to be used.
+     */
+    public void setMatches(List<SoccerMatch> matches) {
+        this.matches.clear();
+        this.matches.addAll(matches);
     }
 
-    private float calculate12Odds(SoccerMatch match) {
-        return match.getOdds1() * match.getOdds2() / (match.getOdds1() + match.getOdds2());
+    /**
+     * Runs the One X strategy test on the list of soccer matches.
+     * For each match, it calculates the 1X odds and checks if they are between 1.60 and 2.50.
+     * If the odds are in this range, it bets on the home team to win or draw.
+     * It updates the match summary panel, the statistics, and the bank balance accordingly.
+     */
+    public void runTest() {
+        for (SoccerMatch match : matches) {
+            final float oneXOdds = calculate1XOdds(match);
+            if ( shouldBetOn(match).equals("1X")) {
+                // bet on home win or draw
+                ((VBox)matchesSummaryScrollPane.getContent()).getChildren().add(new MatchSummaryPanelRow(match, wonLossBank.getValue(), oneXOdds, betAmount.getValue()));
+                matchesPlayedStatRow.increaseValue();
+                if (match.getHomeScore() >= match.getAwayScore()) {
+                    matchesWonStatRow.increaseValue();
+                    wonLossBank.increaseValue((betAmount.getValue() * oneXOdds) - betAmount.getValue());
+                } else {
+                    matchesLostStatRow.increaseValue();
+                    wonLossBank.decreaseValue(betAmount.getValue());
+                }
+            }
+        }
     }
 
+    @Override
+    public String shouldBetOn(SoccerMatch match) {
+        return calculate1XOdds(match) > 1.60 && calculate1XOdds(match) < 2.50?"1X":"";
+    }
+
+    @Override
+    public List<SoccerMatch> sortMatchesOnBetPotential(List<SoccerMatch> matches) {
+        // Not used in this strategy
+        return Collections.emptyList();
+    }
 }

+ 6 - 4
OddsJavaFx/src/cronjob/updateStatistics.java

@@ -1,7 +1,9 @@
 package cronjob;
 
 import data.GuiMysql;
-import objects.*;
+import objects.League;
+import objects.SoccerMatch;
+import objects.SoccerMatchAnalysis;
 
 import java.sql.*;
 import java.time.LocalDate;
@@ -49,8 +51,8 @@ public class updateStatistics {
             diff = homeTeamRes - awayTeamRes;
             db.addWinLossRatioStat(match,l.getLeagueId(),l.getScoringTotal(), diff);
 
-            homeTeamRes = match.winLossRatioHomeAndAway(true, l.getWinLossRatioHomeAndAway());
-            awayTeamRes = match.winLossRatioHomeAndAway(false, l.getWinLossRatioHomeAndAway());
+            homeTeamRes = match.winLossRatioHomeAndAway( l.getWinLossRatioHomeAndAway(), true);
+            awayTeamRes = match.winLossRatioHomeAndAway( l.getWinLossRatioHomeAndAway(), false);
             diff = homeTeamRes - awayTeamRes;
             db.addWinLossRatioHomeAndAwayStat(match, l.getLeagueId(), l.getWinLossRatioHomeAndAway(), diff);
 
@@ -76,7 +78,7 @@ public class updateStatistics {
     }
 
     private List<SoccerMatchAnalysis> getMatchesToUpdate(String lastUpdatedStatisticsDate) {
-        String sql = "SELECT * FROM SoccerResults WHERE prio = 1 AND DATE(gameDate) > ?";
+        String sql = "SELECT * FROM SoccerResults sr JOIN League l on l.id = sr.leagueId WHERE l.prio = 1 AND DATE(gameDate) > ?";
         List<SoccerMatchAnalysis> result = new ArrayList<>();
         try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
             stat.setString(1, lastUpdatedStatisticsDate);

+ 108 - 1
OddsJavaFx/src/data/BetStrategyMysql/BetStrategyMysql.java

@@ -1,2 +1,109 @@
-package data.BetStrategyMysql;public class BetStrategyMysql {
+package data.BetStrategyMysql;
+
+import data.DTO.FibonacciDTO.FibonacciDTO;
+import data.GuiMysql;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BetStrategyMysql extends GuiMysql {
+
+    private BetStrategyMysql() {
+        super();
+    }
+    private static BetStrategyMysql instance;
+
+    public static BetStrategyMysql getInstance() {
+        if (instance == null) {
+            instance = new BetStrategyMysql();
+        }
+        return instance;
+    }
+
+    public void addFibonacciBet(FibonacciDTO fibonacciDTO) {
+        String sql = "INSERT INTO FibonacciBets (betSequence, matchId, odds, status) VALUES (?, ?, ?, ?)";
+        try (PreparedStatement statement = getConnection().prepareStatement(sql);) {
+            int sequenceNumber = fibonacciDTO.getSequenceNumber();
+            if (sequenceNumber < 0) {
+                sequenceNumber = getNextSequenceNumber();
+            }
+            statement.setInt(1, sequenceNumber);
+            statement.setInt(2, fibonacciDTO.getMatchId());
+            statement.setFloat(3, fibonacciDTO.getOdds());
+            statement.setString(4,"OPEN");
+            statement.executeUpdate();
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public int getNextSequenceNumber() {
+        int sequenceNumber = 0;
+        String sql = "SELECT MAX(betSequence) FROM FibonacciBets";
+        try (PreparedStatement statement = getConnection().prepareStatement(sql);) {
+            ResultSet resultSet = statement.executeQuery();
+            if (resultSet.next()) {
+                sequenceNumber = resultSet.getInt(1);
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return sequenceNumber + 1;
+    }
+
+    public float getTotalBetAmountFibonacci(int sequenceNumber) {
+        float totalBetAmount = 0;
+        String sql = "SELECT SUM(betAmount) FROM FibonacciBets WHERE betSequence = ?";
+        try (PreparedStatement statement = getConnection().prepareStatement(sql);) {
+
+            statement.setInt(1, sequenceNumber);
+            ResultSet resultSet = statement.executeQuery();
+            if (resultSet.next()) {
+                totalBetAmount = resultSet.getFloat(1);
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return totalBetAmount;
+    }
+
+    public List<FibonacciDTO> getAllOpenFibonacciSequences() {
+        List<FibonacciDTO> fibonacciDTOList = new ArrayList<>();
+        String sql = "SELECT fb.*, ht.name as homeTeamName, awt.name as awayTeamName, sr.gameDate as gameDate FROM FibonacciBets fb JOIN SoccerResults sr ON sr.id = fb.matchId JOIN Team ht on ht.id = sr.homeTeamId JOIN Team awt ON awt.id = sr.awayTeamId WHERE status = ?";
+        try (PreparedStatement statement = getConnection().prepareStatement(sql);) {
+            statement.setString(1, "OPEN");
+            ResultSet resultSet = statement.executeQuery();
+            while (resultSet.next()) {
+                FibonacciDTO fibonacciDTO = new FibonacciDTO();
+                fibonacciDTO.setSequenceNumber(resultSet.getInt("betSequence"));
+                fibonacciDTO.setMatchId(resultSet.getInt("matchId"));
+                fibonacciDTO.setOdds(resultSet.getFloat("odds"));
+                fibonacciDTO.setGameDate(resultSet.getString("gameDate"));
+                //fibonacciDTO.setBetAmount(resultSet.getFloat("betAmount"));
+                fibonacciDTO.setStatus(resultSet.getString("status"));
+                fibonacciDTO.setHomeTeamName(resultSet.getString("homeTeamName"));
+                fibonacciDTO.setAwayTeamName(resultSet.getString("awayTeamName"));
+                fibonacciDTOList.add(fibonacciDTO);
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return fibonacciDTOList;
+    }
+
+    public void removeFibonacciBet(int sequenceNumber) {
+        String sql = "UPDATE FibonacciBets SET status = ? WHERE betSequence = ? ";
+        try (PreparedStatement statement = getConnection().prepareStatement(sql);) {
+            statement.setString(1, "CLOSED");
+            statement.setInt(2, sequenceNumber);
+            statement.executeUpdate();
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+
 }

+ 76 - 1
OddsJavaFx/src/data/DTO/FibonacciDTO/FibonacciDTO.java

@@ -1,2 +1,77 @@
-package data.DTO.FibonacciDTO;public class FibonacciDTO {
+package data.DTO.FibonacciDTO;
+
+public class FibonacciDTO {
+    private int matchId;
+    private float odds;
+    private float betAmount;
+    private String status;
+    private int sequenceNumber = -1;
+
+    String homeTeamName;
+    String awayTeamName;
+    private String gameDate;
+
+    public void setSequenceNumber(int betSequence) {
+        this.sequenceNumber = betSequence;
+    }
+
+    public int getSequenceNumber() {
+        return sequenceNumber;
+    }
+
+    public void setMatchId(int matchId) {
+        this.matchId = matchId;
+    }
+
+    public int getMatchId() {
+        return matchId;
+    }
+
+    public void setOdds(float odds) {
+        this.odds = odds;
+    }
+
+    public float getOdds() {
+        return odds;
+    }
+
+    public void setBetAmount(float betAmount) {
+        this.betAmount = betAmount;
+    }
+
+    public float getBetAmount() {
+        return betAmount;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public String getHomeTeamName() {
+        return homeTeamName;
+    }
+
+    public void setHomeTeamName(String homeTeamName) {
+        this.homeTeamName = homeTeamName;
+    }
+
+    public String getAwayTeamName() {
+        return awayTeamName;
+    }
+
+    public void setAwayTeamName(String awayTeamName) {
+        this.awayTeamName = awayTeamName;
+    }
+
+    public void setGameDate(String gameDate) {
+        this.gameDate = gameDate;
+    }
+
+    public String getGameDate() {
+        return gameDate;
+    }
 }

+ 115 - 37
OddsJavaFx/src/data/GuiMysql.java

@@ -1,34 +1,22 @@
 package data;
 
-import java.io.IOException;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import mysql.Mysql;
+import objects.*;
+import objects.bets.Bet;
+import objects.bets.Bet.Status;
+import org.eclipse.jetty.util.log.Log;
+
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import java.sql.Array;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
+import java.sql.*;
 import java.text.DecimalFormat;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.Date;
 import java.util.AbstractMap.SimpleEntry;
-import java.util.logging.FileHandler;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.logging.SimpleFormatter;
-
-import objects.*;
-import org.eclipse.jetty.util.log.Log;
-
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
-import com.mysql.cj.x.protobuf.MysqlxPrepare.Prepare;
-
-import mysql.Mysql;
-import objects.bets.Bet;
-import objects.bets.Bet.Status;
 
 public class GuiMysql extends Mysql {
 
@@ -49,22 +37,10 @@ public class GuiMysql extends Mysql {
     public static final String GAME_DATE = "gameDate";
     private final Connection conn;
 
-    private Logger settingsLogger = Logger.getLogger("SettingsLogger");
-    FileHandler settingsLoggerFileHandler;
 
     protected GuiMysql() {
         super();
         conn = this.getConnection();
-        try {
-            settingsLoggerFileHandler = new FileHandler(System.getProperty("user.dir") + "/SettingsLogger.log");
-            settingsLogger.addHandler(settingsLoggerFileHandler);
-            settingsLogger.setLevel(Level.ALL);
-            SimpleFormatter formatter = new SimpleFormatter();
-            settingsLoggerFileHandler.setFormatter(formatter);
-
-        } catch (SecurityException | IOException e) {
-            e.printStackTrace();
-        }
     }
 
     public static GuiMysql getInstance() {
@@ -1594,8 +1570,8 @@ public class GuiMysql extends Mysql {
         List<SoccerMatchAnalysis> matches = getMatches(leagueId);
 
         for (SoccerMatchAnalysis match : matches) {
-            int homeRatio = match.winLossRatioHomeAndAway(true, lookback);
-            int awayRatio = match.winLossRatioHomeAndAway(false, lookback);
+            int homeRatio = match.winLossRatioHomeAndAway( lookback, true);
+            int awayRatio = match.winLossRatioHomeAndAway( lookback, false);
 
             int diff = homeRatio - awayRatio;
             addWinLossRatioHomeAndAwayStat(match, leagueId, lookback, diff);
@@ -1706,6 +1682,30 @@ public class GuiMysql extends Mysql {
         return result;
     }
 
+    public List<SoccerMatch> getPrioMatchesByDate(String date) {
+        List<SoccerMatch> result = new ArrayList<>();
+
+        String sql = "SELECT * FROM SoccerResults sr JOIN League l ON l.id = sr.leagueId WHERE DATE(gameDate) = ? AND l.prio = 1";
+
+        try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
+            stat.setString(1, date);
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                Team homeTeam = getTeam(rs.getInt(HOME_TEAM_ID));
+                Team awayTeam = getTeam(rs.getInt(AWAY_TEAM_ID));
+                result.add(new SoccerMatch(rs.getInt("id"), homeTeam, awayTeam, rs.getFloat(ODDS_1),
+                        rs.getFloat(ODDS_X), rs.getFloat(ODDS_2), rs.getInt(HOME_SCORE), rs.getInt(AWAY_SCORE),
+                        LocalDateTime.parse(rs.getString(GAME_DATE)), rs.getString(SEASON)));
+            }
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
     public List<League> getLeaguesWithPrio() {
         List<League> result = new ArrayList<>();
         String sql = "SELECT * FROM League WHERE prio = 1";
@@ -1876,10 +1876,88 @@ public class GuiMysql extends Mysql {
                 stat.setInt(2, leagueId);
 
                 int res = stat.executeUpdate();
-                settingsLogger.log(Level.INFO, String.format("Updated %s to %s", setting, value));
             }
         } catch (SQLException e) {
             e.printStackTrace();
         }
     }
+
+    public List<SoccerMatch> getLeagueMatches(int leagueId) {
+        return getLeagueMatches("1990-01-01", leagueId);
+    }
+
+    public List<SoccerMatch> getLeagueMatches(String startDate, int leagueId) {
+        String sql = "SELECT * FROM SoccerResults sm JOIN League l ON l.id = sm.leagueId JOIN Team ht ON ht.id = sm.homeTeamId JOIN Team awt ON awt.id = sm.awayTeamId WHERE l.id = ? AND DATE(gameDate) > ? ORDER BY gameDate ASC";
+        List<SoccerMatch> matches = new ArrayList<>();
+
+        try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
+            stat.setInt(1, leagueId);
+            stat.setString(2, startDate);
+            ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                matches.add(new SoccerMatch(rs));
+            }
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return matches;
+    }
+
+    public List<SoccerMatch> getPrioMatches() {
+        return getPrioMatches("1990-01-01");
+    }
+
+    public List<SoccerMatch> getPrioMatches(String startDate) {
+        String sql = "SELECT * FROM SoccerResults sm JOIN League l ON l.id = sm.leagueId JOIN Team ht ON ht.id = sm.homeTeamId JOIN Team awt ON awt.id = sm.awayTeamId WHERE l.prio = 1 AND DATE(gameDate) > ? ORDER BY gameDate ASC";
+        List<SoccerMatch> matches = new ArrayList<>();
+
+        try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
+            stat.setString(1, startDate);
+            ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                matches.add(new SoccerMatch(rs));
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return matches;
+    }
+
+    public List<SoccerMatch> getPrioMatchesOfDate(String date) {
+        String sql = "SELECT * FROM SoccerResults sm JOIN League l ON l.id = sm.leagueId JOIN Team ht ON ht.id = sm.homeTeamId JOIN Team awt ON awt.id = sm.awayTeamId WHERE l.prio = 1 AND DATE(gameDate) = ? ORDER BY gameDate ASC";
+        List<SoccerMatch> matches = new ArrayList<>();
+
+        try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
+            stat.setString(1, date);
+            ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                matches.add(new SoccerMatch(rs));
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return matches;
+    }
+
+
+    public List<SoccerMatch> getPrioMatches(String startDate, String endDate) {
+        String sql = "SELECT * FROM SoccerResults sm JOIN League l ON l.id = sm.leagueId JOIN Team ht ON ht.id = sm.homeTeamId JOIN Team awt ON awt.id = sm.awayTeamId WHERE l.prio = 1 AND DATE(gameDate) > ? AND DATE(gameDate) < ? AND DATE(gameDate) < DATE(NOW()) AND homeScore >= 0 AND awayScore >= 0 ORDER BY gameDate ASC";
+        List<SoccerMatch> matches = new ArrayList<>();
+
+
+        try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
+            stat.setString(1, startDate);
+            stat.setString(2, endDate);
+            ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                matches.add(new SoccerMatch(rs));
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return matches;
+    }
+
 }

+ 256 - 1
OddsJavaFx/src/data/MatchStatSql.java

@@ -1,2 +1,257 @@
-package data;public class MatchStatSql {
+package data;
+
+import objects.SoccerMatch;
+import objects.TeamResults;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class MatchStatSql extends GuiMysql {
+
+    private final Logger LOG = Logger.getLogger(this.getClass().getName());
+
+    public List<SoccerMatch> getAllMatchesForLeague(int leagueId) {
+        return getAllMatchesForLeague(leagueId, "DATE(NOW())");
+    }
+
+    public List<SoccerMatch> getAllMatchesForLeague(int leagueId, String stopDate) {
+        List<SoccerMatch> result = new ArrayList<>();
+
+        String sql = "SELECT * FROM SoccerResults sr " +
+                "JOIN Team ht ON ht.id = sr.homeTeamId " +
+                "JOIN Team awt ON awt.id = sr.awayTeamId " +
+                "JOIN League l ON l.id = sr.leagueId " +
+                "WHERE sr.leagueId = ? AND DATE(gameDate) < "+stopDate+" ORDER BY gameDate ASC";
+        try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
+            stat.setInt(1, leagueId);
+
+            ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                result.add(new SoccerMatch(rs));
+            }
+
+        } catch (SQLException e) {
+            System.out.println(String.format("Something wrong with sql %n%s", sql));
+            e.printStackTrace();
+            LOG.log(Level.ALL, String.format("Something wrong with sql %n%s", sql), e);
+        }
+        return result;
+    }
+
+    public int goalsScoredLastXGames(int teamId, boolean homeTeam, int limit) {
+        return goalsScoredLastXGames(teamId, homeTeam, "DATE(NOW())", limit);
+    }
+
+    public int goalsScoredLastXGames(int teamId, boolean homeTeam, String gameDate, int limit) {
+        int result = 0;
+        String sql = "SELECT sum(hs." + (homeTeam ? "home" : "away") + "Score) res FROM " +
+                "(SELECT " + (homeTeam ? "home" : "away") + "Score FROM SoccerResults sr " +
+                "WHERE sr." + (homeTeam ? "home" : "away") + "TeamId = ? AND " +
+                "DATE(gameDate) < ? " +
+                "ORDER BY gameDate DESC " +
+                "LIMIT ?) hs;";
+
+        try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
+            stat.setInt(1, teamId);
+            stat.setString(2, gameDate);
+            stat.setInt(3, limit);
+            ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                result = rs.getInt("res");
+            }
+        } catch (SQLException e) {
+            LOG.log(Level.ALL, String.format("Something wrong with sql %n%s", sql), e);
+        }
+        return result;
+    }
+
+    public int goalsScoreLastXGamesHomeANDAway(int teamId, int limit) {
+        return goalsScoreLastXGamesHomeANDAway(teamId, "DATE(NOW())", limit);
+    }
+
+    public int goalsScoreLastXGamesHomeANDAway(int teamId, String gameDate, int limit) {
+        int result = 0;
+        String sql = "SELECT sum(score) res FROM " +
+                "(SELECT IF (sr.homeTeamId = ?, sr.homeScore, sr.awayScore) score " +
+                "FROM SoccerResults sr " +
+                "WHERE (sr.homeTeamId = ? OR " +
+                "sr.awayTeamId = ?) AND " +
+                "DATE(gameDate) < ? " +
+                "ORDER BY gameDate DESC " +
+                "LIMIT ?) hs;";
+        try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
+            stat.setInt(1, teamId);
+            stat.setInt(2, teamId);
+            stat.setInt(3, teamId);
+            stat.setString(4, gameDate);
+            stat.setInt(5, limit);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result = rs.getInt("res");
+            }
+        } catch (SQLException e) {
+            LOG.log(Level.ALL, String.format("Something wrong with sql %n%s", sql), e);
+        }
+        return result;
+    }
+
+    public TeamResults formLastXGames(int teamId, int limit) {
+        return formLastXGames(teamId, "DATE(NOW())", limit);
+    }
+
+    public TeamResults formLastXGames(int teamId, String gameDate, int limit) {
+        TeamResults result = new TeamResults();
+
+        String sql = "SELECT sum(win) as wins, sum(draw) as draws, sum(loss) as losses FROM " +
+                "(SELECT CASE WHEN homeTeamId = ? AND " +
+                "homeScore > awayScore THEN 1 ELSE 0 end win," +
+                "CASE WHEN homeTeamId = ? AND homeScore = awayScore THEN 1 ELSE 0 end draw," +
+                "CASE WHEN homeTeamId = ? AND homeScore < awayScore THEN 1 ELSE 0  end loss" +
+                "FROM SoccerResults sr " +
+                "WHERE sr.homeTeamId = ? AND " +
+                "DATE(gameDate) < ? " +
+                "ORDER BY gameDate DESC " +
+                "LIMIT ?) h;";
+
+        try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
+            stat.setInt(1,teamId);
+            stat.setInt(2,teamId);
+            stat.setInt(3,teamId);
+            stat.setInt(4,teamId);
+
+            stat.setString(5, gameDate);
+            stat.setInt(6, limit);
+
+            ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                result.setWins(rs.getInt("wins"));
+                result.setDraws(rs.getInt("draws"));
+                result.setLosses(rs.getInt("losses"));
+                result.setCount(limit);
+            }
+        } catch (SQLException e) {
+            LOG.log(Level.ALL, String.format("Something wrong with sql %n%s", sql), e);
+        }
+
+        return result;
+    }
+
+    public TeamResults formLastXGamesHomeANDAway(int teamId, int limit) {
+        return formLastXGamesHomeANDAway(teamId, "DATE(NOW())", limit);
+    }
+
+    public TeamResults formLastXGamesHomeANDAway(int teamId, String gameDate, int limit) {
+        TeamResults result = new TeamResults();
+        String sql = "SELECT sum(win) as wins, sum(draw) as draws, sum(loss) as losses FROM " +
+                "(SELECT CASE WHEN homeTeamId = ? AND homeScore > awayScore THEN 1 " +
+                    "WHEN awayTeamId = ? AND awayScore > homeScore THEN 1 " +
+                    "ELSE 0 END win," +
+                "CASE WHEN (homeTeamId = ? OR awayTeamId = ?) AND homeScore = awayScore THEN 1 " +
+                    "ELSE 0 END draw," +
+                "CASE WHEN homeTeamId = ? AND homeScore < awayScore THEN 1 " +
+                    "WHEN awayTeamId = ? AND awayScore < homeScore THEN 1 " +
+                    "ELSE 0 END loss" +
+                "FROM SoccerResults sr " +
+                "WHERE (sr.homeTeamId = ? OR sr.awayTeamId = ?) AND " +
+                "DATE(gameDate) < ? " +
+                "ORDER BY gameDate DESC " +
+                "LIMIT ?) h;";
+
+        try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
+            stat.setInt(1, teamId);
+            stat.setInt(2, teamId);
+            stat.setInt(3, teamId);
+            stat.setInt(4, teamId);
+            stat.setInt(5, teamId);
+            stat.setInt(6, teamId);
+            stat.setInt(7, teamId);
+            stat.setInt(8, teamId);
+            stat.setString(9, gameDate);
+            stat.setInt(10, limit);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result.setWins(rs.getInt("wins"));
+                result.setDraws(rs.getInt("draws"));
+                result.setLosses(rs.getInt("losses"));
+            }
+
+        } catch (SQLException e) {
+            LOG.log(Level.ALL, String.format("Something wrong with sql %n%s", sql), e);
+        }
+        return result;
+    }
+
+    public int totalGoalResult(int teamId, boolean home, int limit) {
+        return totalGoalResult(teamId, "DATE(NOW())", home, limit);
+    }
+    public int totalGoalResult(int teamId, String gameDate, boolean home, int limit) {
+        int result = 0;
+
+        String sql = "SELECT " + (home?"sum(homeScore - awayScore)":"sum(awayScore - homeScore)") + " res FROM " +
+                "(SELECT homeScore, awayScore " +
+                "FROM SoccerResults sr " +
+                "WHERE sr."+ (home?"home":"away") + "TeamId = ? AND " +
+                "DATE(gameDate) < ? " +
+                "ORDER BY gameDate DESC " +
+                "LIMIT ?) h;";
+
+        try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
+            stat.setInt(1, teamId);
+            stat.setString(2, gameDate);
+            stat.setInt(3, limit);
+
+            ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                result = rs.getInt("res");
+            }
+        } catch (SQLException e) {
+            LOG.log(Level.ALL, String.format("Something wrong with sql %n%s", sql), e);
+        }
+        return result;
+    }
+
+
+    public int totalGoalResultHomeANDAway(int teamId, int limit) {
+        return totalGoalResultHomeANDAway(teamId, "DATE(NOW())", limit);
+    }
+    public int totalGoalResultHomeANDAway(int teamId, String gameDate, int limit) {
+        int result = 0;
+
+        String sql = "SELECT SUM(hScore + aScore) res FROM (" +
+                "SELECT CASE " +
+                "WHEN homeTeamId = ? THEN homeScore - awayScore ELSE 0 END hScore, " +
+                "CASE WHEN awayTeamId = ? THEN awayScore - homeScore ELSE 0 END aScore " +
+                "FROM SoccerResults sr " +
+                "WHERE (sr.homeTeamId = ? OR awayTeamId = ?) AND " +
+                "DATE(gameDate) < ? " +
+                "ORDER BY gameDate DESC " +
+                "LIMIT ?) h;";
+
+        try (PreparedStatement stat = getConnection().prepareStatement(sql)) {
+            stat.setInt(1, teamId);
+            stat.setInt(2, teamId);
+            stat.setInt(3, teamId);
+            stat.setInt(4, teamId);
+            stat.setString(5, gameDate);
+            stat.setInt(6, limit);
+
+            ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                result = rs.getInt("res");
+            }
+        } catch (SQLException e) {
+            LOG.log(Level.ALL, String.format("Something wrong with sql %n%s", sql), e);
+        }
+        return result;
+    }
 }
+

+ 24 - 10
OddsJavaFx/src/fxml/MatchStatistics.fxml

@@ -1,14 +1,28 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<?import java.lang.*?>
-<?import java.util.*?>
-<?import javafx.scene.*?>
-<?import javafx.scene.control.*?>
-<?import javafx.scene.layout.*?>
-
-<AnchorPane xmlns="http://javafx.com/javafx"
-            xmlns:fx="http://javafx.com/fxml"
-            fx:controller="$CONTROLLER_NAME$"
-            prefHeight="400.0" prefWidth="600.0" >
+<?import javafx.scene.control.DatePicker?>
+<?import javafx.scene.control.ListView?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.BorderPane?>
+<?import javafx.scene.layout.HBox?>
+<?import javafx.scene.layout.Pane?>
+<?import javafx.scene.layout.VBox?>
 
+<AnchorPane xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.MatchStatisticsController">
+    <BorderPane layoutX="110.0" layoutY="93.0" prefHeight="546.0" prefWidth="893.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+      <left>
+         <VBox minWidth="200.0" BorderPane.alignment="CENTER">
+            <children>
+               <HBox>
+                  <children>
+                     <DatePicker fx:id="datePicker" promptText="DATE" />
+                  </children>
+               </HBox>
+               <ListView fx:id="MatchesListView" VBox.vgrow="ALWAYS" />
+            </children>
+         </VBox>
+      </left>
+      <center>
+         <Pane fx:id="MatchPanel" BorderPane.alignment="CENTER" />
+      </center></BorderPane>
 </AnchorPane>

+ 17 - 25
OddsJavaFx/src/fxml/OddsFxBuilder.fxml

@@ -1,21 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<?import javafx.scene.control.Button?>
-<?import javafx.scene.control.ChoiceBox?>
-<?import javafx.scene.control.ComboBox?>
-<?import javafx.scene.control.SplitPane?>
-<?import javafx.scene.control.Tab?>
-<?import javafx.scene.control.TabPane?>
-<?import javafx.scene.control.TextField?>
-<?import javafx.scene.effect.Light.Distant?>
-<?import javafx.scene.effect.Lighting?>
-<?import javafx.scene.effect.Shadow?>
-<?import javafx.scene.layout.BorderPane?>
-<?import javafx.scene.layout.FlowPane?>
-<?import javafx.scene.layout.Pane?>
-<?import javafx.scene.layout.StackPane?>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
 <?import javafx.scene.text.Font?>
-
 <StackPane prefHeight="800.0" prefWidth="1600.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.MainController">
    <children>
       <BorderPane prefHeight="600.0" prefWidth="1200.0">
@@ -134,6 +121,21 @@
                           <fx:include fx:id="analyser" source="Analyser.fxml" />
                       </content>
                   </Tab>
+                  <Tab text="MatchStatistics">
+                      <content>
+                          <fx:include fx:id="matchStatistics" source="MatchStatistics.fxml" />
+                      </content>
+                  </Tab>
+                  <Tab text="Strategy Tester">
+                      <content>
+                          <fx:include fx:id="strategyTester" source="StrategyTester.fxml" />
+                      </content>
+                  </Tab>
+                  <Tab text="Upcomming Matches">
+                      <content>
+                          <fx:include fx:id="upcommingMatches" source="UpcommingMatches.fxml" />
+                      </content>
+                  </Tab>
               </tabs>
             </TabPane>
          </center>
@@ -144,16 +146,6 @@
                <font>
                   <Font size="65.0" />
                </font>
-               <effect>
-                  <Lighting>
-                     <bumpInput>
-                        <Shadow />
-                     </bumpInput>
-                     <light>
-                        <Light.Distant />
-                     </light>
-                  </Lighting>
-               </effect>
             </TextField>
          </children>
       </Pane>

+ 64 - 15
OddsJavaFx/src/fxml/StrategyTester.fxml

@@ -1,28 +1,77 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
+<?import javafx.scene.control.Button?>
 <?import javafx.scene.control.DatePicker?>
-<?import javafx.scene.control.ListView?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.control.Separator?>
 <?import javafx.scene.layout.AnchorPane?>
 <?import javafx.scene.layout.BorderPane?>
+<?import javafx.scene.layout.FlowPane?>
 <?import javafx.scene.layout.HBox?>
 <?import javafx.scene.layout.Pane?>
 <?import javafx.scene.layout.VBox?>
+<?import javafx.scene.text.Font?>
 
-<AnchorPane xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.MatchStatisticsController">
+<AnchorPane stylesheets="@css/StrategyStyles.css" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.StrategyTesterController">
     <BorderPane layoutX="110.0" layoutY="93.0" prefHeight="546.0" prefWidth="893.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
-      <left>
-         <VBox minWidth="200.0" BorderPane.alignment="CENTER">
+        <center>
+        </center>
+        <top>
+            <VBox minWidth="200.0" BorderPane.alignment="CENTER">
+                <children>
+                    <HBox>
+                        <children>
+                            <DatePicker fx:id="DP_StartDate" promptText="Start date" />
+                            <DatePicker fx:id="DP_EndDate" promptText="End date" />
+                     <Button fx:id="btn_go" disable="true" mnemonicParsing="false" onAction="#runTests" text="Go" textAlignment="CENTER" visible="false" />
+                        </children>
+                    </HBox>
+                </children>
+            </VBox>
+        </top>
+        <center>
+            <Pane fx:id="centerPane" BorderPane.alignment="CENTER">
+                <Label fx:id="L_InfoText" alignment="CENTER" contentDisplay="CENTER" text="Please pick a date" textAlignment="CENTER">
+                    <font>
+                        <Font name="System Bold" size="24.0" />
+                    </font>
+                </Label>
+                <HBox fx:id="HBox_testsPanel" disable="true" spacing="10.0" visible="false">
+                    <VBox fx:id="oneXStatPanel" HBox.hgrow="ALWAYS">
+                        <Label styleClass="Title" text="1X Strategy" />
+                    </VBox>
+                    <VBox fx:id="allInPanel">
+                        <Label styleClass="Title" text="All-In on 1.2" />
+                    </VBox>
+                    <VBox fx:id="oneThreeTwoSixPanel">
+                        <Label styleClass="Title" text="1-3-2-6" />
+                    </VBox>
+                    <VBox fx:id="FibonacciPanel">
+                        <Label styleClass="Title" text="Fibonacci" />
+                    </VBox>
+                    <VBox fx:id="KellyFormulaPanel">
+                        <Label styleClass="Title" text="Kelly Formula" />
+                    </VBox>
+                    <VBox fx:id="DutchingPanel">
+                        <Label styleClass="Title" text="Dutching" />
+                    </VBox>
+                    <VBox fx:id="MoneyRacePanel">
+                        <Label styleClass="Title" text="Money Race" />
+                    </VBox>
+                    <VBox fx:id="BetOnDrawPanel">
+                        <Label styleClass="Title" text="Bet on Draw" />
+                    </VBox>
+                </HBox>
+            </Pane>
+        </center>
+      <bottom>
+         <FlowPane hgap="10.0" prefHeight="20.0" BorderPane.alignment="CENTER">
             <children>
-               <HBox>
-                  <children>
-                     <DatePicker fx:id="datePicker" promptText="DATE" />
-                  </children>
-               </HBox>
-               <ListView fx:id="MatchesListView" VBox.vgrow="ALWAYS" />
+               <Label text="LoadedMatches:" />
+               <Label fx:id="Label_LoadedMatches" text="0" />
+               <Separator orientation="VERTICAL" prefHeight="20.0" />
             </children>
-         </VBox>
-      </left>
-      <center>
-         <Pane fx:id="MatchPanel" BorderPane.alignment="CENTER" />
-      </center></BorderPane>
+         </FlowPane>
+      </bottom>
+    </BorderPane>
 </AnchorPane>

+ 4 - 9
OddsJavaFx/src/fxml/Testing.fxml

@@ -1,14 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<?import javafx.scene.control.Button?>
-<?import javafx.scene.control.ComboBox?>
-<?import javafx.scene.control.DatePicker?>
-<?import javafx.scene.control.SplitPane?>
-<?import javafx.scene.control.TextField?>
-<?import javafx.scene.layout.AnchorPane?>
-<?import javafx.scene.layout.FlowPane?>
-<?import javafx.scene.layout.VBox?>
-
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
 <AnchorPane fx:id="basePane" prefWidth="736.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.TestsController">
    <children>
       <VBox prefHeight="414.0" prefWidth="736.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
@@ -69,6 +62,8 @@
                                     <Button onAction="#analysisTets" text="Analysis Test" />
                                     <Button onAction="#analysisDrawTests" text="Analysis DRAW Test" />
                                     <Button onAction="#updatePrioLeagues" prefWidth="75.0" text="Update Prio League Settings" />
+
+                                     <Button onAction="#runXBestGamesTest" prefWidth="75.0" text="Run the XBestGames test" />
                                  </children>
                               </VBox>
                            </children>

+ 34 - 0
OddsJavaFx/src/fxml/TodaysMatches.fxml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.Tab?>
+<?import javafx.scene.control.TabPane?>
+<?import javafx.scene.control.TableView?>
+<?import javafx.scene.layout.AnchorPane?>
+
+
+<AnchorPane stylesheets="@css/StrategyStyles.css" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.StrategyTesterController">
+   <children>
+      <TabPane tabClosingPolicy="UNAVAILABLE">
+        <tabs>
+          <Tab text="Todays Matches">
+            <content>
+              <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
+                     <children>
+                        <TableView fx:id="todaysMatchesTableView" prefHeight="180.0" prefWidth="254.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
+                     </children>
+                  </AnchorPane>
+            </content>
+          </Tab>
+          <Tab text="Tommorrows Matches">
+            <content>
+              <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
+                     <children>
+                        <TableView fx:id="tomorrowsMatchesTableView" prefHeight="180.0" prefWidth="254.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
+                     </children>
+                  </AnchorPane>
+            </content>
+          </Tab>
+        </tabs>
+      </TabPane>
+   </children>
+</AnchorPane>

+ 64 - 22
OddsJavaFx/src/fxml/UpcommingMatches.fxml

@@ -1,25 +1,67 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<?import javafx.scene.control.Tab?>
-<?import javafx.scene.control.TabPane?>
-<?import javafx.scene.layout.AnchorPane?>
-
-
-<AnchorPane stylesheets="@css/StrategyStyles.css" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.StrategyTesterController">
-   <children>
-      <TabPane tabClosingPolicy="UNAVAILABLE">
-        <tabs>
-          <Tab text="Todays Matches">
-            <content>
-              <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
-            </content>
-          </Tab>
-          <Tab text="Tommorrows Matches">
-            <content>
-              <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
-            </content>
-          </Tab>
-        </tabs>
-      </TabPane>
-   </children>
+<?import javafx.scene.control.*?>
+<?import javafx.scene.layout.*?>
+<AnchorPane stylesheets="@css/StrategyStyles.css" xmlns="http://javafx.com/javafx/21"
+            xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.CommingMatches">
+    <children>
+        <SplitPane dividerPositions="0.75" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0"
+                   AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
+                   AnchorPane.topAnchor="0.0">
+            <items>
+                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
+                    <children>
+                        <TabPane prefHeight="146.0" prefWidth="158.0" tabClosingPolicy="UNAVAILABLE"
+                                 AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
+                                 AnchorPane.topAnchor="0.0">
+                            <tabs>
+                                <Tab text="Todays Matches">
+                                    <content>
+                                        <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
+                                            <children>
+                                                <TableView fx:id="todaysMatchesTableView" prefHeight="117.0"
+                                                           prefWidth="158.0" AnchorPane.bottomAnchor="0.0"
+                                                           AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
+                                                           AnchorPane.topAnchor="0.0"/>
+                                            </children>
+                                        </AnchorPane>
+                                    </content>
+                                </Tab>
+                                <Tab text="Tommorrows Matches">
+                                    <content>
+                                        <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
+                                            <children>
+                                                <TableView fx:id="tomorrowsMatchesTableView" prefHeight="117.0"
+                                                           prefWidth="158.0" AnchorPane.bottomAnchor="0.0"
+                                                           AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
+                                                           AnchorPane.topAnchor="0.0"/>
+                                            </children>
+                                        </AnchorPane>
+                                    </content>
+                                </Tab>
+                            </tabs>
+                        </TabPane>
+                    </children>
+                </AnchorPane>
+                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
+                    <children>
+                        <BorderPane prefHeight="46.0" prefWidth="158.0" AnchorPane.bottomAnchor="0.0"
+                                    AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                            <center>
+                                <VBox fx:id="betsContentPanel" BorderPane.alignment="CENTER"/>
+                            </center>
+                            <left>
+                                <VBox>
+                                    <VBox fx:id="actionsPanel" prefHeight="200.0" prefWidth="100.0"
+                                          BorderPane.alignment="CENTER"/>
+                                    <VBox fx:id="betsPanel" prefHeight="200.0" prefWidth="200.0"
+                                          BorderPane.alignment="CENTER"/>
+                                </VBox>
+                            </left>
+                        </BorderPane>
+                    </children>
+                </AnchorPane>
+            </items>
+        </SplitPane>
+    </children>
 </AnchorPane>

+ 8 - 2
OddsJavaFx/src/fxml/css/StrategyStyles.css

@@ -1,4 +1,10 @@
-VBox {
+Label.Title {
     -fx-border-color: BLACK;
     -fx-border-width: 1px;
-}
+    -fx-font-size: 18px;
+    -fx-font-weight: bold;
+}
+
+.bold-label {
+    -fx-font-weight: bold;
+}

+ 65 - 1
OddsJavaFx/src/interfaces/strategytest/BettingStrategyInterface.java

@@ -1,2 +1,66 @@
-package interfaces.strategytest;public interface bettingStrategyInterface {
+package interfaces.strategytest;
+
+import objects.SoccerMatch;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public interface BettingStrategyInterface {
+
+    void setMatches(List<SoccerMatch> matches);
+    void buildSettingsGuiPanel();
+
+    void buildStatGuiPanel();
+
+    void buildMatchSummaryPanel();
+
+    void runTest();
+    String shouldBetOn(SoccerMatch match);
+
+    List<?> sortMatchesOnBetPotential(List<SoccerMatch> matches);
+
+    default float calculate1XOdds(SoccerMatch match) {
+        return match.getOddsX() * match.getOdds1() / (match.getOddsX() + match.getOdds1());
+    }
+
+    default float calculate1XOdds(float odds1, float oddsX) {
+        return oddsX * odds1 / (oddsX + odds1);
+    }
+
+    default float calculateX2Odds(SoccerMatch match) {
+        return match.getOddsX() * match.getOdds2() / (match.getOddsX() + match.getOdds2());
+    }
+
+    default float calculateX2Odds(float oddsX, float odds2) {
+        return oddsX * odds2 / (oddsX + odds2);
+    }
+
+    default float calculate12Odds(SoccerMatch match) {
+        return match.getOdds1() * match.getOdds2() / (match.getOdds1() + match.getOdds2());
+    }
+
+    default float calculate12Odds(float odds1, float odds2) {
+        return odds1 * odds2 / (odds1 + odds2);
+    }
+
+    default float convertPercentageToOdds(float percentage) {
+        if (percentage > 1f) {
+            return (1f / (percentage / 100));
+        }
+        return (1f / percentage);
+    }
+
+    default float convertOddsToPercentage(float odds) {
+        return 1 / (odds + 1f) * 100;
+    }
+
+    default float convertOddsToPercentageDecimal(float odds) {
+        return 1 / (odds + 1f);
+    }
+
+    default List<SoccerMatch> filterTodaysMatches(List<SoccerMatch> matches, SoccerMatch match) {
+        return matches.stream()
+                .filter(p -> p.getGameDate().toLocalDate().isEqual(match.getGameDate().toLocalDate())).collect(Collectors.toList());
+    }
+
 }

+ 125 - 1
OddsJavaFx/src/objects/MatchViewDTO.java

@@ -1,2 +1,126 @@
-package objects;public class MatchViewDTO {
+package objects;
+
+public class MatchViewDTO extends SoccerMatchAnalysis {
+
+    float homeWinPercent;
+    float drawPercent;
+    float awayWinPercent;
+
+    float calculatedOdds1;
+    float calculatedOddsX;
+    float calculatedOdds2;
+    float calculatedOddsOneX;
+    float calculatedOddsX2;
+    float calculatedOdds12;
+
+    public MatchViewDTO(SoccerMatch match) {
+        super(match);
+
+        Percentages percentages = calculateWinPercentages();
+        homeWinPercent = percentages.getHomeWinPercentage();
+        drawPercent = percentages.getDrawPercentage();
+        awayWinPercent = percentages.getAwayWinPercentage();
+
+        calculatedOddsOneX = calculate1XOdds(match);
+        calculatedOddsX2 = calculateX2Odds(match);
+        calculatedOdds12 = calculate12Odds(match);
+
+    }
+
+    public float getCalculatedOdds1() {
+        return calculatedOdds1;
+    }
+
+    public void setCalculatedOdds1(float calculatedOdds1) {
+        this.calculatedOdds1 = calculatedOdds1;
+    }
+
+    public float getCalculatedOddsX() {
+        return calculatedOddsX;
+    }
+
+    public void setCalculatedOddsX(float calculatedOddsX) {
+        this.calculatedOddsX = calculatedOddsX;
+    }
+
+    public float getCalculatedOdds2() {
+        return calculatedOdds2;
+    }
+
+    public void setCalculatedOdds2(float calculatedOdds2) {
+        this.calculatedOdds2 = calculatedOdds2;
+    }
+
+    public float getCalculatedOddsOneX() {
+        return calculatedOddsOneX;
+    }
+
+    public void setCalculatedOddsOneX(float calculatedOddsOneX) {
+        this.calculatedOddsOneX = calculatedOddsOneX;
+    }
+
+    public float getCalculatedOddsX2() {
+        return calculatedOddsX2;
+    }
+
+    public void setCalculatedOddsX2(float calculatedOddsX2) {
+        this.calculatedOddsX2 = calculatedOddsX2;
+    }
+
+    public float getCalculatedOdds12() {
+        return calculatedOdds12;
+    }
+
+    public void setCalculatedOdds12(float calculatedOdds12) {
+        this.calculatedOdds12 = calculatedOdds12;
+    }
+
+    public float getHomeWinPercent() {
+        return homeWinPercent;
+    }
+
+    public void setHomeWinPercent(float homeWinPercent) {
+        this.homeWinPercent = homeWinPercent;
+    }
+
+    @Override
+    public float getDrawPercent() {
+        return drawPercent;
+    }
+
+    public void setDrawPercent(float drawPercent) {
+        this.drawPercent = drawPercent;
+    }
+
+    public float getAwayWinPercent() {
+        return awayWinPercent;
+    }
+
+    public void setAwayWinPercent(float awayWinPercent) {
+        this.awayWinPercent = awayWinPercent;
+    }
+
+    private float calculate1XOdds(SoccerMatch match) {
+        return match.getOddsX() * match.getOdds1() / (match.getOddsX() + match.getOdds1());
+    }
+
+    private float calculate1XOdds(float odds1, float oddsX) {
+        return oddsX * odds1 / (oddsX + odds1);
+    }
+
+    private float calculateX2Odds(SoccerMatch match) {
+        return match.getOddsX() * match.getOdds2() / (match.getOddsX() + match.getOdds2());
+    }
+
+    private float calculateX2Odds(float oddsX, float odds2) {
+        return oddsX * odds2 / (oddsX + odds2);
+    }
+
+    private float calculate12Odds(SoccerMatch match) {
+        return match.getOdds1() * match.getOdds2() / (match.getOdds1() + match.getOdds2());
+    }
+
+    private float calculate12Odds(float odds1, float odds2) {
+        return odds1 * odds2 / (odds1 + odds2);
+    }
 }

+ 82 - 1
OddsJavaFx/src/objects/OddsStat.java

@@ -1,2 +1,83 @@
-package objects;public class OddsStatt {
+package objects;
+
+import java.util.ArrayList;
+
+public class OddsStat {
+
+    int homeWin = 0;
+    int draw = 0;
+    int awayWin = 0;
+    int gamesCount = 0;
+    private ArrayList<Integer> goalScored = new ArrayList<>();
+
+
+    public void addHomeWin() {
+        homeWin++;
+        gamesCount++;
+    }
+
+    public void addDraw() {
+        draw++;
+        gamesCount++;
+    }
+
+    public void addAwayWin() {
+        awayWin++;
+        gamesCount++;
+    }
+
+    public int getHomeWin() {
+        return homeWin;
+    }
+
+    public void setHomeWin(int homeWin) {
+        this.homeWin = homeWin;
+    }
+
+    public int getDraw() {
+        return draw;
+    }
+
+    public void setDraw(int draw) {
+        this.draw = draw;
+    }
+
+    public int getAwayWin() {
+        return awayWin;
+    }
+
+    public void setAwayWin(int awayWin) {
+        this.awayWin = awayWin;
+    }
+
+    public int getGamesCount() {
+        return gamesCount;
+    }
+
+    public void setGamesCount(int gamesCount) {
+        this.gamesCount = gamesCount;
+    }
+
+    public String getHomeWinPercent() {
+        return String.format("%.2f", (homeWin / (float)gamesCount) * 100);
+    }
+    public String getDrawPercent() {
+        return String.format("%.2f", (draw / (float)gamesCount) * 100);
+    }
+    public String getAwayWinPercent() {
+        return String.format("%.2f" , (awayWin / (float)gamesCount)*100);
+    }
+
+    @Override
+    public String toString() {
+        return "(" + getHomeWinPercent() + ", " + getDrawPercent() + ", " + getAwayWinPercent() + ")";
+    }
+
+    public void addGoalsScored(int numGoals) {
+        goalScored.add(numGoals);
+    }
+
+    public String getAvgGoalsScores() {
+        return String.format("%.2f",goalScored.stream().mapToInt(Integer::intValue).average().orElse(-1.0d));
+    }
 }

+ 49 - 12
OddsJavaFx/src/objects/Percentages.java

@@ -14,13 +14,16 @@ public class Percentages {
     private int winLossRatioHomeWin = 0;
     private int winLossRatioDraw = 0;
     private int winLossRatioAwayWin = 0;
+    private float homeWinPercentage = 0f;
+    private float drawPercentage = 0f;
+    private float awayWinPercentage = 0f;
 
     public int getTotalGoalsHomeWin() {
         return totalGoalsHomeWin;
     }
 
     public void setTotalGoalsHomeWin(int totalGoalsHomeWin) {
-        this.totalGoalsHomeWin = totalGoalsHomeWin;
+        this.totalGoalsHomeWin += totalGoalsHomeWin;
     }
 
     public int getTotalGoalsDraw() {
@@ -28,7 +31,7 @@ public class Percentages {
     }
 
     public void setTotalGoalsDraw(int totalGoalsDraw) {
-        this.totalGoalsDraw = totalGoalsDraw;
+        this.totalGoalsDraw += totalGoalsDraw;
     }
 
     public int getWinLossRatioHomeAndAwayHomeWin() {
@@ -36,7 +39,7 @@ public class Percentages {
     }
 
     public void setWinLossRatioHomeAndAwayHomeWin(int winLossRatioHomeAndAwayHomeWin) {
-        this.winLossRatioHomeAndAwayHomeWin = winLossRatioHomeAndAwayHomeWin;
+        this.winLossRatioHomeAndAwayHomeWin += winLossRatioHomeAndAwayHomeWin;
     }
 
     public int getWinLossRatioHomeAndAwayDraw() {
@@ -44,7 +47,7 @@ public class Percentages {
     }
 
     public void setWinLossRatioHomeAndAwayDraw(int winLossRatioHomeAndAwayDraw) {
-        this.winLossRatioHomeAndAwayDraw = winLossRatioHomeAndAwayDraw;
+        this.winLossRatioHomeAndAwayDraw += winLossRatioHomeAndAwayDraw;
     }
 
     public int getWinLossRatioHomeAndAwayAwayWin() {
@@ -52,7 +55,7 @@ public class Percentages {
     }
 
     public void setWinLossRatioHomeAndAwayAwayWin(int winLossRatioHomeAndAwayAwayWin) {
-        this.winLossRatioHomeAndAwayAwayWin = winLossRatioHomeAndAwayAwayWin;
+        this.winLossRatioHomeAndAwayAwayWin += winLossRatioHomeAndAwayAwayWin;
     }
 
     public int getWinLossRatioHomeWin() {
@@ -60,7 +63,7 @@ public class Percentages {
     }
 
     public void setWinLossRatioHomeWin(int winLossRatioHomeWin) {
-        this.winLossRatioHomeWin = winLossRatioHomeWin;
+        this.winLossRatioHomeWin += winLossRatioHomeWin;
     }
 
     public int getWinLossRatioDraw() {
@@ -68,7 +71,7 @@ public class Percentages {
     }
 
     public void setWinLossRatioDraw(int winLossRatioDraw) {
-        this.winLossRatioDraw = winLossRatioDraw;
+        this.winLossRatioDraw += winLossRatioDraw;
     }
 
     public int getWinLossRatioAwayWin() {
@@ -76,7 +79,7 @@ public class Percentages {
     }
 
     public void setWinLossRatioAwayWin(int winLossRatioAwayWin) {
-        this.winLossRatioAwayWin = winLossRatioAwayWin;
+        this.winLossRatioAwayWin += winLossRatioAwayWin;
     }
 
     public int getTotalGoalsAwayWin() {
@@ -84,7 +87,7 @@ public class Percentages {
     }
 
     public void setTotalGoalsAwayWin(int totalGoalsAwayWin) {
-        this.totalGoalsAwayWin = totalGoalsAwayWin;
+        this.totalGoalsAwayWin += totalGoalsAwayWin;
     }
 
     public int getScoringDiffHomeWin() {
@@ -92,7 +95,7 @@ public class Percentages {
     }
 
     public void setScoringDiffHomeWin(int homeWin) {
-        scoringDiffHomeWin = homeWin;
+        scoringDiffHomeWin += homeWin;
     }
 
     public int getScoringDiffDraw() {
@@ -100,7 +103,7 @@ public class Percentages {
     }
 
     public void setScoringDiffDraw(int draws) {
-        scoringDiffDraw = draws;
+        scoringDiffDraw += draws;
     }
 
     public int getScoringDiffAwayWin() {
@@ -108,7 +111,7 @@ public class Percentages {
     }
 
     public void setScoringDiffAwayWin(int awayWin) {
-        scoringDiffAwayWin = awayWin;
+        scoringDiffAwayWin += awayWin;
     }
 
     public String getCalculation() {
@@ -131,4 +134,38 @@ public class Percentages {
 
         return "(" + homeWin/sum + "%, " + draws/sum + "%, " + awayWin/sum + "%)";
     }
+
+    public void calculatePercentages() {
+        int homeWinValues = scoringDiffHomeWin > 0 ? 1 : 0 + totalGoalsHomeWin > 0 ? 1 : 0 + winLossRatioHomeWin > 0
+                ? 1 : 0 + winLossRatioHomeAndAwayHomeWin > 0 ? 1 : 0;
+        int drawWinValues = scoringDiffDraw > 0 ? 1 : 0 + totalGoalsDraw > 0 ? 1 : 0 + winLossRatioDraw > 0 ? 1 :
+                0 + winLossRatioHomeAndAwayDraw > 0 ? 1 : 0;
+        int awayWinValues = scoringDiffAwayWin > 0 ? 1 : 0 + totalGoalsAwayWin > 0 ? 1 : 0 + winLossRatioAwayWin > 0
+                ? 1 : 0 + winLossRatioHomeAndAwayAwayWin > 0 ? 1 : 0;
+
+        float homeWin =
+                (scoringDiffHomeWin + totalGoalsHomeWin + winLossRatioHomeWin + winLossRatioHomeAndAwayHomeWin) / (float) homeWinValues;
+        float draws =
+                (scoringDiffDraw + totalGoalsDraw + winLossRatioDraw + winLossRatioHomeAndAwayDraw) / (float) drawWinValues;
+        float awayWin =
+                (scoringDiffAwayWin + totalGoalsAwayWin + winLossRatioAwayWin + winLossRatioHomeAndAwayAwayWin) / (float) awayWinValues;
+
+        float sum = homeWin + draws + awayWin;
+
+        homeWinPercentage = homeWin / sum;
+        drawPercentage = draws / sum;
+        awayWinPercentage = awayWin / sum;
+    }
+
+    public float getHomeWinPercentage() {
+        return homeWinPercentage;
+    }
+
+    public float getDrawPercentage() {
+        return drawPercentage;
+    }
+
+    public float getAwayWinPercentage() {
+        return awayWinPercentage;
+    }
 }

+ 52 - 2
OddsJavaFx/src/objects/SoccerMatch.java

@@ -1,10 +1,12 @@
 package objects;
 
+import objects.bets.Bet;
+
 import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
 import java.time.LocalDateTime;
 
-import objects.bets.Bet;
-
 public class SoccerMatch {
 
     private LocalDateTime gameDate;
@@ -48,6 +50,35 @@ public class SoccerMatch {
     public SoccerMatch() {
     }
 
+    public SoccerMatch(ResultSet rs) throws SQLException {
+        homeTeam = new Team();
+        awayTeam = new Team();
+
+        homeTeam.setTeamId(rs.getInt(Constants.HOME_TEAM_ID));
+        awayTeam.setTeamId(rs.getInt(Constants.AWAY_TEAM_ID));
+        homeTeam.setTeamName(rs.getString("ht.name"));
+        awayTeam.setTeamName(rs.getString("awt.name"));
+        homeTeam.setTeamLeagueId(rs.getInt(Constants.LEAGUE_ID));
+        awayTeam.setTeamLeagueId(rs.getInt(Constants.LEAGUE_ID));
+        homeTeam.setTeamLeague(rs.getString("l.name"));
+        awayTeam.setTeamLeague(rs.getString("l.name"));
+        homeTeam.setCountryId(rs.getInt(Constants.COUNTRY_ID));
+        awayTeam.setCountryId(rs.getInt(Constants.COUNTRY_ID));
+
+        gameDate = LocalDateTime.parse(rs.getString(Constants.GAME_DATE));
+        leagueName = rs.getString("l.name");
+        awayScore = rs.getInt(Constants.AWAY_SCORE);
+        homeScore = rs.getInt(Constants.HOME_SCORE);
+        matchId = rs.getInt(Constants.ID);
+        odds1 = rs.getFloat(Constants.ODDS_1);
+        oddsX = rs.getFloat(Constants.ODDS_X);
+        odds2 = rs.getFloat(Constants.ODDS_2);
+        season = rs.getString(Constants.SEASON);
+
+        homeTeamName = homeTeam.getTeamName();
+        awayTeamName = awayTeam.getTeamName();
+    }
+
     public void setMatchData(SoccerMatch match) {
         this.matchId = match.getMatchId();
         this.homeTeam = match.getHomeTeam();
@@ -370,4 +401,23 @@ public class SoccerMatch {
         this.bet = bet;
     }
 
+    public String getMatchResult() {
+        if (homeScore < 0 || awayScore < 0) {
+            return "Unknown";
+        }
+        if (homeScore > awayScore) {
+            return "1";
+        } else if (homeScore == awayScore){
+            return "X";
+        } else if (homeScore < awayScore) {
+            return "2";
+        } else {
+            return "Unknown";
+        }
+    }
+
+    @Override
+    public String toString() {
+        return homeTeamName + " - " + awayTeamName;
+    }
 }

+ 101 - 19
OddsJavaFx/src/objects/SoccerMatchAnalysis.java

@@ -1,15 +1,18 @@
 package objects;
 
+import data.GuiMysql;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.text.DecimalFormat;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.util.List;
 import java.util.Optional;
 
-import data.GuiMysql;
-
 public class SoccerMatchAnalysis extends SoccerMatch {
 
     GuiMysql database;
@@ -20,7 +23,7 @@ public class SoccerMatchAnalysis extends SoccerMatch {
     private int winCount;
     private int winLossRatio;
     private String percentages;
-
+    Percentages calculatedPercentages;
     private int scoringTotalValue;
 
     public SoccerMatchAnalysis(SoccerMatch match) {
@@ -127,10 +130,17 @@ public class SoccerMatchAnalysis extends SoccerMatch {
      */
     public int scoringTotal(int gamesLookback, boolean homeTeam) {
         int result = 0;
-        String sql = "SELECT * FROM " + "(SELECT * FROM SoccerResults WHERE homeTeamId = ? AND leagueId = ? AND DATE" +
+        /* String sql = "SELECT * FROM " + "(SELECT * FROM SoccerResults WHERE homeTeamId = ? AND leagueId = ? AND DATE" +
                 "(gameDate) < ? ORDER BY gameDate DESC LIMIT ?) ht " + "UNION DISTINCT " + "(SELECT * FROM " +
                 "SoccerResults WHERE awayTeamId = ? AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC " +
-                "LIMIT ?)";
+                "LIMIT ?)"; */
+
+        String sql = "SELECT * FROM ( " +
+                "SELECT * FROM SoccerResults " +
+                "WHERE (homeTeamId = ? OR awayTeamId = ?) AND leagueId = ? AND gameDate < ? " +
+                ") AS CombinedResults " +
+                "ORDER BY gameDate DESC " +
+                "LIMIT ?";
 
         try (PreparedStatement stat = database.getDbConnection().prepareStatement(sql)) {
             final Team team;
@@ -141,15 +151,16 @@ public class SoccerMatchAnalysis extends SoccerMatch {
             }
 
             stat.setInt(1, team.getTeamId());
-            stat.setInt(2, team.getTeamLeagueId());
-            stat.setString(3, getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
-            stat.setInt(4, gamesLookback);
+            stat.setInt(2, team.getTeamId());
+            stat.setInt(3, team.getTeamLeagueId());
+            stat.setString(4, getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(5, gamesLookback);
 
-            stat.setInt(5, team.getTeamId());
+           /* stat.setInt(5, team.getTeamId());
             stat.setInt(6, team.getTeamLeagueId());
             stat.setString(7, getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
             stat.setInt(8, gamesLookback);
-
+*/
             ResultSet rs = stat.executeQuery();
 
             while (rs.next()) {
@@ -264,16 +275,29 @@ public class SoccerMatchAnalysis extends SoccerMatch {
         return result;
     }
 
-    public int winLossRatioHomeAndAway(boolean homeTeam, int gamesLookback) {
+    public int winLossRatioHomeAndAway(int gamesLookback, boolean homeTeam) {
         int result = 0;
 
-        String sql = "SELECT * FROM " + "(SELECT * FROM SoccerResults WHERE homeTeamId = ? AND leagueId = ? AND DATE" +
+        String sql = "SELECT * FROM SoccerResults " +
+                "WHERE (homeTeamId = ? OR awayTeamId = ?) " +
+                "AND leagueId = ? " +
+                "AND DATE(gameDate) < ? " +
+                "ORDER BY gameDate DESC " +
+                "LIMIT ?";
+        /*String sql = "SELECT * FROM " + "(SELECT * FROM SoccerResults WHERE homeTeamId = ? AND leagueId = ? AND DATE" +
                 "(gameDate) < ? ORDER BY gameDate DESC LIMIT ?) a " + "UNION DISTINCT " + "(SELECT * FROM " +
                 "SoccerResults WHERE awayTeamId = ? AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC " +
-                "LIMIT ?) " + "ORDER BY gameDate DESC " + "LIMIT ?";
+                "LIMIT ?) " + "ORDER BY gameDate DESC " + "LIMIT ?"; */
+
         Team team = homeTeam ? getHomeTeam() : getAwayTeam();
         try (PreparedStatement stat = database.getDbConnection().prepareStatement(sql)) {
             stat.setInt(1, team.getTeamId());
+            stat.setInt(2, team.getTeamId());
+            stat.setInt(3,team.getTeamLeagueId());
+            stat.setString(4, getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(5, gamesLookback);
+
+           /* stat.setInt(1, team.getTeamId());
             stat.setInt(2, team.getTeamLeagueId());
             stat.setString(3, getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
             stat.setInt(4, gamesLookback);
@@ -283,7 +307,7 @@ public class SoccerMatchAnalysis extends SoccerMatch {
             stat.setString(7, getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
             stat.setInt(8, gamesLookback);
 
-            stat.setInt(9, gamesLookback);
+            stat.setInt(9, gamesLookback); */
 
             ResultSet rs = stat.executeQuery();
 
@@ -304,25 +328,38 @@ public class SoccerMatchAnalysis extends SoccerMatch {
         return result;
     }
 
-    public int goalsScoredHomeAndAway(boolean homeTeam, int gameLookback) {
+    public float goalsScoredHomeAndAway(boolean homeTeam, int gameLookback) {
         int result = 0;
         Team team = homeTeam ? getHomeTeam() : getAwayTeam();
 
-        String sql = "SELECT * FROM " + "(SELECT * FROM SoccerResults WHERE homeTeamId = ? AND leagueId = ? AND DATE" +
+        String sql = "SELECT * FROM SoccerResults " +
+                "WHERE (" + (homeTeam?"home":"away") + "TeamId = ?) " +
+                "  AND leagueId = ? " +
+                "  AND DATE(gameDate) < ? " +
+                "ORDER BY gameDate DESC " +
+                "LIMIT ?";
+
+      /*  String sql = "SELECT * FROM " + "(SELECT * FROM SoccerResults WHERE homeTeamId = ? AND leagueId = ? AND DATE" +
                 "(gameDate) < ? ORDER BY gameDate DESC LIMIT ?) a " + "UNION ALL " + "(SELECT * FROM SoccerResults " +
                 "WHERE awayTeamId = ? AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?) " +
-                "ORDER BY gameDate DESC " + "LIMIT ?";
+                "ORDER BY gameDate DESC " + "LIMIT ?"; */
+
+
 
         try (PreparedStatement stat = database.getDbConnection().prepareStatement(sql)) {
             stat.setInt(1, team.getTeamId());
             stat.setInt(2, team.getTeamLeagueId());
             stat.setString(3, getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
             stat.setInt(4, gameLookback);
+            /*stat.setInt(1, team.getTeamId());
+            stat.setInt(2, team.getTeamLeagueId());
+            stat.setString(3, getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(4, gameLookback);
             stat.setInt(5, team.getTeamId());
             stat.setInt(6, team.getTeamLeagueId());
             stat.setString(7, getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
             stat.setInt(8, gameLookback);
-            stat.setInt(9, gameLookback);
+            stat.setInt(9, gameLookback); */
 
             ResultSet rs = stat.executeQuery();
 
@@ -337,7 +374,14 @@ public class SoccerMatchAnalysis extends SoccerMatch {
         } catch (SQLException e) {
             e.printStackTrace();
         }
-        return result;
+        // TODO Think Should the result be divided by lookback??
+        // NEW TEST, devide by lookback (OR SIZE IF LESS THAN LOOKBACK?
+
+        BigDecimal res = BigDecimal.valueOf((result / (float) gameLookback) * 2);
+        res = res.setScale(1, RoundingMode.HALF_UP);
+
+        DecimalFormat df = new DecimalFormat("#.00");
+        return Float.valueOf(df.format(res.floatValue() / 2.0f).replaceAll(",","."));
     }
 
     public int goalsScoredHomeOrAway(boolean homeTeam, int gameLookback) {
@@ -371,4 +415,42 @@ public class SoccerMatchAnalysis extends SoccerMatch {
     public void setScoringTotalValue(int value) {
         scoringTotalValue = value;
     }
+
+    public Percentages calculateWinPercentages() {
+        calculatedPercentages = new Percentages();
+        League leagueInfo = database.getLeagueInfo(this.getHomeTeam().getTeamLeagueId());
+        int homeScore = this.scoringTotal(leagueInfo.getScoringTotal(), true);
+        int awayScore = this.scoringTotal(leagueInfo.getScoringTotal(), false);
+
+        database.getTotalGoalStat(calculatedPercentages, leagueInfo.getLeagueId(),leagueInfo.getScoringTotal(),
+                homeScore - awayScore);
+
+        database.getScoringDiffLastGames(calculatedPercentages, leagueInfo.getLeagueId(), leagueInfo.getScoringDiffLastGame(),
+                this.getScoringDiffLastGames(leagueInfo.getScoringDiffLastGame()));
+
+        int winLossHAHome = this.winLossRatioHomeAndAway( leagueInfo.getWinLossRatioHomeAndAway(), true);
+        int winLossHAAway = this.winLossRatioHomeAndAway(leagueInfo.getWinLossRatioHomeAndAway(), false);
+        database.getWinLossRatioHomeAndAwayStatistics(calculatedPercentages, leagueInfo.getLeagueId(), leagueInfo.getWinLossRatioHomeAndAway(),
+                winLossHAHome-winLossHAAway);
+
+        int winLossHome = this.winLossRatio(leagueInfo.getWinLossRatio(), true);
+        int winLossAway = this.winLossRatio(leagueInfo.getWinLossRatio(), false);
+        this.winLossRatio(leagueInfo.getWinLossRatio(), false);
+        database.getWinLossRatioStatisticsGames(calculatedPercentages,leagueInfo.getLeagueId(),leagueInfo.getWinLossRatio(),winLossHome-winLossAway);
+
+        calculatedPercentages.calculatePercentages();
+
+        return calculatedPercentages;
+    }
+
+    public Percentages getCalculatedPercentages() {
+        if (calculatedPercentages == null) {
+            calculatedPercentages = calculateWinPercentages();
+        }
+        return calculatedPercentages;
+    }
+
+    public void setCalculatedPercentages(Percentages calculatedPercentages) {
+        this.calculatedPercentages = calculatedPercentages;
+    }
 }

+ 176 - 1
OddsJavaFx/src/objects/visual/FibonacciBets.java

@@ -1,2 +1,177 @@
-package objects.visual;public class FibonacciBets {
+package objects.visual;
+
+import data.BetStrategyMysql.BetStrategyMysql;
+import data.DTO.FibonacciDTO.FibonacciDTO;
+import javafx.scene.control.Button;
+import javafx.scene.control.ComboBox;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.FlowPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+import objects.MatchViewDTO;
+import objects.SoccerMatch;
+
+import java.time.LocalDate;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+public class FibonacciBets extends VBox {
+    BetStrategyMysql database;
+    List<FibonacciDTO> allOpenFibonacciSequences;
+    private final int maxActiveFibonacciSequences = 4;
+    private static final List<Integer> fibonacciNumberSequence = Arrays.asList(1, 1, 2, 3, 5, 8, 13, 21, 34, 55); //,89,144);
+    private SoccerMatch currentMatch;
+    Label matchTeamLabel = new Label();
+    VBox betPanel;
+
+    TextField oddsField;
+    ComboBox<String> sequenceNumberComboBox;
+
+    public FibonacciBets() {
+        database = BetStrategyMysql.getInstance();
+        this.getChildren().add(buildCurrentBetsPanel());
+    }
+
+    private VBox buildCurrentBetsPanel() {
+        VBox panel = new VBox();
+        allOpenFibonacciSequences = database.getAllOpenFibonacciSequences();
+
+        List<Integer> sequenceNumbers = allOpenFibonacciSequences.stream().map(FibonacciDTO::getSequenceNumber).distinct().collect(Collectors.toList());
+
+        for (Integer sequenceNumber : sequenceNumbers) {
+            List<FibonacciDTO> fibonacciDTOs = allOpenFibonacciSequences.stream()
+                    .filter(fibonacciDTO -> fibonacciDTO.getSequenceNumber() == sequenceNumber)
+                    .collect(Collectors.toList());
+
+            FlowPane fibonacciSequencePanel = new FlowPane();
+            fibonacciSequencePanel.setHgap(2);
+            fibonacciSequencePanel.setVgap(2);
+            HBox infoPanel = new HBox(3);
+            infoPanel.getChildren().add(new Label("Sequence Number: " + sequenceNumber + " ; "));
+            infoPanel.getChildren().add(new Label("                    "));
+            int pos = 0;
+            for (Integer i : fibonacciNumberSequence) {
+                Label label = new Label(i.toString());
+                if (pos++ == fibonacciDTOs.size()) {
+                    label.getStyleClass().add("bold-label");
+                }
+                infoPanel.getChildren().add(label);
+            }
+            panel.getChildren().add(infoPanel);
+            for (FibonacciDTO dto : fibonacciDTOs) {
+                fibonacciSequencePanel.getChildren().add(new Label(dto.getHomeTeamName() + " - " + dto.getAwayTeamName() + " (" + dto.getOdds() + ")"));
+                fibonacciSequencePanel.getChildren().add(new Label(";"));
+            }
+            Button removeButton = new Button("X");
+            removeButton.setStyle("-fx-background-color: darkred; -fx-text-fill: white; -fx-font-weight: bold;");
+            removeButton.setOnAction(event -> {
+                database.removeFibonacciBet(sequenceNumber);
+                allOpenFibonacciSequences.removeIf(m -> m.getSequenceNumber() == sequenceNumber);
+                panel.getChildren().remove(fibonacciSequencePanel);
+            });
+            fibonacciSequencePanel.getChildren().add(removeButton);
+
+            panel.getChildren().add(fibonacciSequencePanel);
+        }
+
+        return panel;
+    }
+
+    public int getSequenceToBetOn(LocalDate date) {
+        Optional<FibonacciDTO> sequenceToBetOn = allOpenFibonacciSequences.stream()
+                .filter(p -> !LocalDate.parse(p.getGameDate()).isBefore(date))
+                .min((p1, p2) -> Integer.compare(p1.getSequenceNumber(), p2.getSequenceNumber()));
+
+        return sequenceToBetOn.map(FibonacciDTO::getSequenceNumber).orElse(-1);
+    }
+
+    public List<FibonacciDTO> getOpenFibonacciSequences() {
+        return allOpenFibonacciSequences;
+    }
+
+    public int getMaxActiveFibonacciSequences() {
+        return maxActiveFibonacciSequences;
+    }
+
+    public VBox getNewBetGui() {
+        betPanel = new VBox();
+        if (currentMatch == null) {
+            return betPanel;
+        }
+
+        sequenceNumberComboBox = new ComboBox<>();
+        sequenceNumberComboBox.getItems().addAll(allOpenFibonacciSequences.stream().map(FibonacciDTO::getSequenceNumber).distinct().map(Object::toString).toList());
+        sequenceNumberComboBox.getItems().add("New Sequence");
+
+        matchTeamLabel.setText(currentMatch.toString());
+        oddsField = new TextField();
+        oddsField.setPromptText("Odds");
+
+        betPanel.getChildren().addAll(sequenceNumberComboBox, matchTeamLabel, oddsField);
+        return betPanel;
+    }
+
+    public void setCurrentMatch(SoccerMatch match) {
+        this.currentMatch = match;
+        updateBetsPanel();
+    }
+
+    private void updateBetsPanel() {
+        matchTeamLabel.setText(currentMatch.toString());
+        if (betPanel != null) {
+            betPanel.getChildren().clear();
+            betPanel.getChildren().addAll(sequenceNumberComboBox, matchTeamLabel, oddsField);
+        }
+    }
+
+    public String getOddsField() {
+        return oddsField.getText();
+    }
+
+    public float getOddsFieldFloat() {
+        return Float.parseFloat(oddsField.getText());
+    }
+
+    public int getSequenceNumber() {
+        try {
+            return Integer.parseInt(sequenceNumberComboBox.getValue());
+        } catch (NumberFormatException e) {
+            return database.getNextSequenceNumber();
+        }
+    }
+
+    public boolean validBetSettings() {
+        try {
+            if (Float.parseFloat(oddsField.getText()) < 0.0f) {
+                return false;
+            }
+        } catch (Exception e) {
+            return false;
+        }
+        if (sequenceNumberComboBox.getValue() == null || sequenceNumberComboBox.getValue().isEmpty()) {
+            return false;
+        }
+        return true;
+    }
+
+    public void addBet(int sequenceNumber, float odds, MatchViewDTO match) {
+        List<FibonacciDTO> fibonacciDTO = getOpenFibonacciSequences().stream().filter(p -> p.getSequenceNumber() == sequenceNumber).collect(Collectors.toList());
+        int currentSequenceBetAmount;
+        try {
+            currentSequenceBetAmount = fibonacciNumberSequence.get(fibonacciDTO.size());
+        } catch (IndexOutOfBoundsException e) {
+            return;
+        }
+        FibonacciDTO dto = new FibonacciDTO();
+        dto.setBetAmount(currentSequenceBetAmount);
+        dto.setOdds(odds);
+        dto.setMatchId(match.getMatchId());
+        dto.setSequenceNumber(sequenceNumber);
+        database.addFibonacciBet(dto);
+
+        allOpenFibonacciSequences.add(dto);
+    }
 }

+ 6 - 6
OddsJavaFx/src/tests/AnalysisBettDrawTest.java

@@ -13,7 +13,7 @@ import java.util.*;
 import java.util.Map.Entry;
 import java.util.stream.Collectors;
 
-public class AnalysisBettDrawTester extends TestClass {
+public class AnalysisBettDrawTest extends TestClass {
 
     public class DifferenceAsianBetDTO extends AsianHandicap {
         boolean resolved = false;
@@ -139,10 +139,10 @@ public class AnalysisBettDrawTester extends TestClass {
             float awayTotalGoalsHomeAway = analysis.goalsScoredHomeAndAway(false, leagueInfo.getDrawDiffHomeAway());
             float totalGoalsHomeAwayDecider = homeTotalGoalsHomeAway - awayTotalGoalsHomeAway;
 
-            int homeFormHomeAndAway = analysis.winLossRatioHomeAndAway(true,
-                    leagueInfo.getDrawWinningFormHomeAway());
-            int awayFormHomeAndAway = analysis.winLossRatioHomeAndAway(false,
-                    leagueInfo.getDrawWinningFormHomeAway());
+            int homeFormHomeAndAway = analysis.winLossRatioHomeAndAway(
+                    leagueInfo.getDrawWinningFormHomeAway(), true);
+            int awayFormHomeAndAway = analysis.winLossRatioHomeAndAway(
+                    leagueInfo.getDrawWinningFormHomeAway(), false);
             int formHomeAwayDecider = homeFormHomeAndAway - awayFormHomeAndAway;
 
             int homeWiningForm = analysis.winLossRatio(leagueInfo.getDrawWinningForm(), true);
@@ -246,7 +246,7 @@ public class AnalysisBettDrawTester extends TestClass {
             betsList.add(bet);
             placedBets.put(soccerMatch.decider, betsList);
 
-            // F�r att t�cka upp freg�ende bets
+            // F�r att t�cka upp föreg�ende bets
 
 //            float currentBetAmount = 0;
 ////            betSeries.sort((b1, b2) -> Float.compare(b2.getBetAmount(), b1.getBetAmount()));

+ 12 - 12
OddsJavaFx/src/tests/AnalysisBettTest.java

@@ -1,12 +1,5 @@
 package tests;
 
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map.Entry;
-
 import data.TestDatabase;
 import objects.League;
 import objects.SoccerMatch;
@@ -15,7 +8,14 @@ import objects.bets.AsianHandicap;
 import objects.bets.Bet;
 import tests.objects.LeagueDTO;
 
-public class AnalysisBettTester extends TestClass {
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+public class AnalysisBettTest extends TestClass {
 
     TestDatabase database;
     List<SoccerMatch> betsToPlace = new ArrayList<>();
@@ -76,10 +76,10 @@ public class AnalysisBettTester extends TestClass {
             int homeWinsCount = analysis.winLossRatio(leagueInfo.getWinLossRatio(), true);
             int awayWinsCount = analysis.winLossRatio(leagueInfo.getWinLossRatio(), false);
 
-            int homeWinLossRatioCount = analysis.winLossRatioHomeAndAway(true,
-                    leagueInfo.getWinLossRatioHomeAndAway());
-            int awayWinLossRatioCount = analysis.winLossRatioHomeAndAway(false,
-                    leagueInfo.getWinLossRatioHomeAndAway());
+            int homeWinLossRatioCount = analysis.winLossRatioHomeAndAway(
+                    leagueInfo.getWinLossRatioHomeAndAway(), true);
+            int awayWinLossRatioCount = analysis.winLossRatioHomeAndAway(
+                    leagueInfo.getWinLossRatioHomeAndAway(), false);
 
             int homeScoringTotal = analysis.scoringTotal(leagueInfo.getScoringTotal(), true);
             int awayScoringTotal = analysis.scoringTotal(leagueInfo.getScoringTotal(), false);

+ 4 - 4
OddsJavaFx/src/tests/Away2Test.java

@@ -1,5 +1,8 @@
 package tests;
 
+import objects.League;
+import objects.SoccerMatch;
+
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.time.LocalDate;
@@ -9,10 +12,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 
-import objects.League;
-import objects.SoccerMatch;
-
-public class AwayTests2 extends TestClass {
+public class Away2Test extends TestClass {
 
 	private League leagueInfo;
 

+ 6 - 6
OddsJavaFx/src/tests/AwayTest.java

@@ -1,5 +1,10 @@
 package tests;
 
+import data.GuiMysql;
+import objects.League;
+import objects.SoccerMatch;
+import objects.TeamResults;
+
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.time.LocalDate;
@@ -7,12 +12,7 @@ import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 
-import data.GuiMysql;
-import objects.League;
-import objects.SoccerMatch;
-import objects.TeamResults;
-
-public class AwayTests extends TestClass {
+public class AwayTest extends TestClass {
 
 	private League leagueInfo;
 

+ 7 - 7
OddsJavaFx/src/tests/BetOnDifferenceTest.java

@@ -1,5 +1,11 @@
 package tests;
 
+import data.TestDatabase;
+import objects.SoccerMatch;
+import objects.bets.AsianHandicap;
+import objects.bets.Bet;
+import tests.objects.LeagueDTO;
+
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
@@ -8,13 +14,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map.Entry;
 
-import data.TestDatabase;
-import objects.SoccerMatch;
-import objects.bets.AsianHandicap;
-import objects.bets.Bet;
-import tests.objects.LeagueDTO;
-
-public class BetOnDifference extends TestClass {
+public class BetOnDifferenceTest extends TestClass {
 
     private static final float MIN_DIFF_IN_GOALS = 0.5f;
     private static final float LOWER_LIMIT_COVER_BET = 1.3f;

+ 4 - 4
OddsJavaFx/src/tests/Draw2Tests.java

@@ -1,5 +1,8 @@
 package tests;
 
+import objects.League;
+import objects.SoccerMatch;
+
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.time.LocalDate;
@@ -9,10 +12,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 
-import objects.League;
-import objects.SoccerMatch;
-
-public class DrawTests2 extends TestClass {
+public class Draw2Tests extends TestClass {
 
 	private League leagueInfo;
 

+ 6 - 6
OddsJavaFx/src/tests/DrawTest.java

@@ -1,5 +1,10 @@
 package tests;
 
+import data.GuiMysql;
+import objects.League;
+import objects.SoccerMatch;
+import objects.TeamResults;
+
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.time.LocalDate;
@@ -7,12 +12,7 @@ import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 
-import data.GuiMysql;
-import objects.League;
-import objects.SoccerMatch;
-import objects.TeamResults;
-
-public class DrawTests extends TestClass {
+public class DrawTest extends TestClass {
 
 	private League leagueInfo;
 

+ 4 - 4
OddsJavaFx/src/tests/Home2Test.java

@@ -1,5 +1,8 @@
 package tests;
 
+import objects.League;
+import objects.SoccerMatch;
+
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.time.LocalDate;
@@ -9,10 +12,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 
-import objects.League;
-import objects.SoccerMatch;
-
-public class HomeTests2 extends TestClass {
+public class Home2Test extends TestClass {
 
 	private League leagueInfo;
 

+ 6 - 6
OddsJavaFx/src/tests/HomeTest.java

@@ -1,5 +1,10 @@
 package tests;
 
+import data.GuiMysql;
+import objects.League;
+import objects.SoccerMatch;
+import objects.TeamResults;
+
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.time.LocalDate;
@@ -7,12 +12,7 @@ import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 
-import data.GuiMysql;
-import objects.League;
-import objects.SoccerMatch;
-import objects.TeamResults;
-
-public class HomeTests extends TestClass {
+public class HomeTest extends TestClass {
 
 	private League leagueInfo;
 

+ 7 - 8
OddsJavaFx/src/tests/PrioCountriesAllTest.java

@@ -1,5 +1,11 @@
 package tests;
 
+import com.google.common.collect.Lists;
+import data.GuiMysql;
+import objects.League;
+import objects.SoccerMatch;
+import objects.TeamResults;
+
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -8,14 +14,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
-import com.google.common.collect.Lists;
-
-import data.GuiMysql;
-import objects.League;
-import objects.SoccerMatch;
-import objects.TeamResults;
-
-public class PrioCountriesAll extends TestClass {
+public class PrioCountriesAllTest extends TestClass {
 
     private ArrayList<League> prioLeagues;
 

+ 7 - 13
OddsJavaFx/src/tests/RelevanceTest.java

@@ -1,20 +1,14 @@
 package tests;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.TreeMap;
-
 import data.GuiMysql;
 import data.TestDatabase;
 import objects.SoccerMatch;
 import objects.SoccerMatchAnalysis;
 import tests.objects.LeagueDTO;
 
+import java.util.*;
+import java.util.Map.Entry;
+
 @java.lang.SuppressWarnings("squid:S106")
 public class RelevanceTest extends TestClass {
 
@@ -273,8 +267,8 @@ public class RelevanceTest extends TestClass {
 
         for (SoccerMatch soccerMatch : matches) {
             SoccerMatchAnalysis analysis = new SoccerMatchAnalysis(soccerMatch);
-            int homeWinsCount = analysis.winLossRatioHomeAndAway(true, gamesLookback);
-            int awayWinsCount = analysis.winLossRatioHomeAndAway(false, gamesLookback);
+            int homeWinsCount = analysis.winLossRatioHomeAndAway( gamesLookback, true);
+            int awayWinsCount = analysis.winLossRatioHomeAndAway( gamesLookback, false);
 
             int diff = homeWinsCount - awayWinsCount;
 
@@ -332,8 +326,8 @@ public class RelevanceTest extends TestClass {
             int homeWinsCount = analysis.winLossRatio(winLossRatio, true);
             int awayWindCount = analysis.winLossRatio(winLossRatio, false);
 
-            int homeWinLossRatioCount = analysis.winLossRatioHomeAndAway(true, winLossRationHomeAndAway);
-            int awayWinLossRatioCount = analysis.winLossRatioHomeAndAway(false, winLossRationHomeAndAway);
+            int homeWinLossRatioCount = analysis.winLossRatioHomeAndAway(winLossRationHomeAndAway, true);
+            int awayWinLossRatioCount = analysis.winLossRatioHomeAndAway(winLossRationHomeAndAway, false);
 
             int homeScoringTotal = analysis.scoringTotal(scoringTotal, true);
             int awayScoringTotal = analysis.scoringTotal(scoringTotal, false);

+ 160 - 7
OddsJavaFx/src/tests/XBestRatedGamesBettingTest.java

@@ -2,22 +2,175 @@ package tests;
 
 import data.GuiMysql;
 import objects.SoccerMatch;
+import objects.SoccerMatchAnalysis;
+import tests.objects.GamePercentages;
+import tests.objects.XBestGamesDTO;
+import tests.objects.XBestGamesWinPercentageStatistics;
 
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.stream.Collectors;
 
-public class XBestRatedGamesBetting extends TestClass {
+public class XBestRatedGamesBettingTest extends TestClass {
     GuiMysql db = GuiMysql.getInstance();
     List<SoccerMatch> matches = new ArrayList<>();
 
+    // Lista med spelade matches och dess värden, så att man enkelt kan få ut referens värden på alla mätvärden och
+    // även beräkna procentuell vinschans (och odds)
+
+
+    /**
+     * For each day (with matches) calculate analysis values and compare them to previous matches with the same values
+     * calculate win percentage for both teams and normalize them against each other
+     */
+
     @Override
     public void runTest() {
-        matches.addAll(db.getPrioMatches());
+        //matches.addAll(db.getPrioMatches("2019-01-01"));
+
+        matches.addAll(db.getLeagueMatches("2015-01-01", 15290));
+
+        while (!matches.isEmpty()) {
+            LocalDateTime date = matches.get(0).getGameDate();
+
+            List<SoccerMatch> todaysMatches = matches.stream()
+                    .filter(m -> date.isEqual(m.getGameDate())).toList();
+
+            matches.removeAll(todaysMatches);
+
+            List<XBestGamesDTO> gamesCalculated = new ArrayList<>();
+
+            for (SoccerMatch match : todaysMatches) {
+                SoccerMatchAnalysis matchAnalysis = new SoccerMatchAnalysis(match);
+                XBestGamesDTO dto = new XBestGamesDTO(5, 5);
+                dto.calculateAllData(matchAnalysis);
+                dto.setMatch(match);
+                gamesCalculated.add(dto);
+            }
+
+            for (XBestGamesDTO dto : gamesCalculated) {
+                dto.setPercentages(getPercenages(dto, 5)); // TODO: 5 is hardcoded, should be dynamic
+
+            }
+
+            if (todaysMatches.get(0).getGameDate().isAfter(LocalDateTime.of(2020,1,1, 0, 0))) {
+
+                for (XBestGamesDTO dto : gamesCalculated) {
+
+                    boolean bet = false;
+                    String message = "";
+                    if (dto.getMatch().getOdds1() > dto.getPercenage().getWinOdds()) {
+                        message = "Bet on Home! Diff is: " + (dto.getPercenage().getWinOdds() - dto.getMatch().getOdds1());
+                        bet = true;
+                    }
+                    if(dto.getMatch().getOddsX() > dto.getPercenage().getDrawOdds()) {
+                        message = "Bet on Draw! Diff is: " + (dto.getPercenage().getDrawOdds() - dto.getMatch().getOddsX());
+                        bet = true;
+                    }
+                    if (dto.getMatch().getOdds2() > dto.getPercenage().getLossOdds()) {
+                        message = "Bet on Away! Diff is: " + (dto.getPercenage().getLossOdds() - dto.getMatch().getOdds2());
+                        bet = true;
+                    }
+
+                    if (bet) {
+                        System.out.println(dto.getMatch().getHomeTeamName() + " - " + dto.getMatch().getAwayTeamName() + " (" + dto.getMatch().getOdds1() + ", " + dto.getMatch().getOddsX() + ", " + dto.getMatch().getOdds2() + ") Result: " + dto.getMatch().getHomeScore() + " - " + dto.getMatch().getAwayScore());
+                        System.out.println("calculated percent: " + dto.getPercenage().toString());
+                        System.out.println("Calculated odds; " + dto.getPercenage().toOddsString());
+                        System.out.println(message);
+                    }
+                }
+
+
+                // TODO Pick winners from percentages.
+            }
+            // TODO update statistics with mathes.
+            for (XBestGamesDTO dto : gamesCalculated) {
+                XBestGamesWinPercentageStatistics.INSTANCE.addHomeWinLossRatio(5, dto.getValuesMap().get(5).getHomeWinLossRatio(),
+                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore());
+                XBestGamesWinPercentageStatistics.INSTANCE.addAwayWinLossRatio(5, dto.getValuesMap().get(5).getAwayWinLossRatio(),
+                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore());
+
+                XBestGamesWinPercentageStatistics.INSTANCE.addHomeWinLossRatioHomeAndAwayMap(5, dto.getValuesMap().get(5).getHomeWinLossRatioHomeAndAway(),
+                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore());
+                XBestGamesWinPercentageStatistics.INSTANCE.addAwayWinLossRatioHomeAndAwayMap(5, dto.getValuesMap().get(5).getAwayWinLossRatioHomeAndAway(),
+                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore());
+
+                XBestGamesWinPercentageStatistics.INSTANCE.addHomeScoringTotal(5, dto.getValuesMap().get(5).getHomeScoringTotal(),
+                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore());
+                XBestGamesWinPercentageStatistics.INSTANCE.addAwayScoringTotal(5, dto.getValuesMap().get(5).getAwayScoringTotal(),
+                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore());
+
+                XBestGamesWinPercentageStatistics.INSTANCE.addScoringDiffLastGamesMap(5, dto.getValuesMap().get(5).getScoringDiffLastGames(),
+                        dto.getMatch().getHomeScore() > dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() == dto.getMatch().getAwayScore(),
+                        dto.getMatch().getHomeScore() < dto.getMatch().getAwayScore());
+            }
+
+            // TODO update bank.
+            System.out.println("End of loop for date: " + todaysMatches.get(0).getGameDate());
+        }
+    }
+
+    private GamePercentages getPercenages(XBestGamesDTO dto, int lookback) {
+        XBestGamesDTO.Values valuesMap = dto.getValuesMap().getOrDefault(lookback, new XBestGamesDTO.Values());
+
+        GamePercentages homeWinRatioPercetage = XBestGamesWinPercentageStatistics.INSTANCE.getHomeWinRatioPercetage(lookback, valuesMap.getHomeWinLossRatio());
+        GamePercentages awayWinRatioPercetage = XBestGamesWinPercentageStatistics.INSTANCE.getAwayWinRatioPercetage(lookback, valuesMap.getAwayWinLossRatio());
+
+        GamePercentages homeWinLossRatioHomeAndAwayPercentage = XBestGamesWinPercentageStatistics.INSTANCE.getHomeWinLossRatioHomeAndAwayPercentage(lookback, valuesMap.getHomeWinLossRatioHomeAndAway());
+        GamePercentages awayWinLossRatioHomeAndAwayPercentage = XBestGamesWinPercentageStatistics.INSTANCE.getAwayWinLossRatioHomeAndAwayPercentage(lookback, valuesMap.getAwayWinLossRatioHomeAndAway());
+
+        GamePercentages homeScoringWinPercentage = XBestGamesWinPercentageStatistics.INSTANCE.getHomeScoringWinPercentage(lookback, valuesMap.getHomeScoringTotal());
+        GamePercentages awayScoringWinPercentage = XBestGamesWinPercentageStatistics.INSTANCE.getAwayScoringWinPercentage(lookback, valuesMap.getAwayScoringTotal());
+
+        GamePercentages scoringDiffLastGamesPercentage = XBestGamesWinPercentageStatistics.INSTANCE.getScoringDiffLastGamesPercentage(lookback, valuesMap.getScoringDiffLastGames());
+
+
+        GamePercentages totalPercentages = new GamePercentages((homeWinRatioPercetage.getWinPercent() +
+                homeWinLossRatioHomeAndAwayPercentage.getWinPercent() +
+                homeScoringWinPercentage.getWinPercent() +
+                scoringDiffLastGamesPercentage.getWinPercent()), // +
+                //awayWinRatioPercetage.getLossPercent() +
+                //awayWinLossRatioHomeAndAwayPercentage.getLossPercent() +
+                //awayScoringWinPercentage.getLossPercent()),
+                (homeWinRatioPercetage.getDrawPercent() + awayWinRatioPercetage.getDrawPercent() +
+                        homeWinLossRatioHomeAndAwayPercentage.getDrawPercent() + awayWinLossRatioHomeAndAwayPercentage.getDrawPercent() +
+                        homeScoringWinPercentage.getDrawPercent() + awayScoringWinPercentage.getDrawPercent() + scoringDiffLastGamesPercentage.getDrawPercent()),
+                // homeWinRatioPercetage.getLossPercent() +
+                        awayWinRatioPercetage.getWinPercent() +
+//                        homeWinLossRatioHomeAndAwayPercentage.getLossPercent() +
+                                awayWinLossRatioHomeAndAwayPercentage.getWinPercent() +
+//                        homeScoringWinPercentage.getLossPercent() +
+                                awayScoringWinPercentage.getWinPercent() +
+                                scoringDiffLastGamesPercentage.getLossPercent());
+
+        GamePercentages test = totalPercentages;
+        normalize(totalPercentages);
+
+        return totalPercentages;
+    }
+
+    private void normalize(GamePercentages gamePercentages) {
+        float total = gamePercentages.getWinPercent() + gamePercentages.getDrawPercent() + gamePercentages.getLossPercent();
+        float win = gamePercentages.getWinPercent() / total;
+        float draw = gamePercentages.getDrawPercent() / total;
+        float loss = gamePercentages.getLossPercent() / total;
+
+        gamePercentages.setWinPercent(win);
+        gamePercentages.setDrawPercent(draw);
+        gamePercentages.setLossPercent(loss);
 
-        List<SoccerMatch> todaysMatches = matches.stream()
-                .filter(m -> matches.get(0).getGameDate()
-                        .isEqual(m.getGameDate()))
-                .collect(Collectors.toList());
     }
 }

+ 73 - 1
OddsJavaFx/src/tests/objects/GamePercentages.java

@@ -1,2 +1,74 @@
-package tests.objects;public class GamePercentages {
+package tests.objects;
+
+import objects.SoccerMatch;
+
+public class GamePercentages {
+    float winPercent;
+    float drawPercent;
+    float lossPercent;
+
+    SoccerMatch match;
+
+    public GamePercentages(float winPercent, float drawPercent, float lossPercent) {
+        this.winPercent = winPercent;
+        this.drawPercent = drawPercent;
+        this.lossPercent = lossPercent;
+    }
+
+    public GamePercentages() {
+
+    }
+
+    public SoccerMatch getMatch() {
+        return match;
+    }
+
+    public void setMatch(SoccerMatch match) {
+        this.match = match;
+    }
+
+    public void setWinPercent(float winPercent) {
+        this.winPercent = winPercent;
+    }
+
+    public void setDrawPercent(float drawPercent) {
+        this.drawPercent = drawPercent;
+    }
+
+    public void setLossPercent(float lossPercent) {
+        this.lossPercent = lossPercent;
+    }
+
+    public float getWinPercent() {
+        return winPercent;
+    }
+
+    public float getDrawPercent() {
+        return drawPercent;
+    }
+
+    public float getLossPercent() {
+        return lossPercent;
+    }
+
+    @Override
+    public String toString() {
+        return "Win: " + winPercent + "%, Draw: " + drawPercent + "%, Loss: " + lossPercent + "%";
+    }
+
+    public String toOddsString() {
+        return (1 / (winPercent)) + ", " + (1 / (drawPercent)) + ", " + (1 / (lossPercent));
+    }
+
+    public float getWinOdds() {
+        return 1 / winPercent;
+    }
+
+    public float getDrawOdds() {
+        return 1 / drawPercent;
+    }
+
+    public float getLossOdds() {
+        return 1 / lossPercent;
+    }
 }

+ 114 - 1
OddsJavaFx/src/tests/objects/XBestGamesDTO.java

@@ -1,2 +1,115 @@
-package tests.objects;public class XBestGamesDTO {
+package tests.objects;
+
+import objects.SoccerMatch;
+import objects.SoccerMatchAnalysis;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class XBestGamesDTO {
+
+    SoccerMatch match;
+
+    private int maxLookback = 15;
+
+    private int minLookback = 1;
+
+    Map<Integer, Values> valuesMap = new HashMap<>();
+    private GamePercentages percenage;
+
+    public XBestGamesDTO() {
+    }
+
+    public XBestGamesDTO(int min, int max) {
+        minLookback = min;
+        maxLookback = max;
+    }
+
+    public SoccerMatch getMatch() {
+        return match;
+    }
+
+    public void setMatch(SoccerMatch match) {
+        this.match = match;
+    }
+
+    public Map<Integer, Values> getValuesMap() {
+        return valuesMap;
+    }
+
+    public void calculateAllData(SoccerMatchAnalysis sma) {
+        for (int i = minLookback; i <= maxLookback; i++) {
+
+            valuesMap.put(i, new Values(
+                    sma.winLossRatio(i, true),
+                    sma.winLossRatio(i, false),
+
+                    sma.winLossRatioHomeAndAway(i, true),
+                    sma.winLossRatioHomeAndAway(i, false),
+
+                    sma.scoringTotal(i, true),
+                    sma.scoringTotal(i, false),
+
+                    sma.getScoringDiffLastGames(i)));
+        }
+    }
+
+    public void setPercentages(GamePercentages percenages) {
+        this.percenage = percenages;
+    }
+
+    public GamePercentages getPercenage() {
+        return percenage;
+    }
+
+    public static class Values {
+        int homeWinLossRatio;
+        int awayWinLossRatio;
+        int homeWinLossRatioHomeAndAway;
+        int awayWinLossRatioHomeAndAway;
+        int homeScoringTotal;
+        int awayScoringTotal;
+        int scoringDiffLastGames;
+
+        public Values() {
+        }
+
+        public Values(int homeWinLossRatio, int awayWinLossRatio, int homeWinLossRatioHomeAndAway, int awayWinLossRatioHomeAndAway, int homeScoringTotal, int awayScoringTotal, int scoringDiffLastGames) {
+            this.homeWinLossRatio = homeWinLossRatio;
+            this.awayWinLossRatio = awayWinLossRatio;
+            this.homeWinLossRatioHomeAndAway = homeWinLossRatioHomeAndAway;
+            this.awayWinLossRatioHomeAndAway = awayWinLossRatioHomeAndAway;
+            this.homeScoringTotal = homeScoringTotal;
+            this.awayScoringTotal = awayScoringTotal;
+            this.scoringDiffLastGames = scoringDiffLastGames;
+        }
+
+        public int getHomeWinLossRatio() {
+            return homeWinLossRatio;
+        }
+
+        public int getAwayWinLossRatio() {
+            return awayWinLossRatio;
+        }
+
+        public int getHomeWinLossRatioHomeAndAway() {
+            return homeWinLossRatioHomeAndAway;
+        }
+
+        public int getAwayWinLossRatioHomeAndAway() {
+            return awayWinLossRatioHomeAndAway;
+        }
+
+        public int getHomeScoringTotal() {
+            return homeScoringTotal;
+        }
+
+        public int getAwayScoringTotal() {
+            return awayScoringTotal;
+        }
+
+        public int getScoringDiffLastGames() {
+            return scoringDiffLastGames;
+        }
+    }
 }

+ 248 - 1
OddsJavaFx/src/tests/objects/XBestGamesWinPercentageStatistics.java

@@ -1,2 +1,249 @@
-package tests.objects;public class XBestGamesWinPercentageStatistics {
+package tests.objects;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class XBestGamesWinPercentageStatistics {
+
+
+    Map<Integer, Map<Integer,WinDrawLoss>> homeWinLossRatioMap = new HashMap<>();
+    Map<Integer, Map<Integer,WinDrawLoss>> awayWinLossRatioMap = new HashMap<>();
+
+    Map<Integer, Map<Integer,WinDrawLoss>> homeWinLossRatioHomeAndAwayMap = new HashMap<>();
+    Map<Integer, Map<Integer,WinDrawLoss>>  awayWinLossRatioHomeAndAwayMap = new HashMap<>();
+
+    Map<Integer, Map<Integer,WinDrawLoss>>  homeScoringTotal = new HashMap<>();
+    Map<Integer, Map<Integer,WinDrawLoss>>  awayScoringTotal = new HashMap<>();
+
+    Map<Integer, Map<Integer,WinDrawLoss>>  scoringDiffLastGamesMap = new HashMap<>();
+
+    public static final XBestGamesWinPercentageStatistics INSTANCE = new XBestGamesWinPercentageStatistics();
+
+    private XBestGamesWinPercentageStatistics() { }
+
+    public void addHomeWinLossRatio(int lookback, int value, boolean win, boolean draw, boolean loss) {
+        Map<Integer,WinDrawLoss> winDrawLossValueMap = homeWinLossRatioMap.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss winDrawLoss = winDrawLossValueMap.getOrDefault(value, new WinDrawLoss());
+        if (win) {
+            winDrawLoss.addWin();
+        }
+        if (draw) {
+            winDrawLoss.addDraw();
+        }
+        if (loss) {
+            winDrawLoss.addLoss();
+        }
+        winDrawLossValueMap.put(value, winDrawLoss);
+        homeWinLossRatioMap.put(lookback, winDrawLossValueMap);
+    }
+    public void addAwayWinLossRatio(int lookback, int value, boolean win, boolean draw, boolean loss) {
+        Map<Integer,WinDrawLoss> winDrawLossValueMap = awayWinLossRatioMap.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss winDrawLoss = winDrawLossValueMap.getOrDefault(value, new WinDrawLoss());
+        if (win) {
+            winDrawLoss.addWin();
+        }
+        if (draw) {
+            winDrawLoss.addDraw();
+        }
+        if (loss) {
+            winDrawLoss.addLoss();
+        }
+        winDrawLossValueMap.put(value,winDrawLoss);
+        awayWinLossRatioMap.put(lookback, winDrawLossValueMap);
+    }
+    public void addHomeWinLossRatioHomeAndAwayMap(int lookback, int value, boolean win, boolean draw, boolean loss) {
+        Map<Integer,WinDrawLoss> winDrawLossValueMap = homeWinLossRatioHomeAndAwayMap.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss winDrawLoss = winDrawLossValueMap.getOrDefault(value, new WinDrawLoss());
+        if (win) {
+            winDrawLoss.addWin();
+        }
+        if (draw) {
+            winDrawLoss.addDraw();
+        }
+        if (loss) {
+            winDrawLoss.addLoss();
+        }
+        winDrawLossValueMap.put(value, winDrawLoss);
+        homeWinLossRatioHomeAndAwayMap.put(lookback, winDrawLossValueMap);
+    }
+    public void addAwayWinLossRatioHomeAndAwayMap(int lookback, int value, boolean win, boolean draw, boolean loss) {
+        Map<Integer, WinDrawLoss> winDrawLossValueMap = awayWinLossRatioHomeAndAwayMap.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss winDrawLoss = winDrawLossValueMap.getOrDefault(value, new WinDrawLoss());
+        if (win) {
+            winDrawLoss.addWin();
+        }
+        if (draw) {
+            winDrawLoss.addDraw();
+        }
+        if (loss) {
+            winDrawLoss.addLoss();
+        }
+        winDrawLossValueMap.put(value,winDrawLoss);
+        awayWinLossRatioHomeAndAwayMap.put(lookback, winDrawLossValueMap);
+    }
+
+
+    public void addHomeScoringTotal(int lookback, int value, boolean win, boolean draw, boolean loss) {
+
+        Map<Integer, WinDrawLoss> winDrawLossValueMap = homeScoringTotal.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss winDrawLoss = winDrawLossValueMap.getOrDefault(value, new WinDrawLoss());
+
+        if (win) {
+            winDrawLoss.addWin();
+        }
+        if (draw) {
+            winDrawLoss.addDraw();
+        }
+        if (loss) {
+            winDrawLoss.addLoss();
+        }
+        winDrawLossValueMap.put(value, winDrawLoss);
+        homeScoringTotal.put(lookback, winDrawLossValueMap);
+    }
+    public void addAwayScoringTotal(int lookback, int value, boolean win, boolean draw, boolean loss) {
+        Map<Integer,WinDrawLoss> winDrawLossValueMap = awayScoringTotal.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss winDrawLoss = winDrawLossValueMap.getOrDefault(value, new WinDrawLoss());
+        if (win) {
+            winDrawLoss.addWin();
+        }
+        if (draw) {
+            winDrawLoss.addDraw();
+        }
+        if (loss) {
+            winDrawLoss.addLoss();
+        }
+        winDrawLossValueMap.put(value, winDrawLoss);
+        awayScoringTotal.put(lookback, winDrawLossValueMap);
+    }
+
+    public void addScoringDiffLastGamesMap(int lookback, int value, boolean win, boolean draw, boolean loss) {
+        Map<Integer,WinDrawLoss> winDrawLossValueMap = scoringDiffLastGamesMap.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss winDrawLoss = winDrawLossValueMap.getOrDefault(value, new WinDrawLoss());
+        if (win) {
+            winDrawLoss.addWin();
+        }
+        if (draw) {
+            winDrawLoss.addDraw();
+        }
+        if (loss) {
+            winDrawLoss.addLoss();
+        }
+        winDrawLossValueMap.put(value, winDrawLoss);
+        scoringDiffLastGamesMap.put(lookback, winDrawLossValueMap);
+    }
+
+
+    public GamePercentages getAwayScoringWinPercentage(int lookback, int awayScoringTotal) {
+        Map<Integer, WinDrawLoss> mappedValues = this.awayScoringTotal.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss values = mappedValues.getOrDefault(awayScoringTotal, null);
+        if (values == null) {
+            return new GamePercentages();
+        }
+        return new GamePercentages((float) values.getWins() / (float) values.getTotal(),
+                (float) values.getDraws() / (float) values.getTotal(),
+        (float) values.getLosses() / (float) values.getTotal());
+    }
+
+    public GamePercentages getHomeScoringWinPercentage(int lookback, int homeScoringTotal) {
+        Map<Integer, WinDrawLoss> mappedValues = this.homeScoringTotal.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss values = mappedValues.getOrDefault(homeScoringTotal, null);
+        if (values == null) {
+            return new GamePercentages();
+        }
+        return new GamePercentages((float) values.getWins() / (float) values.getTotal(),
+                (float) values.getDraws() / (float) values.getTotal(),
+                (float) values.getLosses() / (float) values.getTotal());
+    }
+
+    public GamePercentages getHomeWinRatioPercetage(int lookback, int homeWinLossRatio) {
+        Map<Integer, WinDrawLoss> mappedValues = this.homeWinLossRatioMap.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss values = mappedValues.getOrDefault(homeWinLossRatio, null);
+        if (values == null) {
+            return new GamePercentages();
+        }
+        return new GamePercentages((float) values.getWins() / (float) values.getTotal(),
+                (float) values.getDraws() / (float) values.getTotal(),
+                (float) values.getLosses() / (float) values.getTotal());
+    }
+
+    public GamePercentages getAwayWinRatioPercetage(int lookback, int awayWinLossRatio) {
+        Map<Integer, WinDrawLoss> mappedValues = this.awayWinLossRatioMap.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss values = mappedValues.getOrDefault(awayWinLossRatio, null);
+        if (values == null) {
+            return new GamePercentages();
+        }
+        return new GamePercentages((float) values.getWins() / (float) values.getTotal(),
+                (float) values.getDraws() / (float) values.getTotal(),
+                (float) values.getLosses() / (float) values.getTotal());
+    }
+
+    public GamePercentages getHomeWinLossRatioHomeAndAwayPercentage(int lookback, int homeWinLossRatioHomeAndAway) {
+        Map<Integer, WinDrawLoss> mappedValues = this.homeWinLossRatioHomeAndAwayMap.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss values = mappedValues.getOrDefault(homeWinLossRatioHomeAndAway, null);
+        if (values == null) {
+            return new GamePercentages();
+        }
+        return new GamePercentages((float) values.getWins() / (float) values.getTotal(),
+                (float) values.getDraws() / (float) values.getTotal(),
+                (float) values.getLosses() / (float) values.getTotal());
+    }
+
+    public GamePercentages getAwayWinLossRatioHomeAndAwayPercentage(int lookback, int awayWinLossRatioHomeAndAway) {
+        Map<Integer, WinDrawLoss> mappedValues = this.awayWinLossRatioHomeAndAwayMap.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss values = mappedValues.getOrDefault(awayWinLossRatioHomeAndAway, null);
+        if (values == null) {
+            return new GamePercentages();
+        }
+        return new GamePercentages((float) values.getWins() / (float) values.getTotal(),
+                (float) values.getDraws() / (float) values.getTotal(),
+                (float) values.getLosses() / (float) values.getTotal());
+    }
+
+    public GamePercentages getScoringDiffLastGamesPercentage(int lookback, int scoringDiffLastGames) {
+        Map<Integer, WinDrawLoss> mappedValues = this.scoringDiffLastGamesMap.getOrDefault(lookback, new HashMap<>());
+        WinDrawLoss values = mappedValues.getOrDefault(scoringDiffLastGames, null);
+        if (values == null) {
+            return new GamePercentages();
+        }
+        return new GamePercentages((float) values.getWins() / (float) values.getTotal(),
+                (float) values.getDraws() / (float) values.getTotal(),
+                (float) values.getLosses() / (float) values.getTotal());
+    }
+
+
+    private class WinDrawLoss {
+        int wins = 0;
+        int draws = 0;
+        int losses = 0;
+
+        int total = 0;
+
+        public int getWins() {
+            return wins;
+        }
+
+        public void addWin() {
+            this.wins++; total++;
+        }
+
+        public int getDraws() {
+            return draws;
+        }
+
+        public void addDraw() {
+            this.draws++; total++;
+        }
+
+        public int getLosses() {
+            return losses;
+        }
+
+        public void addLoss() {
+            this.losses++; total++;
+        }
+
+        public int getTotal() {
+            return total;
+        }
+    }
 }

+ 7 - 1
OddsJavaFx/src/tests/objects/XGamesPercentages.java

@@ -1,2 +1,8 @@
-package tests.objects;public class XGamesPercentages {
+package tests.objects;
+
+public class XGamesPercentages {
+    public XGamesPercentages() {
+    }
+
+
 }

+ 0 - 5
OddsStrategyWeb/src/main/java/Main.html

@@ -1,5 +0,0 @@
-<html xmlns:wicket="http://wicket.apache.org">
-<body>
-<span wicket:id="message">Message is here</span>
-</body>
-</html>

+ 5 - 0
OddsStrategyWeb/src/main/java/MainPage.html

@@ -0,0 +1,5 @@
+<html>
+<body>
+<span wicket:id="message">Message goes here</span>
+</body>
+</html>

+ 3 - 2
OddsStrategyWeb/src/main/java/Main.java → OddsStrategyWeb/src/main/java/MainPage.java

@@ -1,11 +1,12 @@
 package main.java;
 
-
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
 
 public class Main extends WebPage {
-    public Main() {
+    public Main(final PageParameters parameters) {
+        super(parameters);
         add(new Label("message", "Hello World!"));
     }
 }

BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT.war


+ 0 - 5
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/classes/Main.html

@@ -1,5 +0,0 @@
-<html xmlns:wicket="http://www.w3.org/1999/xhtml">
-<body>
-<span wicket:id="message">Message is here</span>
-</body>
-</html>

BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/classes/main/java/Main.class


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/classes/main/java/MainApplication.class


+ 5 - 0
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/classes/main/java/MainPage.html

@@ -0,0 +1,5 @@
+<html>
+    <body>
+        <span wicket:id="message">Message goes here</span>
+    </body>
+</html>

BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/commons-collections4-4.4.jar


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/commons-fileupload2-core-2.0.0-M2.jar


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/commons-fileupload2-jakarta-servlet5-2.0.0-M2.jar


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/commons-io-2.16.1.jar


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/jdk-serializable-functional-1.9.0.jar


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/openjson-1.0.13.jar


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/slf4j-api-2.0.16.jar


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/slf4j-simple-2.0.16.jar


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/wicket-core-10.2.0.jar


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/wicket-native-websocket-core-10.2.0.jar


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/wicket-native-websocket-javax-10.2.0.jar


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/wicket-request-10.2.0.jar


BIN
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/lib/wicket-util-10.2.0.jar


+ 0 - 25
OddsStrategyWeb/target/OddsStrategyWeb-1.0-SNAPSHOT/WEB-INF/web.xml

@@ -1,25 +0,0 @@
-<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
-         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
-         version="3.1">
-
-    <filter>
-        <filter-name>wicket.filter</filter-name>
-        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
-        <init-param>
-            <param-name>applicationClassName</param-name>
-            <param-value>main.java.MainApplication</param-value>
-        </init-param>
-        <init-param>
-            <param-name>filterMappingUrlPattern</param-name>
-            <param-value>/*</param-value>
-        </init-param>
-    </filter>
-
-    <filter-mapping>
-        <filter-name>wicket.filter</filter-name>
-        <url-pattern>/*</url-pattern>
-    </filter-mapping>
-
-</web-app>

+ 0 - 5
OddsStrategyWeb/target/classes/Main.html

@@ -1,5 +0,0 @@
-<html xmlns:wicket="http://www.w3.org/1999/xhtml">
-<body>
-<span wicket:id="message">Message is here</span>
-</body>
-</html>

BIN
OddsStrategyWeb/target/classes/main/java/Main.class


+ 5 - 0
OddsStrategyWeb/target/classes/main/java/Main.html

@@ -0,0 +1,5 @@
+<html>
+<body>
+<span wicket:id="message">Message goes here</span>
+</body>
+</html>

BIN
OddsStrategyWeb/target/classes/main/java/MainApplication.class


+ 5 - 0
OddsStrategyWeb/target/classes/main/java/MainPage.html

@@ -0,0 +1,5 @@
+<html>
+    <body>
+        <span wicket:id="message">Message goes here</span>
+    </body>
+</html>

+ 0 - 3
OddsStrategyWeb/target/maven-archiver/pom.properties

@@ -1,3 +0,0 @@
-artifactId=OddsStrategyWeb
-groupId=nordh.xyz
-version=1.0-SNAPSHOT

+ 0 - 2
OddsStrategyWeb/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst

@@ -1,2 +0,0 @@
-main\java\MainApplication.class
-main\java\Main.class

+ 0 - 2
OddsStrategyWeb/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst

@@ -1,2 +0,0 @@
-D:\GitRepos\Odds\Odds\OddsStrategyWeb\src\main\java\Main.java
-D:\GitRepos\Odds\Odds\OddsStrategyWeb\src\main\java\MainApplication.java

+ 0 - 0
OddsStrategyWeb/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst


+ 0 - 0
OddsStrategyWeb/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst