From f38b5b952fa6655a131349be1c4e5ac167fd09ec Mon Sep 17 00:00:00 2001 From: Anton Micke Date: Fri, 9 May 2025 15:42:04 +0200 Subject: [PATCH] Add 2 vs 2 win rates --- .../kickerelo/layout/KickerAppLayout.java | 3 +- .../repository/Ergebnis2vs2Repository.java | 5 +++ .../kickerelo/service/Stat2vs2Service.java | 45 +++++++++++++++++++ .../kickerelo/kickerelo/util/Position.java | 5 +++ .../kickerelo/views/Stat2vs2View.java | 42 +++++++++++++++++ 5 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/kickerelo/kickerelo/service/Stat2vs2Service.java create mode 100644 src/main/java/org/kickerelo/kickerelo/util/Position.java create mode 100644 src/main/java/org/kickerelo/kickerelo/views/Stat2vs2View.java diff --git a/src/main/java/org/kickerelo/kickerelo/layout/KickerAppLayout.java b/src/main/java/org/kickerelo/kickerelo/layout/KickerAppLayout.java index ee8a1e8..ef3ff53 100644 --- a/src/main/java/org/kickerelo/kickerelo/layout/KickerAppLayout.java +++ b/src/main/java/org/kickerelo/kickerelo/layout/KickerAppLayout.java @@ -39,7 +39,8 @@ public class KickerAppLayout extends AppLayout { nav2.setCollapsible(true); nav2.addItem(new SideNavItem("Ergebnis eintragen", Enter2vs2View.class, VaadinIcon.EDIT.create()), new SideNavItem("ELO-Graph", Graph2vs2View.class, VaadinIcon.BAR_CHART.create()), - new SideNavItem("Historie", History2vs2View.class, VaadinIcon.RECORDS.create())); + new SideNavItem("Historie", History2vs2View.class, VaadinIcon.RECORDS.create()), + new SideNavItem("Statistik", Stat2vs2View.class, VaadinIcon.ABACUS.create())); Image githubLogo = new Image("github-mark.png", "Github"); diff --git a/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java b/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java index 3e9c3f9..ab3a421 100644 --- a/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java +++ b/src/main/java/org/kickerelo/kickerelo/repository/Ergebnis2vs2Repository.java @@ -1,9 +1,14 @@ 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.stereotype.Repository; @Repository public interface Ergebnis2vs2Repository extends JpaRepository { + int countByGewinnerHinten(Spieler gewinnerHinten); + int countByGewinnerVorn(Spieler gewinnerVon); + int countByVerliererHinten(Spieler verliererHinten); + int countByVerliererVorn(Spieler verlierVon); } diff --git a/src/main/java/org/kickerelo/kickerelo/service/Stat2vs2Service.java b/src/main/java/org/kickerelo/kickerelo/service/Stat2vs2Service.java new file mode 100644 index 0000000..dd1f863 --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/service/Stat2vs2Service.java @@ -0,0 +1,45 @@ +package org.kickerelo.kickerelo.service; + +import org.kickerelo.kickerelo.data.Spieler; +import org.kickerelo.kickerelo.exception.NoSuchPlayerException; +import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository; +import org.kickerelo.kickerelo.repository.SpielerRepository; +import org.kickerelo.kickerelo.util.Position; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +public class Stat2vs2Service { + Ergebnis2vs2Repository ergebnis2vs2Repository; + SpielerRepository spielerRepository; + + public Stat2vs2Service(Ergebnis2vs2Repository ergebnis2vs2Repository, SpielerRepository spielerRepository) { + this.ergebnis2vs2Repository = ergebnis2vs2Repository; + this.spielerRepository = spielerRepository; + } + + public Float getWinrate(Spieler s, Position p) { + int wins, losses; + switch (p) { + case BACK: + wins = ergebnis2vs2Repository.countByGewinnerHinten(s); + losses = ergebnis2vs2Repository.countByVerliererHinten(s); + break; + case FRONT: + wins = ergebnis2vs2Repository.countByGewinnerVorn(s); + losses = ergebnis2vs2Repository.countByVerliererVorn(s); + break; + default: + wins = 0; + losses = 0; + } + return (float) (100 * wins) / (wins+losses); + } + + public Float getWinrate(String playerName, Position p) { + Optional spieler = spielerRepository.findByName(playerName); + if (spieler.isEmpty()) throw new NoSuchPlayerException(playerName); + return getWinrate(spieler.get(), p); + } +} diff --git a/src/main/java/org/kickerelo/kickerelo/util/Position.java b/src/main/java/org/kickerelo/kickerelo/util/Position.java new file mode 100644 index 0000000..7fc835e --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/util/Position.java @@ -0,0 +1,5 @@ +package org.kickerelo.kickerelo.util; + +public enum Position { + FRONT, BACK +} diff --git a/src/main/java/org/kickerelo/kickerelo/views/Stat2vs2View.java b/src/main/java/org/kickerelo/kickerelo/views/Stat2vs2View.java new file mode 100644 index 0000000..c78a8f8 --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/views/Stat2vs2View.java @@ -0,0 +1,42 @@ +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.Paragraph; +import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.router.Route; +import org.kickerelo.kickerelo.data.Spieler; +import org.kickerelo.kickerelo.service.KickerEloService; +import org.kickerelo.kickerelo.service.Stat2vs2Service; +import org.kickerelo.kickerelo.util.Position; + +@Route("stat2vs2") +public class Stat2vs2View extends VerticalLayout { + Stat2vs2Service stat2vs2Service; + KickerEloService kickerEloService; + H2 subheading; + ComboBox selector; + Paragraph winrateBack; + Paragraph winrateFront; + public Stat2vs2View(Stat2vs2Service service, KickerEloService kickerService) { + this.stat2vs2Service = service; + this.kickerEloService = kickerService; + subheading = new H2("2 vs 2 Ergebnis"); + selector = new ComboBox<>("Spieler"); + selector.setItems(kickerService.getSpielerEntities()); + selector.addValueChangeListener(event -> { + updateData(selector.getValue()); + }); + winrateBack = new Paragraph(""); + winrateFront = new Paragraph(""); + + add(subheading, selector, winrateBack, winrateFront); + } + + private void updateData(Spieler s) { + Float rateBack = stat2vs2Service.getWinrate(s, Position.BACK); + Float rateFront = stat2vs2Service.getWinrate(s, Position.FRONT); + winrateBack.setText("Winrate hinten: " + (rateBack.isNaN() ? "-" : rateBack)); + winrateFront.setText("Winrate vorne: " + (rateFront.isNaN() ? "-" : rateFront)); + } +}