diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 9cf50bc..6944e2d 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -5,10 +5,11 @@ updates:
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
- target-branch: "develop"
-
+ target-branch: "master"
+
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- target-branch: "develop"
+ target-branch: "master"
+
diff --git a/.gitignore b/.gitignore
index 77c7396..6ed06f0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@ target/
!**/src/test/**/target/
data.mv.db
src/main/bundles
+node_modules
# for secrets
.env
diff --git a/README.md b/README.md
index 93418c2..6b3bf55 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ To build the project and run the application with the embedded H2 database, use
```sh
mvn clean package
-mvn spring-boot:run
+mvn spring-boot:run -Ptest
```
diff --git a/pom.xml b/pom.xml
index 30e336f..6af9682 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
org.springframework.boot
spring-boot-starter-parent
- 3.4.4
+ 3.5.0
@@ -19,7 +19,7 @@
23
23
UTF-8
- 24.7.1
+ 24.7.5
test
@@ -46,11 +46,6 @@
com.vaadin
vaadin-spring-boot-starter
-
- com.github.appreciated
- apexcharts
- 24.0.2
-
org.mariadb.jdbc
@@ -151,4 +146,4 @@
-
\ No newline at end of file
+
diff --git a/src/main/java/org/kickerelo/kickerelo/data/Spieler.java b/src/main/java/org/kickerelo/kickerelo/data/Spieler.java
index 257b16f..db2843e 100644
--- a/src/main/java/org/kickerelo/kickerelo/data/Spieler.java
+++ b/src/main/java/org/kickerelo/kickerelo/data/Spieler.java
@@ -69,4 +69,10 @@ public class Spieler {
public String toString() {
return this.name;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Spieler)) return false;
+ return this.id == ((Spieler) o).id;
+ }
}
diff --git a/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java b/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java
index e3163dc..8e8f7e9 100644
--- a/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java
+++ b/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java
@@ -3,6 +3,8 @@ package org.kickerelo.kickerelo.repository;
import org.kickerelo.kickerelo.data.Ergebnis2vs2;
import org.kickerelo.kickerelo.data.Spieler;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
@Repository
@@ -12,7 +14,14 @@ public interface Ergebnis2vs2Repository extends JpaRepository changes1vs1 = new HashMap<>();
+ static Map changes2vs2 = new HashMap<>();
+
+ public static void put1vs1Result(Long gameId, EloChange1vs1 change) {
+ changes1vs1.put(gameId, change);
+ }
+
+ public static void put2vs2Result(long gameId, EloChange2vs2 change) {
+ changes2vs2.put(gameId, change);
+ }
+
+ public static EloChange1vs1 get1vs1Result(long gameId) {
+ var result = changes1vs1.get(gameId);
+ assert result != null;
+ return result;
+ }
+
+ public static EloChange2vs2 get2vs2Result(long gameId) {
+ var result = changes2vs2.get(gameId);
+ assert result != null;
+ return result;
+ }
+}
diff --git a/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java b/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java
index b6308e7..e611a96 100644
--- a/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java
+++ b/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java
@@ -2,7 +2,6 @@ package org.kickerelo.kickerelo.service;
import org.kickerelo.kickerelo.exception.DuplicatePlayerException;
import org.kickerelo.kickerelo.exception.InvalidDataException;
-import org.kickerelo.kickerelo.exception.NoSuchPlayerException;
import org.kickerelo.kickerelo.data.Ergebnis1vs1;
import org.kickerelo.kickerelo.data.Ergebnis2vs2;
import org.kickerelo.kickerelo.data.Spieler;
@@ -10,10 +9,11 @@ import org.kickerelo.kickerelo.exception.PlayerNameNotSetException;
import org.kickerelo.kickerelo.repository.Ergebnis1vs1Repository;
import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository;
import org.kickerelo.kickerelo.repository.SpielerRepository;
-import org.kickerelo.kickerelo.util.Ergebnis1vs1TimeComparator;
-import org.kickerelo.kickerelo.util.Ergebnis2vs2TimeComparator;
-import org.kickerelo.kickerelo.util.Spieler1vs1EloComparator;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.kickerelo.kickerelo.util.EloChange1vs1;
+import org.kickerelo.kickerelo.util.EloChange2vs2;
+import org.kickerelo.kickerelo.util.comparator.Ergebnis1vs1TimeComparator;
+import org.kickerelo.kickerelo.util.comparator.Ergebnis2vs2TimeComparator;
+import org.kickerelo.kickerelo.util.comparator.SpielerNameComparator;
import org.springframework.stereotype.Service;
import java.util.HashMap;
@@ -25,14 +25,22 @@ import java.util.stream.Stream;
*/
@Service
public class KickerEloService {
- @Autowired
- private Ergebnis1vs1Repository ergebnis1vs1Repository;
- @Autowired
- private Ergebnis2vs2Repository ergebnis2vs2Repository;
- @Autowired
- private SpielerRepository spielerRepository;
- @Autowired
- private EloCalculationService eloCalculationService;
+ private final Ergebnis1vs1Repository ergebnis1vs1Repository;
+ private final Ergebnis2vs2Repository ergebnis2vs2Repository;
+ private final SpielerRepository spielerRepository;
+ private final EloCalculationService eloCalculationService;
+
+ public KickerEloService(Ergebnis1vs1Repository ergebnis1vs1Repository,
+ Ergebnis2vs2Repository ergebnis2vs2Repository,
+ SpielerRepository spielerRepository,
+ EloCalculationService eloCalculationService) {
+ this.ergebnis1vs1Repository = ergebnis1vs1Repository;
+ this.ergebnis2vs2Repository = ergebnis2vs2Repository;
+ this.spielerRepository = spielerRepository;
+ this.eloCalculationService = eloCalculationService;
+ recalculateAll1vs1();
+ recalculateAll2vs2();
+ }
/**
* @return List of all player names sorted alphabetically
@@ -45,68 +53,61 @@ public class KickerEloService {
* @return List of all player entities sorted by 1 vs 1 ELO
*/
public List getSpielerEntities() {
- return spielerRepository.findAll().stream().sorted(new Spieler1vs1EloComparator()).toList();
+ return spielerRepository.findAll().stream().sorted(new SpielerNameComparator()).toList();
}
/**
* Enter a result of a 1 vs 1 game
- * @param gewinnerName The name of the winning player
- * @param verliererName The name of the losing player
+ * @param gewinner The winning player
+ * @param verlierer The losing player
* @param toreVerlierer The number of goals of the loser
*/
- public void enterResult1vs1(String gewinnerName, String verliererName,
+ public void enterResult1vs1(Spieler gewinner, Spieler verlierer,
short toreVerlierer) {
// Check if the inputs are valid
- if (gewinnerName == null || verliererName == null) {
+ if (gewinner == null || verlierer == null) {
throw new PlayerNameNotSetException("Alle Namen müssen gesetzt sein");
}
- if (gewinnerName.equals(verliererName)) {
+ if (gewinner.equals(verlierer)) {
throw new DuplicatePlayerException("winner and loser identical");
}
if (toreVerlierer > 9 || toreVerlierer < 0) {
throw new InvalidDataException("too many goals");
}
- Spieler gewinner = spielerRepository.findByName(gewinnerName)
- .orElseThrow(() -> new NoSuchPlayerException(gewinnerName));
-
- Spieler verlierer = spielerRepository.findByName(verliererName)
- .orElseThrow(() -> new NoSuchPlayerException(verliererName));
-
-
Ergebnis1vs1 ergebnis = new Ergebnis1vs1(gewinner, verlierer, toreVerlierer);
- ergebnis1vs1Repository.save(ergebnis);
+ ergebnis = ergebnis1vs1Repository.save(ergebnis);
- eloCalculationService.updateElo1vs1(gewinner, verlierer, toreVerlierer);
+ EloChange1vs1 change = eloCalculationService.updateElo1vs1(gewinner, verlierer, toreVerlierer);
+ EloChangeTracker.put1vs1Result(ergebnis.getId(), change);
spielerRepository.save(gewinner);
spielerRepository.save(verlierer);
-
}
/**
* Enter the result of a 2 vs 2 game
- * @param gewinnerNameVorn Name of the winning offensive player
- * @param gewinnerNameHinten Name of the winning defensive player
- * @param verliererNameVorn Name of the losing offensive player
- * @param verliererNameHinten Name of the losing defensive player
+ * @param gewinnerVorn winning offensive player
+ * @param gewinnerHinten winning defensive player
+ * @param verliererVorn losing offensive player
+ * @param verliererHinten losing defensive player
* @param toreVerlierer Number of goals of the losing team
*/
- public void enterResult2vs2(String gewinnerNameVorn, String gewinnerNameHinten,
- String verliererNameVorn, String verliererNameHinten,
+ public void enterResult2vs2(Spieler gewinnerVorn, Spieler gewinnerHinten,
+ Spieler verliererVorn, Spieler verliererHinten,
short toreVerlierer) {
// Check if the inputs are valid
- if (gewinnerNameVorn == null || gewinnerNameHinten == null
- || verliererNameVorn == null || verliererNameHinten == null) {
+ if (gewinnerVorn == null || gewinnerHinten == null
+ || verliererVorn == null || verliererHinten == null) {
throw new PlayerNameNotSetException("Alle Namen müssen gesetzt sein");
}
- if (gewinnerNameVorn.equals(gewinnerNameHinten) ||
- gewinnerNameVorn.equals(verliererNameVorn) ||
- gewinnerNameVorn.equals(verliererNameHinten) ||
- gewinnerNameHinten.equals(verliererNameVorn) ||
- gewinnerNameHinten.equals(verliererNameHinten) ||
- verliererNameVorn.equals(verliererNameHinten)) {
+ if (gewinnerVorn.equals(gewinnerHinten) ||
+ gewinnerVorn.equals(verliererVorn) ||
+ gewinnerVorn.equals(verliererHinten) ||
+ gewinnerHinten.equals(verliererVorn) ||
+ gewinnerHinten.equals(verliererHinten) ||
+ verliererVorn.equals(verliererHinten)) {
throw new DuplicatePlayerException("players must not be identical");
}
@@ -114,22 +115,11 @@ public class KickerEloService {
throw new InvalidDataException("too many loser goals");
}
- Spieler gewinnerVorn = spielerRepository.findByName(gewinnerNameVorn)
- .orElseThrow(() -> new NoSuchPlayerException(gewinnerNameVorn));
-
- Spieler gewinnerHinten = spielerRepository.findByName(gewinnerNameHinten)
- .orElseThrow(() -> new NoSuchPlayerException(gewinnerNameHinten));
-
- Spieler verliererVorn = spielerRepository.findByName(verliererNameVorn)
- .orElseThrow(() -> new NoSuchPlayerException(verliererNameVorn));
-
- Spieler verliererHinten = spielerRepository.findByName(verliererNameHinten)
- .orElseThrow(() -> new NoSuchPlayerException(verliererNameHinten));
-
Ergebnis2vs2 ergebnis = new Ergebnis2vs2(gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer);
- ergebnis2vs2Repository.save(ergebnis);
+ ergebnis = ergebnis2vs2Repository.save(ergebnis);
- eloCalculationService.updateElo2vs2(gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer);
+ EloChange2vs2 change = eloCalculationService.updateElo2vs2(gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer);
+ EloChangeTracker.put2vs2Result(ergebnis.getId(), change);
spielerRepository.save(gewinnerVorn);
spielerRepository.save(gewinnerHinten);
spielerRepository.save(verliererVorn);
@@ -169,9 +159,10 @@ public class KickerEloService {
}
Stream results = ergebnis1vs1Repository.findAll().stream().sorted(new Ergebnis1vs1TimeComparator());
results.forEach(r -> {
- eloCalculationService.updateElo1vs1(players.get(r.getGewinner().getId()),
- players.get(r.getVerlierer().getId()),
- r.getToreVerlierer());
+ EloChange1vs1 c = eloCalculationService.updateElo1vs1(players.get(r.getGewinner().getId()),
+ players.get(r.getVerlierer().getId()),
+ r.getToreVerlierer());
+ EloChangeTracker.put1vs1Result(r.getId(), c);
});
spielerRepository.saveAll(players.values());
}
@@ -187,11 +178,12 @@ public class KickerEloService {
}
Stream results = ergebnis2vs2Repository.findAll().stream().sorted(new Ergebnis2vs2TimeComparator());
results.forEach(r -> {
- eloCalculationService.updateElo2vs2(players.get(r.getGewinnerVorn().getId()),
- players.get(r.getGewinnerHinten().getId()),
- players.get(r.getVerliererVorn().getId()),
- players.get(r.getVerliererHinten().getId()),
- r.getToreVerlierer());
+ EloChange2vs2 c = eloCalculationService.updateElo2vs2(players.get(r.getGewinnerVorn().getId()),
+ players.get(r.getGewinnerHinten().getId()),
+ players.get(r.getVerliererVorn().getId()),
+ players.get(r.getVerliererHinten().getId()),
+ r.getToreVerlierer());
+ EloChangeTracker.put2vs2Result(r.getId(), c);
});
spielerRepository.saveAll(players.values());
}
diff --git a/src/main/java/org/kickerelo/kickerelo/service/Stat2vs2Service.java b/src/main/java/org/kickerelo/kickerelo/service/Stat2vs2Service.java
index 7d73e62..26094dc 100644
--- a/src/main/java/org/kickerelo/kickerelo/service/Stat2vs2Service.java
+++ b/src/main/java/org/kickerelo/kickerelo/service/Stat2vs2Service.java
@@ -35,7 +35,7 @@ public class Stat2vs2Service {
}
public Float getFrontRate(Spieler s) {
- int numFront = ergebnis2vs2Repository.countByGewinnerVornOrGewinnerHinten(s, s);
+ int numFront = ergebnis2vs2Repository.countByGewinnerVornOrVerliererVorn(s, s);
int numAll = ergebnis2vs2Repository.countByGewinnerVornOrGewinnerHintenOrVerliererVornOrVerliererHinten(s, s, s, s);
return (float) numFront / numAll;
}
diff --git a/src/main/java/org/kickerelo/kickerelo/util/EloChange1vs1.java b/src/main/java/org/kickerelo/kickerelo/util/EloChange1vs1.java
new file mode 100644
index 0000000..265481f
--- /dev/null
+++ b/src/main/java/org/kickerelo/kickerelo/util/EloChange1vs1.java
@@ -0,0 +1,5 @@
+package org.kickerelo.kickerelo.util;
+
+public record EloChange1vs1(double winnerEloChange,
+ double loserEloChange) {
+}
diff --git a/src/main/java/org/kickerelo/kickerelo/util/EloChange2vs2.java b/src/main/java/org/kickerelo/kickerelo/util/EloChange2vs2.java
new file mode 100644
index 0000000..426b760
--- /dev/null
+++ b/src/main/java/org/kickerelo/kickerelo/util/EloChange2vs2.java
@@ -0,0 +1,7 @@
+package org.kickerelo.kickerelo.util;
+
+public record EloChange2vs2(double winnerFrontEloChange,
+ double winnerBackEloChange,
+ double loserFrontEloChange,
+ double loserBackEloChange) {
+}
diff --git a/src/main/java/org/kickerelo/kickerelo/util/Ergebnis1vs1TimeComparator.java b/src/main/java/org/kickerelo/kickerelo/util/comparator/Ergebnis1vs1TimeComparator.java
similarity index 86%
rename from src/main/java/org/kickerelo/kickerelo/util/Ergebnis1vs1TimeComparator.java
rename to src/main/java/org/kickerelo/kickerelo/util/comparator/Ergebnis1vs1TimeComparator.java
index 660e0cd..94cb9da 100644
--- a/src/main/java/org/kickerelo/kickerelo/util/Ergebnis1vs1TimeComparator.java
+++ b/src/main/java/org/kickerelo/kickerelo/util/comparator/Ergebnis1vs1TimeComparator.java
@@ -1,4 +1,4 @@
-package org.kickerelo.kickerelo.util;
+package org.kickerelo.kickerelo.util.comparator;
import org.kickerelo.kickerelo.data.Ergebnis1vs1;
diff --git a/src/main/java/org/kickerelo/kickerelo/util/Ergebnis2vs2TimeComparator.java b/src/main/java/org/kickerelo/kickerelo/util/comparator/Ergebnis2vs2TimeComparator.java
similarity index 86%
rename from src/main/java/org/kickerelo/kickerelo/util/Ergebnis2vs2TimeComparator.java
rename to src/main/java/org/kickerelo/kickerelo/util/comparator/Ergebnis2vs2TimeComparator.java
index ed0ab69..508d544 100644
--- a/src/main/java/org/kickerelo/kickerelo/util/Ergebnis2vs2TimeComparator.java
+++ b/src/main/java/org/kickerelo/kickerelo/util/comparator/Ergebnis2vs2TimeComparator.java
@@ -1,4 +1,4 @@
-package org.kickerelo.kickerelo.util;
+package org.kickerelo.kickerelo.util.comparator;
import org.kickerelo.kickerelo.data.Ergebnis2vs2;
diff --git a/src/main/java/org/kickerelo/kickerelo/util/Spieler1vs1EloComparator.java b/src/main/java/org/kickerelo/kickerelo/util/comparator/Spieler1vs1EloComparator.java
similarity index 85%
rename from src/main/java/org/kickerelo/kickerelo/util/Spieler1vs1EloComparator.java
rename to src/main/java/org/kickerelo/kickerelo/util/comparator/Spieler1vs1EloComparator.java
index b424ffd..0ee483e 100644
--- a/src/main/java/org/kickerelo/kickerelo/util/Spieler1vs1EloComparator.java
+++ b/src/main/java/org/kickerelo/kickerelo/util/comparator/Spieler1vs1EloComparator.java
@@ -1,4 +1,4 @@
-package org.kickerelo.kickerelo.util;
+package org.kickerelo.kickerelo.util.comparator;
import org.kickerelo.kickerelo.data.Spieler;
diff --git a/src/main/java/org/kickerelo/kickerelo/util/Spieler2vs2EloComparator.java b/src/main/java/org/kickerelo/kickerelo/util/comparator/Spieler2vs2EloComparator.java
similarity index 85%
rename from src/main/java/org/kickerelo/kickerelo/util/Spieler2vs2EloComparator.java
rename to src/main/java/org/kickerelo/kickerelo/util/comparator/Spieler2vs2EloComparator.java
index f9ea739..d6add0e 100644
--- a/src/main/java/org/kickerelo/kickerelo/util/Spieler2vs2EloComparator.java
+++ b/src/main/java/org/kickerelo/kickerelo/util/comparator/Spieler2vs2EloComparator.java
@@ -1,4 +1,4 @@
-package org.kickerelo.kickerelo.util;
+package org.kickerelo.kickerelo.util.comparator;
import org.kickerelo.kickerelo.data.Spieler;
diff --git a/src/main/java/org/kickerelo/kickerelo/util/comparator/SpielerNameComparator.java b/src/main/java/org/kickerelo/kickerelo/util/comparator/SpielerNameComparator.java
new file mode 100644
index 0000000..8626caa
--- /dev/null
+++ b/src/main/java/org/kickerelo/kickerelo/util/comparator/SpielerNameComparator.java
@@ -0,0 +1,12 @@
+package org.kickerelo.kickerelo.util.comparator;
+
+import org.kickerelo.kickerelo.data.Spieler;
+
+import java.util.Comparator;
+
+public class SpielerNameComparator implements Comparator {
+ @Override
+ public int compare(Spieler o1, Spieler o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+}
diff --git a/src/main/java/org/kickerelo/kickerelo/views/Chart.java b/src/main/java/org/kickerelo/kickerelo/views/Chart.java
new file mode 100644
index 0000000..a963ff6
--- /dev/null
+++ b/src/main/java/org/kickerelo/kickerelo/views/Chart.java
@@ -0,0 +1,49 @@
+package org.kickerelo.kickerelo.views;
+
+import java.util.List;
+
+import com.vaadin.flow.component.Component;
+import com.vaadin.flow.component.UI;
+import com.vaadin.flow.component.Tag;
+
+import org.json.JSONArray;
+
+@Tag("canvas")
+public class Chart extends Component {
+
+ public Chart(List xvalues, List yvalues) {
+ setId("chart");
+
+ UI.getCurrent().getPage().addJavaScript("https://cdn.jsdelivr.net/npm/chart.js");
+
+ JSONArray x = new JSONArray(xvalues);
+ JSONArray y = new JSONArray(yvalues);
+
+ String js = "";
+
+ // Dark mode setting
+ js += "if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {";
+ js += "Chart.defaults.color = 'hsla(214, 96%, 96%, 0.9)';";
+ js += "Chart.defaults.borderColor = 'hsla(214, 78%, 88%, 0.5)';";
+ js += "}";
+
+ // Font size
+ js += "Chart.defaults.font.size = 16;";
+
+ // Scales
+ js += "Chart.defaults.scales.category.ticks.autoSkip = false;";
+ js += "Chart.defaults.scales.category.offset = true;";
+
+ // Chart
+ js += "new Chart(document.getElementById('chart'), {type: 'line', ";
+ js += "options: {showLine: false, pointRadius: 7, plugins: { legend: { display: false}}, layout: { padding: 10}}, ";
+
+ // Data
+ js += "data: { labels: " + x + ", datasets:[{data: " + y + ", ";
+ js += "borderColor: 'hsl(214, 90%, 48%)', backgroundColor: 'hsl(214, 90%, 77%)'}]}});";
+
+ getElement().executeJs(js);
+
+ }
+
+}
diff --git a/src/main/java/org/kickerelo/kickerelo/views/Chart1vs1.java b/src/main/java/org/kickerelo/kickerelo/views/Chart1vs1.java
deleted file mode 100644
index 7f109ae..0000000
--- a/src/main/java/org/kickerelo/kickerelo/views/Chart1vs1.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.kickerelo.kickerelo.views;
-
-import java.util.List;
-
-import org.kickerelo.kickerelo.data.Spieler;
-import org.kickerelo.kickerelo.util.Spieler1vs1EloComparator;
-
-import com.github.appreciated.apexcharts.ApexChartsBuilder;
-import com.github.appreciated.apexcharts.config.Theme;
-import com.github.appreciated.apexcharts.config.builder.ChartBuilder;
-import com.github.appreciated.apexcharts.config.builder.XAxisBuilder;
-import com.github.appreciated.apexcharts.config.builder.YAxisBuilder;
-import com.github.appreciated.apexcharts.config.chart.Type;
-import com.github.appreciated.apexcharts.config.chart.builder.ZoomBuilder;
-import com.github.appreciated.apexcharts.config.chart.zoom.ZoomType;
-import com.github.appreciated.apexcharts.config.theme.Mode;
-import com.github.appreciated.apexcharts.config.theme.Monochrome;
-import com.github.appreciated.apexcharts.config.xaxis.Labels;
-import com.github.appreciated.apexcharts.helper.Series;
-import com.vaadin.flow.router.Route;
-
-@Route(value = "app/chart1vs1")
-public class Chart1vs1 extends ApexChartsBuilder {
- public Chart1vs1(List l) {
- Theme theme = new Theme();
- Monochrome monochrome = new Monochrome();
- monochrome.setEnabled(true);
- theme.setMode(Mode.DARK);
- theme.setMonochrome(monochrome);
- Labels labels = new Labels();
- labels.setRotate(270d);
- labels.setShow(true);
- labels.setRotateAlways(false);
-
-
- withChart(ChartBuilder.get().withType(Type.SCATTER)
- .withZoom(ZoomBuilder.get().withEnabled(true).withType(ZoomType.XY).build()).build())
- .withSeries(new Series<>("ELO",
- l.stream().sorted(new Spieler1vs1EloComparator()).map(Spieler::getElo1vs1).toArray()
- ))
- .withXaxis(XAxisBuilder.get().withCategories(l.stream().sorted(new Spieler1vs1EloComparator())
- .map(Spieler::getName).toList()).withLabels(labels).build())
- .withYaxis(YAxisBuilder.get().build())
- .withTheme(theme);
- }
-}
diff --git a/src/main/java/org/kickerelo/kickerelo/views/Chart2vs2.java b/src/main/java/org/kickerelo/kickerelo/views/Chart2vs2.java
deleted file mode 100644
index 24e6e86..0000000
--- a/src/main/java/org/kickerelo/kickerelo/views/Chart2vs2.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.kickerelo.kickerelo.views;
-
-import java.util.List;
-
-import org.kickerelo.kickerelo.data.Spieler;
-import org.kickerelo.kickerelo.util.Spieler2vs2EloComparator;
-
-import com.github.appreciated.apexcharts.ApexChartsBuilder;
-import com.github.appreciated.apexcharts.config.Theme;
-import com.github.appreciated.apexcharts.config.builder.ChartBuilder;
-import com.github.appreciated.apexcharts.config.builder.XAxisBuilder;
-import com.github.appreciated.apexcharts.config.builder.YAxisBuilder;
-import com.github.appreciated.apexcharts.config.chart.Type;
-import com.github.appreciated.apexcharts.config.chart.builder.ZoomBuilder;
-import com.github.appreciated.apexcharts.config.chart.zoom.ZoomType;
-import com.github.appreciated.apexcharts.config.theme.Mode;
-import com.github.appreciated.apexcharts.config.theme.Monochrome;
-import com.github.appreciated.apexcharts.config.xaxis.Labels;
-import com.github.appreciated.apexcharts.helper.Series;
-import com.vaadin.flow.router.Route;
-
-@Route(value = "app/chart2vs2")
-public class Chart2vs2 extends ApexChartsBuilder {
- public Chart2vs2(List l) {
- Theme theme = new Theme();
- Monochrome monochrome = new Monochrome();
- monochrome.setEnabled(true);
- theme.setMode(Mode.DARK);
- theme.setMonochrome(monochrome);
- Labels labels = new Labels();
- labels.setRotate(270d);
- labels.setShow(true);
- labels.setRotateAlways(false);
-
- withChart(ChartBuilder.get().withType(Type.SCATTER)
- .withZoom(ZoomBuilder.get().withEnabled(true).withType(ZoomType.XY).build()).build())
- .withSeries(new Series<>("ELO",
- l.stream().sorted(new Spieler2vs2EloComparator()).map(Spieler::getElo2vs2).toArray()
- ))
- .withXaxis(XAxisBuilder.get().withCategories(l.stream().sorted(new Spieler2vs2EloComparator()).map(Spieler::getName).toList()).withLabels(labels).build())
- .withYaxis(YAxisBuilder.get().build())
- .withTheme(theme);
- }
-}
diff --git a/src/main/java/org/kickerelo/kickerelo/views/Enter1vs1View.java b/src/main/java/org/kickerelo/kickerelo/views/Enter1vs1View.java
index ca94328..dd5437d 100644
--- a/src/main/java/org/kickerelo/kickerelo/views/Enter1vs1View.java
+++ b/src/main/java/org/kickerelo/kickerelo/views/Enter1vs1View.java
@@ -1,5 +1,6 @@
package org.kickerelo.kickerelo.views;
+import org.kickerelo.kickerelo.data.Spieler;
import org.kickerelo.kickerelo.exception.DuplicatePlayerException;
import org.kickerelo.kickerelo.exception.InvalidDataException;
import org.kickerelo.kickerelo.exception.NoSuchPlayerException;
@@ -21,12 +22,12 @@ public class Enter1vs1View extends VerticalLayout {
public Enter1vs1View(KickerEloService eloService) {
H2 subheading = new H2("1 vs 1 Ergebnis");
- ComboBox winnerSelect = new ComboBox<>("Gewinner");
- winnerSelect.setItems(eloService.getSpielerNamen());
+ ComboBox winnerSelect = new ComboBox<>("Gewinner");
+ winnerSelect.setItems(eloService.getSpielerEntities());
winnerSelect.setPlaceholder("Spieler auswählen");
- ComboBox loserSelect = new ComboBox<>("Verlierer");
- loserSelect.setItems(eloService.getSpielerNamen());
+ ComboBox loserSelect = new ComboBox<>("Verlierer");
+ loserSelect.setItems(eloService.getSpielerEntities());
loserSelect.setPlaceholder("Spieler auswählen");
IntegerField loserGoals = new IntegerField("Tore des Verlierers");
diff --git a/src/main/java/org/kickerelo/kickerelo/views/Enter2vs2View.java b/src/main/java/org/kickerelo/kickerelo/views/Enter2vs2View.java
index 3f97e52..f6278df 100644
--- a/src/main/java/org/kickerelo/kickerelo/views/Enter2vs2View.java
+++ b/src/main/java/org/kickerelo/kickerelo/views/Enter2vs2View.java
@@ -1,5 +1,6 @@
package org.kickerelo.kickerelo.views;
+import org.kickerelo.kickerelo.data.Spieler;
import org.kickerelo.kickerelo.exception.DuplicatePlayerException;
import org.kickerelo.kickerelo.exception.InvalidDataException;
import org.kickerelo.kickerelo.exception.NoSuchPlayerException;
@@ -20,20 +21,20 @@ public class Enter2vs2View extends VerticalLayout {
public Enter2vs2View(KickerEloService eloService) {
H2 subheading = new H2("2 vs 2 Ergebnis");
- ComboBox winnerFrontSelect = new ComboBox<>("Gewinner vorne");
- winnerFrontSelect.setItems(eloService.getSpielerNamen());
+ ComboBox winnerFrontSelect = new ComboBox<>("Gewinner vorne");
+ winnerFrontSelect.setItems(eloService.getSpielerEntities());
winnerFrontSelect.setPlaceholder("Spieler auswählen");
- ComboBox winnerBackSelect = new ComboBox<>("Gewinner hinten");
- winnerBackSelect.setItems(eloService.getSpielerNamen());
+ ComboBox winnerBackSelect = new ComboBox<>("Gewinner hinten");
+ winnerBackSelect.setItems(eloService.getSpielerEntities());
winnerBackSelect.setPlaceholder("Spieler auswählen");
- ComboBox loserFrontSelect = new ComboBox<>("Verlierer vorne");
- loserFrontSelect.setItems(eloService.getSpielerNamen());
+ ComboBox loserFrontSelect = new ComboBox<>("Verlierer vorne");
+ loserFrontSelect.setItems(eloService.getSpielerEntities());
loserFrontSelect.setPlaceholder("Spieler auswählen");
- ComboBox loserBackSelect = new ComboBox<>("Verlierer hinten");
- loserBackSelect.setItems(eloService.getSpielerNamen());
+ ComboBox loserBackSelect = new ComboBox<>("Verlierer hinten");
+ loserBackSelect.setItems(eloService.getSpielerEntities());
loserBackSelect.setPlaceholder("Spieler auswählen");
IntegerField loserGoals = new IntegerField("Tore des Verlierers");
diff --git a/src/main/java/org/kickerelo/kickerelo/views/Graph1vs1View.java b/src/main/java/org/kickerelo/kickerelo/views/Graph1vs1View.java
index 9ed689e..aeb89a7 100644
--- a/src/main/java/org/kickerelo/kickerelo/views/Graph1vs1View.java
+++ b/src/main/java/org/kickerelo/kickerelo/views/Graph1vs1View.java
@@ -1,9 +1,11 @@
package org.kickerelo.kickerelo.views;
-import org.kickerelo.kickerelo.repository.SpielerRepository;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.kickerelo.kickerelo.repository.SpielerRepository;
+import org.kickerelo.kickerelo.util.comparator.Spieler1vs1EloComparator;
-import com.github.appreciated.apexcharts.ApexCharts;
-import com.vaadin.flow.component.Unit;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
@@ -11,14 +13,17 @@ import com.vaadin.flow.router.Route;
@Route("app/graph1vs1")
public class Graph1vs1View extends VerticalLayout {
- ApexCharts chart1vs1;
public Graph1vs1View(SpielerRepository repo) {
setSizeFull();
H2 subheading = new H2("1 vs 1 Elo");
- chart1vs1 = new Chart1vs1(repo.getSpielerWith1vs1Games()).build();
- chart1vs1.setWidth(100, Unit.PERCENTAGE);
- chart1vs1.setHeight(100, Unit.PERCENTAGE);
- add(subheading, chart1vs1);
+ List names = new ArrayList<>();
+ List elo = new ArrayList<>();
+
+ repo.getSpielerWith1vs1Games().stream().sorted(new Spieler1vs1EloComparator()).forEach((s) -> {names.add(s.getName()); elo.add(s.getElo1vs1());});
+
+ Chart chart = new Chart(names, elo);
+
+ add(subheading, chart);
}
}
diff --git a/src/main/java/org/kickerelo/kickerelo/views/Graph2vs2View.java b/src/main/java/org/kickerelo/kickerelo/views/Graph2vs2View.java
index 19d9f64..4932a7c 100644
--- a/src/main/java/org/kickerelo/kickerelo/views/Graph2vs2View.java
+++ b/src/main/java/org/kickerelo/kickerelo/views/Graph2vs2View.java
@@ -1,23 +1,29 @@
package org.kickerelo.kickerelo.views;
-import org.kickerelo.kickerelo.repository.SpielerRepository;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.kickerelo.kickerelo.repository.SpielerRepository;
+import org.kickerelo.kickerelo.util.comparator.Spieler2vs2EloComparator;
-import com.github.appreciated.apexcharts.ApexCharts;
-import com.vaadin.flow.component.Unit;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
@Route("app/graph2vs2")
public class Graph2vs2View extends VerticalLayout {
- ApexCharts chart2vs2;
+
public Graph2vs2View(SpielerRepository repo) {
setSizeFull();
H2 subheading = new H2("2 vs 2 Elo");
- chart2vs2 = new Chart2vs2(repo.getSpielerWith2vs2Games()).build();
- chart2vs2.setWidth(100, Unit.PERCENTAGE);
- chart2vs2.setHeight(100, Unit.PERCENTAGE);
- add(subheading, chart2vs2);
+ List names = new ArrayList<>();
+ List elo = new ArrayList<>();
+
+ repo.getSpielerWith2vs2Games().stream().sorted(new Spieler2vs2EloComparator()).forEach((s) -> {names.add(s.getName()); elo.add(s.getElo2vs2());});
+
+ Chart chart = new Chart(names, elo);
+
+ add(subheading, chart);
}
}
diff --git a/src/main/java/org/kickerelo/kickerelo/views/History1vs1View.java b/src/main/java/org/kickerelo/kickerelo/views/History1vs1View.java
index 6ccaf52..dfc0001 100644
--- a/src/main/java/org/kickerelo/kickerelo/views/History1vs1View.java
+++ b/src/main/java/org/kickerelo/kickerelo/views/History1vs1View.java
@@ -12,17 +12,22 @@ import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
-import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.provider.SortDirection;
+import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.data.renderer.LocalDateTimeRenderer;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.router.Route;
@Route("app/history1vs1")
-public class History1vs1View extends VerticalLayout {
+public class History1vs1View extends HistoryView {
+
+ private final Ergebnis1vs1Repository repo;
+
List res;
public History1vs1View(Ergebnis1vs1Repository repo) {
+ this.repo = repo;
+
setSizeFull();
H2 subheading = new H2("Spiele 1 vs 1");
res = repo.findAll();
@@ -50,8 +55,10 @@ public class History1vs1View extends VerticalLayout {
grid.removeColumnByKey("id");
Grid.Column winnerColumn = grid.getColumnByKey("gewinner");
winnerColumn.setHeader("Gewinner");
+ winnerColumn.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis, PlayerType1vs1.GEWINNER)));
Grid.Column loserColumn = grid.getColumnByKey("verlierer");
loserColumn.setHeader("Verlierer");
+ loserColumn.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis, PlayerType1vs1.VERLIERER)));
Grid.Column goals = grid.getColumnByKey("toreVerlierer");
goals.setHeader("Verlierertore");
Grid.Column timestamp = grid.getColumnByKey("timestamp");
diff --git a/src/main/java/org/kickerelo/kickerelo/views/History2vs2View.java b/src/main/java/org/kickerelo/kickerelo/views/History2vs2View.java
index aae20be..d6e2b3c 100644
--- a/src/main/java/org/kickerelo/kickerelo/views/History2vs2View.java
+++ b/src/main/java/org/kickerelo/kickerelo/views/History2vs2View.java
@@ -13,16 +13,21 @@ import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
-import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.provider.SortDirection;
+import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.data.renderer.LocalDateTimeRenderer;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.router.Route;
+
@Route("app/history2vs2")
-public class History2vs2View extends VerticalLayout {
+public class History2vs2View extends HistoryView {
+
+ private final Ergebnis2vs2Repository repo;
+
public History2vs2View(Ergebnis2vs2Repository repo) {
+ this.repo = repo;
setSizeFull();
H2 subheading = new H2("Spiele 2 vs 2");
List res = repo.findAll();
@@ -64,12 +69,16 @@ public class History2vs2View extends VerticalLayout {
grid.removeColumnByKey("id");
Grid.Column winnerFront = grid.getColumnByKey("gewinnerVorn");
winnerFront.setHeader("Gewinner vorne");
+ winnerFront.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis, PlayerType2vs2.GEWINNER_VORN)));
Grid.Column winnerBack = grid.getColumnByKey("gewinnerHinten");
winnerBack.setHeader("Gewinner hinten");
+ winnerBack.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis, PlayerType2vs2.GEWINNER_HINTEN)));
Grid.Column loserFront = grid.getColumnByKey("verliererVorn");
loserFront.setHeader("Verlierer vorne");
+ loserFront.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis, PlayerType2vs2.VERLIERER_VORN)));
Grid.Column loserBack = grid.getColumnByKey("verliererHinten");
loserBack.setHeader("Verlierer hinten");
+ loserBack.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis, PlayerType2vs2.VERLIERER_HINTEN)));
Grid.Column goals = grid.getColumnByKey("toreVerlierer");
goals.setHeader("Verlierertore");
Grid.Column timestamp = grid.getColumnByKey("timestamp");
diff --git a/src/main/java/org/kickerelo/kickerelo/views/HistoryView.java b/src/main/java/org/kickerelo/kickerelo/views/HistoryView.java
new file mode 100644
index 0000000..1d3826e
--- /dev/null
+++ b/src/main/java/org/kickerelo/kickerelo/views/HistoryView.java
@@ -0,0 +1,57 @@
+package org.kickerelo.kickerelo.views;
+
+import com.vaadin.flow.component.html.Div;
+import com.vaadin.flow.component.html.Span;
+import com.vaadin.flow.component.orderedlayout.VerticalLayout;
+import com.vaadin.flow.theme.lumo.LumoUtility;
+import org.kickerelo.kickerelo.data.Ergebnis1vs1;
+import org.kickerelo.kickerelo.data.Ergebnis2vs2;
+import org.kickerelo.kickerelo.data.Spieler;
+import org.kickerelo.kickerelo.service.EloChangeTracker;
+import org.kickerelo.kickerelo.util.EloChange1vs1;
+import org.kickerelo.kickerelo.util.EloChange2vs2;
+
+public class HistoryView extends VerticalLayout {
+
+ enum PlayerType1vs1 {
+ GEWINNER,
+ VERLIERER
+ }
+ enum PlayerType2vs2 {
+ GEWINNER_VORN,
+ GEWINNER_HINTEN,
+ VERLIERER_VORN,
+ VERLIERER_HINTEN
+ }
+
+ static Div formatEloChange(Ergebnis1vs1 ergebnis, PlayerType1vs1 type) {
+ EloChange1vs1 change = EloChangeTracker.get1vs1Result(ergebnis.getId());
+ return switch (type) {
+ case GEWINNER -> formatEloChange(ergebnis.getGewinner(), change.winnerEloChange());
+ case VERLIERER -> formatEloChange(ergebnis.getVerlierer(), change.loserEloChange());
+ };
+ }
+
+ static Div formatEloChange(Ergebnis2vs2 ergebnis, PlayerType2vs2 type) {
+ EloChange2vs2 change = EloChangeTracker.get2vs2Result(ergebnis.getId());
+ return switch (type) {
+ case GEWINNER_VORN -> formatEloChange(ergebnis.getGewinnerVorn(), change.winnerFrontEloChange());
+ case GEWINNER_HINTEN -> formatEloChange(ergebnis.getGewinnerHinten(), change.winnerBackEloChange());
+ case VERLIERER_VORN -> formatEloChange(ergebnis.getVerliererVorn(), change.loserFrontEloChange());
+ case VERLIERER_HINTEN -> formatEloChange(ergebnis.getVerliererHinten(), change.loserBackEloChange());
+ };
+ }
+
+ static Div formatEloChange(Spieler spieler, double change) {
+ Div div = new Div();
+
+ Span nameSpan = new Span(spieler.getName() + " ");
+ String formattedChange = String.format("%+.2f", change);
+ Span changeSpan = new Span(formattedChange);
+ changeSpan.addClassNames(LumoUtility.FontSize.SMALL, LumoUtility.TextColor.SECONDARY, LumoUtility.FontWeight.LIGHT);
+
+ div.add(nameSpan, changeSpan);
+
+ return div;
+ }
+}
diff --git a/src/main/java/org/kickerelo/kickerelo/views/Stat2vs2View.java b/src/main/java/org/kickerelo/kickerelo/views/Stat2vs2View.java
index 132881d..1eb05ae 100644
--- a/src/main/java/org/kickerelo/kickerelo/views/Stat2vs2View.java
+++ b/src/main/java/org/kickerelo/kickerelo/views/Stat2vs2View.java
@@ -1,6 +1,7 @@
package org.kickerelo.kickerelo.views;
import org.kickerelo.kickerelo.data.Spieler;
+import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository;
import org.kickerelo.kickerelo.service.KickerEloService;
import org.kickerelo.kickerelo.service.Stat2vs2Service;
import org.kickerelo.kickerelo.util.Position;
@@ -8,6 +9,7 @@ import org.kickerelo.kickerelo.util.Position;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.NativeLabel;
+import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.progressbar.ProgressBar;
import com.vaadin.flow.component.progressbar.ProgressBarVariant;
@@ -17,29 +19,43 @@ import com.vaadin.flow.router.Route;
public class Stat2vs2View extends VerticalLayout {
Stat2vs2Service stat2vs2Service;
KickerEloService kickerEloService;
+ Ergebnis2vs2Repository repo;
H2 subheading;
ComboBox selector;
+ Paragraph generalInfo = new Paragraph();
ProgressBar frontRate = new ProgressBar();
NativeLabel frontRateText = new NativeLabel();
ProgressBar winRateFront = new ProgressBar();
NativeLabel winRateFrontText = new NativeLabel();
ProgressBar winRateBack = new ProgressBar();
NativeLabel winRateBackText = new NativeLabel();
+ Paragraph goalDiffBack = new Paragraph();
+ Paragraph goalDiffFront = new Paragraph();
- public Stat2vs2View(Stat2vs2Service service, KickerEloService kickerService) {
+ public Stat2vs2View(Stat2vs2Service service, KickerEloService kickerService, Ergebnis2vs2Repository repo) {
this.stat2vs2Service = service;
this.kickerEloService = kickerService;
- subheading = new H2("2 vs 2 Ergebnis");
+ this.repo = repo;
+ subheading = new H2("2 vs 2 Spielerstatistik");
selector = new ComboBox<>("Spieler");
selector.setItems(kickerService.getSpielerEntities());
selector.addValueChangeListener(event -> updateData(selector.getValue()));
- add(subheading, selector, frontRateText, frontRate, winRateFrontText, winRateFront, winRateBackText, winRateBack);
+ add(subheading, selector, generalInfo, frontRateText, frontRate, winRateFrontText, winRateFront, winRateBackText, winRateBack, goalDiffBack, goalDiffFront);
}
private void updateData(Spieler s) {
+ updateGeneralInfo(s);
updateFrontRate(s);
updateFrontWinrate(s);
updateBackWinrate(s);
+ updateGoalDiffs(s);
+ }
+
+ private void updateGeneralInfo(Spieler s) {
+ int anzahl = repo.countByGewinnerVornOrGewinnerHintenOrVerliererVornOrVerliererHinten(s, s, s, s);
+ float elo = s.getElo2vs2();
+ String text = String.format("%.2f", elo) + " Elo bei " + anzahl + " Spielen";
+ generalInfo.setText(text);
}
private void updateFrontRate(Spieler s) {
@@ -66,4 +82,14 @@ public class Stat2vs2View extends VerticalLayout {
winRateBack.addThemeVariants((winRate > 0.5f ? ProgressBarVariant.LUMO_SUCCESS : ProgressBarVariant.LUMO_ERROR));
winRateBackText.setText(winRate.isNaN() ? text + "-" : text + String.format("%.2f", winRate * 100) + "%");
}
+
+ private void updateGoalDiffs(Spieler s) {
+ String text = "Mittlere Tordifferenz hinten: ";
+ Float backDiff = repo.avgGoalDiffBack(s);
+ goalDiffBack.setText(backDiff.isNaN() ? text + "-" : text + String.format("%.2f", backDiff));
+ text = "Mittlere Tordifferenz vorne: ";
+ Float frontDiff = repo.avgGoalDiffFront(s);
+ goalDiffFront.setText(frontDiff.isNaN() ? text + "-" : text + String.format("%.2f", frontDiff));
+
+ }
}
diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties
index deec540..9a9210e 100644
--- a/src/main/resources/application-prod.properties
+++ b/src/main/resources/application-prod.properties
@@ -18,3 +18,6 @@ spring.security.oauth2.client.registration.oidc.redirect-uri={baseUrl}/login/oau
spring.security.oauth2.client.provider.oidc.issuer-uri=${OIDC_ISSUER_URI}
vaadin.urlMapping=/app/*
+
+# In prod mode, never add the test data to the database
+spring.sql.init.mode=never
diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties
index 8898ffb..40805fd 100644
--- a/src/main/resources/application-test.properties
+++ b/src/main/resources/application-test.properties
@@ -3,7 +3,6 @@ logging.level.org.atmosphere = warn
logging.level.org.springframework.security=DEBUG
spring.mustache.check-template-location = false
-spring.datasource.url=jdbc:h2:file:./data
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql
new file mode 100644
index 0000000..4c2d6ec
--- /dev/null
+++ b/src/main/resources/data.sql
@@ -0,0 +1,231 @@
+INSERT INTO spieler (id, name, elo1vs1, elo2vs2, elo_alt) VALUES
+ (1, 'Alfons', 1500, 1500, 0),
+ (2, 'Bertha', 1500, 1500, 0),
+ (3, 'Claude', 1500, 1500, 0),
+ (4, 'Doris', 1500, 1500, 0),
+ (5, 'Emil', 1500, 1500, 0),
+ (6, 'Friederike', 1500, 1500, 0),
+ (7, 'Gisela', 1500, 1500, 0),
+ (8, 'Heinrich', 1500, 1500, 0),
+ (9, 'Ingrid', 1500, 1500, 0),
+ (10, 'Johann', 1500, 1500, 0),
+ (11, 'Käthe', 1500, 1500, 0),
+ (12, 'Lorenz', 1500, 1500, 0),
+ (13, 'Marie', 1500, 1500, 0),
+ (14, 'Noah', 1500, 1500, 0),
+ (15, 'Odile', 1500, 1500, 0),
+ (16, 'Paula', 1500, 1500, 0),
+ (17, 'Quirin', 1500, 1500, 0),
+ (18, 'Roland', 1500, 1500, 0),
+ (19, 'Sophie', 1500, 1500, 0),
+ (20, 'Torsten', 1500, 1500, 0),
+ (21, 'Ulrich', 1500, 1500, 0),
+ (22, 'Veronika', 1500, 1500, 0),
+ (23, 'Werner', 1500, 1500, 0),
+ (24, 'Xaver', 1500, 1500, 0),
+ (25, 'Yseult', 1500, 1500, 0),
+ (26, 'Zacharias', 1500, 1500, 0);
+
+INSERT INTO ergebnis1vs1 (id, gewinner, verlierer, tore_verlierer, zeitpunkt) VALUES
+ (1, 5, 12, 2, '2024-11-01 10:00:00'),
+ (2, 18, 7, 1, '2024-11-02 11:30:00'),
+ (3, 3, 25, 0, '2024-11-03 13:45:00'),
+ (4, 22, 1, 3, '2024-11-04 15:00:00'),
+ (5, 10, 15, 2, '2024-11-05 16:15:00'),
+ (6, 7, 20, 4, '2024-11-06 17:30:00'),
+ (7, 2, 14, 1, '2024-11-07 10:45:00'),
+ (8, 11, 23, 0, '2024-11-08 12:00:00'),
+ (9, 26, 9, 5, '2024-11-09 14:15:00'),
+ (10, 16, 4, 3, '2024-11-10 16:30:00'),
+ (11, 13, 21, 2, '2024-11-11 10:00:00'),
+ (12, 8, 19, 1, '2024-11-12 11:30:00'),
+ (13, 1, 6, 0, '2024-11-13 13:45:00'),
+ (14, 24, 17, 3, '2024-11-14 15:00:00'),
+ (15, 20, 5, 2, '2024-11-15 16:15:00'),
+ (16, 9, 2, 4, '2024-11-16 17:30:00'),
+ (17, 14, 10, 1, '2024-11-17 10:45:00'),
+ (18, 23, 18, 0, '2024-11-18 12:00:00'),
+ (19, 4, 11, 5, '2024-11-19 14:15:00'),
+ (20, 21, 3, 3, '2024-11-20 16:30:00'),
+ (21, 19, 26, 2, '2024-11-21 10:00:00'),
+ (22, 6, 16, 1, '2024-11-22 11:30:00'),
+ (23, 17, 13, 0, '2024-11-23 13:45:00'),
+ (24, 5, 24, 3, '2024-11-24 15:00:00'),
+ (25, 12, 7, 2, '2024-11-25 16:15:00'),
+ (26, 25, 22, 4, '2024-11-26 17:30:00'),
+ (27, 15, 1, 1, '2024-11-27 10:45:00'),
+ (28, 2, 10, 0, '2024-11-28 12:00:00'),
+ (29, 23, 14, 5, '2024-11-29 14:15:00'),
+ (30, 11, 20, 3, '2024-11-30 16:30:00'),
+ (31, 18, 9, 2, '2024-12-01 10:00:00'),
+ (32, 26, 13, 1, '2024-12-02 11:30:00'),
+ (33, 4, 19, 0, '2024-12-03 13:45:00'),
+ (34, 21, 6, 3, '2024-12-04 15:00:00'),
+ (35, 16, 17, 2, '2024-12-05 16:15:00'),
+ (36, 7, 24, 4, '2024-12-06 17:30:00'),
+ (37, 1, 12, 1, '2024-12-07 10:45:00'),
+ (38, 10, 25, 0, '2024-12-08 12:00:00'),
+ (39, 14, 3, 5, '2024-12-09 14:15:00'),
+ (40, 20, 2, 3, '2024-12-10 16:30:00'),
+ (41, 9, 23, 2, '2024-12-11 10:00:00'),
+ (42, 13, 11, 1, '2024-12-12 11:30:00'),
+ (43, 22, 18, 0, '2024-12-13 13:45:00'),
+ (44, 24, 15, 3, '2024-12-14 15:00:00'),
+ (45, 5, 16, 2, '2024-12-15 16:15:00'),
+ (46, 17, 26, 4, '2024-12-16 17:30:00'),
+ (47, 3, 19, 1, '2024-12-17 10:45:00'),
+ (48, 6, 4, 0, '2024-12-18 12:00:00'),
+ (49, 11, 21, 5, '2024-12-19 14:15:00'),
+ (50, 25, 7, 3, '2024-12-20 16:30:00'),
+ (51, 12, 1, 2, '2024-12-21 10:00:00'),
+ (52, 15, 18, 1, '2024-12-22 11:30:00'),
+ (53, 2, 22, 0, '2024-12-23 13:45:00'),
+ (54, 10, 20, 3, '2024-12-24 15:00:00'),
+ (55, 14, 9, 2, '2024-12-25 16:15:00'),
+ (56, 23, 26, 4, '2024-12-26 17:30:00'),
+ (57, 19, 16, 1, '2024-12-27 10:45:00'),
+ (58, 4, 13, 0, '2024-12-28 12:00:00'),
+ (59, 21, 17, 5, '2024-12-29 14:15:00'),
+ (60, 6, 5, 3, '2024-12-30 16:30:00'),
+ (61, 20, 12, 2, '2025-01-01 10:00:00'),
+ (62, 7, 10, 1, '2025-01-02 11:30:00'),
+ (63, 1, 2, 0, '2025-01-03 13:45:00'),
+ (64, 25, 14, 3, '2025-01-04 15:00:00'),
+ (65, 18, 11, 2, '2025-01-05 16:15:00'),
+ (66, 22, 23, 4, '2025-01-06 17:30:00'),
+ (67, 9, 4, 1, '2025-01-07 10:45:00'),
+ (68, 16, 19, 0, '2025-01-08 12:00:00'),
+ (69, 13, 21, 5, '2025-01-09 14:15:00'),
+ (70, 26, 3, 3, '2025-01-10 16:30:00'),
+ (71, 5, 17, 2, '2025-01-11 10:00:00'),
+ (72, 12, 24, 1, '2025-01-12 11:30:00'),
+ (73, 15, 6, 0, '2025-01-13 13:45:00'),
+ (74, 2, 20, 3, '2025-01-14 15:00:00'),
+ (75, 10, 1, 2, '2025-01-15 16:15:00'),
+ (76, 14, 7, 4, '2025-01-16 17:30:00'),
+ (77, 23, 18, 1, '2025-01-17 10:45:00'),
+ (78, 11, 9, 0, '2025-01-18 12:00:00'),
+ (79, 21, 22, 5, '2025-01-19 14:15:00'),
+ (80, 4, 25, 3, '2025-01-20 16:30:00'),
+ (81, 19, 13, 2, '2025-02-01 10:00:00'),
+ (82, 6, 16, 1, '2025-02-02 11:30:00'),
+ (83, 17, 26, 0, '2025-02-03 13:45:00'),
+ (84, 1, 5, 3, '2025-02-04 15:00:00'),
+ (85, 24, 12, 2, '2025-02-05 16:15:00'),
+ (86, 7, 15, 4, '2025-02-06 17:30:00'),
+ (87, 2, 10, 1, '2025-02-07 10:45:00'),
+ (88, 20, 14, 0, '2025-02-08 12:00:00'),
+ (89, 9, 23, 5, '2025-02-09 14:15:00'),
+ (90, 18, 11, 3, '2025-02-10 16:30:00'),
+ (91, 3, 21, 2, '2025-03-01 10:00:00'),
+ (92, 25, 19, 1, '2025-03-02 11:30:00'),
+ (93, 16, 4, 0, '2025-03-03 13:45:00'),
+ (94, 22, 6, 3, '2025-03-04 15:00:00'),
+ (95, 13, 17, 2, '2025-03-05 16:15:00'),
+ (96, 26, 1, 4, '2025-03-06 17:30:00'),
+ (97, 5, 2, 1, '2025-03-07 10:45:00'),
+ (98, 10, 24, 0, '2025-03-08 12:00:00'),
+ (99, 14, 12, 5, '2025-03-09 14:15:00'),
+ (100, 23, 7, 3, '2025-03-10 16:30:00');
+
+INSERT INTO ergebnis2vs2 (id, gewinner_vorn, gewinner_hinten, verlierer_vorn, verlierer_hinten, tore_verlierer, zeitpunkt) VALUES
+ (1, 5, 12, 1, 18, 2, '2024-11-01 10:00:00'),
+ (2, 7, 20, 3, 25, 1, '2024-11-02 11:30:00'),
+ (3, 22, 1, 10, 15, 0, '2024-11-03 13:45:00'),
+ (4, 11, 23, 2, 14, 3, '2024-11-04 15:00:00'),
+ (5, 26, 9, 16, 4, 2, '2024-11-05 16:15:00'),
+ (6, 13, 21, 8, 19, 4, '2024-11-06 17:30:00'),
+ (7, 1, 6, 24, 17, 1, '2024-11-07 10:45:00'),
+ (8, 20, 5, 9, 2, 0, '2024-11-08 12:00:00'),
+ (9, 14, 10, 23, 18, 5, '2024-11-09 14:15:00'),
+ (10, 4, 11, 21, 3, 3, '2024-11-10 16:30:00'),
+ (11, 19, 26, 6, 16, 2, '2024-11-11 10:00:00'),
+ (12, 17, 13, 5, 24, 1, '2024-11-12 11:30:00'),
+ (13, 12, 7, 25, 22, 0, '2024-11-13 13:45:00'),
+ (14, 15, 1, 2, 10, 3, '2024-11-14 15:00:00'),
+ (15, 23, 14, 11, 20, 2, '2024-11-15 16:15:00'),
+ (16, 18, 9, 26, 13, 4, '2024-11-16 17:30:00'),
+ (17, 4, 19, 21, 6, 1, '2024-11-17 10:45:00'),
+ (18, 16, 17, 7, 24, 0, '2024-11-18 12:00:00'),
+ (19, 1, 12, 10, 25, 5, '2024-11-19 14:15:00'),
+ (20, 14, 3, 20, 2, 3, '2024-11-20 16:30:00'),
+ (21, 9, 23, 13, 11, 2, '2024-11-21 10:00:00'),
+ (22, 22, 18, 24, 15, 1, '2024-11-22 11:30:00'),
+ (23, 5, 16, 17, 26, 0, '2024-11-23 13:45:00'),
+ (24, 3, 19, 6, 4, 3, '2024-11-24 15:00:00'),
+ (25, 11, 21, 25, 7, 2, '2024-11-25 16:15:00'),
+ (26, 12, 1, 15, 18, 4, '2024-11-26 17:30:00'),
+ (27, 2, 22, 10, 20, 1, '2024-11-27 10:45:00'),
+ (28, 14, 9, 23, 26, 0, '2024-11-28 12:00:00'),
+ (29, 19, 16, 4, 13, 5, '2024-11-29 14:15:00'),
+ (30, 21, 17, 6, 5, 3, '2024-11-30 16:30:00'),
+ (31, 20, 12, 7, 10, 2, '2024-12-01 10:00:00'),
+ (32, 1, 2, 25, 14, 1, '2024-12-02 11:30:00'),
+ (33, 18, 11, 22, 23, 0, '2024-12-03 13:45:00'),
+ (34, 9, 4, 16, 19, 3, '2024-12-04 15:00:00'),
+ (35, 13, 21, 26, 3, 2, '2024-12-05 16:15:00'),
+ (36, 5, 17, 12, 24, 4, '2024-12-06 17:30:00'),
+ (37, 15, 6, 2, 20, 1, '2024-12-07 10:45:00'),
+ (38, 10, 1, 14, 7, 0, '2024-12-08 12:00:00'),
+ (39, 23, 18, 11, 9, 5, '2024-12-09 14:15:00'),
+ (40, 21, 22, 4, 25, 3, '2024-12-10 16:30:00'),
+ (41, 19, 13, 6, 16, 2, '2024-12-11 10:00:00'),
+ (42, 17, 26, 1, 5, 1, '2024-12-12 11:30:00'),
+ (43, 24, 12, 7, 15, 0, '2024-12-13 13:45:00'),
+ (44, 2, 10, 20, 14, 3, '2024-12-14 15:00:00'),
+ (45, 9, 23, 18, 11, 2, '2024-12-15 16:15:00'),
+ (46, 3, 21, 25, 19, 4, '2024-12-16 17:30:00'),
+ (47, 16, 4, 22, 6, 1, '2024-12-17 10:45:00'),
+ (48, 13, 17, 26, 1, 0, '2024-12-18 12:00:00'),
+ (49, 5, 2, 10, 24, 5, '2024-12-19 14:15:00'),
+ (50, 14, 12, 23, 7, 3, '2024-12-20 16:30:00'),
+ (51, 18, 25, 15, 3, 2, '2024-12-21 10:00:00'),
+ (52, 22, 1, 7, 11, 1, '2024-12-22 11:30:00'),
+ (53, 20, 9, 13, 24, 0, '2024-12-23 13:45:00'),
+ (54, 4, 16, 2, 21, 3, '2024-12-24 15:00:00'),
+ (55, 6, 19, 17, 10, 2, '2024-12-25 16:15:00'),
+ (56, 26, 5, 1, 14, 4, '2024-12-26 17:30:00'),
+ (57, 12, 23, 11, 18, 1, '2024-12-27 10:45:00'),
+ (58, 2, 25, 20, 3, 0, '2024-12-28 12:00:00'),
+ (59, 15, 22, 7, 13, 5, '2024-12-29 14:15:00'),
+ (60, 24, 9, 16, 21, 3, '2024-12-30 16:30:00'),
+ (61, 10, 17, 4, 6, 2, '2025-01-01 10:00:00'),
+ (62, 1, 26, 19, 5, 1, '2025-01-02 11:30:00'),
+ (63, 11, 12, 14, 2, 0, '2025-01-03 13:45:00'),
+ (64, 18, 20, 23, 25, 3, '2025-01-04 15:00:00'),
+ (65, 3, 7, 21, 16, 2, '2025-01-05 16:15:00'),
+ (66, 22, 13, 1, 24, 4, '2025-01-06 17:30:00'),
+ (67, 5, 9, 17, 18, 1, '2025-01-07 10:45:00'),
+ (68, 10, 15, 2, 26, 0, '2025-01-08 12:00:00'),
+ (69, 14, 11, 20, 4, 5, '2025-01-09 14:15:00'),
+ (70, 23, 19, 12, 21, 3, '2025-01-10 16:30:00'),
+ (71, 6, 25, 3, 1, 2, '2025-01-11 10:00:00'),
+ (72, 16, 7, 22, 10, 1, '2025-01-12 11:30:00'),
+ (73, 17, 13, 14, 15, 0, '2025-01-13 13:45:00'),
+ (74, 18, 24, 5, 2, 3, '2025-01-14 15:00:00'),
+ (75, 11, 20, 23, 26, 2, '2025-01-15 16:15:00'),
+ (76, 9, 21, 4, 19, 4, '2025-01-16 17:30:00'),
+ (77, 12, 1, 6, 17, 1, '2025-01-17 10:45:00'),
+ (78, 25, 10, 3, 22, 0, '2025-01-18 12:00:00'),
+ (79, 7, 13, 15, 14, 5, '2025-01-19 14:15:00'),
+ (80, 2, 18, 24, 20, 3, '2025-01-20 16:30:00'),
+ (81, 16, 11, 5, 23, 2, '2025-02-01 10:00:00'),
+ (82, 1, 4, 9, 26, 1, '2025-02-02 11:30:00'),
+ (83, 19, 21, 12, 17, 0, '2025-02-03 13:45:00'),
+ (84, 6, 22, 13, 2, 3, '2025-02-04 15:00:00'),
+ (85, 20, 7, 10, 14, 2, '2025-02-05 16:15:00'),
+ (86, 25, 15, 1, 18, 4, '2025-02-06 17:30:00'),
+ (87, 23, 3, 24, 11, 1, '2025-02-07 10:45:00'),
+ (88, 5, 26, 16, 9, 0, '2025-02-08 12:00:00'),
+ (89, 12, 4, 17, 21, 5, '2025-02-09 14:15:00'),
+ (90, 13, 6, 2, 19, 3, '2025-02-10 16:30:00'),
+ (91, 10, 22, 18, 7, 2, '2025-03-01 10:00:00'),
+ (92, 14, 25, 11, 1, 1, '2025-03-02 11:30:00'),
+ (93, 20, 23, 3, 16, 0, '2025-03-03 13:45:00'),
+ (94, 9, 17, 26, 13, 3, '2025-03-04 15:00:00'),
+ (95, 21, 5, 24, 12, 2, '2025-03-05 16:15:00'),
+ (96, 4, 15, 2, 10, 4, '2025-03-06 17:30:00'),
+ (97, 6, 1, 18, 14, 1, '2025-03-07 10:45:00'),
+ (98, 19, 23, 7, 25, 0, '2025-03-08 12:00:00'),
+ (99, 11, 26, 22, 3, 5, '2025-03-09 14:15:00'),
+ (100, 16, 12, 5, 17, 3, '2025-03-10 16:30:00');
\ No newline at end of file
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
new file mode 100644
index 0000000..c056b5d
--- /dev/null
+++ b/src/main/resources/schema.sql
@@ -0,0 +1,58 @@
+CREATE SEQUENCE ergebnis1vs1_seq INCREMENT BY 50 START WITH 1;
+
+CREATE SEQUENCE ergebnis2vs2_seq INCREMENT BY 50 START WITH 1;
+
+CREATE SEQUENCE spieler_seq INCREMENT BY 50 START WITH 1;
+
+CREATE TABLE ergebnis1vs1
+(
+ id BIGINT NOT NULL,
+ gewinner INT NOT NULL,
+ verlierer INT NOT NULL,
+ tore_verlierer SMALLINT NOT NULL,
+ zeitpunkt datetime NULL,
+ CONSTRAINT pk_ergebnis1vs1 PRIMARY KEY (id)
+);
+
+CREATE TABLE ergebnis2vs2
+(
+ id BIGINT NOT NULL,
+ gewinner_vorn INT NOT NULL,
+ gewinner_hinten INT NOT NULL,
+ verlierer_vorn INT NOT NULL,
+ verlierer_hinten INT NOT NULL,
+ tore_verlierer SMALLINT NOT NULL,
+ zeitpunkt datetime NOT NULL,
+ CONSTRAINT pk_ergebnis2vs2 PRIMARY KEY (id)
+);
+
+CREATE TABLE spieler
+(
+ id INT NOT NULL,
+ name VARCHAR(255) NOT NULL,
+ elo1vs1 FLOAT NOT NULL,
+ elo2vs2 FLOAT NOT NULL,
+ elo_alt FLOAT NULL,
+ CONSTRAINT pk_spieler PRIMARY KEY (id)
+);
+
+ALTER TABLE spieler
+ ADD CONSTRAINT uc_spieler_name UNIQUE (name);
+
+ALTER TABLE ergebnis1vs1
+ ADD CONSTRAINT FK_ERGEBNIS1VS1_ON_GEWINNER FOREIGN KEY (gewinner) REFERENCES spieler (id);
+
+ALTER TABLE ergebnis1vs1
+ ADD CONSTRAINT FK_ERGEBNIS1VS1_ON_VERLIERER FOREIGN KEY (verlierer) REFERENCES spieler (id);
+
+ALTER TABLE ergebnis2vs2
+ ADD CONSTRAINT FK_ERGEBNIS2VS2_ON_GEWINNER_HINTEN FOREIGN KEY (gewinner_hinten) REFERENCES spieler (id);
+
+ALTER TABLE ergebnis2vs2
+ ADD CONSTRAINT FK_ERGEBNIS2VS2_ON_GEWINNER_VORN FOREIGN KEY (gewinner_vorn) REFERENCES spieler (id);
+
+ALTER TABLE ergebnis2vs2
+ ADD CONSTRAINT FK_ERGEBNIS2VS2_ON_VERLIERER_HINTEN FOREIGN KEY (verlierer_hinten) REFERENCES spieler (id);
+
+ALTER TABLE ergebnis2vs2
+ ADD CONSTRAINT FK_ERGEBNIS2VS2_ON_VERLIERER_VORN FOREIGN KEY (verlierer_vorn) REFERENCES spieler (id);
\ No newline at end of file