Selaa lähdekoodia

Test av gränsvärden, startfil för web

Axel Nordh 4 vuotta sitten
vanhempi
sitoutus
f257de6459
52 muutettua tiedostoa jossa 1982 lisäystä ja 33 poistoa
  1. 11 9
      OddsJavaFx/.classpath
  2. 1 0
      OddsJavaFx/.gitignore
  3. 6 0
      OddsJavaFx/.project
  4. 5 4
      OddsJavaFx/.settings/org.eclipse.jdt.core.prefs
  5. 4 0
      OddsJavaFx/.settings/org.eclipse.m2e.core.prefs
  6. 0 5
      OddsJavaFx/bin/.gitignore
  7. BIN
      OddsJavaFx/bin/application/Main.class
  8. 1 0
      OddsJavaFx/bin/application/application.css
  9. BIN
      OddsJavaFx/bin/controllers/MainController.class
  10. BIN
      OddsJavaFx/bin/controllers/MatchResultTabController.class
  11. BIN
      OddsJavaFx/bin/controllers/MatchStatTabController.class
  12. BIN
      OddsJavaFx/bin/controllers/MatchTabController.class
  13. BIN
      OddsJavaFx/bin/controllers/PastResultsController.class
  14. BIN
      OddsJavaFx/bin/controllers/StatisticsTabController.class
  15. BIN
      OddsJavaFx/bin/controllers/TestsController.class
  16. BIN
      OddsJavaFx/bin/data/GuiMysql.class
  17. 21 0
      OddsJavaFx/bin/fxml/MatchResultTabBuilder.fxml
  18. 27 0
      OddsJavaFx/bin/fxml/MatchStatTabBuilder.fxml
  19. 33 0
      OddsJavaFx/bin/fxml/MatchTabBuilder.fxml
  20. 145 0
      OddsJavaFx/bin/fxml/OddsFxBuilder.fxml
  21. 36 0
      OddsJavaFx/bin/fxml/PastResults.fxml
  22. 20 0
      OddsJavaFx/bin/fxml/Settings.fxml
  23. 34 0
      OddsJavaFx/bin/fxml/StatisticsTabBuilder.fxml
  24. 71 0
      OddsJavaFx/bin/fxml/Testing.fxml
  25. BIN
      OddsJavaFx/bin/objects/ActionButtonTableCell.class
  26. BIN
      OddsJavaFx/bin/objects/CountryObject.class
  27. BIN
      OddsJavaFx/bin/objects/MatchData.class
  28. BIN
      OddsJavaFx/bin/objects/OverUnder.class
  29. BIN
      OddsJavaFx/bin/objects/SoccerMatch.class
  30. BIN
      OddsJavaFx/bin/objects/Team.class
  31. BIN
      OddsJavaFx/bin/objects/TeamResults.class
  32. BIN
      OddsJavaFx/bin/objects/TeamStanding.class
  33. BIN
      OddsJavaFx/bin/parser/OddsPortal.class
  34. BIN
      OddsJavaFx/bin/tests/LastResultsTest.class
  35. 38 0
      OddsJavaFx/pom.xml
  36. 9 2
      OddsJavaFx/src/controllers/MainController.java
  37. 33 5
      OddsJavaFx/src/controllers/MatchTabController.java
  38. 180 0
      OddsJavaFx/src/controllers/PastResultsController.java
  39. 234 0
      OddsJavaFx/src/controllers/TestsController.java
  40. 145 7
      OddsJavaFx/src/data/GuiMysql.java
  41. 11 1
      OddsJavaFx/src/fxml/OddsFxBuilder.fxml
  42. 36 0
      OddsJavaFx/src/fxml/PastResults.fxml
  43. 20 0
      OddsJavaFx/src/fxml/Settings.fxml
  44. 76 0
      OddsJavaFx/src/fxml/Testing.fxml
  45. 34 0
      OddsJavaFx/src/objects/CountryObject.java
  46. 43 0
      OddsJavaFx/src/objects/League.java
  47. 23 0
      OddsJavaFx/src/objects/SoccerMatch.java
  48. 5 0
      OddsJavaFx/src/objects/TeamResults.java
  49. 319 0
      OddsJavaFx/src/parser/OddsPortal.java
  50. 163 0
      OddsJavaFx/src/tests/LastResultsTest.java
  51. 195 0
      OddsJavaFx/src/tests/PrioCountriesAll.java
  52. 3 0
      OddsJavaFx/src/web/front/index.php

+ 11 - 9
OddsJavaFx/.classpath

@@ -1,21 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
+	<classpathentry kind="src" output="target/classes" path="src">
 		<attributes>
-			<attribute name="module" value="true"/>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="lib" path="C:/Users/Axel/.m2/repository/com/google/guava/guava/30.0-jre/guava-30.0-jre.jar" sourcepath="C:/Users/Axel/.m2/repository/com/google/guava/guava/30.0-jre/guava-30.0-jre-sources.jar">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
 		<attributes>
+			<attribute name="module" value="true"/>
 			<attribute name="maven.pomderived" value="true"/>
-			<attribute name="maven.groupId" value="com.google.guava"/>
-			<attribute name="maven.artifactId" value="guava"/>
-			<attribute name="maven.version" value="30.0-jre"/>
-			<attribute name="maven.scope" value="compile"/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/JavaFX"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/Odds"/>
-	<classpathentry kind="output" path="bin"/>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
 </classpath>

+ 1 - 0
OddsJavaFx/.gitignore

@@ -0,0 +1 @@
+/target/

+ 6 - 0
OddsJavaFx/.project

@@ -15,8 +15,14 @@
 			<arguments>
 			</arguments>
 		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 	</buildSpec>
 	<natures>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
 	</natures>

+ 5 - 4
OddsJavaFx/.settings/org.eclipse.jdt.core.prefs

@@ -1,15 +1,16 @@
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.debug.lineNumber=generate
 org.eclipse.jdt.core.compiler.debug.localVariable=generate
 org.eclipse.jdt.core.compiler.debug.sourceFile=generate
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
 org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
 org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
-org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8

+ 4 - 0
OddsJavaFx/.settings/org.eclipse.m2e.core.prefs

@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1

+ 0 - 5
OddsJavaFx/bin/.gitignore

@@ -1,5 +0,0 @@
-/application/
-/controllers/
-/data/
-/fxml/
-/objects/

BIN
OddsJavaFx/bin/application/Main.class


+ 1 - 0
OddsJavaFx/bin/application/application.css

@@ -0,0 +1 @@
+/* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */

BIN
OddsJavaFx/bin/controllers/MainController.class


BIN
OddsJavaFx/bin/controllers/MatchResultTabController.class


BIN
OddsJavaFx/bin/controllers/MatchStatTabController.class


BIN
OddsJavaFx/bin/controllers/MatchTabController.class


BIN
OddsJavaFx/bin/controllers/PastResultsController.class


BIN
OddsJavaFx/bin/controllers/StatisticsTabController.class


BIN
OddsJavaFx/bin/controllers/TestsController.class


BIN
OddsJavaFx/bin/data/GuiMysql.class


+ 21 - 0
OddsJavaFx/bin/fxml/MatchResultTabBuilder.fxml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.TableColumn?>
+<?import javafx.scene.control.TableView?>
+<?import javafx.scene.layout.AnchorPane?>
+
+<AnchorPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/11.0.1" fx:controller="controllers.MatchResultTabController">
+	<children>
+	   <TableView fx:id="matchResultTable" 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">
+	     <columns>
+	       <TableColumn fx:id="homeTeamColumn" prefWidth="75.0" text="Home team" />
+	       <TableColumn fx:id="awayTeamColumn" prefWidth="75.0" text="Away team" />
+	       <TableColumn fx:id="goalsHomeColumn" prefWidth="75.0" text="Goals home" />
+	       <TableColumn fx:id="goalsAwayColumn" prefWidth="75.0" text="Goals away" />
+	       <TableColumn fx:id="countryColumn" prefWidth="75.0" text="Country" />
+	       <TableColumn fx:id="leagueColumn" prefWidth="75.0" text="League" />
+	     </columns>
+	   </TableView>
+	</children>
+</AnchorPane>
+

+ 27 - 0
OddsJavaFx/bin/fxml/MatchStatTabBuilder.fxml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.TableColumn?>
+<?import javafx.scene.control.TableView?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.BorderPane?>
+
+<AnchorPane xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.MatchStatTabController">
+   <children>
+      <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">
+         <center>
+            <TableView fx:id="matchStatTable" prefHeight="546.0" prefWidth="479.0" BorderPane.alignment="CENTER">
+              <columns>
+                <TableColumn fx:id="team" prefWidth="100.0" text="Team" />
+                <TableColumn fx:id="gamesPlayed" prefWidth="87.0" text="Games played" />
+                <TableColumn fx:id="win" prefWidth="63.0" text="Win" />
+                <TableColumn fx:id="draw" prefWidth="75.0" text="Draw" />
+                <TableColumn fx:id="loss" prefWidth="75.0" text="Loss" />
+                <TableColumn fx:id="points" prefWidth="75.0" text="Points" />
+                <TableColumn fx:id="goalsScored" prefWidth="85.0" text="Goals scored" />
+                <TableColumn fx:id="goalsConceded" prefWidth="101.0" text="Goals conceded" />
+                <TableColumn fx:id="diff" prefWidth="39.0" text="Difference" />
+              </columns>
+            </TableView>
+         </center></BorderPane>
+   </children>
+</AnchorPane>

+ 33 - 0
OddsJavaFx/bin/fxml/MatchTabBuilder.fxml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.TableColumn?>
+<?import javafx.scene.control.TableView?>
+<?import javafx.scene.layout.AnchorPane?>
+
+<AnchorPane xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.MatchTabController">
+	<children>
+	   <TableView fx:id="matchTable" 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">
+	     <columns>
+	       <TableColumn fx:id="gameDateColumn" editable="false" prefWidth="75.0" text="Game date" />
+	       <TableColumn fx:id="homeTeamColumn" editable="false" prefWidth="75.0" text="Home team" />
+	       <TableColumn fx:id="awayTeamColumn" prefWidth="75.0" text="Away team" />
+	       <TableColumn fx:id="odds1Column" prefWidth="75.0" text="Odds 1" />
+	       <TableColumn fx:id="oddsXColumn" prefWidth="75.0" text="Odds X" />
+	       <TableColumn fx:id="odds2Column" prefWidth="75.0" text="Odds 2" />
+	       <TableColumn fx:id="goalsHomeColumn" prefWidth="75.0" text="Goals home" />
+	       <TableColumn fx:id="goalsAwayColumn" prefWidth="75.0" text="Goals away" />
+	       <TableColumn fx:id="goalDiff" prefWidth="75.0" text="Difference" />
+	       <TableColumn fx:id="avgScoreHomeColumn" prefWidth="75.0" text="Avg score home" />
+	       <TableColumn fx:id="avgConcededHomeColumn" prefWidth="75.0" text="Avg conceded home" />
+	       <TableColumn fx:id="avgScoreAwayColumn" prefWidth="75.0" text="Avg score away" />
+	       <TableColumn fx:id="avgConcededAwayColumn" prefWidth="75.0" text="Avg conceded away" />
+	       <TableColumn fx:id="countryColumn" prefWidth="75.0" text="Country" />
+	       <TableColumn fx:id="leagueColumn" prefWidth="75.0" text="League" />
+	       
+	       <TableColumn fx:id="homeWinColumn" prefWidth="75.0" text="Home Win" />
+	       <TableColumn fx:id="drawColumn" prefWidth="75.0" text="Draw" />
+	       <TableColumn fx:id="awayWinColumn" prefWidth="75.0" text="Away win" />
+	     </columns>
+	   </TableView>
+	</children>
+</AnchorPane>

+ 145 - 0
OddsJavaFx/bin/fxml/OddsFxBuilder.fxml

@@ -0,0 +1,145 @@
+<?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.text.Font?>
+
+<StackPane prefHeight="800.0" prefWidth="1600.0" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.MainController">
+   <children>
+      <BorderPane prefHeight="600.0" prefWidth="1200.0">
+         <top>
+            <FlowPane BorderPane.alignment="CENTER">
+               <children>
+                  <ComboBox id="SportComboBox" fx:id="sportSelector" onAction="#SportSelected" prefHeight="25.0" prefWidth="200.0" promptText="Sport" />
+                  <ComboBox id="CountryComboBox" fx:id="countrySelector" disable="true" onAction="#CountrySelected" prefHeight="25.0" prefWidth="200.0" promptText="Country" />
+                  <ComboBox id="LeagueComboBox" fx:id="leagueSelector" disable="true" onAction="#LeagueSelected" prefHeight="25.0" prefWidth="200.0" promptText="League" />
+                  <Button fx:id="resetFilterButton" mnemonicParsing="false" onAction="#ResetFilter" text="Reset Filter" />
+                  <Button fx:id="getLeagueInfoButton" disable="true" mnemonicParsing="false" onAction="#getLeagueInfo" text="Get League Info" />
+                  <Button fx:id="getMoreLeagueInfo" disable="true" mnemonicParsing="false" onAction="#getMoreLeagueInfo" text="Get more league info" />
+                  <Button fx:id="updateStatsTableButton" disable="true" mnemonicParsing="false" onAction="#UpdateStatsTable" text="Update Statistics" />
+                  <Button fx:id="showMatchStatsButton" disable="true" mnemonicParsing="false" onAction="#setMatchStatInfo" text="Show match stats" />
+               </children>
+            </FlowPane>
+         </top>
+         <left>
+            <SplitPane dividerPositions="0.38190954773869346" prefHeight="575.0" prefWidth="300.0" BorderPane.alignment="CENTER">
+              <items>
+                  <FlowPane prefHeight="573.0">
+                     <children>
+                        <TextField alignment="CENTER" editable="false" prefHeight="25.0" text="Home team" />
+                        <TextField alignment="CENTER" editable="false" prefHeight="25.0" text="Away team" />
+                        <TextField editable="false" prefHeight="25.0" prefWidth="100.0" text="League avarages">
+                           <font>
+                              <Font name="System Bold" size="12.0" />
+                           </font>
+                        </TextField>
+                        <TextField editable="false" text="Home score" />
+                        <TextField editable="false" text="Away score" />
+                        <TextField editable="false" prefHeight="25.0" prefWidth="149.0" text="Season Scoring">
+                           <font>
+                              <Font name="System Bold" size="12.0" />
+                           </font>
+                        </TextField>
+                        <TextField editable="false" text="0 Goals" />
+                        <TextField editable="false" text="1 Goal" />
+                        <TextField editable="false" text="2 Goals" />
+                        <TextField editable="false" text="3 Goals" />
+                        <TextField editable="false" text="4 Goals" />
+                        <TextField editable="false" text="5 Goals" />
+                        <TextField editable="false" text="6+ Goals" />
+                     </children>
+                  </FlowPane>
+                  <FlowPane prefHeight="573.0" prefWidth="149.0">
+                     <children>
+                        <ChoiceBox id="HomeTeamSelector" fx:id="homeTeamSelector" disable="true" prefHeight="25.0" prefWidth="100.0" />
+                        <ChoiceBox id="AwayTeamSelector" fx:id="awayTeamSelector" disable="true" prefHeight="25.0" prefWidth="100.0" />
+                        <TextField editable="false" prefHeight="25.0" prefWidth="100.0" text="League avarages">
+                           <font>
+                              <Font name="System Bold" size="12.0" />
+                           </font>
+                        </TextField>
+                        <TextField fx:id="avgLeagueHomeScoreTxt" editable="false" />
+                        <TextField fx:id="avgLeagueAwayScoreTxt" editable="false" />
+                        <TextField editable="false" />
+                        <TextField fx:id="league0Goals" editable="false" />
+                        <TextField fx:id="league1Goal" editable="false" />
+                        <TextField fx:id="league2Goals" editable="false" />
+                        <TextField fx:id="league3Goals" editable="false" />
+                        <TextField fx:id="league4Goals" editable="false" />
+                        <TextField fx:id="league5Goals" editable="false" />
+                        <TextField fx:id="league6Goals" editable="false" />
+                     </children>
+                  </FlowPane>
+              </items>
+            </SplitPane>
+         </left>
+         <center>
+            <TabPane prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" BorderPane.alignment="CENTER">
+              <tabs>
+                <Tab text="Predictions">
+                  <content>
+                    <fx:include fx:id="matchTab" source="MatchTabBuilder.fxml" />
+                  </content>
+                </Tab>
+                <Tab text="To Be Resolved">
+                  <content>
+                    <fx:include fx:id="resultsTab" source="MatchResultTabBuilder.fxml" />
+                  </content>
+                </Tab>
+                <Tab text="Statistic Tests">
+                  <content>
+                    <fx:include fx:id="statTab" source="StatisticsTabBuilder.fxml" />
+                  </content>
+                </Tab>
+                <Tab text="Match Statistics">
+                	<content>
+ 						<fx:include fx:id="matchStatTab" source="MatchStatTabBuilder.fxml" />               	
+                	</content>
+                </Tab>
+                <Tab text="Old results">
+                	<content>
+                		<fx:include fx:id="oldResultsTab" source="PastResults.fxml" />
+                	</content>
+                </Tab>
+                <Tab text="Testing">
+	                <content>
+	                   <fx:include fx:id="testsTab" source="Testing.fxml" />
+	                </content>
+                </Tab>
+              </tabs>
+            </TabPane>
+         </center>
+      </BorderPane>
+      <Pane fx:id="glass" disable="true" opacity="0.0" prefHeight="600.0" prefWidth="1200.0" style="-fx-background-color: #000111;" visible="false">
+         <children>
+            <TextField alignment="CENTER" editable="false" layoutX="198.0" layoutY="231.0" style="-fx-background-color: #000FFF; -fx-text-fill: #FFFFFF;" text="WAIT">
+               <font>
+                  <Font size="65.0" />
+               </font>
+               <effect>
+                  <Lighting>
+                     <bumpInput>
+                        <Shadow />
+                     </bumpInput>
+                     <light>
+                        <Light.Distant />
+                     </light>
+                  </Lighting>
+               </effect>
+            </TextField>
+         </children>
+      </Pane>
+   </children>
+</StackPane>

+ 36 - 0
OddsJavaFx/bin/fxml/PastResults.fxml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.control.DatePicker?>
+<?import javafx.scene.control.ScrollPane?>
+<?import javafx.scene.control.ComboBox?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.FlowPane?>
+<?import javafx.scene.layout.VBox?>
+
+<AnchorPane fx:id="basePane" prefHeight="414.0" prefWidth="736.0" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.PastResultsController">
+   <children>
+      <VBox prefHeight="414.0" prefWidth="736.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+         <children>
+          <AnchorPane>
+               <children>
+                  <FlowPane maxHeight="30.0" minHeight="30.0" prefHeight="30.0" prefWidth="598.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                     <children>
+                        <DatePicker fx:id="date" prefHeight="30.0" prefWidth="209.0" />
+                        <Button fx:id="getResults" mnemonicParsing="false" prefHeight="30.0" prefWidth="96.0" text="GetResults" onAction="#getResults" />
+                        <ComboBox id="SportComboBox" fx:id="sportSelector" onAction="#SportSelected" prefHeight="25.0" prefWidth="200.0" promptText="Sport" />
+            		    <ComboBox id="CountryComboBox" fx:id="countrySelector" disable="true" onAction="#CountrySelected" prefHeight="25.0" prefWidth="200.0" promptText="Country" />
+                        <ComboBox id="LeagueComboBox" fx:id="leagueSelector" disable="true" onAction="#LeagueSelected" prefHeight="25.0" prefWidth="200.0" promptText="League" />
+                     </children>
+                  </FlowPane>
+               </children>
+            </AnchorPane>
+          <AnchorPane>
+               <children>
+                  <ScrollPane fx:id="resultsPanel" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
+               </children>
+            </AnchorPane>
+         </children>
+      </VBox>
+   </children>
+</AnchorPane>

+ 20 - 0
OddsJavaFx/bin/fxml/Settings.fxml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.ScrollPane?>
+<?import javafx.scene.control.SplitPane?>
+<?import javafx.scene.control.TextField?>
+<?import javafx.scene.layout.AnchorPane?>
+
+<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1">
+   <children>
+      <ScrollPane fx:id="scrollPane" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+         <content>
+            <SplitPane dividerPositions="0.5" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
+               <items>
+                  <TextField editable="false" text="Prioriterade ligor" />
+                  <ScrollPane fx:id="prioLeaguesSelector" prefHeight="200.0" prefWidth="200.0" />
+               </items>
+            </SplitPane>
+         </content></ScrollPane>
+   </children>
+</AnchorPane>

+ 34 - 0
OddsJavaFx/bin/fxml/StatisticsTabBuilder.fxml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.TableColumn?>
+<?import javafx.scene.control.TableView?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.BorderPane?>
+
+<AnchorPane prefHeight="411.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.StatisticsTabController">
+   <children>
+      <BorderPane prefHeight="411.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+         <center>
+            <TableView fx:id="statsTable" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
+              <columns>
+                <TableColumn fx:id="diffColumn" prefWidth="75.0" text="Difference" />
+                  <TableColumn fx:id="u05" prefWidth="75.0" text="Under 0.5 mål" />
+                  <TableColumn fx:id="o05" prefWidth="75.0" text="Över 0.5 mål" />
+                  <TableColumn fx:id="u15" prefWidth="75.0" text="Under 1.5 mål" />
+                  <TableColumn fx:id="o15" prefWidth="75.0" text="Över 1.5 mål" />
+                  <TableColumn fx:id="u25" prefWidth="75.0" text="Under 2.5 mål" />
+                  <TableColumn fx:id="o25" prefWidth="75.0" text="Över 2.5 mål" />
+                  <TableColumn fx:id="u35" prefWidth="75.0" text="Under 3.5 mål" />
+                  <TableColumn fx:id="o35" prefWidth="75.0" text="Över 3.5 mål" />
+                  <TableColumn fx:id="u45" prefWidth="75.0" text="Under 4.5 mål" />
+                  <TableColumn fx:id="o45" prefWidth="75.0" text="Över 4.5 mål" />
+                  <TableColumn fx:id="u55" prefWidth="75.0" text="Under 5.5 mål" />
+                  <TableColumn fx:id="o55" prefWidth="75.0" text="Över 5.5 mål" />
+                  <TableColumn fx:id="u65" prefWidth="75.0" text="Under 6.5 mål" />
+                  <TableColumn fx:id="o65" prefWidth="75.0" text="Över 6.5 mål" />
+              </columns>
+            </TableView>
+         </center>
+      </BorderPane>
+   </children>
+</AnchorPane>

+ 71 - 0
OddsJavaFx/bin/fxml/Testing.fxml

@@ -0,0 +1,71 @@
+<?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.Pane?>
+<?import javafx.scene.layout.VBox?>
+
+<AnchorPane fx:id="basePane" prefHeight="414.0" prefWidth="736.0" xmlns="http://javafx.com/javafx/15.0.1" 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">
+         <children>
+          <AnchorPane>
+               <children>
+                  <FlowPane maxHeight="30.0" minHeight="30.0" prefHeight="30.0" prefWidth="598.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                     <children>
+                        <DatePicker fx:id="date" prefHeight="30.0" prefWidth="209.0" />
+                        <Button fx:id="getResults" mnemonicParsing="false" onAction="#getResults" prefHeight="30.0" prefWidth="96.0" text="GetResults" />
+            		    <ComboBox id="CountryComboBox" fx:id="countrySelector" disable="true" onAction="#CountrySelected" prefHeight="25.0" prefWidth="200.0" promptText="Country" />
+                        <ComboBox id="LeagueComboBox" fx:id="leagueSelector" disable="true" onAction="#LeagueSelected" prefHeight="25.0" prefWidth="200.0" promptText="League" />
+                     </children>
+                  </FlowPane>
+               </children>
+            </AnchorPane>
+          <AnchorPane fx:id="testSettingsPanel" prefHeight="386.0" prefWidth="736.0">
+               <children>
+                  <SplitPane dividerPositions="0.5" prefHeight="351.0" prefWidth="736.0" AnchorPane.bottomAnchor="34.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                    <items>
+                      <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
+                           <children>
+                              <VBox prefHeight="383.0" prefWidth="216.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                                 <children>
+                                    <TextField editable="false" text="Starting cash" />
+                                    <TextField editable="false" text="Betting level" />
+                                    <TextField editable="false" text="Games lookback" />
+                                    <TextField editable="false" text="Bet margin" />
+                                 </children>
+                              </VBox>
+                           </children>
+                        </AnchorPane>
+                      <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
+                           <children>
+                              <VBox prefHeight="383.0" prefWidth="512.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                                 <children>
+                                    <TextField fx:id="startingBank" promptText="1000" />
+                                    <TextField fx:id="bettingLevel" promptText="1%" />
+                                    <TextField fx:id="lookBack" promptText="10" />
+                                    <TextField fx:id="betMargin" promptText="5%" />
+                                 </children>
+                              </VBox>
+                           </children>
+                        </AnchorPane>
+                    </items>
+                  </SplitPane>
+                  <Pane layoutX="-1.0" layoutY="390.0" prefHeight="30.0" prefWidth="736.0">
+                     <children>
+                        <Button onAction="#runTestAction" layoutX="338.0" layoutY="2.0" mnemonicParsing="false" text="Run test" />
+                     </children>
+                  </Pane>
+               </children>
+            </AnchorPane>
+            <AnchorPane fx:id="testResultsPanel" prefHeight="386.0" prefWidth="736.0">
+            </AnchorPane>
+         </children>
+      </VBox>
+   </children>
+</AnchorPane>

BIN
OddsJavaFx/bin/objects/ActionButtonTableCell.class


BIN
OddsJavaFx/bin/objects/CountryObject.class


BIN
OddsJavaFx/bin/objects/MatchData.class


BIN
OddsJavaFx/bin/objects/OverUnder.class


BIN
OddsJavaFx/bin/objects/SoccerMatch.class


BIN
OddsJavaFx/bin/objects/Team.class


BIN
OddsJavaFx/bin/objects/TeamResults.class


BIN
OddsJavaFx/bin/objects/TeamStanding.class


BIN
OddsJavaFx/bin/parser/OddsPortal.class


BIN
OddsJavaFx/bin/tests/LastResultsTest.class


+ 38 - 0
OddsJavaFx/pom.xml

@@ -0,0 +1,38 @@
+<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>Odds</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <build>
+    <sourceDirectory>src</sourceDirectory>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.8.1</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+   <dependencies>
+   <dependency>
+	 <groupId>com.google.guava</groupId>
+	 <artifactId>guava</artifactId>
+	 <version>30.0-jre</version>
+	</dependency>
+	<dependency>
+ 	   <groupId>net.sourceforge.htmlunit</groupId>
+	    <artifactId>htmlunit</artifactId>
+	    <version>2.50.0</version>
+	</dependency>
+	<dependency>
+	    <groupId>com.github.jbytecode</groupId>
+	    <artifactId>RCaller</artifactId>
+	    <version>3.0</version>
+	</dependency>
+
+   </dependencies>
+</project>

+ 9 - 2
OddsJavaFx/src/controllers/MainController.java

@@ -3,6 +3,7 @@ package controllers;
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.net.URL;
+import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
@@ -30,6 +31,8 @@ import parser.OddsPortal;
 
 public class MainController implements Initializable {
 
+	public static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
+
 	@FXML private MatchTabController matchTabController;
 	@FXML private StatisticsTabController statTabController;
 	@FXML private MatchStatTabController matchStatTabController;
@@ -98,7 +101,7 @@ public class MainController implements Initializable {
 		if (sportSelector.getValue() != null && !sportSelector.getValue().equals("Sport")) {
 			countrySelector.setDisable(false);
 			final int sportId = sportsList.stream().filter(p -> p.getValue().equals(sportSelector.getValue())).findFirst().get().getKey();
-			final ArrayList<SoccerMatch> upcomingMatches = GuiMysql.getInstance().getTodaysMatches("SoccerResults", sportId);
+			final ArrayList<SoccerMatch> upcomingMatches = GuiMysql.getInstance().getUpcomingMatches("SoccerResults", sportId);
 
 			matchTabController.setMatches(upcomingMatches, matchStatTabController);
 			countriesList.clear();
@@ -111,11 +114,12 @@ public class MainController implements Initializable {
 				}
 			}
 
-			countriesList.sort((c1, c2) -> c1.getValue().compareTo(c2.getValue()));
+			//			countriesList.sort((c1, c2) -> c1.getValue().compareTo(c2.getValue()));
 			countriesList.forEach(c -> countries.add(c.getValue()));
 
 			homeTeamSelector.setItems(homeTeams);
 			awayTeamSelector.setItems(awayTeams);
+
 		}
 	}
 
@@ -135,6 +139,7 @@ public class MainController implements Initializable {
 			leagues.clear();
 			leagues.add("League");
 			leagues.addAll(newHashSet);
+
 		}
 	}
 
@@ -170,6 +175,7 @@ public class MainController implements Initializable {
 
 			avgLeagueHomeScoreTxt.setText(leagueAvareges.get(0).toString());
 			avgLeagueAwayScoreTxt.setText(leagueAvareges.get(1).toString());
+
 		} else {
 			getMoreLeagueInfo.setDisable(true);
 			getLeagueInfoButton.setDisable(true);
@@ -246,4 +252,5 @@ public class MainController implements Initializable {
 				((Float)selectedItem.get("avgScoreAway")),
 				((Float)selectedItem.get("avgConcededAway")));
 	}
+
 }

+ 33 - 5
OddsJavaFx/src/controllers/MatchTabController.java

@@ -3,6 +3,7 @@ package controllers;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.net.URL;
+import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -23,6 +24,7 @@ import javafx.fxml.Initializable;
 import javafx.scene.control.TableColumn;
 import javafx.scene.control.TableView;
 import javafx.scene.control.cell.MapValueFactory;
+import objects.League;
 import objects.SoccerMatch;
 import objects.TeamResults;
 
@@ -118,14 +120,40 @@ public class MatchTabController implements Initializable {
 			match.put("country", soccerMatch.getHomeTeam().getCountryName());
 			match.put("league", soccerMatch.getHomeTeam().getTeamLeague());
 
+			final DecimalFormat df = new DecimalFormat("#.##");
+			df.setRoundingMode(RoundingMode.CEILING);
+
+			final League leagueInfo = GuiMysql.getInstance().getLeagueInfo(soccerMatch.getHomeTeam().getTeamLeague());
+
+			final int lookBack;
+			if (leagueInfo.getLookback() != 0) {
+				lookBack = leagueInfo.getLookback();
+			} else {
+				lookBack = 10;
+			}
+
+			final float betMargin;
+			if (leagueInfo.getBetMargin() != 0) {
+				betMargin = 1 + (leagueInfo.getBetMargin() / (float)100);
+			} else {
+				betMargin = 1.1f; // Default value???
+			}
 
-			final int lookBack = 15;
 			final TeamResults homeTeamResults = GuiMysql.getInstance().getTeamResults(soccerMatch.getHomeTeam().getTeamId(), lookBack, true);
-			final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResults(soccerMatch.getAwayTeam().getTeamId(), lookBack, true);
+			final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResults(soccerMatch.getAwayTeam().getTeamId(), lookBack, false);
+
+			if (soccerMatch.getHomeTeam().getCountryName().equals("finland")) {
+				System.out.println("HomeTeam " + soccerMatch.getHomeTeam().getTeamName() + " " + homeTeamResults);
+				System.out.println("AwayTeam " + soccerMatch.getAwayTeam().getTeamName() + " "  + homeTeamResults);
+			}
+
+			final float homeWinPercent = (homeTeamResults.getWins() + awayTeamResults.getLosses()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount())* 100;
+			final float drawPercent = (homeTeamResults.getDraws() + awayTeamResults.getDraws()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
+			final float awayWinPercent = (homeTeamResults.getLosses() + awayTeamResults.getWins()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
 
-			match.put("homeWin", (homeTeamResults.getWins() + awayTeamResults.getLosses()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100f + "(" + (homeTeamResults.getCount() + awayTeamResults.getCount()) + ")");
-			match.put("draw", (homeTeamResults.getDraws() + awayTeamResults.getDraws()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100f);
-			match.put("awayWin", (homeTeamResults.getLosses() + awayTeamResults.getWins()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100f);
+			match.put("homeWin", String.format("%.02f", homeWinPercent) + "(" + String.format("%.02f", (100 / homeWinPercent) * betMargin) + ")");
+			match.put("draw", String.format("%.02f", drawPercent) + "(" + String.format("%.02f", (100 / drawPercent ) * betMargin) + ")");
+			match.put("awayWin", String.format("%.02f", awayWinPercent) + "(" + String.format("%.02f", (100 / awayWinPercent) * betMargin) + ")");
 
 			matches.add(match);
 		}

+ 180 - 0
OddsJavaFx/src/controllers/PastResultsController.java

@@ -0,0 +1,180 @@
+package controllers;
+
+import java.io.IOException;
+import java.net.URL;
+import java.time.LocalDate;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.ResourceBundle;
+
+import com.google.common.collect.Lists;
+
+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.ScrollPane;
+import javafx.scene.layout.AnchorPane;
+
+public class PastResultsController implements Initializable {
+
+	@FXML AnchorPane basePane;
+	@FXML Button getResults;
+	@FXML ScrollPane resultsPanel;
+	@FXML DatePicker date;
+	@FXML ComboBox<String> sportSelector;
+	@FXML ComboBox<String> countrySelector;
+	@FXML ComboBox<String> leagueSelector;
+
+	ObservableList<String> sports = FXCollections.observableArrayList();
+	ObservableList<String> countries = FXCollections.observableArrayList();
+	ObservableList<String> leagues = FXCollections.observableArrayList();
+
+	private final ArrayList<SimpleEntry<Integer, String>> sportsList = Lists.newArrayList();
+	private final ArrayList<SimpleEntry<Integer, String>> countriesList = Lists.newArrayList();
+	private final ArrayList<SimpleEntry<Integer, String>> leaguesList = Lists.newArrayList();
+
+
+	@Override
+	public void initialize(URL arg0, ResourceBundle arg1) {
+
+		getResults.setDisable(true);
+		basePane.setPrefWidth(0.0);
+		basePane.setPrefHeight(0.0);
+
+		resultsPanel.setPrefHeight(0.0);
+
+		date.valueProperty().addListener((ov, oldValue, newValue) -> {
+			if (newValue == null || newValue.isAfter(LocalDate.now())) {
+				getResults.setDisable(true);
+			} else {
+				getResults.setDisable(false);
+			}
+		});
+
+		sportsList.addAll(GuiMysql.getInstance().getSports());
+		sports.add("Sport");
+		for (final SimpleEntry<Integer, String>  entry : sportsList) {
+			if (entry.getValue().equals("soccer")) { // Använder just nu bara Soccer
+				sports.add(entry.getValue());
+			}
+		}
+
+		sportSelector.setItems(sports);
+		countrySelector.setItems(countries);
+		leagueSelector.setItems(leagues);
+
+	}
+
+
+	@FXML
+	private void getResults() {
+		final String selectedSport = sportSelector.getValue();
+		if (selectedSport != null && !selectedSport.equals("Sport")) {
+			//			countrySelector.setDisable(false);
+			//			final int sportId = sportsList.stream().filter(p -> p.getValue().equals(sportSelector.getValue())).findFirst().get().getKey();
+			//			final ArrayList<SoccerMatch> upcomingMatches = GuiMysql.getInstance().getMatches("SoccerResults", sportId, "");
+			//
+			//			matchTabController.setMatches(upcomingMatches, matchStatTabController);
+			//			countriesList.clear();
+			//			for (final SoccerMatch soccerMatch : upcomingMatches) {
+			//				homeTeams.add(soccerMatch.getHomeTeam().getTeamName());
+			//				awayTeams.add(soccerMatch.getAwayTeam().getTeamName());
+			//
+			//				if (countriesList.stream().noneMatch(p -> p != null && p.getValue().equals(soccerMatch.getHomeTeam().getCountryName()))) {
+			//					countriesList.add(new SimpleEntry<>(soccerMatch.getHomeTeam().getCountryId(), soccerMatch.getHomeTeam().getCountryName()));
+			//				}
+			//			}
+			//
+			//			countriesList.sort((c1, c2) -> c1.getValue().compareTo(c2.getValue()));
+			//			countriesList.forEach(c -> countries.add(c.getValue()));
+			//
+			//			homeTeamSelector.setItems(homeTeams);
+			//			awayTeamSelector.setItems(awayTeams);
+		}
+	}
+
+	@FXML
+	private void CountrySelected(ActionEvent event) {
+		//		if (countrySelector.getValue() != null && !countrySelector.getValue().equals("Country")) {
+		//			leagueSelector.setDisable(false);
+		//			final int countryId = getCountryIdFromSelector();
+		//			final int sportId = getSportIdFromName(selectedSport);
+		//
+		//			matchTabController.filterCountryMatches(countrySelector.getValue());
+		//
+		//			leaguesList = GuiMysql.getInstance().getLeagues(sportId, countryId);
+		//			final List<String> leaguesInTable = Lists.newArrayList();
+		//			matchTabController.getTableMatches().forEach(tr -> leaguesInTable.add((String) tr.get("league")));
+		//			final HashSet<String> newHashSet = Sets.newHashSet(leaguesInTable);
+		//
+		//			leagues.clear();
+		//			leagues.add("League");
+		//			leagues.addAll(newHashSet);
+		//
+		//			selectedCountry = countrySelector.getValue();
+		//		}
+	}
+
+	@FXML
+	private void SportSelected(ActionEvent event) throws IOException {
+		if (sportSelector.getValue() != null && !sportSelector.getValue().equals("Sport")) {
+			countrySelector.setDisable(false);
+			final int sportId = getSportIdFromName(sportSelector.getValue());
+
+			// GetCuntries by Sport needed
+			countriesList.clear();
+			countriesList.addAll(GuiMysql.getInstance().getCountriesBySport(sportId, date.getValue().toString()));
+			//			final ArrayList<SoccerMatch> upcomingMatches = GuiMysql.getInstance().getMatches("SoccerResults", sportId, date.getValue().toString());
+
+			//			for (final SoccerMatch soccerMatch : upcomingMatches) {
+			//				if (countriesList.stream().noneMatch(p -> p != null && p.getValue().equals(soccerMatch.getHomeTeam().getCountryName()))) {
+			//					countriesList.add(new SimpleEntry<>(soccerMatch.getHomeTeam().getCountryId(), soccerMatch.getHomeTeam().getCountryName()));
+			//				}
+			//			}
+
+			//			countriesList.sort((c1, c2) -> c1.getValue().compareTo(c2.getValue()));
+			countriesList.forEach(c -> countries.add(c.getValue()));
+		}
+	}
+
+	private int getSportIdFromName(String value) {
+		return sportsList.stream().filter(p -> p.getValue().equals(value)).findFirst().get().getKey();
+	}
+
+
+	@FXML
+	private void LeagueSelected(ActionEvent event) {
+
+		//		if (leagueSelector.getValue() != null && !leagueSelector.getValue().equals("League")) {
+		//			homeTeamSelector.setDisable(false);
+		//			awayTeamSelector.setDisable(false);
+		//			showMatchStatsButton.setDisable(false);
+		//			if (GuiMysql.getInstance().getParsingStarted(getCountryIdFromSelector(), getLeagueIdFromSelector())) {
+		//				getLeagueInfoButton.setDisable(true);
+		//				getMoreLeagueInfo.setDisable(false);
+		//			} else {
+		//				getLeagueInfoButton.setDisable(false);
+		//				getMoreLeagueInfo.setDisable(true);
+		//			}
+		//			matchTabController.filterLeagueMatches(leagueSelector.getValue());
+		//			updateStatsTableButton.setDisable(false);
+		//			final ArrayList<Float> leagueAvareges = GuiMysql.getInstance().getLeagueAvarages(getLeagueIdFromSelector(), getCountryIdFromSelector());
+		//
+		//			avgLeagueHomeScoreTxt.setText(leagueAvareges.get(0).toString());
+		//			avgLeagueAwayScoreTxt.setText(leagueAvareges.get(1).toString());
+		//
+		//			selectedLeague = leagueSelector.getValue();
+		//		} else {
+		//			getMoreLeagueInfo.setDisable(true);
+		//			getLeagueInfoButton.setDisable(true);
+		//			updateStatsTableButton.setDisable(true);
+		//			showMatchStatsButton.setDisable(true);
+		//		}
+	}
+}

+ 234 - 0
OddsJavaFx/src/controllers/TestsController.java

@@ -0,0 +1,234 @@
+package controllers;
+
+import java.net.URL;
+import java.time.LocalDate;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.ResourceBundle;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+
+import data.GuiMysql;
+import javafx.application.Platform;
+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.ScrollPane;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.AnchorPane;
+import parser.OddsPortal;
+import tests.LastResultsTest;
+import tests.PrioCountriesAll;
+
+public class TestsController implements Initializable {
+
+	@FXML AnchorPane basePane;
+	@FXML AnchorPane testSettingsPanel;
+	@FXML AnchorPane testResultsPanel;
+	@FXML Button getResults;
+	@FXML ScrollPane resultsPanel;
+	@FXML DatePicker date;
+	@FXML ComboBox<String> countrySelector;
+	@FXML ComboBox<String> leagueSelector;
+	@FXML TextField bettingLevel;
+	@FXML TextField startingBank;
+	@FXML TextField lookBack;
+	@FXML TextField betMargin;
+	@FXML Button calcBestValues;
+	@FXML Button getLeagueInfoButton;
+	@FXML Button getMoreLeagueInfoButton;
+	@FXML Button topLeaguesTest;
+
+
+	ObservableList<String> countries = FXCollections.observableArrayList();
+	ObservableList<String> leagues = FXCollections.observableArrayList();
+
+	private final ArrayList<SimpleEntry<Integer, String>> countriesList = Lists.newArrayList();
+	private ArrayList<SimpleEntry<Integer, String>> leaguesList = Lists.newArrayList();
+	private int mSportId;
+
+	@Override
+	public void initialize(URL arg0, ResourceBundle arg1) {
+		getResults.setDisable(true);
+		basePane.setPrefWidth(0.0);
+		basePane.setPrefHeight(0.0);
+
+		date.valueProperty().addListener((ov, oldValue, newValue) -> {
+			if (newValue == null || newValue.isAfter(LocalDate.now())) {
+				getResults.setDisable(true);
+			} else {
+				getResults.setDisable(false);
+			}
+		});
+
+		countrySelector.setItems(countries);
+		leagueSelector.setItems(leagues);
+		testSettingsPanel.setVisible(false);
+	}
+
+	@FXML
+	private void getResults() {
+		initCountries();
+	}
+
+	@FXML
+	private void CountrySelected(ActionEvent event) {
+		if (countrySelector.getValue() != null && !countrySelector.getValue().equals("Country")) {
+			leagueSelector.setDisable(false);
+			final int countryId = getCountryIdFromSelector();
+			final int sportId = getSoccerId();
+
+			leaguesList = GuiMysql.getInstance().getLeaguesByDate(sportId, countryId, date.getValue().toString());
+
+			leagues.clear();
+			leagues.add("League");
+			leaguesList.forEach(l -> leagues.add(l.getValue()));
+		}
+	}
+
+	private Integer getCountryIdFromSelector() {
+		return countriesList.stream().filter(p -> p.getValue().equals(countrySelector.getValue())).findFirst().get().getKey();
+	}
+
+	private Integer getLeagueIdFromSelector() {
+		return leaguesList.stream().filter(p -> p.getValue().equals(leagueSelector.getValue())).findFirst().get().getKey();
+	}
+
+	private void initCountries() {
+		countrySelector.setDisable(false);
+		final int sportId = getSoccerId();
+
+		countriesList.clear();
+		countriesList.addAll(GuiMysql.getInstance().getCountriesBySport(sportId, date.getValue().toString()));
+
+		countriesList.forEach(c -> countries.add(c.getValue()));
+	}
+
+	private int getSoccerId() {
+		if (mSportId <= 0) {
+			mSportId = GuiMysql.getInstance().getSportId("soccer");
+		}
+
+		return mSportId;
+	}
+
+	@FXML
+	private void LeagueSelected(ActionEvent event) {
+
+		//		if (leagueSelector.getValue() != null && !leagueSelector.getValue().equals("League")) {
+		//			homeTeamSelector.setDisable(false);
+		//			awayTeamSelector.setDisable(false);
+		//			showMatchStatsButton.setDisable(false);
+		//			if (GuiMysql.getInstance().getParsingStarted(getCountryIdFromSelector(), getLeagueIdFromSelector())) {
+		//				getLeagueInfoButton.setDisable(true);
+		//				getMoreLeagueInfo.setDisable(false);
+		//			} else {
+		//				getLeagueInfoButton.setDisable(false);
+		//				getMoreLeagueInfo.setDisable(true);
+		//			}
+		//			matchTabController.filterLeagueMatches(leagueSelector.getValue());
+		//			updateStatsTableButton.setDisable(false);
+		//			final ArrayList<Float> leagueAvareges = GuiMysql.getInstance().getLeagueAvarages(getLeagueIdFromSelector(), getCountryIdFromSelector());
+		//
+		//			avgLeagueHomeScoreTxt.setText(leagueAvareges.get(0).toString());
+		//			avgLeagueAwayScoreTxt.setText(leagueAvareges.get(1).toString());
+		//
+		//			selectedLeague = leagueSelector.getValue();
+		//		} else {
+		//			getMoreLeagueInfo.setDisable(true);
+		//			getLeagueInfoButton.setDisable(true);
+		//			updateStatsTableButton.setDisable(true);
+		//			showMatchStatsButton.setDisable(true);
+		//		}
+
+		if (GuiMysql.getInstance().getParsingStarted(getCountryIdFromSelector(), getLeagueIdFromSelector())) {
+			getLeagueInfoButton.setDisable(true);
+			getMoreLeagueInfoButton.setDisable(false);
+		} else {
+			getLeagueInfoButton.setDisable(false);
+			getMoreLeagueInfoButton.setDisable(true);
+		}
+		testSettingsPanel.setVisible(true);
+	}
+
+	@FXML
+	private void runTestAction() {
+		//		testSettingsPanel.setVisible(false);
+		//		testResultsPanel.setVisible(true);
+
+		String betLevel = Strings.isNullOrEmpty(bettingLevel.getText())?bettingLevel.getPromptText():bettingLevel.getText();
+		String betM = Strings.isNullOrEmpty(betMargin.getText())?betMargin.getPromptText():betMargin.getText();
+		final String startBank = Strings.isNullOrEmpty(startingBank.getText())?startingBank.getPromptText():startingBank.getText();
+		final String lookBackVal = Strings.isNullOrEmpty(lookBack.getText())?lookBack.getPromptText():lookBack.getText();
+
+
+		betLevel = betLevel.replace("%", "").trim();
+		betM = betM.replace("%","").trim();
+
+		final LastResultsTest test = new LastResultsTest();
+		System.out.println("Running tests");
+		test.run(date.getValue().toString(), Float.valueOf(startBank), Float.valueOf(betLevel), Float.valueOf(betM),
+				Integer.valueOf(lookBackVal), mSportId, getCountryIdFromSelector(), getLeagueIdFromSelector());
+	}
+
+	@FXML
+	private void calcBestResultsAction() {
+		final LastResultsTest test = new LastResultsTest();
+
+		calcBestValues.setDisable(true);
+		final String buttonText = calcBestValues.getText();
+		Platform.runLater(() -> {
+			calcBestValues.setText("RUNNING...");
+			test.calcBestResults(mSportId, getCountryIdFromSelector(), getLeagueIdFromSelector());
+			calcBestValues.setDisable(false);
+
+			calcBestValues.setText(buttonText);
+		});
+	}
+	@FXML void getLeagueInfo() {
+		final String country = countrySelector.getValue().trim();
+		final String league = leagueSelector.getValue().trim();
+		final OddsPortal op = new OddsPortal();
+		op.getHistoricMatches("soccer", country, league, String.valueOf(LocalDate.now().getYear()));
+	}
+
+	@FXML
+	private void getMoreLeagueInfo() {
+		final String lastParsedYear = GuiMysql.getInstance().getLastParsedYear(leagueSelector.getValue().trim(), getCountryIdFromSelector());
+		final String nextParseYear;
+		if (lastParsedYear.contains("-")) {
+			final String[] years = lastParsedYear.split("-");
+			int firstYear = Integer.valueOf(years[0]);
+			int lastYear = Integer.valueOf(years[1]);
+			firstYear--;
+			lastYear--;
+			nextParseYear = firstYear + "-" + lastYear;
+		} else if (lastParsedYear.length() == 4) {
+			Integer val = Integer.valueOf(lastParsedYear);
+			val--;
+			nextParseYear = String.valueOf(val);
+		} else {
+			System.out.println("Fail to get More league info for " + lastParsedYear);
+			return;
+		}
+
+		final String country = countrySelector.getValue().trim();
+		final String league = leagueSelector.getValue().trim();
+
+
+		final OddsPortal op = new OddsPortal();
+		op.getHistoricMatches("soccer", country, league, nextParseYear);
+	}
+
+	@FXML
+	private void topLeaguesTestAction() {
+		final PrioCountriesAll prioCountriesAll = new PrioCountriesAll();
+		prioCountriesAll.runTest();
+	}
+}

+ 145 - 7
OddsJavaFx/src/data/GuiMysql.java

@@ -16,6 +16,7 @@ import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 
 import mysql.Mysql;
+import objects.League;
 import objects.OverUnder;
 import objects.SoccerMatch;
 import objects.Team;
@@ -99,18 +100,26 @@ public class GuiMysql extends Mysql {
 		return leagues;
 	}
 
-	public ArrayList<SoccerMatch> getTodaysMatches(String sportResultTable, int sportId) {
+
+	public ArrayList<SoccerMatch> getUpcomingMatches(String sportResultTable, int sportId) {
 		final ArrayList<SoccerMatch> matches = Lists.newArrayList();
+		final String dateSql;
+		dateSql =  " AND DATE(gameDate) >= DATE(now())";
+
 		final String sql = "SELECT res.id, homeTeam, awayTeam, homeScore, awayScore, overtime, odds1, oddsX, odds2, gameDate, season, res.leagueId, res.countryId, " +
 				"hTeam.name as homeTeamName, aTeam.name as awayTeamName, " +
 				"league.name as leagueName, " +
-				"country.name as countryName " +
+				"country.name as countryName, " +
+				"country.prio as prio " +
 				"FROM " + sportResultTable + " as res " +
 				"Join Team as hTeam ON res.homeTeam = hTeam.id " +
 				"Join Team as aTeam ON res.awayTeam = aTeam.id " +
 				"Join League as league ON res.leagueId = league.id " +
 				"Join Country as country ON res.countryId = country.id " +
-				"where homeScore = -1 AND DATE(gameDate) = DATE(now()) AND league.name NOT LIKE '%cup%' AND league.name NOT LIKE '%group%'";
+				"where homeScore = -1 " +
+				dateSql +
+				"AND league.name NOT LIKE '%cup%' AND league.name NOT LIKE '%group%' " +
+				"ORDER BY country.prio DESC, country.name ASC";
 
 		try {
 			final PreparedStatement stmt = conn.prepareStatement(sql);
@@ -143,6 +152,7 @@ public class GuiMysql extends Mysql {
 				sm.setOddsX(rs.getFloat("oddsX"));
 				sm.setOdds2(rs.getFloat("odds2"));
 				sm.setGameDate(LocalDateTime.parse(rs.getString("gameDate")));
+				sm.setCountryPrio(rs.getBoolean("prio"));
 
 				matches.add(sm);
 			}
@@ -376,14 +386,14 @@ public class GuiMysql extends Mysql {
 			sql = "SELECT count(case when homeScore > awayScore then 1 end) wins, " +
 					"count(case when awayScore > homeScore then 1 end) lost, " +
 					"count(case when homeScore = awayScore then 1 end) draws " +
-					"FROM SoccerResults WHERE homeTeam = ? AND " +
-					"HomeScore >= 0 AND awayScore >= 0 LIMIT ?";
+					"FROM (SELECT * FROM SoccerResults WHERE homeTeam = ? AND " +
+					"HomeScore >= 0 AND awayScore >= 0 ORDER BY gameDate DESC LIMIT ?) as t";
 		} else {
 			sql = "SELECT count(case when homeScore < awayScore then 1 end) wins, " +
 					"count(case when awayScore < homeScore then 1 end) lost, " +
 					"count(case when homeScore = awayScore then 1 end) draws " +
-					"FROM SoccerResults WHERE awayTeam = ? AND " +
-					"HomeScore >= 0 AND awayScore >= 0 LIMIT ?";
+					"FROM (SELECT * FROM SoccerResults WHERE awayTeam = ? AND " +
+					"HomeScore >= 0 AND awayScore >= 0 ORDER BY gameDate DESC LIMIT ?) as t";
 		}
 
 		try {
@@ -401,6 +411,8 @@ public class GuiMysql extends Mysql {
 				tr.setLosses(lost);
 				tr.setCount(wins+draws+lost);
 			}
+
+			stat.close();
 		} catch (final SQLException e) {
 			// TODO Auto-generated catch block
 			e.printStackTrace();
@@ -408,4 +420,130 @@ public class GuiMysql extends Mysql {
 
 		return tr;
 	}
+
+	public ArrayList<SimpleEntry<Integer, String>> getCountriesBySport(int sportId, String date) {
+		final String sql = "SELECT * FROM Country WHERE id IN (SELECT DISTINCT(countryId) FROM SoccerResults WHERE DATE(gameDate) = ?) ORDER BY prio DESC, name ASC";
+		final ArrayList<SimpleEntry<Integer, String>> result = new ArrayList<>();
+		try {
+			final PreparedStatement stat = getConnection().prepareStatement(sql);
+			if (date.equals("")) {
+				stat.setString(1, "DATE(NOW())");
+			} else {
+				stat.setString(1, date);
+			}
+
+			final ResultSet rs = stat.executeQuery();
+
+			while (rs.next()) {
+				result.add(new SimpleEntry<Integer, String>(rs.getInt("id"), rs.getString("name")));
+			}
+		} catch (final SQLException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+
+		return result;
+	}
+
+	public ArrayList<SimpleEntry<Integer, String>> getLeaguesByDate(int sportId, int countryId, String date) {
+		final ArrayList<AbstractMap.SimpleEntry<Integer, String>> leagues = Lists.newArrayList();
+		try {
+			final String sql = "SELECT id, name FROM League WHERE id IN (SELECT leagueId FROM SoccerResults WHERE sportId = ? AND countryId = ? AND DATE(gameDate) = ?)";
+			//			final String sql = "SELECT id, name FROM League WHERE sportId = ? AND countryId = ? ORDER BY name ASC";
+			final PreparedStatement stmt = conn.prepareStatement(sql);
+			stmt.setInt(1, sportId);
+			stmt.setInt(2, countryId);
+			stmt.setString(3, date);
+
+			final ResultSet rs = stmt.executeQuery();
+
+			while (rs.next()) {
+				final SimpleEntry<Integer, String> entry = new SimpleEntry<>(rs.getInt("id"), rs.getString("name"));
+				leagues.add(entry);
+			}
+		} catch (final SQLException e) {
+			e.printStackTrace();
+		}
+		return leagues;
+	}
+
+	public ArrayList<SoccerMatch> getMatches(int sportId, Integer countryId, Integer leagueId, String date, String order) {
+		final ArrayList<SoccerMatch> matches = Lists.newArrayList();
+		final String dateSql;
+		final String orderSql = " ORDER BY gameDate " + order;
+		if (date.equals("")) {
+			dateSql =  "DATE(gameDate) = DATE(NOW()) ";
+		} else {
+			dateSql = "DATE(gameDate) <= '" + date + "' ";
+		}
+		final String sql = "SELECT res.*, " +
+				"hTeam.name as homeTeamName, aTeam.name as awayTeamName " +
+				"FROM SoccerResults as res " +
+				"Join Team as hTeam ON res.homeTeam = hTeam.id " +
+				"Join Team as aTeam ON res.awayTeam = aTeam.id " +
+				"WHERE " +
+				dateSql +
+				"AND res.leagueId = ? " +
+				"AND res.countryId = ? " +
+				orderSql;
+
+		try {
+			final PreparedStatement stmt = conn.prepareStatement(sql);
+
+			stmt.setInt(1, leagueId);
+			stmt.setInt(2, countryId);
+
+			final ResultSet rs = stmt.executeQuery();
+			while (rs.next()) {
+				final SoccerMatch sm = new SoccerMatch();
+				final Team homeTeam = new Team();
+				final Team awayTeam = new Team();
+
+				homeTeam.setTeamId(rs.getInt("homeTeam"));
+				awayTeam.setTeamId(rs.getInt("awayTeam"));
+				homeTeam.setTeamName(rs.getString("homeTeamName"));
+				awayTeam.setTeamName(rs.getString("awayTeamName"));
+				homeTeam.setTeamLeagueId(rs.getInt("leagueId"));
+				awayTeam.setTeamLeagueId(rs.getInt("leagueId"));
+				homeTeam.setCountryId(rs.getInt("countryId"));
+				awayTeam.setCountryId(rs.getInt("countryId"));
+
+				sm.setAwayScore(rs.getInt("awayScore"));
+				sm.setHomeScore(rs.getInt("homeScore"));
+				sm.setHomeTeam(homeTeam);
+				sm.setAwayTeam(awayTeam);
+				sm.setMatchId(rs.getInt("id"));
+				sm.setOdds1(rs.getFloat("odds1"));
+				sm.setOddsX(rs.getFloat("oddsX"));
+				sm.setOdds2(rs.getFloat("odds2"));
+				sm.setGameDate(LocalDateTime.parse(rs.getString("gameDate")));
+				sm.setSeason(rs.getString("season"));
+
+				matches.add(sm);
+			}
+
+		} catch (final SQLException e) {
+			e.printStackTrace();
+		}
+
+		return matches;
+	}
+
+	public League getLeagueInfo(String teamLeague) {
+		final String sql = "SELECT * FROM League WHERE name = ?";
+		League result = null;
+		try {
+			final PreparedStatement stat = getConnection().prepareStatement(sql);
+			stat.setString(1, teamLeague);
+			final ResultSet rs = stat.executeQuery();
+
+			while (rs.next()) {
+				result = new League(rs.getInt("id"), rs.getString("name"), rs.getInt("lookback"), rs.getInt("betMargin"));
+			}
+		} catch (final SQLException e) {
+			e.printStackTrace();
+		}
+
+		return result;
+	}
 }

+ 11 - 1
OddsJavaFx/src/fxml/OddsFxBuilder.fxml

@@ -16,7 +16,7 @@
 <?import javafx.scene.layout.StackPane?>
 <?import javafx.scene.text.Font?>
 
-<StackPane prefHeight="800.0" prefWidth="1600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.MainController">
+<StackPane prefHeight="800.0" prefWidth="1600.0" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.MainController">
    <children>
       <BorderPane prefHeight="600.0" prefWidth="1200.0">
          <top>
@@ -108,6 +108,16 @@
  						<fx:include fx:id="matchStatTab" source="MatchStatTabBuilder.fxml" />               	
                 	</content>
                 </Tab>
+                <Tab text="Old results">
+                	<content>
+                		<fx:include fx:id="oldResultsTab" source="PastResults.fxml" />
+                	</content>
+                </Tab>
+                <Tab text="Testing">
+	                <content>
+	                   <fx:include fx:id="testsTab" source="Testing.fxml" />
+	                </content>
+                </Tab>
               </tabs>
             </TabPane>
          </center>

+ 36 - 0
OddsJavaFx/src/fxml/PastResults.fxml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.control.DatePicker?>
+<?import javafx.scene.control.ScrollPane?>
+<?import javafx.scene.control.ComboBox?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.FlowPane?>
+<?import javafx.scene.layout.VBox?>
+
+<AnchorPane fx:id="basePane" prefHeight="414.0" prefWidth="736.0" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.PastResultsController">
+   <children>
+      <VBox prefHeight="414.0" prefWidth="736.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+         <children>
+          <AnchorPane>
+               <children>
+                  <FlowPane maxHeight="30.0" minHeight="30.0" prefHeight="30.0" prefWidth="598.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                     <children>
+                        <DatePicker fx:id="date" prefHeight="30.0" prefWidth="209.0" />
+                        <Button fx:id="getResults" mnemonicParsing="false" prefHeight="30.0" prefWidth="96.0" text="GetResults" onAction="#getResults" />
+                        <ComboBox id="SportComboBox" fx:id="sportSelector" onAction="#SportSelected" prefHeight="25.0" prefWidth="200.0" promptText="Sport" />
+            		    <ComboBox id="CountryComboBox" fx:id="countrySelector" disable="true" onAction="#CountrySelected" prefHeight="25.0" prefWidth="200.0" promptText="Country" />
+                        <ComboBox id="LeagueComboBox" fx:id="leagueSelector" disable="true" onAction="#LeagueSelected" prefHeight="25.0" prefWidth="200.0" promptText="League" />
+                     </children>
+                  </FlowPane>
+               </children>
+            </AnchorPane>
+          <AnchorPane>
+               <children>
+                  <ScrollPane fx:id="resultsPanel" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
+               </children>
+            </AnchorPane>
+         </children>
+      </VBox>
+   </children>
+</AnchorPane>

+ 20 - 0
OddsJavaFx/src/fxml/Settings.fxml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.ScrollPane?>
+<?import javafx.scene.control.SplitPane?>
+<?import javafx.scene.control.TextField?>
+<?import javafx.scene.layout.AnchorPane?>
+
+<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1">
+   <children>
+      <ScrollPane fx:id="scrollPane" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+         <content>
+            <SplitPane dividerPositions="0.5" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
+               <items>
+                  <TextField editable="false" text="Prioriterade ligor" />
+                  <ScrollPane fx:id="prioLeaguesSelector" prefHeight="200.0" prefWidth="200.0" />
+               </items>
+            </SplitPane>
+         </content></ScrollPane>
+   </children>
+</AnchorPane>

+ 76 - 0
OddsJavaFx/src/fxml/Testing.fxml

@@ -0,0 +1,76 @@
+<?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.Pane?>
+<?import javafx.scene.layout.VBox?>
+
+<AnchorPane fx:id="basePane" prefHeight="414.0" prefWidth="736.0" xmlns="http://javafx.com/javafx/15.0.1" 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">
+         <children>
+          <AnchorPane>
+               <children>
+                  <FlowPane maxHeight="30.0" minHeight="30.0" prefHeight="30.0" prefWidth="598.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                     <children>
+                        <DatePicker fx:id="date" prefHeight="30.0" prefWidth="209.0" />
+                        <Button fx:id="getResults" mnemonicParsing="false" onAction="#getResults" prefHeight="30.0" prefWidth="96.0" text="GetResults" />
+            		    <ComboBox id="CountryComboBox" fx:id="countrySelector" disable="true" onAction="#CountrySelected" prefHeight="25.0" prefWidth="200.0" promptText="Country" />
+                        <ComboBox id="LeagueComboBox" fx:id="leagueSelector" disable="true" onAction="#LeagueSelected" prefHeight="25.0" prefWidth="200.0" promptText="League" />
+                        
+                        <Button fx:id="getLeagueInfoButton" mnemonicParsing="false" disable="true" onAction="#getLeagueInfo" prefHeight="30.0" prefWidth="96.0" text="Get league info" />
+                        <Button fx:id="getMoreLeagueInfoButton" mnemonicParsing="false" disable="true" onAction="#getMoreLeagueInfo" prefHeight="30.0" prefWidth="96.0" text="Get more league info" />
+                     </children>
+                  </FlowPane>
+               </children>
+            </AnchorPane>
+          <AnchorPane fx:id="testSettingsPanel" prefHeight="386.0" prefWidth="736.0">
+               <children>
+                  <SplitPane dividerPositions="0.5" prefHeight="351.0" prefWidth="736.0" AnchorPane.bottomAnchor="34.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                    <items>
+                      <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
+                           <children>
+                              <VBox prefHeight="383.0" prefWidth="216.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                                 <children>
+                                    <TextField editable="false" text="Starting cash" />
+                                    <TextField editable="false" text="Betting level" />
+                                    <TextField editable="false" text="Games lookback" />
+                                    <TextField editable="false" text="Bet margin" />
+                                 </children>
+                              </VBox>
+                           </children>
+                        </AnchorPane>
+                      <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
+                           <children>
+                              <VBox prefHeight="383.0" prefWidth="512.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                                 <children>
+                                    <TextField fx:id="startingBank" promptText="1000" />
+                                    <TextField fx:id="bettingLevel" promptText="1%" />
+                                    <TextField fx:id="lookBack" promptText="10" />
+                                    <TextField fx:id="betMargin" promptText="5%" />
+                                    <Button fx:id="calcBestValues" onAction="#calcBestResultsAction" text="Calc Best values"/>
+                                    <Button fx:id="topLeaguesTest" onAction="#topLeaguesTestAction" text="Top Leagues Test"/>
+                                 </children>
+                              </VBox>
+                           </children>
+                        </AnchorPane>
+                    </items>
+                  </SplitPane>
+                  <Pane layoutX="-1.0" layoutY="390.0" prefHeight="30.0" prefWidth="736.0">
+                     <children>
+                        <Button onAction="#runTestAction" layoutX="338.0" layoutY="2.0" mnemonicParsing="false" text="Run test" />
+                     </children>
+                  </Pane>
+               </children>
+            </AnchorPane>
+            <AnchorPane fx:id="testResultsPanel" prefHeight="386.0" prefWidth="736.0">
+            </AnchorPane>
+         </children>
+      </VBox>
+   </children>
+</AnchorPane>

+ 34 - 0
OddsJavaFx/src/objects/CountryObject.java

@@ -0,0 +1,34 @@
+package objects;
+
+public class CountryObject {
+
+	int id;
+	String name;
+	boolean prio;
+
+	public CountryObject(int id, String name, boolean prio) {
+		super();
+		this.id = id;
+		this.name = name;
+		this.prio = prio;
+	}
+
+	public int getId() {
+		return id;
+	}
+	public String getName() {
+		return name;
+	}
+	public boolean isPrio() {
+		return prio;
+	}
+	public void setId(int id) {
+		this.id = id;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public void setPrio(boolean prio) {
+		this.prio = prio;
+	}
+}

+ 43 - 0
OddsJavaFx/src/objects/League.java

@@ -0,0 +1,43 @@
+package objects;
+
+public class League {
+
+	int leagueId;
+	String leagueName;
+	int lookback;
+	int betMargin;
+
+	public League(int leagueId, String leagueName, int lookback, int betMargin) {
+		this.leagueId = leagueId;
+		this.leagueName = leagueName;
+		this.lookback = lookback;
+		this.betMargin = betMargin;
+	}
+
+
+	public int getLeagueId() {
+		return leagueId;
+	}
+	public String getLeagueName() {
+		return leagueName;
+	}
+	public int getLookback() {
+		return lookback;
+	}
+	public int getBetMargin() {
+		return betMargin;
+	}
+	public void setLeagueId(int leagueId) {
+		this.leagueId = leagueId;
+	}
+	public void setLeagueName(String leagueName) {
+		this.leagueName = leagueName;
+	}
+	public void setLookback(int lookback) {
+		this.lookback = lookback;
+	}
+	public void setBetMargin(int betMargin) {
+		this.betMargin = betMargin;
+	}
+
+}

+ 23 - 0
OddsJavaFx/src/objects/SoccerMatch.java

@@ -16,6 +16,9 @@ public class SoccerMatch {
 	private float odds2;
 
 	private LocalDateTime gameDate;
+	private String season;
+
+	private boolean countryPrio;
 
 	public Team getHomeTeam() {
 		return homeTeam;
@@ -106,4 +109,24 @@ public class SoccerMatch {
 		this.gameDate = gameDate;
 	}
 
+
+	public String getSeason() {
+		return season;
+	}
+
+
+	public void setSeason(String season) {
+		this.season = season;
+	}
+
+
+	public boolean isCountryPrio() {
+		return countryPrio;
+	}
+
+
+	public void setCountryPrio(boolean countryPrio) {
+		this.countryPrio = countryPrio;
+	}
+
 }

+ 5 - 0
OddsJavaFx/src/objects/TeamResults.java

@@ -34,4 +34,9 @@ public class TeamResults {
 	public void setCount(int count) {
 		this.count = count;
 	}
+
+	@Override
+	public String toString() {
+		return "w: " + wins + " d: " + draws + " l: " + losses + " (Count: " + getCount() + ")";
+	}
 }

+ 319 - 0
OddsJavaFx/src/parser/OddsPortal.java

@@ -0,0 +1,319 @@
+package parser;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Locale;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
+import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
+import com.gargoylesoftware.htmlunit.html.HtmlDivision;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.gargoylesoftware.htmlunit.html.HtmlSpan;
+import com.gargoylesoftware.htmlunit.html.HtmlTable;
+import com.gargoylesoftware.htmlunit.html.HtmlTableCell;
+import com.gargoylesoftware.htmlunit.html.HtmlTableRow;
+import com.google.common.base.Strings;
+
+import mysql.Mysql;
+
+public class OddsPortal implements ParserJoinedFunctions {
+
+	private LocalDateTime baseDate;
+	private int currentParsePage;
+	private int sportId;
+	private int countryId;
+	private int leagueId;
+	private LocalDateTime gameDate;
+
+	// https://stackoverflow.com/questions/14439991/skip-particular-javascript-execution-in-html-unit Skip url
+	public void getMatchesByDate(String date) {
+		final String soccerUrl = "https://oddsportal.com/matches/soccer/" + date;
+		//		final String hockeyUrl = "https://oddsportal.com/matches/hockey/" + date;
+
+		final WebClient webClient = new WebClient();
+		webClient.getOptions().setUseInsecureSSL(true);
+		webClient.getOptions().setCssEnabled(false);
+		webClient.getOptions().setJavaScriptEnabled(true);
+		webClient.getOptions().setThrowExceptionOnScriptError(false);
+		Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
+
+		webClient.waitForBackgroundJavaScript(3000);
+		parseSoccerMatches(soccerUrl, webClient);
+
+		webClient.close();
+	}
+
+	private void parseSoccerMatches(final String soccerUrl, final WebClient webClient) {
+		try {
+			System.out.println("Getting Webpage");
+			final HtmlPage soccerMatches = webClient.getPage(soccerUrl);
+			final HtmlTable matchesTable = soccerMatches.getFirstByXPath("//table[contains(@class, table-main)]");
+			final List<HtmlTableRow> rows = matchesTable.getRows();
+			String countryName = "";
+			String leagueName = "";
+			int i = 1;
+			final int size = rows.size();
+			for (final HtmlTableRow tr : rows) {
+				System.out.println("Processing " + i++ + " of " + size);
+				if (tr.getAttribute("class").equals("dark center")) {
+					final List<HtmlAnchor> countryLeague = tr.getByXPath(".//a");
+					countryName = countryLeague.get(0).getTextContent().toLowerCase().trim();
+					leagueName = countryLeague.get(1).getTextContent().toLowerCase().trim();
+					leagueName = leagueName.replaceAll(" ", "-");
+					leagueName = leagueName.replaceAll("\\.", "");
+					countryName = countryName.replaceAll(" ", "-");
+					countryName = countryName.replaceAll("\\.", "");
+				} else {
+					final List<HtmlTableCell> cells = tr.getCells();
+					final String[] time = cells.get(0).getTextContent().split(":");
+					final String[] teams = cells.get(1).getTextContent().split(" - ");
+					float odds1 = 0F;
+					float oddsX = 0F;
+					float odds2 = 0F;
+					int homeScore = -1;
+					int awayScore = -1;
+					boolean overtime = false;
+
+					boolean abandon = false;
+
+					try {
+						for (final HtmlTableCell tc : cells) {
+							if (tc.getAttribute("class").contains("live-score")) {
+								abandon = true;
+								break;
+							}
+							//Score
+							if (tc.getAttribute("class").contains("table-score")) {
+								final String[] scoreValue = tc.getTextContent().split(":");
+								homeScore = Integer.valueOf(scoreValue[0]);
+								if (scoreValue[1].matches("\\D+")) {
+									overtime = true;
+								}
+								awayScore = Integer.valueOf(scoreValue[1].replaceAll("\\D+", ""));
+							}
+							if (tc.getAttribute("class").contains("odds-nowrp")) {
+								if (tc.getTextContent().matches("[+-][0-9][0-9][0-9]")) {
+									if (odds1 == 0F) {
+										odds1 = convertAmericanOddsToDecimal(Integer.valueOf(tc.getTextContent()));
+									} else if (oddsX == 0F ) {
+										oddsX = convertAmericanOddsToDecimal(Integer.valueOf(tc.getTextContent()));
+									} else if (odds2 == 0F ) {
+										odds2 = convertAmericanOddsToDecimal(Integer.valueOf(tc.getTextContent()));
+									}
+								} else if (tc.getTextContent().matches("[0-9].[0-9]+")) {
+									if (odds1 == 0F) {
+										odds1 = Float.valueOf(tc.getTextContent());
+									} else if (oddsX == 0F ) {
+										oddsX = Float.valueOf(tc.getTextContent());
+									} else if (odds2 == 0F ) {
+										odds2 = Float.valueOf(tc.getTextContent());
+									}
+								}
+							}
+
+						}
+					} catch (final NumberFormatException e) {
+						System.out.println("Failed to get the match between " + teams[0].trim() + " and " + teams[1].trim() + " at " +
+								baseDate.withHour(Integer.valueOf(time[0])).withMinute(Integer.valueOf(time[1])) +
+								" odds1: " + odds1 + " oddsX: " + oddsX + " odds2: " + odds2 + " homeScore " + homeScore + " awayScore " + awayScore + " overtime: " + (overtime?"true":"false"));
+						continue;
+					}
+
+					if (abandon) {
+						continue;
+					}
+					final Mysql mysql = Mysql.getInstance();
+					final int leagueId = mysql.addLueague(leagueName, countryName, "soccer");
+					final int countryId = mysql.getCountryId(countryName);
+					final int sportId = mysql.getSportId("soccer");
+
+					String season = mysql.getLastParsedYear(leagueName, countryId);
+
+					if (Strings.isNullOrEmpty(season)) {
+						season = String.valueOf(LocalDateTime.now().getYear());
+					}
+
+					final LocalDateTime dt = baseDate.withHour(Integer.valueOf(time[0])).withMinute(Integer.valueOf(time[1])).withSecond(0).withNano(0);
+					mysql.addResult("SoccerResults", dt, teams[0].trim(), teams[1].trim(), homeScore, awayScore, overtime, odds1, oddsX, odds2, countryId, season, leagueId, sportId);
+				}
+			}
+		} catch (FailingHttpStatusCodeException | IOException e) {
+			e.printStackTrace();
+		} catch (final SQLException e) {
+			e.printStackTrace();
+		}
+	}
+
+	public void getHistoricMatches(String sport, String country, String league, String year) {
+		final String url = "https://www.oddsportal.com/";
+		final String resultsPage = "/results";
+		final WebClient webClient = new WebClient();
+		webClient.getOptions().setUseInsecureSSL(true);
+		webClient.getOptions().setCssEnabled(false);
+		webClient.getOptions().setJavaScriptEnabled(true);
+		webClient.getOptions().setThrowExceptionOnScriptError(false);
+		Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
+
+		league = league.replaceAll(" ", "-");
+		league = league.replaceAll("\\.", "");
+		country = country.replaceAll(" ", "-");
+		league = league.replaceAll("\\.", "");
+		final Mysql mysql = Mysql.getInstance();
+
+		currentParsePage = 1;
+
+		final String urlYearPart;
+		if (year.equals(String.valueOf(LocalDate.now().getYear()))) {
+			urlYearPart = "";
+		} else {
+			urlYearPart = "-" + year;
+		}
+
+		try {
+			sportId = mysql.getSportId(sport);
+			countryId = mysql.getCountryId(country);
+			leagueId = mysql.getLeagueId(sportId, countryId, league);
+			String season = "";
+
+			final HtmlPage leaguePage = webClient.getPage(url + "/" + sport + "/" + country + "/" + league + urlYearPart + resultsPage);
+			final List<HtmlAnchor> yearFilter = leaguePage.getByXPath("//ul[contains(@class,'main-filter')]//a");
+			for (final HtmlAnchor a : yearFilter) {
+				System.out.println("Year filter: " + a.getHrefAttribute());
+				final String active = ((HtmlSpan)a.getParentNode().getParentNode()).getAttribute("class");
+				if (active.contains("active") && !active.contains("inactive")) {
+					season = a.getTextContent();
+					year = season.replace('/', '-');
+				}
+			}
+
+			HtmlDivision tournamentTableDiv = leaguePage.getHtmlElementById("tournamentTable");
+			HtmlTable tournamentTable = (HtmlTable) tournamentTableDiv.getFirstChild();
+
+			gameDate = LocalDateTime.now();
+			final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd MMM yyyy", Locale.ENGLISH);
+			parseTournamentTable(sportId, countryId, leagueId, season, tournamentTable, gameDate, dateFormatter);
+			final HtmlDivision paginationLinksDiv = (HtmlDivision) tournamentTableDiv.getLastChild();
+			final List<HtmlAnchor> pagiantionLinks = paginationLinksDiv.getByXPath(".//a[contains(@href, 'page') and not(.//span[contains(@class, 'arrow')])]");
+			for (final HtmlAnchor a : pagiantionLinks) {
+				System.out.println("Continuing with Pagination: " + a.getHrefAttribute());
+				// When done with start page click pagiantion
+				final int parsePage = Integer.valueOf(a.getTextContent());
+				if (parsePage > currentParsePage) {
+					a.click();
+					webClient.waitForBackgroundJavaScript(1000);
+
+					tournamentTableDiv = leaguePage.getHtmlElementById("tournamentTable");
+					tournamentTable = (HtmlTable) tournamentTableDiv.getFirstChild();
+					parseTournamentTable(sportId, countryId, leagueId, season, tournamentTable, gameDate, dateFormatter);
+					currentParsePage = parsePage;
+				}
+				// process new tournament table content
+			}
+		} catch (FailingHttpStatusCodeException | IOException e) {
+			e.printStackTrace();
+		} catch (final SQLException sqle) {
+			sqle.printStackTrace();
+		} catch (final ClassCastException cce) {
+			System.out.println("No pagination table");
+			//			cce.printStackTrace();
+		}
+		finally {
+			Mysql.getInstance().setParsingForLeague(leagueId, sportId, countryId, gameDate, currentParsePage, year);
+		}
+		webClient.close();
+		System.out.println("DONE with " + country + " (" + countryId + ") league " + league + "(" + leagueId + ")");
+	}
+
+	private void parseTournamentTable(int sportId, int countryId, int leagueId, String season,
+			HtmlTable tournamentTable, LocalDateTime gameDate, DateTimeFormatter dateFormatter) throws SQLException {
+		for (final HtmlTableRow tr : tournamentTable.getRows()) {
+			if (tr.getAttribute("class").contains("deactivate")) {
+				String homeTeam;
+				String awayTeam;
+				int homeScore = -1;
+				int awayScore = -1;
+				float odds1 = 0f;
+				float oddsX = 0f;
+				float odds2 = 0f;
+				boolean overtime = false;
+
+				final HtmlTableCell timeCell = tr.getCell(0);
+				final HtmlTableCell participantsCell = tr.getCell(1);
+
+				// Game Time
+				final String[] timeValue = timeCell.getTextContent().split(":");
+				gameDate = gameDate.withHour(Integer.valueOf(timeValue[0]));
+				gameDate = gameDate.withMinute(Integer.valueOf(timeValue[1]));
+
+				// Teams
+				final String[] participantsValue = participantsCell.getTextContent().split(" - ");
+				homeTeam = participantsValue[0].trim();
+				awayTeam = participantsValue[1].trim();
+
+
+				final List<HtmlTableCell> cells = tr.getCells();
+				for (final HtmlTableCell tc : cells) {
+					//Score
+					if (tc.getAttribute("class").contains("table-score")) {
+						final String[] scoreValue = tc.getTextContent().split(":");
+						if (scoreValue[0].matches("\\D+")) {
+							continue;
+						}
+						homeScore = Integer.valueOf(scoreValue[0]);
+						if (scoreValue[1].matches("\\D+")) {
+							overtime = true;
+						}
+						awayScore = Integer.valueOf(scoreValue[1].replaceAll("\\D+", ""));
+					}
+
+					if (tc.getAttribute("class").contains("odds-nowrp")) {
+						if (tc.getTextContent().matches("[+-][0-9][0-9][0-9]")) {
+							if (odds1 == 0F) {
+								odds1 = convertAmericanOddsToDecimal(Integer.valueOf(tc.getTextContent()));
+							} else if (oddsX == 0F ) {
+								oddsX = convertAmericanOddsToDecimal(Integer.valueOf(tc.getTextContent()));
+							} else if (odds2 == 0F ) {
+								odds2 = convertAmericanOddsToDecimal(Integer.valueOf(tc.getTextContent()));
+							}
+						} else if (tc.getTextContent().matches("[0-9].[0-9]+")) {
+							if (odds1 == 0F) {
+								odds1 = Float.valueOf(tc.getTextContent());
+							} else if (oddsX == 0F ) {
+								oddsX = Float.valueOf(tc.getTextContent());
+							} else if (odds2 == 0F ) {
+								odds2 = Float.valueOf(tc.getTextContent());
+							}
+						}
+					}
+				}
+
+				if (gameDate != null && homeTeam != null && awayTeam != null &&
+						odds1 != 0 && oddsX != 0 && odds2 != 0 && !Strings.isNullOrEmpty(season)) { // All set.. update sql result table
+					System.out.println("Adding game between " + homeTeam + " and " + awayTeam + " with score " + homeScore + "-" + awayScore);
+					Mysql.getInstance().addResult("SoccerResults", gameDate, homeTeam, awayTeam, homeScore, awayScore, overtime, odds1, oddsX, odds2, countryId, season, leagueId, sportId);
+				} else {
+					System.out.println(String.format("Not adding, missing somethind.. gameDate: %s, homeTeam %s, awayTeam %s, odds1 %s, oddsX %s, odds2 %s, "
+							+ "season %s", gameDate, homeTeam, awayTeam, odds1, oddsX, odds2, season));
+				}
+
+			} else if (tr.getAttribute("class").contains("center nob-border")) { // Datum rader
+				final List<HtmlSpan> dateSpan = tr.getByXPath(".//span[contains(@class, 'datet')]");
+				final String dateString = dateSpan.get(0).getTextContent();
+				if (dateString.toLowerCase().contains("yesterday")) {
+					gameDate = LocalDateTime.now().minusDays(1);
+				} else if (dateString.toLowerCase().contains("today")) {
+					gameDate = LocalDateTime.now();
+				} else {
+					gameDate = LocalDate.parse(dateString, dateFormatter).atStartOfDay();
+				}
+			}
+		}
+	}
+}

+ 163 - 0
OddsJavaFx/src/tests/LastResultsTest.java

@@ -0,0 +1,163 @@
+package tests;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+
+import data.GuiMysql;
+import objects.SoccerMatch;
+import objects.TeamResults;
+
+public class LastResultsTest {
+
+	float bank;
+	float betLevel;
+	float betMarginDecimal;
+
+
+	public void run(String date, float startingBank, float bettingLevel, Float betMargin, int lookBack, int sportId,
+			Integer countryId, Integer leagueId) {
+		bank = startingBank;
+		betLevel = bettingLevel / 100;
+		betMarginDecimal = 1 + (betMargin / 100);
+		final ArrayList<SoccerMatch> matches = GuiMysql.getInstance().getMatches(sportId, countryId, leagueId, date, "ASC");
+
+		final int totalMatchCount = matches.size();
+
+		String season = matches.get(0).getSeason();
+		int betOnGameCount = 0;
+		final LocalDateTime currentDate = matches.get(0).getGameDate();
+		LocalDate localDate = currentDate.toLocalDate();
+		float betAmount = bank * betLevel;
+		for (final SoccerMatch soccerMatch : matches) {
+			if (soccerMatch.getHomeScore() < 0 || soccerMatch.getAwayScore() < 0) {
+				continue;
+			}
+			if (!season.equals(soccerMatch.getSeason())) { // new season reset bank, report result
+				System.out.println("season " + season + " ended with " + bank);
+				bank = startingBank;
+				season = soccerMatch.getSeason();
+			}
+			final TeamResults homeTeamResults = GuiMysql.getInstance().getTeamResults(soccerMatch.getHomeTeam().getTeamId(), lookBack, true);
+			final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResults(soccerMatch.getAwayTeam().getTeamId(), lookBack, false);
+
+			final float homeWinPercent = (homeTeamResults.getWins() + awayTeamResults.getLosses()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount())* 100;
+			final float drawPercent = (homeTeamResults.getDraws() + awayTeamResults.getDraws()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
+			final float awayWinPercent = (homeTeamResults.getLosses() + awayTeamResults.getWins()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
+
+			final float homeOdds = 100 / homeWinPercent;
+			final float drawOdds = 100 / drawPercent;
+			final float awayOdds = 100 / awayWinPercent;
+
+			if (localDate.isBefore(soccerMatch.getGameDate().toLocalDate())) {
+				betAmount = bank * betLevel;
+				localDate = soccerMatch.getGameDate().toLocalDate();
+			}
+			if (homeOdds * betMarginDecimal <= soccerMatch.getOdds1()) {
+				betOnGameCount++;
+				//				System.out.print(soccerMatch.getGameDate() + " Bet " + betAmount + " on home team " + soccerMatch.getHomeTeam().getTeamName() + " - " + soccerMatch.getAwayTeam().getTeamName() + " at odds " + soccerMatch.getOdds1()
+				//				+ " Result " + soccerMatch.getHomeScore() + " - " + soccerMatch.getAwayScore());
+				bank = bank - betAmount;
+				if (soccerMatch.getHomeScore() > soccerMatch.getAwayScore()) {
+					bank = bank + betAmount * soccerMatch.getOdds1();
+					//					System.out.println(" Win, new Bank " + bank);
+				} else {
+					//					System.out.println(" Loss new Bank " + bank);
+				}
+			}
+			if (awayOdds * betMarginDecimal <= soccerMatch.getOdds2()) {
+				betOnGameCount++;
+				//				System.out.print(soccerMatch.getGameDate() + " Bet " + betAmount + " on away team " + soccerMatch.getHomeTeam().getTeamName() + " - " + soccerMatch.getAwayTeam().getTeamName() + " at odds " + soccerMatch.getOdds2()
+				//				+ " Result " + soccerMatch.getHomeScore() + " - " + soccerMatch.getAwayScore());
+				bank = bank - betAmount;
+				if (soccerMatch.getAwayScore() > soccerMatch.getHomeScore()) {
+					bank = bank + betAmount * soccerMatch.getOdds2();
+					//					System.out.println(" Win, new Bank " + bank);
+				} else {
+					//					System.out.println(" Loss new Bank " + bank);
+				}
+			}
+
+		}
+
+		System.out.println("season " + season + " ended with " + bank);
+		System.out.println("Match count " + matches.size() + " leagueId " + leagueId + " countryId " + countryId + " bet on " + betOnGameCount + "(" + betOnGameCount / (float)totalMatchCount + ")");
+	}
+
+	public void calcBestResults( int sportId, Integer countryId, Integer leagueId) {
+		final float startingBank = 1000f;
+		float bank = startingBank;
+		final float betLevel = 1 / 100f;
+
+		int bestBetMargin = 1;
+		int bestLookBack = 1;
+		float bestBankResult = 1000f;
+
+		final ArrayList<SoccerMatch> matches = GuiMysql.getInstance().getMatches(sportId, countryId, leagueId, LocalDate.now().atStartOfDay().format(DateTimeFormatter.ISO_DATE), "ASC");
+
+		final LocalDateTime currentDate = matches.get(0).getGameDate();
+		LocalDate localDate = currentDate.toLocalDate();
+		float betAmount = bank * betLevel;
+
+		for (int lookBack = 1; lookBack < 25; lookBack++) {
+			for (int betMargin = 1; betMargin < 35; betMargin++) {
+				int betOnGameCount = 0;
+				int wins = 0;
+				final float betMarginDecimal = 1 + (betMargin / (float)100);
+				bank = startingBank;
+				for (final SoccerMatch soccerMatch : matches) {
+					if (soccerMatch.getHomeScore() < 0 || soccerMatch.getAwayScore() < 0) {
+						continue;
+					}
+
+					final TeamResults homeTeamResults = GuiMysql.getInstance().getTeamResults(soccerMatch.getHomeTeam().getTeamId(), lookBack, true);
+					final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResults(soccerMatch.getAwayTeam().getTeamId(), lookBack, false);
+
+					final float homeWinPercent = (homeTeamResults.getWins() + awayTeamResults.getLosses()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
+					final float drawPercent = (homeTeamResults.getDraws() + awayTeamResults.getDraws()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
+					final float awayWinPercent = (homeTeamResults.getLosses() + awayTeamResults.getWins()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
+
+					final float homeOdds = 100 / homeWinPercent;
+					final float drawOdds = 100 / drawPercent;
+					final float awayOdds = 100 / awayWinPercent;
+
+					if (localDate.isBefore(soccerMatch.getGameDate().toLocalDate())) {
+						betAmount = bank * betLevel;
+						localDate = soccerMatch.getGameDate().toLocalDate();
+					}
+					if (homeOdds * betMarginDecimal <= soccerMatch.getOdds1()) {
+						betOnGameCount++;
+						bank = bank - betAmount;
+						if (soccerMatch.getHomeScore() > soccerMatch.getAwayScore()) {
+							wins++;
+							bank = bank + betAmount * soccerMatch.getOdds1();
+						}
+					}
+					if (awayOdds * betMarginDecimal <= soccerMatch.getOdds2()) {
+						betOnGameCount++;
+						bank = bank - betAmount;
+						if (soccerMatch.getAwayScore() > soccerMatch.getHomeScore()) {
+							wins++;
+							bank = bank + betAmount * soccerMatch.getOdds2();
+						}
+					}
+				}
+
+				if (bestBankResult < bank) {
+					System.out.println("New best bank " + bank + " with lookback " + lookBack + " and betMargin " + betMargin +
+							" Bet on " + betOnGameCount + " of " + matches.size() + "(" + betOnGameCount / (float)matches.size() + ") wins " + wins + "(" + wins/Float.valueOf(betOnGameCount) + ")" +
+							" Win / game " + (bank - startingBank) / Float.valueOf(wins) + " kr");
+					bestBetMargin = betMargin;
+					bestLookBack = lookBack;
+					bestBankResult = bank;
+				} else {
+					System.out.println("NOT BEST bank " + bank + " with lookback " + lookBack + " and betMargin " + betMargin +
+							" Bet on " + betOnGameCount + " of " + matches.size() + "(" + betOnGameCount / (float)matches.size() + ") wins " + wins + "(" + wins/Float.valueOf(betOnGameCount) + ")" +
+							" Win / game " + (bank - startingBank) / Float.valueOf(wins) + " kr");
+				}
+			}
+		}
+	}
+
+}

+ 195 - 0
OddsJavaFx/src/tests/PrioCountriesAll.java

@@ -0,0 +1,195 @@
+package tests;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+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.Team;
+import objects.TeamResults;
+
+public class PrioCountriesAll {
+
+	Connection conn;
+	private ArrayList<League> prioLeagues;
+
+	public void runTest() {
+		float bank = 1000;
+		float betAmount = 1;
+		final float betLevel = 0.01f;
+
+		final ArrayList<SoccerMatch> matches = getMatches();
+
+		for (int i = 0; i < matches.size();) {
+
+			final SoccerMatch soccerMatch = matches.get(i);
+
+			final List<SoccerMatch> matchesThisDate = matches.stream()
+					.filter(p -> p.getGameDate().format(DateTimeFormatter.ISO_DATE)
+							.equals(soccerMatch.getGameDate().format(DateTimeFormatter.ISO_DATE)))
+					.collect(Collectors.toList());
+
+			final int matchesThisDateCount = matchesThisDate.size();
+			betAmount = bank * betLevel;
+			int gamesBettedOn = 0;
+			int winsThisDay = 0;
+			final float startBank = bank;
+			for (final SoccerMatch sm : matchesThisDate) {
+				final int leagueId = sm.getHomeTeam().getTeamLeagueId();
+				final League activeLeague = prioLeagues.stream().filter(p -> p.getLeagueId() == leagueId).findFirst().get();
+
+				final int betOnThisMatch = checkIfBet(sm, activeLeague);
+				if (betOnThisMatch > 0) {
+					gamesBettedOn++;
+					if (betOnThisMatch == 1) { // Spela på hemma lag
+						bank = bank - betAmount;
+						if (sm.getHomeScore() > sm.getAwayScore()) {
+							bank += betAmount * sm.getOdds1();
+							winsThisDay++;
+						}
+					} else if (betOnThisMatch == 2) { // Spela på borta lag
+						bank = bank - betAmount;
+
+						if (sm.getAwayScore() > sm.getHomeScore()) {
+							bank += betAmount * sm.getOdds2();
+							winsThisDay++;
+						}
+					} else if (betOnThisMatch == 3) { // Spela på bort och hemma
+						bank = bank - betAmount*2;
+						if (sm.getHomeScore() > sm.getAwayScore()) {
+							bank += betAmount * sm.getOdds1();
+							winsThisDay++;
+						}
+						if (sm.getAwayScore() > sm.getHomeScore()) {
+							bank += betAmount * sm.getOdds2();
+							winsThisDay++;
+						}
+					}
+				}
+			}
+
+			System.out.println(matchesThisDate.get(0).getGameDate() + " result " + (bank - startBank) + " current bank: " + bank +
+					" bet on " + gamesBettedOn + "/" + matchesThisDateCount + " wins " + winsThisDay);
+			i += matchesThisDate.size();
+
+		}
+	}
+
+	private int checkIfBet(SoccerMatch sm, League league) {
+		int returnValue = 0;
+		final float betMarginDecimal = 1 + (league.getBetMargin() / 100f);
+
+		final TeamResults homeTeamResults = GuiMysql.getInstance().getTeamResults(sm.getHomeTeam().getTeamId(), league.getLookback(), true);
+		final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResults(sm.getAwayTeam().getTeamId(), league.getLookback(), false);
+
+		final float homeWinPercent = (homeTeamResults.getWins() + awayTeamResults.getLosses()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
+		final float drawPercent = (homeTeamResults.getDraws() + awayTeamResults.getDraws()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
+		final float awayWinPercent = (homeTeamResults.getLosses() + awayTeamResults.getWins()) / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
+
+		final float homeOdds = 100 / homeWinPercent;
+		final float drawOdds = 100 / drawPercent;
+		final float awayOdds = 100 / awayWinPercent;
+
+		if (homeOdds * betMarginDecimal <= sm.getOdds1()) {
+			returnValue += 1;
+		}
+		if (awayOdds * betMarginDecimal <= sm.getOdds2()) {
+			returnValue += 2;
+		}
+
+		return returnValue;
+	}
+
+	private ArrayList<SoccerMatch> getMatches() {
+		int i = 0;
+		final ArrayList<SoccerMatch> matches = Lists.newArrayList();
+
+		prioLeagues = getPrioLeagues();
+
+		final ArrayList<String> leagueIds = Lists.newArrayList();
+		prioLeagues.forEach(p -> leagueIds.add(String.valueOf(p.getLeagueId())));
+
+		final String sql = "SELECT res.*, " +
+				"hTeam.name as homeTeamName, aTeam.name as awayTeamName " +
+				"FROM SoccerResults as res " +
+				"Join Team as hTeam ON res.homeTeam = hTeam.id " +
+				"Join Team as aTeam ON res.awayTeam = aTeam.id " +
+				"WHERE " +
+				"res.leagueId IN (" +
+				String.join(",", leagueIds) + ") " +
+				"ORDER BY gameDate ASC";
+
+		try {
+			final PreparedStatement stmt = conn.prepareStatement(sql);
+
+			final ResultSet rs = stmt.executeQuery();
+			while (rs.next()) {
+				i++;
+				final SoccerMatch sm = new SoccerMatch();
+				final Team homeTeam = new Team();
+				final Team awayTeam = new Team();
+
+				homeTeam.setTeamId(rs.getInt("homeTeam"));
+				awayTeam.setTeamId(rs.getInt("awayTeam"));
+				homeTeam.setTeamName(rs.getString("homeTeamName"));
+				awayTeam.setTeamName(rs.getString("awayTeamName"));
+				homeTeam.setTeamLeagueId(rs.getInt("leagueId"));
+				awayTeam.setTeamLeagueId(rs.getInt("leagueId"));
+				homeTeam.setCountryId(rs.getInt("countryId"));
+				awayTeam.setCountryId(rs.getInt("countryId"));
+
+				sm.setAwayScore(rs.getInt("awayScore"));
+				sm.setHomeScore(rs.getInt("homeScore"));
+				sm.setHomeTeam(homeTeam);
+				sm.setAwayTeam(awayTeam);
+				sm.setMatchId(rs.getInt("id"));
+				sm.setOdds1(rs.getFloat("odds1"));
+				sm.setOddsX(rs.getFloat("oddsX"));
+				sm.setOdds2(rs.getFloat("odds2"));
+				sm.setGameDate(LocalDateTime.parse(rs.getString("gameDate")));
+				sm.setSeason(rs.getString("season"));
+
+				matches.add(sm);
+			}
+		} catch (final SQLException e) {
+			e.printStackTrace();
+		}
+
+		return matches;
+	}
+
+	private ArrayList<League> getPrioLeagues() {
+		final String sql = "SELECT * FROM League WHERE prio = 1";
+		final ArrayList<League> result = Lists.newArrayList();
+		try {
+			final PreparedStatement stat = getConnection().prepareStatement(sql);
+			final ResultSet rs = stat.executeQuery();
+
+			while (rs.next()) {
+				result.add(new League(rs.getInt("id"), rs.getString("name"), rs.getInt("lookback"), rs.getInt("betMargin")));
+			}
+		} catch (final SQLException e) {
+			e.printStackTrace();
+		}
+
+		return result;
+	}
+
+	private Connection getConnection() {
+		if (conn == null) {
+			conn = GuiMysql.getInstance().getDbConnection();
+		}
+
+		return conn;
+	}
+}

+ 3 - 0
OddsJavaFx/src/web/front/index.php

@@ -0,0 +1,3 @@
+<?php
+
+echo "<H1>TEST</H1>";