Jelajahi Sumber

BetAnalysis with covered bets

Axel Nordh 3 tahun lalu
induk
melakukan
b7d9cf128d
35 mengubah file dengan 8288 tambahan dan 4024 penghapusan
  1. 19 3
      Odds/.classpath
  2. 567 0
      Odds/.settings/org.eclipse.jdt.core.prefs
  3. 31 25
      Odds/pom.xml
  4. 339 303
      Odds/src/mysql/Mysql.java
  5. 328 319
      Odds/src/parser/OddsPortal.java
  6. 17 1
      OddsJavaFx/.classpath
  7. 559 0
      OddsJavaFx/.settings/org.eclipse.jdt.core.prefs
  8. 37 22
      OddsJavaFx/pom.xml
  9. 1 1
      OddsJavaFx/src/application/Main.java
  10. 492 0
      OddsJavaFx/src/controllers/AnalysisTestController.java
  11. 1 1
      OddsJavaFx/src/controllers/MainController.java
  12. 431 338
      OddsJavaFx/src/controllers/MatchTabController.java
  13. 672 551
      OddsJavaFx/src/controllers/PastResultsController.java
  14. 361 248
      OddsJavaFx/src/controllers/TestsController.java
  15. 1170 965
      OddsJavaFx/src/data/GuiMysql.java
  16. 170 96
      OddsJavaFx/src/data/TestDatabase.java
  17. 81 0
      OddsJavaFx/src/fxml/AnalysisTesting.fxml
  18. 13 33
      OddsJavaFx/src/fxml/MatchTabBuilder.fxml
  19. 5 0
      OddsJavaFx/src/fxml/OddsFxBuilder.fxml
  20. 1 0
      OddsJavaFx/src/fxml/PastResults.fxml
  21. 25 28
      OddsJavaFx/src/fxml/Testing.fxml
  22. 136 112
      OddsJavaFx/src/objects/League.java
  23. 77 59
      OddsJavaFx/src/objects/OverUnder.java
  24. 350 122
      OddsJavaFx/src/objects/SoccerMatch.java
  25. 331 0
      OddsJavaFx/src/objects/SoccerMatchAnalysis.java
  26. 70 0
      OddsJavaFx/src/objects/bets/AsianHandicap.java
  27. 185 0
      OddsJavaFx/src/objects/bets/Bet.java
  28. 203 0
      OddsJavaFx/src/tests/AnalysisBettTester.java
  29. 188 0
      OddsJavaFx/src/tests/BetOnDifference.java
  30. 218 0
      OddsJavaFx/src/tests/FibonacciDrawTest.java
  31. 210 199
      OddsJavaFx/src/tests/HomeDrawAwayTest.java
  32. 0 51
      OddsJavaFx/src/tests/LeagueTablePositionTest.java
  33. 149 139
      OddsJavaFx/src/tests/PrioCountriesAll.java
  34. 343 0
      OddsJavaFx/src/tests/RelevanceTest.java
  35. 508 408
      OddsJavaFx/src/tests/TestClass.java

+ 19 - 3
Odds/.classpath

@@ -1,19 +1,35 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="src" output="target/classes" path="src">
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-18">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" path="target/generated-sources/annotations">
 		<attributes>
 			<attribute name="optional" value="true"/>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="ignore_optional_problems" value="true"/>
+			<attribute name="m2e-apt" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+	<classpathentry kind="src" output="target/classes" path="src">
 		<attributes>
+			<attribute name="optional" value="true"/>
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-18">
+	<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
 		<attributes>
+			<attribute name="optional" value="true"/>
 			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="ignore_optional_problems" value="true"/>
+			<attribute name="m2e-apt" value="true"/>
 		</attributes>
 	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>

+ 567 - 0
Odds/.settings/org.eclipse.jdt.core.prefs

@@ -1,9 +1,576 @@
 eclipse.preferences.version=1
+enableParallelJavaIndexSearch=true
+org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=
+org.eclipse.jdt.core.circularClasspath=warning
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.camelCaseMatch=enabled
+org.eclipse.jdt.core.codeComplete.deprecationCheck=disabled
+org.eclipse.jdt.core.codeComplete.discouragedReferenceCheck=disabled
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.forbiddenReferenceCheck=enabled
+org.eclipse.jdt.core.codeComplete.forceImplicitQualification=disabled
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.subwordMatch=disabled
+org.eclipse.jdt.core.codeComplete.suggestStaticImports=enabled
+org.eclipse.jdt.core.codeComplete.visibilityCheck=enabled
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=javax.annotation.Nonnull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=javax.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.lambda.genericSignature=do not generate
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.shareCommonFinallyBlocks=disabled
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=18
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
 org.eclipse.jdt.core.compiler.compliance=18
+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.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.emulateJavacBug8031744=enabled
+org.eclipse.jdt.core.compiler.generateClassFiles=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deadCodeInTrivialIfStatement=disabled
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
 org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
 org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.tasks=warning
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.uninternedIdentityComparison=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeArgumentsForMethodInvocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
 org.eclipse.jdt.core.compiler.processAnnotations=disabled
 org.eclipse.jdt.core.compiler.release=disabled
 org.eclipse.jdt.core.compiler.source=18
+org.eclipse.jdt.core.compiler.storeAnnotations=disabled
+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,NORMAL
+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX
+org.eclipse.jdt.core.computeJavaBuildOrder=ignore
+org.eclipse.jdt.core.encoding=utf8
+org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
+org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
+org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line=true
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false
+org.eclipse.jdt.core.formatter.align_with_spaces=false
+org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assertion_message=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon=16
+org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_module_statements=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_record_components=16
+org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0
+org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow=20
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0
+org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0
+org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=true
+org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
+org.eclipse.jdt.core.formatter.comment.indent_tag_description=false
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=do not insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=false
+org.eclipse.jdt.core.formatter.join_wrapped_lines=false
+org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.text_block_indentation=0
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false
+org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true
+org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator=false
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
+org.eclipse.jdt.core.timeoutForParameterNameFromAttachedJavadoc=50

+ 31 - 25
Odds/pom.xml

@@ -35,33 +35,39 @@
 -->
     </plugins>
   </build>
-
+<repositories>
+  <repository>
+    <id>nordhs-repo</id>
+    <name>Nords Repo</name>
+    <url>http://nordh.xyz:9099/repository/nordhs-repo/</url>
+  </repository>
+</repositories>
   <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.64.0</version>
-	</dependency>
-	<dependency>
-	   <groupId>com.github.jbytecode</groupId>
-	   <artifactId>RCaller</artifactId>
-	   <version>3.0</version>
-	</dependency>
-  <dependency>
-      <groupId>mysql</groupId>
-      <artifactId>mysql-connector-java</artifactId>
-      <version>8.0.30</version>
-  </dependency>
-  <dependency>
-      <groupId>org.springframework.boot</groupId>
-      <artifactId>spring-boot-maven-plugin</artifactId>
-      <version>2.7.1</version>
-  </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.64.0</version>
+    </dependency>
+    <dependency>
+      <groupId>com.github.jbytecode</groupId>
+      <artifactId>RCaller</artifactId>
+      <version>3.0</version>
+    </dependency>
+    <dependency>
+        <groupId>mysql</groupId>
+        <artifactId>mysql-connector-java</artifactId>
+        <version>8.0.30</version>
+    </dependency>
+    <dependency>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+        <version>2.7.1</version>
+    </dependency>
 
   </dependencies>
 </project>

+ 339 - 303
Odds/src/mysql/Mysql.java

@@ -6,321 +6,357 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 
 import org.eclipse.jetty.util.log.Log;
 
+import com.google.common.base.Strings;
+
 import object.CurrentParsing;
 import object.ResultDTO;
 
 public class Mysql {
 
-	private static final Mysql instance = new Mysql();
-
-	private static final String USERNAME = "OddsNy";
-	private static final String PASSWORD = "Odds1_Ny_Password";
-	private static final String DATABASE = "new_odds";
-	private static final String URL = "jdbc:mysql://nordh.xyz:3306/";
-	private static final String TIMEZONE_FIX = "?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";
-
-	private Connection conn;
-
-	protected Mysql() {
-		getConnection();
-	}
-
-	public static Mysql getInstance() {
-		return instance;
-	}
-
-	protected Connection getConnection() {
-		if (conn == null) {
-			try {
-				conn = DriverManager.getConnection(URL + DATABASE + TIMEZONE_FIX, USERNAME, PASSWORD);
-			} catch (final SQLException e) {
-				throw new RuntimeException(e.getMessage(), e);
-			}
-		}
-		return conn;
-	}
-
-	public CurrentParsing getCurrentParsing() {
-		final CurrentParsing returnValue = new CurrentParsing();
-		final String sql = "SELECT * FROM parsing";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			final ResultSet rs = stat.executeQuery();
-			while (rs.next()) {
-				returnValue.setDone(rs.getBoolean("done"));
-				returnValue.setCurrentYear(rs.getInt("year"));
-				returnValue.setCurrentDate(rs.getDate("gameDate"));
-				returnValue.setLeague(rs.getString("league"));
-				returnValue.setPage(rs.getInt("page"));
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-		return returnValue;
-	}
-
-	public int addLeague(String leagueName, String country, String sport) throws SQLException {
-		leagueName = leagueName.trim();
-		leagueName = leagueName.replace(" ", "-");
-		leagueName = leagueName.replace("\\.", "");
-		final int sportId = addSport(sport);
-		final int countryId = addCountry(country);
-		final String sql = "INSERT INTO League (name, sportId, countryId) VALUES (?, ?, ?) " + "ON DUPLICATE KEY UPDATE name = ?";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, leagueName);
-			stat.setInt(2, sportId);
-			stat.setInt(3, countryId);
-			stat.setString(4, leagueName);
-
-			stat.executeUpdate();
-		}
-		return getId("League", leagueName, countryId, -1);
-	}
-
-	public int addCountry(String name) throws SQLException {
-		name = name.replace(" ", "-");
-		name = name.replace("\\.", "");
-		final String sql = "INSERT INTO Country (name) VALUES (?) ON DUPLICATE KEY UPDATE name = ?";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, name);
-			stat.setString(2, name);
-			stat.executeUpdate();
-		}
-
-		return getId("Country", name, -1, -1);
-	}
-
-	public int addSport(String sport) throws SQLException {
-		sport = sport.replace(" ", "-");
-		sport = sport.replace("\\.", "");
-		final String sql = "INSERT INTO Sport (name) VALUES (?) ON DUPLICATE KEY UPDATE name = ?";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, sport);
-			stat.setString(2, sport);
-			stat.executeUpdate();
-		}
-		return getId("Sport", sport, -1, -1);
-	}
-
-	private int getId(String table, String name, int countryId, int leagueId) throws SQLException {
-		String sql = "SELECT id FROM " + table + " WHERE name = ?";
-		int id = -1;
-		if (countryId > -1) {
-			sql += " AND countryId = ?";
-		}
-		if (leagueId > -1) {
-			sql += " AND leagueId = ?";
-		}
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, name.trim());
-			if (countryId > -1 && leagueId > -1) {
-				stat.setInt(2, countryId);
-				stat.setInt(3, leagueId);
-			} else if (countryId > -1) {
-				stat.setInt(2, countryId);
-			} else if (leagueId > -1) {
-				stat.setInt(2, leagueId);
-			}
-			final ResultSet insertRs = stat.executeQuery();
-			if (insertRs.next()) {
-				id = insertRs.getInt("id");
-			}
-		}
-		return id;
-	}
-
-	public int getLeagueId(int sportId, int countryId, String leagueName) {
-		final String sql = "SELECT id FROM League WHERE name = ? AND countryId = ? AND sportId = ?";
-		int id = -1;
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, leagueName.trim());
-			stat.setInt(2, countryId);
-			stat.setInt(3, sportId);
-
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				id = rs.getInt("id");
-			}
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-		return id;
-	}
-
-	public int getSportId(String sportName) {
-		final String sql = "SELECT id from Sport WHERE name = ?";
-		int id = 0;
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, sportName.trim());
-
-			final ResultSet rs = stat.executeQuery();
-			while (rs.next()) {
-				id = rs.getInt("id");
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-		return id;
-	}
-
-	public int getCountryId(String country) throws SQLException {
-		final String sql = "SELECT id from Country WHERE name = ?";
-		int id = -1;
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, country.trim());
-
-			final ResultSet rs = stat.executeQuery();
-			while (rs.next()) {
-				id = rs.getInt("id");
-			}
-		}
-		return id;
-	}
-
-	public void addResult(ResultDTO result) throws SQLException {
+    private static final Mysql instance = new Mysql();
+
+    private static final String USERNAME = "OddsNy";
+    private static final String PASSWORD = "Odds1_Ny_Password";
+    private static final String DATABASE = "new_odds";
+    private static final String URL = "jdbc:mysql://nordh.xyz:3306/";
+    private static final String TIMEZONE_FIX = "?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";
+
+    private Connection conn;
+
+    protected Mysql() {
+        getConnection();
+    }
+
+    public static Mysql getInstance() {
+        return instance;
+    }
+
+    protected Connection getConnection() {
+        if (conn == null) {
+            try {
+                conn = DriverManager.getConnection(URL + DATABASE + TIMEZONE_FIX, USERNAME, PASSWORD);
+            } catch (final SQLException e) {
+                throw new RuntimeException(e.getMessage(), e);
+            }
+        }
+        return conn;
+    }
+
+    public CurrentParsing getCurrentParsing() {
+        final CurrentParsing returnValue = new CurrentParsing();
+        final String sql = "SELECT * FROM parsing";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            final ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                returnValue.setDone(rs.getBoolean("done"));
+                returnValue.setCurrentYear(rs.getInt("year"));
+                returnValue.setCurrentDate(rs.getDate("gameDate"));
+                returnValue.setLeague(rs.getString("league"));
+                returnValue.setPage(rs.getInt("page"));
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+        return returnValue;
+    }
+
+    public int addLeague(String leagueName, String country, String sport) throws SQLException {
+        leagueName = leagueName.trim();
+        leagueName = leagueName.replace(" ", "-");
+        leagueName = leagueName.replace("\\.", "");
+        final int sportId = addSport(sport);
+        final int countryId = addCountry(country);
+        final String sql = "INSERT INTO League (name, sportId, countryId) VALUES (?, ?, ?) "
+                + "ON DUPLICATE KEY UPDATE name = ?";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, leagueName);
+            stat.setInt(2, sportId);
+            stat.setInt(3, countryId);
+            stat.setString(4, leagueName);
+
+            stat.executeUpdate();
+        }
+        return getId("League", leagueName, countryId, -1);
+    }
+
+    public int addCountry(String name) throws SQLException {
+        name = name.replace(" ", "-");
+        name = name.replace("\\.", "");
+        final String sql = "INSERT INTO Country (name) VALUES (?) ON DUPLICATE KEY UPDATE name = ?";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, name);
+            stat.setString(2, name);
+            stat.executeUpdate();
+        }
+
+        return getId("Country", name, -1, -1);
+    }
+
+    public int addSport(String sport) throws SQLException {
+        sport = sport.replace(" ", "-");
+        sport = sport.replace("\\.", "");
+        final String sql = "INSERT INTO Sport (name) VALUES (?) ON DUPLICATE KEY UPDATE name = ?";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, sport);
+            stat.setString(2, sport);
+            stat.executeUpdate();
+        }
+        return getId("Sport", sport, -1, -1);
+    }
+
+    private int getId(String table, String name, int countryId, int leagueId) throws SQLException {
+        String sql = "SELECT id FROM " + table + " WHERE name = ?";
+        int id = -1;
+        if (countryId > -1) {
+            sql += " AND countryId = ?";
+        }
+        if (leagueId > -1) {
+            sql += " AND leagueId = ?";
+        }
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, name.trim());
+            if (countryId > -1 && leagueId > -1) {
+                stat.setInt(2, countryId);
+                stat.setInt(3, leagueId);
+            } else if (countryId > -1) {
+                stat.setInt(2, countryId);
+            } else if (leagueId > -1) {
+                stat.setInt(2, leagueId);
+            }
+            final ResultSet insertRs = stat.executeQuery();
+            if (insertRs.next()) {
+                id = insertRs.getInt("id");
+            }
+        }
+        return id;
+    }
+
+    public int getLeagueId(int sportId, int countryId, String leagueName) {
+        final String sql = "SELECT id FROM League WHERE name = ? AND countryId = ? AND sportId = ?";
+        int id = -1;
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, leagueName.trim());
+            stat.setInt(2, countryId);
+            stat.setInt(3, sportId);
+
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                id = rs.getInt("id");
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return id;
+    }
+
+    public int getSportId(String sportName) {
+        final String sql = "SELECT id from Sport WHERE name = ?";
+        int id = 0;
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, sportName.trim());
+
+            final ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                id = rs.getInt("id");
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+        return id;
+    }
+
+    public int getCountryId(String country) throws SQLException {
+        final String sql = "SELECT id from Country WHERE name = ?";
+        int id = -1;
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, country.trim());
+
+            final ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                id = rs.getInt("id");
+            }
+        }
+        return id;
+    }
+
+    public void addResult(ResultDTO result) throws SQLException {
 //		String tableName, LocalDateTime gameDate, String homeTeam, String awayTeam, int homeScore,
 //			int awayScore, boolean overtime, float odds1, float oddsX, float odds2, int countryId, String season,
 //			int leagueId, int sportId) throws SQLException {
 
-		final int homeTeamId = getOrInsertTeam(result.getHomeTeam(), result.getCountryId(), result.getLeagueId(), result.getSportId());
-		final int awayTeamId = getOrInsertTeam(result.getAwayTeam(), result.getCountryId(), result.getLeagueId(), result.getSportId());
-
-		final String selectSql = "SELECT id FROM SoccerResults WHERE homeTeamId = ? AND awayTeamId = ? AND DATE(gameDate) = DATE(?)";
-		final ResultSet rs;
-		int gameId = -1;
-		final String date = result.getGameDate().format(DateTimeFormatter.ISO_DATE);
-		try (PreparedStatement stat = conn.prepareStatement(selectSql)) {
-			stat.setInt(1, homeTeamId);
-			stat.setInt(2, awayTeamId);
-			stat.setString(3, date);
-
-			rs = stat.executeQuery();
-			while (rs.next()) {
-				gameId = rs.getInt("id");
-			}
-		}
-
-		if (gameId != -1) {
-			final String sql = "UPDATE " + result.getTableName() + " SET homeScore = ?, awayScore = ?, overtime = ?, odds1 = ?, oddsX = ?, odds2 = ? "
-					+ "WHERE homeTeamId = ? AND awayTeamId = ? AND DATE(gameDate) = ?";
-
-			try (PreparedStatement stat = conn.prepareStatement(sql)) {
-				stat.setInt(1, result.getHomeScore());
-				stat.setInt(2, result.getAwayScore());
-				stat.setBoolean(3, result.isOvertime());
-				stat.setFloat(4, result.getOdds1());
-				stat.setFloat(5, result.getOddsX());
-				stat.setFloat(6, result.getOdds2());
-				stat.setInt(7, homeTeamId);
-				stat.setInt(8, awayTeamId);
-				stat.setString(9, date);
-
-				stat.executeUpdate();
-			}
-
-		} else {
-			final String sql = "INSERT INTO " + result.getTableName()
-					+ " (homeTeamId, awayTeamId, homeScore, awayScore, overtime, odds1, oddsX, odds2, countryId, gameDate, season, leagueId) "
-					+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE homeScore = ?, awayScore = ?, odds1 = ?, oddsX = ?, odds2 = ?";
-			try (PreparedStatement stat = conn.prepareStatement(sql)) {
-				stat.setInt(1, homeTeamId);
-				stat.setInt(2, awayTeamId);
-				stat.setInt(3, result.getHomeScore());
-				stat.setInt(4, result.getAwayScore());
-				stat.setBoolean(5, result.isOvertime());
-				stat.setFloat(6, result.getOdds1());
-				stat.setFloat(7, result.getOddsX());
-				stat.setFloat(8, result.getOdds2());
-				stat.setInt(9, result.getCountryId());
-				stat.setString(10, result.getGameDate().toString());
-				stat.setString(11, result.getSeason());
-				stat.setInt(12, result.getLeagueId());
-				stat.setInt(13, result.getHomeScore());
-				stat.setInt(14, result.getAwayScore());
-				stat.setFloat(15, result.getOdds1());
-				stat.setFloat(16, result.getOddsX());
-				stat.setFloat(17, result.getOdds2());
-
-				stat.execute();
-			}
-		}
-	}
-
-	private int getOrInsertTeam(String teamName, int countryId, int leagueId, int sportId) throws SQLException {
-		teamName = teamName.replace('\u00A0', ' ').trim();
-		int teamId;
-		if (leagueId > 0) {
-
-			teamId = getId("Team", teamName, countryId, leagueId);
-			if (teamId <= 0) {
-				final String insertSql = "INSERT INTO Team (name, sportId, countryId, leagueId) VALUES (? ,? ,? ,?)";
-				try (PreparedStatement stat = conn.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS)) {
-					stat.setString(1, teamName.trim());
-					stat.setInt(2, sportId);
-					stat.setInt(3, countryId);
-					stat.setInt(4, leagueId);
-
-					stat.executeUpdate();
-					final ResultSet generatedKeys = stat.getGeneratedKeys();
-					generatedKeys.next();
-					teamId = generatedKeys.getInt(1);
-				}
-			}
-		} else {
-			Log.getLog().info("No league Specified for " + teamName + " with countryId " + countryId);
-			teamId = -1;
-		}
-
-		return teamId;
-	}
-
-	public void setParsingForLeague(int leagueId, int sportId, int countryId, LocalDateTime gameDate, int currentParsePage, String parsedYear) {
-		final String sql = "UPDATE League SET parsedYear = ?, parsedPage = ?, lastParsedGameDate = ? WHERE sportId = ? AND countryId = ? AND id = ?";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, parsedYear);
-			stat.setInt(2, currentParsePage);
-			stat.setString(3, gameDate.toString());
-			stat.setInt(4, sportId);
-			stat.setInt(5, countryId);
-			stat.setInt(6, leagueId);
-
-			stat.executeUpdate();
-		} catch (final SQLException e) {
-			Log.getLog().info("Failing sql: %s, %s, %s, %s, %s, %s, %s", sql, parsedYear, currentParsePage, gameDate.toString(), sportId, countryId,
-					leagueId);
-			e.printStackTrace();
-		}
-	}
-
-	public String getLastParsedYear(String leagueName, int countryId) {
-		String returnValue = "";
-
-		final String sql = "SELECT parsedYear FROM League WHERE name = ? AND countryId = ?";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, leagueName);
-			stat.setInt(2, countryId);
-
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				returnValue = rs.getString("parsedYear");
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return returnValue;
-	}
-
-	public Connection getDbConnection() {
-		if (conn == null) {
-			conn = getConnection();
-		}
-		return conn;
-	}
+        if (result.getCountryId() < 0 || result.getLeagueId() < 0) {
+            System.out.println(String.format("Must supply countryId %s and leagueId %s", result.getCountryId(),
+                    result.getLeagueId()));
+            return;
+        }
+        final int homeTeamId = getOrInsertTeam(result.getHomeTeam(), result.getCountryId(), result.getLeagueId(),
+                result.getSportId());
+        final int awayTeamId = getOrInsertTeam(result.getAwayTeam(), result.getCountryId(), result.getLeagueId(),
+                result.getSportId());
+
+        final String selectSql = "SELECT id FROM SoccerResults WHERE homeTeamId = ? AND awayTeamId = ? AND DATE(gameDate) = DATE(?)";
+        final ResultSet rs;
+        int gameId = -1;
+        final String date = result.getGameDate().format(DateTimeFormatter.ISO_DATE);
+        try (PreparedStatement stat = conn.prepareStatement(selectSql)) {
+            stat.setInt(1, homeTeamId);
+            stat.setInt(2, awayTeamId);
+            stat.setString(3, date);
+
+            rs = stat.executeQuery();
+            while (rs.next()) {
+                gameId = rs.getInt("id");
+            }
+        }
+
+        if (gameId != -1) {
+            final String sql = "UPDATE " + result.getTableName()
+                    + " SET homeScore = ?, awayScore = ?, overtime = ?, odds1 = ?, oddsX = ?, odds2 = ? "
+                    + "WHERE homeTeamId = ? AND awayTeamId = ? AND DATE(gameDate) = ?";
+
+            try (PreparedStatement stat = conn.prepareStatement(sql)) {
+                stat.setInt(1, result.getHomeScore());
+                stat.setInt(2, result.getAwayScore());
+                stat.setBoolean(3, result.isOvertime());
+                stat.setFloat(4, result.getOdds1());
+                stat.setFloat(5, result.getOddsX());
+                stat.setFloat(6, result.getOdds2());
+                stat.setInt(7, homeTeamId);
+                stat.setInt(8, awayTeamId);
+                stat.setString(9, date);
+
+                stat.executeUpdate();
+            }
+
+        } else {
+            final String sql = "INSERT INTO " + result.getTableName()
+                    + " (homeTeamId, awayTeamId, homeScore, awayScore, overtime, odds1, oddsX, odds2, countryId, gameDate, season, leagueId) "
+                    + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE homeScore = ?, awayScore = ?, odds1 = ?, oddsX = ?, odds2 = ?";
+            try (PreparedStatement stat = conn.prepareStatement(sql)) {
+                stat.setInt(1, homeTeamId);
+                stat.setInt(2, awayTeamId);
+                stat.setInt(3, result.getHomeScore());
+                stat.setInt(4, result.getAwayScore());
+                stat.setBoolean(5, result.isOvertime());
+                stat.setFloat(6, result.getOdds1());
+                stat.setFloat(7, result.getOddsX());
+                stat.setFloat(8, result.getOdds2());
+                stat.setInt(9, result.getCountryId());
+                stat.setString(10, result.getGameDate().toString());
+                stat.setString(11, result.getSeason());
+                stat.setInt(12, result.getLeagueId());
+                stat.setInt(13, result.getHomeScore());
+                stat.setInt(14, result.getAwayScore());
+                stat.setFloat(15, result.getOdds1());
+                stat.setFloat(16, result.getOddsX());
+                stat.setFloat(17, result.getOdds2());
+
+                stat.execute();
+            }
+        }
+    }
+
+    private int getOrInsertTeam(String teamName, int countryId, int leagueId, int sportId) throws SQLException {
+        teamName = teamName.replace('\u00A0', ' ').trim();
+        int teamId;
+        if (leagueId > 0) {
+
+            teamId = getId("Team", teamName, countryId, leagueId);
+            if (teamId <= 0) {
+                final String insertSql = "INSERT INTO Team (name, sportId, countryId, leagueId) VALUES (? ,? ,? ,?)";
+                try (PreparedStatement stat = conn.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS)) {
+                    stat.setString(1, teamName.trim());
+                    stat.setInt(2, sportId);
+                    stat.setInt(3, countryId);
+                    stat.setInt(4, leagueId);
+
+                    stat.executeUpdate();
+                    final ResultSet generatedKeys = stat.getGeneratedKeys();
+                    generatedKeys.next();
+                    teamId = generatedKeys.getInt(1);
+                }
+            }
+        } else {
+            Log.getLog().info("No league Specified for " + teamName + " with countryId " + countryId);
+            teamId = -1;
+        }
+
+        return teamId;
+    }
+
+    public void setParsingForLeague(int leagueId, int sportId, int countryId, LocalDateTime gameDate,
+            int currentParsePage, String parsedYear) {
+        final String sql = "UPDATE League SET parsedYear = ?, parsedPage = ?, lastParsedGameDate = ? WHERE sportId = ? AND countryId = ? AND id = ?";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, parsedYear);
+            stat.setInt(2, currentParsePage);
+            stat.setString(3, gameDate.toString());
+            stat.setInt(4, sportId);
+            stat.setInt(5, countryId);
+            stat.setInt(6, leagueId);
+
+            stat.executeUpdate();
+        } catch (final SQLException e) {
+            Log.getLog().info("Failing sql: %s, %s, %s, %s, %s, %s, %s", sql, parsedYear, currentParsePage,
+                    gameDate.toString(), sportId, countryId,
+                    leagueId);
+            e.printStackTrace();
+        }
+    }
+
+    public String getLastParsedYear(String leagueName, int countryId) {
+        String returnValue = "";
+
+        final String sql = "SELECT parsedYear FROM League WHERE name = ? AND countryId = ?";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, leagueName);
+            stat.setInt(2, countryId);
+
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                returnValue = rs.getString("parsedYear");
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return returnValue;
+    }
+
+    public Connection getDbConnection() {
+        if (conn == null) {
+            conn = getConnection();
+        }
+        return conn;
+    }
+
+    public String getLastSeason(String leagueName, int countryId) {
+        String sql = "SELECT season FROM SoccerResults WHERE leagueId = (SELECT id FROM League WHERE name = ? AND countryId = ?) ORDER BY gameDate DESC limit 1";
+        String result = null;
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, leagueName);
+            stat.setInt(2, countryId);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result = rs.getString("season");
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        if (Strings.isNullOrEmpty(result)) {
+            result = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy"));
+        }
+        return result;
+    }
 }

+ 328 - 319
Odds/src/parser/OddsPortal.java

@@ -29,323 +29,332 @@ import object.ResultDTO;
 
 public class OddsPortal implements ParserJoinedFunctions {
 
-	private static final String CLASS = "class";
-	private static final String DATE_PATTERN = "yyyyMMdd";
-	private LocalDateTime baseDate;
-	private int sportId;
-	private int countryId;
-	private int leagueId;
-	private LocalDateTime gameDate;
-
-	public void getYesterdaysMatches() {
-		baseDate = LocalDateTime.now().plusDays(-1);
-		final String date = LocalDate.now().plusDays(-1).format(DateTimeFormatter.ofPattern(DATE_PATTERN));
-		getMatchesByDate(date);
-	}
-
-	public void getTodaysMatches() {
-		baseDate = LocalDateTime.now();
-		final String date = LocalDate.now().format(DateTimeFormatter.ofPattern(DATE_PATTERN));
-		getMatchesByDate(date);
-	}
-
-	public void getTomorrowsMatches() {
-		baseDate = LocalDateTime.now().plusDays(1);
-		final String dateTomorrow = LocalDate.now().plusDays(1).format(DateTimeFormatter.ofPattern(DATE_PATTERN));
-		getMatchesByDate(dateTomorrow);
-	}
-
-	public void getNextDaysMatches() {
-		baseDate = LocalDateTime.now().plusDays(2);
-		final String dateTomorrow = LocalDate.now().plusDays(2).format(DateTimeFormatter.ofPattern(DATE_PATTERN));
-		getMatchesByDate(dateTomorrow);
-	}
-
-	// https://stackoverflow.com/questions/14439991/skip-particular-javascript-execution-in-html-unit
-	// Skip url
-	private void getMatchesByDate(String date) {
-		final String soccerUrl = "https://oddsportal.com/matches/soccer/" + date;
-		// final String hockeyUrl = "https://oddsportal.com/matches/hockey/" + date;
-
-		try (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, date);
-
-		} catch (Exception e) {
-			System.out.println("Webclient failed " + e.getMessage());
-			e.printStackTrace();
-		}
-	}
-
-	private void parseSoccerMatches(final String soccerUrl, final WebClient webClient, String date) {
-		try {
-			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;
-			for (final HtmlTableRow tr : rows) {
-				if (tr.getAttribute(CLASS).equals("dark center")) {
-					final List<HtmlAnchor> countryLeague = tr.getByXPath(".//a");
-					countryName = countryLeague.get(0).asNormalizedText().toLowerCase().trim();
-					leagueName = countryLeague.get(1).asNormalizedText().toLowerCase().trim();
-					leagueName = leagueName.replace(" ", "-");
-					leagueName = leagueName.replace("\\.", "");
-					countryName = countryName.replace(" ", "-");
-					countryName = countryName.replace("\\.", "");
-				} else {
-					final List<HtmlTableCell> cells = tr.getCells();
-					final String[] time = cells.get(0).asNormalizedText().split(":");
-					final String[] teams = cells.get(1).asNormalizedText().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.asNormalizedText().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.asNormalizedText().matches("[+-][0-9][0-9][0-9]")) {
-									if (odds1 == 0F) {
-										odds1 = convertAmericanOddsToDecimal(Integer.valueOf(tc.asNormalizedText()));
-									} else if (oddsX == 0F) {
-										oddsX = convertAmericanOddsToDecimal(Integer.valueOf(tc.asNormalizedText()));
-									} else if (odds2 == 0F) {
-										odds2 = convertAmericanOddsToDecimal(Integer.valueOf(tc.asNormalizedText()));
-									}
-								} else if (tc.asNormalizedText().matches("[0-9].[0-9]+")) {
-									if (odds1 == 0F) {
-										odds1 = Float.valueOf(tc.asNormalizedText());
-									} else if (oddsX == 0F) {
-										oddsX = Float.valueOf(tc.asNormalizedText());
-									} else if (odds2 == 0F) {
-										odds2 = Float.valueOf(tc.asNormalizedText());
-									}
-								}
-							}
-
-						}
-					} catch (final NumberFormatException e) {
-						Log.getLog().info(String.format(
-								"Failed to get the match between %s and %s at %s odds1 %s oddsX %s odds2 %s homeScore %s awayScore %s overtime %s",
-								teams[0].trim(), teams[1].trim(), baseDate.withHour(Integer.valueOf(time[0])).withMinute(Integer.valueOf(time[1])),
-								odds1, oddsX, odds2, homeScore, awayScore, (overtime ? "true" : "false")));
-						continue;
-					}
-
-					if (abandon) {
-						continue;
-					}
-					final Mysql mysql = Mysql.getInstance();
-					final int leaguesId = mysql.addLeague(leagueName, countryName, "soccer");
-					final int countrysId = mysql.getCountryId(countryName);
-					final int sportsId = mysql.getSportId("soccer");
-
-					// String season = mysql.getLastParsedYear(leagueName, countryId); // TODO This
-					// don't work
-					String season = String.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern(DATE_PATTERN)).getYear());
-					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);
-					if (teams.length != 2) {
-						System.out.println("Something wrong with teams " + Arrays.toString(teams));
-					} else {
-						mysql.addResult(new ResultDTO("SoccerResults", dt, teams[0].trim(), teams[1].trim(), homeScore, awayScore, overtime, odds1,
-								oddsX, odds2, countrysId, season, leaguesId, sportsId));
-					}
-				}
-			}
-		} catch (FailingHttpStatusCodeException | IOException | 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.replace(" ", "-");
-		league = league.replace("\\.", "");
-		country = country.replace(" ", "-");
-		league = league.replace("\\.", "");
-		final Mysql mysql = Mysql.getInstance();
-
-		int 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) {
-				final String active = ((HtmlSpan) a.getParentNode().getParentNode()).getAttribute(CLASS);
-				if (active.contains("active") && !active.contains("inactive")) {
-					season = a.asNormalizedText();
-					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) {
-				// When done with start page click pagiantion
-				final int parsePage = Integer.parseInt(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 | SQLException e) {
-			e.printStackTrace();
-		} catch (final ClassCastException cce) {
-			Log.getLog().info("Class cast exception message: " + cce.getMessage() + " \ncause: " + cce.getCause());
-		} finally {
-			Mysql.getInstance().setParsingForLeague(leagueId, sportId, countryId, gameDate, currentParsePage, year);
-		}
-		webClient.close();
-		Log.getLog().info("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.asNormalizedText().split(":");
-				if (gameDate != null) {
-					gameDate = gameDate.withHour(Integer.valueOf(timeValue[0]));
-					gameDate = gameDate.withMinute(Integer.valueOf(timeValue[1]));
-				}
-
-				// Teams
-				final String[] participantsValue = participantsCell.asNormalizedText().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.asNormalizedText().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.asNormalizedText().matches("[+-][0-9][0-9][0-9]")) {
-							if (odds1 == 0F) {
-								odds1 = convertAmericanOddsToDecimal(Integer.valueOf(tc.asNormalizedText()));
-							} else if (oddsX == 0F) {
-								oddsX = convertAmericanOddsToDecimal(Integer.valueOf(tc.asNormalizedText()));
-							} else if (odds2 == 0F) {
-								odds2 = convertAmericanOddsToDecimal(Integer.valueOf(tc.asNormalizedText()));
-							}
-						} else if (tc.asNormalizedText().matches("[0-9]+.[0-9]+")) {
-							if (odds1 == 0F) {
-								odds1 = Float.valueOf(tc.asNormalizedText());
-							} else if (oddsX == 0F) {
-								oddsX = Float.valueOf(tc.asNormalizedText());
-							} else if (odds2 == 0F) {
-								odds2 = Float.valueOf(tc.asNormalizedText());
-							}
-						}
-					}
-				}
-
-				if (gameDate != null && homeTeam != null && awayTeam != null && odds1 != 0 && oddsX != 0 && odds2 != 0
-						&& !Strings.isNullOrEmpty(season)) { // All set.. update sql result table
-					Mysql.getInstance().addResult(new ResultDTO("SoccerResults", gameDate, homeTeam, awayTeam, homeScore, awayScore, overtime, odds1,
-							oddsX, odds2, countryId, season, leagueId, sportId));
-				} else {
-					Log.getLog().info(String.format("Failed to insert result %s %s %s odds %s %s %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).asNormalizedText();
-				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();
-				}
-			}
-		}
-	}
+    private static final String CLASS = "class";
+    private static final String DATE_PATTERN = "yyyyMMdd";
+    private LocalDateTime baseDate;
+    private int sportId;
+    private int countryId;
+    private int leagueId;
+    private LocalDateTime gameDate;
+
+    public void getYesterdaysMatches() {
+        baseDate = LocalDateTime.now().plusDays(-1);
+        final String date = LocalDate.now().plusDays(-1).format(DateTimeFormatter.ofPattern(DATE_PATTERN));
+        getMatchesByDate(date);
+    }
+
+    public void getTodaysMatches() {
+        baseDate = LocalDateTime.now();
+        final String date = LocalDate.now().format(DateTimeFormatter.ofPattern(DATE_PATTERN));
+        getMatchesByDate(date);
+    }
+
+    public void getTomorrowsMatches() {
+        baseDate = LocalDateTime.now().plusDays(1);
+        final String dateTomorrow = LocalDate.now().plusDays(1).format(DateTimeFormatter.ofPattern(DATE_PATTERN));
+        getMatchesByDate(dateTomorrow);
+    }
+
+    public void getNextDaysMatches() {
+        baseDate = LocalDateTime.now().plusDays(2);
+        final String dateTomorrow = LocalDate.now().plusDays(2).format(DateTimeFormatter.ofPattern(DATE_PATTERN));
+        getMatchesByDate(dateTomorrow);
+    }
+
+    // https://stackoverflow.com/questions/14439991/skip-particular-javascript-execution-in-html-unit
+    // Skip url
+    private void getMatchesByDate(String date) {
+        final String soccerUrl = "https://oddsportal.com/matches/soccer/" + date;
+        // final String hockeyUrl = "https://oddsportal.com/matches/hockey/" + date;
+
+        try (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, date);
+
+        } catch (Exception e) {
+            System.out.println("Webclient failed " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    private void parseSoccerMatches(final String soccerUrl, final WebClient webClient, String date) {
+        try {
+            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;
+            for (final HtmlTableRow tr : rows) {
+                if (tr.getAttribute(CLASS).equals("dark center")) {
+                    final List<HtmlAnchor> countryLeague = tr.getByXPath(".//a");
+                    countryName = countryLeague.get(0).asNormalizedText().toLowerCase().trim();
+                    leagueName = countryLeague.get(1).asNormalizedText().toLowerCase().trim();
+                    leagueName = leagueName.replace(" ", "-");
+                    leagueName = leagueName.replace("\\.", "");
+                    countryName = countryName.replace(" ", "-");
+                    countryName = countryName.replace("\\.", "");
+                } else {
+                    final List<HtmlTableCell> cells = tr.getCells();
+                    final String[] time = cells.get(0).asNormalizedText().split(":");
+                    final String[] teams = cells.get(1).asNormalizedText().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.asNormalizedText().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.asNormalizedText().matches("[+-][0-9][0-9][0-9]")) {
+                                    if (odds1 == 0F) {
+                                        odds1 = convertAmericanOddsToDecimal(Integer.valueOf(tc.asNormalizedText()));
+                                    } else if (oddsX == 0F) {
+                                        oddsX = convertAmericanOddsToDecimal(Integer.valueOf(tc.asNormalizedText()));
+                                    } else if (odds2 == 0F) {
+                                        odds2 = convertAmericanOddsToDecimal(Integer.valueOf(tc.asNormalizedText()));
+                                    }
+                                } else if (tc.asNormalizedText().matches("[0-9].[0-9]+")) {
+                                    if (odds1 == 0F) {
+                                        odds1 = Float.valueOf(tc.asNormalizedText());
+                                    } else if (oddsX == 0F) {
+                                        oddsX = Float.valueOf(tc.asNormalizedText());
+                                    } else if (odds2 == 0F) {
+                                        odds2 = Float.valueOf(tc.asNormalizedText());
+                                    }
+                                }
+                            }
+
+                        }
+                    } catch (final NumberFormatException e) {
+                        Log.getLog().info(String.format(
+                                "Failed to get the match between %s and %s at %s odds1 %s oddsX %s odds2 %s homeScore %s awayScore %s overtime %s",
+                                teams[0].trim(), teams[1].trim(),
+                                baseDate.withHour(Integer.valueOf(time[0])).withMinute(Integer.valueOf(time[1])),
+                                odds1, oddsX, odds2, homeScore, awayScore, (overtime ? "true" : "false")));
+                        continue;
+                    }
+
+                    if (abandon) {
+                        continue;
+                    }
+                    final Mysql mysql = Mysql.getInstance();
+                    final int leaguesId = mysql.addLeague(leagueName, countryName, "soccer");
+                    final int countrysId = mysql.getCountryId(countryName);
+                    final int sportsId = mysql.getSportId("soccer");
+
+                    String season = mysql.getLastSeason(leagueName, countryId); // TODO This don't work
+//					String season = String.valueOf(LocalDate.parse(date, DateTimeFormatter.ofPattern(DATE_PATTERN)).getYear());
+                    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);
+                    if (teams.length != 2) {
+                        System.out.println("Something wrong with teams " + Arrays.toString(teams));
+                    } else {
+                        mysql.addResult(new ResultDTO("SoccerResults", dt, teams[0].trim(), teams[1].trim(), homeScore,
+                                awayScore, overtime, odds1,
+                                oddsX, odds2, countrysId, season, leaguesId, sportsId));
+                    }
+                }
+            }
+        } catch (FailingHttpStatusCodeException | IOException | 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.replace(" ", "-");
+        league = league.replace("\\.", "");
+        country = country.replace(" ", "-");
+        league = league.replace("\\.", "");
+        final Mysql mysql = Mysql.getInstance();
+
+        int 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) {
+                final String active = ((HtmlSpan) a.getParentNode().getParentNode()).getAttribute(CLASS);
+                if (active.contains("active") && !active.contains("inactive")) {
+                    season = a.asNormalizedText();
+                    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) {
+                // When done with start page click pagiantion
+                final int parsePage = Integer.parseInt(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 | SQLException e) {
+            e.printStackTrace();
+        } catch (final ClassCastException cce) {
+            Log.getLog().info("Class cast exception message: " + cce.getMessage() + " \ncause: " + cce.getCause());
+        } finally {
+            Mysql.getInstance().setParsingForLeague(leagueId, sportId, countryId, gameDate, currentParsePage, year);
+        }
+        webClient.close();
+        Log.getLog().info("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.asNormalizedText().split(":");
+                if (gameDate != null) {
+                    gameDate = gameDate.withHour(Integer.valueOf(timeValue[0]));
+                    gameDate = gameDate.withMinute(Integer.valueOf(timeValue[1]));
+                }
+
+                // Teams
+                final String[] participantsValue = participantsCell.asNormalizedText().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.asNormalizedText().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.asNormalizedText().matches("[+-][0-9][0-9][0-9]")) {
+                            if (odds1 == 0F) {
+                                odds1 = convertAmericanOddsToDecimal(Integer.valueOf(tc.asNormalizedText()));
+                            } else if (oddsX == 0F) {
+                                oddsX = convertAmericanOddsToDecimal(Integer.valueOf(tc.asNormalizedText()));
+                            } else if (odds2 == 0F) {
+                                odds2 = convertAmericanOddsToDecimal(Integer.valueOf(tc.asNormalizedText()));
+                            }
+                        } else if (tc.asNormalizedText().matches("[0-9]+.[0-9]+")) {
+                            if (odds1 == 0F) {
+                                odds1 = Float.valueOf(tc.asNormalizedText());
+                            } else if (oddsX == 0F) {
+                                oddsX = Float.valueOf(tc.asNormalizedText());
+                            } else if (odds2 == 0F) {
+                                odds2 = Float.valueOf(tc.asNormalizedText());
+                            }
+                        }
+                    }
+                }
+
+                if (gameDate != null && homeTeam != null && awayTeam != null && odds1 != 0 && oddsX != 0 && odds2 != 0
+                        && !Strings.isNullOrEmpty(season)) { // All set.. update sql result table
+                    Mysql.getInstance()
+                            .addResult(new ResultDTO("SoccerResults", gameDate, homeTeam, awayTeam, homeScore,
+                                    awayScore, overtime, odds1,
+                                    oddsX, odds2, countryId, season, leagueId, sportId));
+                } else {
+                    Log.getLog()
+                            .info(String.format("Failed to insert result %s %s %s odds %s %s %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).asNormalizedText();
+                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();
+                }
+            }
+        }
+    }
 }

+ 17 - 1
OddsJavaFx/.classpath

@@ -13,11 +13,27 @@
 	</classpathentry>
 	<classpathentry kind="con" path="org.eclipse.fx.ide.jdt.core.JAVAFX_CONTAINER"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/JavaFx"/>
-	<classpathentry kind="src" output="target/classes" path="src">
+	<classpathentry including="**/*.java" kind="src" output="target/classes" path="src">
 		<attributes>
 			<attribute name="optional" value="true"/>
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
+	<classpathentry kind="src" path="target/generated-sources/annotations">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="ignore_optional_problems" value="true"/>
+			<attribute name="m2e-apt" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="ignore_optional_problems" value="true"/>
+			<attribute name="m2e-apt" value="true"/>
+		</attributes>
+	</classpathentry>
 	<classpathentry kind="output" path="target/classes"/>
 </classpath>

+ 559 - 0
OddsJavaFx/.settings/org.eclipse.jdt.core.prefs

@@ -1,17 +1,576 @@
 eclipse.preferences.version=1
+enableParallelJavaIndexSearch=true
+org.eclipse.jdt.core.builder.annotationPath.allLocations=disabled
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=
+org.eclipse.jdt.core.circularClasspath=warning
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.camelCaseMatch=enabled
+org.eclipse.jdt.core.codeComplete.deprecationCheck=disabled
+org.eclipse.jdt.core.codeComplete.discouragedReferenceCheck=disabled
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.forbiddenReferenceCheck=enabled
+org.eclipse.jdt.core.codeComplete.forceImplicitQualification=disabled
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.subwordMatch=disabled
+org.eclipse.jdt.core.codeComplete.suggestStaticImports=enabled
+org.eclipse.jdt.core.codeComplete.visibilityCheck=enabled
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=javax.annotation.Nonnull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=javax.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.lambda.genericSignature=do not generate
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.shareCommonFinallyBlocks=disabled
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=18
 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
 org.eclipse.jdt.core.compiler.compliance=18
 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.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.emulateJavacBug8031744=enabled
+org.eclipse.jdt.core.compiler.generateClassFiles=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deadCodeInTrivialIfStatement=disabled
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
 org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=warning
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
 org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.tasks=warning
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.uninternedIdentityComparison=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeArgumentsForMethodInvocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
 org.eclipse.jdt.core.compiler.processAnnotations=disabled
 org.eclipse.jdt.core.compiler.release=disabled
 org.eclipse.jdt.core.compiler.source=18
+org.eclipse.jdt.core.compiler.storeAnnotations=disabled
+org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled
+org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,NORMAL
+org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX
+org.eclipse.jdt.core.computeJavaBuildOrder=ignore
+org.eclipse.jdt.core.encoding=utf8
+org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
+org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
+org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line=true
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false
+org.eclipse.jdt.core.formatter.align_with_spaces=false
+org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant=49
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=49
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable=49
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method=49
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package=49
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter=0
+org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type=49
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assertion_message=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon=16
+org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_module_statements=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_record_components=16
+org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0
+org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow=20
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_type_annotations=0
+org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0
+org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch=0
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_record_constructor=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_record_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=true
+org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
+org.eclipse.jdt.core.formatter.comment.indent_tag_description=false
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags=do not insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_not_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert
+org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=false
+org.eclipse.jdt.core.formatter.join_wrapped_lines=false
+org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block=0
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block=0
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block=0
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.text_block_indentation=0
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false
+org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true
+org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator=false
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
+org.eclipse.jdt.core.timeoutForParameterNameFromAttachedJavadoc=50

+ 37 - 22
OddsJavaFx/pom.xml

@@ -7,6 +7,13 @@
     <maven.compiler.source>18</maven.compiler.source>
     <maven.compiler.target>18</maven.compiler.target>
   </properties>
+  <repositories>
+    <repository>
+      <id>nordhs-repo</id>
+      <name>Nords Repo</name>
+      <url>http://nordh.xyz:9099/repository/nordhs-repo/</url>
+    </repository>
+  </repositories>
   <build>
     <sourceDirectory>src</sourceDirectory>
     <plugins>
@@ -30,34 +37,42 @@
           </executions>
         </plugin>
     </plugins>
+    <resources>
+      <resource>
+        <directory>src/fxml/</directory>
+        <includes>
+          <include>**/*.fxml</include>
+        </includes>
+      </resource>
+    </resources>
   </build>
-   <dependencies>
-   <dependency>
+  <dependencies>
+    <dependency>
       <groupId>Odds</groupId>
-	  <artifactId>Odds</artifactId>
-	  <version>0.0.1-SNAPSHOT</version>
-   </dependency>
-   <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>
+      <artifactId>Odds</artifactId>
+      <version>Odds-0.0.1-SNAPSHOT</version>
+    </dependency>
+    <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>
 		<dependency>
 	    <groupId>com.google.code.gson</groupId>
 	    <artifactId>gson</artifactId>
 	    <version>2.9.0</version>
-	</dependency>
-	<dependency>
+	  </dependency>
+  	<dependency>
 	    <groupId>org.openjfx</groupId>
 	    <artifactId>javafx-controls</artifactId>
 	    <version>19-ea+8</version>

+ 1 - 1
OddsJavaFx/src/application/Main.java

@@ -30,7 +30,7 @@ public class Main extends Application {
 		try {
 			// Load root layout from fxml file.
 			final FXMLLoader loader = new FXMLLoader();
-			loader.setLocation(Main.class.getResource("../fxml/OddsFxBuilder.fxml"));
+			loader.setLocation(getClass().getClassLoader().getResource("OddsFxBuilder.fxml"));
 			rootLayout = (StackPane) loader.load();
 
 			// Show the scene containing the root layout.

+ 492 - 0
OddsJavaFx/src/controllers/AnalysisTestController.java

@@ -0,0 +1,492 @@
+package controllers;
+
+import java.math.RoundingMode;
+import java.net.URL;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+import java.util.ResourceBundle;
+
+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.DatePicker;
+import javafx.scene.control.TableCell;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.TextField;
+import javafx.scene.control.cell.MapValueFactory;
+import javafx.scene.control.cell.PropertyValueFactory;
+import javafx.util.Callback;
+import objects.League;
+import objects.SoccerMatch;
+import objects.SoccerMatchAnalysis;
+import objects.bets.Bet;
+import objects.bets.Bet.Status;
+
+public class AnalysisTestController implements Initializable {
+
+    @FXML
+    TableView<SoccerMatch> gameViewTable;
+    TableColumn<SoccerMatch, String> homeTeamNameColumn = new TableColumn<>("Home Team");
+    TableColumn<SoccerMatch, String> awayTeamNameColumn = new TableColumn<>("Away Team");
+    TableColumn<SoccerMatch, Float> odds1Column = new TableColumn<>("1");
+    TableColumn<SoccerMatch, Float> oddsXColumn = new TableColumn<>("X");
+    TableColumn<SoccerMatch, Float> odds2Column = new TableColumn<>("2");
+    TableColumn<SoccerMatch, String> leagueNameColumn = new TableColumn<>("Country");
+    TableColumn<SoccerMatch, String> countryNameColumn = new TableColumn<>("League");
+    TableColumn<SoccerMatch, String> analyzeValueColumn = new TableColumn<>("Value");
+    TableColumn<SoccerMatch, Float> matchBetAmountColumn = new TableColumn<>("Bet Amount");
+
+    TableColumn<SoccerMatch, Void> addBetColumn = new TableColumn<>("Add Bet");
+
+    @FXML
+    TableView<Bet> activeBetsTable;
+    TableColumn<Bet, String> matchupColumn = new TableColumn<>("Matchup");
+    TableColumn<Bet, Float> oddsColumn = new TableColumn<>("Odds");
+    TableColumn<Bet, Float> betAmountColumn = new TableColumn<>("BetAmount");
+    TableColumn<Bet, Bet.Status> statusColumn = new TableColumn<>("Status");
+    TableColumn<Bet, Integer> homeScoreColumn = new TableColumn<>("Home Score");
+    TableColumn<Bet, Integer> awayScoreColumn = new TableColumn<>("Away Score");
+
+    @FXML
+    TableView<Map<String, Object>> LeagueBetStatsTable;
+    @FXML
+    TableColumn<Map, String> statsLeagueNameColumn = new TableColumn<>("League");
+    @FXML
+    TableColumn<Map, Integer> statsHomeWinColumn = new TableColumn<>("Home Win");
+    @FXML
+    TableColumn<Map, Integer> statsHomeLossColumn = new TableColumn<>("Home Loss");
+    @FXML
+    TableColumn<Map, Float> statsHomePercentColumn = new TableColumn<>("Home Percent");
+    @FXML
+    TableColumn<Map, Integer> statsAwayWinColumn = new TableColumn<>("Away Win");
+    @FXML
+    TableColumn<Map, Integer> statsAwayLossColumn = new TableColumn<>("Away Loss");
+    @FXML
+    TableColumn<Map, Float> statsAwayPercentColumn = new TableColumn<>("Away Percent");
+    @FXML
+    TableColumn<Map, Float> statsTotalPercentColumn = new TableColumn<>("Total Percent");
+
+    @FXML
+    Button checkBetsButton;
+    @FXML
+    Button getMatchesButton;
+    @FXML
+    DatePicker date;
+    @FXML
+    TextField bankTextField;
+    @FXML
+    TextField bettingPercentTextField;
+    private float currentBetAmount = 10f;
+
+    private static final float MIN_COVER_ODDS = 1.25f;
+    private static final float MAX_COVER_ODDS = 2.25f;
+
+    private static final DecimalFormat FLOAT_FORMATTER = new DecimalFormat("0.00");
+
+    @Override
+    public void initialize(URL location, ResourceBundle resources) {
+        FLOAT_FORMATTER.setRoundingMode(RoundingMode.UP);
+        DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.ENGLISH);
+        dfs.setDecimalSeparator('.');
+        dfs.setGroupingSeparator(',');
+        FLOAT_FORMATTER.setDecimalFormatSymbols(dfs);
+
+        bettingPercentTextField.textProperty().addListener((observable, oldValue, newValue) -> {
+            if (newValue.length() > 0) {
+                checkValidBetAmount();
+            }
+        });
+
+        date.valueProperty().addListener((observable, oldValue, newValue) -> {
+            if (oldValue != newValue) {
+                gameViewTable.getItems().clear();
+            }
+        });
+
+        gameViewTable.getSelectionModel().selectedItemProperty().addListener((obj, oldValue, newValue) -> {
+            if (oldValue != null) {
+                oldValue.setBetAmount(currentBetAmount);
+                Bet previousBet = oldValue.getPreviousBet();
+//                if (previousBet != null && previousBet.getStatus() != Status.COVERED) {
+//                    oldValue.setPreviousBet(null);
+//                }
+            }
+
+            if (newValue != null) {
+                newValue.setBetAmount(getNewBetValue(newValue));
+            }
+
+            gameViewTable.refresh();
+            activeBetsTable.refresh();
+        });
+
+        homeTeamNameColumn.setCellValueFactory(new PropertyValueFactory<>("homeTeamName"));
+        awayTeamNameColumn.setCellValueFactory(new PropertyValueFactory<>("awayTeamName"));
+        odds1Column.setCellValueFactory(new PropertyValueFactory<>("odds1"));
+        oddsXColumn.setCellValueFactory(new PropertyValueFactory<>("oddsX"));
+        odds2Column.setCellValueFactory(new PropertyValueFactory<>("odds2"));
+        leagueNameColumn.setCellValueFactory(new PropertyValueFactory<>("leagueName"));
+        countryNameColumn.setCellValueFactory(new PropertyValueFactory<>("countryName"));
+        analyzeValueColumn.setCellValueFactory(new PropertyValueFactory<>("analysisValue"));
+
+        matchBetAmountColumn.setCellValueFactory(new PropertyValueFactory<>("betAmount"));
+
+        Callback<TableColumn<SoccerMatch, Void>, TableCell<SoccerMatch, Void>> cellFactory = new Callback<TableColumn<SoccerMatch, Void>, TableCell<SoccerMatch, Void>>() {
+            @Override
+            public TableCell<SoccerMatch, Void> call(final TableColumn<SoccerMatch, Void> param) {
+                return new TableCell<SoccerMatch, Void>() {
+
+                    private final Button btn = new Button("Submit");
+                    {
+                        btn.setOnAction((ActionEvent event) -> {
+                            SoccerMatch data = getTableView().getItems().get(getIndex());
+
+                            addToBets(data);
+
+//                            btn.setDisable(true);
+                        });
+                    }
+
+                    @Override
+                    public void updateItem(Void item, boolean empty) {
+                        super.updateItem(item, empty);
+                        if (empty) {
+                            setGraphic(null);
+                        } else {
+                            setGraphic(btn);
+                        }
+                    }
+
+                };
+            }
+        };
+
+        addBetColumn.setCellFactory(cellFactory);
+
+        gameViewTable.getColumns().addAll(homeTeamNameColumn, awayTeamNameColumn, odds1Column, oddsXColumn, odds2Column,
+                countryNameColumn, leagueNameColumn, analyzeValueColumn, matchBetAmountColumn, addBetColumn);
+        gameViewTable.setEditable(false);
+
+        matchupColumn.setCellValueFactory(new PropertyValueFactory<>("matchup"));
+        matchupColumn.setMinWidth(100d);
+
+        oddsColumn.setCellValueFactory(new PropertyValueFactory<>("betOdds"));
+        betAmountColumn.setCellValueFactory(new PropertyValueFactory<>("betAmount"));
+        homeScoreColumn.setCellValueFactory(new PropertyValueFactory<>("homeScore"));
+        awayScoreColumn.setCellValueFactory(new PropertyValueFactory<>("awayScore"));
+
+        statusColumn.setCellValueFactory(new PropertyValueFactory<>("status"));
+
+        activeBetsTable.getColumns().addAll(matchupColumn, oddsColumn, betAmountColumn, statusColumn, homeScoreColumn,
+                awayScoreColumn);
+
+        statsLeagueNameColumn.setCellValueFactory(new MapValueFactory<>("statsLeagueName"));
+        statsHomeWinColumn.setCellValueFactory(new MapValueFactory<>("statsHomeWin"));
+        statsHomeLossColumn.setCellValueFactory(new MapValueFactory<>("statsHomeLoss"));
+        statsAwayWinColumn.setCellValueFactory(new MapValueFactory<>("statsAwayWin"));
+        statsAwayLossColumn.setCellValueFactory(new MapValueFactory<>("statsAwayLoss"));
+
+        statsHomePercentColumn.setCellValueFactory(new MapValueFactory<>("statsHomePercent"));
+        statsAwayPercentColumn.setCellValueFactory(new MapValueFactory<>("statsAwayPercent"));
+        statsTotalPercentColumn.setCellValueFactory(new MapValueFactory<>("statsTotalPercent"));
+
+    }
+
+    private Float getNewBetValue(SoccerMatch newValue) {
+        float odds = 0f;
+        float currentDebt = 0f;
+        float result = currentBetAmount;
+        if (((newValue.getAnalysisValueInt() > 0 && newValue.getOdds1() > MIN_COVER_ODDS
+                && newValue.getOdds1() < MAX_COVER_ODDS) ||
+                (newValue.getAnalysisValueInt() < 0 && newValue.getOdds2() > MIN_COVER_ODDS
+                        && newValue.getOdds2() < MAX_COVER_ODDS))
+                &&
+                activeBetsTable.getItems().stream().filter(p -> p.getStatus() == Bet.Status.LOST).count() > 0) {
+            Bet bet = activeBetsTable.getItems().stream().filter(p -> p.getStatus() == Bet.Status.LOST).findFirst()
+                    .get();
+
+            Bet tempBet = bet;
+            while (tempBet.getMatch().getPreviousBet() != null) {
+                currentDebt += tempBet.getMatch().getPreviousBet().getBetAmount();
+                tempBet = tempBet.getMatch().getPreviousBet();
+            }
+            currentDebt += bet.getBetAmount();
+            newValue.setPreviousBet(bet);
+            if (newValue.getAnalysisValueInt() > 0f) {
+                odds = newValue.getOdds1();
+            } else if (newValue.getAnalysisValueInt() < 0f) {
+                odds = newValue.getOdds2();
+            }
+
+            if (currentDebt > 0f && odds > 0f) {
+                result = currentDebt / (odds - 1f); // + currentBetAmount;
+            } else if (newValue.getBetAmount() != null) {
+                result = newValue.getBetAmount();
+            }
+        }
+
+        return Float.parseFloat(FLOAT_FORMATTER.format(result));
+    }
+
+    private void checkValidBetAmount() {
+        try {
+            float bankValue = Float.parseFloat(bankTextField.getText());
+            float betPercent = Float.parseFloat(bettingPercentTextField.getText());
+
+            final float betAmount = Float.parseFloat(FLOAT_FORMATTER.format(bankValue * (betPercent / 100f)));
+            currentBetAmount = betAmount;
+            gameViewTable.getItems().forEach(i -> {
+                i.setBetAmount(betAmount);
+            });
+            gameViewTable.refresh();
+
+        } catch (NumberFormatException e) {
+// Ignore
+        }
+    }
+
+    private void addToBets(SoccerMatch data) {
+        if (data.getAnalysisValueInt() > 0) {
+            setNewBet(data, true);
+        } else if (data.getAnalysisValueInt() < 0f) {
+            setNewBet(data, false);
+        } else {
+            System.out.println("Can't add bets with analysts value " + data.getAnalysisValueInt());
+        }
+    }
+
+    private void setNewBet(SoccerMatch data, boolean isHomeBet) {
+        Bet bet = new Bet(-1, data, data.getBetAmount(), isHomeBet ? data.getOdds1() : data.getOdds2());
+        bet.setBetOnAwayTeam(!isHomeBet);
+        bet.setBetOnHomeTeam(isHomeBet);
+        if (data.getPreviousBet() != null) {
+            data.getPreviousBet().setStatus(Status.COVERED);
+            try {
+                activeBetsTable.getItems().set(activeBetsTable.getItems().indexOf(data.getPreviousBet()),
+                        data.getPreviousBet());
+            } catch (IndexOutOfBoundsException e) {
+                data.setPreviousBet(null); // TODO, ingen bra lösning kanske.. Men enkel att göra :)
+            } finally {
+                GuiMysql.getInstance().updateBetStatus(data.getPreviousBet().getId(), Status.COVERED);
+            }
+
+        }
+        activeBetsTable.getItems().add(bet);
+        updateBank(-bet.getBetAmount());
+
+        GuiMysql.getInstance().addAnalysisBet(bet);
+    }
+
+    @FXML
+    private void GetMatchesAction() {
+        List<SoccerMatch> matches = GuiMysql.getInstance().getMatches(1, date.getValue().toString(), "ASC", true);
+
+        addMatchesToTable(matches);
+    }
+
+    private void addMatchesToTable(List<SoccerMatch> matches) {
+        ObservableList<SoccerMatch> currentMatches = FXCollections.<SoccerMatch>observableArrayList();
+
+        for (SoccerMatch soccerMatch : matches) {
+
+            int analyzeValue = getAnalyzeValue(soccerMatch);
+            soccerMatch.setAnalysisValue(analyzeValue);
+            if (currentBetAmount > 0) {
+                soccerMatch.setBetAmount(currentBetAmount);
+            }
+
+            currentMatches.add(soccerMatch);
+        }
+
+        gameViewTable.getItems().addAll(currentMatches);
+    }
+
+    private Integer getAnalyzeValue(SoccerMatch soccerMatch) {
+        int result = 0;
+
+        SoccerMatchAnalysis analysis = new SoccerMatchAnalysis(soccerMatch);
+        League leagueInfo = GuiMysql.getInstance().getLeagueInfo(soccerMatch.getHomeTeam().getTeamLeagueId());
+        if (leagueInfo != null) {
+            int homeWinsCount = analysis.winLossRatio(leagueInfo.getWinLossRatio(), true);
+            int awayWindCount = analysis.winLossRatio(leagueInfo.getWinLossRatio(), false);
+
+            int homeWinLossRatioCount = analysis.winLossRationHomeAndAway(true,
+                    leagueInfo.getWinLossRatioHomeAndAway());
+            int awayWinLossRatioCount = analysis.winLossRationHomeAndAway(false,
+                    leagueInfo.getWinLossRatioHomeAndAway());
+
+            int homeScoringTotal = analysis.scoringTotal(leagueInfo.getScoringTotal(), true);
+            int awayScoringTotal = analysis.scoringTotal(leagueInfo.getScoringTotal(), false);
+
+            int scoringDiffLastGames = analysis.getScoringDiffLastGames(leagueInfo.getScoringDiffLastGame());
+            int winsCountDiff = homeWinsCount - awayWindCount;
+            int winLossRatioDiff = homeWinLossRatioCount - awayWinLossRatioCount;
+            int scoringTotalDiff = homeScoringTotal - awayScoringTotal;
+
+            if (scoringDiffLastGames < 0 && winsCountDiff < 0 && winLossRatioDiff < 0 && scoringTotalDiff < 0) {
+                result = (scoringDiffLastGames + winsCountDiff + winLossRatioDiff + scoringTotalDiff) / 4;
+            } else if (scoringDiffLastGames > 0 && winsCountDiff > 0 && winLossRatioDiff > 0
+                    && scoringTotalDiff > 0) {
+                result = (scoringDiffLastGames + winsCountDiff + winLossRatioDiff + scoringTotalDiff) / 4;
+            }
+        }
+        return result;
+    }
+
+    @FXML
+    private void CheckBetsAction() {
+
+        activeBetsTable.getItems().stream().filter(p -> p.getStatus() == Bet.Status.OPEN).forEach(this::checkBet);
+
+        activeBetsTable.refresh();
+
+        updateBetAmount();
+
+    }
+
+    private void updateBetAmount() {
+        try {
+            float betLevel = Float.parseFloat(bettingPercentTextField.getText());
+            currentBetAmount = Float.parseFloat(FLOAT_FORMATTER.format(getBank() * (betLevel / 100f)));
+
+        } catch (NumberFormatException e) {
+
+        }
+    }
+
+    private void checkBet(Bet b) {
+        if ((b.isBetOnHomeTeam() && b.getHomeScore() > b.getAwayScore())
+                || (b.isBetOnAwayTeam() && b.getHomeScore() < b.getAwayScore())) { // Win
+            b.setStatus(Bet.Status.DONE);
+            Float win = (b.getBetOdds() * b.getBetAmount());
+            updateBank(win);
+        } else { // Loss
+            b.setStatus(Bet.Status.LOST);
+        }
+
+        updateStatsPanel(b);
+    }
+
+    private void updateStatsPanel(Bet b) {
+        String leagueName = b.getMatch().getLeagueName();
+
+        Optional<Map<String, Object>> leagueStatsRow = LeagueBetStatsTable.getItems().stream()
+                .filter(p -> p.get("statsLeagueName").equals(leagueName)).findFirst();
+
+        if (leagueStatsRow.isEmpty()) {
+            Map<String, Object> newItem = new HashMap<>();
+            newItem.put("statsLeagueName", leagueName);
+            newItem.put("statsHomeWin", b.isBetOnHomeTeam() && b.getHomeScore() > b.getAwayScore() ? 1 : 0);
+            newItem.put("statsHomeLoss",
+                    b.isBetOnHomeTeam() && (b.getHomeScore() < b.getAwayScore() || b.getHomeScore() == b.getAwayScore())
+                            ? 1
+                            : 0);
+            int statsHomeWin = (int) newItem.get("statsHomeWin");
+            int statsHomeLoss = (int) newItem.get("statsHomeLoss");
+            if (statsHomeWin > 0 || statsHomeLoss > 0) {
+                newItem.put("statsHomePercent", (statsHomeWin / (float) (statsHomeWin + statsHomeLoss)) * 100);
+            }
+            newItem.put("statsAwayWin", b.isBetOnAwayTeam() && b.getHomeScore() < b.getAwayScore() ? 1 : 0);
+            newItem.put("statsAwayLoss",
+                    b.isBetOnAwayTeam() && (b.getHomeScore() > b.getAwayScore() || b.getHomeScore() == b.getAwayScore())
+                            ? 1
+                            : 0);
+
+            int statsAwayWin = (int) newItem.get("statsAwayWin");
+            int statsAwayLoss = (int) newItem.get("statsAwayLoss");
+            if (statsAwayWin > 0 || statsAwayLoss > 0) {
+                newItem.put("statsAwayPercent", (statsAwayWin / (float) (statsAwayWin + statsAwayLoss)) * 100);
+            }
+            if (statsHomeWin + statsHomeLoss + statsAwayWin + statsAwayLoss > 0) {
+                newItem.put("statsTotalPercent",
+                        ((statsHomeWin + statsAwayWin)
+                                / (float) (statsHomeWin + statsHomeLoss + statsAwayWin + statsAwayLoss)) * 100);
+            }
+            ObservableList<Map<String, Object>> items = LeagueBetStatsTable.getItems();
+
+            items.add(newItem);
+        } else {
+            Map<String, Object> map = leagueStatsRow.get();
+            if (b.isBetOnHomeTeam() && b.getHomeScore() > b.getAwayScore()) {
+                map.put("statsHomeWin", (int) map.get("statsHomeWin") + 1);
+            } else if (b.isBetOnHomeTeam()
+                    && (b.getHomeScore() < b.getAwayScore() || b.getHomeScore() == b.getAwayScore())) {
+                map.put("statsHomeLoss", (int) map.get("statsHomeLoss") + 1);
+            } else if (b.isBetOnAwayTeam() && b.getHomeScore() < b.getAwayScore()) {
+                map.put("statsAwayWin", (int) map.get("statsAwayWin") + 1);
+            } else if (b.isBetOnAwayTeam()
+                    && (b.getHomeScore() > b.getAwayScore() || b.getHomeScore() == b.getAwayScore())) {
+                map.put("statsAwayLoss", (int) map.get("statsAwayLoss") + 1);
+            }
+
+            int statsHomeWin = (int) map.get("statsHomeWin");
+            int statsHomeLoss = (int) map.get("statsHomeLoss");
+            if (statsHomeWin > 0 || statsHomeLoss > 0) {
+                map.put("statsHomePercent", (statsHomeWin / (float) (statsHomeWin + statsHomeLoss)) * 100);
+            }
+            int statsAwayWin = (int) map.get("statsAwayWin");
+            int statsAwayLoss = (int) map.get("statsAwayLoss");
+            if (statsAwayWin > 0 || statsAwayLoss > 0) {
+                map.put("statsAwayPercent", (statsAwayWin / (float) (statsAwayWin + statsAwayLoss)) * 100);
+            }
+            if (statsHomeWin + statsHomeLoss + statsAwayWin + statsAwayLoss > 0) {
+                map.put("statsTotalPercent",
+                        ((statsHomeWin + statsAwayWin)
+                                / (float) (statsHomeWin + statsHomeLoss + statsAwayWin + statsAwayLoss)) * 100);
+            }
+
+            LeagueBetStatsTable.getItems().set(LeagueBetStatsTable.getItems().indexOf(map), map);
+        }
+        LeagueBetStatsTable.refresh();
+    }
+
+    private void updateBank(float value) {
+        float bank;
+        try {
+            bank = Float.parseFloat(bankTextField.getText());
+            bank += value;
+
+            bankTextField.setText(String.valueOf(bank));
+        } catch (NumberFormatException e) {
+
+        }
+    }
+
+    private float getBank() {
+        float bank = 0;
+        try {
+            bank = Float.parseFloat(bankTextField.getText());
+        } catch (NumberFormatException e) {
+
+        }
+
+        return bank;
+    }
+
+    @FXML
+    private void RemoveDoneBetsAction() {
+        List<Bet> doneBets = activeBetsTable.getItems().stream()
+                .filter(p -> p.getStatus() == Status.DONE || p.getStatus() == Status.COVERED)
+                .toList();
+
+        for (Bet bet : doneBets) {
+            activeBetsTable.getItems().remove(bet);
+        }
+
+        activeBetsTable.getItems().sort((b1, b2) -> Float.compare(b2.getBetAmount(), b1.getBetAmount()));
+
+        activeBetsTable.refresh();
+
+    }
+
+}

+ 1 - 1
OddsJavaFx/src/controllers/MainController.java

@@ -127,7 +127,7 @@ public class MainController implements Initializable {
 
 				leaguesList = GuiMysql.getInstance().getLeagues(sportId, countryId);
 				final List<String> leaguesInTable = Lists.newArrayList();
-				matchTabController.getTableMatches().forEach(tr -> leaguesInTable.add((String) tr.get("league")));
+				matchTabController.getTableMatches().forEach(tr -> leaguesInTable.add(tr.getLeagueName()));
 				final HashSet<String> newHashSet = Sets.newHashSet(leaguesInTable);
 
 				leagues.clear();

+ 431 - 338
OddsJavaFx/src/controllers/MatchTabController.java

@@ -6,7 +6,6 @@ import java.net.URL;
 import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -21,6 +20,7 @@ import com.google.common.collect.Lists;
 import data.GuiMysql;
 import javafx.beans.binding.Bindings;
 import javafx.beans.property.StringProperty;
+import javafx.beans.value.ChangeListener;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 import javafx.event.ActionEvent;
@@ -34,348 +34,441 @@ import javafx.scene.control.TableColumn;
 import javafx.scene.control.TablePosition;
 import javafx.scene.control.TableView;
 import javafx.scene.control.TextField;
-import javafx.scene.control.cell.MapValueFactory;
 import javafx.scene.control.cell.PropertyValueFactory;
 import javafx.scene.control.cell.TextFieldTableCell;
 import javafx.util.Callback;
+import javafx.util.StringConverter;
 import javafx.util.converter.FloatStringConverter;
 import objects.BetDTO;
-import objects.Constants;
-import objects.League;
 import objects.SoccerMatch;
-import objects.TeamResults;
-
-@SuppressWarnings("rawtypes") public class MatchTabController implements Initializable {
-
-	@FXML private TableView<Map<String, Object>> matchTable;
-	@FXML TableColumn<Map, String> gameDateColumn = new TableColumn<>("Gamedate");
-	@FXML TableColumn<Map, String> homeTeamColumn = new TableColumn<>("Home Team");
-	@FXML TableColumn<Map, String> awayTeamColumn = new TableColumn<>("Away Team");
-	@FXML TableColumn<Map, Float> odds1Column = new TableColumn<>("odds 1");
-	@FXML TableColumn<Map, Float> oddsXColumn = new TableColumn<>("odds X");
-	@FXML TableColumn<Map, Float> odds2Column = new TableColumn<>("odds 2");
-	@FXML TableColumn<Map, Float> goalsHomeColumn = new TableColumn<>("Goals home");
-	@FXML TableColumn<Map, Float> goalsAwayColumn = new TableColumn<>("Goals away");
-	@FXML TableColumn<Map, Float> goalDiff = new TableColumn<>("Difference");
-	@FXML TableColumn<Map, Float> avgScoreHomeColumn = new TableColumn<>("Avg score home");
-	@FXML TableColumn<Map, Float> avgConcededHomeColumn = new TableColumn<>("Avg conceded home");
-	@FXML TableColumn<Map, Float> avgScoreAwayColumn = new TableColumn<>("Avg score away");
-	@FXML TableColumn<Map, Float> avgConcededAwayColumn = new TableColumn<>("Avg conceded away");
-	@FXML TableColumn<Map, String> countryColumn = new TableColumn<>("Country");
-	@FXML TableColumn<Map, String> leagueColumn = new TableColumn<>("League");
-
-	@FXML TableColumn<Map, String> homeWinColumn = new TableColumn<>(Constants.HOME_WIN);
-	@FXML TableColumn<Map, String> drawColumn = new TableColumn<>("draw");
-	@FXML TableColumn<Map, String> awayWinColumn = new TableColumn<>(Constants.AWAY_WIN);
-	@FXML TableColumn<Map, String> scoringScore = new TableColumn<>("scoringScore");
-
-	@FXML TableColumn<Map, TextField> ownOddsPerdiction = new TableColumn<>("ownOdds");
-	@FXML TableColumn<Map, TextField> givenOdds = new TableColumn<>("givenOdds");
-	@FXML TableColumn<Map, String> percentageToBet = new TableColumn<>("toBetPercent");
-
-	@FXML TableColumn<Map, Boolean> addToBetSlip = new TableColumn<>("addToBetslip");
-
-	@FXML private TableView<BetDTO> activeBettingTable;
-	private final ObservableList<BetDTO> betObservableList = FXCollections.observableArrayList();
-
-	@FXML TableColumn<BetDTO, StringProperty> betSeries = new TableColumn<>("Bet series");
-	@FXML TableColumn<BetDTO, String> gameDate = new TableColumn<>("Game date");
-	@FXML TableColumn<BetDTO, String> match = new TableColumn<>("Match");
-	@FXML TableColumn<BetDTO, String> betType = new TableColumn<>("Bet type");
-	@FXML TableColumn<BetDTO, Float> bet = new TableColumn<>("Bet amount");
-	@FXML TableColumn<BetDTO, Float> odds = new TableColumn<>("Odds");
-	@FXML TableColumn<BetDTO, String> result = new TableColumn<>("Result");
-	@FXML TableColumn<BetDTO, String> winAmount = new TableColumn<>("Win amount");
-	@FXML TableColumn<BetDTO, Void> submitButton = new TableColumn<>("Submit row");
-
-	private ObservableList<Map<String, Object>> coutryFilteredMatches;
-	private List<SoccerMatch> upcomingMatches;
-	private int countryId;
-	private static final String FLOAT_FORMAT = "%.02f";
-
-	private ObservableList<String> betSeriesOptions = FXCollections.observableArrayList();
-	private List<BetDTO> dbBetSeries;
-	private int lastBetSeries;
-
-	@Override public void initialize(URL arg0, ResourceBundle arg1) {
-		gameDateColumn.setCellValueFactory(new MapValueFactory<>("gameDate"));
-		homeTeamColumn.setCellValueFactory(new MapValueFactory<>("homeTeam"));
-		awayTeamColumn.setCellValueFactory(new MapValueFactory<>("awayTeam"));
-		odds1Column.setCellValueFactory(new MapValueFactory<>("odds1"));
-		oddsXColumn.setCellValueFactory(new MapValueFactory<>("oddsX"));
-		odds2Column.setCellValueFactory(new MapValueFactory<>("odds2"));
-		goalsHomeColumn.setCellValueFactory(new MapValueFactory<>("goalsHome"));
-		goalsAwayColumn.setCellValueFactory(new MapValueFactory<>("goalsAway"));
-		goalDiff.setCellValueFactory(new MapValueFactory<>("goalDiff"));
-		avgScoreHomeColumn.setCellValueFactory(new MapValueFactory<>("avgScoreHome"));
-		avgConcededHomeColumn.setCellValueFactory(new MapValueFactory<>("avgConcededHome"));
-		avgScoreAwayColumn.setCellValueFactory(new MapValueFactory<>("avgScoreAway"));
-		avgConcededAwayColumn.setCellValueFactory(new MapValueFactory<>("avgConcededAway"));
-		countryColumn.setCellValueFactory(new MapValueFactory<>("country"));
-		leagueColumn.setCellValueFactory(new MapValueFactory<>(Constants.LEAGUE));
-
-		homeWinColumn.setCellValueFactory(new MapValueFactory<>(Constants.HOME_WIN));
-		drawColumn.setCellValueFactory(new MapValueFactory<>("draw"));
-		awayWinColumn.setCellValueFactory(new MapValueFactory<>(Constants.AWAY_WIN));
-		scoringScore.setCellValueFactory(new MapValueFactory<>("scoringScore"));
-
-		betSeries.setCellValueFactory(i -> {
-			return Bindings.createObjectBinding(() -> i.getValue().optionProperty());
-		});
-
-		gameDate.setCellValueFactory(new PropertyValueFactory<>("gameDate"));
-		match.setCellValueFactory(new PropertyValueFactory<>("match"));
-		betType.setCellValueFactory(new PropertyValueFactory<>("betType"));
-		bet.setCellValueFactory(new PropertyValueFactory<>("bet"));
-		odds.setCellValueFactory(new PropertyValueFactory<>("odds"));
-		result.setCellValueFactory(new PropertyValueFactory<>("result"));
-		winAmount.setCellValueFactory(new PropertyValueFactory<>("winAmount"));
-
-		makeColumnsEditable();
-
-		activeBettingTable.getColumns().addAll(betSeries, gameDate, match, betType, bet, odds, result, winAmount);
-		activeBettingTable.setItems(betObservableList);
-
-		activeBettingTable.setEditable(true);
-
-		addSubmitButtonToTable();
-
-		addActiveBetsFromDatabase();
-
-	}
-
-	private void addActiveBetsFromDatabase() {
-		dbBetSeries = GuiMysql.getInstance().getBetSeries(false);
-
-		betSeriesOptions.addAll(dbBetSeries.stream().map(BetDTO::getBetSeries).sorted().map(String::valueOf).distinct()
-				.collect(Collectors.toCollection(LinkedList::new)));
-
-		lastBetSeries = GuiMysql.getInstance().getBetSeriesEndNumber();
-		betSeriesOptions.add(String.valueOf(lastBetSeries + 1));
-
-		betObservableList.addAll(dbBetSeries);
-	}
-
-	private void makeColumnsEditable() {
-
-		betSeries.setCellFactory(col -> {
-			TableCell<BetDTO, StringProperty> c = new TableCell<>();
-			final ComboBox<String> comboBox = new ComboBox<>(betSeriesOptions);
-			c.itemProperty().addListener((observable, oldValue, newValue) -> {
-				if (oldValue != null) {
-					comboBox.valueProperty().unbindBidirectional(oldValue);
-				}
-				if (newValue != null) {
-					comboBox.valueProperty().bindBidirectional(newValue);
-				}
-			});
-			c.graphicProperty().bind(Bindings.when(c.emptyProperty()).then((Node) null).otherwise(comboBox));
-			return c;
-		});
-
-		match.setCellFactory(TextFieldTableCell.forTableColumn());
-		match.setOnEditCommit(e -> e.getTableView().getItems().get(e.getTablePosition().getRow()).setMatch(e.getNewValue()));
-		betType.setCellFactory(TextFieldTableCell.forTableColumn());
-		betType.setOnEditCommit(e -> e.getTableView().getItems().get(e.getTablePosition().getRow()).setBetType(e.getNewValue()));
-		bet.setCellFactory(TextFieldTableCell.forTableColumn(new FloatStringConverter()));
-		bet.setOnEditCommit(e -> e.getTableView().getItems().get(e.getTablePosition().getRow()).setBet(e.getNewValue()));
-		odds.setCellFactory(TextFieldTableCell.forTableColumn(new FloatStringConverter()));
-		odds.setOnEditCommit(e -> e.getTableView().getItems().get(e.getTablePosition().getRow()).setOdds(e.getNewValue()));
-	}
-
-	private void addSubmitButtonToTable() {
-		Callback<TableColumn<BetDTO, Void>, TableCell<BetDTO, Void>> cellFactory = new Callback<TableColumn<BetDTO, Void>, TableCell<BetDTO, Void>>() {
-			@Override public TableCell<BetDTO, Void> call(final TableColumn<BetDTO, Void> param) {
-				return new TableCell<BetDTO, Void>() {
-
-					private final Button btn = new Button("Submit");
-					{
-						btn.setOnAction((ActionEvent event) -> {
-							BetDTO data = getTableView().getItems().get(getIndex());
-							GuiMysql.getInstance().addBetSeries(data);
-						});
-					}
-
-					@Override public void updateItem(Void item, boolean empty) {
-						super.updateItem(item, empty);
-						if (empty) {
-							setGraphic(null);
-						} else {
-							setGraphic(btn);
-						}
-					}
-				};
-			}
-		};
-
-		submitButton.setCellFactory(cellFactory);
-
-		activeBettingTable.getColumns().add(submitButton);
-
-	}
-
-	public void setMatches(List<SoccerMatch> upcomingMatches) {
-		ObservableList<Map<String, Object>> matches = FXCollections.<Map<String, Object>>observableArrayList();
-		for (final SoccerMatch soccerMatch : upcomingMatches) {
-
-			final Map<String, Object> match = new HashMap<>();
-			match.put("homeTeam", soccerMatch.getHomeTeam().getTeamName());
-			match.put("awayTeam", soccerMatch.getAwayTeam().getTeamName());
-			match.put("odds1", soccerMatch.getOdds1());
-			match.put("oddsX", soccerMatch.getOddsX());
-			match.put("odds2", soccerMatch.getOdds2());
-
-			final List<Float> avgHomeTeamGoals = calculateAvgHomeScore(soccerMatch.getHomeTeam().getTeamId());
-			final List<Float> avgAwayTeamGoals = calculateAvgAwayScore(soccerMatch.getAwayTeam().getTeamId());
-
-			match.put("gameDate", soccerMatch.getGameDate().toString());
-			match.put("avgScoreHome", avgHomeTeamGoals.get(0));
-			match.put("avgConcededHome", avgHomeTeamGoals.get(1));
-			match.put("avgScoreAway", avgAwayTeamGoals.get(0));
-			match.put("avgConcededAway", avgAwayTeamGoals.get(1));
-			match.put("goalsHome", GuiMysql.getInstance().round(BigDecimal.valueOf(avgHomeTeamGoals.get(0) + avgAwayTeamGoals.get(1)),
-					GuiMysql.getInstance().getIncrement(), RoundingMode.HALF_UP));
-			match.put("goalsAway", GuiMysql.getInstance().round(BigDecimal.valueOf(avgAwayTeamGoals.get(0) + avgHomeTeamGoals.get(1)),
-					GuiMysql.getInstance().getIncrement(), RoundingMode.HALF_UP));
-
-			match.put("country", soccerMatch.getHomeTeam().getCountryName());
-			match.put(Constants.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 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() + Float.valueOf(awayTeamResults.getCount())) * 100;
-			final float drawPercent = (homeTeamResults.getDraws() + awayTeamResults.getDraws())
-					/ Float.valueOf(homeTeamResults.getCount() + Float.valueOf(awayTeamResults.getCount())) * 100;
-			final float awayWinPercent = (homeTeamResults.getLosses() + awayTeamResults.getWins())
-					/ Float.valueOf(homeTeamResults.getCount() + Float.valueOf(awayTeamResults.getCount())) * 100;
-
-			match.put(Constants.HOME_WIN,
-					String.format(FLOAT_FORMAT, homeWinPercent) + "(" + String.format(FLOAT_FORMAT, (100 / homeWinPercent) * betMargin) + ")");
-			match.put("draw", String.format(FLOAT_FORMAT, drawPercent) + "(" + String.format(FLOAT_FORMAT, (100 / drawPercent) * betMargin) + ")");
-			match.put(Constants.AWAY_WIN,
-					String.format(FLOAT_FORMAT, awayWinPercent) + "(" + String.format(FLOAT_FORMAT, (100 / awayWinPercent) * betMargin) + ")");
-
-			List<Float> avgHomeScoreThisSeason = GuiMysql.getInstance().getAvgHomeScoreThisSeason(soccerMatch.getHomeTeam().getTeamId(),
-					soccerMatch.getHomeTeam().getCountryId(), soccerMatch.getHomeTeam().getTeamLeagueId());
-			List<Float> avgAwayScoreThisSeason = GuiMysql.getInstance().getAvgAwayScoreThisSeason(soccerMatch.getAwayTeam().getTeamId(),
-					soccerMatch.getAwayTeam().getCountryId(), soccerMatch.getAwayTeam().getTeamLeagueId());
-
-			match.put("scoringScore", (avgHomeScoreThisSeason.get(0) * avgAwayScoreThisSeason.get(1))
-					+ (avgAwayScoreThisSeason.get(0) * avgHomeScoreThisSeason.get(1)));
-
-			match.put("goalDiff",
-					GuiMysql.getInstance()
-							.round(BigDecimal.valueOf((avgHomeScoreThisSeason.get(0) * avgAwayScoreThisSeason.get(1))
-									+ (avgAwayScoreThisSeason.get(0) * avgHomeScoreThisSeason.get(1))), GuiMysql.getInstance().getIncrement(),
-									RoundingMode.HALF_UP));
-			match.put("addToBetslip", false);
-			match.put("id", soccerMatch.getMatchId());
-
-			matches.add(match);
-		}
-		matchTable.getItems().addAll(matches);
-	}
-
-	public void filterLeagueMatches(String filterByName, int countryId) {
-		List<SoccerMatch> filteredMatches = upcomingMatches.stream().filter(p -> p.getHomeTeam().getCountryId() == countryId)
-				.filter(p -> p.getHomeTeam().getTeamLeague().equals(filterByName)).toList();
-		this.countryId = countryId;
-		matchTable.getItems().clear();
-		setMatches(new ArrayList<>(filteredMatches));
-	}
-
-	public void filterCountryMatches(String filterByName) {
-		List<SoccerMatch> filteredMatches = upcomingMatches.stream().filter(p -> p.getHomeTeam().getCountryName().equals(filterByName)).toList();
-
-		matchTable.getItems().clear();
-		setMatches(new ArrayList<>(filteredMatches));
-		coutryFilteredMatches = matchTable.getItems();
-	}
-
-	public void resetFilter() {
-		matchTable.getItems().clear();
-	}
-
-	private List<Float> calculateAvgHomeScore(int teamId) {
-		return GuiMysql.getInstance().getAvgHomeScore(teamId);
-	}
-
-	private List<Float> calculateAvgAwayScore(int teamId) {
-		return GuiMysql.getInstance().getAvgAwayScore(teamId);
-	}
-
-	public Collection<Map<String, Object>> getTableMatches() {
-		return matchTable.getItems();
-	}
-
-	public List<String> getLeaguesFromSelection() {
-		final ArrayList<String> leagues = Lists.newArrayList();
-		coutryFilteredMatches.forEach(f -> {
-			if (!leagues.contains(f.get(Constants.LEAGUE))) {
-				leagues.add((String) f.get(Constants.LEAGUE));
-			}
-		});
-		return leagues;
-	}
-
-	public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
-
-		final Map<Object, Boolean> seen = new ConcurrentHashMap<>();
-		return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
-	}
-
-	public TableView getTable() {
-		return matchTable;
-	}
-
-	public void setUpcomingMatches(List<SoccerMatch> upcomingMatches) {
-		this.upcomingMatches = upcomingMatches;
-		matchTable.getItems().clear();
-		setMatches(new ArrayList<>(upcomingMatches));
-	}
-
-	@FXML public void addRowAction(ActionEvent event) {
-		ObservableList<TablePosition> selectedCells = matchTable.getSelectionModel().getSelectedCells();
-		if (selectedCells.size() > 0) {
-			Map<String, Object> selectedRow = matchTable.getItems().get(selectedCells.get(0).getRow());
-			BetDTO betDTO = new BetDTO();
-			betDTO.setCountryId(countryId);
-			betDTO.setLeague(selectedRow.get("league").toString());
-			betDTO.setHomeTeam(selectedRow.get("homeTeam").toString());
-			betDTO.setAwayTeam(selectedRow.get("awayTeam").toString());
-			betDTO.setGameDate(selectedRow.get("gameDate").toString());
-			betDTO.setBetSeries(lastBetSeries + 1);
-			betDTO.setMatch(selectedRow.get("homeTeam").toString(), selectedRow.get("awayTeam").toString());
-			betDTO.setBetType("O/U 1.5");
-			betDTO.setWinAmount(-1);
-
-			betDTO.setGameId(Integer.valueOf(selectedRow.get("id").toString()));
-
-			betObservableList.add(betDTO);
-		} else {
-			System.out.println("No row selected");
-		}
-	}
+
+@SuppressWarnings("rawtypes")
+public class MatchTabController implements Initializable {
+
+    @FXML
+    private TableView<SoccerMatch> matchTable;
+    @FXML
+    TableColumn<SoccerMatch, String> gameDateColumn = new TableColumn<>("Gamedate");
+    @FXML
+    TableColumn<SoccerMatch, String> homeTeamColumn = new TableColumn<>("Home Team");
+    @FXML
+    TableColumn<SoccerMatch, String> awayTeamColumn = new TableColumn<>("Away Team");
+    @FXML
+    TableColumn<SoccerMatch, Float> odds1Column = new TableColumn<>("odds 1");
+    @FXML
+    TableColumn<SoccerMatch, Float> oddsXColumn = new TableColumn<>("odds X");
+    @FXML
+    TableColumn<SoccerMatch, Float> odds2Column = new TableColumn<>("odds 2");
+    @FXML
+    TableColumn<SoccerMatch, Float> goalsHomeColumn = new TableColumn<>("Goals home");
+    @FXML
+    TableColumn<SoccerMatch, Float> goalsAwayColumn = new TableColumn<>("Goals away");
+    @FXML
+    TableColumn<SoccerMatch, Float> goalDiff = new TableColumn<>("Difference");
+    @FXML
+    TableColumn<SoccerMatch, Float> avgScoreHomeColumn = new TableColumn<>("Avg score home");
+    @FXML
+    TableColumn<SoccerMatch, Float> avgConcededHomeColumn = new TableColumn<>("Avg conceded home");
+    @FXML
+    TableColumn<SoccerMatch, Float> avgScoreAwayColumn = new TableColumn<>("Avg score away");
+    @FXML
+    TableColumn<SoccerMatch, Float> avgConcededAwayColumn = new TableColumn<>("Avg conceded away");
+    @FXML
+    TableColumn<SoccerMatch, String> countryColumn = new TableColumn<>("Country");
+    @FXML
+    TableColumn<SoccerMatch, String> leagueColumn = new TableColumn<>("League");
+
+    @FXML
+    TableColumn<SoccerMatch, String> scoringScore = new TableColumn<>("scoringScore");
+
+    @FXML
+    TableColumn<SoccerMatch, Float> ownOddsPerdiction = new TableColumn<>("ownOdds");
+    @FXML
+    TableColumn<SoccerMatch, Float> givenOdds = new TableColumn<>("givenOdds");
+    @FXML
+    TableColumn<SoccerMatch, String> percentageToBet = new TableColumn<>("toBetPercent");
+    @FXML
+    TableColumn<SoccerMatch, String> betAmount = new TableColumn<>("betAmount");
+
+    @FXML
+    TableColumn<Map, Boolean> addToBetSlip = new TableColumn<>("addToBetslip");
+
+    @FXML
+    TextField betAmountTextField;
+
+    @FXML
+    private TableView<BetDTO> activeBettingTable;
+    private final ObservableList<BetDTO> betObservableList = FXCollections.observableArrayList();
+    private final ObservableList<SoccerMatch> soccerMatchesObservableList = FXCollections.observableArrayList();
+
+    @FXML
+    TableColumn<BetDTO, StringProperty> betSeries = new TableColumn<>("Bet series");
+    @FXML
+    TableColumn<BetDTO, String> gameDate = new TableColumn<>("Game date");
+    @FXML
+    TableColumn<BetDTO, String> match = new TableColumn<>("Match");
+    @FXML
+    TableColumn<BetDTO, String> betType = new TableColumn<>("Bet type");
+    @FXML
+    TableColumn<BetDTO, Float> bet = new TableColumn<>("Bet amount");
+    @FXML
+    TableColumn<BetDTO, Float> odds = new TableColumn<>("Odds");
+    @FXML
+    TableColumn<BetDTO, String> result = new TableColumn<>("Result");
+    @FXML
+    TableColumn<BetDTO, String> winAmount = new TableColumn<>("Win amount");
+    @FXML
+    TableColumn<BetDTO, Void> submitButton = new TableColumn<>("Submit row");
+
+    private ObservableList<SoccerMatch> coutryFilteredMatches;
+    private List<SoccerMatch> upcomingMatches;
+    private int countryId;
+    private static final String FLOAT_FORMAT = "%.02f";
+
+    private ObservableList<String> betSeriesOptions = FXCollections.observableArrayList();
+    private List<BetDTO> dbBetSeries;
+    private int lastBetSeries;
+
+    @Override
+    public void initialize(URL arg0, ResourceBundle arg1) {
+        gameDateColumn.setCellValueFactory(new PropertyValueFactory<>("gameDate"));
+        homeTeamColumn.setCellValueFactory(new PropertyValueFactory<>("homeTeamName"));
+        awayTeamColumn.setCellValueFactory(new PropertyValueFactory<>("awayTeamName"));
+        odds1Column.setCellValueFactory(new PropertyValueFactory<>("odds1"));
+        oddsXColumn.setCellValueFactory(new PropertyValueFactory<>("oddsX"));
+        odds2Column.setCellValueFactory(new PropertyValueFactory<>("odds2"));
+        goalsHomeColumn.setCellValueFactory(new PropertyValueFactory<>("goalsHome"));
+        goalsAwayColumn.setCellValueFactory(new PropertyValueFactory<>("goalsAway"));
+        goalDiff.setCellValueFactory(new PropertyValueFactory<>("goalsDiff"));
+        avgScoreHomeColumn.setCellValueFactory(new PropertyValueFactory<>("avgScoreHome"));
+        avgConcededHomeColumn.setCellValueFactory(new PropertyValueFactory<>("avgConcededHome"));
+        avgScoreAwayColumn.setCellValueFactory(new PropertyValueFactory<>("avgScoreAway"));
+        avgConcededAwayColumn.setCellValueFactory(new PropertyValueFactory<>("avgConcededAway"));
+        countryColumn.setCellValueFactory(new PropertyValueFactory<>("countryName"));
+        leagueColumn.setCellValueFactory(new PropertyValueFactory<>("leagueName"));
+
+        scoringScore.setCellValueFactory(new PropertyValueFactory<>("scoringScore"));
+
+        ownOddsPerdiction.setCellValueFactory(new PropertyValueFactory<>("ownOdds"));
+        givenOdds.setCellValueFactory(new PropertyValueFactory<>("givenOdds"));
+        percentageToBet.setCellValueFactory(new PropertyValueFactory<>("percentageToBet"));
+        betAmount.setCellValueFactory(new PropertyValueFactory<>("betAmount"));
+
+        ownOddsPerdiction.setCellFactory(TextFieldTableCell.forTableColumn(new OwnFloatStringConverter()));
+        ownOddsPerdiction.setEditable(true);
+        ownOddsPerdiction.setOnEditCommit(e -> {
+            SoccerMatch soccerMatch = e.getTableView().getItems().get(e.getTablePosition().getRow());
+            soccerMatch.setOwnOdds(e.getNewValue());
+            if (soccerMatch.getGivenOdds() != null && soccerMatch.getGivenOdds() > 0f) {
+                calculateBetPercent(soccerMatch);
+                setBetAmount(soccerMatch);
+                matchTable.getItems().set(e.getTablePosition().getRow(), soccerMatch);
+            }
+        });
+
+        givenOdds.setCellFactory(TextFieldTableCell.forTableColumn(new OwnFloatStringConverter()));
+        givenOdds.setEditable(true);
+        givenOdds.setOnEditCommit(e -> {
+            SoccerMatch soccerMatch = e.getTableView().getItems().get(e.getTablePosition().getRow());
+            soccerMatch.setGivenOdds(e.getNewValue());
+
+            if (soccerMatch.getOwnOdds() != null && soccerMatch.getOwnOdds() > 0f) {
+                calculateBetPercent(soccerMatch);
+                setBetAmount(soccerMatch);
+                matchTable.getItems().set(e.getTablePosition().getRow(), soccerMatch);
+            }
+
+        });
+
+        betSeries.setCellValueFactory(i -> {
+            return Bindings.createObjectBinding(() -> i.getValue().optionProperty());
+        });
+
+        matchTable.getColumns().addAll(gameDateColumn, homeTeamColumn, awayTeamColumn, odds1Column, oddsXColumn,
+                odds2Column, goalsHomeColumn,
+                goalsAwayColumn, goalDiff, avgScoreHomeColumn, avgConcededHomeColumn, avgScoreAwayColumn,
+                avgConcededAwayColumn, countryColumn,
+                leagueColumn, scoringScore, ownOddsPerdiction, givenOdds, percentageToBet, betAmount);
+        matchTable.setItems(soccerMatchesObservableList);
+
+        matchTable.setEditable(true);
+
+        gameDate.setCellValueFactory(new PropertyValueFactory<>("gameDate"));
+        match.setCellValueFactory(new PropertyValueFactory<>("match"));
+        betType.setCellValueFactory(new PropertyValueFactory<>("betType"));
+        bet.setCellValueFactory(new PropertyValueFactory<>("bet"));
+        odds.setCellValueFactory(new PropertyValueFactory<>("odds"));
+        result.setCellValueFactory(new PropertyValueFactory<>("result"));
+        winAmount.setCellValueFactory(new PropertyValueFactory<>("winAmount"));
+
+        makeColumnsEditable();
+
+        activeBettingTable.getColumns().addAll(betSeries, gameDate, match, betType, bet, odds, result, winAmount);
+        activeBettingTable.setItems(betObservableList);
+
+        activeBettingTable.setEditable(true);
+
+        addSubmitButtonToTable();
+
+        addActiveBetsFromDatabase();
+
+        betAmountTextField.setText(GuiMysql.getInstance().getBetBaseAmount());
+
+        betAmountTextField.focusedProperty().addListener(new ChangeListener<Boolean>() {
+            @Override
+            public void changed(javafx.beans.value.ObservableValue<? extends Boolean> observable, Boolean oldValue,
+                    Boolean newValue) {
+                if (!newValue) { // Textfield focus lost
+                    GuiMysql.getInstance().updateBetBaseAmount(betAmountTextField.getText());
+                }
+            };
+        });
+    }
+
+    private void setBetAmount(SoccerMatch soccerMatch) {
+        if (betAmountTextField.getText().length() > 0) {
+            float betAmountValue = Float.parseFloat(betAmountTextField.getText());
+            soccerMatch.setBetAmount(betAmountValue * (soccerMatch.getPercentageToBet() / 100f));
+        }
+    }
+
+    /*
+     * Kelly Criterion formula (BP - Q) / B B = Decimal odds -1 P = Probability of
+     * success Q = Probability of failure (1 - P)
+     */
+    private void calculateBetPercent(SoccerMatch soccerMatch) {
+        float oddsMinusOne = soccerMatch.getGivenOdds() - 1;
+        float probabilityOfSuccess = (1 / soccerMatch.getOwnOdds());
+        float probabilityOfFailure = 1 - probabilityOfSuccess;
+        float value = ((oddsMinusOne * probabilityOfSuccess) - probabilityOfFailure) / oddsMinusOne;
+
+        soccerMatch.setPercentageToBet(value * 100f);
+    }
+
+    private void addActiveBetsFromDatabase() {
+        dbBetSeries = GuiMysql.getInstance().getBetSeries(false);
+
+        betSeriesOptions.addAll(dbBetSeries.stream().map(BetDTO::getBetSeries).sorted().map(String::valueOf).distinct()
+                .collect(Collectors.toCollection(LinkedList::new)));
+
+        lastBetSeries = GuiMysql.getInstance().getBetSeriesEndNumber();
+        betSeriesOptions.add(String.valueOf(lastBetSeries + 1));
+
+        betObservableList.addAll(dbBetSeries);
+    }
+
+    private void makeColumnsEditable() {
+
+        betSeries.setCellFactory(col -> {
+            TableCell<BetDTO, StringProperty> c = new TableCell<>();
+            final ComboBox<String> comboBox = new ComboBox<>(betSeriesOptions);
+            c.itemProperty().addListener((observable, oldValue, newValue) -> {
+                if (oldValue != null) {
+                    comboBox.valueProperty().unbindBidirectional(oldValue);
+                }
+                if (newValue != null) {
+                    comboBox.valueProperty().bindBidirectional(newValue);
+                }
+            });
+            c.graphicProperty().bind(Bindings.when(c.emptyProperty()).then((Node) null).otherwise(comboBox));
+            return c;
+        });
+
+        match.setCellFactory(TextFieldTableCell.forTableColumn());
+        match.setOnEditCommit(
+                e -> e.getTableView().getItems().get(e.getTablePosition().getRow()).setMatch(e.getNewValue()));
+        betType.setCellFactory(TextFieldTableCell.forTableColumn());
+        betType.setOnEditCommit(
+                e -> e.getTableView().getItems().get(e.getTablePosition().getRow()).setBetType(e.getNewValue()));
+        bet.setCellFactory(TextFieldTableCell.forTableColumn(new FloatStringConverter()));
+        bet.setOnEditCommit(
+                e -> e.getTableView().getItems().get(e.getTablePosition().getRow()).setBet(e.getNewValue()));
+        odds.setCellFactory(TextFieldTableCell.forTableColumn(new FloatStringConverter()));
+        odds.setOnEditCommit(
+                e -> e.getTableView().getItems().get(e.getTablePosition().getRow()).setOdds(e.getNewValue()));
+    }
+
+    private void addSubmitButtonToTable() {
+        Callback<TableColumn<BetDTO, Void>, TableCell<BetDTO, Void>> cellFactory = new Callback<TableColumn<BetDTO, Void>, TableCell<BetDTO, Void>>() {
+            @Override
+            public TableCell<BetDTO, Void> call(final TableColumn<BetDTO, Void> param) {
+                return new TableCell<BetDTO, Void>() {
+
+                    private final Button btn = new Button("Submit");
+                    {
+                        btn.setOnAction((ActionEvent event) -> {
+                            BetDTO data = getTableView().getItems().get(getIndex());
+                            GuiMysql.getInstance().addBetSeries(data);
+                        });
+                    }
+
+                    @Override
+                    public void updateItem(Void item, boolean empty) {
+                        super.updateItem(item, empty);
+                        if (empty) {
+                            setGraphic(null);
+                        } else {
+                            setGraphic(btn);
+                        }
+                    }
+                };
+            }
+        };
+
+        submitButton.setCellFactory(cellFactory);
+
+        activeBettingTable.getColumns().add(submitButton);
+
+    }
+
+    public void setMatches(List<SoccerMatch> upcomingMatches) {
+        ObservableList<Map<String, Object>> matches = FXCollections.<Map<String, Object>>observableArrayList();
+        for (final SoccerMatch soccerMatch : upcomingMatches) {
+
+            final List<Float> avgHomeTeamGoals = calculateAvgHomeScore(soccerMatch.getHomeTeam().getTeamId());
+            final List<Float> avgAwayTeamGoals = calculateAvgAwayScore(soccerMatch.getAwayTeam().getTeamId());
+
+            List<Float> avgHomeScoreThisSeason = GuiMysql.getInstance().getAvgHomeScoreThisSeason(
+                    soccerMatch.getHomeTeam().getTeamId(),
+                    soccerMatch.getHomeTeam().getCountryId(), soccerMatch.getHomeTeam().getTeamLeagueId());
+            List<Float> avgAwayScoreThisSeason = GuiMysql.getInstance().getAvgAwayScoreThisSeason(
+                    soccerMatch.getAwayTeam().getTeamId(),
+                    soccerMatch.getAwayTeam().getCountryId(), soccerMatch.getAwayTeam().getTeamLeagueId());
+
+            soccerMatch.setGoalsHome(
+//                    GuiMysql.getInstance().round(
+                    BigDecimal.valueOf(avgHomeScoreThisSeason.get(0) * avgAwayScoreThisSeason.get(1)));// ,
+//                    GuiMysql.getInstance().getIncrement()
+//                            , RoundingMode.HALF_UP));
+            soccerMatch.setGoalsAway(
+//                    GuiMysql.getInstance().round(
+                    BigDecimal.valueOf(avgAwayScoreThisSeason.get(0) * avgHomeScoreThisSeason.get(1))); // ,
+//                            GuiMysql.getInstance().getIncrement(), RoundingMode.HALF_UP));
+
+            soccerMatch.setGoalsDiff(GuiMysql.getInstance()
+                    .round(BigDecimal.valueOf((avgHomeScoreThisSeason.get(0) * avgAwayScoreThisSeason.get(1))
+                            + (avgAwayScoreThisSeason.get(0) * avgHomeScoreThisSeason.get(1))),
+                            GuiMysql.getInstance().getIncrement(),
+                            RoundingMode.HALF_UP));
+
+            soccerMatch.setAvgScoreHome(avgHomeTeamGoals.get(0));
+            soccerMatch.setAvgConcededHome(avgHomeTeamGoals.get(1));
+            soccerMatch.setAvgScoreAway(avgAwayTeamGoals.get(0));
+            soccerMatch.setAvgConcededAway(avgAwayTeamGoals.get(1));
+            soccerMatch.setCountryName(soccerMatch.getHomeTeam().getCountryName());
+            soccerMatch.setLeagueName(soccerMatch.getHomeTeam().getTeamLeague());
+
+            final DecimalFormat df = new DecimalFormat("#.##");
+            df.setRoundingMode(RoundingMode.CEILING);
+
+            soccerMatch.setScoringScore((avgHomeScoreThisSeason.get(0) * avgAwayScoreThisSeason.get(1))
+                    + (avgAwayScoreThisSeason.get(0) * avgHomeScoreThisSeason.get(1)));
+
+            soccerMatch.setAddToBetSlip(false);
+            soccerMatch.setHomeTeamName(soccerMatch.getHomeTeam().getTeamName());
+            soccerMatch.setAwayTeamName(soccerMatch.getAwayTeam().getTeamName());
+            soccerMatchesObservableList.add(soccerMatch);
+        }
+    }
+
+    public void filterLeagueMatches(String filterByName, int countryId) {
+        List<SoccerMatch> filteredMatches = upcomingMatches.stream()
+                .filter(p -> p.getHomeTeam().getCountryId() == countryId)
+                .filter(p -> p.getHomeTeam().getTeamLeague().equals(filterByName)).toList();
+        this.countryId = countryId;
+        matchTable.getItems().clear();
+        setMatches(new ArrayList<>(filteredMatches));
+    }
+
+    public void filterCountryMatches(String filterByName) {
+        List<SoccerMatch> filteredMatches = upcomingMatches.stream()
+                .filter(p -> p.getHomeTeam().getCountryName().equals(filterByName)).toList();
+
+        matchTable.getItems().clear();
+        setMatches(new ArrayList<>(filteredMatches));
+        coutryFilteredMatches = matchTable.getItems();
+    }
+
+    public void resetFilter() {
+        matchTable.getItems().clear();
+    }
+
+    private List<Float> calculateAvgHomeScore(int teamId) {
+        return GuiMysql.getInstance().getAvgHomeScore(teamId);
+    }
+
+    private List<Float> calculateAvgAwayScore(int teamId) {
+        return GuiMysql.getInstance().getAvgAwayScore(teamId);
+    }
+
+    public Collection<SoccerMatch> getTableMatches() {
+        return matchTable.getItems();
+    }
+
+    public List<String> getLeaguesFromSelection() {
+        final ArrayList<String> leagues = Lists.newArrayList();
+        coutryFilteredMatches.forEach(f -> {
+            if (!leagues.contains(f.getLeagueName())) {
+                leagues.add(f.getLeagueName());
+            }
+        });
+        return leagues;
+    }
+
+    public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
+
+        final Map<Object, Boolean> seen = new ConcurrentHashMap<>();
+        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
+    }
+
+    public TableView getTable() {
+        return matchTable;
+    }
+
+    public void setUpcomingMatches(List<SoccerMatch> upcomingMatches) {
+        this.upcomingMatches = upcomingMatches;
+        matchTable.getItems().clear();
+        setMatches(new ArrayList<>(upcomingMatches));
+    }
+
+    @FXML
+    public void addRowAction(ActionEvent event) {
+        ObservableList<TablePosition> selectedCells = matchTable.getSelectionModel().getSelectedCells();
+        if (selectedCells.size() > 0) {
+            SoccerMatch selectedRow = matchTable.getItems().get(selectedCells.get(0).getRow());
+            BetDTO betDTO = new BetDTO();
+            betDTO.setCountryId(countryId);
+            betDTO.setLeague(selectedRow.getLeagueName());
+            betDTO.setHomeTeam(selectedRow.getHomeTeam().getTeamName());
+            betDTO.setAwayTeam(selectedRow.getAwayTeam().getTeamName());
+            betDTO.setGameDate(MainController.DATE_FORMAT.format(selectedRow.getGameDate()));
+            betDTO.setBetSeries(lastBetSeries + 1);
+            betDTO.setMatch(selectedRow.getHomeTeam().getTeamName(), selectedRow.getAwayTeam().getTeamName());
+            betDTO.setBetType("O/U 1.5");
+            betDTO.setWinAmount(-1);
+
+            betDTO.setGameId(selectedRow.getMatchId());
+
+            betObservableList.add(betDTO);
+        } else {
+            System.out.println("No row selected");
+        }
+    }
+
+    public class OwnFloatStringConverter extends StringConverter {
+
+        @Override
+        public String toString(Object object) {
+
+            return object == null || Float.isNaN((float) object) ? "" : Float.toString((float) object);
+        }
+
+        @Override
+        public Object fromString(String string) {
+
+            return Float.valueOf(string.replace(",", "."));
+        }
+
+    }
 
 }

+ 672 - 551
OddsJavaFx/src/controllers/PastResultsController.java

@@ -40,561 +40,682 @@ import javafx.scene.layout.AnchorPane;
 import javafx.scene.text.Text;
 import javafx.util.Callback;
 import objects.Constants;
+import objects.League;
 import objects.SoccerMatch;
+import objects.SoccerMatchAnalysis;
 import tests.objects.Standing;
 
-@SuppressWarnings("rawtypes") public class PastResultsController implements Initializable {
-
-	@FXML AnchorPane basePane;
-	@FXML TableView<Map<String, Object>> matchTable;
-	@FXML DatePicker date;
-	@FXML ComboBox<String> countrySelector;
-	@FXML ComboBox<String> leagueSelector;
-
-	@FXML TableColumn<Map, String> gameDateColumn = new TableColumn<>("Gamedate");
-	@FXML TableColumn<Map, String> homeTeamColumn = new TableColumn<>("Home Team");
-	@FXML TableColumn<Map, String> awayTeamColumn = new TableColumn<>("Away Team");
-	@FXML TableColumn<Map, Float> odds1Column = new TableColumn<>("odds 1");
-	@FXML TableColumn<Map, Float> oddsXColumn = new TableColumn<>("odds X");
-	@FXML TableColumn<Map, Float> odds2Column = new TableColumn<>("odds 2");
-	@FXML TableColumn<Map, Float> goalsHomeColumn = new TableColumn<>("Goals home");
-	@FXML TableColumn<Map, Float> goalsAwayColumn = new TableColumn<>("Goals away");
-	@FXML TableColumn<Map, Float> goalDiff = new TableColumn<>("Difference");
-	@FXML TableColumn<Map, Float> avgScoreHomeColumn = new TableColumn<>("Avg score home");
-	@FXML TableColumn<Map, Float> avgConcededHomeColumn = new TableColumn<>("Avg conceded home");
-	@FXML TableColumn<Map, Float> avgScoreAwayColumn = new TableColumn<>("Avg score away");
-	@FXML TableColumn<Map, Float> avgConcededAwayColumn = new TableColumn<>("Avg conceded away");
-
-	@FXML TableColumn<Map, String> avgHomeScoredSeason = new TableColumn<>("AvgHomeScoredThisSeason");
-	@FXML TableColumn<Map, String> avgHomeConcededSeason = new TableColumn<>("AvgHomeConcededThisSeason");
-
-	@FXML TableColumn<Map, String> avgAwayScoredSeason = new TableColumn<>("AvgAwayScoredThisSeason");
-	@FXML TableColumn<Map, String> avgAwayConcededSeason = new TableColumn<>("AvgAwayConcededThisSeason");
-
-	@FXML TableColumn<Map, String> sumScoringColumn = new TableColumn<>("Sum scoring");
-	@FXML TableColumn<Map, Float> positionAdjustmentColumn = new TableColumn<>("PositionAdjustment");
-	@FXML TableColumn<Map, String> newScoringTestColumn = new TableColumn<>("New Scoring test");
-	@FXML TableColumn<Map, Void> addToBetsButtonColumn = new TableColumn<>("Add bet");
-
-	@FXML Text homeTeamPastResultsText;
-	@FXML Text awayTeamPastResultsText;
-	@FXML Text previousMeetingsText;
-	@FXML Text previousReverseMeetingsText;
-
-	@FXML Label NumberOfGamesText;
-	@FXML TextArea SystemsText;
-	@FXML Label ReslutsText;
-
-	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();
-
-	GuiMysql db = GuiMysql.getInstance();
-	private String selectedHomeTeam;
-	private String selectedAwayTeam;
-
-	Set<betSystemDTO> bets = new HashSet<>();
-
-	@Override public void initialize(URL arg0, ResourceBundle arg1) {
-		gameDateColumn.setCellValueFactory(new MapValueFactory<>("gameDate"));
-		homeTeamColumn.setCellValueFactory(new MapValueFactory<>("homeTeam"));
-		awayTeamColumn.setCellValueFactory(new MapValueFactory<>("awayTeam"));
-		odds1Column.setCellValueFactory(new MapValueFactory<>("odds1"));
-		oddsXColumn.setCellValueFactory(new MapValueFactory<>("oddsX"));
-		odds2Column.setCellValueFactory(new MapValueFactory<>("odds2"));
-		goalsHomeColumn.setCellValueFactory(new MapValueFactory<>("goalsHome"));
-		goalsAwayColumn.setCellValueFactory(new MapValueFactory<>("goalsAway"));
-		goalDiff.setCellValueFactory(new MapValueFactory<>("goalDiff"));
-		avgScoreHomeColumn.setCellValueFactory(new MapValueFactory<>("avgScoreHome"));
-		avgConcededHomeColumn.setCellValueFactory(new MapValueFactory<>("avgConcededHome"));
-		avgScoreAwayColumn.setCellValueFactory(new MapValueFactory<>("avgScoreAway"));
-		avgConcededAwayColumn.setCellValueFactory(new MapValueFactory<>("avgConcededAway"));
-
-		avgHomeScoredSeason.setCellValueFactory(new MapValueFactory<>("avgScoredHomeSeason"));
-		avgHomeConcededSeason.setCellValueFactory(new MapValueFactory<>("avgConcededHomeSeason"));
-		avgAwayScoredSeason.setCellValueFactory(new MapValueFactory<>("avgScoredAwaySeason"));
-		avgAwayConcededSeason.setCellValueFactory(new MapValueFactory<>("avgConcededAwaySeason"));
-
-		sumScoringColumn.setCellValueFactory(new MapValueFactory<>("sumScoring"));
-		positionAdjustmentColumn.setCellValueFactory(new MapValueFactory<>("positionAdjustment"));
-		newScoringTestColumn.setCellValueFactory(new MapValueFactory<>("newScoringTest"));
-
-		Callback<TableColumn<Map, Void>, TableCell<Map, Void>> cellFactory = new Callback<TableColumn<Map, Void>, TableCell<Map, Void>>() {
-			@Override public TableCell<Map, Void> call(final TableColumn<Map, Void> param) {
-				return new TableCell<Map, Void>() {
-
-					private final Button btn = new Button("Submit");
-					{
-						btn.setOnAction((ActionEvent event) -> {
-							Map data = getTableView().getItems().get(getIndex());
-
-							addToBets(data);
-						});
-					}
-
-					@Override public void updateItem(Void item, boolean empty) {
-						super.updateItem(item, empty);
-						if (empty) {
-							setGraphic(null);
-						} else {
-							setGraphic(btn);
-						}
-					}
-				};
-			}
-		};
-
-		addToBetsButtonColumn.setCellFactory(cellFactory);
-
-		basePane.setPrefWidth(0.0);
-		basePane.setPrefHeight(0.0);
-
-		date.valueProperty().addListener((ov, oldValue, newValue) -> {
-			clear();
-			getCountriesAtDate();
-		});
-
-		sportsList.addAll(GuiMysql.getInstance().getSports());
-		sports.add(MainController.SPORT);
-		for (final SimpleEntry<Integer, String> entry : sportsList) {
-			if (entry.getValue().equals("soccer")) { // Anv�nder just nu bara Soccer
-				sports.add(entry.getValue());
-			}
-		}
-
-		countrySelector.setItems(countries);
-		leagueSelector.setItems(leagues);
-
-		matchTable.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> {
-			updateMatchStats(newSelection);
-		});
-	}
-
-	public void addToBets(Map data) {
-		String betType;
-		if (Float.valueOf(data.get("sumScoring").toString()) > 5.0f && Float.valueOf(data.get("newScoringTest").toString()) > 6.5f) {
-			betType = "O 1.5";
-		} else if (Float.valueOf(data.get("sumScoring").toString()) < 2.0f && Float.valueOf(data.get("newScoringTest").toString()) < 3.5f) {
-			betType = "U 3.5";
-		} else if (Float.valueOf(data.get("sumScoring").toString()) < 3.0f && Float.valueOf(data.get("newScoringTest").toString()) < 4.5f) {
-			betType = "U 4.5";
-		} else {
-			return;
-		}
-
-		bets.add(new betSystemDTO(Integer.valueOf(data.get("id").toString()), Integer.valueOf(data.get("homeScore").toString()),
-				Integer.valueOf(data.get("awayScore").toString()), betType));
-		increaseNumberOfBets();
-		calculateSystems();
-	}
-
-	private void increaseNumberOfBets() {
-		NumberOfGamesText.setText(String.valueOf(Integer.valueOf(NumberOfGamesText.getText()) + 1));
-	}
-
-	private void calculateSystems() {
-		Set<Set<betSystemDTO>> combinations = Sets.powerSet(bets);
-
-		combinations = combinations.stream().sorted((s1, s2) -> Integer.compare(s1.size(), s2.size())).collect(Collectors.toSet());
-
-		String combinationText = "";
-		int totalCombinations = 0;
-		Map<Integer, Integer> sets = new HashMap<>();
-		for (Set<betSystemDTO> set : combinations) {
-			if (set.size() > 0) {
-				totalCombinations += set.size();
-				sets.put(set.size(), sets.getOrDefault(set.size(), 0) + 1);
-			}
-		}
-
-		String text = "Total Combinations: " + sets.values().stream().mapToInt(Integer::intValue).sum() + "\n";
-		StringBuilder sb = new StringBuilder();
-		sets.forEach((k, v) -> sb.append(k.toString() + "'s: " + v.toString() + "\n"));
-
-		text += sb.toString();
-		SystemsText.setText(text);
-	}
-
-	private void updateMatchStats(Map<String, Object> newSelection) {
-		if (newSelection != null) {
-			Map<String, String> previousMatches = db.getPreviousMatches(5, newSelection.get("homeTeam").toString(),
-					newSelection.get("awayTeam").toString(), date.getValue().toString(), getCountryIdFromSelector(), getLeagueIdFromSelector());
-			homeTeamPastResultsText.setText(previousMatches.get("PrevHomeTeam"));
-			awayTeamPastResultsText.setText(previousMatches.get("PrevAwayTeam"));
-			previousMeetingsText.setText(previousMatches.get("PrevCombined"));
-			previousReverseMeetingsText.setText(previousMatches.get("PrevReversedCombined"));
-
-			selectedHomeTeam = newSelection.get("homeTeam").toString();
-			selectedAwayTeam = newSelection.get("awayTeam").toString();
-			MatchStatTabController.getInstance().clearSelection();
-			MatchStatTabController.getInstance().setTeamSelected(selectedHomeTeam, true);
-			MatchStatTabController.getInstance().setTeamSelected(selectedAwayTeam, false);
-
-			StatisticsTabController.getInstance().markValueInTable(((BigDecimal) newSelection.get("goalDiff")).floatValue());
-		}
-	}
-
-	private void clear() {
-		matchTable.getItems().clear();
-		countriesList.clear();
-		leaguesList.clear();
-		countries.clear();
-		leagues.clear();
-	}
-
-	private void getCountriesAtDate() {
-		countriesList.clear();
-		countriesList.addAll(GuiMysql.getInstance().getCountriesBySport(db.getSportId(MainController.SPORT), date.getValue().toString()));
-
-		countriesList.forEach(c -> countries.add(c.getValue()));
-	}
-
-	private void getLeaguesAtDate(int countryId) {
-		leaguesList.clear();
-		leaguesList.addAll(db.getLeaguesByDate(db.getSportId("soccer"), countryId, date.getValue().toString()));
-
-		leaguesList.forEach(l -> leagues.add(l.getValue()));
-	}
-
-	@FXML private void getResults() {
-		throw new NotImplementedException();
-	}
-
-	@FXML private void countrySelected(ActionEvent event) {
-		if (getCountryIdFromSelector() > 0) {
-			getLeaguesAtDate(getCountryIdFromSelector());
-			leagueSelector.setDisable(false);
-		}
-	}
-
-	private int getCountryIdFromSelector() {
-		Optional<SimpleEntry<Integer, String>> o = countriesList.stream().filter(p -> p.getValue().equals(countrySelector.getValue())).findFirst();
-		return o.isPresent() ? o.get().getKey() : -1;
-	}
-
-	private int getLeagueIdFromSelector() {
-		Optional<SimpleEntry<Integer, String>> o = leaguesList.stream().filter(p -> p.getValue().equals(leagueSelector.getValue())).findFirst();
-		return o.isPresent() ? o.get().getKey() : -1;
-	}
-
-	private float getAvgGoalsWithSameDiff(int countryId, int leagueId, int placementDiff) {
-		List<Standing> tempStanding = new ArrayList<>();
-		float result = 0.0f;
-		int matchedMatches = 0;
-
-		if (placementDiff == 0) {
-			return 0f;
-		}
-
-		List<SoccerMatch> matchesBefore = GuiMysql.getInstance().getMatches(1, countryId, leagueId, date.getValue().toString(), "ASC", false, false);
-
-		for (SoccerMatch match : matchesBefore) {
-			Optional<Standing> homeTeamStanding = tempStanding.stream().filter(ts -> ts.getTeamName().equals(match.getHomeTeam().getTeamName()))
-					.findFirst();
-			Optional<Standing> awayTeamStanding = tempStanding.stream().filter(ts -> ts.getTeamName().equals(match.getAwayTeam().getTeamName()))
-					.findFirst();
-
-			if (homeTeamStanding.isPresent() && awayTeamStanding.isPresent()) {
-				int homeTeamPosition = tempStanding.indexOf(homeTeamStanding.get());
-				int awayTeamPosition = tempStanding.indexOf(awayTeamStanding.get());
-
-				int diff = Math.abs(homeTeamPosition - awayTeamPosition);
-
-				if (diff == placementDiff) {
-					matchedMatches++;
-					result += match.getHomeScore() + match.getAwayScore();
-				}
-			}
-			updateStanding(tempStanding, match,
-					tempStanding.stream().filter(p -> p.getTeamName().equals(match.getHomeTeam().getTeamName())).findFirst(),
-					tempStanding.stream().filter(p -> p.getTeamName().equals(match.getAwayTeam().getTeamName())).findFirst());
-
-			tempStanding.sort((s1, s2) -> Integer.compare(s2.getPoints(), s1.getPoints()));
-		}
-
-		return matchedMatches > 0 ? result / matchedMatches : 0f;
-	}
-
-	private void updateStanding(List<Standing> result, SoccerMatch match, Optional<Standing> homeTeam, Optional<Standing> awayTeam) {
-		int homeScore = match.getHomeScore();
-		int awayScore = match.getAwayScore();
-		if (homeScore > awayScore) {
-			homeTeam.ifPresentOrElse(ht -> {
-				ht.setWins(ht.getWins() + 1);
-				ht.setGamesPlayed(ht.getGamesPlayed() + 1);
-				ht.setPoints(ht.getPoints() + 3);
-			}, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 1, 0, 0, 3, 1)));
-
-			awayTeam.ifPresentOrElse(at -> {
-				at.setLosses(at.getLosses() + 1);
-				at.setGamesPlayed(at.getGamesPlayed() + 1);
-			}, () -> result.add(new Standing(match.getAwayTeam().getTeamName(), 0, 0, 1, 0, 1)));
-
-		} else if (homeScore == awayScore) {
-
-			homeTeam.ifPresentOrElse(ht -> {
-				ht.setDraws(ht.getDraws() + 1);
-				ht.setGamesPlayed(ht.getGamesPlayed() + 1);
-				ht.setPoints(ht.getPoints() + 1);
-			}, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 1, 0, 1, 1)));
-			awayTeam.ifPresentOrElse(at -> {
-				at.setDraws(at.getDraws() + 1);
-				at.setGamesPlayed(at.getGamesPlayed() + 1);
-				at.setPoints(at.getPoints() + 1);
-			}, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 1, 0, 1, 1)));
-		} else if (homeScore < awayScore) {
-			homeTeam.ifPresentOrElse(ht -> {
-				ht.setLosses(ht.getLosses() + 1);
-				ht.setGamesPlayed(ht.getGamesPlayed() + 1);
-			}, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 0, 1, 0, 1)));
-			awayTeam.ifPresentOrElse(at -> {
-				at.setWins(at.getWins() + 1);
-				at.setGamesPlayed(at.getGamesPlayed() + 1);
-				at.setPoints(at.getPoints() + 3);
-			}, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 1, 0, 0, 3, 1)));
-		}
-	}
-
-	@FXML private void leagueSelected(ActionEvent event) {
-		updateStandingsTable();
-		if (getCountryIdFromSelector() > 0) {
-			List<SoccerMatch> matchesList = db.getMatches(db.getSportId(MainController.SOCCER), getCountryIdFromSelector(),
-					db.getLeagueId(db.getSportId(MainController.SOCCER), getCountryIdFromSelector(), leagueSelector.getValue()),
-					date.getValue().toString(), "ASC", true, false);
-
-			addMatchesToTable(matchesList);
-		}
-	}
-
-	private void addMatchesToTable(List<SoccerMatch> matchesList) {
-		ObservableList<Map<String, Object>> matches = FXCollections.<Map<String, Object>>observableArrayList();
-
-		for (final SoccerMatch soccerMatch : matchesList) {
-
-			final Map<String, Object> match = new HashMap<>();
-			match.put("homeTeam", soccerMatch.getHomeTeam().getTeamName());
-			match.put("awayTeam", soccerMatch.getAwayTeam().getTeamName());
-			match.put("odds1", soccerMatch.getOdds1());
-			match.put("oddsX", soccerMatch.getOddsX());
-			match.put("odds2", soccerMatch.getOdds2());
-
-			final List<Float> avgHomeTeamGoals = calculateAvgHomeScore(soccerMatch.getHomeTeam().getTeamId());
-			final List<Float> avgAwayTeamGoals = calculateAvgAwayScore(soccerMatch.getAwayTeam().getTeamId());
-
-			final List<Float> avgHomeTeamGoalsThisSeason = calculateAvgHomeScoreThisSeason(soccerMatch.getHomeTeam().getTeamId(),
-					soccerMatch.getHomeTeam().getCountryId(), soccerMatch.getHomeTeam().getTeamLeagueId());
-			final List<Float> avgAwayTeamGoalsThisSeason = calculateAvgAwayScoreThisSeason(soccerMatch.getAwayTeam().getTeamId(),
-					soccerMatch.getAwayTeam().getCountryId(), soccerMatch.getAwayTeam().getTeamLeagueId());
-
-			match.put("gameDate", soccerMatch.getGameDate().toString());
-			match.put("avgScoreHome", avgHomeTeamGoals.get(0));
-			match.put("avgConcededHome", avgHomeTeamGoals.get(1));
-			match.put("avgScoreAway", avgAwayTeamGoals.get(0));
-			match.put("avgConcededAway", avgAwayTeamGoals.get(1));
-
-			match.put("avgScoredHomeSeason", avgHomeTeamGoalsThisSeason.get(0));
-			match.put("avgConcededHomeSeason", avgHomeTeamGoalsThisSeason.get(1));
-
-			match.put("avgScoredAwaySeason", avgAwayTeamGoalsThisSeason.get(0));
-			match.put("avgConcededAwaySeason", avgAwayTeamGoalsThisSeason.get(1));
-
-			match.put("sumScoring", avgHomeTeamGoalsThisSeason.get(0) * avgAwayTeamGoalsThisSeason.get(1)
-					+ avgAwayTeamGoalsThisSeason.get(0) * avgHomeTeamGoalsThisSeason.get(1));
-
-			match.put("goalsHome",
-					GuiMysql.getInstance().round(BigDecimal.valueOf(avgHomeTeamGoalsThisSeason.get(0) + avgAwayTeamGoalsThisSeason.get(1)),
-							GuiMysql.getInstance().getIncrement(), RoundingMode.HALF_UP));
-			match.put("goalsAway",
-					GuiMysql.getInstance().round(BigDecimal.valueOf(avgAwayTeamGoalsThisSeason.get(0) + avgHomeTeamGoalsThisSeason.get(1)),
-							GuiMysql.getInstance().getIncrement(), RoundingMode.HALF_UP));
-
-			match.put("goalDiff",
-					GuiMysql.getInstance()
-							.round(BigDecimal.valueOf((avgHomeTeamGoalsThisSeason.get(0) * avgAwayTeamGoalsThisSeason.get(1))
-									+ (avgAwayTeamGoalsThisSeason.get(0) * avgHomeTeamGoalsThisSeason.get(1))), GuiMysql.getInstance().getIncrement(),
-									RoundingMode.HALF_UP));
-			match.put("country", soccerMatch.getHomeTeam().getCountryName());
-
-			List<Float> leagueAvarages = GuiMysql.getInstance().getLeagueAvarages(getLeagueIdFromSelector(), getCountryIdFromSelector(),
-					soccerMatch.getGameDate().format(DateTimeFormatter.BASIC_ISO_DATE));
-			match.put("positionAdjustment", getAvgGoalsWithSameDiff(soccerMatch.getHomeTeam().getCountryId(),
-					soccerMatch.getHomeTeam().getTeamLeagueId(), MatchStatTabController.getInstance()
-							.getTeamPositionDiff(soccerMatch.getHomeTeam().getTeamName(), soccerMatch.getAwayTeam().getTeamName()))
-					- (leagueAvarages.get(0) + leagueAvarages.get(1)));
-
-			match.put("newScoringTest",
-					(avgHomeTeamGoalsThisSeason.get(0) * avgAwayTeamGoalsThisSeason.get(1)
-							+ avgAwayTeamGoalsThisSeason.get(0) * avgHomeTeamGoalsThisSeason.get(1))
-							+ ((avgHomeTeamGoals.get(0) * avgAwayTeamGoals.get(1)) + avgAwayTeamGoals.get(0) * avgHomeTeamGoals.get(1)) / 2);
-
-			match.put(Constants.LEAGUE, soccerMatch.getHomeTeam().getTeamLeague());
-
-			match.put("id", soccerMatch.getMatchId());
-			match.put("homeScore", soccerMatch.getHomeScore());
-			match.put("awayScore", soccerMatch.getAwayScore());
-			final DecimalFormat df = new DecimalFormat("#.##");
-			df.setRoundingMode(RoundingMode.CEILING);
+@SuppressWarnings("rawtypes")
+public class PastResultsController implements Initializable {
+
+    @FXML
+    AnchorPane basePane;
+    @FXML
+    TableView<Map<String, Object>> matchTable;
+    @FXML
+    DatePicker date;
+    @FXML
+    ComboBox<String> countrySelector;
+    @FXML
+    ComboBox<String> leagueSelector;
+
+    @FXML
+    TableColumn<Map, String> gameDateColumn = new TableColumn<>("Gamedate");
+    @FXML
+    TableColumn<Map, String> homeTeamColumn = new TableColumn<>("Home Team");
+    @FXML
+    TableColumn<Map, String> awayTeamColumn = new TableColumn<>("Away Team");
+    @FXML
+    TableColumn<Map, Float> odds1Column = new TableColumn<>("odds 1");
+    @FXML
+    TableColumn<Map, Float> oddsXColumn = new TableColumn<>("odds X");
+    @FXML
+    TableColumn<Map, Float> odds2Column = new TableColumn<>("odds 2");
+    @FXML
+    TableColumn<Map, Float> goalsHomeColumn = new TableColumn<>("Goals home");
+    @FXML
+    TableColumn<Map, Float> goalsAwayColumn = new TableColumn<>("Goals away");
+    @FXML
+    TableColumn<Map, Float> goalDiff = new TableColumn<>("Difference");
+    @FXML
+    TableColumn<Map, Float> avgScoreHomeColumn = new TableColumn<>("Avg score home");
+    @FXML
+    TableColumn<Map, Float> avgConcededHomeColumn = new TableColumn<>("Avg conceded home");
+    @FXML
+    TableColumn<Map, Float> avgScoreAwayColumn = new TableColumn<>("Avg score away");
+    @FXML
+    TableColumn<Map, Float> avgConcededAwayColumn = new TableColumn<>("Avg conceded away");
+
+    @FXML
+    TableColumn<Map, String> avgHomeScoredSeason = new TableColumn<>("AvgHomeScoredThisSeason");
+    @FXML
+    TableColumn<Map, String> avgHomeConcededSeason = new TableColumn<>("AvgHomeConcededThisSeason");
+
+    @FXML
+    TableColumn<Map, String> avgAwayScoredSeason = new TableColumn<>("AvgAwayScoredThisSeason");
+    @FXML
+    TableColumn<Map, String> avgAwayConcededSeason = new TableColumn<>("AvgAwayConcededThisSeason");
+
+    @FXML
+    TableColumn<Map, String> sumScoringColumn = new TableColumn<>("Sum scoring");
+    @FXML
+    TableColumn<Map, Float> positionAdjustmentColumn = new TableColumn<>("PositionAdjustment");
+    @FXML
+    TableColumn<Map, String> newScoringTestColumn = new TableColumn<>("New Scoring test");
+    @FXML
+    TableColumn<Map, Void> addToBetsButtonColumn = new TableColumn<>("Add bet");
+    @FXML
+    TableColumn<Map, String> analysisColumn = new TableColumn<>("Analysis");
+
+    @FXML
+    Text homeTeamPastResultsText;
+    @FXML
+    Text awayTeamPastResultsText;
+    @FXML
+    Text previousMeetingsText;
+    @FXML
+    Text previousReverseMeetingsText;
+
+    @FXML
+    Label NumberOfGamesText;
+    @FXML
+    TextArea SystemsText;
+    @FXML
+    Label ReslutsText;
+
+    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();
+
+    GuiMysql db = GuiMysql.getInstance();
+    private String selectedHomeTeam;
+    private String selectedAwayTeam;
+
+    Set<betSystemDTO> bets = new HashSet<>();
+    private League leagueInfo;
+
+    @Override
+    public void initialize(URL arg0, ResourceBundle arg1) {
+        gameDateColumn.setCellValueFactory(new MapValueFactory<>("gameDate"));
+        homeTeamColumn.setCellValueFactory(new MapValueFactory<>("homeTeam"));
+        awayTeamColumn.setCellValueFactory(new MapValueFactory<>("awayTeam"));
+        odds1Column.setCellValueFactory(new MapValueFactory<>("odds1"));
+        oddsXColumn.setCellValueFactory(new MapValueFactory<>("oddsX"));
+        odds2Column.setCellValueFactory(new MapValueFactory<>("odds2"));
+        goalsHomeColumn.setCellValueFactory(new MapValueFactory<>("goalsHome"));
+        goalsAwayColumn.setCellValueFactory(new MapValueFactory<>("goalsAway"));
+        goalDiff.setCellValueFactory(new MapValueFactory<>("goalDiff"));
+        avgScoreHomeColumn.setCellValueFactory(new MapValueFactory<>("avgScoreHome"));
+        avgConcededHomeColumn.setCellValueFactory(new MapValueFactory<>("avgConcededHome"));
+        avgScoreAwayColumn.setCellValueFactory(new MapValueFactory<>("avgScoreAway"));
+        avgConcededAwayColumn.setCellValueFactory(new MapValueFactory<>("avgConcededAway"));
+
+        avgHomeScoredSeason.setCellValueFactory(new MapValueFactory<>("avgScoredHomeSeason"));
+        avgHomeConcededSeason.setCellValueFactory(new MapValueFactory<>("avgConcededHomeSeason"));
+        avgAwayScoredSeason.setCellValueFactory(new MapValueFactory<>("avgScoredAwaySeason"));
+        avgAwayConcededSeason.setCellValueFactory(new MapValueFactory<>("avgConcededAwaySeason"));
+
+        sumScoringColumn.setCellValueFactory(new MapValueFactory<>("sumScoring"));
+        positionAdjustmentColumn.setCellValueFactory(new MapValueFactory<>("positionAdjustment"));
+        newScoringTestColumn.setCellValueFactory(new MapValueFactory<>("newScoringTest"));
+        analysisColumn.setCellValueFactory(new MapValueFactory<>("analysis"));
+
+        Callback<TableColumn<Map, Void>, TableCell<Map, Void>> cellFactory = new Callback<TableColumn<Map, Void>, TableCell<Map, Void>>() {
+            @Override
+            public TableCell<Map, Void> call(final TableColumn<Map, Void> param) {
+                return new TableCell<Map, Void>() {
+
+                    private final Button btn = new Button("Submit");
+                    {
+                        btn.setOnAction((ActionEvent event) -> {
+                            Map data = getTableView().getItems().get(getIndex());
+
+                            addToBets(data);
+                        });
+                    }
+
+                    @Override
+                    public void updateItem(Void item, boolean empty) {
+                        super.updateItem(item, empty);
+                        if (empty) {
+                            setGraphic(null);
+                        } else {
+                            setGraphic(btn);
+                        }
+                    }
+                };
+            }
+        };
+
+        addToBetsButtonColumn.setCellFactory(cellFactory);
+
+        basePane.setPrefWidth(0.0);
+        basePane.setPrefHeight(0.0);
+
+        date.valueProperty().addListener((ov, oldValue, newValue) -> {
+            clear();
+            getCountriesAtDate();
+        });
+
+        sportsList.addAll(GuiMysql.getInstance().getSports());
+        sports.add(MainController.SPORT);
+        for (final SimpleEntry<Integer, String> entry : sportsList) {
+            if (entry.getValue().equals("soccer")) { // Anv�nder just nu bara Soccer
+                sports.add(entry.getValue());
+            }
+        }
+
+        countrySelector.setItems(countries);
+        leagueSelector.setItems(leagues);
+
+        matchTable.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> {
+            updateMatchStats(newSelection);
+        });
+    }
+
+    public void addToBets(Map data) {
+        String betType;
+        if (Float.valueOf(data.get("sumScoring").toString()) > 5.0f
+                && Float.valueOf(data.get("newScoringTest").toString()) > 6.5f) {
+            betType = "O 1.5";
+        } else if (Float.valueOf(data.get("sumScoring").toString()) < 2.0f
+                && Float.valueOf(data.get("newScoringTest").toString()) < 3.5f) {
+            betType = "U 3.5";
+        } else if (Float.valueOf(data.get("sumScoring").toString()) < 3.0f
+                && Float.valueOf(data.get("newScoringTest").toString()) < 4.5f) {
+            betType = "U 4.5";
+        } else {
+            return;
+        }
+
+        bets.add(new betSystemDTO(Integer.valueOf(data.get("id").toString()),
+                Integer.valueOf(data.get("homeScore").toString()),
+                Integer.valueOf(data.get("awayScore").toString()), betType));
+        increaseNumberOfBets();
+        calculateSystems();
+    }
+
+    private void increaseNumberOfBets() {
+        NumberOfGamesText.setText(String.valueOf(Integer.valueOf(NumberOfGamesText.getText()) + 1));
+    }
+
+    private void calculateSystems() {
+        Set<Set<betSystemDTO>> combinations = Sets.powerSet(bets);
+
+        combinations = combinations.stream().sorted((s1, s2) -> Integer.compare(s1.size(), s2.size()))
+                .collect(Collectors.toSet());
+
+        String combinationText = "";
+        int totalCombinations = 0;
+        Map<Integer, Integer> sets = new HashMap<>();
+        for (Set<betSystemDTO> set : combinations) {
+            if (set.size() > 0) {
+                totalCombinations += set.size();
+                sets.put(set.size(), sets.getOrDefault(set.size(), 0) + 1);
+            }
+        }
+
+        String text = "Total Combinations: " + sets.values().stream().mapToInt(Integer::intValue).sum() + "\n";
+        StringBuilder sb = new StringBuilder();
+        sets.forEach((k, v) -> sb.append(k.toString() + "'s: " + v.toString() + "\n"));
+
+        text += sb.toString();
+        SystemsText.setText(text);
+    }
+
+    private void updateMatchStats(Map<String, Object> newSelection) {
+        if (newSelection != null) {
+            Map<String, String> previousMatches = db.getPreviousMatches(5, newSelection.get("homeTeam").toString(),
+                    newSelection.get("awayTeam").toString(), date.getValue().toString(), getCountryIdFromSelector(),
+                    getLeagueIdFromSelector());
+            homeTeamPastResultsText.setText(previousMatches.get("PrevHomeTeam"));
+            awayTeamPastResultsText.setText(previousMatches.get("PrevAwayTeam"));
+            previousMeetingsText.setText(previousMatches.get("PrevCombined"));
+            previousReverseMeetingsText.setText(previousMatches.get("PrevReversedCombined"));
+
+            selectedHomeTeam = newSelection.get("homeTeam").toString();
+            selectedAwayTeam = newSelection.get("awayTeam").toString();
+            MatchStatTabController.getInstance().clearSelection();
+            MatchStatTabController.getInstance().setTeamSelected(selectedHomeTeam, true);
+            MatchStatTabController.getInstance().setTeamSelected(selectedAwayTeam, false);
+
+            StatisticsTabController.getInstance()
+                    .markValueInTable(((BigDecimal) newSelection.get("goalDiff")).floatValue());
+        }
+    }
+
+    private void clear() {
+        matchTable.getItems().clear();
+        countriesList.clear();
+        leaguesList.clear();
+        countries.clear();
+        leagues.clear();
+    }
+
+    private void getCountriesAtDate() {
+        countriesList.clear();
+        countriesList.addAll(GuiMysql.getInstance().getCountriesBySport(db.getSportId(MainController.SPORT),
+                date.getValue().toString()));
+
+        countriesList.forEach(c -> countries.add(c.getValue()));
+    }
+
+    private void getLeaguesAtDate(int countryId) {
+        leaguesList.clear();
+        leaguesList.addAll(db.getLeaguesByDate(db.getSportId("soccer"), countryId, date.getValue().toString()));
+
+        leaguesList.forEach(l -> leagues.add(l.getValue()));
+    }
+
+    @FXML
+    private void getResults() {
+        throw new NotImplementedException();
+    }
+
+    @FXML
+    private void countrySelected(ActionEvent event) {
+        if (getCountryIdFromSelector() > 0) {
+            getLeaguesAtDate(getCountryIdFromSelector());
+            leagueSelector.setDisable(false);
+        }
+    }
+
+    private int getCountryIdFromSelector() {
+        Optional<SimpleEntry<Integer, String>> o = countriesList.stream()
+                .filter(p -> p.getValue().equals(countrySelector.getValue())).findFirst();
+        return o.isPresent() ? o.get().getKey() : -1;
+    }
+
+    private int getLeagueIdFromSelector() {
+        Optional<SimpleEntry<Integer, String>> o = leaguesList.stream()
+                .filter(p -> p.getValue().equals(leagueSelector.getValue())).findFirst();
+        return o.isPresent() ? o.get().getKey() : -1;
+    }
+
+    private float getAvgGoalsWithSameDiff(int countryId, int leagueId, int placementDiff) {
+        List<Standing> tempStanding = new ArrayList<>();
+        float result = 0.0f;
+        int matchedMatches = 0;
+
+        if (placementDiff == 0) {
+            return 0f;
+        }
+
+        List<SoccerMatch> matchesBefore = GuiMysql.getInstance().getMatches(1, countryId, leagueId,
+                date.getValue().toString(), "ASC", false, false);
+
+        for (SoccerMatch match : matchesBefore) {
+            Optional<Standing> homeTeamStanding = tempStanding.stream()
+                    .filter(ts -> ts.getTeamName().equals(match.getHomeTeam().getTeamName()))
+                    .findFirst();
+            Optional<Standing> awayTeamStanding = tempStanding.stream()
+                    .filter(ts -> ts.getTeamName().equals(match.getAwayTeam().getTeamName()))
+                    .findFirst();
+
+            if (homeTeamStanding.isPresent() && awayTeamStanding.isPresent()) {
+                int homeTeamPosition = tempStanding.indexOf(homeTeamStanding.get());
+                int awayTeamPosition = tempStanding.indexOf(awayTeamStanding.get());
+
+                int diff = Math.abs(homeTeamPosition - awayTeamPosition);
+
+                if (diff == placementDiff) {
+                    matchedMatches++;
+                    result += match.getHomeScore() + match.getAwayScore();
+                }
+            }
+            updateStanding(tempStanding, match,
+                    tempStanding.stream().filter(p -> p.getTeamName().equals(match.getHomeTeam().getTeamName()))
+                            .findFirst(),
+                    tempStanding.stream().filter(p -> p.getTeamName().equals(match.getAwayTeam().getTeamName()))
+                            .findFirst());
+
+            tempStanding.sort((s1, s2) -> Integer.compare(s2.getPoints(), s1.getPoints()));
+        }
+
+        return matchedMatches > 0 ? result / matchedMatches : 0f;
+    }
+
+    private void updateStanding(List<Standing> result, SoccerMatch match, Optional<Standing> homeTeam,
+            Optional<Standing> awayTeam) {
+        int homeScore = match.getHomeScore();
+        int awayScore = match.getAwayScore();
+        if (homeScore > awayScore) {
+            homeTeam.ifPresentOrElse(ht -> {
+                ht.setWins(ht.getWins() + 1);
+                ht.setGamesPlayed(ht.getGamesPlayed() + 1);
+                ht.setPoints(ht.getPoints() + 3);
+            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 1, 0, 0, 3, 1)));
+
+            awayTeam.ifPresentOrElse(at -> {
+                at.setLosses(at.getLosses() + 1);
+                at.setGamesPlayed(at.getGamesPlayed() + 1);
+            }, () -> result.add(new Standing(match.getAwayTeam().getTeamName(), 0, 0, 1, 0, 1)));
+
+        } else if (homeScore == awayScore) {
+
+            homeTeam.ifPresentOrElse(ht -> {
+                ht.setDraws(ht.getDraws() + 1);
+                ht.setGamesPlayed(ht.getGamesPlayed() + 1);
+                ht.setPoints(ht.getPoints() + 1);
+            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 1, 0, 1, 1)));
+            awayTeam.ifPresentOrElse(at -> {
+                at.setDraws(at.getDraws() + 1);
+                at.setGamesPlayed(at.getGamesPlayed() + 1);
+                at.setPoints(at.getPoints() + 1);
+            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 1, 0, 1, 1)));
+        } else if (homeScore < awayScore) {
+            homeTeam.ifPresentOrElse(ht -> {
+                ht.setLosses(ht.getLosses() + 1);
+                ht.setGamesPlayed(ht.getGamesPlayed() + 1);
+            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 0, 1, 0, 1)));
+            awayTeam.ifPresentOrElse(at -> {
+                at.setWins(at.getWins() + 1);
+                at.setGamesPlayed(at.getGamesPlayed() + 1);
+                at.setPoints(at.getPoints() + 3);
+            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 1, 0, 0, 3, 1)));
+        }
+    }
+
+    @FXML
+    private void leagueSelected(ActionEvent event) {
+        updateStandingsTable();
+        if (getCountryIdFromSelector() > 0) {
+            List<SoccerMatch> matchesList = db.getMatches(db.getSportId(MainController.SOCCER),
+                    getCountryIdFromSelector(),
+                    db.getLeagueId(db.getSportId(MainController.SOCCER), getCountryIdFromSelector(),
+                            leagueSelector.getValue()),
+                    date.getValue().toString(), "ASC", true, false);
+
+            leagueInfo = GuiMysql.getInstance().getLeagueInfo(getLeagueIdFromSelector());
+            addMatchesToTable(matchesList);
+        }
+    }
+
+    private void addMatchesToTable(List<SoccerMatch> matchesList) {
+        ObservableList<Map<String, Object>> matches = FXCollections.<Map<String, Object>>observableArrayList();
+
+        for (final SoccerMatch soccerMatch : matchesList) {
+
+            final Map<String, Object> match = new HashMap<>();
+            match.put("homeTeam", soccerMatch.getHomeTeam().getTeamName());
+            match.put("awayTeam", soccerMatch.getAwayTeam().getTeamName());
+            match.put("odds1", soccerMatch.getOdds1());
+            match.put("oddsX", soccerMatch.getOddsX());
+            match.put("odds2", soccerMatch.getOdds2());
+
+            final List<Float> avgHomeTeamGoals = calculateAvgHomeScore(soccerMatch.getHomeTeam().getTeamId());
+            final List<Float> avgAwayTeamGoals = calculateAvgAwayScore(soccerMatch.getAwayTeam().getTeamId());
+
+            final List<Float> avgHomeTeamGoalsThisSeason = calculateAvgHomeScoreThisSeason(
+                    soccerMatch.getHomeTeam().getTeamId(),
+                    soccerMatch.getHomeTeam().getCountryId(), soccerMatch.getHomeTeam().getTeamLeagueId());
+            final List<Float> avgAwayTeamGoalsThisSeason = calculateAvgAwayScoreThisSeason(
+                    soccerMatch.getAwayTeam().getTeamId(),
+                    soccerMatch.getAwayTeam().getCountryId(), soccerMatch.getAwayTeam().getTeamLeagueId());
+
+            match.put("gameDate", soccerMatch.getGameDate().toString());
+            match.put("avgScoreHome", avgHomeTeamGoals.get(0));
+            match.put("avgConcededHome", avgHomeTeamGoals.get(1));
+            match.put("avgScoreAway", avgAwayTeamGoals.get(0));
+            match.put("avgConcededAway", avgAwayTeamGoals.get(1));
+
+            match.put("avgScoredHomeSeason", avgHomeTeamGoalsThisSeason.get(0));
+            match.put("avgConcededHomeSeason", avgHomeTeamGoalsThisSeason.get(1));
+
+            match.put("avgScoredAwaySeason", avgAwayTeamGoalsThisSeason.get(0));
+            match.put("avgConcededAwaySeason", avgAwayTeamGoalsThisSeason.get(1));
+
+            match.put("sumScoring", avgHomeTeamGoalsThisSeason.get(0) * avgAwayTeamGoalsThisSeason.get(1)
+                    + avgAwayTeamGoalsThisSeason.get(0) * avgHomeTeamGoalsThisSeason.get(1));
+
+            match.put("goalsHome",
+                    GuiMysql.getInstance().round(
+                            BigDecimal.valueOf(avgHomeTeamGoalsThisSeason.get(0) + avgAwayTeamGoalsThisSeason.get(1)),
+                            GuiMysql.getInstance().getIncrement(), RoundingMode.HALF_UP));
+            match.put("goalsAway",
+                    GuiMysql.getInstance().round(
+                            BigDecimal.valueOf(avgAwayTeamGoalsThisSeason.get(0) + avgHomeTeamGoalsThisSeason.get(1)),
+                            GuiMysql.getInstance().getIncrement(), RoundingMode.HALF_UP));
+
+            match.put("goalDiff",
+                    GuiMysql.getInstance()
+                            .round(BigDecimal
+                                    .valueOf((avgHomeTeamGoalsThisSeason.get(0) * avgAwayTeamGoalsThisSeason.get(1))
+                                            + (avgAwayTeamGoalsThisSeason.get(0) * avgHomeTeamGoalsThisSeason.get(1))),
+                                    GuiMysql.getInstance().getIncrement(),
+                                    RoundingMode.HALF_UP));
+            match.put("country", soccerMatch.getHomeTeam().getCountryName());
+
+            List<Float> leagueAvarages = GuiMysql.getInstance().getLeagueAvarages(getLeagueIdFromSelector(),
+                    getCountryIdFromSelector(),
+                    soccerMatch.getGameDate().format(DateTimeFormatter.BASIC_ISO_DATE));
+            match.put("positionAdjustment", getAvgGoalsWithSameDiff(soccerMatch.getHomeTeam().getCountryId(),
+                    soccerMatch.getHomeTeam().getTeamLeagueId(), MatchStatTabController.getInstance()
+                            .getTeamPositionDiff(soccerMatch.getHomeTeam().getTeamName(),
+                                    soccerMatch.getAwayTeam().getTeamName()))
+                    - (leagueAvarages.get(0) + leagueAvarages.get(1)));
+
+            match.put("newScoringTest",
+                    (avgHomeTeamGoalsThisSeason.get(0) * avgAwayTeamGoalsThisSeason.get(1)
+                            + avgAwayTeamGoalsThisSeason.get(0) * avgHomeTeamGoalsThisSeason.get(1))
+                            + ((avgHomeTeamGoals.get(0) * avgAwayTeamGoals.get(1))
+                                    + avgAwayTeamGoals.get(0) * avgHomeTeamGoals.get(1)) / 2);
+
+            SoccerMatchAnalysis analysis = new SoccerMatchAnalysis(soccerMatch);
+            if (leagueInfo == null || leagueInfo.getLeagueId() != soccerMatch.getHomeTeam().getTeamLeagueId()) {
+                leagueInfo = GuiMysql.getInstance().getLeagueInfo(soccerMatch.getHomeTeam().getTeamLeagueId());
+            }
+            if (leagueInfo != null) {
+                int homeWinsCount = analysis.winLossRatio(leagueInfo.getWinLossRatio(), true);
+                int awayWindCount = analysis.winLossRatio(leagueInfo.getWinLossRatio(), false);
+
+                int homeWinLossRatioCount = analysis.winLossRationHomeAndAway(true,
+                        leagueInfo.getWinLossRatioHomeAndAway());
+                int awayWinLossRatioCount = analysis.winLossRationHomeAndAway(false,
+                        leagueInfo.getWinLossRatioHomeAndAway());
+
+                int homeScoringTotal = analysis.scoringTotal(leagueInfo.getScoringTotal(), true);
+                int awayScoringTotal = analysis.scoringTotal(leagueInfo.getScoringTotal(), false);
+
+                int scoringDiffLastGames = analysis.getScoringDiffLastGames(leagueInfo.getScoringDiffLastGame());
+                int winsCountDiff = homeWinsCount - awayWindCount;
+                int winLossRatioDiff = homeWinLossRatioCount - awayWinLossRatioCount;
+                int scoringTotalDiff = homeScoringTotal - awayScoringTotal;
+
+                int testValue = 0;
+                if (scoringDiffLastGames < 0 && winsCountDiff < 0 && winLossRatioDiff < 0 && scoringTotalDiff < 0) {
+                    testValue = (scoringDiffLastGames + winsCountDiff + winLossRatioDiff + scoringTotalDiff) / 4;
+                    match.put("analysis", testValue);
+                } else if (scoringDiffLastGames > 0 && winsCountDiff > 0 && winLossRatioDiff > 0
+                        && scoringTotalDiff > 0) {
+                    testValue = (scoringDiffLastGames + winsCountDiff + winLossRatioDiff + scoringTotalDiff) / 4;
+                    match.put("analysis", testValue);
+                } else {
+                    match.put("analysis", "NoBet");
+                }
+            }
+
+            match.put(Constants.LEAGUE, soccerMatch.getHomeTeam().getTeamLeague());
+
+            match.put("id", soccerMatch.getMatchId());
+            match.put("homeScore", soccerMatch.getHomeScore());
+            match.put("awayScore", soccerMatch.getAwayScore());
+            final DecimalFormat df = new DecimalFormat("#.##");
+            df.setRoundingMode(RoundingMode.CEILING);
 
 //			final League leagueInfo = GuiMysql.getInstance().getLeagueInfo(soccerMatch.getHomeTeam().getTeamLeague());
 
-			matches.add(match);
-		}
-		matchTable.getItems().addAll(matches);
-	}
-
-	private List<Float> calculateAvgHomeScore(int teamId) {
-		return GuiMysql.getInstance().getAvgHomeScore(teamId);
-	}
-
-	private List<Float> calculateAvgAwayScore(int teamId) {
-		return GuiMysql.getInstance().getAvgAwayScore(teamId);
-	}
-
-	private List<Float> calculateAvgHomeScoreThisSeason(int teamId, int countryId, int leagueId) {
-		return GuiMysql.getInstance().getAvgHomeScoreThisSeason(teamId, countryId, leagueId, date.getValue().toString());
-	}
-
-	private List<Float> calculateAvgAwayScoreThisSeason(int teamId, int countryId, int leagueId) {
-		return GuiMysql.getInstance().getAvgAwayScoreThisSeason(teamId, countryId, leagueId, date.getValue().toString());
-	}
-
-	@FXML private void updateStatsTable() {
-		StatisticsTabController.getInstance().setOverUnderTable(getLeagueIdFromSelector(), date.getValue().toString());
-	}
-
-	@FXML private void updateStandingsTable() {
-		int countryId = getCountryIdFromSelector();
-		if (countryId > 0) {
-			String seasonFromDate = GuiMysql.getInstance().getSeasonFromDate(countryId, getLeagueIdFromSelector(), date.getValue().toString());
-			MatchStatTabController.getInstance().setLeagueStandingsTable(getLeagueIdFromSelector(), seasonFromDate, countryId,
-					date.getValue().toString());
-		}
-	}
-
-	@FXML private void getAllMatchesAtDate() {
-		String dateString = date.getValue().toString();
-
-		List<SoccerMatch> matches = GuiMysql.getInstance().getMatches(1, dateString, "ASC", true);
-		addMatchesToTable(matches);
-	}
-
-	@FXML private void ClearBetSlip() {
-		NumberOfGamesText.setText("0");
-		SystemsText.setText("");
-		ReslutsText.setText("");
-		bets.clear();
-	}
-
-	@FXML private void CheckBetSlip() {
-		Set<Set<betSystemDTO>> combinations = Sets.powerSet(bets);
-
-		Map<Integer, Integer> resultWins = new HashMap<>();
-		Map<Integer, Integer> resultLosses = new HashMap<>();
-
-		int setTest = 0;
-		double betAmount = 10.0d;
-
-		Map<Integer, Double> banks = new HashMap<>();
-
-		for (Set<betSystemDTO> set : combinations) {
-			if (set.size() > 0) {
-				System.out.println("Set " + ++setTest);
-				if (set.stream().allMatch(this::isWin)) {
-					resultWins.put(set.size(), resultWins.getOrDefault(set.size(), 0) + 1);
-					set.forEach(s -> {
-						System.out.println(
-								"WIN size " + set.size() + " GameId: " + s.getGameId() + " Score " + s.getHomeScore() + " - " + s.getAwayScore());
-						banks.put(set.size(), banks.getOrDefault(set.size(), 0d) + ((betAmount * Math.pow(1.15d, set.size())) - betAmount));
-					});
-
-				} else { // Set/combination lost
-					resultLosses.put(set.size(), resultLosses.getOrDefault(set.size(), 0) + 1);
-					set.forEach(s -> System.out.println("LOSS size " + set.size() + " GameId: " + s.getGameId() + " Score " + s.getHomeScore() + " - "
-							+ s.getAwayScore() + " type " + s.getBetType()));
-					banks.put(set.size(), banks.getOrDefault(set.size(), 0d) - betAmount);
-				}
-			}
-		}
-
-		StringBuilder losses = new StringBuilder();
-		StringBuilder wins = new StringBuilder();
-		StringBuilder bankString = new StringBuilder();
-
-		resultLosses.forEach((k, v) -> losses.append("Set size: " + k + " number of losses: " + v + "\n"));
-		resultWins.forEach((k, v) -> wins.append("Set size: " + k + " number of Wins: " + v + "\n"));
-		banks.forEach((k, v) -> bankString.append("Set " + k + " result " + v + "\n"));
-
-		System.out.println("Results \n WINS \n" + wins.toString() + "\nLOSSES\n" + losses.toString() + "\nBanks:" + bankString);
-	}
-
-	public boolean isWin(betSystemDTO bet) {
-		boolean result = false;
-		String betType = bet.getBetType();
-		String overUnder = betType.substring(0, 1);
-		float res = Float.valueOf(betType.substring(2, betType.length()));
-		int gameGoals = bet.getHomeScore() + bet.getAwayScore();
-
-		if (overUnder.equals("O")) {
-			if (gameGoals > res) {
-				result = true;
-			}
-		} else if (overUnder.equals("U")) {
-			if (gameGoals < res) {
-				result = true;
-			}
-		}
-		return result;
-	}
-
-	class betSystemDTO {
-		int gameId;
-		int homeScore;
-		int awayScore;
-		String betType;
-
-		public betSystemDTO(int gameId, int homeScore, int awayScore, String betType) {
-			super();
-			this.gameId = gameId;
-			this.homeScore = homeScore;
-			this.awayScore = awayScore;
-			this.betType = betType;
-		}
-
-		public int getGameId() {
-			return gameId;
-		}
-
-		public void setGameId(int gameId) {
-			this.gameId = gameId;
-		}
-
-		public int getHomeScore() {
-			return homeScore;
-		}
-
-		public void setHomeScore(int homeScore) {
-			this.homeScore = homeScore;
-		}
-
-		public int getAwayScore() {
-			return awayScore;
-		}
-
-		public void setAwayScore(int awayScore) {
-			this.awayScore = awayScore;
-		}
-
-		public String getBetType() {
-			return betType;
-		}
-
-		public void setBetType(String betType) {
-			this.betType = betType;
-		}
-
-	}
+            matches.add(match);
+        }
+        matchTable.getItems().addAll(matches);
+    }
+
+    private List<Float> calculateAvgHomeScore(int teamId) {
+        return GuiMysql.getInstance().getAvgHomeScore(teamId);
+    }
+
+    private List<Float> calculateAvgAwayScore(int teamId) {
+        return GuiMysql.getInstance().getAvgAwayScore(teamId);
+    }
+
+    private List<Float> calculateAvgHomeScoreThisSeason(int teamId, int countryId, int leagueId) {
+        return GuiMysql.getInstance().getAvgHomeScoreThisSeason(teamId, countryId, leagueId,
+                date.getValue().toString());
+    }
+
+    private List<Float> calculateAvgAwayScoreThisSeason(int teamId, int countryId, int leagueId) {
+        return GuiMysql.getInstance().getAvgAwayScoreThisSeason(teamId, countryId, leagueId,
+                date.getValue().toString());
+    }
+
+    @FXML
+    private void updateStatsTable() {
+        StatisticsTabController.getInstance().setOverUnderTable(getLeagueIdFromSelector(), date.getValue().toString());
+    }
+
+    @FXML
+    private void updateStandingsTable() {
+        int countryId = getCountryIdFromSelector();
+        if (countryId > 0) {
+            String seasonFromDate = GuiMysql.getInstance().getSeasonFromDate(countryId, getLeagueIdFromSelector(),
+                    date.getValue().toString());
+            MatchStatTabController.getInstance().setLeagueStandingsTable(getLeagueIdFromSelector(), seasonFromDate,
+                    countryId,
+                    date.getValue().toString());
+        }
+    }
+
+    @FXML
+    private void getAllMatchesAtDate() {
+        String dateString = date.getValue().toString();
+
+        List<SoccerMatch> matches = GuiMysql.getInstance().getMatches(1, dateString, "ASC", true);
+        addMatchesToTable(matches);
+    }
+
+    @FXML
+    private void ClearBetSlip() {
+        NumberOfGamesText.setText("0");
+        SystemsText.setText("");
+        ReslutsText.setText("");
+        bets.clear();
+    }
+
+    @FXML
+    private void CheckBetSlip() {
+        Set<Set<betSystemDTO>> combinations = Sets.powerSet(bets);
+
+        Map<Integer, Integer> resultWins = new HashMap<>();
+        Map<Integer, Integer> resultLosses = new HashMap<>();
+
+        int setTest = 0;
+        double betAmount = 10.0d;
+
+        Map<Integer, Double> banks = new HashMap<>();
+
+        for (Set<betSystemDTO> set : combinations) {
+            if (set.size() > 0) {
+                System.out.println("Set " + ++setTest);
+                if (set.stream().allMatch(this::isWin)) {
+                    resultWins.put(set.size(), resultWins.getOrDefault(set.size(), 0) + 1);
+                    set.forEach(s -> {
+                        System.out.println(
+                                "WIN size " + set.size() + " GameId: " + s.getGameId() + " Score " + s.getHomeScore()
+                                        + " - " + s.getAwayScore());
+                        banks.put(set.size(), banks.getOrDefault(set.size(), 0d)
+                                + ((betAmount * Math.pow(1.15d, set.size())) - betAmount));
+                    });
+
+                } else { // Set/combination lost
+                    resultLosses.put(set.size(), resultLosses.getOrDefault(set.size(), 0) + 1);
+                    set.forEach(s -> System.out.println("LOSS size " + set.size() + " GameId: " + s.getGameId()
+                            + " Score " + s.getHomeScore() + " - "
+                            + s.getAwayScore() + " type " + s.getBetType()));
+                    banks.put(set.size(), banks.getOrDefault(set.size(), 0d) - betAmount);
+                }
+            }
+        }
+
+        StringBuilder losses = new StringBuilder();
+        StringBuilder wins = new StringBuilder();
+        StringBuilder bankString = new StringBuilder();
+
+        resultLosses.forEach((k, v) -> losses.append("Set size: " + k + " number of losses: " + v + "\n"));
+        resultWins.forEach((k, v) -> wins.append("Set size: " + k + " number of Wins: " + v + "\n"));
+        banks.forEach((k, v) -> bankString.append("Set " + k + " result " + v + "\n"));
+
+        System.out.println(
+                "Results \n WINS \n" + wins.toString() + "\nLOSSES\n" + losses.toString() + "\nBanks:" + bankString);
+    }
+
+    public boolean isWin(betSystemDTO bet) {
+        boolean result = false;
+        String betType = bet.getBetType();
+        String overUnder = betType.substring(0, 1);
+        float res = Float.valueOf(betType.substring(2, betType.length()));
+        int gameGoals = bet.getHomeScore() + bet.getAwayScore();
+
+        if (overUnder.equals("O")) {
+            if (gameGoals > res) {
+                result = true;
+            }
+        } else if (overUnder.equals("U")) {
+            if (gameGoals < res) {
+                result = true;
+            }
+        }
+        return result;
+    }
+
+    class betSystemDTO {
+        int gameId;
+        int homeScore;
+        int awayScore;
+        String betType;
+
+        public betSystemDTO(int gameId, int homeScore, int awayScore, String betType) {
+            super();
+            this.gameId = gameId;
+            this.homeScore = homeScore;
+            this.awayScore = awayScore;
+            this.betType = betType;
+        }
+
+        public int getGameId() {
+            return gameId;
+        }
+
+        public void setGameId(int gameId) {
+            this.gameId = gameId;
+        }
+
+        public int getHomeScore() {
+            return homeScore;
+        }
+
+        public void setHomeScore(int homeScore) {
+            this.homeScore = homeScore;
+        }
+
+        public int getAwayScore() {
+            return awayScore;
+        }
+
+        public void setAwayScore(int awayScore) {
+            this.awayScore = awayScore;
+        }
+
+        public String getBetType() {
+            return betType;
+        }
+
+        public void setBetType(String betType) {
+            this.betType = betType;
+        }
+
+    }
 }

+ 361 - 248
OddsJavaFx/src/controllers/TestsController.java

@@ -25,286 +25,399 @@ import javafx.scene.control.DatePicker;
 import javafx.scene.control.ScrollPane;
 import javafx.scene.control.TextField;
 import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
 import parser.OddsPortal;
 import tests.AddedScoringTest;
+import tests.AnalysisBettTester;
 import tests.AwayTeamWinTest;
 import tests.AwayTests2;
+import tests.BetOnDifference;
 import tests.DrawTests2;
+import tests.FibonacciDrawTest;
 import tests.HomeDrawAwayTest;
 import tests.HomeTeamWinTest;
 import tests.HomeTests2;
 import tests.LastResultsTest;
 import tests.LeagueTablePositionTest;
 import tests.PrioCountriesAll;
+import tests.RelevanceTest;
 import tests.TestClass;
 import tests.recalcTest;
 
 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;
-	@FXML Button homeTest;
-	@FXML Button drawTest;
-	@FXML Button awayTest;
-	@FXML Button homeDrawAwayTest;
-	@FXML Button homeTeamTest;
-	@FXML Button awayTeamTest;
-	@FXML Button addedScoreTest;
-	@FXML Button recalcTest;
-
-	ObservableList<String> countries = FXCollections.observableArrayList();
-	ObservableList<String> leagues = FXCollections.observableArrayList();
-
-	private final List<SimpleEntry<Integer, String>> countriesList = Lists.newArrayList();
-	private List<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) -> getResults.setDisable(newValue.isAfter(LocalDate.now())));
-
-		countrySelector.setItems(countries);
-		leagueSelector.setItems(leagues);
-		testSettingsPanel.setVisible(false);
-	}
-
-	@FXML private void getResults() {
-		countriesList.clear();
-		leaguesList.clear();
-		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() {
-		Optional<SimpleEntry<Integer, String>> o = countriesList.stream().filter(p -> p.getValue().equals(countrySelector.getValue())).findFirst();
-		return o.isPresent() ? o.get().getKey() : null;
-	}
-
-	private Integer getLeagueIdFromSelector() {
-		Optional<SimpleEntry<Integer, String>> o = leaguesList.stream().filter(p -> p.getValue().equals(leagueSelector.getValue())).findFirst();
-		return o.isPresent() ? o.get().getKey() : null;
-	}
-
-	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(MainController.SPORT);
-		}
-
-		return mSportId;
-	}
-
-	@FXML private void leagueSelected(ActionEvent event) {
-
-		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() {
-
-		final String betLevel = getBetLevel();
-		final String betM = getBetMargin();
-		final String startBank = getStartingBank();
-		final String lookBackVal = getLookback();
-
-		final TestClass test = new LastResultsTest();
-		test.setup(date.getValue().toString(), Float.valueOf(startBank), Float.valueOf(betLevel), Float.valueOf(betM), Integer.valueOf(lookBackVal),
-				mSportId, getCountryIdFromSelector(), getLeagueIdFromSelector());
-		test.runTest();
-	}
-
-	private String getLookback() {
-		return Strings.isNullOrEmpty(lookBack.getText()) ? lookBack.getPromptText() : lookBack.getText();
-	}
-
-	private String getStartingBank() {
-		return Strings.isNullOrEmpty(startingBank.getText()) ? startingBank.getPromptText() : startingBank.getText();
-	}
-
-	private String getBetMargin() {
-		String betM = Strings.isNullOrEmpty(betMargin.getText()) ? betMargin.getPromptText() : betMargin.getText();
-		betM = betM.replace("%", "").trim();
-		return betM;
-	}
-
-	private String getBetLevel() {
-		String betLevel = Strings.isNullOrEmpty(bettingLevel.getText()) ? bettingLevel.getPromptText() : bettingLevel.getText();
-		betLevel = betLevel.replace("%", "").trim();
-		return betLevel;
-	}
-
-	@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.parseInt(years[0]);
-			int lastYear = Integer.parseInt(years[1]);
-			firstYear--;
-			lastYear--;
-			nextParseYear = firstYear + "-" + lastYear;
-		} else if (lastParsedYear.length() == 4) {
-			Integer val = Integer.valueOf(lastParsedYear);
-			val--;
-			nextParseYear = String.valueOf(val);
-		} else {
-			Log.getLog().info("Fail to get More league info for %s", lastParsedYear);
-			return;
-		}
+    @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;
+    @FXML
+    Button homeTest;
+    @FXML
+    Button drawTest;
+    @FXML
+    Button awayTest;
+    @FXML
+    Button homeDrawAwayTest;
+    @FXML
+    Button homeTeamTest;
+    @FXML
+    Button awayTeamTest;
+    @FXML
+    Button addedScoreTest;
+    @FXML
+    Button recalcTest;
+    @FXML
+    Button fibonacciDrawTest;
+
+    @FXML
+    VBox testPanelVBox;
+
+    ObservableList<String> countries = FXCollections.observableArrayList();
+    ObservableList<String> leagues = FXCollections.observableArrayList();
+
+    private final List<SimpleEntry<Integer, String>> countriesList = Lists.newArrayList();
+    private List<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);
+
+        VBox.setVgrow(testPanelVBox, Priority.ALWAYS);
+
+        date.valueProperty()
+                .addListener((ov, oldValue, newValue) -> getResults.setDisable(newValue.isAfter(LocalDate.now())));
+
+        countrySelector.setItems(countries);
+        leagueSelector.setItems(leagues);
+        testSettingsPanel.setVisible(false);
+    }
+
+    @FXML
+    private void getResults() {
+        countriesList.clear();
+        leaguesList.clear();
+        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() {
+        Optional<SimpleEntry<Integer, String>> o = countriesList.stream()
+                .filter(p -> p.getValue().equals(countrySelector.getValue())).findFirst();
+        return o.isPresent() ? o.get().getKey() : null;
+    }
+
+    private Integer getLeagueIdFromSelector() {
+        Optional<SimpleEntry<Integer, String>> o = leaguesList.stream()
+                .filter(p -> p.getValue().equals(leagueSelector.getValue())).findFirst();
+        return o.isPresent() ? o.get().getKey() : null;
+    }
+
+    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(MainController.SPORT);
+        }
+
+        return mSportId;
+    }
+
+    @FXML
+    private void leagueSelected(ActionEvent event) {
+
+        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() {
+
+        final String betLevel = getBetLevel();
+        final String betM = getBetMargin();
+        final String startBank = getStartingBank();
+        final String lookBackVal = getLookback();
+
+        final TestClass test = new LastResultsTest();
+        test.setup(date.getValue().toString(), Float.valueOf(startBank), Float.valueOf(betLevel), Float.valueOf(betM),
+                Integer.valueOf(lookBackVal),
+                mSportId, getCountryIdFromSelector(), getLeagueIdFromSelector());
+        test.runTest();
+    }
+
+    private String getLookback() {
+        return Strings.isNullOrEmpty(lookBack.getText()) ? lookBack.getPromptText() : lookBack.getText();
+    }
+
+    private String getStartingBank() {
+        return Strings.isNullOrEmpty(startingBank.getText()) ? startingBank.getPromptText() : startingBank.getText();
+    }
+
+    private String getBetMargin() {
+        String betM = Strings.isNullOrEmpty(betMargin.getText()) ? betMargin.getPromptText() : betMargin.getText();
+        betM = betM.replace("%", "").trim();
+        return betM;
+    }
+
+    private String getBetLevel() {
+        String betLevel = Strings.isNullOrEmpty(bettingLevel.getText()) ? bettingLevel.getPromptText()
+                : bettingLevel.getText();
+        betLevel = betLevel.replace("%", "").trim();
+        return betLevel;
+    }
+
+    @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.parseInt(years[0]);
+            int lastYear = Integer.parseInt(years[1]);
+            firstYear--;
+            lastYear--;
+            nextParseYear = firstYear + "-" + lastYear;
+        } else if (lastParsedYear.length() == 4) {
+            Integer val = Integer.valueOf(lastParsedYear);
+            val--;
+            nextParseYear = String.valueOf(val);
+        } else {
+            Log.getLog().info("Fail to get More league info for %s", 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();
+    }
+
+    @FXML
+    private void homeTestAction() {
+        final HomeTests2 test = new HomeTests2();
+
+        test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()),
+                Integer.valueOf(getLookback()),
+                1, getCountryIdFromSelector(), getLeagueIdFromSelector());
+
+        test.runTest();
+    }
+
+    @FXML
+    private void drawTestAction() {
+        final DrawTests2 test = new DrawTests2();
+
+        test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()),
+                Integer.valueOf(getLookback()),
+                1, getCountryIdFromSelector(), getLeagueIdFromSelector());
+
+        test.runTest();
+    }
+
+    @FXML
+    private void awayTestAction() {
+        final AwayTests2 test = new AwayTests2();
+
+        test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()),
+                Integer.valueOf(getLookback()),
+                1, getCountryIdFromSelector(), getLeagueIdFromSelector());
+
+        test.runTest();
+    }
+
+    @FXML
+    private void homeDrawAwayTestAction() {
+        final HomeDrawAwayTest test = new HomeDrawAwayTest();
+
+        test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()),
+                Integer.valueOf(getLookback()),
+                1, getCountryIdFromSelector(), getLeagueIdFromSelector());
+
+        test.runTest();
+    }
+
+    @FXML
+    private void homeTeamTestAction() {
+        final HomeTeamWinTest test = new HomeTeamWinTest();
+
+        test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()),
+                Integer.valueOf(getLookback()),
+                1, getCountryIdFromSelector(), getLeagueIdFromSelector());
+
+        test.runTest();
+    }
+
+    @FXML
+    private void awayTeamTestAction() {
+        final AwayTeamWinTest test = new AwayTeamWinTest();
+
+        test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()),
+                Integer.valueOf(getLookback()),
+                1, getCountryIdFromSelector(), getLeagueIdFromSelector());
+
+        test.runTest();
+    }
+
+    @FXML
+    private void addedScoreTestAction() {
+        final AddedScoringTest test = new AddedScoringTest();
+
+        test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()),
+                Integer.valueOf(getLookback()),
+                1, getCountryIdFromSelector(), getLeagueIdFromSelector());
 
-		final String country = countrySelector.getValue().trim();
-		final String league = leagueSelector.getValue().trim();
+        test.runTest();
+    }
 
-		final OddsPortal op = new OddsPortal();
-		op.getHistoricMatches("soccer", country, league, nextParseYear);
-	}
+    @FXML
+    private void recalcTestAction() {
+        final recalcTest test = new recalcTest();
 
-	@FXML private void topLeaguesTestAction() {
-		final PrioCountriesAll prioCountriesAll = new PrioCountriesAll();
-		prioCountriesAll.runTest();
-	}
+        test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()),
+                Integer.valueOf(getLookback()),
+                1, getCountryIdFromSelector(), getLeagueIdFromSelector());
 
-	@FXML private void homeTestAction() {
-		final HomeTests2 test = new HomeTests2();
+        test.runTest();
+    }
 
-		test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()), Integer.valueOf(getLookback()),
-				1, getCountryIdFromSelector(), getLeagueIdFromSelector());
-
-		test.runTest();
-	}
-
-	@FXML private void drawTestAction() {
-		final DrawTests2 test = new DrawTests2();
+    @FXML
+    private void standingsTest() {
+        final TestClass test = new LeagueTablePositionTest();
 
-		test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()), Integer.valueOf(getLookback()),
-				1, getCountryIdFromSelector(), getLeagueIdFromSelector());
+        test.runTest();
+    }
 
-		test.runTest();
-	}
-
-	@FXML private void awayTestAction() {
-		final AwayTests2 test = new AwayTests2();
+    @FXML
+    private void fibonacciDrawTestAction() {
+        final TestClass test = new FibonacciDrawTest();
 
-		test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()), Integer.valueOf(getLookback()),
-				1, getCountryIdFromSelector(), getLeagueIdFromSelector());
+        test.setup(date.getValue().toString(), Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), -1.0f,
+                -1, GuiMysql.getInstance().getSportId("soccer"),
+                getCountryIdFromSelector(), getLeagueIdFromSelector());
 
-		test.runTest();
-	}
+        test.runTest();
+    }
 
-	@FXML private void homeDrawAwayTestAction() {
-		final HomeDrawAwayTest test = new HomeDrawAwayTest();
+    @FXML
+    private void goalDiffTest() {
+        final TestClass test = new BetOnDifference();
 
-		test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()), Integer.valueOf(getLookback()),
-				1, getCountryIdFromSelector(), getLeagueIdFromSelector());
+        test.setup(date.getValue().toString(), Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), -1.0f,
+                -1, GuiMysql.getInstance().getSportId("soccer"),
+                getCountryIdFromSelector(), getLeagueIdFromSelector());
 
-		test.runTest();
-	}
+        test.runTest();
+    }
 
-	@FXML private void homeTeamTestAction() {
-		final HomeTeamWinTest test = new HomeTeamWinTest();
+    @FXML
+    private void relevanceTest() {
+        final TestClass test = new RelevanceTest();
 
-		test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()), Integer.valueOf(getLookback()),
-				1, getCountryIdFromSelector(), getLeagueIdFromSelector());
+        test.setup(date.getValue().toString(), Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), -1.0f,
+                -1, GuiMysql.getInstance().getSportId("soccer"),
+                getCountryIdFromSelector(), getLeagueIdFromSelector());
 
-		test.runTest();
-	}
+        test.runTest();
+    }
 
-	@FXML private void awayTeamTestAction() {
-		final AwayTeamWinTest test = new AwayTeamWinTest();
+    @FXML
+    private void analysisTets() {
+        final TestClass test = new AnalysisBettTester();
 
-		test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()), Integer.valueOf(getLookback()),
-				1, getCountryIdFromSelector(), getLeagueIdFromSelector());
+        test.setup(date.getValue().toString(), Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), -1.0f,
+                -1, GuiMysql.getInstance().getSportId("soccer"),
+                getCountryIdFromSelector(), getLeagueIdFromSelector());
 
-		test.runTest();
-	}
-
-	@FXML private void addedScoreTestAction() {
-		final AddedScoringTest test = new AddedScoringTest();
-
-		test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()), Integer.valueOf(getLookback()),
-				1, getCountryIdFromSelector(), getLeagueIdFromSelector());
-
-		test.runTest();
-	}
-
-	@FXML private void recalcTestAction() {
-		final recalcTest test = new recalcTest();
-
-		test.setup("", Float.valueOf(getStartingBank()), Float.valueOf(getBetLevel()), Float.valueOf(getBetMargin()), Integer.valueOf(getLookback()),
-				1, getCountryIdFromSelector(), getLeagueIdFromSelector());
-
-		test.runTest();
-	}
-
-	@FXML private void standingsTest() {
-		final LeagueTablePositionTest test = new LeagueTablePositionTest();
-
-		test.runTest();
-	}
+        test.runTest();
+    }
 }

+ 1170 - 965
OddsJavaFx/src/data/GuiMysql.java

@@ -31,972 +31,1177 @@ import objects.SoccerMatch;
 import objects.Team;
 import objects.TeamResults;
 import objects.TeamStanding;
+import objects.bets.Bet;
+import objects.bets.Bet.Status;
 
 public class GuiMysql extends Mysql {
 
-	private static final BigDecimal INCREMENT = BigDecimal.valueOf(0.2);
-	private static final GuiMysql instance = new GuiMysql();
-	private final Connection conn;
-
-	protected GuiMysql() {
-		super();
-		conn = this.getConnection();
-	}
-
-	public static GuiMysql getInstance() {
-		return instance;
-	}
-
-	public List<SimpleEntry<Integer, String>> getSports() {
-
-		final ArrayList<AbstractMap.SimpleEntry<Integer, String>> sports = Lists.newArrayList();
-		final String sql = "SELECT id, name FROM Sport";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				final SimpleEntry<Integer, String> entry = new SimpleEntry<>(rs.getInt(Constants.ID), rs.getString("name"));
-				sports.add(entry);
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return sports;
-	}
-
-	public List<SimpleEntry<Integer, String>> getCountries() {
-
-		final ArrayList<AbstractMap.SimpleEntry<Integer, String>> countries = Lists.newArrayList();
-		final String sql = "SELECT id, name FROM Country";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				final SimpleEntry<Integer, String> entry = new SimpleEntry<>(rs.getInt(Constants.ID), rs.getString("name"));
-				countries.add(entry);
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-		return countries;
-	}
-
-	public List<SimpleEntry<Integer, String>> getLeagues(int sportId, int countryId) {
-
-		final ArrayList<AbstractMap.SimpleEntry<Integer, String>> leagues = Lists.newArrayList();
-		final String sql = "SELECT id, name FROM League WHERE sportId = ? AND countryId = ? ORDER BY name ASC";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, sportId);
-			stat.setInt(2, countryId);
-
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				final SimpleEntry<Integer, String> entry = new SimpleEntry<>(rs.getInt(Constants.ID), rs.getString("name"));
-				leagues.add(entry);
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-		return leagues;
-	}
-
-	public List<SoccerMatch> getUpcomingMatches(String sportResultTable) {
-		final ArrayList<SoccerMatch> matches = Lists.newArrayList();
-		final String dateSql;
-		dateSql = " AND DATE(gameDate) >= DATE(now())";
-
-		final String sql = "SELECT res.id, homeTeamId, awayTeamId, 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.prio as prio " + "FROM " + sportResultTable + " as res " + "Join Team as hTeam ON res.homeTeamId = hTeam.id "
-				+ "Join Team as aTeam ON res.awayTeamId = aTeam.id " + "Join League as league ON res.leagueId = league.id "
-				+ "Join Country as country ON res.countryId = country.id " + "WHERE homeScore = -1 " + dateSql
-				+ "AND league.name NOT LIKE '%cup%' AND league.name NOT LIKE '%group%' AND league.prio = 1 "
-				+ "ORDER BY country.prio DESC, country.name ASC";
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-
-			final ResultSet rs = stat.executeQuery();
-			while (rs.next()) {
-				final SoccerMatch sm = new SoccerMatch();
-				final Team homeTeam = new Team();
-				final Team awayTeam = new Team();
-
-				homeTeam.setTeamId(rs.getInt(Constants.HOME_TEAM_ID));
-				awayTeam.setTeamId(rs.getInt(Constants.AWAY_TEAM_ID));
-				homeTeam.setTeamName(rs.getString(Constants.HOME_TEAM_NAME));
-				awayTeam.setTeamName(rs.getString(Constants.AWAY_TEAM_NAME));
-				homeTeam.setTeamLeagueId(rs.getInt(Constants.LEAGUE_ID));
-				awayTeam.setTeamLeagueId(rs.getInt(Constants.LEAGUE_ID));
-				homeTeam.setTeamLeague(rs.getString(Constants.LEAGUE_NAME));
-				awayTeam.setTeamLeague(rs.getString(Constants.LEAGUE_NAME));
-				homeTeam.setCountryId(rs.getInt(Constants.COUNTRY_ID));
-				awayTeam.setCountryId(rs.getInt(Constants.COUNTRY_ID));
-				homeTeam.setCountryName(rs.getString(Constants.COUNTRY_NAME));
-				awayTeam.setCountryName(rs.getString(Constants.COUNTRY_NAME));
-
-				sm.setAwayScore(rs.getInt(Constants.AWAY_SCORE));
-				sm.setHomeScore(rs.getInt(Constants.HOME_SCORE));
-				sm.setHomeTeam(homeTeam);
-				sm.setAwayTeam(awayTeam);
-				sm.setMatchId(rs.getInt(Constants.ID));
-				sm.setOdds1(rs.getFloat(Constants.ODDS_1));
-				sm.setOddsX(rs.getFloat(Constants.ODDS_X));
-				sm.setOdds2(rs.getFloat(Constants.ODDS_2));
-				sm.setGameDate(LocalDateTime.parse(rs.getString(Constants.GAME_DATE)));
-				sm.setCountryPrio(rs.getBoolean("prio"));
-
-				matches.add(sm);
-			}
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return matches;
-	}
-
-	public List<Float> getAvgHomeScore(int teamId) {
-		final ArrayList<Float> returnValue = Lists.newArrayList();
-		final String sql = "SELECT AVG(homeScore) as avgScored, AVG(awayScore) as avgConceded FROM SoccerResults WHERE homeScore != -1 AND homeTeamId = ?";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, teamId);
-
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				returnValue.add(rs.getFloat("avgScored"));
-				returnValue.add(rs.getFloat("avgConceded"));
-			}
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return returnValue;
-	}
-
-	public List<Float> getAvgHomeScoreThisSeason(int teamId, int countryId, int leagueId) {
-		return getAvgHomeScoreThisSeason(teamId, countryId, leagueId, "");
-	}
-
-	public List<Float> getAvgHomeScoreThisSeason(int teamId, int countryId, int leagueId, String gameDate) {
-		final ArrayList<Float> returnValue = Lists.newArrayList();
-		final String sql = "SELECT AVG(homeScore) as avgScoredSeason, AVG(awayScore) as avgConcededSeason FROM SoccerResults WHERE homeScore != -1 AND homeTeamId = ? AND season = ? AND DATE(gameDate) < ? ORDER BY gameDate ASC";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, teamId);
-
-			if (Strings.isNullOrEmpty(gameDate) || getSeasonFromDate(countryId, leagueId, gameDate).equals(getLastSeason(countryId, leagueId))) {
-				stat.setString(2, getLastSeason(countryId, leagueId));
-			} else {
-				String seasonFromDate = getSeasonFromDate(countryId, leagueId, gameDate);
-				stat.setString(2, seasonFromDate);
-			}
-			if (Strings.isNullOrEmpty(gameDate)) {
-				stat.setString(3, new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
-			} else {
-				stat.setString(3, gameDate);
-			}
-
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				returnValue.add(rs.getFloat("avgScoredSeason"));
-				returnValue.add(rs.getFloat("avgConcededSeason"));
-			}
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return returnValue;
-	}
-
-	public String getSeasonFromDate(int countryId, int leagueId, String gameDate) {
-		String sql = "SELECT season FROM SoccerResults WHERE DATE(gameDate) = ? AND countryId = ? AND leagueId = ? LIMIT 1";
-		String returnValue = "";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			if (Strings.isNullOrEmpty(gameDate)) {
-				stat.setString(1, new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
-			} else {
-				stat.setString(1, gameDate);
-			}
-			stat.setInt(2, countryId);
-			stat.setInt(3, leagueId);
-
-			ResultSet rs = stat.executeQuery();
-			while (rs.next()) {
-				returnValue = rs.getString("season");
-			}
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-		return returnValue;
-	}
-
-	public List<Float> getAvgAwayScore(int teamId) {
-		final ArrayList<Float> returnValue = Lists.newArrayList();
-		final String sql = "SELECT AVG(homeScore) as avgConceded, AVG(awayScore) as avgScored FROM SoccerResults WHERE awayScore != -1 AND awayTeamId = ?";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, teamId);
-
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				returnValue.add(rs.getFloat("avgScored"));
-				returnValue.add(rs.getFloat("avgConceded"));
-			}
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return returnValue;
-	}
-
-	public List<Float> getAvgAwayScoreThisSeason(int teamId, int countryId, int leagueId) {
-		return getAvgAwayScoreThisSeason(teamId, countryId, leagueId, "");
-	}
-
-	public List<Float> getAvgAwayScoreThisSeason(int teamId, int countryId, int leagueId, String gameDate) {
-		final ArrayList<Float> returnValue = Lists.newArrayList();
-		final String sql = "SELECT AVG(homeScore) as avgConcededSeason, AVG(awayScore) as avgScoredSeason FROM SoccerResults WHERE awayScore != -1 AND awayTeamId = ? AND season = ? AND DATE(gameDate) < ? ORDER BY gameDate ASC";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, teamId);
-			if (Strings.isNullOrEmpty(gameDate) || getSeasonFromDate(countryId, leagueId, gameDate).equals(getLastSeason(countryId, leagueId))) {
-				stat.setString(2, getLastSeason(countryId, leagueId));
-			} else {
-				String seasonFromDate = getSeasonFromDate(countryId, leagueId, gameDate);
-				stat.setString(2, seasonFromDate);
-			}
-			if (Strings.isNullOrEmpty(gameDate)) {
-				stat.setString(3, new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
-			} else {
-				stat.setString(3, gameDate);
-			}
-
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				returnValue.add(rs.getFloat("avgScoredSeason"));
-				returnValue.add(rs.getFloat("avgConcededSeason"));
-			}
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return returnValue;
-	}
-
-	public List<Float> getLeagueAvarages(int leagueId, int countryId, String gameDate) {
-		final ArrayList<Float> returnValue = Lists.newArrayList();
-		final String sql = "SELECT AVG(homeScore) avgHomeScore, AVG(awayScore) as avgAwayScore"
-				+ " FROM SoccerResults WHERE leagueId = ? AND countryId = ? AND DATE(gameDate) < DATE(?)";
-
-		try (PreparedStatement stat = conn.prepareStatement(sql);) {
-			stat.setInt(1, leagueId);
-			stat.setInt(2, countryId);
-			stat.setString(3, gameDate);
-
-			final ResultSet rs = stat.executeQuery();
-			while (rs.next()) {
-				returnValue.add(rs.getFloat("avgHomeScore"));
-				returnValue.add(rs.getFloat("avgAwayScore"));
-			}
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return returnValue;
-	}
-
-	public Map<Integer, Integer> getGoalAvgThisSeason(int leagueId, int countryId) {
-		Map<Integer, Integer> returnValue = new HashMap<>();
-		final String goalsSql = "SELECT (homeScore + awayScore) as totalGoals, count(*) as count FROM SoccerResults  WHERE leagueId = ? AND countryId = ? AND season = ? GROUP BY totalGoals ORDER BY totalGoals asc";
-		try (PreparedStatement goalStmt = conn.prepareStatement(goalsSql)) {
-			goalStmt.setInt(1, leagueId);
-			goalStmt.setInt(2, countryId);
-			goalStmt.setString(3, getLastSeason(countryId, leagueId));
-
-			final ResultSet goalRs = goalStmt.executeQuery();
-
-			while (goalRs.next()) {
-				int tg = goalRs.getInt("totalGoals");
-				if (tg < 0) {
-					continue;
-				}
-				int numGoals = goalRs.getInt("count");
-
-				returnValue.put(tg, numGoals);
-			}
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-		return returnValue;
-	}
-
-	public List<OverUnder> getStatsOverUnder(int leagueId) {
-		return getStatsOverUnder(leagueId, "");
-	}
-
-	private List<String> getAllSeasons(int leagueId) {
-		List<String> returnValue = new ArrayList<String>();
-		String sql = "SELECT distinct(season) FROM SoccerResults WHERE leagueId = ?";
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, leagueId);
-
-			ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				returnValue.add(rs.getString("season"));
-			}
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-		return returnValue;
-	}
-
-	public List<OverUnder> getStatsOverUnder(int leagueId, String gameDate) {
-
-		final DecimalFormat df = new DecimalFormat("##.##");
-		df.setRoundingMode(RoundingMode.HALF_DOWN);
-		final ArrayList<OverUnder> result = Lists.newArrayList();
-
-		final String sql = "SELECT ((sHome.avgScored * sAway.avgConceded) + (sAway.avgScored * sHome.avgConceded)) as diff, (homeScore + awayScore) as numGoals "
-				+ "FROM SoccerResults "
-				+ "INNER JOIN (SELECT homeTeamId, AVG(homeScore) as avgScored, AVG(awayScore) as avgConceded FROM SoccerResults WHERE homeScore != -1 AND homeTeamId = SoccerResults.homeTeamId AND DATE(gameDate) < ? AND season = ? AND leagueId = ? GROUP BY homeTeamId) as sHome ON SoccerResults.homeTeamId = sHome.homeTeamId "
-				+ "INNER JOIN (SELECT awayTeamId, AVG(homeScore) as avgConceded, AVG(awayScore) as avgScored FROM SoccerResults WHERE awayScore != -1 AND awayTeamId = SoccerResults.awayTeamId AND DATE(gameDate) < ? AND season = ? AND leagueId = ? GROUP BY awayTeamId) as sAway ON SoccerResults.awayTeamId = sAway.awayTeamId "
-				+ "WHERE homeScore != -1 AND awayScore != -1 AND leagueId = ? AND DATE(gameDate) < ? AND season = ? " + "ORDER BY diff ASC";
-		List<String> allSeasons = getAllSeasons(leagueId);
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			final String dateString;
-			if (Strings.isNullOrEmpty(gameDate)) {
-				dateString = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
-			} else {
-				dateString = gameDate;
-			}
-			for (String season : allSeasons) {
-				stat.setString(1, dateString);
-				stat.setString(2, season);
-				stat.setInt(3, leagueId);
-				stat.setString(4, dateString);
-				stat.setString(5, season);
-				stat.setInt(6, leagueId);
-
-				stat.setInt(7, leagueId);
-				stat.setString(8, dateString);
-				stat.setString(9, season);
-
-				final ResultSet rs = stat.executeQuery();
-
-				while (rs.next()) {
-					final float diff = rs.getFloat("diff");
-					final int numGoals = rs.getInt("numGoals");
-					final Float formatted = round(BigDecimal.valueOf(diff), INCREMENT, RoundingMode.HALF_UP).floatValue();
-
-					final OverUnder entry = result.stream().filter(ou -> ou.getKey().compareTo(formatted) == 0).findFirst()
-							.orElse(new OverUnder(formatted));
-					entry.addGoalStat(numGoals);
-					result.add(entry);
-				}
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-		return result;
-	}
-
-	public BigDecimal round(BigDecimal value, BigDecimal increment, RoundingMode roundingMode) {
-		if (increment.signum() == 0) {
-			// 0 increment does not make much sense, but prevent division by 0
-			return value;
-		} else {
-			final BigDecimal divided = value.divide(increment, 0, roundingMode);
-			final BigDecimal result = divided.multiply(increment);
-			return result.setScale(2, RoundingMode.HALF_UP);
-		}
-	}
-
-	public BigDecimal getIncrement() {
-		return INCREMENT;
-	}
-
-	public List<TeamStanding> getLeagueTable(int leagueId, String season, int countryId, String date) {
-		final ArrayList<TeamStanding> result = Lists.newArrayList();
-
-		final String sql = "SELECT teamName.name as teamName, count(*) played, " + "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, "
-				+ "sum(homeScore) homeScore, " + "sum(awayScore) awayScore, " + "sum(homeScore) - sum(awayScore) goal_diff, " + "sum("
-				+ "case when homeScore > awayScore then 3 else 0 end + case " + "WHEN homeScore = awayScore then 1 else 0 end) score, "
-				+ "season FROM "
-				+ "(select hometeamId team, homeScore, awayScore, season, gameDate, leagueId as league, countryId as country FROM SoccerResults "
-				+ "union all SELECT awayteamId, awayScore, homeScore, season, gameDate, leagueId as league, countryId as country FROM SoccerResults) a "
-				+ "INNER JOIN Team teamName ON team = teamName.id " + "WHERE season = ? " + "AND league = ? " + "AND country = ? "
-				+ "AND homeScore != -1 " + "AND awayScore != -1 AND DATE(gameDate) < DATE(?) group by team " + "order by score desc, goal_diff desc";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-
-			stat.setString(1, season);
-			stat.setInt(2, leagueId);
-			stat.setInt(3, countryId);
-			stat.setString(4, date);
-
-			final ResultSet rs = stat.executeQuery();
-			while (rs.next()) {
-				final TeamStanding ts = new TeamStanding(rs.getString("teamName"), rs.getInt("wins"), rs.getInt("lost"), rs.getInt("draws"),
-						rs.getInt("score"), rs.getFloat(Constants.HOME_SCORE), rs.getFloat(Constants.AWAY_SCORE), rs.getFloat("goal_diff"));
-				result.add(ts);
-			}
-
-		} catch (final SQLException e) {
-			Log.getLog().info("Sql vid fel: %s", sql);
-			e.printStackTrace();
-		}
-
-		return result;
-	}
-
-	public boolean getParsingStarted(int countryId, int leagueId) {
-		boolean returnValue = false;
-		final String sql = "SELECT parsedYear FROM League WHERE id = ? AND countryId = ?";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, leagueId);
-			stat.setInt(2, countryId);
-
-			final ResultSet rs = stat.executeQuery();
-			while (rs.next()) {
-				final String parsedYear = rs.getString("parsedYear");
-				if (!Strings.isNullOrEmpty(parsedYear)) {
-					returnValue = true;
-				}
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return returnValue;
-	}
-
-	public String getLastSeason(Integer countryId, Integer leagueId) {
-		String season = "";
-		final String sql = "SELECT season FROM SoccerResults WHERE leagueId = ? AND countryId = ? ORDER BY season DESC limit 1";
-		try (PreparedStatement stmt = conn.prepareStatement(sql)) {
-			stmt.setInt(1, leagueId);
-			stmt.setInt(2, countryId);
-
-			final ResultSet rs = stmt.executeQuery();
-			while (rs.next()) {
-				season = rs.getString(Constants.SEASON);
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return season;
-	}
-
-	public TeamResults getTeamResults(int teamId, int numResults, boolean isHomeTeam) {
-		final String sql;
-		final TeamResults tr = new TeamResults();
-		if (isHomeTeam) {
-			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 (SELECT * FROM SoccerResults WHERE homeTeamId = ? AND "
-					+ "HomeScore >= 0 AND awayScore >= 0 AND DATE(gameDate) < DATE(NOW()) 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 (SELECT * FROM SoccerResults WHERE awayTeamId = ? AND "
-					+ "HomeScore >= 0 AND awayScore >= 0 AND DATE(gameDate) < DATE(NOW()) ORDER BY gameDate DESC LIMIT ?) as t";
-		}
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, teamId);
-			stat.setInt(2, numResults);
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				final int draws = rs.getInt("draws");
-				final int wins = rs.getInt("wins");
-				final int lost = rs.getInt("lost");
-				tr.setDraws(draws);
-				tr.setWins(wins);
-				tr.setLosses(lost);
-				tr.setCount(wins + draws + lost);
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return tr;
-	}
-
-	public TeamResults getTeamResultsTest(int teamId, int numResults, boolean isHomeTeam, String date) {
-		final String sql;
-		final TeamResults tr = new TeamResults();
-		if (isHomeTeam) {
-			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 (SELECT * FROM SoccerResults WHERE homeTeamId = ? AND "
-					+ "HomeScore >= 0 AND awayScore >= 0 AND DATE(gameDate) < ? 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 (SELECT * FROM SoccerResults WHERE awayTeamId = ? AND "
-					+ "HomeScore >= 0 AND awayScore >= 0 AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?) as t";
-		}
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, teamId);
-			stat.setString(2, date);
-			stat.setInt(3, numResults);
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				final int draws = rs.getInt("draws");
-				final int wins = rs.getInt("wins");
-				final int lost = rs.getInt("lost");
-				tr.setDraws(draws);
-				tr.setWins(wins);
-				tr.setLosses(lost);
-				tr.setCount(wins + draws + lost);
-			}
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return tr;
-	}
-
-	public List<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 (PreparedStatement stat = conn.prepareStatement(sql)) {
-			if (date.equals("")) {
-				stat.setString(1, new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
-			} else {
-				stat.setString(1, date);
-			}
-
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				result.add(new SimpleEntry<>(rs.getInt(Constants.ID), rs.getString("name")));
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
-
-	public List<SimpleEntry<Integer, String>> getLeaguesByDate(int sportId, int countryId, String date) {
-		final ArrayList<AbstractMap.SimpleEntry<Integer, String>> leagues = Lists.newArrayList();
-		final String sql = "SELECT id, name FROM League WHERE id IN (SELECT leagueId FROM SoccerResults WHERE sportId = ? AND countryId = ? AND DATE(gameDate) = ?)";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, sportId);
-			stat.setInt(2, countryId);
-			stat.setString(3, date);
-
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				final SimpleEntry<Integer, String> entry = new SimpleEntry<>(rs.getInt(Constants.ID), rs.getString("name"));
-				leagues.add(entry);
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-		return leagues;
-	}
-
-	public List<SoccerMatch> getMatches(int sportId, Integer countryId, Integer leagueId, String date, String order, boolean exactDate,
-			boolean onlyPrio) {
-		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 {
-			if (exactDate) {
-				dateSql = "DATE(gameDate) = '" + date + "' ";
-			} else {
-				dateSql = "DATE(gameDate) <= '" + date + "' ";
-			}
-		}
-		final String countrySql;
-		if (countryId != null) {
-			countrySql = "AND res.countryId = ? ";
-		} else {
-			countrySql = "";
-		}
-		final String leagueSql;
-		if (leagueId != null) {
-			leagueSql = "AND res.leagueId = ? ";
-		} else {
-			leagueSql = "";
-		}
-		final String onlyPrioSql;
-		if (onlyPrio) {
-			onlyPrioSql = "AND l.prio = 1 ";
-		} else {
-			onlyPrioSql = "";
-		}
-
-		final String sql = "SELECT res.*, " + "hTeam.name as homeTeamName, aTeam.name as awayTeamName " + "FROM SoccerResults as res "
-				+ "Join Team as hTeam ON res.homeTeamId = hTeam.id "
-				+ "Join Team as aTeam ON res.awayTeamId = aTeam.id INNER JOIN League l ON res.leagueId = l.id " + "WHERE " + dateSql + leagueSql
-				+ countrySql + onlyPrioSql + orderSql;
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			if (leagueId != null && countryId != null) {
-				stat.setInt(1, leagueId);
-				stat.setInt(2, countryId);
-			} else if (leagueId != null && countryId == null) {
-				stat.setInt(1, leagueId);
-			} else if (leagueId == null && countryId != null) {
-				stat.setInt(1, countryId);
-			}
-
-			final ResultSet rs = stat.executeQuery();
-			while (rs.next()) {
-				final SoccerMatch sm = new SoccerMatch();
-				final Team homeTeam = new Team();
-				final Team awayTeam = new Team();
-
-				homeTeam.setTeamId(rs.getInt(Constants.HOME_TEAM_ID));
-				awayTeam.setTeamId(rs.getInt(Constants.AWAY_TEAM_ID));
-				homeTeam.setTeamName(rs.getString(Constants.HOME_TEAM_NAME));
-				awayTeam.setTeamName(rs.getString(Constants.AWAY_TEAM_NAME));
-				homeTeam.setTeamLeagueId(rs.getInt(Constants.LEAGUE_ID));
-				awayTeam.setTeamLeagueId(rs.getInt(Constants.LEAGUE_ID));
-				homeTeam.setCountryId(rs.getInt(Constants.COUNTRY_ID));
-				awayTeam.setCountryId(rs.getInt(Constants.COUNTRY_ID));
-
-				sm.setAwayScore(rs.getInt(Constants.AWAY_SCORE));
-				sm.setHomeScore(rs.getInt(Constants.HOME_SCORE));
-				sm.setHomeTeam(homeTeam);
-				sm.setAwayTeam(awayTeam);
-				sm.setMatchId(rs.getInt(Constants.ID));
-				sm.setOdds1(rs.getFloat(Constants.ODDS_1));
-				sm.setOddsX(rs.getFloat(Constants.ODDS_X));
-				sm.setOdds2(rs.getFloat(Constants.ODDS_2));
-				sm.setGameDate(LocalDateTime.parse(rs.getString(Constants.GAME_DATE)));
-				sm.setSeason(rs.getString(Constants.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 (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, teamLeague);
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				result = new League(rs.getInt(Constants.ID), rs.getString("name"), rs.getInt("lookback"), rs.getInt("betMargin"),
-						rs.getInt("lookbackHome"), rs.getInt("lookbackDraw"), rs.getInt("lookbackAway"), rs.getInt("betMarginHome"),
-						rs.getInt("betMarginDraw"), rs.getInt("betMarginAway"));
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
-
-	public League getLeagueInfo(int leagueId) {
-		final String sql = "SELECT * FROM League WHERE id = ?";
-		League result = null;
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, leagueId);
-			final ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				result = new League(rs.getInt(Constants.ID), rs.getString("name"), rs.getInt("lookback"), rs.getInt("betMargin"),
-						rs.getInt("lookbackHome"), rs.getInt("lookbackDraw"), rs.getInt("lookbackAway"), rs.getInt("betMarginHome"),
-						rs.getInt("betMarginDraw"), rs.getInt("betMarginAway"));
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
-
-	public void setTeamMarginHome(int teamId, int marginHome) {
-		final String sql = "UPDATE Team SET marginHome = ? WHERE id = ?";
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, marginHome);
-			stat.setInt(2, teamId);
-
-			stat.executeUpdate();
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-	}
-
-	public void setTeamMarginDraw(int teamId, int marginDraw) {
-		final String sql = "UPDATE Team SET marginDraw = ? WHERE id = ?";
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, marginDraw);
-			stat.setInt(2, teamId);
-
-			stat.executeUpdate();
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-	}
-
-	public void setTeamMarginAway(int teamId, int marginAway) {
-		final String sql = "UPDATE Team SET marginAway = ? WHERE id = ?";
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, marginAway);
-			stat.setInt(2, teamId);
-
-			stat.executeUpdate();
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-	}
-
-	public void setTeamLookbackHome(int teamId, int lookbackHome) {
-		final String sql = "UPDATE Team SET lookbackHome = ? WHERE id = ?";
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, lookbackHome);
-			stat.setInt(2, teamId);
-
-			stat.executeUpdate();
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-	}
-
-	public void setTeamLookbackDraw(int teamId, int lookbackDraw) {
-		final String sql = "UPDATE Team SET lookbackDraw = ? WHERE id = ?";
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, lookbackDraw);
-			stat.setInt(2, teamId);
-
-			stat.executeUpdate();
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-	}
-
-	public void setTeamLookbackAway(int teamId, int lookbackAway) {
-		final String sql = "UPDATE Team SET lookbackAway = ? WHERE id = ?";
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, lookbackAway);
-			stat.setInt(2, teamId);
-
-			stat.executeUpdate();
-
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-	}
-
-	public List<BetDTO> getBetSeries(boolean includeInactive) {
-		List<BetDTO> result = new ArrayList<>();
-		String sql = "SELECT ab.*, sr.gameDate as gameDate, sr.id as gameId, sr.homeScore as homeScore, sr.awayScore as awayScore, "
-				+ "ht.name as homeTeam, aw.name as awayTeam " + "FROM ActiveBets ab " + "INNER JOIN SoccerResults sr ON ab.gameId = sr.id "
-				+ "INNER JOIN Team ht ON sr.homeTeamId = ht.id " + "INNER JOIN Team aw ON sr.awayTeamId = aw.id "
-				+ "WHERE done = ? ORDER BY series ASC, sr.gameDate DESC";
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setBoolean(1, includeInactive);
-
-			ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				BetDTO dto = new BetDTO();
-				dto.setHomeTeam(rs.getString("homeTeam"));
-				dto.setAwayTeam(rs.getString("awayTeam"));
-				dto.setBet(rs.getFloat("bet"));
-				dto.setBetType(rs.getString("betType"));
-				dto.setBetSeries(rs.getInt("series"));
-				dto.setGameId(rs.getInt("gameId"));
-				dto.setMatch(rs.getString("homeTeam"), rs.getString("awayTeam"));
-				dto.setOdds(rs.getFloat("odds"));
-				dto.setResult(rs.getInt("homeScore"), rs.getInt("AwayScore"));
-				dto.setGameDate(rs.getString("gameDate"));
-				dto.setWinAmount(rs.getFloat("odds") * rs.getFloat("bet"));
-				result.add(dto);
-			}
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
-
-	public void addBetSeries(BetDTO bet) {
-		String sql = "INSERT INTO ActiveBets (series, gameId, betType, bet, odds, done) VALUES (?, ?, ?, ?, ?, ?)";
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setInt(1, bet.getBetSeries());
-			stat.setInt(2, getGameId(bet.getHomeTeam(), bet.getAwayTeam(), bet.getGameDate(), bet.getCountryId(), bet.getLeagueId()));
-			stat.setString(3, bet.getBetType());
-			stat.setFloat(4, bet.getBet());
-			stat.setFloat(5, bet.getOdds());
-			stat.setBoolean(6, false);
-
-			stat.execute();
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-	}
-
-	public int getGameId(String homeTeam, String awayTeam, String gameDate, int countryId, int leagueId) {
-		int result = -1;
-		String sql = "SELECT id FROM SoccerResults WHERE homeTeamId = (SELECT id FROM Team WHERE name = ? AND countryId = ? AND leagueId = ?) AND awayTeamId = (SELECT id FROM Team WHERE name = ? AND countryId = ? AND leagueId = ?) AND DATE(gameDate) = DATE(?)";
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, homeTeam);
-			stat.setInt(2, countryId);
-			stat.setInt(3, leagueId);
-			stat.setString(4, awayTeam);
-			stat.setInt(5, countryId);
-			stat.setInt(6, leagueId);
-			stat.setString(7, gameDate);
-
-			ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				result = rs.getInt("id");
-			}
-
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
-
-	public Map<String, String> getPreviousMatches(int numberOfMatches, String homeTeamName, String awayTeamName, String date, int countryId,
-			int leagueId) {
-		Map<String, String> result = new HashMap<>();
-
-		String homeTeamSql = "SELECT * FROM SoccerResults sr INNER JOIN Team t ON sr.homeTeamId = t.id WHERE t.name = ? AND sr.leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC limit ?";
-		String awayTeamSql = "SELECT * FROM SoccerResults sr INNER JOIN Team t ON sr.awayTeamId = t.id WHERE t.name = ? AND sr.leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC limit ?";
-		String combinedSql = "SELECT * FROM SoccerResults sr INNER JOIN Team homeTeam ON homeTeamId = homeTeam.id INNER JOIN Team awayTeam ON sr.awayTeamId = awayTeam.id WHERE homeTeam.name = ? AND awayTeam.name = ? AND sr.leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?";
-		String combinedReverseSql = "SELECT * FROM SoccerResults sr INNER JOIN Team homeTeam ON homeTeamId = homeTeam.id INNER JOIN Team awayTeam ON sr.awayTeamId = awayTeam.id WHERE homeTeam.name = ? AND awayTeam.name = ? AND sr.leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?";
-		try (PreparedStatement homeTeamStat = conn.prepareStatement(homeTeamSql);
-				PreparedStatement awayTeamStat = conn.prepareStatement(awayTeamSql);
-				PreparedStatement combinedStat = conn.prepareStatement(combinedSql);
-				PreparedStatement combinedReversedStat = conn.prepareStatement(combinedReverseSql);) {
-
-			homeTeamStat.setString(1, homeTeamName);
-			homeTeamStat.setInt(2, leagueId);
-			homeTeamStat.setString(3, date);
-			homeTeamStat.setInt(4, numberOfMatches);
-
-			awayTeamStat.setString(1, awayTeamName);
-			awayTeamStat.setInt(2, leagueId);
-			awayTeamStat.setString(3, date);
-			awayTeamStat.setInt(4, numberOfMatches);
-
-			combinedStat.setString(1, homeTeamName);
-			combinedStat.setString(2, awayTeamName);
-			combinedStat.setInt(3, leagueId);
-			combinedStat.setString(4, date);
-			combinedStat.setInt(5, numberOfMatches);
-
-			combinedReversedStat.setString(1, awayTeamName);
-			combinedReversedStat.setString(2, homeTeamName);
-			combinedReversedStat.setInt(3, leagueId);
-			combinedReversedStat.setString(4, date);
-			combinedReversedStat.setInt(5, numberOfMatches);
-
-			ResultSet homeTeamRs = homeTeamStat.executeQuery();
-			ResultSet awayTeamRs = awayTeamStat.executeQuery();
-			ResultSet combinedTeamRs = combinedStat.executeQuery();
-			ResultSet combinedReversedTeamRs = combinedReversedStat.executeQuery();
-
-			String homeTeamMeets = "";
-			while (homeTeamRs.next()) {
-				homeTeamMeets += homeTeamRs.getInt("homeScore") + "-" + homeTeamRs.getInt("awayScore") + ", ";
-			}
-			String awayTeamMeets = "";
-			while (awayTeamRs.next()) {
-				awayTeamMeets += awayTeamRs.getInt("homeScore") + "-" + awayTeamRs.getInt("awayScore") + ", ";
-			}
-			String combinedMeets = "";
-			while (combinedTeamRs.next()) {
-				combinedMeets += combinedTeamRs.getInt("homeScore") + "-" + combinedTeamRs.getInt("awayScore") + ", ";
-			}
-			String combinedReversedMeets = "";
-			while (combinedReversedTeamRs.next()) {
-				combinedReversedMeets += combinedReversedTeamRs.getInt("homeScore") + "-" + combinedReversedTeamRs.getInt("awayScore") + ", ";
-			}
-			if (homeTeamMeets.length() > 2) {
-				result.put("PrevHomeTeam", homeTeamMeets.substring(0, homeTeamMeets.length() - 2));
-			} else {
-				result.put("PrevHomeTeam", homeTeamMeets);
-			}
-			if (awayTeamMeets.length() > 2) {
-				result.put("PrevAwayTeam", awayTeamMeets.substring(0, awayTeamMeets.length() - 2));
-			} else {
-				result.put("PrevAwayTeam", awayTeamMeets);
-			}
-			if (combinedMeets.length() > 2) {
-				result.put("PrevCombined", combinedMeets.substring(0, combinedMeets.length() - 2));
-			} else {
-				result.put("PrevCombined", combinedMeets);
-			}
-
-			if (combinedReversedMeets.length() > 2) {
-				result.put("PrevReversedCombined", combinedReversedMeets.substring(0, combinedReversedMeets.length() - 2));
-			} else {
-				result.put("PrevReversedCombined", combinedReversedMeets);
-			}
-
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
-
-	public int getBetSeriesEndNumber() {
-		int result = -1;
-		String sql = "SELECT MAX(series) FROM ActiveBets";
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				result = rs.getInt(1);
-			}
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
-
-	public List<SoccerMatch> getMatches(int sportId, String dateString, String sortOrder, boolean exactDate) {
-		return getMatches(sportId, null, null, dateString, sortOrder, exactDate, true);
-	}
+    private static final BigDecimal INCREMENT = BigDecimal.valueOf(0.2);
+    private static final GuiMysql instance = new GuiMysql();
+    private final Connection conn;
+
+    protected GuiMysql() {
+        super();
+        conn = this.getConnection();
+    }
+
+    public static GuiMysql getInstance() {
+        return instance;
+    }
+
+    public List<SimpleEntry<Integer, String>> getSports() {
+
+        final ArrayList<AbstractMap.SimpleEntry<Integer, String>> sports = Lists.newArrayList();
+        final String sql = "SELECT id, name FROM Sport";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                final SimpleEntry<Integer, String> entry = new SimpleEntry<>(rs.getInt(Constants.ID),
+                        rs.getString("name"));
+                sports.add(entry);
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return sports;
+    }
+
+    public List<SimpleEntry<Integer, String>> getCountries() {
+
+        final ArrayList<AbstractMap.SimpleEntry<Integer, String>> countries = Lists.newArrayList();
+        final String sql = "SELECT id, name FROM Country";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                final SimpleEntry<Integer, String> entry = new SimpleEntry<>(rs.getInt(Constants.ID),
+                        rs.getString("name"));
+                countries.add(entry);
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+        return countries;
+    }
+
+    public List<SimpleEntry<Integer, String>> getLeagues(int sportId, int countryId) {
+
+        final ArrayList<AbstractMap.SimpleEntry<Integer, String>> leagues = Lists.newArrayList();
+        final String sql = "SELECT id, name FROM League WHERE sportId = ? AND countryId = ? ORDER BY name ASC";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, sportId);
+            stat.setInt(2, countryId);
+
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                final SimpleEntry<Integer, String> entry = new SimpleEntry<>(rs.getInt(Constants.ID),
+                        rs.getString("name"));
+                leagues.add(entry);
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+        return leagues;
+    }
+
+    public List<SoccerMatch> getUpcomingMatches(String sportResultTable) {
+        final ArrayList<SoccerMatch> matches = Lists.newArrayList();
+        final String dateSql;
+        dateSql = " AND DATE(gameDate) >= DATE(now())";
+
+        final String sql = "SELECT res.id, homeTeamId, awayTeamId, 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.prio as prio " + "FROM " + sportResultTable + " as res "
+                + "Join Team as hTeam ON res.homeTeamId = hTeam.id "
+                + "Join Team as aTeam ON res.awayTeamId = aTeam.id "
+                + "Join League as league ON res.leagueId = league.id "
+                + "Join Country as country ON res.countryId = country.id " + "WHERE homeScore = -1 " + dateSql
+                + "AND league.name NOT LIKE '%cup%' AND league.name NOT LIKE '%group%' AND league.prio = 1 "
+                + "ORDER BY country.prio DESC, country.name ASC";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+
+            final ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                final SoccerMatch sm = new SoccerMatch();
+                final Team homeTeam = new Team();
+                final Team awayTeam = new Team();
+
+                homeTeam.setTeamId(rs.getInt(Constants.HOME_TEAM_ID));
+                awayTeam.setTeamId(rs.getInt(Constants.AWAY_TEAM_ID));
+                homeTeam.setTeamName(rs.getString(Constants.HOME_TEAM_NAME));
+                awayTeam.setTeamName(rs.getString(Constants.AWAY_TEAM_NAME));
+                homeTeam.setTeamLeagueId(rs.getInt(Constants.LEAGUE_ID));
+                awayTeam.setTeamLeagueId(rs.getInt(Constants.LEAGUE_ID));
+                homeTeam.setTeamLeague(rs.getString(Constants.LEAGUE_NAME));
+                awayTeam.setTeamLeague(rs.getString(Constants.LEAGUE_NAME));
+                homeTeam.setCountryId(rs.getInt(Constants.COUNTRY_ID));
+                awayTeam.setCountryId(rs.getInt(Constants.COUNTRY_ID));
+                homeTeam.setCountryName(rs.getString(Constants.COUNTRY_NAME));
+                awayTeam.setCountryName(rs.getString(Constants.COUNTRY_NAME));
+
+                sm.setAwayScore(rs.getInt(Constants.AWAY_SCORE));
+                sm.setHomeScore(rs.getInt(Constants.HOME_SCORE));
+                sm.setHomeTeam(homeTeam);
+                sm.setAwayTeam(awayTeam);
+                sm.setMatchId(rs.getInt(Constants.ID));
+                sm.setOdds1(rs.getFloat(Constants.ODDS_1));
+                sm.setOddsX(rs.getFloat(Constants.ODDS_X));
+                sm.setOdds2(rs.getFloat(Constants.ODDS_2));
+                sm.setGameDate(LocalDateTime.parse(rs.getString(Constants.GAME_DATE)));
+                sm.setCountryPrio(rs.getBoolean("prio"));
+
+                matches.add(sm);
+            }
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return matches;
+    }
+
+    public List<Float> getAvgHomeScore(int teamId) {
+        final ArrayList<Float> returnValue = Lists.newArrayList();
+        final String sql = "SELECT AVG(homeScore) as avgScored, AVG(awayScore) as avgConceded FROM SoccerResults WHERE homeScore != -1 AND homeTeamId = ?";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, teamId);
+
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                returnValue.add(rs.getFloat("avgScored"));
+                returnValue.add(rs.getFloat("avgConceded"));
+            }
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return returnValue;
+    }
+
+    public List<Float> getAvgHomeScoreThisSeason(int teamId, int countryId, int leagueId) {
+        return getAvgHomeScoreThisSeason(teamId, countryId, leagueId, "");
+    }
+
+    public List<Float> getAvgHomeScoreThisSeason(int teamId, int countryId, int leagueId, String gameDate) {
+        final ArrayList<Float> returnValue = Lists.newArrayList();
+        final String sql = "SELECT AVG(homeScore) as avgScoredSeason, AVG(awayScore) as avgConcededSeason FROM SoccerResults WHERE homeScore != -1 AND homeTeamId = ? AND season = ? AND DATE(gameDate) < ? ORDER BY gameDate ASC";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, teamId);
+
+            if (Strings.isNullOrEmpty(gameDate)
+                    || getSeasonFromDate(countryId, leagueId, gameDate).equals(getLastSeason(countryId, leagueId))) {
+                stat.setString(2, getLastSeason(countryId, leagueId));
+            } else {
+                String seasonFromDate = getSeasonFromDate(countryId, leagueId, gameDate);
+                stat.setString(2, seasonFromDate);
+            }
+            if (Strings.isNullOrEmpty(gameDate)) {
+                stat.setString(3, new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
+            } else {
+                stat.setString(3, gameDate);
+            }
+
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                returnValue.add(rs.getFloat("avgScoredSeason"));
+                returnValue.add(rs.getFloat("avgConcededSeason"));
+            }
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return returnValue;
+    }
+
+    public String getSeasonFromDate(int countryId, int leagueId, String gameDate) {
+        String sql = "SELECT season FROM SoccerResults WHERE DATE(gameDate) = ? AND countryId = ? AND leagueId = ? LIMIT 1";
+        String returnValue = "";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            if (Strings.isNullOrEmpty(gameDate)) {
+                stat.setString(1, new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
+            } else {
+                stat.setString(1, gameDate);
+            }
+            stat.setInt(2, countryId);
+            stat.setInt(3, leagueId);
+
+            ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                returnValue = rs.getString("season");
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return returnValue;
+    }
+
+    public List<Float> getAvgAwayScore(int teamId) {
+        final ArrayList<Float> returnValue = Lists.newArrayList();
+        final String sql = "SELECT AVG(homeScore) as avgConceded, AVG(awayScore) as avgScored FROM SoccerResults WHERE awayScore != -1 AND awayTeamId = ?";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, teamId);
+
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                returnValue.add(rs.getFloat("avgScored"));
+                returnValue.add(rs.getFloat("avgConceded"));
+            }
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return returnValue;
+    }
+
+    public List<Float> getAvgAwayScoreThisSeason(int teamId, int countryId, int leagueId) {
+        return getAvgAwayScoreThisSeason(teamId, countryId, leagueId, "");
+    }
+
+    public List<Float> getAvgAwayScoreThisSeason(int teamId, int countryId, int leagueId, String gameDate) {
+        final ArrayList<Float> returnValue = Lists.newArrayList();
+        final String sql = "SELECT AVG(homeScore) as avgConcededSeason, AVG(awayScore) as avgScoredSeason FROM SoccerResults WHERE awayScore != -1 AND awayTeamId = ? AND season = ? AND DATE(gameDate) < ? ORDER BY gameDate ASC";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, teamId);
+            if (Strings.isNullOrEmpty(gameDate)
+                    || getSeasonFromDate(countryId, leagueId, gameDate).equals(getLastSeason(countryId, leagueId))) {
+                stat.setString(2, getLastSeason(countryId, leagueId));
+            } else {
+                String seasonFromDate = getSeasonFromDate(countryId, leagueId, gameDate);
+                stat.setString(2, seasonFromDate);
+            }
+            if (Strings.isNullOrEmpty(gameDate)) {
+                stat.setString(3, new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
+            } else {
+                stat.setString(3, gameDate);
+            }
+
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                returnValue.add(rs.getFloat("avgScoredSeason"));
+                returnValue.add(rs.getFloat("avgConcededSeason"));
+            }
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return returnValue;
+    }
+
+    public List<Float> getLeagueAvarages(int leagueId, int countryId, String gameDate) {
+        final ArrayList<Float> returnValue = Lists.newArrayList();
+        final String sql = "SELECT AVG(homeScore) avgHomeScore, AVG(awayScore) as avgAwayScore"
+                + " FROM SoccerResults WHERE leagueId = ? AND countryId = ? AND DATE(gameDate) < DATE(?)";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql);) {
+            stat.setInt(1, leagueId);
+            stat.setInt(2, countryId);
+            stat.setString(3, gameDate);
+
+            final ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                returnValue.add(rs.getFloat("avgHomeScore"));
+                returnValue.add(rs.getFloat("avgAwayScore"));
+            }
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return returnValue;
+    }
+
+    public Map<Integer, Integer> getGoalAvgThisSeason(int leagueId, int countryId) {
+        Map<Integer, Integer> returnValue = new HashMap<>();
+        final String goalsSql = "SELECT (homeScore + awayScore) as totalGoals, count(*) as count FROM SoccerResults  WHERE leagueId = ? AND countryId = ? AND season = ? GROUP BY totalGoals ORDER BY totalGoals asc";
+        try (PreparedStatement goalStmt = conn.prepareStatement(goalsSql)) {
+            goalStmt.setInt(1, leagueId);
+            goalStmt.setInt(2, countryId);
+            goalStmt.setString(3, getLastSeason(countryId, leagueId));
+
+            final ResultSet goalRs = goalStmt.executeQuery();
+
+            while (goalRs.next()) {
+                int tg = goalRs.getInt("totalGoals");
+                if (tg < 0) {
+                    continue;
+                }
+                int numGoals = goalRs.getInt("count");
+
+                returnValue.put(tg, numGoals);
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return returnValue;
+    }
+
+    public List<OverUnder> getStatsOverUnder(int leagueId) {
+        return getStatsOverUnder(leagueId, "");
+    }
+
+    private List<String> getAllSeasons(int leagueId) {
+        List<String> returnValue = new ArrayList<String>();
+        String sql = "SELECT distinct(season) FROM SoccerResults WHERE leagueId = ?";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, leagueId);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                returnValue.add(rs.getString("season"));
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return returnValue;
+    }
+
+    public List<OverUnder> getStatsOverUnderWithDrawStats(int leagueId, String gameDate) {
+        final DecimalFormat df = new DecimalFormat("##.##");
+        df.setRoundingMode(RoundingMode.HALF_DOWN);
+        final ArrayList<OverUnder> result = Lists.newArrayList();
+
+        final String sql = "SELECT (homeScore + awayScore) as numGoals, count(case when homeScore = awayScore then 1 end) draws, ROUND((sHome.avgScored * sAway.avgConceded) + (sAway.avgScored * sHome.avgConceded),1) roundedDiff, count(*) as numGames "
+                + "FROM SoccerResults "
+                + "INNER JOIN (SELECT homeTeamId, AVG(homeScore) as avgScored, AVG(awayScore) as avgConceded FROM SoccerResults WHERE homeScore != -1 AND homeTeamId = SoccerResults.homeTeamId AND DATE(gameDate) < ? AND leagueId = ? GROUP BY homeTeamId) as sHome ON SoccerResults.homeTeamId = sHome.homeTeamId "
+                + "INNER JOIN (SELECT awayTeamId, AVG(homeScore) as avgConceded, AVG(awayScore) as avgScored FROM SoccerResults WHERE awayScore != -1 AND awayTeamId = SoccerResults.awayTeamId AND DATE(gameDate) < ? AND leagueId = ? GROUP BY awayTeamId) as sAway ON SoccerResults.awayTeamId = sAway.awayTeamId "
+                + "WHERE homeScore != -1 AND awayScore != -1 AND leagueId = ? AND DATE(gameDate) < ? GROUP BY roundedDiff;";
+
+        List<String> allSeasons = getAllSeasons(leagueId);
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            final String dateString;
+            if (Strings.isNullOrEmpty(gameDate)) {
+                dateString = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
+            } else {
+                dateString = gameDate;
+            }
+            for (String season : allSeasons) {
+                stat.setString(1, dateString);
+                stat.setInt(2, leagueId);
+                stat.setString(3, dateString);
+                stat.setInt(4, leagueId);
+
+                stat.setInt(5, leagueId);
+                stat.setString(6, dateString);
+
+                final ResultSet rs = stat.executeQuery();
+
+                while (rs.next()) {
+                    final float diff = rs.getFloat("roundedDiff");
+                    final int numGoals = rs.getInt("numGoals");
+
+                    final OverUnder entry = result.stream().filter(ou -> ou.getKey().compareTo(diff) == 0)
+                            .findFirst()
+                            .orElse(new OverUnder(diff));
+                    entry.addGoalStat(numGoals);
+                    entry.setDraws(rs.getInt("draws"));
+                    entry.setTotalGames(rs.getInt("numGames"));
+                    result.add(entry);
+                }
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    public List<OverUnder> getStatsOverUnder(int leagueId, String gameDate) {
+
+        final DecimalFormat df = new DecimalFormat("##.##");
+        df.setRoundingMode(RoundingMode.HALF_DOWN);
+        final ArrayList<OverUnder> result = Lists.newArrayList();
+
+        final String sql = "SELECT ((sHome.avgScored * sAway.avgConceded) + (sAway.avgScored * sHome.avgConceded)) as diff, (homeScore + awayScore) as numGoals "
+                + "FROM SoccerResults "
+                + "INNER JOIN (SELECT homeTeamId, AVG(homeScore) as avgScored, AVG(awayScore) as avgConceded FROM SoccerResults WHERE homeScore != -1 AND homeTeamId = SoccerResults.homeTeamId AND DATE(gameDate) < ? AND season = ? AND leagueId = ? GROUP BY homeTeamId) as sHome ON SoccerResults.homeTeamId = sHome.homeTeamId "
+                + "INNER JOIN (SELECT awayTeamId, AVG(homeScore) as avgConceded, AVG(awayScore) as avgScored FROM SoccerResults WHERE awayScore != -1 AND awayTeamId = SoccerResults.awayTeamId AND DATE(gameDate) < ? AND season = ? AND leagueId = ? GROUP BY awayTeamId) as sAway ON SoccerResults.awayTeamId = sAway.awayTeamId "
+                + "WHERE homeScore != -1 AND awayScore != -1 AND leagueId = ? AND DATE(gameDate) < ? AND season = ? "
+                + "ORDER BY diff ASC";
+        List<String> allSeasons = getAllSeasons(leagueId);
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            final String dateString;
+            if (Strings.isNullOrEmpty(gameDate)) {
+                dateString = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
+            } else {
+                dateString = gameDate;
+            }
+            for (String season : allSeasons) {
+                stat.setString(1, dateString);
+                stat.setString(2, season);
+                stat.setInt(3, leagueId);
+                stat.setString(4, dateString);
+                stat.setString(5, season);
+                stat.setInt(6, leagueId);
+
+                stat.setInt(7, leagueId);
+                stat.setString(8, dateString);
+                stat.setString(9, season);
+
+                final ResultSet rs = stat.executeQuery();
+
+                while (rs.next()) {
+                    final float diff = rs.getFloat("diff");
+                    final int numGoals = rs.getInt("numGoals");
+                    final Float formatted = round(BigDecimal.valueOf(diff), INCREMENT, RoundingMode.HALF_UP)
+                            .floatValue();
+
+                    final OverUnder entry = result.stream().filter(ou -> ou.getKey().compareTo(formatted) == 0)
+                            .findFirst()
+                            .orElse(new OverUnder(formatted));
+                    entry.addGoalStat(numGoals);
+                    result.add(entry);
+                }
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    public BigDecimal round(BigDecimal value, BigDecimal increment, RoundingMode roundingMode) {
+        if (increment.signum() == 0) {
+            // 0 increment does not make much sense, but prevent division by 0
+            return value;
+        } else {
+            final BigDecimal divided = value.divide(increment, 0, roundingMode);
+            final BigDecimal result = divided.multiply(increment);
+            return result.setScale(2, RoundingMode.HALF_UP);
+        }
+    }
+
+    public BigDecimal getIncrement() {
+        return INCREMENT;
+    }
+
+    public List<TeamStanding> getLeagueTable(int leagueId, String season, int countryId, String date) {
+        final ArrayList<TeamStanding> result = Lists.newArrayList();
+
+        final String sql = "SELECT teamName.name as teamName, count(*) played, "
+                + "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, "
+                + "sum(homeScore) homeScore, " + "sum(awayScore) awayScore, "
+                + "sum(homeScore) - sum(awayScore) goal_diff, " + "sum("
+                + "case when homeScore > awayScore then 3 else 0 end + case "
+                + "WHEN homeScore = awayScore then 1 else 0 end) score, "
+                + "season FROM "
+                + "(select hometeamId team, homeScore, awayScore, season, gameDate, leagueId as league, countryId as country FROM SoccerResults "
+                + "union all SELECT awayteamId, awayScore, homeScore, season, gameDate, leagueId as league, countryId as country FROM SoccerResults) a "
+                + "INNER JOIN Team teamName ON team = teamName.id " + "WHERE season = ? " + "AND league = ? "
+                + "AND country = ? "
+                + "AND homeScore != -1 " + "AND awayScore != -1 AND DATE(gameDate) < DATE(?) group by team "
+                + "order by score desc, goal_diff desc";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+
+            stat.setString(1, season);
+            stat.setInt(2, leagueId);
+            stat.setInt(3, countryId);
+            stat.setString(4, date);
+
+            final ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                final TeamStanding ts = new TeamStanding(rs.getString("teamName"), rs.getInt("wins"), rs.getInt("lost"),
+                        rs.getInt("draws"),
+                        rs.getInt("score"), rs.getFloat(Constants.HOME_SCORE), rs.getFloat(Constants.AWAY_SCORE),
+                        rs.getFloat("goal_diff"));
+                result.add(ts);
+            }
+
+        } catch (final SQLException e) {
+            Log.getLog().info("Sql vid fel: %s", sql);
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public boolean getParsingStarted(int countryId, int leagueId) {
+        boolean returnValue = false;
+        final String sql = "SELECT parsedYear FROM League WHERE id = ? AND countryId = ?";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, leagueId);
+            stat.setInt(2, countryId);
+
+            final ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                final String parsedYear = rs.getString("parsedYear");
+                if (!Strings.isNullOrEmpty(parsedYear)) {
+                    returnValue = true;
+                }
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return returnValue;
+    }
+
+    public String getLastSeason(Integer countryId, Integer leagueId) {
+        String season = "";
+        final String sql = "SELECT season FROM SoccerResults WHERE leagueId = ? AND countryId = ? ORDER BY season DESC limit 1";
+        try (PreparedStatement stmt = conn.prepareStatement(sql)) {
+            stmt.setInt(1, leagueId);
+            stmt.setInt(2, countryId);
+
+            final ResultSet rs = stmt.executeQuery();
+            while (rs.next()) {
+                season = rs.getString(Constants.SEASON);
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return season;
+    }
+
+    public TeamResults getTeamResults(int teamId, int numResults, boolean isHomeTeam) {
+        final String sql;
+        final TeamResults tr = new TeamResults();
+        if (isHomeTeam) {
+            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 (SELECT * FROM SoccerResults WHERE homeTeamId = ? AND "
+                    + "HomeScore >= 0 AND awayScore >= 0 AND DATE(gameDate) < DATE(NOW()) 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 (SELECT * FROM SoccerResults WHERE awayTeamId = ? AND "
+                    + "HomeScore >= 0 AND awayScore >= 0 AND DATE(gameDate) < DATE(NOW()) ORDER BY gameDate DESC LIMIT ?) as t";
+        }
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, teamId);
+            stat.setInt(2, numResults);
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                final int draws = rs.getInt("draws");
+                final int wins = rs.getInt("wins");
+                final int lost = rs.getInt("lost");
+                tr.setDraws(draws);
+                tr.setWins(wins);
+                tr.setLosses(lost);
+                tr.setCount(wins + draws + lost);
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return tr;
+    }
+
+    public TeamResults getTeamResultsTest(int teamId, int numResults, boolean isHomeTeam, String date) {
+        final String sql;
+        final TeamResults tr = new TeamResults();
+        if (isHomeTeam) {
+            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 (SELECT * FROM SoccerResults WHERE homeTeamId = ? AND "
+                    + "HomeScore >= 0 AND awayScore >= 0 AND DATE(gameDate) < ? 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 (SELECT * FROM SoccerResults WHERE awayTeamId = ? AND "
+                    + "HomeScore >= 0 AND awayScore >= 0 AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?) as t";
+        }
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, teamId);
+            stat.setString(2, date);
+            stat.setInt(3, numResults);
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                final int draws = rs.getInt("draws");
+                final int wins = rs.getInt("wins");
+                final int lost = rs.getInt("lost");
+                tr.setDraws(draws);
+                tr.setWins(wins);
+                tr.setLosses(lost);
+                tr.setCount(wins + draws + lost);
+            }
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return tr;
+    }
+
+    public List<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 (PreparedStatement stat = conn.prepareStatement(sql)) {
+            if (date.equals("")) {
+                stat.setString(1, new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
+            } else {
+                stat.setString(1, date);
+            }
+
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result.add(new SimpleEntry<>(rs.getInt(Constants.ID), rs.getString("name")));
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public List<SimpleEntry<Integer, String>> getLeaguesByDate(int sportId, int countryId, String date) {
+        final ArrayList<AbstractMap.SimpleEntry<Integer, String>> leagues = Lists.newArrayList();
+        final String sql = "SELECT id, name FROM League WHERE id IN (SELECT leagueId FROM SoccerResults WHERE countryId = ? AND DATE(gameDate) = ?)";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, countryId);
+            stat.setString(2, date);
+
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                final SimpleEntry<Integer, String> entry = new SimpleEntry<>(rs.getInt(Constants.ID),
+                        rs.getString("name"));
+                leagues.add(entry);
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+        return leagues;
+    }
+
+    public List<SoccerMatch> getMatches(int sportId, Integer countryId, Integer leagueId, String date, String order,
+            boolean exactDate,
+            boolean onlyPrio) {
+        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 {
+            if (exactDate) {
+                dateSql = "DATE(gameDate) = '" + date + "' ";
+            } else {
+                dateSql = "DATE(gameDate) <= '" + date + "' ";
+            }
+        }
+        final String countrySql;
+        if (countryId != null) {
+            countrySql = "AND res.countryId = ? ";
+        } else {
+            countrySql = "";
+        }
+        final String leagueSql;
+        if (leagueId != null) {
+            leagueSql = "AND res.leagueId = ? ";
+        } else {
+            leagueSql = "";
+        }
+        final String onlyPrioSql;
+        if (onlyPrio) {
+            onlyPrioSql = "AND l.prio = 1 ";
+        } else {
+            onlyPrioSql = "";
+        }
+
+        final String sql = "SELECT res.*, c.name as countryName, l.name as leagueName, "
+                + "hTeam.name as homeTeamName, aTeam.name as awayTeamName "
+                + "FROM SoccerResults as res "
+                + "INNER Join Team as hTeam ON res.homeTeamId = hTeam.id AND res.leagueId = hTeam.leagueId "
+                + "INNER Join Team as aTeam ON res.awayTeamId = aTeam.id AND res.leagueId = hTeam.leagueId "
+                + "INNER JOIN League l ON res.leagueId = l.id "
+                + "INNER JOIN Country c ON res.countryId = c.id "
+                + "WHERE " + dateSql + leagueSql
+                + countrySql + onlyPrioSql + orderSql;
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            if (leagueId != null && countryId != null) {
+                stat.setInt(1, leagueId);
+                stat.setInt(2, countryId);
+            } else if (leagueId != null && countryId == null) {
+                stat.setInt(1, leagueId);
+            } else if (leagueId == null && countryId != null) {
+                stat.setInt(1, countryId);
+            }
+
+            final ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                final SoccerMatch sm = new SoccerMatch();
+                final Team homeTeam = new Team();
+                final Team awayTeam = new Team();
+
+                homeTeam.setTeamId(rs.getInt(Constants.HOME_TEAM_ID));
+                awayTeam.setTeamId(rs.getInt(Constants.AWAY_TEAM_ID));
+                homeTeam.setTeamName(rs.getString(Constants.HOME_TEAM_NAME));
+                awayTeam.setTeamName(rs.getString(Constants.AWAY_TEAM_NAME));
+                homeTeam.setTeamLeagueId(rs.getInt(Constants.LEAGUE_ID));
+                awayTeam.setTeamLeagueId(rs.getInt(Constants.LEAGUE_ID));
+                homeTeam.setTeamLeague(rs.getString("leagueName"));
+                awayTeam.setTeamLeague(rs.getString("leagueName"));
+                homeTeam.setCountryId(rs.getInt(Constants.COUNTRY_ID));
+                awayTeam.setCountryId(rs.getInt(Constants.COUNTRY_ID));
+                homeTeam.setCountryName(rs.getString("countryName"));
+                awayTeam.setCountryName(rs.getString("countryName"));
+
+                sm.setLeagueName(rs.getString("leagueName"));
+                sm.setCountryName(rs.getString("countryName"));
+                sm.setAwayScore(rs.getInt(Constants.AWAY_SCORE));
+                sm.setHomeScore(rs.getInt(Constants.HOME_SCORE));
+                sm.setHomeTeam(homeTeam);
+                sm.setAwayTeam(awayTeam);
+                sm.setMatchId(rs.getInt(Constants.ID));
+                sm.setOdds1(rs.getFloat(Constants.ODDS_1));
+                sm.setOddsX(rs.getFloat(Constants.ODDS_X));
+                sm.setOdds2(rs.getFloat(Constants.ODDS_2));
+                sm.setGameDate(LocalDateTime.parse(rs.getString(Constants.GAME_DATE)));
+                sm.setSeason(rs.getString(Constants.SEASON));
+
+                sm.setHomeTeamName(homeTeam.getTeamName());
+                sm.setAwayTeamName(awayTeam.getTeamName());
+
+                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 (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, teamLeague);
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result = new League(rs.getInt(Constants.ID), rs.getString("name"), rs.getInt("scoringDiffLastGame"),
+                        rs.getInt("scoringTotal"),
+                        rs.getInt("winLossRatioHomeAndAway"), rs.getInt("winLossRatio"));
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public League getLeagueInfo(int leagueId) {
+        final String sql = "SELECT * FROM League WHERE id = ?";
+        League result = null;
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, leagueId);
+            final ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result = new League(rs.getInt(Constants.ID), rs.getString("name"), rs.getInt("scoringDiffLastGame"),
+                        rs.getInt("scoringTotal"),
+                        rs.getInt("winLossRatioHomeAndAway"), rs.getInt("winLossRatio"));
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public void setTeamMarginHome(int teamId, int marginHome) {
+        final String sql = "UPDATE Team SET marginHome = ? WHERE id = ?";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, marginHome);
+            stat.setInt(2, teamId);
+
+            stat.executeUpdate();
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void setTeamMarginDraw(int teamId, int marginDraw) {
+        final String sql = "UPDATE Team SET marginDraw = ? WHERE id = ?";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, marginDraw);
+            stat.setInt(2, teamId);
+
+            stat.executeUpdate();
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void setTeamMarginAway(int teamId, int marginAway) {
+        final String sql = "UPDATE Team SET marginAway = ? WHERE id = ?";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, marginAway);
+            stat.setInt(2, teamId);
+
+            stat.executeUpdate();
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void setTeamLookbackHome(int teamId, int lookbackHome) {
+        final String sql = "UPDATE Team SET lookbackHome = ? WHERE id = ?";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, lookbackHome);
+            stat.setInt(2, teamId);
+
+            stat.executeUpdate();
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void setTeamLookbackDraw(int teamId, int lookbackDraw) {
+        final String sql = "UPDATE Team SET lookbackDraw = ? WHERE id = ?";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, lookbackDraw);
+            stat.setInt(2, teamId);
+
+            stat.executeUpdate();
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void setTeamLookbackAway(int teamId, int lookbackAway) {
+        final String sql = "UPDATE Team SET lookbackAway = ? WHERE id = ?";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, lookbackAway);
+            stat.setInt(2, teamId);
+
+            stat.executeUpdate();
+
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public List<BetDTO> getBetSeries(boolean includeInactive) {
+        List<BetDTO> result = new ArrayList<>();
+        String sql = "SELECT ab.*, sr.gameDate as gameDate, sr.id as gameId, sr.homeScore as homeScore, sr.awayScore as awayScore, "
+                + "ht.name as homeTeam, aw.name as awayTeam " + "FROM ActiveBets ab "
+                + "INNER JOIN SoccerResults sr ON ab.gameId = sr.id "
+                + "INNER JOIN Team ht ON sr.homeTeamId = ht.id " + "INNER JOIN Team aw ON sr.awayTeamId = aw.id "
+                + "WHERE done = ? ORDER BY series ASC, sr.gameDate DESC";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setBoolean(1, includeInactive);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                BetDTO dto = new BetDTO();
+                dto.setHomeTeam(rs.getString("homeTeam"));
+                dto.setAwayTeam(rs.getString("awayTeam"));
+                dto.setBet(rs.getFloat("bet"));
+                dto.setBetType(rs.getString("betType"));
+                dto.setBetSeries(rs.getInt("series"));
+                dto.setGameId(rs.getInt("gameId"));
+                dto.setMatch(rs.getString("homeTeam"), rs.getString("awayTeam"));
+                dto.setOdds(rs.getFloat("odds"));
+                dto.setResult(rs.getInt("homeScore"), rs.getInt("AwayScore"));
+                dto.setGameDate(rs.getString("gameDate"));
+                dto.setWinAmount(rs.getFloat("odds") * rs.getFloat("bet"));
+                result.add(dto);
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public void addBetSeries(BetDTO bet) {
+        String sql = "INSERT INTO ActiveBets (series, gameId, betType, bet, odds, done) VALUES (?, ?, ?, ?, ?, ?)";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, bet.getBetSeries());
+            stat.setInt(2, getGameId(bet.getHomeTeam(), bet.getAwayTeam(), bet.getGameDate(), bet.getCountryId(),
+                    bet.getLeagueId()));
+            stat.setString(3, bet.getBetType());
+            stat.setFloat(4, bet.getBet());
+            stat.setFloat(5, bet.getOdds());
+            stat.setBoolean(6, false);
+
+            stat.execute();
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public int getGameId(String homeTeam, String awayTeam, String gameDate, int countryId, int leagueId) {
+        int result = -1;
+        String sql = "SELECT id FROM SoccerResults WHERE homeTeamId = (SELECT id FROM Team WHERE name = ? AND countryId = ? AND leagueId = ?) AND awayTeamId = (SELECT id FROM Team WHERE name = ? AND countryId = ? AND leagueId = ?) AND DATE(gameDate) = DATE(?)";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, homeTeam);
+            stat.setInt(2, countryId);
+            stat.setInt(3, leagueId);
+            stat.setString(4, awayTeam);
+            stat.setInt(5, countryId);
+            stat.setInt(6, leagueId);
+            stat.setString(7, gameDate);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result = rs.getInt("id");
+            }
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public Map<String, String> getPreviousMatches(int numberOfMatches, String homeTeamName, String awayTeamName,
+            String date, int countryId,
+            int leagueId) {
+        Map<String, String> result = new HashMap<>();
+
+        String homeTeamSql = "SELECT * FROM SoccerResults sr INNER JOIN Team t ON sr.homeTeamId = t.id WHERE t.name = ? AND sr.leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC limit ?";
+        String awayTeamSql = "SELECT * FROM SoccerResults sr INNER JOIN Team t ON sr.awayTeamId = t.id WHERE t.name = ? AND sr.leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC limit ?";
+        String combinedSql = "SELECT * FROM SoccerResults sr INNER JOIN Team homeTeam ON homeTeamId = homeTeam.id INNER JOIN Team awayTeam ON sr.awayTeamId = awayTeam.id WHERE homeTeam.name = ? AND awayTeam.name = ? AND sr.leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?";
+        String combinedReverseSql = "SELECT * FROM SoccerResults sr INNER JOIN Team homeTeam ON homeTeamId = homeTeam.id INNER JOIN Team awayTeam ON sr.awayTeamId = awayTeam.id WHERE homeTeam.name = ? AND awayTeam.name = ? AND sr.leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?";
+        try (PreparedStatement homeTeamStat = conn.prepareStatement(homeTeamSql);
+                PreparedStatement awayTeamStat = conn.prepareStatement(awayTeamSql);
+                PreparedStatement combinedStat = conn.prepareStatement(combinedSql);
+                PreparedStatement combinedReversedStat = conn.prepareStatement(combinedReverseSql);) {
+
+            homeTeamStat.setString(1, homeTeamName);
+            homeTeamStat.setInt(2, leagueId);
+            homeTeamStat.setString(3, date);
+            homeTeamStat.setInt(4, numberOfMatches);
+
+            awayTeamStat.setString(1, awayTeamName);
+            awayTeamStat.setInt(2, leagueId);
+            awayTeamStat.setString(3, date);
+            awayTeamStat.setInt(4, numberOfMatches);
+
+            combinedStat.setString(1, homeTeamName);
+            combinedStat.setString(2, awayTeamName);
+            combinedStat.setInt(3, leagueId);
+            combinedStat.setString(4, date);
+            combinedStat.setInt(5, numberOfMatches);
+
+            combinedReversedStat.setString(1, awayTeamName);
+            combinedReversedStat.setString(2, homeTeamName);
+            combinedReversedStat.setInt(3, leagueId);
+            combinedReversedStat.setString(4, date);
+            combinedReversedStat.setInt(5, numberOfMatches);
+
+            ResultSet homeTeamRs = homeTeamStat.executeQuery();
+            ResultSet awayTeamRs = awayTeamStat.executeQuery();
+            ResultSet combinedTeamRs = combinedStat.executeQuery();
+            ResultSet combinedReversedTeamRs = combinedReversedStat.executeQuery();
+
+            String homeTeamMeets = "";
+            while (homeTeamRs.next()) {
+                homeTeamMeets += homeTeamRs.getInt("homeScore") + "-" + homeTeamRs.getInt("awayScore") + ", ";
+            }
+            String awayTeamMeets = "";
+            while (awayTeamRs.next()) {
+                awayTeamMeets += awayTeamRs.getInt("homeScore") + "-" + awayTeamRs.getInt("awayScore") + ", ";
+            }
+            String combinedMeets = "";
+            while (combinedTeamRs.next()) {
+                combinedMeets += combinedTeamRs.getInt("homeScore") + "-" + combinedTeamRs.getInt("awayScore") + ", ";
+            }
+            String combinedReversedMeets = "";
+            while (combinedReversedTeamRs.next()) {
+                combinedReversedMeets += combinedReversedTeamRs.getInt("homeScore") + "-"
+                        + combinedReversedTeamRs.getInt("awayScore") + ", ";
+            }
+            if (homeTeamMeets.length() > 2) {
+                result.put("PrevHomeTeam", homeTeamMeets.substring(0, homeTeamMeets.length() - 2));
+            } else {
+                result.put("PrevHomeTeam", homeTeamMeets);
+            }
+            if (awayTeamMeets.length() > 2) {
+                result.put("PrevAwayTeam", awayTeamMeets.substring(0, awayTeamMeets.length() - 2));
+            } else {
+                result.put("PrevAwayTeam", awayTeamMeets);
+            }
+            if (combinedMeets.length() > 2) {
+                result.put("PrevCombined", combinedMeets.substring(0, combinedMeets.length() - 2));
+            } else {
+                result.put("PrevCombined", combinedMeets);
+            }
+
+            if (combinedReversedMeets.length() > 2) {
+                result.put("PrevReversedCombined",
+                        combinedReversedMeets.substring(0, combinedReversedMeets.length() - 2));
+            } else {
+                result.put("PrevReversedCombined", combinedReversedMeets);
+            }
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public int getBetSeriesEndNumber() {
+        int result = -1;
+        String sql = "SELECT MAX(series) FROM ActiveBets";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result = rs.getInt(1);
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public List<SoccerMatch> getMatches(int sportId, String dateString, String sortOrder, boolean exactDate) {
+        return getMatches(sportId, null, null, dateString, sortOrder, exactDate, true);
+    }
+
+    public void updateBetBaseAmount(String value) {
+        String sql = "INSERT INTO Settings (name, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = ?";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, "BetBaseAmount");
+            stat.setString(2, value);
+            stat.setString(3, value);
+
+            stat.execute();
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public String getBetBaseAmount() {
+        String sql = "SELECT value FROM Settings WHERE name = ?";
+        String result = "";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, "BetBaseAmount");
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result = rs.getString("value");
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public void updateBetStatus(int betId, Status newStatus) {
+        String sql = "UPDATE AnalysisBetTable SET status = ? WHERE id = ?";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, newStatus.name());
+            stat.setInt(2, betId);
+
+            stat.executeUpdate();
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public Team getTeam(int teamId) {
+        Team result = null;
+        String sql = "SELECT t.*, c.name as countryName, l.name AS leagueName FROM Team t "
+                + "INNER JOIN Country c ON t.countryId = c.id "
+                + "INNER JOIN League l ON t.leagueId = l.id "
+                + "WHERE id = ? ";
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, teamId);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result = new Team(rs.getInt("id"), rs.getString("name"), rs.getInt("countryId"),
+                        rs.getString("countryName"), rs.getInt("leagueId"), rs.getString("leagueName"));
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    public List<Bet> getAnalysisBets() {
+        List<Bet> result = new ArrayList<>();
+        String sql = "SELECT * FROM AnalysisBetTable abt "
+                + "INNER JOIN SoccerResults sr ON abt.matchId = sr.id ";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+
+                SoccerMatch match = new SoccerMatch(rs.getInt("matchId"), getTeam(rs.getInt("homeTeamId")),
+                        getTeam(rs.getInt("awayTeamId")),
+                        rs.getFloat("odds1"),
+                        rs.getFloat("oddsX"), rs.getFloat("odds2"), rs.getInt("homeScore"), rs.getInt("awayScore"),
+                        LocalDateTime.parse(rs.getString("gameDate")), rs.getString("season"));
+
+                new Bet(rs.getInt("id"), match, rs.getFloat("betAmount"), rs.getFloat("betOdds"),
+                        Status.valueOf(rs.getString("status")));
+            }
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    public void addAnalysisBet(Bet bet) {
+        String sql = "INSERT INTO AnalysisBetTable (matchId, betAmount, betOdds, status) VALUES (?,?,?,?)";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, bet.getMatch().getMatchId());
+            stat.setFloat(2, bet.getBetAmount());
+            stat.setFloat(3, bet.getBetOdds());
+            stat.setString(4, bet.getStatus().name());
+
+            stat.execute();
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+    }
 }

+ 170 - 96
OddsJavaFx/src/data/TestDatabase.java

@@ -5,6 +5,7 @@ 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;
 
@@ -14,101 +15,174 @@ import tests.objects.LeagueDTO;
 
 public class TestDatabase extends GuiMysql {
 
-	private static TestDatabase instance;
-	private Connection conn;
-
-	private TestDatabase() {
-		conn = getConnection();
-	}
-
-	public static TestDatabase getInstance() {
-		if (instance == null) {
-			instance = new TestDatabase();
-		}
-
-		return instance;
-	}
-
-	public int getLeagueId(int countryId, String leagueName) {
-		String sql = "SELECT id FROM League WHERE name = ? AND countryId = ?";
-		int result = -1;
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, leagueName);
-			stat.setInt(2, countryId);
-
-			ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				result = rs.getInt("id");
-			}
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
-
-	@Override public int getCountryId(String countryName) {
-		String sql = "SELECT id FROM country WHERE name = ?";
-		int result = -1;
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setString(1, countryName);
-
-			ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				result = rs.getInt("id");
-			}
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
-
-	public List<LeagueDTO> getPrioLeagues() {
-		String sql = "SELECT l.id as id, l.name as name, l.countryId as countryId, c.name as countryName FROM `League` l inner join Country c ON c.id = l.countryId where l.prio = ?";
-		List<LeagueDTO> result = new ArrayList<>();
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-			stat.setBoolean(1, true);
-
-			ResultSet rs = stat.executeQuery();
-
-			while (rs.next()) {
-				result.add(new LeagueDTO(rs.getInt("id"), rs.getString("name"), rs.getInt("countryId"), rs.getString("countryName")));
-			}
-
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
-
-	public List<SoccerMatch> getMatches(LeagueDTO league) {
-		String sql = "SELECT sr.*, ht.name as homeTeam, awt.name as awayTeam, c.name AS countryName, c.id AS countryId FROM SoccerResults sr INNER JOIN Country c ON c.id = sr.countryId INNER JOIN Team ht ON ht.id = sr.homeTeamId INNER JOIN Team awt ON awt.id = sr.awayTeamId WHERE sr.leagueId = ? ORDER BY gameDate ASC";
-		List<SoccerMatch> result = new ArrayList<>();
-
-		try (PreparedStatement stat = conn.prepareStatement(sql)) {
-
-			stat.setInt(1, league.getId());
-			ResultSet rs = stat.executeQuery();
-			while (rs.next()) {
-				result.add(new SoccerMatch(rs.getInt("id"),
-						new Team(rs.getInt("homeTeamId"), rs.getString("homeTeam"), rs.getInt("countryId"), rs.getString("countryName"),
-								league.getId(), league.getName()),
-						new Team(rs.getInt("awayTeamId"), rs.getString("awayTeam"), rs.getInt("countryId"), rs.getString("countryName"),
-								league.getId(), league.getName()),
-						rs.getFloat("odds1"), rs.getFloat("oddsX"), rs.getFloat("odds2"), rs.getInt("homeScore"), rs.getInt("awayScore"),
-						LocalDateTime.parse(rs.getString("gameDate")), rs.getString("season")));
-			}
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
+    private static TestDatabase instance;
+    private Connection conn;
+
+    private TestDatabase() {
+        conn = getConnection();
+    }
+
+    public static TestDatabase getInstance() {
+        if (instance == null) {
+            instance = new TestDatabase();
+        }
+
+        return instance;
+    }
+
+    public int getLeagueId(int countryId, String leagueName) {
+        String sql = "SELECT id FROM League WHERE name = ? AND countryId = ?";
+        int result = -1;
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, leagueName);
+            stat.setInt(2, countryId);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result = rs.getInt("id");
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    @Override
+    public int getCountryId(String countryName) {
+        String sql = "SELECT id FROM country WHERE name = ?";
+        int result = -1;
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setString(1, countryName);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result = rs.getInt("id");
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public List<LeagueDTO> getPrioLeagues() {
+        String sql = "SELECT l.id as id, l.name as name, l.countryId as countryId, c.name as countryName FROM `League` l inner join Country c ON c.id = l.countryId where l.prio = ?";
+        List<LeagueDTO> result = new ArrayList<>();
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setBoolean(1, true);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result.add(new LeagueDTO(rs.getInt("id"), rs.getString("name"), rs.getInt("countryId"),
+                        rs.getString("countryName")));
+            }
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public LeagueDTO getLeagueDTO(int leagueId) {
+        String sql = "SELECT l.id as id, l.name as name, l.countryId as countryId, c.name as countryName FROM `League` l inner join Country c ON c.id = l.countryId where l.id = ?";
+        LeagueDTO result = null;
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, leagueId);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result = new LeagueDTO(rs.getInt("id"), rs.getString("name"), rs.getInt("countryId"),
+                        rs.getString("countryName"));
+            }
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public List<SoccerMatch> getMatches(LeagueDTO league) {
+        String sql = "SELECT sr.*, ht.name as homeTeam, awt.name as awayTeam, c.name AS countryName, c.id AS countryId FROM SoccerResults sr INNER JOIN Country c ON c.id = sr.countryId INNER JOIN Team ht ON ht.id = sr.homeTeamId AND ht.leagueId = sr.leagueId INNER JOIN Team awt ON awt.id = sr.awayTeamId AND awt.leagueId = sr.leagueId  WHERE sr.leagueId = ? ORDER BY gameDate ASC";
+        List<SoccerMatch> result = new ArrayList<>();
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+
+            stat.setInt(1, league.getId());
+            ResultSet rs = stat.executeQuery();
+            while (rs.next()) {
+                SoccerMatch sm = new SoccerMatch(rs.getInt("id"),
+                        new Team(rs.getInt("homeTeamId"), rs.getString("homeTeam"), rs.getInt("countryId"),
+                                rs.getString("countryName"),
+                                league.getId(), league.getName()),
+                        new Team(rs.getInt("awayTeamId"), rs.getString("awayTeam"), rs.getInt("countryId"),
+                                rs.getString("countryName"),
+                                league.getId(), league.getName()),
+                        rs.getFloat("odds1"), rs.getFloat("oddsX"), rs.getFloat("odds2"), rs.getInt("homeScore"),
+                        rs.getInt("awayScore"),
+                        LocalDateTime.parse(rs.getString("gameDate")), rs.getString("season"));
+                sm.setHomeTeamName(rs.getString("homeTeam"));
+                sm.setAwayTeamName(rs.getString("awayTeam"));
+                result.add(sm);
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public float getRoundedDiff(SoccerMatch soccerMatch) {
+        float result = -1f;
+        String sql = "SELECT ROUND((sHome.avgScored * sAway.avgConceded) + (sAway.avgScored * sHome.avgConceded),1) roundedDiff "
+                + "FROM SoccerResults "
+                + "INNER JOIN (SELECT homeTeamId, AVG(homeScore) as avgScored, AVG(awayScore) as avgConceded "
+                + "FROM SoccerResults "
+                + "WHERE homeScore != -1 AND homeTeamId = ? AND DATE(gameDate) < ? AND leagueId = ? "
+                + "GROUP BY homeTeamId) as sHome "
+                + "ON SoccerResults.homeTeamId = sHome.homeTeamId "
+                + "INNER JOIN (SELECT awayTeamId, AVG(homeScore) as avgConceded, AVG(awayScore) as avgScored "
+                + "FROM SoccerResults "
+                + "WHERE awayScore != -1 AND awayTeamId = ? AND DATE(gameDate) < ? AND leagueId = ? "
+                + "GROUP BY awayTeamId) as sAway "
+                + "ON SoccerResults.awayTeamId = sAway.awayTeamId "
+                + "WHERE homeScore != -1 "
+                + "AND awayScore != -1 "
+                + "AND leagueId = ? "
+                + "AND DATE(gameDate) < ? "
+                + "GROUP BY roundedDiff;";
+
+        try (PreparedStatement stat = conn.prepareStatement(sql)) {
+            stat.setInt(1, soccerMatch.getHomeTeam().getTeamId());
+            stat.setString(2, soccerMatch.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(3, soccerMatch.getHomeTeam().getTeamLeagueId());
+
+            stat.setInt(4, soccerMatch.getAwayTeam().getTeamId());
+            stat.setString(5, soccerMatch.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(6, soccerMatch.getAwayTeam().getTeamLeagueId());
+
+            stat.setInt(7, soccerMatch.getHomeTeam().getTeamLeagueId());
+            stat.setString(8, soccerMatch.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result = rs.getFloat("roundedDiff");
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
 
 }

+ 81 - 0
OddsJavaFx/src/fxml/AnalysisTesting.fxml

@@ -0,0 +1,81 @@
+<?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.SplitPane?>
+<?import javafx.scene.control.TableColumn?>
+<?import javafx.scene.control.TableView?>
+<?import javafx.scene.control.TextField?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.FlowPane?>
+<?import javafx.scene.layout.VBox?>
+
+<AnchorPane xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.AnalysisTestController">
+   <children>
+      <VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+         <children>
+            <FlowPane alignment="CENTER_LEFT" prefHeight="30.0">
+               <children>
+                  <TextField fx:id="bankTextField" promptText="Bank" />
+                  <TextField fx:id="bettingPercentTextField" promptText="Betting percent" />
+                  <DatePicker fx:id="date" />
+                  <Button fx:id="getMatchesButton" mnemonicParsing="false" onAction="#GetMatchesAction" text="Get Matches" />
+               </children>
+            </FlowPane>
+            <SplitPane dividerPositions="0.5" orientation="VERTICAL">
+              <items>
+                <AnchorPane>
+                     <children>
+                        <ScrollPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                           <content>
+                              <TableView fx:id="gameViewTable" />
+                           </content>
+                        </ScrollPane>
+                     </children>
+                  </AnchorPane>
+                <AnchorPane>
+                     <children>
+                        <SplitPane dividerPositions="0.6666666666666666" prefHeight="281.0" prefWidth="398.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                          <items>
+                            <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
+                                 <children>
+                                    <ScrollPane prefHeight="158.0" prefWidth="56.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                                       <content>
+                                          <TableView fx:id="activeBetsTable" />
+                                       </content>
+                                    </ScrollPane>
+                                 </children>
+                              </AnchorPane>
+                            <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
+                                 <children>
+                                    <VBox prefHeight="339.0" prefWidth="129.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+                                       <children>
+                                          <Button fx:id="checkBetsButton" mnemonicParsing="false" onAction="#CheckBetsAction" text="Check bets" />
+                                          <Button mnemonicParsing="false" onAction="#RemoveDoneBetsAction" text="Remove Done bets" />
+                                          <TableView fx:id="LeagueBetStatsTable" prefHeight="200.0" prefWidth="200.0">
+                                            <columns>
+                                              <TableColumn fx:id="statsLeagueNameColumn" prefWidth="75.0" text="League" />
+                                              <TableColumn fx:id="statsHomeWinColumn" prefWidth="75.0" text="Home Wins" />
+                                              <TableColumn fx:id="statsHomeLossColumn" prefWidth="75.0" text="Home Losses" />
+                                              <TableColumn fx:id="statsHomePercentColumn" prefWidth="75.0" text="Home Percent" />
+                                              <TableColumn fx:id="statsAwayWinColumn" prefWidth="75.0" text="Away Wins" />
+                                              <TableColumn fx:id="statsAwayLossColumn" prefWidth="75.0" text="Away Losses" />
+                                              <TableColumn fx:id="statsAwayPercentColumn" prefWidth="75.0" text="Away Percent" />
+                                              <TableColumn fx:id="statsTotalPercentColumn" prefWidth="75.0" text="Total Percent" />
+                                            </columns>
+                                          </TableView>
+                                       </children>
+                                    </VBox>
+                                 </children>
+                              </AnchorPane>
+                          </items>
+                        </SplitPane>
+                     </children>
+                  </AnchorPane>
+              </items>
+            </SplitPane>
+         </children>
+      </VBox>
+   </children>
+</AnchorPane>

+ 13 - 33
OddsJavaFx/src/fxml/MatchTabBuilder.fxml

@@ -1,48 +1,29 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
+<?import javafx.geometry.Insets?>
 <?import javafx.scene.control.Button?>
 <?import javafx.scene.control.SplitPane?>
-<?import javafx.scene.control.TableColumn?>
 <?import javafx.scene.control.TableView?>
+<?import javafx.scene.control.TextField?>
 <?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.FlowPane?>
 <?import javafx.scene.layout.HBox?>
-<?import javafx.scene.text.Text?>
 <?import javafx.scene.layout.VBox?>
+<?import javafx.scene.text.Text?>
 
-<AnchorPane xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1"
-  fx:controller="controllers.MatchTabController">
+<AnchorPane xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.MatchTabController">
   <children>
-    <SplitPane dividerPositions="0.7305764411027569" orientation="VERTICAL" prefHeight="800.0" prefWidth="1000.0"
-      AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+    <SplitPane dividerPositions="0.7305764411027569" orientation="VERTICAL" prefHeight="800.0" prefWidth="1000.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
       <items>
         <VBox alignment="center" minHeight="0.0" minWidth="0.0" prefHeight="700.0" prefWidth="1000.0">
           <children>
+                  <FlowPane prefHeight="30.0" prefWidth="998.0">
+                     <children>
+                        <Text strokeType="OUTSIDE" strokeWidth="0.0" text="This weeks bet amount" />
+                        <TextField fx:id="betAmountTextField" />
+                     </children>
+                  </FlowPane>
             <TableView fx:id="matchTable" prefHeight="580.0" prefWidth="1427.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" />
-                <TableColumn fx:id="scoringScore" prefWidth="75.0" text="Scoring score" />
-                <TableColumn fx:id="ownOddsPerdiction" text="Calculated Odds"/>
-                <TableColumn fx:id="givenOdds" text="Given Odds"/>
-                <TableColumn fx:id="percentageToBet" text="Percentage to Bet"/>
-              </columns>
             </TableView>
           </children>
         </VBox>
@@ -51,8 +32,7 @@
             <HBox prefHeight="23.0" prefWidth="998.0">
               <children>
                 <Button mnemonicParsing="false" onAction="#addRowAction" text="Add New Row" />
-                <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Över 1.5 om score &gt; 5 och under 4.5 om score &lt; 3"
-                  wrappingWidth="303.486328125" />
+                <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Över 1.5 om score &gt; 5 och under 4.5 om score &lt; 3" wrappingWidth="303.486328125" />
               </children>
             </HBox>
 

+ 5 - 0
OddsJavaFx/src/fxml/OddsFxBuilder.fxml

@@ -119,6 +119,11 @@
 	                   <fx:include fx:id="testsTab" source="Testing.fxml" />
 	                </content>
                 </Tab>
+                <Tab text="Analyze Betting">
+                  <content>
+                     <fx:include fx:id="analyzeTesting" source="AnalysisTesting.fxml" />
+                  </content>
+                </Tab>
               </tabs>
             </TabPane>
          </center>

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

@@ -60,6 +60,7 @@
 				       <TableColumn fx:id="positionAdjustmentColumn" prefWidth="75.0" text="Position Adjustments" />
 				       <TableColumn fx:id="newScoringTestColumn" prefWidth="75.0" text="New scoring test" />
 				       <TableColumn fx:id="addToBetsButtonColumn" prefWidth="75.0" text="Add bet" />
+                       <TableColumn fx:id="analysisColumn" prefWidth="75.0" text="Analysis" />
 				     </columns>
 				   </TableView>
                </children>

+ 25 - 28
OddsJavaFx/src/fxml/Testing.fxml

@@ -7,10 +7,9 @@
 <?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">
+<AnchorPane fx:id="basePane" prefWidth="736.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.TestsController">
    <children>
       <VBox prefHeight="414.0" prefWidth="736.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
          <children>
@@ -23,20 +22,20 @@
             		    <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" />
-                                                        <Button onAction="#standingsTest" text="Standings test"/>
+                        <Button fx:id="getLeagueInfoButton" disable="true" mnemonicParsing="false" onAction="#getLeagueInfo" prefHeight="30.0" prefWidth="96.0" text="Get league info" />
+                        <Button fx:id="getMoreLeagueInfoButton" disable="true" mnemonicParsing="false" onAction="#getMoreLeagueInfo" prefHeight="30.0" prefWidth="96.0" text="Get more league info" />
+                                                        <Button onAction="#standingsTest" text="Standings test" />
                      </children>
                   </FlowPane>
                </children>
             </AnchorPane>
-          <AnchorPane fx:id="testSettingsPanel" prefHeight="386.0" prefWidth="736.0">
+          <AnchorPane fx:id="testSettingsPanel" 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">
+                  <SplitPane dividerPositions="0.5" prefWidth="736.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                     <items>
-                      <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
+                      <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.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">
+                              <VBox 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" />
@@ -46,39 +45,37 @@
                               </VBox>
                            </children>
                         </AnchorPane>
-                      <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
+                      <AnchorPane minHeight="0.0" minWidth="0.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">
+                              <VBox fx:id="testPanelVBox" prefWidth="512.0"  prefHeight="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"/>
-                                    <Button fx:id="homeTest" onAction="#homeTestAction" text="Home Test"/>
-                                    <Button fx:id="drawTest" onAction="#drawTestAction" text="Draw Test"/>
-                                    <Button fx:id="awayTest" onAction="#awayTestAction" text="Away Test"/>
-                                    <Button fx:id="homeDrawAwayTest" onAction="#homeDrawAwayTestAction" text="Combined 1X2 Test"/>
-                                    <Button fx:id="homeTeamTest" onAction="#homeTeamTestAction" text="Home Team margin test"/>
-                                    <Button fx:id="awayTeamTest" onAction="#awayTeamTestAction" text="Away Team margin test"/>
-                                    <Button fx:id="addedScoreTest" onAction="#addedScoreTestAction" text="Added score test"/>
-                                    <Button fx:id="recalcTest" onAction="#recalcTestAction" text="Recalc test"/>
+                                    <Button fx:id="calcBestValues" onAction="#calcBestResultsAction" text="Calc Best values" />
+                                    <Button fx:id="topLeaguesTest" onAction="#topLeaguesTestAction" text="Top Leagues Test" />
+                                    <Button fx:id="homeTest" onAction="#homeTestAction" text="Home Test" />
+                                    <Button fx:id="drawTest" onAction="#drawTestAction" text="Draw Test" />
+                                    <Button fx:id="awayTest" onAction="#awayTestAction" text="Away Test" />
+                                    <Button fx:id="homeDrawAwayTest" onAction="#homeDrawAwayTestAction" text="Combined 1X2 Test" />
+                                    <Button fx:id="homeTeamTest" onAction="#homeTeamTestAction" text="Home Team margin test" />
+                                    <Button fx:id="awayTeamTest" onAction="#awayTeamTestAction" text="Away Team margin test" />
+                                    <Button fx:id="addedScoreTest" onAction="#addedScoreTestAction" text="Added score test" />
+                                    <Button fx:id="recalcTest" onAction="#recalcTestAction" text="Recalc test" />
+                                    <Button fx:id="fibonacciDrawTest" onAction="#fibonacciDrawTestAction" text="Fibonacci draw test" />
+                                    <Button onAction="#goalDiffTest" text="GoalDiff" />
+                                    <Button onAction="#relevanceTest" text="Test for Relevance" />
+                                    <Button onAction="#analysisTets" text="Analysis 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>

+ 136 - 112
OddsJavaFx/src/objects/League.java

@@ -2,120 +2,144 @@ package objects;
 
 public class League {
 
-	int leagueId;
-	String leagueName;
-	int lookback;
-	int betMargin;
+    int leagueId;
+    String leagueName;
+    int lookback;
+    int betMargin;
+
+    int lookbackHome;
+    int lookbackDraw;
+    int lookbackAway;
+
+    int betMarginHome;
+    int betMarginDraw;
+    int betMarginAway;
+
+    int scoringDiffLastGame;
+    int scoringTotal;
+    int winLossRatioHomeAndAway;
+    int winLossRatio;
+
+    public League(int leagueId, String leagueName, int scoringDiffLastGame,
+            int scoringTotal, int winLossRatioHomeAndAway, int winLossRatio) {
+        this.leagueId = leagueId;
+        this.leagueName = leagueName;
+        this.scoringDiffLastGame = scoringDiffLastGame;
+        this.scoringTotal = scoringTotal;
+        this.winLossRatioHomeAndAway = winLossRatioHomeAndAway;
+        this.winLossRatio = winLossRatio;
+    }
+
+    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;
+    }
+
+    public int getLookbackHome() {
+        return lookbackHome;
+    }
+
+    public int getLookbackDraw() {
+        return lookbackDraw;
+    }
+
+    public int getLookbackAway() {
+        return lookbackAway;
+    }
+
+    public int getBetMarginHome() {
+        return betMarginHome;
+    }
+
+    public int getBetMarginDraw() {
+        return betMarginDraw;
+    }
+
+    public int getBetMarginAway() {
+        return betMarginAway;
+    }
+
+    public void setLookbackHome(int lookbackHome) {
+        this.lookbackHome = lookbackHome;
+    }
+
+    public void setLookbackDraw(int lookbackDraw) {
+        this.lookbackDraw = lookbackDraw;
+    }
+
+    public void setLookbackAway(int lookbackAway) {
+        this.lookbackAway = lookbackAway;
+    }
+
+    public void setBetMarginHome(int betMarginHome) {
+        this.betMarginHome = betMarginHome;
+    }
+
+    public void setBetMarginDraw(int betMarginDraw) {
+        this.betMarginDraw = betMarginDraw;
+    }
+
+    public void setBetMarginAway(int betMarginAway) {
+        this.betMarginAway = betMarginAway;
+    }
+
+    public int getScoringDiffLastGame() {
+        return scoringDiffLastGame;
+    }
+
+    public int getScoringTotal() {
+        return scoringTotal;
+    }
+
+    public int getWinLossRatioHomeAndAway() {
+        return winLossRatioHomeAndAway;
+    }
+
+    public int getWinLossRatio() {
+        return winLossRatio;
+    }
+
+    public void setScoringDiffLastGame(int scoringDiffLastGame) {
+        this.scoringDiffLastGame = scoringDiffLastGame;
+    }
 
-	int lookbackHome;
-	int lookbackDraw;
-	int lookbackAway;
+    public void setScoringTotal(int scoringTotal) {
+        this.scoringTotal = scoringTotal;
+    }
 
-	int betMarginHome;
-	int betMarginDraw;
-	int betMarginAway;
+    public void setWinLossRatioHomeAndAway(int winLossRatioHomeAndAway) {
+        this.winLossRatioHomeAndAway = winLossRatioHomeAndAway;
+    }
 
-	public League(int leagueId, String leagueName, int lookback, int betMargin, int lookbackHome, int lookbackDraw, int lookbackAway,
-			int betMarginHome, int betMarginDraw, int betMarginAway) {
-		this.leagueId = leagueId;
-		this.leagueName = leagueName;
-		this.lookback = lookback;
-		this.betMargin = betMargin;
-		this.lookbackHome = lookbackHome;
-		this.lookbackDraw = lookbackDraw;
-		this.lookbackAway = lookbackAway;
-		this.betMarginHome = betMarginHome;
-		this.betMarginDraw = betMarginDraw;
-		this.betMarginAway = betMarginAway;
-	}
-
-
-	public League() {}
-
-
-	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;
-	}
-
-
-	public int getLookbackHome() {
-		return lookbackHome;
-	}
-
-
-	public int getLookbackDraw() {
-		return lookbackDraw;
-	}
-
-
-	public int getLookbackAway() {
-		return lookbackAway;
-	}
-
-
-	public int getBetMarginHome() {
-		return betMarginHome;
-	}
-
-
-	public int getBetMarginDraw() {
-		return betMarginDraw;
-	}
-
-
-	public int getBetMarginAway() {
-		return betMarginAway;
-	}
-
-
-	public void setLookbackHome(int lookbackHome) {
-		this.lookbackHome = lookbackHome;
-	}
-
-
-	public void setLookbackDraw(int lookbackDraw) {
-		this.lookbackDraw = lookbackDraw;
-	}
-
-
-	public void setLookbackAway(int lookbackAway) {
-		this.lookbackAway = lookbackAway;
-	}
-
-
-	public void setBetMarginHome(int betMarginHome) {
-		this.betMarginHome = betMarginHome;
-	}
-
-
-	public void setBetMarginDraw(int betMarginDraw) {
-		this.betMarginDraw = betMarginDraw;
-	}
-
-
-	public void setBetMarginAway(int betMarginAway) {
-		this.betMarginAway = betMarginAway;
-	}
+    public void setWinLossRatio(int winLossRatio) {
+        this.winLossRatio = winLossRatio;
+    }
 
 }

+ 77 - 59
OddsJavaFx/src/objects/OverUnder.java

@@ -6,63 +6,81 @@ import com.google.common.collect.Lists;
 
 public class OverUnder {
 
-	private Float key;
-	private final ArrayList<Integer> goals;
-	private int total;
-
-	public OverUnder() {
-		goals = Lists.newArrayList(0,0,0,0,0,0,0,0,0,0);
-	}
-
-	public OverUnder(Float key) {
-		this.key = key;
-		goals = Lists.newArrayList(0,0,0,0,0,0,0,0,0,0);
-	}
-
-	public void addGoalStat(int numGoals) {
-		if (numGoals > 9) {
-			Integer val = goals.get(9);
-			val++;
-			goals.set(9, val);
-		} else {
-			Integer val = goals.get(numGoals);
-			val++;
-			goals.set(numGoals, val);
-		}
-
-		updateTotal();
-	}
-
-	private void updateTotal() {
-		total = 0;
-		goals.forEach(g -> total += g);
-	}
-
-	public Float getKey() {
-		return key;
-	}
-
-	public void setKey(Float key) {
-		this.key = key;
-	}
-
-	public ArrayList<Integer> getGoals() {
-		return goals;
-	}
-
-	public int getTotal() {
-		return total;
-	}
-
-	public void setTotal(int total) {
-		this.total = total;
-	}
-
-	public float calcMinOdds(int numGoals) {
-		if (numGoals == 0) {
-			return 1F;
-		}
-		return 1 / (1 / (goals.stream().mapToInt(Integer::intValue).sum()/Float.valueOf(numGoals)));
-
-	}
+    private Float key;
+    private final ArrayList<Integer> goals;
+    private int total;
+    private int draws;
+    private int totalGames;
+
+    public OverUnder() {
+        goals = Lists.newArrayList(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+    }
+
+    public OverUnder(Float key) {
+        this.key = key;
+        goals = Lists.newArrayList(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+    }
+
+    public void addGoalStat(int numGoals) {
+        if (numGoals > 9) {
+            Integer val = goals.get(9);
+            val++;
+            goals.set(9, val);
+        } else {
+            Integer val = goals.get(numGoals);
+            val++;
+            goals.set(numGoals, val);
+        }
+
+        updateTotal();
+    }
+
+    private void updateTotal() {
+        total = 0;
+        goals.forEach(g -> total += g);
+    }
+
+    public Float getKey() {
+        return key;
+    }
+
+    public void setKey(Float key) {
+        this.key = key;
+    }
+
+    public ArrayList<Integer> getGoals() {
+        return goals;
+    }
+
+    public int getTotal() {
+        return total;
+    }
+
+    public void setTotal(int total) {
+        this.total = total;
+    }
+
+    public float calcMinOdds(int numGoals) {
+        if (numGoals == 0) {
+            return 1F;
+        }
+        return 1 / (1 / (goals.stream().mapToInt(Integer::intValue).sum() / Float.valueOf(numGoals)));
+
+    }
+
+    public int getDraws() {
+        return draws;
+    }
+
+    public void setDraws(int draws) {
+        this.draws = draws;
+    }
+
+    public int getTotalGames() {
+        return totalGames;
+    }
+
+    public void setTotalGames(int totalGames) {
+        this.totalGames = totalGames;
+    }
 }

+ 350 - 122
OddsJavaFx/src/objects/SoccerMatch.java

@@ -1,130 +1,358 @@
 package objects;
 
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
+import objects.bets.Bet;
+
 public class SoccerMatch {
 
-	private Team homeTeam;
-	private Team awayTeam;
-
-	private int matchId;
-	private int homeScore;
-	private int awayScore;
-
-	private float odds1;
-	private float oddsX;
-	private float odds2;
-
-	private LocalDateTime gameDate;
-	private String season;
-
-	private boolean countryPrio;
-	private String homeTeamName;
-	private String awayTeamName;
-
-	public SoccerMatch() {
-	}
-
-	public SoccerMatch(int id, Team homeTeam, Team awayTeam, float odds1, float oddsX, float odds2, int homeScore, int awayScore,
-			LocalDateTime gameDate, String season) {
-		this.matchId = id;
-		this.homeTeam = homeTeam;
-		this.awayTeam = awayTeam;
-		this.odds1 = odds1;
-		this.oddsX = oddsX;
-		this.odds2 = odds2;
-		this.homeScore = homeScore;
-		this.awayScore = awayScore;
-		this.gameDate = gameDate;
-		this.season = season;
-	}
-
-	public Team getHomeTeam() {
-		return homeTeam;
-	}
-
-	public Team getAwayTeam() {
-		return awayTeam;
-	}
-
-	public int getMatchId() {
-		return matchId;
-	}
-
-	public int getHomeScore() {
-		return homeScore;
-	}
-
-	public int getAwayScore() {
-		return awayScore;
-	}
-
-	public float getOdds1() {
-		return odds1;
-	}
-
-	public float getOddsX() {
-		return oddsX;
-	}
-
-	public float getOdds2() {
-		return odds2;
-	}
-
-	public void setHomeTeam(Team homeTeam) {
-		this.homeTeam = homeTeam;
-	}
-
-	public void setAwayTeam(Team awayTeam) {
-		this.awayTeam = awayTeam;
-	}
-
-	public void setMatchId(int matchId) {
-		this.matchId = matchId;
-	}
-
-	public void setHomeScore(int homeScore) {
-		this.homeScore = homeScore;
-	}
-
-	public void setAwayScore(int awayScore) {
-		this.awayScore = awayScore;
-	}
-
-	public void setOdds1(float odds1) {
-		this.odds1 = odds1;
-	}
-
-	public void setOddsX(float oddsX) {
-		this.oddsX = oddsX;
-	}
-
-	public void setOdds2(float odds2) {
-		this.odds2 = odds2;
-	}
-
-	public LocalDateTime getGameDate() {
-		return gameDate;
-	}
-
-	public void setGameDate(LocalDateTime gameDate) {
-		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;
-	}
+    private LocalDateTime gameDate;
+    private Team homeTeam;
+    private Team awayTeam;
+
+    private int matchId;
+    private int homeScore; // Actual Result home
+    private int awayScore; // Actual Result away
+    private String season;
+    private boolean countryPrio;
+
+    private String homeTeamName;
+    private String awayTeamName;
+    private float odds1;
+    private float oddsX;
+    private float odds2;
+    private BigDecimal goalsHome;
+    private BigDecimal goalsAway;
+    private BigDecimal goalsDiff;
+    private float avgScoreHome;
+    private float avgScoreAway;
+    private float avgConcededHome;
+    private float avgConcededAway;
+    private String leagueName;
+    private String countryName;
+    private String homeWin;
+    private String draw;
+    private String awayWin;
+    private Float scoringScore;
+    private Float ownOdds;
+    private Float givenOdds;
+    private Float percentageToBet;
+    private boolean addToBetSlip;
+    private Float betAmount;
+    private float roundedDiff;
+    private float drawPercentage;
+    private String analysisValue;
+    private Bet bet;
+
+    public SoccerMatch() {
+    }
+
+    public SoccerMatch(int id, Team homeTeam, Team awayTeam, float odds1, float oddsX, float odds2, int homeScore,
+            int awayScore,
+            LocalDateTime gameDate, String season) {
+        this.matchId = id;
+        this.homeTeam = homeTeam;
+        this.awayTeam = awayTeam;
+        this.odds1 = odds1;
+        this.oddsX = oddsX;
+        this.odds2 = odds2;
+        this.homeScore = homeScore;
+        this.awayScore = awayScore;
+        this.gameDate = gameDate;
+        this.season = season;
+        this.homeTeamName = homeTeam.getTeamName();
+        this.awayTeamName = awayTeam.getTeamName();
+    }
+
+    public Team getHomeTeam() {
+        return homeTeam;
+    }
+
+    public Team getAwayTeam() {
+        return awayTeam;
+    }
+
+    public int getMatchId() {
+        return matchId;
+    }
+
+    public int getHomeScore() {
+        return homeScore;
+    }
+
+    public int getAwayScore() {
+        return awayScore;
+    }
+
+    public float getOdds1() {
+        return odds1;
+    }
+
+    public float getOddsX() {
+        return oddsX;
+    }
+
+    public float getOdds2() {
+        return odds2;
+    }
+
+    public BigDecimal getGoalsHome() {
+        return goalsHome;
+    }
+
+    public void setGoalsHome(BigDecimal goalsHome) {
+        this.goalsHome = goalsHome;
+    }
+
+    public BigDecimal getGoalsAway() {
+        return goalsAway;
+    }
+
+    public void setGoalsAway(BigDecimal goalsAway) {
+        this.goalsAway = goalsAway;
+    }
+
+    public BigDecimal getGoalsDiff() {
+        return goalsDiff;
+    }
+
+    public void setGoalsDiff(BigDecimal goalsDiff) {
+        this.goalsDiff = goalsDiff;
+    }
+
+    public float getAvgScoreHome() {
+        return avgScoreHome;
+    }
+
+    public void setAvgScoreHome(float avgScoreHome) {
+        this.avgScoreHome = avgScoreHome;
+    }
+
+    public float getAvgScoreAway() {
+        return avgScoreAway;
+    }
+
+    public void setAvgScoreAway(float avgScoreAway) {
+        this.avgScoreAway = avgScoreAway;
+    }
+
+    public float getAvgConcededHome() {
+        return avgConcededHome;
+    }
+
+    public void setAvgConcededHome(float avgConcedeHome) {
+        this.avgConcededHome = avgConcedeHome;
+    }
+
+    public float getAvgConcededAway() {
+        return avgConcededAway;
+    }
+
+    public void setAvgConcededAway(float avgConcedeAway) {
+        this.avgConcededAway = avgConcedeAway;
+    }
+
+    public void setHomeTeam(Team homeTeam) {
+        this.homeTeam = homeTeam;
+    }
+
+    public void setAwayTeam(Team awayTeam) {
+        this.awayTeam = awayTeam;
+    }
+
+    public void setMatchId(int matchId) {
+        this.matchId = matchId;
+    }
+
+    public void setHomeScore(int homeScore) {
+        this.homeScore = homeScore;
+    }
+
+    public void setAwayScore(int awayScore) {
+        this.awayScore = awayScore;
+    }
+
+    public void setOdds1(float odds1) {
+        this.odds1 = odds1;
+    }
+
+    public void setOddsX(float oddsX) {
+        this.oddsX = oddsX;
+    }
+
+    public void setOdds2(float odds2) {
+        this.odds2 = odds2;
+    }
+
+    public LocalDateTime getGameDate() {
+        return gameDate;
+    }
+
+    public void setGameDate(LocalDateTime gameDate) {
+        this.gameDate = gameDate;
+    }
+
+    public String getSeason() {
+        return season;
+    }
+
+    public void setSeason(String season) {
+        this.season = season;
+    }
+
+    public boolean isCountryPrio() {
+        return countryPrio;
+    }
+
+    public String getHomeTeamName() {
+        return homeTeamName;
+    }
+
+    public void setHomeTeamName(String homeTeamName) {
+        this.homeTeamName = homeTeamName;
+    }
+
+    public String getAwayTeamName() {
+        return awayTeamName;
+    }
+
+    public void setAwayTeamName(String awayTeamName) {
+        this.awayTeamName = awayTeamName;
+    }
+
+    public void setCountryPrio(boolean countryPrio) {
+        this.countryPrio = countryPrio;
+    }
+
+    public String getLeagueName() {
+        return leagueName;
+    }
+
+    public void setLeagueName(String leagueName) {
+        this.leagueName = leagueName;
+    }
+
+    public String getCountryName() {
+        return countryName;
+    }
+
+    public void setCountryName(String countryName) {
+        this.countryName = countryName;
+    }
+
+    public String getHomeWin() {
+        return homeWin;
+    }
+
+    public void setHomeWin(String homeWin) {
+        this.homeWin = homeWin;
+    }
+
+    public String getDraw() {
+        return draw;
+    }
+
+    public void setDraw(String draw) {
+        this.draw = draw;
+    }
+
+    public String getAwayWin() {
+        return awayWin;
+    }
+
+    public void setAwayWin(String awayWin) {
+        this.awayWin = awayWin;
+    }
+
+    public Float getScoringScore() {
+        return scoringScore;
+    }
+
+    public void setScoringScore(Float scoringScore) {
+        this.scoringScore = scoringScore;
+    }
+
+    public Float getOwnOdds() {
+        return ownOdds;
+    }
+
+    public void setOwnOdds(Float ownOddsPerdiction) {
+        this.ownOdds = ownOddsPerdiction;
+    }
+
+    public Float getGivenOdds() {
+        return givenOdds;
+    }
+
+    public void setGivenOdds(Float givenOdds) {
+        this.givenOdds = givenOdds;
+    }
+
+    public Float getPercentageToBet() {
+        return percentageToBet;
+    }
+
+    public void setPercentageToBet(Float percentageToBet) {
+        this.percentageToBet = percentageToBet;
+    }
+
+    public boolean isAddToBetSlip() {
+        return addToBetSlip;
+    }
+
+    public void setAddToBetSlip(boolean addToBetSlip) {
+        this.addToBetSlip = addToBetSlip;
+    }
+
+    public void setBetAmount(Float value) {
+        betAmount = value;
+    }
+
+    public Float getBetAmount() {
+        return betAmount;
+    }
+
+    public void setRoundedDiff(float roundedDiff) {
+        this.roundedDiff = roundedDiff;
+    }
+
+    public float getRoundedDiff() {
+        return roundedDiff;
+    }
+
+    public void setDrawPercetage(float drawPercentage) {
+        this.drawPercentage = drawPercentage;
+    }
+
+    public float getDrawPercent() {
+        return this.drawPercentage;
+    }
+
+    public String getAnalysisValue() {
+        return analysisValue;
+    }
+
+    public void setAnalysisValue(int analysisValue) {
+        this.analysisValue = analysisValue == 0 ? "No Bet" : String.valueOf(analysisValue);
+    }
+
+    public int getAnalysisValueInt() {
+        Integer intValue;
+        try {
+            intValue = Integer.valueOf(getAnalysisValue());
+        } catch (NumberFormatException e) {
+            intValue = 0;
+        }
+        return intValue;
+    }
+
+    public Bet getPreviousBet() {
+        return bet;
+    }
+
+    public void setPreviousBet(Bet bet) {
+        this.bet = bet;
+    }
 
 }

+ 331 - 0
OddsJavaFx/src/objects/SoccerMatchAnalysis.java

@@ -0,0 +1,331 @@
+package objects;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Optional;
+
+import data.GuiMysql;
+
+public class SoccerMatchAnalysis {
+
+    SoccerMatch match;
+    GuiMysql database;
+    private List<TeamStanding> leagueTable;
+    private LocalDate leagueTableUpdated;
+
+    public SoccerMatchAnalysis(SoccerMatch match) {
+        this.match = match;
+        database = GuiMysql.getInstance();
+    }
+
+    /**
+     * Antalet mål som hemma laget gjort de senaste "gamesLookback" matcherna -
+     * antalet mål för bortalaget under samma period
+     * 
+     * @param gamesLookback - hur många matcher bakåt i tiden som ska kontrolleras
+     * @return Float med skillnaden i mål mellan lagen hemma/borta
+     */
+    public int getScoringDiffLastGames(int gamesLookback) {
+        int result = 0;
+
+        String sql = "SELECT * FROM "
+                + "(SELECT * FROM SoccerResults WHERE homeTeamId = ? AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?) ht "
+                + "UNION DISTINCT "
+                + "(SELECT * FROM SoccerResults WHERE awayTeamId = ? AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?);";
+
+        int homeRes = 0;
+        int awayRes = 0;
+        try (PreparedStatement stat = database.getDbConnection().prepareStatement(sql)) {
+            stat.setInt(1, match.getHomeTeam().getTeamId());
+            stat.setInt(2, match.getHomeTeam().getTeamLeagueId());
+            stat.setString(3, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(4, gamesLookback);
+
+            stat.setInt(5, match.getAwayTeam().getTeamId());
+            stat.setInt(6, match.getAwayTeam().getTeamLeagueId());
+            stat.setString(7, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(8, gamesLookback);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                if (match.getHomeTeam().getTeamId() == rs.getInt("homeTeamId")) {
+                    homeRes += rs.getInt("homeScore");
+                }
+                if (match.getAwayTeam().getTeamId() == rs.getInt("awayTeamId")) {
+                    awayRes += rs.getInt("awayScore");
+                }
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return homeRes - awayRes;
+    }
+
+    /**
+     * 
+     * Plocka fram antalet mål som ett specifikt lag gjort under de senaste
+     * <gamesLookback> matcherna
+     * 
+     * @param gamesLookback - hur många matcher bakåt i tiden som ska kontrolleras
+     * @param homeTeam      - är det hemma laget som ska kontrolleras i matchen
+     * @return antalet mål som är gjorda av bestämt lag.
+     */
+    public int scoringTotal(int gamesLookback, boolean homeTeam) {
+        int result = 0;
+        String sql = "SELECT * FROM "
+                + "(SELECT * FROM SoccerResults WHERE homeTeamId = ? AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?) ht "
+                + "UNION DISTINCT "
+                + "(SELECT * FROM SoccerResults WHERE awayTeamId = ? AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?)";
+
+        try (PreparedStatement stat = database.getDbConnection().prepareStatement(sql)) {
+            final Team team;
+            if (homeTeam) {
+                team = match.getHomeTeam();
+            } else {
+                team = match.getAwayTeam();
+            }
+
+            stat.setInt(1, team.getTeamId());
+            stat.setInt(2, team.getTeamLeagueId());
+            stat.setString(3, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(4, gamesLookback);
+
+            stat.setInt(5, team.getTeamId());
+            stat.setInt(6, team.getTeamLeagueId());
+            stat.setString(7, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(8, gamesLookback);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                if (rs.getInt("homeTeamId") == team.getTeamId()) {
+                    result += rs.getInt("homeScore");
+                } else if (rs.getInt("awayTeamId") == team.getTeamId()) {
+                    result += rs.getInt("awayScore");
+                }
+            }
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    /**
+     * Hämta tabell positionen för hemma eller borta laget
+     * 
+     * @param homeTeam - är det hemma laget som ska kontrolleras för matchen?
+     * @return position för specifierat lag
+     */
+    public int getTablePosition(boolean homeTeam) {
+        int result = 0;
+        updateLeagueTable();
+        Optional<TeamStanding> standingOptional = leagueTable.stream()
+                .filter(p -> p.getTeamName()
+                        .equals(homeTeam ? match.getHomeTeam().getTeamName() : match.getAwayTeam().getTeamName()))
+                .findFirst();
+
+        if (standingOptional.isPresent()) {
+            TeamStanding standing = standingOptional.get();
+            result = leagueTable.indexOf(standing);
+        }
+        return result;
+    }
+
+    private void updateLeagueTable() {
+        if (!leagueTableUpdated.isEqual(match.getGameDate().toLocalDate())) {
+            leagueTable = database.getLeagueTable(match.getHomeTeam().getTeamLeagueId(), match.getSeason(),
+                    match.getHomeTeam().getCountryId(),
+                    match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+
+            leagueTableUpdated = match.getGameDate().toLocalDate();
+        }
+    }
+
+    /**
+     * 
+     * @return Integer - hur många platser det är mellan hemma och borta laget
+     */
+    public int diffInStanding() {
+        int result = 0;
+        updateLeagueTable();
+
+        Optional<TeamStanding> homeTeamStandingOptional = leagueTable.stream()
+                .filter(p -> p.getTeamName().equals(match.getHomeTeam().getTeamName()))
+                .findFirst();
+
+        Optional<TeamStanding> awayTeamStandingOptional = leagueTable.stream()
+                .filter(p -> p.getTeamName().equals(match.getAwayTeam().getTeamName()))
+                .findFirst();
+
+        if (homeTeamStandingOptional.isPresent() && awayTeamStandingOptional.isPresent()) {
+            TeamStanding homeStanding = homeTeamStandingOptional.get();
+            TeamStanding awayStanding = awayTeamStandingOptional.get();
+
+            result = leagueTable.indexOf(homeStanding) - leagueTable.indexOf(awayStanding);
+        }
+        return result;
+    }
+
+    /**
+     * 
+     * Vinst förlust ratio för om man är enbart hemma eller bortalag.
+     * 
+     * @param gamesLookback
+     * @param homeTeam
+     * @return Integer där vinst ger +1 lika ger 0 och förlust get -1
+     */
+    public int winLossRatio(int gamesLookback, boolean homeTeam) {
+        int result = 0;
+
+        Team team = homeTeam ? match.getHomeTeam() : match.getAwayTeam();
+
+        String teamSql = homeTeam ? "homeTeamId = ? " : "awayTeamId = ? ";
+        String sql = "SELECT * FROM SoccerResults WHERE " + teamSql
+                + "AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?";
+
+        try (PreparedStatement stat = database.getDbConnection().prepareStatement(sql)) {
+            stat.setInt(1, team.getTeamId());
+            stat.setInt(2, team.getTeamLeagueId());
+            stat.setString(3, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(4, gamesLookback);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                int homeScore = rs.getInt("homeScore");
+                int awayScore = rs.getInt("awayScore");
+                if (homeTeam) {
+                    if (homeScore > awayScore) {
+                        result++;
+                    } else if (homeScore < awayScore) {
+                        result--;
+                    }
+                } else {
+                    if (homeScore > awayScore) {
+                        result--;
+                    } else if (homeScore < awayScore) {
+                        result++;
+                    }
+                }
+            }
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    public int winLossRationHomeAndAway(boolean homeTeam, int gamesLookback) {
+        int result = 0;
+
+        String sql = "SELECT * FROM "
+                + "(SELECT * FROM SoccerResults WHERE homeTeamId = ? AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?) a "
+                + "UNION DISTINCT "
+                + "(SELECT * FROM SoccerResults WHERE awayTeamId = ? AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?) "
+                + "ORDER BY gameDate DESC "
+                + "LIMIT ?";
+        Team team = homeTeam ? match.getHomeTeam() : match.getAwayTeam();
+        try (PreparedStatement stat = database.getDbConnection().prepareStatement(sql)) {
+            stat.setInt(1, team.getTeamId());
+            stat.setInt(2, team.getTeamLeagueId());
+            stat.setString(3, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(4, gamesLookback);
+
+            stat.setInt(5, team.getTeamId());
+            stat.setInt(6, team.getTeamLeagueId());
+            stat.setString(7, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(8, gamesLookback);
+
+            stat.setInt(9, gamesLookback);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                if (rs.getInt("homeTeamId") == team.getTeamId() && rs.getInt("homeScore") > rs.getInt("awayScore")) {
+                    result++;
+                } else if (rs.getInt("awayTeamId") == team.getTeamId()
+                        && rs.getInt("awayScore") > rs.getInt("homeScore")) {
+                    result++;
+                } else {
+                    result--;
+                }
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    public int goalsScoredHomeAndAway(boolean homeTeam, int gameLookback) {
+        int result = 0;
+        Team team = homeTeam ? match.getHomeTeam() : match.getAwayTeam();
+
+        String sql = "SELECT * FROM "
+                + "(SELECT * FROM SoccerResults WHERE homeTeamId = ? AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?) a "
+                + "UNION ALL "
+                + "(SELECT * FROM SoccerResults WHERE awayTeamId = ? AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ?) "
+                + "ORDER BY gameDate DESC "
+                + "LIMIT ?";
+
+        try (PreparedStatement stat = database.getDbConnection().prepareStatement(sql)) {
+            stat.setInt(1, team.getTeamId());
+            stat.setInt(2, team.getTeamLeagueId());
+            stat.setString(3, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(4, gameLookback);
+            stat.setInt(5, team.getTeamId());
+            stat.setInt(6, team.getTeamLeagueId());
+            stat.setString(7, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(8, gameLookback);
+            stat.setInt(9, gameLookback);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                if (rs.getInt("homeTeamId") == team.getTeamId()) {
+                    result += rs.getInt("homeScore");
+                }
+                if (rs.getInt("awayTeamId") == team.getTeamId()) {
+                    result += rs.getInt("awayScore");
+                }
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    public int goalsScoredHomeOrAway(boolean homeTeam, int gameLookback) {
+        int result = 0;
+        Team team = homeTeam ? match.getHomeTeam() : match.getAwayTeam();
+        String homeOrAway = homeTeam ? "home" : "away";
+        String sql = "SELECT SUM(" + homeOrAway
+                + "Score) FROM SoccerResults WHERE " + homeOrAway
+                + "TeamId = ? AND leagueId = ? AND DATE(gameDate) < ? ORDER BY gameDate DESC LIMIT ? "
+                + "ORDER BY gameDate DESC";
+
+        try (PreparedStatement stat = database.getDbConnection().prepareStatement(sql)) {
+            stat.setInt(1, team.getTeamId());
+            stat.setInt(2, team.getTeamLeagueId());
+            stat.setString(3, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            stat.setInt(4, gameLookback);
+
+            ResultSet rs = stat.executeQuery();
+
+            while (rs.next()) {
+                result += rs.getInt(homeOrAway + "Score");
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+}

+ 70 - 0
OddsJavaFx/src/objects/bets/AsianHandicap.java

@@ -0,0 +1,70 @@
+package objects.bets;
+
+import objects.SoccerMatch;
+
+public class AsianHandicap extends Bet {
+
+    float handicap;
+
+    public AsianHandicap(SoccerMatch match, float betAmount, float betOdds, float handicap) {
+        super(0, match, betAmount, betOdds);
+        this.handicap = handicap;
+    }
+
+    public float getHandicap() {
+        return handicap;
+    }
+
+    public void setHandicap(float handicap) {
+        this.handicap = handicap;
+    }
+
+    @Override
+    public float getResult() {
+        float result = super.getResult();
+        int adjustment = (int) Math.floor(handicap);
+        int homeScore = match.getHomeScore();
+        if (adjustment > 0) {
+            homeScore += adjustment;
+        } else {
+            homeScore -= adjustment;
+        }
+
+        if (handicap == 0f) {
+            if (!correctBet() && isDrawResult()) {
+                result = betAmount;
+            }
+        } else if (handicap == -0.25f) {
+            if (!correctBet() && isDrawResult()) {
+                result = betAmount / 2;
+            }
+        } else if (handicap == 0.25f) {
+            if (!correctBet() && isDrawResult()) {
+                result = (betAmount / 2) + (betAmount * betOdds) / 2;
+            }
+        } else if (handicap == -0.5f) {
+            result = super.getResult();
+        } else if (handicap == 0.5f) {
+            if (!correctBet() && isDrawResult()) {
+                result = super.getResult();
+            }
+        } else if (handicap == -0.75f) {
+            if (homeScore - 2 > match.getAwayScore()) {
+                result = super.getResult();
+            } else if (homeScore - 1 > match.getAwayScore()) {
+                result = (betAmount / 2) + (betAmount * betOdds) / 2;
+            }
+        } else if (handicap == 0.75f) {
+            if (!correctBet() && isDrawResult()) {
+                result = super.getResult();
+            } else {
+                if (homeScore - 1 >= match.getAwayScore()) {
+                    result = betAmount / 2;
+                }
+            }
+        }
+
+        return result;
+    }
+
+}

+ 185 - 0
OddsJavaFx/src/objects/bets/Bet.java

@@ -0,0 +1,185 @@
+package objects.bets;
+
+import objects.SoccerMatch;
+
+public class Bet {
+
+    SoccerMatch match;
+    float betAmount;
+    float betOdds;
+    boolean betOnHomeTeam;
+    boolean betOnDraw;
+    boolean betOnAwayTeam;
+
+    int id;
+    String homeTeamName;
+    String awayTeamName;
+    String matchup;
+    int homeScore;
+    int awayScore;
+
+    Status status;
+
+    public static enum Status {
+        DONE,
+        OPEN,
+        LOST,
+        COVERED,
+        SPLIT
+    }
+
+    public Bet(int id, SoccerMatch match, float betAmount, float betOdds) {
+        new Bet(id, match, betAmount, betOdds, Status.OPEN);
+    }
+
+    public Bet(int id, SoccerMatch match, float betAmount, float betOdds, Status status) {
+        this.betAmount = betAmount;
+        this.betOdds = betOdds;
+        this.match = match;
+
+        homeTeamName = match.getHomeTeam().getTeamName();
+        awayTeamName = match.getAwayTeam().getTeamName();
+
+        setMatchup();
+        homeScore = match.getHomeScore();
+        awayScore = match.getAwayScore();
+        this.status = status;
+        this.id = id;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public SoccerMatch getMatch() {
+        return match;
+    }
+
+    public float getBetAmount() {
+        return betAmount;
+    }
+
+    public float getBetOdds() {
+        return betOdds;
+    }
+
+    public boolean isBetOnHomeTeam() {
+        return betOnHomeTeam;
+    }
+
+    public boolean isBetOnDraw() {
+        return betOnDraw;
+    }
+
+    public boolean isBetOnAwayTeam() {
+        return betOnAwayTeam;
+    }
+
+    public void setMatch(SoccerMatch match) {
+        this.match = match;
+    }
+
+    public void setBetAmount(float betAmount) {
+        this.betAmount = betAmount;
+    }
+
+    public void setBetOdds(float betOdds) {
+        this.betOdds = betOdds;
+    }
+
+    public void setBetOnHomeTeam(boolean betOnHomeTeam) {
+        this.betOnHomeTeam = betOnHomeTeam;
+    }
+
+    public void setBetOnDraw(boolean betOnDraw) {
+        this.betOnDraw = betOnDraw;
+    }
+
+    public void setBetOnAwayTeam(boolean betOnAwayTeam) {
+        this.betOnAwayTeam = betOnAwayTeam;
+    }
+
+    public float getResult() {
+        final float result;
+        if ((betOnHomeTeam && match.getHomeScore() > match.getAwayScore())
+                || (betOnDraw && match.getHomeScore() == match.getAwayScore())
+                || (betOnAwayTeam && match.getHomeScore() < match.getAwayScore())) {
+            result = betOdds * betAmount;
+        } else {
+            result = 0;
+        }
+
+        return result;
+    }
+
+    public boolean correctBet() {
+        boolean result = false;
+        if (betOnHomeTeam && match.getHomeScore() > match.getAwayScore()) {
+            result = true;
+        }
+        if (betOnDraw && match.getHomeScore() == match.getAwayScore()) {
+            result = true;
+        }
+        if (betOnAwayTeam && match.getHomeScore() < match.getAwayScore()) {
+            result = true;
+        }
+        return result;
+    }
+
+    protected boolean isDrawResult() {
+        return match.getHomeScore() == match.getAwayScore();
+    }
+
+    public String getHomeTeamName() {
+        return homeTeamName;
+    }
+
+    public String getAwayTeamName() {
+        return awayTeamName;
+    }
+
+    public String getMatchup() {
+        return matchup;
+    }
+
+    public void setHomeTeamName(String homeTeamName) {
+        this.homeTeamName = homeTeamName;
+    }
+
+    public void setAwayTeamName(String awayTeamName) {
+        this.awayTeamName = awayTeamName;
+    }
+
+    public void setMatchup() {
+        this.matchup = homeTeamName + " - " + awayTeamName;
+    }
+
+    public int getHomeScore() {
+        return homeScore;
+    }
+
+    public int getAwayScore() {
+        return awayScore;
+    }
+
+    public void setHomeScore(int homeScore) {
+        this.homeScore = homeScore;
+    }
+
+    public void setAwayScore(int awayScore) {
+        this.awayScore = awayScore;
+    }
+
+    public Status getStatus() {
+        return status;
+    }
+
+    public void setStatus(Status status) {
+        this.status = status;
+    }
+
+}

+ 203 - 0
OddsJavaFx/src/tests/AnalysisBettTester.java

@@ -0,0 +1,203 @@
+package tests;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+import data.TestDatabase;
+import objects.League;
+import objects.SoccerMatch;
+import objects.SoccerMatchAnalysis;
+import objects.bets.AsianHandicap;
+import objects.bets.Bet;
+import tests.objects.LeagueDTO;
+
+public class AnalysisBettTester extends TestClass {
+
+    TestDatabase database;
+    List<SoccerMatch> betsToPlace = new ArrayList<>();
+    float betAmount;
+    List<DifferenceBetDTO> bets = new ArrayList<>();
+
+    int wins = 0;
+    int losses = 0;
+
+    float bank;
+    private List<DifferenceBetDTO> betSeries = new ArrayList<>();
+    private League leagueInfo;
+
+    @Override
+    public void runTest() {
+        bank = startingBank;
+        database = TestDatabase.getInstance();
+
+        leagueInfo = database.getLeagueInfo(leagueId);
+
+        LeagueDTO leagueDTO = database.getLeagueDTO(leagueId);
+        LinkedHashMap<String, List<SoccerMatch>> matches = getMatchesOrderedBySeason(leagueDTO);
+        this.betAmount = startingBank * (bettingLevel / 100.0f);
+
+        boolean skipFirst = true;
+        for (Entry<String, List<SoccerMatch>> seasonMatches : matches.entrySet()) {
+            if (skipFirst) {
+                skipFirst = false;
+                continue;
+            }
+            analyze(seasonMatches.getValue());
+            System.out
+                    .println(String.format("Wins %s Losses %s %s total bank: %s", wins, losses,
+                            wins / (float) (wins + losses) + "%", bank));
+            break;
+        }
+
+    }
+
+    private void analyze(List<SoccerMatch> seasonMatches) {
+
+        LocalDate currentMatchDate = seasonMatches.get(0).getGameDate().toLocalDate();
+
+        for (SoccerMatch match : seasonMatches) {
+
+            if (currentMatchDate.isBefore(match.getGameDate().toLocalDate())) {
+                placeBets();
+                checkBetResults();
+
+                betAmount = bank * (bettingLevel / 100.0f);
+            }
+            /**
+             * Matchen har en differens mellan hemma lagets mål och borta laget på minst X
+             * (starta att testa med 1)
+             */
+            SoccerMatchAnalysis analysis = new SoccerMatchAnalysis(match);
+
+            int homeWinsCount = analysis.winLossRatio(leagueInfo.getWinLossRatio(), true);
+            int awayWindCount = analysis.winLossRatio(leagueInfo.getWinLossRatio(), false);
+
+            int homeWinLossRatioCount = analysis.winLossRationHomeAndAway(true,
+                    leagueInfo.getWinLossRatioHomeAndAway());
+            int awayWinLossRatioCount = analysis.winLossRationHomeAndAway(false,
+                    leagueInfo.getWinLossRatioHomeAndAway());
+
+            int homeScoringTotal = analysis.scoringTotal(leagueInfo.getScoringTotal(), true);
+            int awayScoringTotal = analysis.scoringTotal(leagueInfo.getScoringTotal(), false);
+
+            int scoringDiffLastGames = analysis.getScoringDiffLastGames(leagueInfo.getScoringDiffLastGame());
+            int winsCountDiff = homeWinsCount - awayWindCount;
+            int winLossRatioDiff = homeWinLossRatioCount - awayWinLossRatioCount;
+            int scoringTotalDiff = homeScoringTotal - awayScoringTotal;
+
+            int testValue = 0;
+            if (scoringDiffLastGames < 0 && winsCountDiff < 0 && winLossRatioDiff < 0 && scoringTotalDiff < 0) {
+                addBet(match, scoringDiffLastGames, winsCountDiff, winLossRatioDiff, scoringTotalDiff);
+            } else if (scoringDiffLastGames > 0 && winsCountDiff > 0 && winLossRatioDiff > 0 && scoringTotalDiff > 0) {
+                addBet(match, scoringDiffLastGames, winsCountDiff, winLossRatioDiff, scoringTotalDiff);
+            } else {
+//                match.put("analysis", "NoBet");
+            }
+
+            currentMatchDate = match.getGameDate().toLocalDate();
+        }
+    }
+
+    private void addBet(SoccerMatch match, int scoringDiffLastGames, int winsCountDiff, int winLossRatioDiff,
+            int scoringTotalDiff) {
+        int testValue;
+        testValue = (scoringDiffLastGames + winsCountDiff + winLossRatioDiff + scoringTotalDiff) / 4;
+        match.setGoalsDiff(BigDecimal.valueOf(testValue));// Temp use GoldsDiff for value
+        betsToPlace.add(match);
+    }
+
+    private void placeBets() {
+
+        for (SoccerMatch soccerMatch : betsToPlace) {
+            float currentBetAmount = 0;
+//            betSeries.sort((b1, b2) -> Float.compare(b2.getBetAmount(), b1.getBetAmount()));
+            if (!betSeries.isEmpty() && !betsToPlace.isEmpty()) {
+                currentBetAmount += betSeries.get(0).getBetAmount();
+                betSeries.remove(0);
+            }
+            if (soccerMatch.getGoalsDiff().floatValue() > 0f) {
+                if (currentBetAmount > 0) {
+                    currentBetAmount = (float) (currentBetAmount / (soccerMatch.getOdds1() - 1.0));
+                }
+                bets.add(new DifferenceBetDTO(soccerMatch, currentBetAmount + betAmount, true));
+            } else if (soccerMatch.getGoalsDiff().floatValue() < 0f) {
+                if (currentBetAmount > 0) {
+                    currentBetAmount = (float) (currentBetAmount / (soccerMatch.getOdds2() - 1.0));
+                }
+                bets.add(new DifferenceBetDTO(soccerMatch, currentBetAmount + betAmount, false));
+            }
+
+            bank -= currentBetAmount + betAmount;
+        }
+
+        betsToPlace.clear();
+    }
+
+    private void checkBetResults() {
+        List<DifferenceBetDTO> activeBets = bets.stream().filter(p -> !p.resolved).toList();
+        for (DifferenceBetDTO bet : activeBets) {
+            if (bet.getResult() > 0) {
+                bank += bet.getResult(); // bet.getBetAmount() * bet.getBetOdds();
+                String winText = bet.correctBet() ? bet.isBetOnHomeTeam() ? "HOME WIN " : "AWAY WIN" : "HALF WIN";
+                System.out.println(String.format(winText + "\t" + "%s \t\tnew bank %s", bet, bank));
+                wins++;
+            } else {
+                // LOSS
+                System.out.println(String.format("LOSS\t\t%s \t\t bank: %s", bet, bank));
+                losses++;
+                betSeries.add(bet);
+            }
+            bet.resolved = true;
+        }
+        if (!betSeries.isEmpty()) {
+            System.out.println("Outstanding bets:");
+            betSeries.forEach(b -> System.out.println(b));
+        }
+    }
+
+    public class DifferenceBetDTO extends Bet {
+        boolean resolved = false;
+
+        public DifferenceBetDTO(SoccerMatch match, float betAmount, boolean betOnHomeTeam) {
+            super(0, match, betAmount, betOnHomeTeam ? match.getOdds1() : match.getOdds2());
+            setBetOnHomeTeam(betOnHomeTeam);
+            setBetOnAwayTeam(!betOnHomeTeam);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%s \t%s - %s \t\tbet amount %s \todds %s \twinner %s \t result %s-%s \tdiff %s",
+                    getMatch().getGameDate().toLocalDate(),
+                    getMatch().getHomeTeamName(),
+                    getMatch().getAwayTeamName(), getBetAmount(), super.getBetOdds(),
+                    super.isBetOnHomeTeam() ? "1" : "2", getMatch().getHomeScore(),
+                    getMatch().getAwayScore(), getMatch().getGoalsDiff());
+        }
+    }
+
+    public class DifferenceAsianBetDTO extends AsianHandicap {
+        boolean resolved = false;
+
+        public DifferenceAsianBetDTO(SoccerMatch match, float betAmount, boolean betOnHomeTeam, float handicap) {
+            super(match, betAmount, betOnHomeTeam ? match.getOdds1() : match.getOdds2(), handicap);
+            setBetOnHomeTeam(betOnHomeTeam);
+            setBetOnAwayTeam(!betOnHomeTeam);
+        }
+
+        @Override
+        public String toString() {
+            return String.format(
+                    "%s \t%s - %s \t\tbet amount %s \todds %s \twinner %s \t result %s-%s \tdiff %s with results %s",
+                    getMatch().getGameDate().toLocalDate(),
+                    getMatch().getHomeTeamName(),
+                    getMatch().getAwayTeamName(), getBetAmount(), super.getBetOdds(),
+                    super.isBetOnHomeTeam() ? "1" : "2", getMatch().getHomeScore(),
+                    getMatch().getAwayScore(), getMatch().getGoalsDiff(), getResult());
+        }
+    }
+
+}

+ 188 - 0
OddsJavaFx/src/tests/BetOnDifference.java

@@ -0,0 +1,188 @@
+package tests;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+import data.TestDatabase;
+import objects.SoccerMatch;
+import objects.bets.AsianHandicap;
+import objects.bets.Bet;
+import tests.objects.LeagueDTO;
+
+public class BetOnDifference extends TestClass {
+
+    private static final float MIN_DIFF_IN_GOALS = 0.5f;
+    private static final float LOWER_LIMIT_COVER_BET = 1.3f;
+    private static final float HIGHER_LIMIT_COVER_BET = 2.0f;
+    TestDatabase database;
+    List<SoccerMatch> betsToPlace = new ArrayList<>();
+    float betAmount;
+    List<DifferenceAsianBetDTO> bets = new ArrayList<>();
+
+    int wins = 0;
+    int losses = 0;
+
+    float bank;
+    private List<DifferenceAsianBetDTO> betSeries = new ArrayList<>();
+
+    @Override
+    public void runTest() {
+        bank = startingBank;
+        database = TestDatabase.getInstance();
+
+        LeagueDTO leagueDTO = database.getLeagueDTO(leagueId);
+        LinkedHashMap<String, List<SoccerMatch>> matches = getMatchesOrderedBySeason(leagueDTO);
+        this.betAmount = startingBank * (bettingLevel / 100.0f);
+
+        boolean skipFirst = true;
+        for (Entry<String, List<SoccerMatch>> seasonMatches : matches.entrySet()) {
+            if (skipFirst) {
+                skipFirst = false;
+                continue;
+            }
+            analyze(seasonMatches.getValue());
+            System.out
+                    .println(String.format("Wins %s Losses %s %s total bank: %s", wins, losses,
+                            wins / (float) (wins + losses) + "%", bank));
+            break;
+        }
+
+    }
+
+    private void analyze(List<SoccerMatch> seasonMatches) {
+
+        LocalDate currentMatchDate = seasonMatches.get(0).getGameDate().toLocalDate();
+
+        int skipFirstXMatchDates = 10;
+        for (SoccerMatch match : seasonMatches) {
+
+            List<Float> avgHomeScoreThisSeason = database.getAvgHomeScoreThisSeason(match.getHomeTeam().getTeamId(),
+                    countryId, leagueId, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+            List<Float> avgAwayScoreThisSeason = database.getAvgAwayScoreThisSeason(match.getAwayTeam().getTeamId(),
+                    countryId, leagueId, match.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+
+            if (currentMatchDate.isBefore(match.getGameDate().toLocalDate())) {
+                if (skipFirstXMatchDates > 0) {
+                    bets.clear();
+                    betsToPlace.clear();
+                    skipFirstXMatchDates--;
+                    continue;
+                }
+                placeBets();
+                checkBetResults();
+            }
+            /**
+             * Matchen har en differens mellan hemma lagets mål och borta laget på minst X
+             * (starta att testa med 1)
+             */
+            match.setAvgScoreHome((avgHomeScoreThisSeason.get(0) * avgAwayScoreThisSeason.get(1)));
+            match.setAvgScoreAway((avgHomeScoreThisSeason.get(1) * avgAwayScoreThisSeason.get(0)));
+            match.setGoalsDiff(
+                    BigDecimal.valueOf((avgHomeScoreThisSeason.get(0) * avgAwayScoreThisSeason.get(1))
+                            - (avgHomeScoreThisSeason.get(1) * avgAwayScoreThisSeason.get(0))));
+            if (Math.abs((avgHomeScoreThisSeason.get(0) * avgAwayScoreThisSeason.get(1))
+                    - (avgHomeScoreThisSeason.get(1) * avgAwayScoreThisSeason.get(0))) >= MIN_DIFF_IN_GOALS) {
+                betsToPlace.add(match);
+            }
+            currentMatchDate = match.getGameDate().toLocalDate();
+        }
+    }
+
+    private void placeBets() {
+
+        betsToPlace.sort((b1, b2) -> Float.compare(Math.abs(b2.getGoalsDiff().floatValue()),
+                Math.abs(b1.getGoalsDiff().floatValue())));
+        for (SoccerMatch soccerMatch : betsToPlace) {
+            float currentBetAmount = 0;
+            betSeries.sort((b1, b2) -> Float.compare(b2.getBetAmount(), b1.getBetAmount()));
+            if (!betSeries.isEmpty() && !betsToPlace.isEmpty()) {
+                currentBetAmount += betSeries.get(0).getBetAmount();
+                betSeries.remove(0);
+            }
+            if (soccerMatch.getAvgScoreHome() > soccerMatch.getAvgScoreAway()) {
+                if (currentBetAmount > 0) {
+                    currentBetAmount = (float) (currentBetAmount / (soccerMatch.getOdds1() - 1.0));
+                }
+                bets.add(new DifferenceAsianBetDTO(soccerMatch, currentBetAmount + betAmount, true, 0f));
+            } else {
+                if (currentBetAmount > 0) {
+                    currentBetAmount = (float) (currentBetAmount / (soccerMatch.getOdds2() - 1.0));
+                }
+                bets.add(new DifferenceAsianBetDTO(soccerMatch, currentBetAmount + betAmount, false, 0f));
+            }
+
+            bank -= currentBetAmount + betAmount;
+        }
+
+        betsToPlace.clear();
+    }
+
+    private void checkBetResults() {
+        List<DifferenceAsianBetDTO> activeBets = bets.stream().filter(p -> !p.resolved).toList();
+        for (DifferenceAsianBetDTO bet : activeBets) {
+            if (bet.getResult() > 0) {
+                bank += bet.getResult(); // bet.getBetAmount() * bet.getBetOdds();
+                String winText = bet.correctBet() ? bet.isBetOnHomeTeam() ? "HOME WIN " : "AWAY WIN" : "HALF WIN";
+                System.out.println(String.format(winText + "\t" + "%s \t\tnew bank %s", bet, bank));
+                wins++;
+            } else {
+                // LOSS
+                System.out.println(String.format("LOSS\t\t%s \t\t bank: %s", bet, bank));
+                losses++;
+                betSeries.add(bet);
+            }
+            bet.resolved = true;
+        }
+        if (!betSeries.isEmpty()) {
+            System.out.println("Outstanding bets:");
+            betSeries.forEach(b -> System.out.println(b));
+        }
+    }
+
+    public class DifferenceBetDTO extends Bet {
+        boolean resolved = false;
+
+        public DifferenceBetDTO(SoccerMatch match, float betAmount, boolean betOnHomeTeam) {
+            super(0, match, betAmount, betOnHomeTeam ? match.getOdds1() : match.getOdds2());
+            setBetOnHomeTeam(betOnHomeTeam);
+            setBetOnAwayTeam(!betOnHomeTeam);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%s \t%s - %s \t\tbet amount %s \todds %s \twinner %s \t result %s-%s \tdiff %s",
+                    getMatch().getGameDate().toLocalDate(),
+                    getMatch().getHomeTeamName(),
+                    getMatch().getAwayTeamName(), betAmount, super.getBetOdds(),
+                    super.isBetOnHomeTeam() ? "1" : "2", getMatch().getHomeScore(),
+                    getMatch().getAwayScore(), getMatch().getGoalsDiff());
+        }
+    }
+
+    public class DifferenceAsianBetDTO extends AsianHandicap {
+        boolean resolved = false;
+
+        public DifferenceAsianBetDTO(SoccerMatch match, float betAmount, boolean betOnHomeTeam, float handicap) {
+            super(match, betAmount, betOnHomeTeam ? match.getOdds1() : match.getOdds2(), handicap);
+            setBetOnHomeTeam(betOnHomeTeam);
+            setBetOnAwayTeam(!betOnHomeTeam);
+        }
+
+        @Override
+        public String toString() {
+            return String.format(
+                    "%s \t%s - %s \t\tbet amount %s \todds %s \twinner %s \t result %s-%s \tdiff %s with results %s",
+                    getMatch().getGameDate().toLocalDate(),
+                    getMatch().getHomeTeamName(),
+                    getMatch().getAwayTeamName(), betAmount, super.getBetOdds(),
+                    super.isBetOnHomeTeam() ? "1" : "2", getMatch().getHomeScore(),
+                    getMatch().getAwayScore(), getMatch().getGoalsDiff(), getResult());
+        }
+    }
+
+}

+ 218 - 0
OddsJavaFx/src/tests/FibonacciDrawTest.java

@@ -0,0 +1,218 @@
+package tests;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+
+import com.google.common.collect.Lists;
+
+import data.TestDatabase;
+import objects.OverUnder;
+import objects.SoccerMatch;
+import tests.objects.LeagueDTO;
+import tests.objects.Standing;
+
+public class FibonacciDrawTest extends TestClass {
+
+    TestDatabase database;
+    List<SoccerMatch> matches;
+    Map<String, List<SoccerMatch>> matchesBySeason = new HashMap<>();
+
+    private int atleastXGamesPlayed = 10;
+    private float drawPercentageLimit = 0.25f;
+
+    List<Integer> fibonacciSequence = Lists.newArrayList(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377);
+    List<BetDTO> bets = new ArrayList<>();
+    float bank;
+
+    int currentBetSeries;
+
+    private float betAmount = 10f;
+
+    List<SoccerMatch> betsToPlace = new ArrayList<>();
+
+    @Override
+    public void runTest() {
+        currentBetSeries = 0;
+        bank = startingBank;
+        database = TestDatabase.getInstance();
+        LeagueDTO leagueDTO = database.getLeagueDTO(leagueId);
+
+        LinkedHashMap<String, List<SoccerMatch>> matches = getMatchesOrderedBySeason(leagueDTO);
+
+        boolean skipFirst = true;
+        for (Entry<String, List<SoccerMatch>> entry : matches.entrySet()) {
+            if (skipFirst) {
+                skipFirst = false;
+                continue;
+            }
+            analyseSeason(entry.getKey(), entry.getValue());
+            break; // TODO remove, testing one season at a time
+        }
+    }
+
+    private void analyseSeason(String season, List<SoccerMatch> seasonMatches) {
+
+        SoccerMatch tempSm = seasonMatches.get(0);
+        LocalDate currentBetDate = tempSm.getGameDate().toLocalDate();
+//        float betAmount = bank * (bettingLevel / 100f);
+        List<OverUnder> statsOverUnderWithDrawStats = database.getStatsOverUnderWithDrawStats(
+                tempSm.getHomeTeam().getTeamLeagueId(), tempSm.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+
+        for (SoccerMatch soccerMatch : seasonMatches) {
+            List<Standing> standings = getStandings(
+                    seasonMatches.stream().filter(
+                            p -> p.getGameDate().toLocalDate().isBefore(soccerMatch.getGameDate().toLocalDate()))
+                            .toList());
+            Optional<Standing> homeTeamStandingOptional = standings.stream()
+                    .filter(s -> s.getTeamName().equals(soccerMatch.getHomeTeamName())).findFirst();
+            Optional<Standing> awayTeamStandingOptional = standings.stream()
+                    .filter(s -> s.getTeamName().equals(soccerMatch.getAwayTeamName())).findFirst();
+
+            if (homeTeamStandingOptional.isPresent() && awayTeamStandingOptional.isPresent()) {
+                Standing homeTeamStanding = homeTeamStandingOptional.get();
+                Standing awayTeamStanding = awayTeamStandingOptional.get();
+
+                if (homeTeamStanding.getGamesPlayed() > atleastXGamesPlayed
+                        && awayTeamStanding.getGamesPlayed() > atleastXGamesPlayed) {
+
+                    if (!soccerMatch.getGameDate().toLocalDate().isEqual(currentBetDate)) {
+                        placeBets(betAmount, statsOverUnderWithDrawStats);
+                        // check bets and update bank with winnings
+                        // update bet amount
+                        statsOverUnderWithDrawStats = database.getStatsOverUnderWithDrawStats(
+                                soccerMatch.getHomeTeam().getTeamLeagueId(),
+                                soccerMatch.getGameDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
+
+                        checkCurrentUnresolvedBets(currentBetDate);
+                        currentBetDate = soccerMatch.getGameDate().toLocalDate();
+                        // betAmount = bank * (bettingLevel / 100f);
+                    }
+
+                    float roundedDiff = database.getRoundedDiff(soccerMatch);
+                    Optional<OverUnder> drawStat = statsOverUnderWithDrawStats.stream()
+                            .filter(p -> p.getKey().equals(roundedDiff)).findFirst();
+                    if (drawStat.isPresent()) {
+                        OverUnder overUnder = drawStat.get();
+                        float drawPercentage = overUnder.getDraws() / (float) overUnder.getTotalGames();
+                        if (drawPercentage > drawPercentageLimit) {
+                            // Make Bet!
+                            soccerMatch.setRoundedDiff(roundedDiff);
+                            soccerMatch.setDrawPercetage(drawPercentage);
+                            betsToPlace.add(soccerMatch);
+                        }
+                    }
+                }
+            }
+        }
+
+        System.out.println("Season done, final bank " + bank + " outstanding bets:");
+        bets.forEach(b -> System.out.println(b.toString()));
+    }
+
+    private void placeBets(float betAmount, List<OverUnder> statsOverUnderWithDrawStats) {
+
+        betsToPlace.sort((b1, b2) -> Float.compare(b2.getDrawPercent(), b1.getDrawPercent()));
+
+        for (SoccerMatch sm : betsToPlace) {
+
+            Optional<OverUnder> drawStat = statsOverUnderWithDrawStats.stream()
+                    .filter(p -> p.getKey().equals(sm.getRoundedDiff())).findFirst();
+            if (drawStat.isPresent()) {
+                OverUnder overUnder = drawStat.get();
+                float drawPercentage = overUnder.getDraws() / (float) overUnder.getTotalGames();
+                if (drawPercentage > drawPercentageLimit) {
+                    // Make Bet!
+                    placeBet(sm, betAmount);
+                }
+            }
+        }
+        betsToPlace.clear();
+    }
+
+    private void checkCurrentUnresolvedBets(LocalDate currentBetDate) {
+        List<BetDTO> activeBets = bets.stream()
+                .filter(p -> p.soccerMatch.getGameDate().toLocalDate().equals(currentBetDate))
+                .toList();
+
+        for (BetDTO betDTO : activeBets) {
+            if (betDTO.soccerMatch.getHomeScore() == betDTO.soccerMatch.getAwayScore()) {
+
+                bank += betDTO.betAmount * betDTO.soccerMatch.getOddsX();
+                System.out.println(
+                        "Total winnings " + betDTO.betAmount * betDTO.soccerMatch.getOddsX() + " New bank: " + bank
+                                + " odds " + betDTO.oddsX);
+
+                System.out.println("REMOVING BETS");
+                bets.stream()
+                        .filter(p -> p.betSeriesId == betDTO.betSeriesId)
+                        .forEach(b -> System.out.println(b));
+                bets.removeIf(p -> p.betSeriesId == betDTO.betSeriesId);
+            }
+        }
+    }
+
+    private void placeBet(SoccerMatch soccerMatch, float betAmount) {
+        List<BetDTO> todaysBets = bets.stream()
+                .filter(p -> p.soccerMatch.getGameDate().toLocalDate().equals(soccerMatch.getGameDate().toLocalDate()))
+                .toList();
+
+        Optional<BetDTO> openBetSeries = bets.stream()
+                .filter(p -> !todaysBets.stream().map(b -> b.betSeriesId).toList().contains(p.betSeriesId)).findFirst();
+        float currentBetAmount;
+        int currentBetLosses;
+        int betSeries;
+        if (openBetSeries.isPresent()) {
+            BetDTO betDTO = openBetSeries.get();
+            currentBetLosses = (int) bets.stream().filter(p -> p.betSeriesId == betDTO.betSeriesId).count();
+            betSeries = betDTO.betSeriesId;
+        } else {
+            currentBetLosses = 0;
+            Optional<BetDTO> max = bets.stream().max((b1, b2) -> Integer.compare(b1.betSeriesId, b2.betSeriesId));
+            if (max.isPresent()) {
+                betSeries = max.get().betSeriesId + 1;
+            } else {
+                betSeries = 0;
+            }
+        }
+        currentBetAmount = betAmount * fibonacciSequence.get(currentBetLosses);
+        bets.add(new BetDTO(betSeries, soccerMatch, currentBetAmount, soccerMatch.getOddsX()));
+
+        bank -= currentBetAmount;
+
+        System.out.println(
+                soccerMatch.getGameDate().toLocalDate() + " Betting on " + soccerMatch.getHomeTeamName() + " - "
+                        + soccerMatch.getAwayTeamName() + " amount " + currentBetAmount + " the "
+                        + currentBetLosses + " in seqence with draw percent: " + soccerMatch.getDrawPercent()
+                        + " result "
+                        + soccerMatch.getHomeScore() + " - " + soccerMatch.getAwayScore());
+    }
+
+    private class BetDTO {
+
+        SoccerMatch soccerMatch;
+        float betAmount;
+        float oddsX;
+        int betSeriesId;
+
+        public BetDTO(int betSeriesId, SoccerMatch soccerMatch, float betAmount, float oddsX) {
+            this.soccerMatch = soccerMatch;
+            this.betAmount = betAmount;
+            this.oddsX = oddsX;
+            this.betSeriesId = betSeriesId;
+        }
+
+        @Override
+        public String toString() {
+            return soccerMatch.getHomeTeamName() + " - " + soccerMatch.getAwayTeamName() + " bet amount " + betAmount
+                    + " betSeries: " + betSeriesId;
+        }
+    }
+
+}

+ 210 - 199
OddsJavaFx/src/tests/HomeDrawAwayTest.java

@@ -17,204 +17,215 @@ import objects.TeamResults;
 
 public class HomeDrawAwayTest extends TestClass {
 
-	private ArrayList<League> prioLeagues;
-	private float activeOdds1;
-	private float activeOddsX;
-	private float activeOdds2;
-
-	@Override public void runTest() {
-		float betAmount;
-		float bank = startingBank;
-		final float betLevel = bettingLevel / 100.0f;
-
-		float homeBank = startingBank;
-		float drawBank = startingBank;
-		float awayBank = startingBank;
-
-		final ArrayList<SoccerMatch> matches = getMatches();
-
-		for (int i = 0; i < matches.size(); i++) {
-			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 String betOnThisMatch = checkWhatBet(sm, activeLeague);
-				if (!"NoBet".equals(betOnThisMatch)) {
-					if (betOnThisMatch.contains("1")) { // Spela p� hemma lag
-						gamesBettedOn++;
-						bank = bank - betAmount;
-						final float homeBetAmount = (homeBank * betLevel);
-						homeBank -= homeBetAmount;
-
-						if (sm.getHomeScore() > sm.getAwayScore()) {
-							bank += betAmount * sm.getOdds1();
-							homeBank += homeBetAmount * sm.getOdds1();
-							winsThisDay++;
-						}
-					}
-					if (betOnThisMatch.contains("2")) { // Spela p� borta lag
-						gamesBettedOn++;
-						bank = bank - betAmount;
-
-						final float awayBetAmount = (awayBank * betLevel);
-						awayBank -= awayBetAmount;
-						if (sm.getAwayScore() > sm.getHomeScore()) {
-							bank += betAmount * sm.getOdds2();
-							awayBank += awayBetAmount * sm.getOdds2();
-							winsThisDay++;
-						}
-					}
-					if (betOnThisMatch.contains("X")) { // Spela p� Lika
-						gamesBettedOn++;
-						bank = bank - betAmount;
-
-						final float drawBetAmount = (drawBank * betLevel);
-						drawBank -= drawBetAmount;
-						if (sm.getHomeScore() == sm.getAwayScore()) {
-							bank += betAmount * sm.getOddsX();
-							drawBank += drawBetAmount * sm.getOddsX();
-							winsThisDay++;
-						}
-					}
-				}
-				System.out.println("Match between " + sm.getHomeTeam().getTeamName() + " - " + sm.getAwayTeam().getTeamName() + " result "
-						+ sm.getHomeScore() + " - " + sm.getAwayScore() + " Betted on " + betOnThisMatch + " at odds " + sm.getOdds1() + ", "
-						+ sm.getOddsX() + ", " + sm.getOdds2() + " Bet Amount: " + betAmount + " calc odds: " + activeOdds1 + ", " + activeOddsX
-						+ ", " + activeOdds2);
-			}
-
-			System.out.println(matchesThisDate.get(0).getGameDate() + " result " + (bank - startBank) + " current bank: " + bank + " bet on "
-					+ gamesBettedOn + "/" + matchesThisDateCount + " wins " + winsThisDay);
-			i += matchesThisDate.size();
-
-		}
-
-		System.out.println("Final bank " + bank + " homeBank " + homeBank + " drawBank " + drawBank + " awayBank " + awayBank);
-	}
-
-	private String checkWhatBet(SoccerMatch sm, League activeLeague) {
-		String result = "NoBet";
-		final float betMarginHomeDecimal = 1 + (activeLeague.getBetMarginHome() / 100f);
-		final float betMarginDrawDecimal = 1 + (activeLeague.getBetMarginDraw() / 100f);
-		final float betMarginAwayDecimal = 1 + (activeLeague.getBetMarginAway() / 100f);
-
-		final int lookbackHome = activeLeague.getLookbackHome();
-		final int lookbackDraw = activeLeague.getLookbackDraw();
-		final int lookbackAway = activeLeague.getLookbackAway();
-
-		if (lookbackHome > 0) {
-			final TeamResults homeTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getHomeTeam().getTeamId(),
-					activeLeague.getLookbackHome(), true, sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
-			final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getAwayTeam().getTeamId(),
-					activeLeague.getLookbackHome(), false, sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
-			final float homeWinPercent = (homeTeamResults.getWins() + awayTeamResults.getLosses())
-					/ Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
-			final float homeOdds = 100 / homeWinPercent;
-
-			activeOdds1 = homeOdds * betMarginHomeDecimal;
-			if (activeLeague.getBetMarginHome() > 0 && homeOdds * betMarginHomeDecimal <= sm.getOdds1()) {
-				if (result.equals("NoBet")) {
-					result = "1";
-				} else {
-					result += "1";
-				}
-			}
-
-		}
-
-		if (lookbackDraw > 0) {
-			final TeamResults homeTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getHomeTeam().getTeamId(),
-					activeLeague.getLookbackDraw(), true, sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
-			final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getAwayTeam().getTeamId(),
-					activeLeague.getLookbackDraw(), false, sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
-			final float drawWinPercent = (homeTeamResults.getDraws() + awayTeamResults.getDraws())
-					/ Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
-			final float drawOdds = 100 / drawWinPercent;
-
-			activeOddsX = drawOdds * betMarginDrawDecimal;
-			if (activeLeague.getBetMarginDraw() > 0 && drawOdds * betMarginDrawDecimal <= sm.getOddsX()) {
-				if (result.equals("NoBet")) {
-					result = "X";
-				} else {
-					result += "X";
-				}
-			}
-
-		}
-
-		if (lookbackAway > 0) {
-			final TeamResults homeTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getHomeTeam().getTeamId(),
-					activeLeague.getLookbackAway(), true, sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
-			final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getAwayTeam().getTeamId(),
-					activeLeague.getLookbackAway(), false, sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
-			final float awayWinPercent = (awayTeamResults.getWins() + homeTeamResults.getLosses())
-					/ Float.valueOf(awayTeamResults.getCount() + homeTeamResults.getCount()) * 100;
-			final float awayOdds = 100 / awayWinPercent;
-
-			activeOdds2 = awayOdds * betMarginAwayDecimal;
-			if (activeLeague.getBetMarginHome() > 0 && awayOdds * betMarginAwayDecimal <= sm.getOdds2()) {
-				if (result.equals("NoBet")) {
-					result = "2";
-				} else {
-					result += "2";
-				}
-			}
-
-		}
-		return result;
-	}
-
-	public ArrayList<SoccerMatch> getMatches() {
-		final ArrayList<SoccerMatch> matches = new ArrayList<>();
-		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 "
-				+ "DATE(gameDate) > '2021-07-01' AND " + "homeScore >= 0 AND " + "awayScore >= 0 AND " + "res.leagueId IN ("
-				+ String.join(",", leagueIds) + ") " + "ORDER BY gameDate ASC";
-
-		PreparedStatement stmt;
-		try {
-			stmt = getConnection().prepareStatement(sql);
-			matches.addAll(super.getMatches(stmt));
-		} 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"), rs.getInt("lookbackHome"),
-						rs.getInt("lookbackDraw"), rs.getInt("lookbackAway"), rs.getInt("betMarginHome"), rs.getInt("betMarginDraw"),
-						rs.getInt("betMarginAway")));
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
+    private ArrayList<League> prioLeagues;
+    private float activeOdds1;
+    private float activeOddsX;
+    private float activeOdds2;
+
+    @Override
+    public void runTest() {
+        float betAmount;
+        float bank = startingBank;
+        final float betLevel = bettingLevel / 100.0f;
+
+        float homeBank = startingBank;
+        float drawBank = startingBank;
+        float awayBank = startingBank;
+
+        final ArrayList<SoccerMatch> matches = getMatches();
+
+        for (int i = 0; i < matches.size(); i++) {
+            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 String betOnThisMatch = checkWhatBet(sm, activeLeague);
+                if (!"NoBet".equals(betOnThisMatch)) {
+                    if (betOnThisMatch.contains("1")) { // Spela p� hemma lag
+                        gamesBettedOn++;
+                        bank = bank - betAmount;
+                        final float homeBetAmount = (homeBank * betLevel);
+                        homeBank -= homeBetAmount;
+
+                        if (sm.getHomeScore() > sm.getAwayScore()) {
+                            bank += betAmount * sm.getOdds1();
+                            homeBank += homeBetAmount * sm.getOdds1();
+                            winsThisDay++;
+                        }
+                    }
+                    if (betOnThisMatch.contains("2")) { // Spela p� borta lag
+                        gamesBettedOn++;
+                        bank = bank - betAmount;
+
+                        final float awayBetAmount = (awayBank * betLevel);
+                        awayBank -= awayBetAmount;
+                        if (sm.getAwayScore() > sm.getHomeScore()) {
+                            bank += betAmount * sm.getOdds2();
+                            awayBank += awayBetAmount * sm.getOdds2();
+                            winsThisDay++;
+                        }
+                    }
+                    if (betOnThisMatch.contains("X")) { // Spela p� Lika
+                        gamesBettedOn++;
+                        bank = bank - betAmount;
+
+                        final float drawBetAmount = (drawBank * betLevel);
+                        drawBank -= drawBetAmount;
+                        if (sm.getHomeScore() == sm.getAwayScore()) {
+                            bank += betAmount * sm.getOddsX();
+                            drawBank += drawBetAmount * sm.getOddsX();
+                            winsThisDay++;
+                        }
+                    }
+                }
+                System.out.println("Match between " + sm.getHomeTeam().getTeamName() + " - "
+                        + sm.getAwayTeam().getTeamName() + " result "
+                        + sm.getHomeScore() + " - " + sm.getAwayScore() + " Betted on " + betOnThisMatch + " at odds "
+                        + sm.getOdds1() + ", "
+                        + sm.getOddsX() + ", " + sm.getOdds2() + " Bet Amount: " + betAmount + " calc odds: "
+                        + activeOdds1 + ", " + activeOddsX
+                        + ", " + activeOdds2);
+            }
+
+            System.out.println(matchesThisDate.get(0).getGameDate() + " result " + (bank - startBank)
+                    + " current bank: " + bank + " bet on "
+                    + gamesBettedOn + "/" + matchesThisDateCount + " wins " + winsThisDay);
+            i += matchesThisDate.size();
+
+        }
+
+        System.out.println(
+                "Final bank " + bank + " homeBank " + homeBank + " drawBank " + drawBank + " awayBank " + awayBank);
+    }
+
+    private String checkWhatBet(SoccerMatch sm, League activeLeague) {
+        String result = "NoBet";
+        final float betMarginHomeDecimal = 1 + (activeLeague.getBetMarginHome() / 100f);
+        final float betMarginDrawDecimal = 1 + (activeLeague.getBetMarginDraw() / 100f);
+        final float betMarginAwayDecimal = 1 + (activeLeague.getBetMarginAway() / 100f);
+
+        final int lookbackHome = activeLeague.getLookbackHome();
+        final int lookbackDraw = activeLeague.getLookbackDraw();
+        final int lookbackAway = activeLeague.getLookbackAway();
+
+        if (lookbackHome > 0) {
+            final TeamResults homeTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getHomeTeam().getTeamId(),
+                    activeLeague.getLookbackHome(), true, sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
+            final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getAwayTeam().getTeamId(),
+                    activeLeague.getLookbackHome(), false, sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
+            final float homeWinPercent = (homeTeamResults.getWins() + awayTeamResults.getLosses())
+                    / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
+            final float homeOdds = 100 / homeWinPercent;
+
+            activeOdds1 = homeOdds * betMarginHomeDecimal;
+            if (activeLeague.getBetMarginHome() > 0 && homeOdds * betMarginHomeDecimal <= sm.getOdds1()) {
+                if (result.equals("NoBet")) {
+                    result = "1";
+                } else {
+                    result += "1";
+                }
+            }
+
+        }
+
+        if (lookbackDraw > 0) {
+            final TeamResults homeTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getHomeTeam().getTeamId(),
+                    activeLeague.getLookbackDraw(), true, sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
+            final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getAwayTeam().getTeamId(),
+                    activeLeague.getLookbackDraw(), false, sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
+            final float drawWinPercent = (homeTeamResults.getDraws() + awayTeamResults.getDraws())
+                    / Float.valueOf(homeTeamResults.getCount() + awayTeamResults.getCount()) * 100;
+            final float drawOdds = 100 / drawWinPercent;
+
+            activeOddsX = drawOdds * betMarginDrawDecimal;
+            if (activeLeague.getBetMarginDraw() > 0 && drawOdds * betMarginDrawDecimal <= sm.getOddsX()) {
+                if (result.equals("NoBet")) {
+                    result = "X";
+                } else {
+                    result += "X";
+                }
+            }
+
+        }
+
+        if (lookbackAway > 0) {
+            final TeamResults homeTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getHomeTeam().getTeamId(),
+                    activeLeague.getLookbackAway(), true, sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
+            final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getAwayTeam().getTeamId(),
+                    activeLeague.getLookbackAway(), false, sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
+            final float awayWinPercent = (awayTeamResults.getWins() + homeTeamResults.getLosses())
+                    / Float.valueOf(awayTeamResults.getCount() + homeTeamResults.getCount()) * 100;
+            final float awayOdds = 100 / awayWinPercent;
+
+            activeOdds2 = awayOdds * betMarginAwayDecimal;
+            if (activeLeague.getBetMarginHome() > 0 && awayOdds * betMarginAwayDecimal <= sm.getOdds2()) {
+                if (result.equals("NoBet")) {
+                    result = "2";
+                } else {
+                    result += "2";
+                }
+            }
+
+        }
+        return result;
+    }
+
+    public ArrayList<SoccerMatch> getMatches() {
+        final ArrayList<SoccerMatch> matches = new ArrayList<>();
+        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 "
+                + "DATE(gameDate) > '2021-07-01' AND " + "homeScore >= 0 AND " + "awayScore >= 0 AND "
+                + "res.leagueId IN ("
+                + String.join(",", leagueIds) + ") " + "ORDER BY gameDate ASC";
+
+        PreparedStatement stmt;
+        try {
+            stmt = getConnection().prepareStatement(sql);
+            matches.addAll(super.getMatches(stmt));
+        } 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("scoringDiffLastGame"),
+                        rs.getInt("scoringTotal"),
+                        rs.getInt("winLossRatioHomeAndAway"), rs.getInt("winLossRatio")));
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
 
 }

+ 0 - 51
OddsJavaFx/src/tests/LeagueTablePositionTest.java

@@ -120,57 +120,6 @@ public class LeagueTablePositionTest extends TestClass {
 		return matchedMatches > 0 ? result / matchedMatches : 0f;
 	}
 
-	private List<Standing> getStandings(List<SoccerMatch> seasonMatches) {
-		List<Standing> result = new ArrayList<>();
-		for (SoccerMatch match : seasonMatches) {
-			Optional<Standing> homeTeam = result.stream().filter(p -> p.getTeamName().equals(match.getHomeTeam().getTeamName())).findFirst();
-			Optional<Standing> awayTeam = result.stream().filter(p -> p.getTeamName().equals(match.getAwayTeam().getTeamName())).findFirst();
-
-			updateStanding(result, match, homeTeam, awayTeam);
-		}
-		return result;
-	}
-
-	private void updateStanding(List<Standing> result, SoccerMatch match, Optional<Standing> homeTeam, Optional<Standing> awayTeam) {
-		int homeScore = match.getHomeScore();
-		int awayScore = match.getAwayScore();
-		if (homeScore > awayScore) {
-			homeTeam.ifPresentOrElse(ht -> {
-				ht.setWins(ht.getWins() + 1);
-				ht.setGamesPlayed(ht.getGamesPlayed() + 1);
-				ht.setPoints(ht.getPoints() + 3);
-			}, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 1, 0, 0, 3, 1)));
-
-			awayTeam.ifPresentOrElse(at -> {
-				at.setLosses(at.getLosses() + 1);
-				at.setGamesPlayed(at.getGamesPlayed() + 1);
-			}, () -> result.add(new Standing(match.getAwayTeam().getTeamName(), 0, 0, 1, 0, 1)));
-
-		} else if (homeScore == awayScore) {
-
-			homeTeam.ifPresentOrElse(ht -> {
-				ht.setDraws(ht.getDraws() + 1);
-				ht.setGamesPlayed(ht.getGamesPlayed() + 1);
-				ht.setPoints(ht.getPoints() + 1);
-			}, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 1, 0, 1, 1)));
-			awayTeam.ifPresentOrElse(at -> {
-				at.setDraws(at.getDraws() + 1);
-				at.setGamesPlayed(at.getGamesPlayed() + 1);
-				at.setPoints(at.getPoints() + 1);
-			}, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 1, 0, 1, 1)));
-		} else if (homeScore < awayScore) {
-			homeTeam.ifPresentOrElse(ht -> {
-				ht.setLosses(ht.getLosses() + 1);
-				ht.setGamesPlayed(ht.getGamesPlayed() + 1);
-			}, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 0, 1, 0, 1)));
-			awayTeam.ifPresentOrElse(at -> {
-				at.setWins(at.getWins() + 1);
-				at.setGamesPlayed(at.getGamesPlayed() + 1);
-				at.setPoints(at.getPoints() + 3);
-			}, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 1, 0, 0, 3, 1)));
-		}
-	}
-
 	private Map<String, Integer> getIntervals(List<SoccerMatch> seasonMatches) {
 		Map<String, Integer> result = new HashMap<>();
 

+ 149 - 139
OddsJavaFx/src/tests/PrioCountriesAll.java

@@ -17,144 +17,154 @@ import objects.TeamResults;
 
 public class PrioCountriesAll extends TestClass {
 
-	private ArrayList<League> prioLeagues;
-
-	@Override 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().getTeamResultsTest(sm.getHomeTeam().getTeamId(), league.getLookback(), true,
-				sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
-		final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getAwayTeam().getTeamId(), league.getLookback(), false,
-				sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
-
-		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;
-	}
-
-	public ArrayList<SoccerMatch> getMatches() {
-		final ArrayList<SoccerMatch> matches = new ArrayList<>();
-		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";
-
-		PreparedStatement stmt;
-		try {
-			stmt = getConnection().prepareStatement(sql);
-			matches.addAll(super.getMatches(stmt));
-		} 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"), rs.getInt("lookbackHome"),
-						rs.getInt("lookbackDraw"), rs.getInt("lookbackAway"), rs.getInt("betMarginHome"), rs.getInt("betMarginDraw"),
-						rs.getInt("betMarginAway")));
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-		return result;
-	}
-
-	@Override public void setup(String date, float startingBank, float bettingLevel, Float betMargin, int lookBack, int sportId, Integer countryId,
-			Integer leagueId) {
-		// TODO Auto-generated method stub
-
-	}
+    private ArrayList<League> prioLeagues;
+
+    @Override
+    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().getTeamResultsTest(sm.getHomeTeam().getTeamId(),
+                league.getLookback(), true,
+                sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
+        final TeamResults awayTeamResults = GuiMysql.getInstance().getTeamResultsTest(sm.getAwayTeam().getTeamId(),
+                league.getLookback(), false,
+                sm.getGameDate().format(DateTimeFormatter.ISO_DATE));
+
+        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;
+    }
+
+    public ArrayList<SoccerMatch> getMatches() {
+        final ArrayList<SoccerMatch> matches = new ArrayList<>();
+        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";
+
+        PreparedStatement stmt;
+        try {
+            stmt = getConnection().prepareStatement(sql);
+            matches.addAll(super.getMatches(stmt));
+        } 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("scoringDiffLastGame"),
+                        rs.getInt("scoringTotal"),
+                        rs.getInt("winLossRatioHomeAndAway"), rs.getInt("winLossRatio")));
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+        return result;
+    }
+
+    @Override
+    public void setup(String date, float startingBank, float bettingLevel, Float betMargin, int lookBack, int sportId,
+            Integer countryId,
+            Integer leagueId) {
+        // TODO Auto-generated method stub
+
+    }
 
 }

+ 343 - 0
OddsJavaFx/src/tests/RelevanceTest.java

@@ -0,0 +1,343 @@
+package tests;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import data.TestDatabase;
+import objects.SoccerMatch;
+import objects.SoccerMatchAnalysis;
+import tests.objects.LeagueDTO;
+
+public class RelevanceTest extends TestClass {
+
+    // Premiere League Siffror
+    // best lookback 16 getScoringDiffLastGames
+    // best lookback 17 scoringTotal
+    // best lookback 19 winLossRationHomeAndAway
+    // best lookback 19 winLossRatio
+
+    // Championship
+    // best lookback 8 getScoringDiffLastGames
+    // best lookback 9 scoringTotal
+    // best lookback 6 winLossRationHomeAndAway
+    // best lookback 5 winLossRatio
+
+    // Allsvenskan
+    // best lookback 12 getScoringDiffLastGames
+    // best lookback 18 scoringTotal
+    // best lookback 14 winLossRationHomeAndAway
+    // best lookback 17 winLossRatio
+
+    // Superettan
+    // best lookback 8 getScoringDiffLastGames
+    // best lookback 4 scoringTotal
+    // best lookback 12 winLossRationHomeAndAway
+    // best lookback 2 winLossRatio
+
+    // MLS
+    // best lookback 9 getScoringDiffLastGames
+    // best lookback 9 scoringTotal
+    // best lookback 7 winLossRationHomeAndAway
+    // best lookback 15 winLossRatio
+
+    private TestDatabase database;
+
+    int scoringDiffLastGames = 8;
+    int scoringTotal = 4;
+    int winLossRationHomeAndAway = 12;
+    int WinLossRatio = 2;
+
+    Map<Float, Integer> winsOnDiff = new HashMap<>();
+    Map<Float, Integer> lossesOnDiff = new HashMap<>();
+    int totalWins = 0;
+    int totalLosses = 0;
+    int draws = 0;
+    int drawsCorrect = 0;
+
+    int gamesLookback = 10;
+
+    float bestPercent = 0;
+    int bestLookback = 0;
+
+    Map<Integer, Float> resultsDiffTotalGoals = new HashMap<>();
+    Map<Integer, Float> resultsDiffHomeAway = new HashMap<>();
+    Map<Integer, Float> resultsWinningForm = new HashMap<>();
+    Map<Integer, Float> resultsWinnignFormHomeVsAway = new HashMap<>();
+    Map<Integer, Float> results = new HashMap<>();
+    Map<String, Float> resultsCombined = new HashMap<>();
+
+    String season;
+
+    @Override
+    public void runTest() {
+        database = TestDatabase.getInstance();
+        LeagueDTO leagueDTO = database.getLeagueDTO(leagueId);
+        LinkedHashMap<String, List<SoccerMatch>> matches = getMatchesOrderedBySeason(leagueDTO);
+
+        boolean skipFirst = true;
+        for (Entry<String, List<SoccerMatch>> seasonMatches : matches.entrySet()) {
+            if (skipFirst) {
+                skipFirst = false;
+                continue;
+            }
+//            for (int i = 1; i < 20; i++) {
+//                gamesLookback = i;
+            season = seasonMatches.getKey();
+//            analyzeDiffHomeAway(seasonMatches.getValue(), resultsDiffHomeAway);
+//            analyzeDiffTotalGoals(seasonMatches.getValue(), resultsDiffTotalGoals);
+//            analyzeWinnigForm(seasonMatches.getValue(), resultsWinningForm);
+//            analyzeWinnigFormHomeVsAway(seasonMatches.getValue(), resultsWinnignFormHomeVsAway);
+            System.out.println("Season " + seasonMatches.getKey());
+            analyzeCombination(seasonMatches.getValue());
+//            break;
+//            }
+        }
+
+        resultsCombined.forEach((k, v) -> System.out.println(k + " result " + v));
+
+//        resultsDiffHomeAway.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
+//                .limit(5)
+//                .forEach(e -> System.out
+//                        .println("resultsDiffHomeAway Lookback " + e.getKey() + " value " + e.getValue()));
+//        resultsDiffTotalGoals.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
+//                .limit(5)
+//                .forEach(e -> System.out
+//                        .println("resultsDiffTotalGoals Lookback " + e.getKey() + " value " + e.getValue()));
+//        resultsWinningForm.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
+//                .limit(5)
+//                .forEach(e -> System.out
+//                        .println("resultsWinningForm Lookback " + e.getKey() + " value " + e.getValue()));
+//        resultsWinnignFormHomeVsAway.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
+//                .limit(5)
+//                .forEach(e -> System.out
+//                        .println("resultsWinnignFormHomeVsAway Lookback " + e.getKey() + " value " + e.getValue()));
+
+        results.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
+                .limit(5)
+                .forEach(e -> System.out.println("Lookback " + e.getKey() + " value " + e.getValue()));
+        System.out.println("Best percent " + bestPercent + " best lookback " + bestLookback);
+
+    }
+
+    private void analyzeDiffHomeAway(List<SoccerMatch> matches, Map<Integer, Float> resultsDiffHomeAway) {
+        System.out.println("Analysis Diff Home Away");
+        winsOnDiff = new HashMap<>();
+        lossesOnDiff = new HashMap<>();
+        totalWins = 0;
+        totalLosses = 0;
+        draws = 0;
+        drawsCorrect = 0;
+
+        for (SoccerMatch soccerMatch : matches) {
+            SoccerMatchAnalysis soccerMatchAnalysis = new SoccerMatchAnalysis(soccerMatch);
+            float scoringDiffLastGames = soccerMatchAnalysis.getScoringDiffLastGames(gamesLookback);
+
+            checkBetResults(soccerMatch, scoringDiffLastGames);
+        }
+
+        TreeMap<Float, Integer> lossesSorted = sortMap(lossesOnDiff);
+        TreeMap<Float, Integer> winsSorted = sortMap(winsOnDiff);
+
+        printResults(winsSorted, lossesSorted, true, resultsDiffHomeAway);
+    }
+
+    private TreeMap<Float, Integer> sortMap(Map<Float, Integer> map) {
+        map.entrySet().stream().sorted(Map.Entry.comparingByKey());
+        TreeMap<Float, Integer> winsSorted = new TreeMap<>(map);
+        return winsSorted;
+    }
+
+    private void analyzeDiffTotalGoals(List<SoccerMatch> matches, Map<Integer, Float> resultsDiffTotalGoals) {
+        System.out.println("Analysis Diff total goals");
+        winsOnDiff = new HashMap<>();
+        lossesOnDiff = new HashMap<>();
+        totalWins = 0;
+        totalLosses = 0;
+        draws = 0;
+        drawsCorrect = 0;
+
+        for (SoccerMatch soccerMatch : matches) {
+            SoccerMatchAnalysis analysis = new SoccerMatchAnalysis(soccerMatch);
+            int homeTeamGoals = analysis.scoringTotal(gamesLookback, true);
+            int awayTeamGoals = analysis.scoringTotal(gamesLookback, false);
+
+            int diff = homeTeamGoals - awayTeamGoals;
+
+            checkBetResults(soccerMatch, diff);
+        }
+
+        TreeMap<Float, Integer> winsSorted = sortMap(winsOnDiff);
+        TreeMap<Float, Integer> lossesSorted = sortMap(lossesOnDiff);
+
+        printResults(winsSorted, lossesSorted, true, resultsDiffTotalGoals);
+    }
+
+    private void analyzeWinnigForm(List<SoccerMatch> matches, Map<Integer, Float> resultsWinningForm) {
+        System.out.println("annalysis Winning form homeAndAway!");
+        winsOnDiff = new HashMap<>();
+        lossesOnDiff = new HashMap<>();
+        totalWins = 0;
+        totalLosses = 0;
+        draws = 0;
+        drawsCorrect = 0;
+
+        for (SoccerMatch soccerMatch : matches) {
+            SoccerMatchAnalysis analysis = new SoccerMatchAnalysis(soccerMatch);
+            int homeWinsCount = analysis.winLossRationHomeAndAway(true, gamesLookback);
+            int awayWindCount = analysis.winLossRationHomeAndAway(false, gamesLookback);
+
+            int diff = homeWinsCount - awayWindCount;
+
+            checkBetResults(soccerMatch, diff);
+        }
+
+        TreeMap<Float, Integer> winsSorted = sortMap(winsOnDiff);
+        TreeMap<Float, Integer> lossesSorted = sortMap(lossesOnDiff);
+
+        printResults(winsSorted, lossesSorted, true, resultsWinningForm);
+    }
+
+    private void analyzeWinnigFormHomeVsAway(List<SoccerMatch> matches,
+            Map<Integer, Float> resultsWinnignFormHomeVsAway) {
+        System.out.println("annalysis Winning form homeVsAway!");
+        winsOnDiff = new HashMap<>();
+        lossesOnDiff = new HashMap<>();
+        totalWins = 0;
+        totalLosses = 0;
+        draws = 0;
+        drawsCorrect = 0;
+
+        for (SoccerMatch soccerMatch : matches) {
+            SoccerMatchAnalysis analysis = new SoccerMatchAnalysis(soccerMatch);
+            int homeWinsCount = analysis.winLossRatio(gamesLookback, true);
+            int awayWindCount = analysis.winLossRatio(gamesLookback, false);
+
+            int diff = homeWinsCount - awayWindCount;
+
+            checkBetResults(soccerMatch, diff);
+        }
+
+        TreeMap<Float, Integer> winsSorted = sortMap(winsOnDiff);
+        TreeMap<Float, Integer> lossesSorted = sortMap(lossesOnDiff);
+
+        printResults(winsSorted, lossesSorted, true, resultsWinnignFormHomeVsAway);
+    }
+
+    private void analyzeCombination(List<SoccerMatch> matches) {
+        System.out.println("analysis Combination!");
+        winsOnDiff = new HashMap<>();
+        lossesOnDiff = new HashMap<>();
+        totalWins = 0;
+        totalLosses = 0;
+        draws = 0;
+        drawsCorrect = 0;
+
+        int betOnHome = 0;
+        int betOnAway = 0;
+
+        int noBet = 0;
+
+        for (SoccerMatch soccerMatch : matches) {
+            SoccerMatchAnalysis analysis = new SoccerMatchAnalysis(soccerMatch);
+            int homeWinsCount = analysis.winLossRatio(WinLossRatio, true);
+            int awayWindCount = analysis.winLossRatio(WinLossRatio, false);
+
+            int homeWinLossRatioCount = analysis.winLossRationHomeAndAway(true, winLossRationHomeAndAway);
+            int awayWinLossRatioCount = analysis.winLossRationHomeAndAway(false, winLossRationHomeAndAway);
+
+            int homeScoringTotal = analysis.scoringTotal(scoringTotal, true);
+            int awayScoringTotal = analysis.scoringTotal(scoringTotal, false);
+
+            int scoringDiffLastGamesDiff = analysis.getScoringDiffLastGames(scoringDiffLastGames);
+            int winsCountDiff = homeWinsCount - awayWindCount;
+            int winLossRatioDiff = homeWinLossRatioCount - awayWinLossRatioCount;
+            int scoringTotalDiff = homeScoringTotal - awayScoringTotal;
+
+            int testValue = 0;
+            if (scoringDiffLastGamesDiff < 0 && winsCountDiff < 0 && winLossRatioDiff < 0 && scoringTotalDiff < 0) {
+                testValue = (scoringDiffLastGamesDiff + winsCountDiff + winLossRatioDiff + scoringTotalDiff) / 4;
+                betOnAway++;
+            } else if (scoringDiffLastGamesDiff > 0 && winsCountDiff > 0 && winLossRatioDiff > 0
+                    && scoringTotalDiff > 0) {
+                testValue = (scoringDiffLastGamesDiff + winsCountDiff + winLossRatioDiff + scoringTotalDiff) / 4;
+                betOnHome++;
+            } else {
+                noBet++;
+            }
+
+            if (testValue != 0) {
+                checkBetResults(soccerMatch, testValue);
+            }
+        }
+
+        TreeMap<Float, Integer> winsSorted = sortMap(winsOnDiff);
+        TreeMap<Float, Integer> lossesSorted = sortMap(lossesOnDiff);
+
+        printResults(winsSorted, lossesSorted, true, results);
+
+        resultsCombined.put(season, (winsSorted.size() / ((float) (winsSorted.size() + lossesSorted.size()))));
+        System.out.println("No Bet " + noBet);
+        System.out.println("Bet on home: " + betOnHome + " bet on away: " + betOnAway);
+    }
+
+    private void checkBetResults(SoccerMatch soccerMatch, float decider) {
+        if (decider > 0) { // Bet on HomeTeam
+            if (soccerMatch.getHomeScore() > soccerMatch.getAwayScore()) {
+                winsOnDiff.put(decider, winsOnDiff.getOrDefault(decider, 0) + 1);
+                totalWins++;
+            } else {
+                lossesOnDiff.put(decider, lossesOnDiff.getOrDefault(decider, 0) + 1);
+                totalLosses++;
+            }
+        } else if (decider < 0) { // Bet on away
+            if (soccerMatch.getHomeScore() < soccerMatch.getAwayScore()) {
+                winsOnDiff.put(decider, winsOnDiff.getOrDefault(decider, 0) + 1);
+                totalWins++;
+            } else {
+                lossesOnDiff.put(decider, lossesOnDiff.getOrDefault(decider, 0) + 1);
+                totalLosses++;
+            }
+        } else { // draw??
+            draws++;
+            if (soccerMatch.getHomeScore() == soccerMatch.getAwayScore()) {
+                drawsCorrect++;
+            }
+        }
+    }
+
+    private void printResults(TreeMap<Float, Integer> winsSorted, TreeMap<Float, Integer> lossesSorted,
+            boolean onlyPercentages, Map<Integer, Float> resultsArray) {
+        StringBuilder winsBuilder = new StringBuilder();
+        winsSorted.forEach((k, v) -> winsBuilder.append(k + " wins " + v + "\n"));
+        StringBuilder lossesBuilder = new StringBuilder();
+        lossesSorted.forEach((k, v) -> lossesBuilder.append(k + " losses " + v + "\n"));
+
+        if (!onlyPercentages) {
+            System.out.println("Analyze Home Away Result");
+            System.out.println("Wins");
+            System.out.println(winsBuilder.toString());
+            System.out.println("Losses");
+            System.out.println(lossesBuilder.toString());
+        }
+
+        float winValue = totalWins / (float) (totalWins + totalLosses);
+        Float res = results.getOrDefault(gamesLookback, 0f);
+
+        resultsArray.put(gamesLookback, res + winValue);
+
+        if (winValue > bestPercent) {
+            bestPercent = winValue;
+            bestLookback = gamesLookback;
+        }
+
+        System.out.println("Totals");
+        System.out.println(winValue + " % total " + (totalWins + totalLosses));
+        System.out.println("Draws " + drawsCorrect / (float) draws + " % total " + draws);
+    }
+
+}

+ 508 - 408
OddsJavaFx/src/tests/TestClass.java

@@ -9,424 +9,524 @@ import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 import com.google.common.collect.Lists;
 
 import data.GuiMysql;
+import data.TestDatabase;
 import objects.League;
 import objects.SoccerMatch;
 import objects.Team;
+import objects.bets.AsianHandicap;
+import tests.objects.LeagueDTO;
+import tests.objects.Standing;
 
 public abstract class TestClass {
 
-	String date;
-	float startingBank;
-	float bettingLevel;
-	float betMargin;
-	int lookBack;
-	int sportId;
-	int countryId;
-	int leagueId;
-	protected int bestAwayLookback;
-	protected int bestAwayMargin;
-	protected int bestDrawMargin;
-	protected int bestDrawLookback;
-	protected int bestHomeMargin;
-	protected int bestHomeLookback;
-	protected float bestDrawBank;
-	protected float bestAwayBank;
-	protected float bestHomeBank;
-
-	ArrayList<results> possitiveResults = new ArrayList<>();
-
-	public abstract void runTest();
-
-	public ArrayList<SoccerMatch> getMatches(PreparedStatement stmt) {
-		final ArrayList<SoccerMatch> matches = Lists.newArrayList();
-
-		try {
-
-			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 void setup(String date, float startingBank, float bettingLevel, Float betMargin, int lookBack, int sportId, Integer countryId,
-			Integer leagueId) {
-		this.startingBank = startingBank;
-		this.bettingLevel = bettingLevel;
-		this.betMargin = betMargin;
-		this.lookBack = lookBack;
-		this.sportId = sportId;
-		this.countryId = countryId;
-		this.leagueId = leagueId;
-		this.date = date;
-	}
-
-	public Connection getConnection() {
-		return GuiMysql.getInstance().getDbConnection();
-	}
-
-	public League getLeagueInfoById() {
-		return GuiMysql.getInstance().getLeagueInfo(leagueId);
-	}
-
-	public League getLeagueInfoByName(String leagueName) {
-		return GuiMysql.getInstance().getLeagueInfo(leagueName);
-	}
-
-	public void CalculateLookback(int leagueId, LocalDateTime date, int daysToCheck) {
-		final LocalDateTime startDate = date.minusDays(daysToCheck);
-		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 = ? AND DATE(gameDate) < ? AND DATE(gameDate) > ? ORDER BY gameDate ASC";
-
-		try {
-			final PreparedStatement stmt = getConnection().prepareStatement(sql);
-			stmt.setInt(1, leagueId);
-			stmt.setString(2, date.format(DateTimeFormatter.ISO_DATE));
-			stmt.setString(3, startDate.format(DateTimeFormatter.ISO_DATE));
-
-			final ArrayList<SoccerMatch> matches = getMatches(stmt);
-			stmt.close();
-
-			if (matches.size() > 0) {
-				this.bestHomeBank = startingBank;
-				this.bestDrawBank = startingBank;
-				this.bestAwayBank = startingBank;
-
-				// TODO Fixa s� att man kontrollerar 1 �r bak�t i tiden som Filtered Matches,
-				// plocka bort om possitive results �r f�rre �n 50%
-				recalcHome(matches);
-				recalcDraw(matches);
-				recalcAway(matches);
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		}
-
-	}
-
-	private void recalcHome(ArrayList<SoccerMatch> matches) {
-		if (this.bestHomeBank < 0) {
-			this.bestHomeBank = startingBank;
-		}
-
-		this.bestHomeLookback = 0;
-		this.bestHomeMargin = 0;
-
-		final float betLevel = bettingLevel / 100f;
-
-		final LocalDateTime currentDate = matches.get(0).getGameDate();
-		LocalDate localDate = currentDate.toLocalDate();
-		float betAmount = startingBank * betLevel;
-
-		possitiveResults.clear();
-
-		for (int lookBack = 4; lookBack < 25; lookBack++) {
-			for (int betMargin = 4; betMargin < 35; betMargin++) {
-				final float betMarginDecimal = 1 + (betMargin / (float) 100);
-				float bank = startingBank;
-				for (final SoccerMatch match : matches) {
-					if (match.getHomeScore() < 0 || match.getAwayScore() < 0) {
-						continue;
-					}
-
-					final List<SoccerMatch> homeMatches = matches.stream().filter(
-							p -> p.getGameDate().isBefore(match.getGameDate()) && p.getHomeTeam().getTeamId() == match.getHomeTeam().getTeamId())
-							.limit(lookBack).collect(Collectors.toList());
-					final List<SoccerMatch> awayMatches = matches.stream().filter(
-							p -> p.getGameDate().isBefore(match.getGameDate()) && p.getAwayTeam().getTeamId() == match.getAwayTeam().getTeamId())
-							.limit(lookBack).collect(Collectors.toList());
-
-					final long hemmaVinster = homeMatches.stream().filter(p -> p.getHomeScore() > p.getAwayScore()).count();
-					final long bortaForluster = awayMatches.stream().filter(p -> p.getAwayScore() < p.getHomeScore()).count();
-
-					final float homeWinPercent = (hemmaVinster + bortaForluster) / Float.valueOf(homeMatches.size() + awayMatches.size()) * 100;
-					final float homeOdds = 100 / homeWinPercent;
-
-					if (localDate.isBefore(match.getGameDate().toLocalDate())) {
-						betAmount = bank * betLevel;
-						localDate = match.getGameDate().toLocalDate();
-					}
-
-					if (homeOdds * betMarginDecimal <= match.getOdds1()) {
-						bank = bank - betAmount;
-						if (match.getHomeScore() > match.getAwayScore()) {
-							bank = bank + betAmount * match.getOdds1();
-						}
-					}
-
-				}
-				if (bank > startingBank) {
-					final int lookBack2 = lookBack;
-					final int betMargin2 = betMargin;
-					final java.util.Optional<results> found = possitiveResults.stream()
-							.filter(r -> r.getLookback() == lookBack2 && r.getMargin() == betMargin2).findFirst();
-					if (found.isPresent()) {
-						final results results = found.get();
-						results.addCount();
-						results.addBank(bank);
-					} else {
-						possitiveResults.add(new results(lookBack, betMargin, bank));
-					}
-				}
-			}
-		}
-		Collections.sort(possitiveResults);
-		if (possitiveResults.size() > 0) {
-			final results res = possitiveResults.get(0);
-			this.bestHomeLookback = res.getLookback();
-			this.bestHomeMargin = res.getMargin();
-			this.bestHomeBank = res.getBank();
-		}
-	}
-
-	private void recalcDraw(ArrayList<SoccerMatch> matches) {
-		if (this.bestDrawBank < 0) {
-			this.bestDrawBank = startingBank;
-		}
-
-		this.bestDrawLookback = 0;
-		this.bestDrawMargin = 0;
-
-		final float betLevel = bettingLevel / 100f;
-
-		final LocalDateTime currentDate = matches.get(0).getGameDate();
-		LocalDate localDate = currentDate.toLocalDate();
-		float betAmount = startingBank * betLevel;
-
-		possitiveResults.clear();
-
-		for (int lookBack = 4; lookBack < 25; lookBack++) {
-			for (int betMargin = 4; betMargin < 35; betMargin++) {
-				final float betMarginDecimal = 1 + (betMargin / (float) 100);
-				float bank = startingBank;
-				for (final SoccerMatch match : matches) {
-					if (match.getHomeScore() < 0 || match.getAwayScore() < 0) {
-						continue;
-					}
-
-					final List<SoccerMatch> homeMatches = matches.stream().filter(
-							p -> p.getGameDate().isBefore(match.getGameDate()) && p.getHomeTeam().getTeamId() == match.getHomeTeam().getTeamId())
-							.limit(lookBack).collect(Collectors.toList());
-					final List<SoccerMatch> awayMatches = matches.stream().filter(
-							p -> p.getGameDate().isBefore(match.getGameDate()) && p.getAwayTeam().getTeamId() == match.getAwayTeam().getTeamId())
-							.limit(lookBack).collect(Collectors.toList());
-
-					final long hemmaLika = homeMatches.stream().filter(p -> p.getHomeScore() == p.getAwayScore()).count();
-					final long bortaLika = awayMatches.stream().filter(p -> p.getAwayScore() == p.getHomeScore()).count();
-
-					final float drawPercent = (hemmaLika + bortaLika) / Float.valueOf(homeMatches.size() + awayMatches.size()) * 100;
-					final float drawOdds = 100 / drawPercent;
-
-					if (localDate.isBefore(match.getGameDate().toLocalDate())) {
-						betAmount = bank * betLevel;
-						localDate = match.getGameDate().toLocalDate();
-					}
-
-					if (drawOdds * betMarginDecimal <= match.getOddsX()) {
-						bank = bank - betAmount;
-						if (match.getHomeScore() == match.getAwayScore()) {
-							bank = bank + betAmount * match.getOddsX();
-						}
-					}
-
-				}
-				if (bank > startingBank) {
-					final int lookBack2 = lookBack;
-					final int betMargin2 = betMargin;
-					final java.util.Optional<results> found = possitiveResults.stream()
-							.filter(r -> r.getLookback() == lookBack2 && r.getMargin() == betMargin2).findFirst();
-					if (found.isPresent()) {
-						final results results = found.get();
-						results.addCount();
-						results.addBank(bank);
-					} else {
-						possitiveResults.add(new results(lookBack, betMargin, bank));
-					}
-				}
-			}
-		}
-		Collections.sort(possitiveResults);
-		if (possitiveResults.size() > 0) {
-			final results res = possitiveResults.get(0);
-			this.bestDrawLookback = res.getLookback();
-			this.bestDrawMargin = res.getMargin();
-			this.bestDrawBank = res.getBank();
-		}
-	}
-
-	private void recalcAway(ArrayList<SoccerMatch> matches) {
-		if (this.bestAwayBank < 0) {
-			this.bestAwayBank = startingBank;
-		}
-
-		this.bestAwayLookback = 0;
-		this.bestAwayMargin = 0;
-
-		final float betLevel = bettingLevel / 100f;
-
-		final LocalDateTime currentDate = matches.get(0).getGameDate();
-		LocalDate localDate = currentDate.toLocalDate();
-		float betAmount = startingBank * betLevel;
-
-		possitiveResults.clear();
-
-		for (int lookBack = 4; lookBack < 25; lookBack++) {
-			for (int betMargin = 4; betMargin < 35; betMargin++) {
-				final float betMarginDecimal = 1 + (betMargin / (float) 100);
-				float bank = startingBank;
-				for (final SoccerMatch match : matches) {
-					if (match.getHomeScore() < 0 || match.getAwayScore() < 0) {
-						continue;
-					}
-
-					final List<SoccerMatch> homeMatches = matches.stream().filter(
-							p -> p.getGameDate().isBefore(match.getGameDate()) && p.getHomeTeam().getTeamId() == match.getHomeTeam().getTeamId())
-							.limit(lookBack).collect(Collectors.toList());
-					final List<SoccerMatch> awayMatches = matches.stream().filter(
-							p -> p.getGameDate().isBefore(match.getGameDate()) && p.getAwayTeam().getTeamId() == match.getAwayTeam().getTeamId())
-							.limit(lookBack).collect(Collectors.toList());
-
-					final long hemmaForluster = homeMatches.stream().filter(p -> p.getHomeScore() < p.getAwayScore()).count();
-					final long bortaVinster = awayMatches.stream().filter(p -> p.getAwayScore() > p.getHomeScore()).count();
-
-					final float awayWinPercent = (hemmaForluster + bortaVinster) / Float.valueOf(homeMatches.size() + awayMatches.size()) * 100;
-					final float awayOdds = 100 / awayWinPercent;
-
-					if (localDate.isBefore(match.getGameDate().toLocalDate())) {
-						betAmount = bank * betLevel;
-						localDate = match.getGameDate().toLocalDate();
-					}
-
-					if (awayOdds * betMarginDecimal <= match.getOdds2()) {
-						bank = bank - betAmount;
-						if (match.getHomeScore() < match.getAwayScore()) {
-							bank = bank + betAmount * match.getOdds2();
-						}
-					}
-
-				}
-
-				if (bank > startingBank) {
-					final int lookBack2 = lookBack;
-					final int betMargin2 = betMargin;
-					final java.util.Optional<results> found = possitiveResults.stream()
-							.filter(r -> r.getLookback() == lookBack2 && r.getMargin() == betMargin2).findFirst();
-					if (found.isPresent()) {
-						final results results = found.get();
-						results.addCount();
-						results.addBank(bank);
-					} else {
-						possitiveResults.add(new results(lookBack, betMargin, bank));
-					}
-				}
-			}
-		}
-
-		Collections.sort(possitiveResults);
-		if (possitiveResults.size() > 0) {
-			final results res = possitiveResults.get(0);
-			this.bestAwayLookback = res.getLookback();
-			this.bestAwayMargin = res.getMargin();
-			this.bestAwayBank = res.getBank();
-		}
-	}
-
-	public class results implements Comparable<results> {
-		int lookback;
-		int margin;
-		int count;
-		float bank;
-
-		public results(int lookback, int margin, float bank) {
-			this.lookback = lookback;
-			this.margin = margin;
-			this.bank = bank;
-			count = 1;
-		}
-
-		public float getBank() {
-			return bank;
-		}
-
-		public void addBank(float bank) {
-			this.bank = (this.bank + bank) / 2;
-		}
-
-		public void addCount() {
-			count++;
-		}
-
-		public int getCount() {
-			return count;
-		}
-
-		public int getLookback() {
-			return lookback;
-		}
-
-		public int getMargin() {
-			return margin;
-		}
-
-		public void setLookback(int lookback) {
-			this.lookback = lookback;
-		}
-
-		public void setMargin(int margin) {
-			this.margin = margin;
-		}
-
-		@Override public int compareTo(results res) {
-			int returnValue = 0;
-			if (this.count > res.getCount()) {
-				returnValue = -1;
-			} else if (this.count == res.getCount()) {
-				if (this.bank > res.getBank()) {
-					returnValue = -1;
-				} else if (this.bank < res.getBank()) {
-					returnValue = 1;
-				} else {
-					returnValue = 0;
-				}
-			} else if (this.count < res.getCount()) {
-				returnValue = 1;
-			}
-			return returnValue;
-		}
-	}
+    String date;
+    float startingBank;
+    float bettingLevel;
+    float betMargin;
+    int lookBack;
+    int sportId;
+    int countryId;
+    int leagueId;
+    protected int bestAwayLookback;
+    protected int bestAwayMargin;
+    protected int bestDrawMargin;
+    protected int bestDrawLookback;
+    protected int bestHomeMargin;
+    protected int bestHomeLookback;
+    protected float bestDrawBank;
+    protected float bestAwayBank;
+    protected float bestHomeBank;
+
+    ArrayList<results> possitiveResults = new ArrayList<>();
+
+    public abstract void runTest();
+
+    public ArrayList<SoccerMatch> getMatches(PreparedStatement stmt) {
+        final ArrayList<SoccerMatch> matches = Lists.newArrayList();
+
+        try {
+
+            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 void setup(String date, float startingBank, float bettingLevel, Float betMargin, int lookBack, int sportId,
+            Integer countryId,
+            Integer leagueId) {
+        this.startingBank = startingBank;
+        this.bettingLevel = bettingLevel;
+        this.betMargin = betMargin;
+        this.lookBack = lookBack;
+        this.sportId = sportId;
+        this.countryId = countryId;
+        this.leagueId = leagueId;
+        this.date = date;
+    }
+
+    public Connection getConnection() {
+        return GuiMysql.getInstance().getDbConnection();
+    }
+
+    public League getLeagueInfoById() {
+        return GuiMysql.getInstance().getLeagueInfo(leagueId);
+    }
+
+    public League getLeagueInfoByName(String leagueName) {
+        return GuiMysql.getInstance().getLeagueInfo(leagueName);
+    }
+
+    public void CalculateLookback(int leagueId, LocalDateTime date, int daysToCheck) {
+        final LocalDateTime startDate = date.minusDays(daysToCheck);
+        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 = ? AND DATE(gameDate) < ? AND DATE(gameDate) > ? ORDER BY gameDate ASC";
+
+        try {
+            final PreparedStatement stmt = getConnection().prepareStatement(sql);
+            stmt.setInt(1, leagueId);
+            stmt.setString(2, date.format(DateTimeFormatter.ISO_DATE));
+            stmt.setString(3, startDate.format(DateTimeFormatter.ISO_DATE));
+
+            final ArrayList<SoccerMatch> matches = getMatches(stmt);
+            stmt.close();
+
+            if (matches.size() > 0) {
+                this.bestHomeBank = startingBank;
+                this.bestDrawBank = startingBank;
+                this.bestAwayBank = startingBank;
+
+                // TODO Fixa s� att man kontrollerar 1 �r bak�t i tiden som Filtered Matches,
+                // plocka bort om possitive results �r f�rre �n 50%
+                recalcHome(matches);
+                recalcDraw(matches);
+                recalcAway(matches);
+            }
+        } catch (final SQLException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public void placeAsianLinesBet(SoccerMatch soccerMatch, AsianHandicap bet) {
+
+    }
+
+    private void recalcHome(ArrayList<SoccerMatch> matches) {
+        if (this.bestHomeBank < 0) {
+            this.bestHomeBank = startingBank;
+        }
+
+        this.bestHomeLookback = 0;
+        this.bestHomeMargin = 0;
+
+        final float betLevel = bettingLevel / 100f;
+
+        final LocalDateTime currentDate = matches.get(0).getGameDate();
+        LocalDate localDate = currentDate.toLocalDate();
+        float betAmount = startingBank * betLevel;
+
+        possitiveResults.clear();
+
+        for (int lookBack = 4; lookBack < 25; lookBack++) {
+            for (int betMargin = 4; betMargin < 35; betMargin++) {
+                final float betMarginDecimal = 1 + (betMargin / (float) 100);
+                float bank = startingBank;
+                for (final SoccerMatch match : matches) {
+                    if (match.getHomeScore() < 0 || match.getAwayScore() < 0) {
+                        continue;
+                    }
+
+                    final List<SoccerMatch> homeMatches = matches.stream().filter(
+                            p -> p.getGameDate().isBefore(match.getGameDate())
+                                    && p.getHomeTeam().getTeamId() == match.getHomeTeam().getTeamId())
+                            .limit(lookBack).collect(Collectors.toList());
+                    final List<SoccerMatch> awayMatches = matches.stream().filter(
+                            p -> p.getGameDate().isBefore(match.getGameDate())
+                                    && p.getAwayTeam().getTeamId() == match.getAwayTeam().getTeamId())
+                            .limit(lookBack).collect(Collectors.toList());
+
+                    final long hemmaVinster = homeMatches.stream().filter(p -> p.getHomeScore() > p.getAwayScore())
+                            .count();
+                    final long bortaForluster = awayMatches.stream().filter(p -> p.getAwayScore() < p.getHomeScore())
+                            .count();
+
+                    final float homeWinPercent = (hemmaVinster + bortaForluster)
+                            / Float.valueOf(homeMatches.size() + awayMatches.size()) * 100;
+                    final float homeOdds = 100 / homeWinPercent;
+
+                    if (localDate.isBefore(match.getGameDate().toLocalDate())) {
+                        betAmount = bank * betLevel;
+                        localDate = match.getGameDate().toLocalDate();
+                    }
+
+                    if (homeOdds * betMarginDecimal <= match.getOdds1()) {
+                        bank = bank - betAmount;
+                        if (match.getHomeScore() > match.getAwayScore()) {
+                            bank = bank + betAmount * match.getOdds1();
+                        }
+                    }
+
+                }
+                if (bank > startingBank) {
+                    final int lookBack2 = lookBack;
+                    final int betMargin2 = betMargin;
+                    final java.util.Optional<results> found = possitiveResults.stream()
+                            .filter(r -> r.getLookback() == lookBack2 && r.getMargin() == betMargin2).findFirst();
+                    if (found.isPresent()) {
+                        final results results = found.get();
+                        results.addCount();
+                        results.addBank(bank);
+                    } else {
+                        possitiveResults.add(new results(lookBack, betMargin, bank));
+                    }
+                }
+            }
+        }
+        Collections.sort(possitiveResults);
+        if (possitiveResults.size() > 0) {
+            final results res = possitiveResults.get(0);
+            this.bestHomeLookback = res.getLookback();
+            this.bestHomeMargin = res.getMargin();
+            this.bestHomeBank = res.getBank();
+        }
+    }
+
+    private void recalcDraw(ArrayList<SoccerMatch> matches) {
+        if (this.bestDrawBank < 0) {
+            this.bestDrawBank = startingBank;
+        }
+
+        this.bestDrawLookback = 0;
+        this.bestDrawMargin = 0;
+
+        final float betLevel = bettingLevel / 100f;
+
+        final LocalDateTime currentDate = matches.get(0).getGameDate();
+        LocalDate localDate = currentDate.toLocalDate();
+        float betAmount = startingBank * betLevel;
+
+        possitiveResults.clear();
+
+        for (int lookBack = 4; lookBack < 25; lookBack++) {
+            for (int betMargin = 4; betMargin < 35; betMargin++) {
+                final float betMarginDecimal = 1 + (betMargin / (float) 100);
+                float bank = startingBank;
+                for (final SoccerMatch match : matches) {
+                    if (match.getHomeScore() < 0 || match.getAwayScore() < 0) {
+                        continue;
+                    }
+
+                    final List<SoccerMatch> homeMatches = matches.stream().filter(
+                            p -> p.getGameDate().isBefore(match.getGameDate())
+                                    && p.getHomeTeam().getTeamId() == match.getHomeTeam().getTeamId())
+                            .limit(lookBack).collect(Collectors.toList());
+                    final List<SoccerMatch> awayMatches = matches.stream().filter(
+                            p -> p.getGameDate().isBefore(match.getGameDate())
+                                    && p.getAwayTeam().getTeamId() == match.getAwayTeam().getTeamId())
+                            .limit(lookBack).collect(Collectors.toList());
+
+                    final long hemmaLika = homeMatches.stream().filter(p -> p.getHomeScore() == p.getAwayScore())
+                            .count();
+                    final long bortaLika = awayMatches.stream().filter(p -> p.getAwayScore() == p.getHomeScore())
+                            .count();
+
+                    final float drawPercent = (hemmaLika + bortaLika)
+                            / Float.valueOf(homeMatches.size() + awayMatches.size()) * 100;
+                    final float drawOdds = 100 / drawPercent;
+
+                    if (localDate.isBefore(match.getGameDate().toLocalDate())) {
+                        betAmount = bank * betLevel;
+                        localDate = match.getGameDate().toLocalDate();
+                    }
+
+                    if (drawOdds * betMarginDecimal <= match.getOddsX()) {
+                        bank = bank - betAmount;
+                        if (match.getHomeScore() == match.getAwayScore()) {
+                            bank = bank + betAmount * match.getOddsX();
+                        }
+                    }
+
+                }
+                if (bank > startingBank) {
+                    final int lookBack2 = lookBack;
+                    final int betMargin2 = betMargin;
+                    final java.util.Optional<results> found = possitiveResults.stream()
+                            .filter(r -> r.getLookback() == lookBack2 && r.getMargin() == betMargin2).findFirst();
+                    if (found.isPresent()) {
+                        final results results = found.get();
+                        results.addCount();
+                        results.addBank(bank);
+                    } else {
+                        possitiveResults.add(new results(lookBack, betMargin, bank));
+                    }
+                }
+            }
+        }
+        Collections.sort(possitiveResults);
+        if (possitiveResults.size() > 0) {
+            final results res = possitiveResults.get(0);
+            this.bestDrawLookback = res.getLookback();
+            this.bestDrawMargin = res.getMargin();
+            this.bestDrawBank = res.getBank();
+        }
+    }
+
+    private void recalcAway(ArrayList<SoccerMatch> matches) {
+        if (this.bestAwayBank < 0) {
+            this.bestAwayBank = startingBank;
+        }
+
+        this.bestAwayLookback = 0;
+        this.bestAwayMargin = 0;
+
+        final float betLevel = bettingLevel / 100f;
+
+        final LocalDateTime currentDate = matches.get(0).getGameDate();
+        LocalDate localDate = currentDate.toLocalDate();
+        float betAmount = startingBank * betLevel;
+
+        possitiveResults.clear();
+
+        for (int lookBack = 4; lookBack < 25; lookBack++) {
+            for (int betMargin = 4; betMargin < 35; betMargin++) {
+                final float betMarginDecimal = 1 + (betMargin / (float) 100);
+                float bank = startingBank;
+                for (final SoccerMatch match : matches) {
+                    if (match.getHomeScore() < 0 || match.getAwayScore() < 0) {
+                        continue;
+                    }
+
+                    final List<SoccerMatch> homeMatches = matches.stream().filter(
+                            p -> p.getGameDate().isBefore(match.getGameDate())
+                                    && p.getHomeTeam().getTeamId() == match.getHomeTeam().getTeamId())
+                            .limit(lookBack).collect(Collectors.toList());
+                    final List<SoccerMatch> awayMatches = matches.stream().filter(
+                            p -> p.getGameDate().isBefore(match.getGameDate())
+                                    && p.getAwayTeam().getTeamId() == match.getAwayTeam().getTeamId())
+                            .limit(lookBack).collect(Collectors.toList());
+
+                    final long hemmaForluster = homeMatches.stream().filter(p -> p.getHomeScore() < p.getAwayScore())
+                            .count();
+                    final long bortaVinster = awayMatches.stream().filter(p -> p.getAwayScore() > p.getHomeScore())
+                            .count();
+
+                    final float awayWinPercent = (hemmaForluster + bortaVinster)
+                            / Float.valueOf(homeMatches.size() + awayMatches.size()) * 100;
+                    final float awayOdds = 100 / awayWinPercent;
+
+                    if (localDate.isBefore(match.getGameDate().toLocalDate())) {
+                        betAmount = bank * betLevel;
+                        localDate = match.getGameDate().toLocalDate();
+                    }
+
+                    if (awayOdds * betMarginDecimal <= match.getOdds2()) {
+                        bank = bank - betAmount;
+                        if (match.getHomeScore() < match.getAwayScore()) {
+                            bank = bank + betAmount * match.getOdds2();
+                        }
+                    }
+
+                }
+
+                if (bank > startingBank) {
+                    final int lookBack2 = lookBack;
+                    final int betMargin2 = betMargin;
+                    final java.util.Optional<results> found = possitiveResults.stream()
+                            .filter(r -> r.getLookback() == lookBack2 && r.getMargin() == betMargin2).findFirst();
+                    if (found.isPresent()) {
+                        final results results = found.get();
+                        results.addCount();
+                        results.addBank(bank);
+                    } else {
+                        possitiveResults.add(new results(lookBack, betMargin, bank));
+                    }
+                }
+            }
+        }
+
+        Collections.sort(possitiveResults);
+        if (possitiveResults.size() > 0) {
+            final results res = possitiveResults.get(0);
+            this.bestAwayLookback = res.getLookback();
+            this.bestAwayMargin = res.getMargin();
+            this.bestAwayBank = res.getBank();
+        }
+    }
+
+    protected List<Standing> getStandings(List<SoccerMatch> seasonMatches) {
+        List<Standing> result = new ArrayList<>();
+        for (SoccerMatch match : seasonMatches) {
+            Optional<Standing> homeTeam = result.stream()
+                    .filter(p -> p.getTeamName().equals(match.getHomeTeam().getTeamName())).findFirst();
+            Optional<Standing> awayTeam = result.stream()
+                    .filter(p -> p.getTeamName().equals(match.getAwayTeam().getTeamName())).findFirst();
+
+            updateStanding(result, match, homeTeam, awayTeam);
+        }
+        return result;
+    }
+
+    protected void updateStanding(List<Standing> result, SoccerMatch match, Optional<Standing> homeTeam,
+            Optional<Standing> awayTeam) {
+        int homeScore = match.getHomeScore();
+        int awayScore = match.getAwayScore();
+        if (homeScore > awayScore) {
+            homeTeam.ifPresentOrElse(ht -> {
+                ht.setWins(ht.getWins() + 1);
+                ht.setGamesPlayed(ht.getGamesPlayed() + 1);
+                ht.setPoints(ht.getPoints() + 3);
+            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 1, 0, 0, 3, 1)));
+
+            awayTeam.ifPresentOrElse(at -> {
+                at.setLosses(at.getLosses() + 1);
+                at.setGamesPlayed(at.getGamesPlayed() + 1);
+            }, () -> result.add(new Standing(match.getAwayTeam().getTeamName(), 0, 0, 1, 0, 1)));
+
+        } else if (homeScore == awayScore) {
+
+            homeTeam.ifPresentOrElse(ht -> {
+                ht.setDraws(ht.getDraws() + 1);
+                ht.setGamesPlayed(ht.getGamesPlayed() + 1);
+                ht.setPoints(ht.getPoints() + 1);
+            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 1, 0, 1, 1)));
+            awayTeam.ifPresentOrElse(at -> {
+                at.setDraws(at.getDraws() + 1);
+                at.setGamesPlayed(at.getGamesPlayed() + 1);
+                at.setPoints(at.getPoints() + 1);
+            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 1, 0, 1, 1)));
+        } else if (homeScore < awayScore) {
+            homeTeam.ifPresentOrElse(ht -> {
+                ht.setLosses(ht.getLosses() + 1);
+                ht.setGamesPlayed(ht.getGamesPlayed() + 1);
+            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 0, 0, 1, 0, 1)));
+            awayTeam.ifPresentOrElse(at -> {
+                at.setWins(at.getWins() + 1);
+                at.setGamesPlayed(at.getGamesPlayed() + 1);
+                at.setPoints(at.getPoints() + 3);
+            }, () -> result.add(new Standing(match.getHomeTeam().getTeamName(), 1, 0, 0, 3, 1)));
+        }
+    }
+
+    protected LinkedHashMap<String, List<SoccerMatch>> getMatchesOrderedBySeason(LeagueDTO leagueDTO) {
+        List<SoccerMatch> matches = TestDatabase.getInstance().getMatches(leagueDTO);
+
+        LinkedHashMap<String, List<SoccerMatch>> matchesBySeason = new LinkedHashMap<>();
+        matches.forEach(sm -> {
+            List<SoccerMatch> matchesInSeason = matchesBySeason.getOrDefault(sm.getSeason(), new ArrayList<>());
+            matchesInSeason.add(sm);
+            matchesBySeason.put(sm.getSeason(), matchesInSeason);
+        });
+
+        LinkedHashMap<String, List<SoccerMatch>> sortedMap = new LinkedHashMap<>();
+        matchesBySeason.entrySet().stream().sorted(Map.Entry.comparingByKey(Comparator.reverseOrder()))
+                .forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));
+        return sortedMap;
+    }
+
+    public class results implements Comparable<results> {
+        int lookback;
+        int margin;
+        int count;
+        float bank;
+
+        public results(int lookback, int margin, float bank) {
+            this.lookback = lookback;
+            this.margin = margin;
+            this.bank = bank;
+            count = 1;
+        }
+
+        public float getBank() {
+            return bank;
+        }
+
+        public void addBank(float bank) {
+            this.bank = (this.bank + bank) / 2;
+        }
+
+        public void addCount() {
+            count++;
+        }
+
+        public int getCount() {
+            return count;
+        }
+
+        public int getLookback() {
+            return lookback;
+        }
+
+        public int getMargin() {
+            return margin;
+        }
+
+        public void setLookback(int lookback) {
+            this.lookback = lookback;
+        }
+
+        public void setMargin(int margin) {
+            this.margin = margin;
+        }
+
+        @Override
+        public int compareTo(results res) {
+            int returnValue = 0;
+            if (this.count > res.getCount()) {
+                returnValue = -1;
+            } else if (this.count == res.getCount()) {
+                if (this.bank > res.getBank()) {
+                    returnValue = -1;
+                } else if (this.bank < res.getBank()) {
+                    returnValue = 1;
+                } else {
+                    returnValue = 0;
+                }
+            } else if (this.count < res.getCount()) {
+                returnValue = 1;
+            }
+            return returnValue;
+        }
+    }
 }