diff --git a/src/main/java/org/kickerelo/kickerelo/MainView.java b/src/main/java/org/kickerelo/kickerelo/MainView.java index b9d0570..14fffc9 100644 --- a/src/main/java/org/kickerelo/kickerelo/MainView.java +++ b/src/main/java/org/kickerelo/kickerelo/MainView.java @@ -9,6 +9,7 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.textfield.IntegerField; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.router.Route; +import org.kickerelo.kickerelo.service.KickerEloService; /** * A sample Vaadin view class. diff --git a/src/main/java/org/kickerelo/kickerelo/layout/KickerAppLayout.java b/src/main/java/org/kickerelo/kickerelo/layout/KickerAppLayout.java new file mode 100644 index 0000000..4b2a430 --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/layout/KickerAppLayout.java @@ -0,0 +1,35 @@ +package org.kickerelo.kickerelo.layout; + +import com.vaadin.flow.component.applayout.AppLayout; +import com.vaadin.flow.component.applayout.DrawerToggle; +import com.vaadin.flow.component.html.H1; +import com.vaadin.flow.component.orderedlayout.Scroller; +import com.vaadin.flow.component.sidenav.SideNav; +import com.vaadin.flow.component.tabs.Tab; +import com.vaadin.flow.component.tabs.Tabs; +import com.vaadin.flow.router.Layout; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.router.RouterLink; +import com.vaadin.flow.theme.lumo.LumoUtility; +import org.kickerelo.kickerelo.views.Enter1vs1View; +import org.kickerelo.kickerelo.views.Enter2vs2View; + +@Layout +public class KickerAppLayout extends AppLayout { + + public KickerAppLayout() { + DrawerToggle drawerToggle = new DrawerToggle(); + + H1 title = new H1("Kicker-ELO"); + title.getStyle().set("font-size", "var(--lumo-font-size-l)").set("margin", "0"); + + addToNavbar(drawerToggle, title); + + RouterLink enter1vs1 = new RouterLink("1 vs 1", Enter1vs1View.class); + RouterLink enter2vs2 = new RouterLink("2 vs 2", Enter2vs2View.class); + + Tabs tabs = new Tabs(new Tab(enter1vs1), new Tab(enter2vs2)); + tabs.setOrientation(Tabs.Orientation.VERTICAL); + addToDrawer(tabs); + } +} diff --git a/src/main/java/org/kickerelo/kickerelo/model/ResultInfo1vs1.java b/src/main/java/org/kickerelo/kickerelo/model/ResultInfo1vs1.java new file mode 100644 index 0000000..043f61c --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/model/ResultInfo1vs1.java @@ -0,0 +1,55 @@ +package org.kickerelo.kickerelo.model; + +public class ResultInfo1vs1 { + float oldEloWinner; + float oldEloLoser; + float newEloWinner; + float newEloLoser; + short loserGoals; + + public ResultInfo1vs1(float oldEloWinner, short loserGoals, float oldEloLoser) { + this.oldEloWinner = oldEloWinner; + this.loserGoals = loserGoals; + this.oldEloLoser = oldEloLoser; + } + + public float getOldEloWinner() { + return oldEloWinner; + } + + public void setOldEloWinner(float oldEloWinner) { + this.oldEloWinner = oldEloWinner; + } + + public float getOldEloLoser() { + return oldEloLoser; + } + + public void setOldEloLoser(float oldEloLoser) { + this.oldEloLoser = oldEloLoser; + } + + public float getNewEloWinner() { + return newEloWinner; + } + + public void setNewEloWinner(float newEloWinner) { + this.newEloWinner = newEloWinner; + } + + public float getNewEloLoser() { + return newEloLoser; + } + + public void setNewEloLoser(float newEloLoser) { + this.newEloLoser = newEloLoser; + } + + public short getLoserGoals() { + return loserGoals; + } + + public void setLoserGoals(short loserGoals) { + this.loserGoals = loserGoals; + } +} diff --git a/src/main/java/org/kickerelo/kickerelo/model/ResultInfo2vs2.java b/src/main/java/org/kickerelo/kickerelo/model/ResultInfo2vs2.java new file mode 100644 index 0000000..96b5edc --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/model/ResultInfo2vs2.java @@ -0,0 +1,93 @@ +package org.kickerelo.kickerelo.model; + +public class ResultInfo2vs2 { + float oldEloWinnerFront; + float oldEloWinnerBack; + float oldEloLoserFront; + float oldEloLoserBack; + float newEloWinnerFront; + float newEloWinnerBack; + float newEloLoserFront; + float newEloLoserBack; + short loserGoals; + + public ResultInfo2vs2(float oldEloWinnerFront, float oldEloWinnerBack, float oldEloLoserFront, float oldEloLoserBack, short loserGoals) { + this.oldEloWinnerFront = oldEloWinnerFront; + this.oldEloWinnerBack = oldEloWinnerBack; + this.oldEloLoserFront = oldEloLoserFront; + this.oldEloLoserBack = oldEloLoserBack; + this.loserGoals = loserGoals; + } + + public float getOldEloWinnerFront() { + return oldEloWinnerFront; + } + + public void setOldEloWinnerFront(float oldEloWinnerFront) { + this.oldEloWinnerFront = oldEloWinnerFront; + } + + public float getOldEloWinnerBack() { + return oldEloWinnerBack; + } + + public void setOldEloWinnerBack(float oldEloWinnerBack) { + this.oldEloWinnerBack = oldEloWinnerBack; + } + + public float getOldEloLoserFront() { + return oldEloLoserFront; + } + + public void setOldEloLoserFront(float oldEloLoserFront) { + this.oldEloLoserFront = oldEloLoserFront; + } + + public float getOldEloLoserBack() { + return oldEloLoserBack; + } + + public void setOldEloLoserBack(float oldEloLoserBack) { + this.oldEloLoserBack = oldEloLoserBack; + } + + public float getNewEloWinnerFront() { + return newEloWinnerFront; + } + + public void setNewEloWinnerFront(float newEloWinnerFront) { + this.newEloWinnerFront = newEloWinnerFront; + } + + public float getNewEloWinnerBack() { + return newEloWinnerBack; + } + + public void setNewEloWinnerBack(float newEloWinnerBack) { + this.newEloWinnerBack = newEloWinnerBack; + } + + public float getNewEloLoserFront() { + return newEloLoserFront; + } + + public void setNewEloLoserFront(float newEloLoserFront) { + this.newEloLoserFront = newEloLoserFront; + } + + public float getNewEloLoserBack() { + return newEloLoserBack; + } + + public void setNewEloLoserBack(float newEloLoserBack) { + this.newEloLoserBack = newEloLoserBack; + } + + public short getLoserGoals() { + return loserGoals; + } + + public void setLoserGoals(short loserGoals) { + this.loserGoals = loserGoals; + } +} diff --git a/src/main/java/org/kickerelo/kickerelo/service/EloCalculationService.java b/src/main/java/org/kickerelo/kickerelo/service/EloCalculationService.java new file mode 100644 index 0000000..54d1f1d --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/service/EloCalculationService.java @@ -0,0 +1,20 @@ +package org.kickerelo.kickerelo.service; + +import org.kickerelo.kickerelo.model.ResultInfo1vs1; +import org.kickerelo.kickerelo.model.ResultInfo2vs2; +import org.springframework.stereotype.Service; + +@Service +public class EloCalculationService { + public void updateElo1vs1(ResultInfo1vs1 result) { + result.setNewEloWinner(result.getOldEloWinner() + 1); + result.setNewEloLoser(result.getOldEloLoser() - 1); + } + + public void updateElo2vs2(ResultInfo2vs2 result) { + result.setNewEloWinnerFront(result.getOldEloWinnerFront() + 1); + result.setNewEloWinnerBack(result.getOldEloWinnerBack() + 1); + result.setNewEloLoserFront(result.getOldEloLoserFront() - 1); + result.setNewEloLoserBack(result.getOldEloLoserBack() - 1); + } +} diff --git a/src/main/java/org/kickerelo/kickerelo/KickerEloService.java b/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java similarity index 67% rename from src/main/java/org/kickerelo/kickerelo/KickerEloService.java rename to src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java index 0edfe88..7356ff2 100644 --- a/src/main/java/org/kickerelo/kickerelo/KickerEloService.java +++ b/src/main/java/org/kickerelo/kickerelo/service/KickerEloService.java @@ -1,8 +1,11 @@ -package org.kickerelo.kickerelo; +package org.kickerelo.kickerelo.service; +import org.kickerelo.kickerelo.NoSuchPlayerException; import org.kickerelo.kickerelo.data.Ergebnis1vs1; import org.kickerelo.kickerelo.data.Ergebnis2vs2; import org.kickerelo.kickerelo.data.Spieler; +import org.kickerelo.kickerelo.model.ResultInfo1vs1; +import org.kickerelo.kickerelo.model.ResultInfo2vs2; import org.kickerelo.kickerelo.repository.Ergebnis1vs1Repository; import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository; import org.kickerelo.kickerelo.repository.SpielerRepository; @@ -19,6 +22,8 @@ public class KickerEloService { private Ergebnis2vs2Repository ergebnis2vs2Repository; @Autowired private SpielerRepository spielerRepository; + @Autowired + private EloCalculationService eloCalculationService; public List getSpielerNamen() { return spielerRepository.findAll().stream().map(Spieler::getName).toList(); @@ -38,7 +43,13 @@ public class KickerEloService { ergebnis1vs1Repository.save(ergebnis); - // Compute the new ELO and update the Spieler entities + ResultInfo1vs1 result = new ResultInfo1vs1(gewinner.getElo(), ergebnis.getToreVerlierer(), verlierer.getElo()); + eloCalculationService.updateElo1vs1(result); + gewinner.setElo(result.getNewEloWinner()); + spielerRepository.save(gewinner); + verlierer.setElo(result.getNewEloLoser()); + spielerRepository.save(verlierer); + } public void enterResult2vs2(String gewinnerNameVorn, String gewinnerNameHinten, @@ -61,7 +72,16 @@ public class KickerEloService { ergebnis2vs2Repository.save(ergebnis); - // Compute the new ELO, update the Spieler entitities + ResultInfo2vs2 result = new ResultInfo2vs2(gewinnerVorn.getElo(), gewinnerHinten.getElo(), verliererVorn.getElo(), verliererHinten.getElo(), toreVerlierer); + eloCalculationService.updateElo2vs2(result); + gewinnerVorn.setElo(result.getNewEloWinnerFront()); + spielerRepository.save(gewinnerVorn); + gewinnerHinten.setElo(result.getNewEloWinnerBack()); + spielerRepository.save(gewinnerHinten); + verliererVorn.setElo(result.getNewEloLoserFront()); + spielerRepository.save(verliererVorn); + verliererHinten.setElo(result.getNewEloLoserBack()); + spielerRepository.save(verliererHinten); } public void addSpieler(String name) { diff --git a/src/main/java/org/kickerelo/kickerelo/views/Enter1vs1View.java b/src/main/java/org/kickerelo/kickerelo/views/Enter1vs1View.java new file mode 100644 index 0000000..cd0c690 --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/views/Enter1vs1View.java @@ -0,0 +1,51 @@ +package org.kickerelo.kickerelo.views; + +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.combobox.ComboBox; +import com.vaadin.flow.component.html.H2; +import com.vaadin.flow.component.notification.Notification; +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.NoSuchPlayerException; +import org.kickerelo.kickerelo.service.KickerEloService; + +@Route(value = "enter1vs1") +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()); + winnerSelect.setPlaceholder("Spieler auswählen"); + + ComboBox loserSelect = new ComboBox<>("Verlierer"); + loserSelect.setItems(eloService.getSpielerNamen()); + loserSelect.setPlaceholder("Spieler auswählen"); + + IntegerField loserGoals = new IntegerField("Tore des Verlierers"); + loserGoals.setMin(0); + loserGoals.setMax(9); + loserGoals.setValue(0); + loserGoals.setStepButtonsVisible(true); + + Button saveButton = new Button("Speichern", e -> { + try { + eloService.enterResult1vs1(winnerSelect.getValue(), loserSelect.getValue(), loserGoals.getValue().shortValue()); + Notification.show("Gespeichert").addThemeVariants(NotificationVariant.LUMO_SUCCESS); + } catch (NoSuchPlayerException err) { + Notification.show("Konnte nicht gespeichert werden").addThemeVariants(NotificationVariant.LUMO_ERROR); + } + }); + + + + // Use custom CSS classes to apply styling. This is defined in + // styles.css. + addClassName("centered-content"); + + add(subheading, winnerSelect, loserSelect, loserGoals, saveButton); + } +} diff --git a/src/main/java/org/kickerelo/kickerelo/views/Enter2vs2View.java b/src/main/java/org/kickerelo/kickerelo/views/Enter2vs2View.java new file mode 100644 index 0000000..ed46440 --- /dev/null +++ b/src/main/java/org/kickerelo/kickerelo/views/Enter2vs2View.java @@ -0,0 +1,57 @@ +package org.kickerelo.kickerelo.views; + +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.combobox.ComboBox; +import com.vaadin.flow.component.html.H2; +import com.vaadin.flow.component.notification.Notification; +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.NoSuchPlayerException; +import org.kickerelo.kickerelo.service.KickerEloService; + +@Route(value = "enter2vs2") +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()); + winnerFrontSelect.setPlaceholder("Spieler auswählen"); + + ComboBox winnerBackSelect = new ComboBox<>("Gewinner hinten"); + winnerBackSelect.setItems(eloService.getSpielerNamen()); + winnerBackSelect.setPlaceholder("Spieler auswählen"); + + ComboBox loserFrontSelect = new ComboBox<>("Verlierer vorne"); + loserFrontSelect.setItems(eloService.getSpielerNamen()); + loserFrontSelect.setPlaceholder("Spieler auswählen"); + + ComboBox loserBackSelect = new ComboBox<>("Verlierer hinten"); + loserBackSelect.setItems(eloService.getSpielerNamen()); + loserBackSelect.setPlaceholder("Spieler auswählen"); + + IntegerField loserGoals = new IntegerField("Tore des Verlierers"); + loserGoals.setMin(0); + loserGoals.setMax(9); + loserGoals.setValue(0); + loserGoals.setStepButtonsVisible(true); + + Button saveButton = new Button("Speichern", e -> { + try { + eloService.enterResult2vs2(winnerFrontSelect.getValue(), winnerBackSelect.getValue(), loserFrontSelect.getValue(), loserBackSelect.getValue(), loserGoals.getValue().shortValue()); + Notification.show("Gespeichert").addThemeVariants(NotificationVariant.LUMO_SUCCESS); + } catch (NoSuchPlayerException err) { + Notification.show("Konnte nicht gespeichert werden").addThemeVariants(NotificationVariant.LUMO_ERROR); + } + }); + + + // Use custom CSS classes to apply styling. This is defined in + // styles.css. + addClassName("centered-content"); + + add(subheading, winnerFrontSelect, winnerBackSelect, loserFrontSelect, loserBackSelect, loserGoals, saveButton); + } +}