From 40e0eed830fef8c1ef1708514cb34f5e70e8d702 Mon Sep 17 00:00:00 2001 From: TheCheetahh <78621162+TheCheetahh@users.noreply.github.com> Date: Wed, 14 May 2025 12:00:30 +0200 Subject: [PATCH 01/17] Fixed wrong numFront calculation to countByGewinnerVornOrVerliererVorn --- .../kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java | 2 ++ .../java/org/kickerelo/kickerelo/service/Stat2vs2Service.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java b/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java index e3163dc..23b75e2 100644 --- a/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java +++ b/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java @@ -15,4 +15,6 @@ public interface Ergebnis2vs2Repository extends JpaRepository Date: Wed, 14 May 2025 13:38:17 +0200 Subject: [PATCH 02/17] Delete unused repo function --- .../kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java b/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java index 23b75e2..2d5bee8 100644 --- a/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java +++ b/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java @@ -12,7 +12,6 @@ public interface Ergebnis2vs2Repository extends JpaRepository Date: Wed, 14 May 2025 14:15:49 +0200 Subject: [PATCH 03/17] Switch to chart.js --- pom.xml | 7 +-- .../org/kickerelo/kickerelo/views/Chart.java | 45 +++++++++++++++++ .../kickerelo/kickerelo/views/Chart1vs1.java | 50 ------------------- .../kickerelo/kickerelo/views/Chart2vs2.java | 41 --------------- .../kickerelo/views/Graph1vs1View.java | 20 +++++--- .../kickerelo/views/Graph2vs2View.java | 21 +++++--- 6 files changed, 73 insertions(+), 111 deletions(-) create mode 100644 src/main/java/org/kickerelo/kickerelo/views/Chart.java delete mode 100644 src/main/java/org/kickerelo/kickerelo/views/Chart1vs1.java delete mode 100644 src/main/java/org/kickerelo/kickerelo/views/Chart2vs2.java diff --git a/pom.xml b/pom.xml index ef2bdd1..62b52d6 100644 --- a/pom.xml +++ b/pom.xml @@ -42,11 +42,6 @@ com.vaadin vaadin-spring-boot-starter - - com.github.appreciated - apexcharts - 24.0.2 - org.mariadb.jdbc @@ -143,4 +138,4 @@ - \ No newline at end of file + 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..38bb729 --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/views/Chart.java @@ -0,0 +1,45 @@ +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;"; + + // 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 48e7df3..0000000 --- a/src/main/java/org/kickerelo/kickerelo/views/Chart1vs1.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.kickerelo.kickerelo.views; - -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.config.xaxis.labels.Style; -import com.github.appreciated.apexcharts.config.yaxis.Title; -import com.github.appreciated.apexcharts.helper.Series; -import com.vaadin.flow.component.UI; -import com.vaadin.flow.component.button.Button; -import com.vaadin.flow.server.VaadinService; -import com.vaadin.flow.theme.lumo.Lumo; -import org.kickerelo.kickerelo.data.Spieler; -import org.kickerelo.kickerelo.util.Spieler1vs1EloComparator; - -import java.math.BigDecimal; -import java.util.List; - -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 696e0cd..0000000 --- a/src/main/java/org/kickerelo/kickerelo/views/Chart2vs2.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.kickerelo.kickerelo.views; - -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 org.kickerelo.kickerelo.data.Spieler; -import org.kickerelo.kickerelo.util.Spieler2vs2EloComparator; - -import java.util.List; - -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/Graph1vs1View.java b/src/main/java/org/kickerelo/kickerelo/views/Graph1vs1View.java index 6d86fc6..1c7d6b1 100644 --- a/src/main/java/org/kickerelo/kickerelo/views/Graph1vs1View.java +++ b/src/main/java/org/kickerelo/kickerelo/views/Graph1vs1View.java @@ -1,23 +1,29 @@ package org.kickerelo.kickerelo.views; -import com.github.appreciated.apexcharts.ApexCharts; -import com.vaadin.flow.component.Unit; +import java.util.ArrayList; +import java.util.List; + import com.vaadin.flow.component.html.H2; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.Route; + import org.kickerelo.kickerelo.repository.SpielerRepository; +import org.kickerelo.kickerelo.util.Spieler1vs1EloComparator; @Route("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 26ad677..62a23be 100644 --- a/src/main/java/org/kickerelo/kickerelo/views/Graph2vs2View.java +++ b/src/main/java/org/kickerelo/kickerelo/views/Graph2vs2View.java @@ -1,22 +1,29 @@ package org.kickerelo.kickerelo.views; -import com.github.appreciated.apexcharts.ApexCharts; -import com.vaadin.flow.component.Unit; +import java.util.ArrayList; +import java.util.List; + import com.vaadin.flow.component.html.H2; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.Route; + import org.kickerelo.kickerelo.repository.SpielerRepository; +import org.kickerelo.kickerelo.util.Spieler2vs2EloComparator; @Route("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); } } From 3be4f284656465343cdecc89462c89e8e6399906 Mon Sep 17 00:00:00 2001 From: lmarz Date: Wed, 14 May 2025 15:13:18 +0200 Subject: [PATCH 04/17] Tell dependabot to use the right branch (#46) --- .github/dependabot.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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" + From a4e9823efd9143ec8c2f1ab7ddbed5f6d91999cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 13:14:06 +0000 Subject: [PATCH 05/17] Bump org.springframework.boot:spring-boot-starter-parent Bumps [org.springframework.boot:spring-boot-starter-parent](https://github.com/spring-projects/spring-boot) from 3.4.4 to 3.4.5. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.4...v3.4.5) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-starter-parent dependency-version: 3.4.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 62b52d6..a625cca 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 3.4.4 + 3.4.5 From 57f869cd4b8b201aaa5a0b836c766fbb4c7d0b36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 13:14:19 +0000 Subject: [PATCH 06/17] Bump vaadin.version from 24.7.1 to 24.7.4 Bumps `vaadin.version` from 24.7.1 to 24.7.4. Updates `com.vaadin:vaadin-bom` from 24.7.1 to 24.7.4 Updates `com.vaadin:vaadin-maven-plugin` from 24.7.1 to 24.7.4 - [Release notes](https://github.com/vaadin/platform/releases) - [Commits](https://github.com/vaadin/platform/compare/24.7.1...24.7.4) --- updated-dependencies: - dependency-name: com.vaadin:vaadin-bom dependency-version: 24.7.4 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.vaadin:vaadin-maven-plugin dependency-version: 24.7.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a625cca..feeac06 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 23 23 UTF-8 - 24.7.1 + 24.7.4 test From eb36a253734919bb0e0d771a94b5b6e736cc288a Mon Sep 17 00:00:00 2001 From: Leon Marz Date: Wed, 21 May 2025 12:24:10 +0200 Subject: [PATCH 07/17] Chart: Always show all labels --- src/main/java/org/kickerelo/kickerelo/views/Chart.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/kickerelo/kickerelo/views/Chart.java b/src/main/java/org/kickerelo/kickerelo/views/Chart.java index 38bb729..a963ff6 100644 --- a/src/main/java/org/kickerelo/kickerelo/views/Chart.java +++ b/src/main/java/org/kickerelo/kickerelo/views/Chart.java @@ -30,6 +30,10 @@ public class Chart extends Component { // 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}}, "; From 4fa309da7570ac7caa5c351e4c3a989c3d2dd872 Mon Sep 17 00:00:00 2001 From: Anton Micke Date: Wed, 21 May 2025 23:39:17 +0200 Subject: [PATCH 08/17] Use in-memory database for testing, add test data on startup when in test mode. --- .../resources/application-prod.properties | 5 +- .../resources/application-test.properties | 1 - src/main/resources/data.sql | 231 ++++++++++++++++++ src/main/resources/schema.sql | 58 +++++ 4 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/data.sql create mode 100644 src/main/resources/schema.sql diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index 292a868..bf204a5 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -8,4 +8,7 @@ spring.datasource.password=${DATABASE_PASSWORD} spring.datasource.driver-class-name=org.mariadb.jdbc.Driver spring.jpa.hibernate.ddl-auto=validate spring.jpa.show-sql=false -spring.jpa.open-in-view=false \ No newline at end of file +spring.jpa.open-in-view=false + +# In prod mode, never add the test data to the database +spring.sql.init.mode=never \ No newline at end of file diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index 9306521..535b5ba 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -2,7 +2,6 @@ server.port=${PORT:8080} logging.level.org.atmosphere = warn 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 From 6a9d231008f56e39538d362e4d23d397417f5ec0 Mon Sep 17 00:00:00 2001 From: AJMicke <7047945+AJMicke@users.noreply.github.com> Date: Fri, 23 May 2025 16:17:47 +0200 Subject: [PATCH 09/17] Specify command to run in test mode in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a062262..ab7c5bf 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,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 ``` From c0402c92ee944fba2fb08eedca31a6fea9322b76 Mon Sep 17 00:00:00 2001 From: Anton Micke Date: Fri, 23 May 2025 16:52:36 +0200 Subject: [PATCH 10/17] Add obvious infos to 2vs2 stats --- .../kickerelo/views/Stat2vs2View.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kickerelo/kickerelo/views/Stat2vs2View.java b/src/main/java/org/kickerelo/kickerelo/views/Stat2vs2View.java index 7bfa90e..2fa4aa5 100644 --- a/src/main/java/org/kickerelo/kickerelo/views/Stat2vs2View.java +++ b/src/main/java/org/kickerelo/kickerelo/views/Stat2vs2View.java @@ -3,11 +3,13 @@ package org.kickerelo.kickerelo.views; 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; import com.vaadin.flow.router.Route; 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; @@ -16,8 +18,10 @@ import org.kickerelo.kickerelo.util.Position; 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(); @@ -25,22 +29,31 @@ public class Stat2vs2View extends VerticalLayout { ProgressBar winRateBack = new ProgressBar(); NativeLabel winRateBackText = new NativeLabel(); - 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); } private void updateData(Spieler s) { + updateGeneralInfo(s); updateFrontRate(s); updateFrontWinrate(s); updateBackWinrate(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) { String text = "Anteil Spiele vorne: "; Float rateFrontGames = stat2vs2Service.getFrontRate(s); From 7485fed2c20d3f3ace5e7c358fa57ee7f2686b7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 May 2025 06:54:30 +0000 Subject: [PATCH 11/17] Bump org.springframework.boot:spring-boot-starter-parent Bumps [org.springframework.boot:spring-boot-starter-parent](https://github.com/spring-projects/spring-boot) from 3.4.5 to 3.5.0. - [Release notes](https://github.com/spring-projects/spring-boot/releases) - [Commits](https://github.com/spring-projects/spring-boot/compare/v3.4.5...v3.5.0) --- updated-dependencies: - dependency-name: org.springframework.boot:spring-boot-starter-parent dependency-version: 3.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index feeac06..9f3a9d3 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 3.4.5 + 3.5.0 From 8e899b230ea6e540943990121cad28c23dc1f556 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 May 2025 06:54:21 +0000 Subject: [PATCH 12/17] Bump vaadin.version from 24.7.4 to 24.7.5 Bumps `vaadin.version` from 24.7.4 to 24.7.5. Updates `com.vaadin:vaadin-bom` from 24.7.4 to 24.7.5 Updates `com.vaadin:vaadin-maven-plugin` from 24.7.4 to 24.7.5 - [Release notes](https://github.com/vaadin/platform/releases) - [Commits](https://github.com/vaadin/platform/compare/24.7.4...24.7.5) --- updated-dependencies: - dependency-name: com.vaadin:vaadin-bom dependency-version: 24.7.5 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.vaadin:vaadin-maven-plugin dependency-version: 24.7.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9f3a9d3..f43e6b9 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 23 23 UTF-8 - 24.7.4 + 24.7.5 test From ad512a3abb3da06c7f6a9dbfd3dda530632be9b3 Mon Sep 17 00:00:00 2001 From: Anton Micke Date: Fri, 30 May 2025 15:10:27 +0200 Subject: [PATCH 13/17] Add average goal diffs to 2vs2 stats --- .../repository/Ergebnis2vs2Repository.java | 8 ++++++++ .../kickerelo/kickerelo/views/Stat2vs2View.java | 15 ++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java b/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java index 2d5bee8..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 @@ -16,4 +18,10 @@ public interface Ergebnis2vs2Repository extends JpaRepository("Spieler"); selector.setItems(kickerService.getSpielerEntities()); selector.addValueChangeListener(event -> updateData(selector.getValue())); - add(subheading, selector, generalInfo, frontRateText, frontRate, winRateFrontText, winRateFront, winRateBackText, winRateBack); + add(subheading, selector, generalInfo, frontRateText, frontRate, winRateFrontText, winRateFront, winRateBackText, winRateBack, goalDiffBack, goalDiffFront); } private void updateData(Spieler s) { @@ -45,6 +47,7 @@ public class Stat2vs2View extends VerticalLayout { updateFrontRate(s); updateFrontWinrate(s); updateBackWinrate(s); + updateGoalDiffs(s); } private void updateGeneralInfo(Spieler s) { @@ -78,4 +81,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)); + + } } From 4760fa590db14848bacf3b5155905cef62aeb8e6 Mon Sep 17 00:00:00 2001 From: Anton Micke Date: Fri, 30 May 2025 15:21:07 +0200 Subject: [PATCH 14/17] Correctly sort player selector in 2vs2 stats --- .../kickerelo/service/KickerEloService.java | 4 ++-- .../kickerelo/util/SpielerNameComparator.java | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/kickerelo/kickerelo/util/SpielerNameComparator.java diff --git a/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java b/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java index b6308e7..75658e2 100644 --- a/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java +++ b/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java @@ -12,7 +12,7 @@ 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.kickerelo.kickerelo.util.SpielerNameComparator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -45,7 +45,7 @@ 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(); } /** diff --git a/src/main/java/org/kickerelo/kickerelo/util/SpielerNameComparator.java b/src/main/java/org/kickerelo/kickerelo/util/SpielerNameComparator.java new file mode 100644 index 0000000..441386e --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/util/SpielerNameComparator.java @@ -0,0 +1,12 @@ +package org.kickerelo.kickerelo.util; + +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()); + } +} From 4ed29fb20ec18072b4670c605bc54507fc4061e3 Mon Sep 17 00:00:00 2001 From: Anton Micke Date: Fri, 30 May 2025 15:36:56 +0200 Subject: [PATCH 15/17] Use Spieler entities instead of names for Enter result views --- .../org/kickerelo/kickerelo/data/Spieler.java | 6 ++ .../kickerelo/service/KickerEloService.java | 59 ++++++------------- .../kickerelo/views/Enter1vs1View.java | 9 +-- .../kickerelo/views/Enter2vs2View.java | 17 +++--- 4 files changed, 39 insertions(+), 52 deletions(-) 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/service/KickerEloService.java b/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java index 75658e2..f7d9ea0 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; @@ -50,63 +49,55 @@ public class KickerEloService { /** * 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); eloCalculationService.updateElo1vs1(gewinner, verlierer, toreVerlierer); 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,18 +105,6 @@ 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); diff --git a/src/main/java/org/kickerelo/kickerelo/views/Enter1vs1View.java b/src/main/java/org/kickerelo/kickerelo/views/Enter1vs1View.java index 016d00d..e4ceb54 100644 --- a/src/main/java/org/kickerelo/kickerelo/views/Enter1vs1View.java +++ b/src/main/java/org/kickerelo/kickerelo/views/Enter1vs1View.java @@ -8,6 +8,7 @@ import com.vaadin.flow.component.notification.NotificationVariant; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.textfield.IntegerField; import com.vaadin.flow.router.Route; +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,12 +21,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 23829bc..e354255 100644 --- a/src/main/java/org/kickerelo/kickerelo/views/Enter2vs2View.java +++ b/src/main/java/org/kickerelo/kickerelo/views/Enter2vs2View.java @@ -8,6 +8,7 @@ import com.vaadin.flow.component.notification.NotificationVariant; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.textfield.IntegerField; import com.vaadin.flow.router.Route; +import org.kickerelo.kickerelo.data.Spieler; import org.kickerelo.kickerelo.exception.DuplicatePlayerException; import org.kickerelo.kickerelo.exception.InvalidDataException; import org.kickerelo.kickerelo.exception.NoSuchPlayerException; @@ -19,20 +20,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"); From 0e64e0fd029895a768413d9a024fc24ccdf66e1e Mon Sep 17 00:00:00 2001 From: Sebastian Beckmann Date: Fri, 30 May 2025 16:18:05 +0200 Subject: [PATCH 16/17] Show player elo change in match history --- .../service/EloCalculationService.java | 15 +++++++- .../kickerelo/service/EloChangeService.java | 37 +++++++++++++++++++ .../kickerelo/service/KickerEloService.java | 26 +++++++++---- .../kickerelo/views/History1vs1View.java | 16 +++++++- .../kickerelo/views/History2vs2View.java | 16 +++++++- .../kickerelo/views/HistoryCommonView.java | 24 ++++++++++++ 6 files changed, 122 insertions(+), 12 deletions(-) create mode 100644 src/main/java/org/kickerelo/kickerelo/service/EloChangeService.java create mode 100644 src/main/java/org/kickerelo/kickerelo/views/HistoryCommonView.java diff --git a/src/main/java/org/kickerelo/kickerelo/service/EloCalculationService.java b/src/main/java/org/kickerelo/kickerelo/service/EloCalculationService.java index d462a0d..f829b91 100644 --- a/src/main/java/org/kickerelo/kickerelo/service/EloCalculationService.java +++ b/src/main/java/org/kickerelo/kickerelo/service/EloCalculationService.java @@ -12,13 +12,19 @@ public class EloCalculationService { private final float initialElo1vs1 = 1500; private final float initialElo2vs2 = 1500; + private final EloChangeService eloChangeService; + + EloCalculationService(EloChangeService eloChangeService) { + this.eloChangeService = eloChangeService; + } + /** * Updates the 1 vs 1 ELOs of the players according to the result of the game. * @param gewinner The entity representing the winning player * @param verlierer The entity representing the losing player * @param toreVerlierer The number of goals of the losing player */ - public void updateElo1vs1(Spieler gewinner, Spieler verlierer, short toreVerlierer) { + public void updateElo1vs1(long gameId, Spieler gewinner, Spieler verlierer, short toreVerlierer) { final float baseK = 50; final float reductionPerGoal = 0.1f * baseK; final float finalK = baseK - (reductionPerGoal * toreVerlierer); @@ -28,17 +34,20 @@ public class EloCalculationService { gewinner.setElo1vs1(gewinner.getElo1vs1() + eloChange); verlierer.setElo1vs1(verlierer.getElo1vs1() - eloChange); + + eloChangeService.put1vs1Result(gameId, eloChange, -eloChange); } /** * Updates the 2 vs 2 ELOs of the players according to the result of the game + * @param gameId ID of the game * @param gewinnerVorn The winning offensive player * @param gewinnerHinten The winning defensive player * @param verliererVorn The losing offensive player * @param verliererHinten The losing defensive player * @param toreVerlierer The number of goals of the losing teams */ - public void updateElo2vs2(Spieler gewinnerVorn, Spieler gewinnerHinten, Spieler verliererVorn, Spieler verliererHinten, short toreVerlierer) { + public void updateElo2vs2(long gameId, Spieler gewinnerVorn, Spieler gewinnerHinten, Spieler verliererVorn, Spieler verliererHinten, short toreVerlierer) { final float baseK = 100; final double adjustedK = baseK * (1 - (0.1 * toreVerlierer)); var totalWinnerElo = gewinnerVorn.getElo2vs2() + gewinnerHinten.getElo2vs2(); @@ -60,6 +69,8 @@ public class EloCalculationService { gewinnerHinten.setElo2vs2((float) (gewinnerHinten.getElo2vs2() + winner2EloChange)); verliererVorn.setElo2vs2((float) (verliererVorn.getElo2vs2() + loser1EloChange)); verliererHinten.setElo2vs2((float) (verliererHinten.getElo2vs2() + loser2EloChange)); + + eloChangeService.put2vs2Result(gameId, winner1EloChange, winner2EloChange, loser1EloChange, loser2EloChange); } public float getInitialElo1vs1() { diff --git a/src/main/java/org/kickerelo/kickerelo/service/EloChangeService.java b/src/main/java/org/kickerelo/kickerelo/service/EloChangeService.java new file mode 100644 index 0000000..320531f --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/service/EloChangeService.java @@ -0,0 +1,37 @@ +package org.kickerelo.kickerelo.service; + +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; + +@Service +public class EloChangeService { + public record UpdateElo1vs1Change(double winnerEloChange, double loserEloChange) { + } + public record UpdateElo2vs2Change(double winnerFrontEloChange, double winnerBackEloChange, double loserFrontEloChange, double loserBackEloChange) { + } + + Map changes1vs1 = new HashMap<>(); + Map changes2vs2 = new HashMap<>(); + + public void put1vs1Result(long gameId, double winnerEloChange, double loserEloChange) { + changes1vs1.put(gameId, new UpdateElo1vs1Change(winnerEloChange, loserEloChange)); + } + + public void put2vs2Result(long gameId, double winnerFrontEloChange, double winnerBackEloChange, double loserFrontEloChange, double loserBackEloChange) { + changes2vs2.put(gameId, new UpdateElo2vs2Change(winnerFrontEloChange, winnerBackEloChange, loserFrontEloChange, loserBackEloChange)); + } + + public UpdateElo1vs1Change get1vs1Result(long gameId) { + var result = changes1vs1.get(gameId); + assert result != null; + return result; + } + + public UpdateElo2vs2Change 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 f7d9ea0..7036392 100644 --- a/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java +++ b/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java @@ -24,15 +24,23 @@ 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; + 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 */ @@ -70,7 +78,7 @@ public class KickerEloService { Ergebnis1vs1 ergebnis = new Ergebnis1vs1(gewinner, verlierer, toreVerlierer); ergebnis1vs1Repository.save(ergebnis); - eloCalculationService.updateElo1vs1(gewinner, verlierer, toreVerlierer); + eloCalculationService.updateElo1vs1(ergebnis.getId(), gewinner, verlierer, toreVerlierer); spielerRepository.save(gewinner); spielerRepository.save(verlierer); } @@ -108,7 +116,7 @@ public class KickerEloService { Ergebnis2vs2 ergebnis = new Ergebnis2vs2(gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer); ergebnis2vs2Repository.save(ergebnis); - eloCalculationService.updateElo2vs2(gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer); + eloCalculationService.updateElo2vs2(ergebnis.getId(), gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer); spielerRepository.save(gewinnerVorn); spielerRepository.save(gewinnerHinten); spielerRepository.save(verliererVorn); @@ -148,7 +156,8 @@ public class KickerEloService { } Stream results = ergebnis1vs1Repository.findAll().stream().sorted(new Ergebnis1vs1TimeComparator()); results.forEach(r -> { - eloCalculationService.updateElo1vs1(players.get(r.getGewinner().getId()), + eloCalculationService.updateElo1vs1(r.getId(), + players.get(r.getGewinner().getId()), players.get(r.getVerlierer().getId()), r.getToreVerlierer()); }); @@ -166,7 +175,8 @@ public class KickerEloService { } Stream results = ergebnis2vs2Repository.findAll().stream().sorted(new Ergebnis2vs2TimeComparator()); results.forEach(r -> { - eloCalculationService.updateElo2vs2(players.get(r.getGewinnerVorn().getId()), + eloCalculationService.updateElo2vs2(r.getId(), + players.get(r.getGewinnerVorn().getId()), players.get(r.getGewinnerHinten().getId()), players.get(r.getVerliererVorn().getId()), players.get(r.getVerliererHinten().getId()), diff --git a/src/main/java/org/kickerelo/kickerelo/views/History1vs1View.java b/src/main/java/org/kickerelo/kickerelo/views/History1vs1View.java index 2c1344f..b660fb7 100644 --- a/src/main/java/org/kickerelo/kickerelo/views/History1vs1View.java +++ b/src/main/java/org/kickerelo/kickerelo/views/History1vs1View.java @@ -10,18 +10,30 @@ 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; import org.kickerelo.kickerelo.data.Ergebnis1vs1; import org.kickerelo.kickerelo.repository.Ergebnis1vs1Repository; +import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository; +import org.kickerelo.kickerelo.service.EloChangeService; import java.util.List; +import static org.kickerelo.kickerelo.views.HistoryCommonView.formatEloChange; + @Route("history1vs1") public class History1vs1View extends VerticalLayout { + + private final Ergebnis1vs1Repository repo; + private final EloChangeService eloChangeService; + List res; - public History1vs1View(Ergebnis1vs1Repository repo) { + public History1vs1View(Ergebnis1vs1Repository repo, EloChangeService eloChangeService) { + this.repo = repo; + this.eloChangeService = eloChangeService; + setSizeFull(); H2 subheading = new H2("Spiele 1 vs 1"); res = repo.findAll(); @@ -49,8 +61,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.getGewinner(), eloChangeService.get1vs1Result(ergebnis.getId()).winnerEloChange()))); Grid.Column loserColumn = grid.getColumnByKey("verlierer"); loserColumn.setHeader("Verlierer"); + loserColumn.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis.getVerlierer(), eloChangeService.get1vs1Result(ergebnis.getId()).loserEloChange()))); 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 5daeb45..c57ebf0 100644 --- a/src/main/java/org/kickerelo/kickerelo/views/History2vs2View.java +++ b/src/main/java/org/kickerelo/kickerelo/views/History2vs2View.java @@ -11,17 +11,27 @@ 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; import org.kickerelo.kickerelo.data.Ergebnis2vs2; import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository; +import org.kickerelo.kickerelo.service.EloChangeService; import java.util.List; +import static org.kickerelo.kickerelo.views.HistoryCommonView.formatEloChange; + @Route("history2vs2") public class History2vs2View extends VerticalLayout { - public History2vs2View(Ergebnis2vs2Repository repo) { + + private final Ergebnis2vs2Repository repo; + private final EloChangeService eloChangeService; + + public History2vs2View(Ergebnis2vs2Repository repo, EloChangeService eloChangeService) { + this.repo = repo; + this.eloChangeService = eloChangeService; setSizeFull(); H2 subheading = new H2("Spiele 2 vs 2"); List res = repo.findAll(); @@ -63,12 +73,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.getGewinnerVorn(), eloChangeService.get2vs2Result(ergebnis.getId()).winnerFrontEloChange()))); Grid.Column winnerBack = grid.getColumnByKey("gewinnerHinten"); winnerBack.setHeader("Gewinner hinten"); + winnerBack.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis.getGewinnerHinten(), eloChangeService.get2vs2Result(ergebnis.getId()).winnerBackEloChange()))); Grid.Column loserFront = grid.getColumnByKey("verliererVorn"); loserFront.setHeader("Verlierer vorne"); + loserFront.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis.getVerliererVorn(), eloChangeService.get2vs2Result(ergebnis.getId()).loserFrontEloChange()))); Grid.Column loserBack = grid.getColumnByKey("verliererHinten"); loserBack.setHeader("Verlierer hinten"); + loserBack.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis.getVerliererHinten(), eloChangeService.get2vs2Result(ergebnis.getId()).loserBackEloChange()))); 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/HistoryCommonView.java b/src/main/java/org/kickerelo/kickerelo/views/HistoryCommonView.java new file mode 100644 index 0000000..98c2bf4 --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/views/HistoryCommonView.java @@ -0,0 +1,24 @@ +package org.kickerelo.kickerelo.views; + +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.component.html.Span; +import org.kickerelo.kickerelo.data.Spieler; + +public class HistoryCommonView { + private HistoryCommonView() {} + + 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.getStyle().set("color", "var(--lumo-secondary-text-color)"); + changeSpan.getStyle().set("font-style", "italic"); + + div.add(nameSpan, changeSpan); + + return div; + } +} From 0286ed7b5691115fee974428b2b3c09ef31571fd Mon Sep 17 00:00:00 2001 From: Anton Micke Date: Fri, 30 May 2025 20:35:28 +0200 Subject: [PATCH 17/17] General Refactoring --- .../service/EloCalculationService.java | 17 ++---- .../kickerelo/service/EloChangeService.java | 37 ------------ .../kickerelo/service/EloChangeTracker.java | 32 +++++++++++ .../kickerelo/service/KickerEloService.java | 47 ++++++++------- .../kickerelo/util/EloChange1vs1.java | 5 ++ .../kickerelo/util/EloChange2vs2.java | 7 +++ .../Ergebnis1vs1TimeComparator.java | 2 +- .../Ergebnis2vs2TimeComparator.java | 2 +- .../Spieler1vs1EloComparator.java | 2 +- .../Spieler2vs2EloComparator.java | 2 +- .../SpielerNameComparator.java | 2 +- .../kickerelo/views/Graph1vs1View.java | 2 +- .../kickerelo/views/Graph2vs2View.java | 2 +- .../kickerelo/views/History1vs1View.java | 15 ++--- .../kickerelo/views/History2vs2View.java | 17 ++---- .../kickerelo/views/HistoryCommonView.java | 24 -------- .../kickerelo/views/HistoryView.java | 57 +++++++++++++++++++ 17 files changed, 149 insertions(+), 123 deletions(-) delete mode 100644 src/main/java/org/kickerelo/kickerelo/service/EloChangeService.java create mode 100644 src/main/java/org/kickerelo/kickerelo/service/EloChangeTracker.java create mode 100644 src/main/java/org/kickerelo/kickerelo/util/EloChange1vs1.java create mode 100644 src/main/java/org/kickerelo/kickerelo/util/EloChange2vs2.java rename src/main/java/org/kickerelo/kickerelo/util/{ => comparator}/Ergebnis1vs1TimeComparator.java (86%) rename src/main/java/org/kickerelo/kickerelo/util/{ => comparator}/Ergebnis2vs2TimeComparator.java (86%) rename src/main/java/org/kickerelo/kickerelo/util/{ => comparator}/Spieler1vs1EloComparator.java (85%) rename src/main/java/org/kickerelo/kickerelo/util/{ => comparator}/Spieler2vs2EloComparator.java (85%) rename src/main/java/org/kickerelo/kickerelo/util/{ => comparator}/SpielerNameComparator.java (84%) delete mode 100644 src/main/java/org/kickerelo/kickerelo/views/HistoryCommonView.java create mode 100644 src/main/java/org/kickerelo/kickerelo/views/HistoryView.java diff --git a/src/main/java/org/kickerelo/kickerelo/service/EloCalculationService.java b/src/main/java/org/kickerelo/kickerelo/service/EloCalculationService.java index f829b91..a822d7c 100644 --- a/src/main/java/org/kickerelo/kickerelo/service/EloCalculationService.java +++ b/src/main/java/org/kickerelo/kickerelo/service/EloCalculationService.java @@ -1,6 +1,8 @@ package org.kickerelo.kickerelo.service; import org.kickerelo.kickerelo.data.Spieler; +import org.kickerelo.kickerelo.util.EloChange1vs1; +import org.kickerelo.kickerelo.util.EloChange2vs2; import org.springframework.stereotype.Service; @@ -12,19 +14,13 @@ public class EloCalculationService { private final float initialElo1vs1 = 1500; private final float initialElo2vs2 = 1500; - private final EloChangeService eloChangeService; - - EloCalculationService(EloChangeService eloChangeService) { - this.eloChangeService = eloChangeService; - } - /** * Updates the 1 vs 1 ELOs of the players according to the result of the game. * @param gewinner The entity representing the winning player * @param verlierer The entity representing the losing player * @param toreVerlierer The number of goals of the losing player */ - public void updateElo1vs1(long gameId, Spieler gewinner, Spieler verlierer, short toreVerlierer) { + public EloChange1vs1 updateElo1vs1(Spieler gewinner, Spieler verlierer, short toreVerlierer) { final float baseK = 50; final float reductionPerGoal = 0.1f * baseK; final float finalK = baseK - (reductionPerGoal * toreVerlierer); @@ -35,19 +31,18 @@ public class EloCalculationService { gewinner.setElo1vs1(gewinner.getElo1vs1() + eloChange); verlierer.setElo1vs1(verlierer.getElo1vs1() - eloChange); - eloChangeService.put1vs1Result(gameId, eloChange, -eloChange); + return new EloChange1vs1(eloChange, -eloChange); } /** * Updates the 2 vs 2 ELOs of the players according to the result of the game - * @param gameId ID of the game * @param gewinnerVorn The winning offensive player * @param gewinnerHinten The winning defensive player * @param verliererVorn The losing offensive player * @param verliererHinten The losing defensive player * @param toreVerlierer The number of goals of the losing teams */ - public void updateElo2vs2(long gameId, Spieler gewinnerVorn, Spieler gewinnerHinten, Spieler verliererVorn, Spieler verliererHinten, short toreVerlierer) { + public EloChange2vs2 updateElo2vs2(Spieler gewinnerVorn, Spieler gewinnerHinten, Spieler verliererVorn, Spieler verliererHinten, short toreVerlierer) { final float baseK = 100; final double adjustedK = baseK * (1 - (0.1 * toreVerlierer)); var totalWinnerElo = gewinnerVorn.getElo2vs2() + gewinnerHinten.getElo2vs2(); @@ -70,7 +65,7 @@ public class EloCalculationService { verliererVorn.setElo2vs2((float) (verliererVorn.getElo2vs2() + loser1EloChange)); verliererHinten.setElo2vs2((float) (verliererHinten.getElo2vs2() + loser2EloChange)); - eloChangeService.put2vs2Result(gameId, winner1EloChange, winner2EloChange, loser1EloChange, loser2EloChange); + return new EloChange2vs2(winner1EloChange, winner2EloChange, loser1EloChange, loser2EloChange); } public float getInitialElo1vs1() { diff --git a/src/main/java/org/kickerelo/kickerelo/service/EloChangeService.java b/src/main/java/org/kickerelo/kickerelo/service/EloChangeService.java deleted file mode 100644 index 320531f..0000000 --- a/src/main/java/org/kickerelo/kickerelo/service/EloChangeService.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.kickerelo.kickerelo.service; - -import org.springframework.stereotype.Service; - -import java.util.HashMap; -import java.util.Map; - -@Service -public class EloChangeService { - public record UpdateElo1vs1Change(double winnerEloChange, double loserEloChange) { - } - public record UpdateElo2vs2Change(double winnerFrontEloChange, double winnerBackEloChange, double loserFrontEloChange, double loserBackEloChange) { - } - - Map changes1vs1 = new HashMap<>(); - Map changes2vs2 = new HashMap<>(); - - public void put1vs1Result(long gameId, double winnerEloChange, double loserEloChange) { - changes1vs1.put(gameId, new UpdateElo1vs1Change(winnerEloChange, loserEloChange)); - } - - public void put2vs2Result(long gameId, double winnerFrontEloChange, double winnerBackEloChange, double loserFrontEloChange, double loserBackEloChange) { - changes2vs2.put(gameId, new UpdateElo2vs2Change(winnerFrontEloChange, winnerBackEloChange, loserFrontEloChange, loserBackEloChange)); - } - - public UpdateElo1vs1Change get1vs1Result(long gameId) { - var result = changes1vs1.get(gameId); - assert result != null; - return result; - } - - public UpdateElo2vs2Change get2vs2Result(long gameId) { - var result = changes2vs2.get(gameId); - assert result != null; - return result; - } -} diff --git a/src/main/java/org/kickerelo/kickerelo/service/EloChangeTracker.java b/src/main/java/org/kickerelo/kickerelo/service/EloChangeTracker.java new file mode 100644 index 0000000..9be3a05 --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/service/EloChangeTracker.java @@ -0,0 +1,32 @@ +package org.kickerelo.kickerelo.service; + +import org.kickerelo.kickerelo.util.EloChange1vs1; +import org.kickerelo.kickerelo.util.EloChange2vs2; + +import java.util.HashMap; +import java.util.Map; + +public class EloChangeTracker { + static Map 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 7036392..e611a96 100644 --- a/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java +++ b/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java @@ -9,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.SpielerNameComparator; -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; @@ -24,10 +25,10 @@ import java.util.stream.Stream; */ @Service public class KickerEloService { - private Ergebnis1vs1Repository ergebnis1vs1Repository; - private Ergebnis2vs2Repository ergebnis2vs2Repository; - private SpielerRepository spielerRepository; - 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, @@ -76,9 +77,10 @@ public class KickerEloService { } Ergebnis1vs1 ergebnis = new Ergebnis1vs1(gewinner, verlierer, toreVerlierer); - ergebnis1vs1Repository.save(ergebnis); + ergebnis = ergebnis1vs1Repository.save(ergebnis); - eloCalculationService.updateElo1vs1(ergebnis.getId(), gewinner, verlierer, toreVerlierer); + EloChange1vs1 change = eloCalculationService.updateElo1vs1(gewinner, verlierer, toreVerlierer); + EloChangeTracker.put1vs1Result(ergebnis.getId(), change); spielerRepository.save(gewinner); spielerRepository.save(verlierer); } @@ -114,9 +116,10 @@ public class KickerEloService { } Ergebnis2vs2 ergebnis = new Ergebnis2vs2(gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer); - ergebnis2vs2Repository.save(ergebnis); + ergebnis = ergebnis2vs2Repository.save(ergebnis); - eloCalculationService.updateElo2vs2(ergebnis.getId(), 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); @@ -156,10 +159,10 @@ public class KickerEloService { } Stream results = ergebnis1vs1Repository.findAll().stream().sorted(new Ergebnis1vs1TimeComparator()); results.forEach(r -> { - eloCalculationService.updateElo1vs1(r.getId(), - 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()); } @@ -175,12 +178,12 @@ public class KickerEloService { } Stream results = ergebnis2vs2Repository.findAll().stream().sorted(new Ergebnis2vs2TimeComparator()); results.forEach(r -> { - eloCalculationService.updateElo2vs2(r.getId(), - 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/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/SpielerNameComparator.java b/src/main/java/org/kickerelo/kickerelo/util/comparator/SpielerNameComparator.java similarity index 84% rename from src/main/java/org/kickerelo/kickerelo/util/SpielerNameComparator.java rename to src/main/java/org/kickerelo/kickerelo/util/comparator/SpielerNameComparator.java index 441386e..8626caa 100644 --- a/src/main/java/org/kickerelo/kickerelo/util/SpielerNameComparator.java +++ b/src/main/java/org/kickerelo/kickerelo/util/comparator/SpielerNameComparator.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/views/Graph1vs1View.java b/src/main/java/org/kickerelo/kickerelo/views/Graph1vs1View.java index 1c7d6b1..9b7928c 100644 --- a/src/main/java/org/kickerelo/kickerelo/views/Graph1vs1View.java +++ b/src/main/java/org/kickerelo/kickerelo/views/Graph1vs1View.java @@ -8,7 +8,7 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.Route; import org.kickerelo.kickerelo.repository.SpielerRepository; -import org.kickerelo.kickerelo.util.Spieler1vs1EloComparator; +import org.kickerelo.kickerelo.util.comparator.Spieler1vs1EloComparator; @Route("graph1vs1") public class Graph1vs1View extends VerticalLayout { diff --git a/src/main/java/org/kickerelo/kickerelo/views/Graph2vs2View.java b/src/main/java/org/kickerelo/kickerelo/views/Graph2vs2View.java index 62a23be..c0de179 100644 --- a/src/main/java/org/kickerelo/kickerelo/views/Graph2vs2View.java +++ b/src/main/java/org/kickerelo/kickerelo/views/Graph2vs2View.java @@ -8,7 +8,7 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.Route; import org.kickerelo.kickerelo.repository.SpielerRepository; -import org.kickerelo.kickerelo.util.Spieler2vs2EloComparator; +import org.kickerelo.kickerelo.util.comparator.Spieler2vs2EloComparator; @Route("graph2vs2") public class Graph2vs2View extends VerticalLayout { diff --git a/src/main/java/org/kickerelo/kickerelo/views/History1vs1View.java b/src/main/java/org/kickerelo/kickerelo/views/History1vs1View.java index b660fb7..b11607d 100644 --- a/src/main/java/org/kickerelo/kickerelo/views/History1vs1View.java +++ b/src/main/java/org/kickerelo/kickerelo/views/History1vs1View.java @@ -7,7 +7,6 @@ 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; @@ -16,23 +15,17 @@ import com.vaadin.flow.data.value.ValueChangeMode; import com.vaadin.flow.router.Route; import org.kickerelo.kickerelo.data.Ergebnis1vs1; import org.kickerelo.kickerelo.repository.Ergebnis1vs1Repository; -import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository; -import org.kickerelo.kickerelo.service.EloChangeService; import java.util.List; -import static org.kickerelo.kickerelo.views.HistoryCommonView.formatEloChange; - @Route("history1vs1") -public class History1vs1View extends VerticalLayout { +public class History1vs1View extends HistoryView { private final Ergebnis1vs1Repository repo; - private final EloChangeService eloChangeService; List res; - public History1vs1View(Ergebnis1vs1Repository repo, EloChangeService eloChangeService) { + public History1vs1View(Ergebnis1vs1Repository repo) { this.repo = repo; - this.eloChangeService = eloChangeService; setSizeFull(); H2 subheading = new H2("Spiele 1 vs 1"); @@ -61,10 +54,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.getGewinner(), eloChangeService.get1vs1Result(ergebnis.getId()).winnerEloChange()))); + 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.getVerlierer(), eloChangeService.get1vs1Result(ergebnis.getId()).loserEloChange()))); + 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 c57ebf0..1dd9eb3 100644 --- a/src/main/java/org/kickerelo/kickerelo/views/History2vs2View.java +++ b/src/main/java/org/kickerelo/kickerelo/views/History2vs2View.java @@ -8,7 +8,6 @@ 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; @@ -17,21 +16,17 @@ import com.vaadin.flow.data.value.ValueChangeMode; import com.vaadin.flow.router.Route; import org.kickerelo.kickerelo.data.Ergebnis2vs2; import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository; -import org.kickerelo.kickerelo.service.EloChangeService; import java.util.List; -import static org.kickerelo.kickerelo.views.HistoryCommonView.formatEloChange; @Route("history2vs2") -public class History2vs2View extends VerticalLayout { +public class History2vs2View extends HistoryView { private final Ergebnis2vs2Repository repo; - private final EloChangeService eloChangeService; - public History2vs2View(Ergebnis2vs2Repository repo, EloChangeService eloChangeService) { + public History2vs2View(Ergebnis2vs2Repository repo) { this.repo = repo; - this.eloChangeService = eloChangeService; setSizeFull(); H2 subheading = new H2("Spiele 2 vs 2"); List res = repo.findAll(); @@ -73,16 +68,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.getGewinnerVorn(), eloChangeService.get2vs2Result(ergebnis.getId()).winnerFrontEloChange()))); + 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.getGewinnerHinten(), eloChangeService.get2vs2Result(ergebnis.getId()).winnerBackEloChange()))); + 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.getVerliererVorn(), eloChangeService.get2vs2Result(ergebnis.getId()).loserFrontEloChange()))); + 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.getVerliererHinten(), eloChangeService.get2vs2Result(ergebnis.getId()).loserBackEloChange()))); + 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/HistoryCommonView.java b/src/main/java/org/kickerelo/kickerelo/views/HistoryCommonView.java deleted file mode 100644 index 98c2bf4..0000000 --- a/src/main/java/org/kickerelo/kickerelo/views/HistoryCommonView.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.kickerelo.kickerelo.views; - -import com.vaadin.flow.component.html.Div; -import com.vaadin.flow.component.html.Span; -import org.kickerelo.kickerelo.data.Spieler; - -public class HistoryCommonView { - private HistoryCommonView() {} - - 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.getStyle().set("color", "var(--lumo-secondary-text-color)"); - changeSpan.getStyle().set("font-style", "italic"); - - div.add(nameSpan, changeSpan); - - return div; - } -} 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; + } +}