mirror of
https://github.com/AJMicke/KickerELO.git
synced 2026-03-11 13:31:02 +01:00
15
pom.xml
15
pom.xml
@@ -22,6 +22,16 @@
|
|||||||
<vaadin.version>24.6.4</vaadin.version>
|
<vaadin.version>24.6.4</vaadin.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>Vaadin Directory</id>
|
||||||
|
<url>https://maven.vaadin.com/vaadin-addons</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@@ -31,6 +41,11 @@
|
|||||||
<groupId>com.vaadin</groupId>
|
<groupId>com.vaadin</groupId>
|
||||||
<artifactId>vaadin-spring-boot-starter</artifactId>
|
<artifactId>vaadin-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.appreciated</groupId>
|
||||||
|
<artifactId>apexcharts</artifactId>
|
||||||
|
<version>24.0.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mariadb.jdbc</groupId>
|
<groupId>org.mariadb.jdbc</groupId>
|
||||||
|
|||||||
12
src/main/frontend/prefers-color-scheme.js
Normal file
12
src/main/frontend/prefers-color-scheme.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
window.applyTheme = () => {
|
||||||
|
const theme = window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||||
|
? "dark"
|
||||||
|
: "";
|
||||||
|
document.documentElement.setAttribute("theme", theme);
|
||||||
|
};
|
||||||
|
window
|
||||||
|
.matchMedia("(prefers-color-scheme: dark)")
|
||||||
|
.addEventListener('change', function () {
|
||||||
|
window.applyTheme()
|
||||||
|
});
|
||||||
|
window.applyTheme();
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
package org.kickerelo.kickerelo;
|
|
||||||
|
|
||||||
import org.kickerelo.kickerelo.data.Ergebnis1vs1;
|
|
||||||
import org.kickerelo.kickerelo.data.Ergebnis2vs2;
|
|
||||||
import org.kickerelo.kickerelo.data.Spieler;
|
|
||||||
import org.kickerelo.kickerelo.repository.Ergebnis1vs1Repository;
|
|
||||||
import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository;
|
|
||||||
import org.kickerelo.kickerelo.repository.SpielerRepository;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class KickerEloService {
|
|
||||||
@Autowired
|
|
||||||
private Ergebnis1vs1Repository ergebnis1vs1Repository;
|
|
||||||
@Autowired
|
|
||||||
private Ergebnis2vs2Repository ergebnis2vs2Repository;
|
|
||||||
@Autowired
|
|
||||||
private SpielerRepository spielerRepository;
|
|
||||||
|
|
||||||
public List<String> getSpielerNamen() {
|
|
||||||
return spielerRepository.findAll().stream().map(Spieler::getName).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enterResult1vs1(String gewinnerName, String verliererName,
|
|
||||||
short toreVerlierer) {
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Compute the new ELO and update the Spieler entities
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enterResult2vs2(String gewinnerNameVorn, String gewinnerNameHinten,
|
|
||||||
String verliererNameVorn, String verliererNameHinten,
|
|
||||||
short toreVerlierer) {
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Compute the new ELO, update the Spieler entitities
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addSpieler(String name) {
|
|
||||||
Spieler spieler = new Spieler();
|
|
||||||
spieler.setName(name);
|
|
||||||
spieler.setElo(1500);
|
|
||||||
spielerRepository.save(spieler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,8 +13,11 @@ public class Spieler {
|
|||||||
@Column(name = "NAME", nullable = false, unique = true)
|
@Column(name = "NAME", nullable = false, unique = true)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Column(name = "ELO", nullable = false)
|
@Column(name = "ELO1vs1", nullable = false)
|
||||||
private float elo;
|
private float elo1vs1;
|
||||||
|
|
||||||
|
@Column(name = "ELO2vs2", nullable = false)
|
||||||
|
private float elo2vs2;
|
||||||
|
|
||||||
@Column(name = "ELO_ALT")
|
@Column(name = "ELO_ALT")
|
||||||
private float elo_alt;
|
private float elo_alt;
|
||||||
@@ -38,12 +41,20 @@ public class Spieler {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getElo() {
|
public float getElo1vs1() {
|
||||||
return elo;
|
return elo1vs1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setElo(float elo) {
|
public void setElo1vs1(float elo) {
|
||||||
this.elo = elo;
|
this.elo1vs1 = elo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getElo2vs2() {
|
||||||
|
return elo2vs2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setElo2vs2(float elo2vs2) {
|
||||||
|
this.elo2vs2 = elo2vs2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getElo_alt() {
|
public float getElo_alt() {
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ CREATE TABLE spieler
|
|||||||
(
|
(
|
||||||
id INT NOT NULL,
|
id INT NOT NULL,
|
||||||
name VARCHAR(255) NOT NULL,
|
name VARCHAR(255) NOT NULL,
|
||||||
elo FLOAT NOT NULL,
|
elo1vs1 FLOAT NOT NULL,
|
||||||
|
elo2vs2 FLOAT NOT NULL,
|
||||||
elo_alt FLOAT NULL,
|
elo_alt FLOAT NULL,
|
||||||
CONSTRAINT pk_spieler PRIMARY KEY (id)
|
CONSTRAINT pk_spieler PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package org.kickerelo.kickerelo.exception;
|
||||||
|
|
||||||
|
public class DuplicatePlayerException extends RuntimeException {
|
||||||
|
public DuplicatePlayerException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package org.kickerelo.kickerelo.exception;
|
||||||
|
|
||||||
|
public class InvalidDataException extends RuntimeException {
|
||||||
|
public InvalidDataException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.kickerelo.kickerelo;
|
package org.kickerelo.kickerelo.exception;
|
||||||
|
|
||||||
public class NoSuchPlayerException extends RuntimeException {
|
public class NoSuchPlayerException extends RuntimeException {
|
||||||
public NoSuchPlayerException(String message) {
|
public NoSuchPlayerException(String message) {
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package org.kickerelo.kickerelo.exception;
|
||||||
|
|
||||||
|
public class PlayerNameNotSetException extends RuntimeException {
|
||||||
|
public PlayerNameNotSetException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package org.kickerelo.kickerelo.layout;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.applayout.AppLayout;
|
||||||
|
import com.vaadin.flow.component.applayout.DrawerToggle;
|
||||||
|
import com.vaadin.flow.component.dependency.JsModule;
|
||||||
|
import com.vaadin.flow.component.html.H1;
|
||||||
|
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.RouterLink;
|
||||||
|
import org.kickerelo.kickerelo.views.*;
|
||||||
|
|
||||||
|
@Layout
|
||||||
|
@JsModule("prefers-color-scheme.js")
|
||||||
|
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);
|
||||||
|
RouterLink playerList = new RouterLink("Spielerliste", PlayerListView.class);
|
||||||
|
RouterLink graph1vs1 = new RouterLink("Graph 1 vs 1", Graph1vs1View.class);
|
||||||
|
RouterLink graph2vs2 = new RouterLink("Graph 2 vs 2", Graph2vs2View.class);
|
||||||
|
RouterLink admin = new RouterLink("Verwaltung", AdminView.class);
|
||||||
|
|
||||||
|
Tabs tabs = new Tabs(new Tab(playerList), new Tab(enter1vs1), new Tab(enter2vs2), new Tab(graph1vs1), new Tab(graph2vs2), new Tab(admin));
|
||||||
|
tabs.setOrientation(Tabs.Orientation.VERTICAL);
|
||||||
|
addToDrawer(tabs);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package org.kickerelo.kickerelo.service;
|
||||||
|
|
||||||
|
import org.kickerelo.kickerelo.data.Spieler;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This contains the math for calculating ELO only.
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class EloCalculationService {
|
||||||
|
private final float initialElo1vs1 = 1500;
|
||||||
|
private final float initialElo2vs2 = 1500;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
final float initialElo = 1500;
|
||||||
|
final float baseK = 50;
|
||||||
|
final float reductionPerGoal = 0.1f * baseK;
|
||||||
|
|
||||||
|
final float finalK = baseK - (reductionPerGoal * toreVerlierer);
|
||||||
|
float expectedScoreWinner = (float) (1 / (1 + Math.pow(10, (verlierer.getElo1vs1() - gewinner.getElo1vs1()) / 400)));
|
||||||
|
float expectedScoreLoser = (float) (1 / (1 + Math.pow(10, (gewinner.getElo1vs1() - verlierer.getElo1vs1()) / 400)));
|
||||||
|
|
||||||
|
gewinner.setElo1vs1(gewinner.getElo1vs1() + finalK * (1-expectedScoreWinner));
|
||||||
|
verlierer.setElo1vs1(verlierer.getElo1vs1() - finalK * expectedScoreLoser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the 2 vs 2 ELOs of the players according to the result 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) {
|
||||||
|
gewinnerVorn.setElo2vs2(gewinnerVorn.getElo2vs2() + 10 - toreVerlierer);
|
||||||
|
gewinnerHinten.setElo2vs2(gewinnerHinten.getElo2vs2() + 10 - toreVerlierer);
|
||||||
|
verliererVorn.setElo2vs2(verliererVorn.getElo2vs2() - 10 + toreVerlierer);
|
||||||
|
verliererHinten.setElo2vs2(verliererHinten.getElo2vs2());
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getInitialElo1vs1() {
|
||||||
|
return initialElo1vs1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getInitialElo2vs2() {
|
||||||
|
return initialElo2vs2;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
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;
|
||||||
|
import org.kickerelo.kickerelo.exception.PlayerNameNotSetException;
|
||||||
|
import org.kickerelo.kickerelo.repository.Ergebnis1vs1Repository;
|
||||||
|
import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository;
|
||||||
|
import org.kickerelo.kickerelo.repository.SpielerRepository;
|
||||||
|
import org.kickerelo.kickerelo.util.Ergebnis1vs1TimeComparator;
|
||||||
|
import org.kickerelo.kickerelo.util.Ergebnis2vs2TimeComparator;
|
||||||
|
import org.kickerelo.kickerelo.util.Spieler1vs1EloComparator;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides all functions for the application
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class KickerEloService {
|
||||||
|
@Autowired
|
||||||
|
private Ergebnis1vs1Repository ergebnis1vs1Repository;
|
||||||
|
@Autowired
|
||||||
|
private Ergebnis2vs2Repository ergebnis2vs2Repository;
|
||||||
|
@Autowired
|
||||||
|
private SpielerRepository spielerRepository;
|
||||||
|
@Autowired
|
||||||
|
private EloCalculationService eloCalculationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return List of all player names sorted alphabetically
|
||||||
|
*/
|
||||||
|
public List<String> getSpielerNamen() {
|
||||||
|
return spielerRepository.findAll().stream().map(Spieler::getName).sorted().toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return List of all player entities sorted by 1 vs 1 ELO
|
||||||
|
*/
|
||||||
|
public List<Spieler> getSpielerEntities() {
|
||||||
|
return spielerRepository.findAll().stream().sorted(new Spieler1vs1EloComparator()).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enter a result of a 1 vs 1 game
|
||||||
|
* @param gewinnerName The name of the winning player
|
||||||
|
* @param verliererName The name of the losing player
|
||||||
|
* @param toreVerlierer The number of goals of the loser
|
||||||
|
*/
|
||||||
|
public void enterResult1vs1(String gewinnerName, String verliererName,
|
||||||
|
short toreVerlierer) {
|
||||||
|
// Check if the inputs are valid
|
||||||
|
if (gewinnerName == null || verliererName == null) {
|
||||||
|
throw new PlayerNameNotSetException("Alle Namen müssen gesetzt sein");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gewinnerName.equals(verliererName)) {
|
||||||
|
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 toreVerlierer Number of goals of the losing team
|
||||||
|
*/
|
||||||
|
public void enterResult2vs2(String gewinnerNameVorn, String gewinnerNameHinten,
|
||||||
|
String verliererNameVorn, String verliererNameHinten,
|
||||||
|
short toreVerlierer) {
|
||||||
|
// Check if the inputs are valid
|
||||||
|
if (gewinnerNameVorn == null || gewinnerNameHinten == null
|
||||||
|
|| verliererNameVorn == null || verliererNameHinten == 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)) {
|
||||||
|
throw new DuplicatePlayerException("players must not be identical");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toreVerlierer > 9 || toreVerlierer < 0) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
eloCalculationService.updateElo2vs2(gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer);
|
||||||
|
spielerRepository.save(gewinnerVorn);
|
||||||
|
spielerRepository.save(gewinnerHinten);
|
||||||
|
spielerRepository.save(verliererVorn);
|
||||||
|
spielerRepository.save(verliererHinten);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new player to the system
|
||||||
|
* @param name Name of the new player
|
||||||
|
*/
|
||||||
|
public void addSpieler(String name) {
|
||||||
|
// Check if the player name is valid
|
||||||
|
if (name == null || name.isBlank()) {
|
||||||
|
throw new PlayerNameNotSetException("Leerer Name");
|
||||||
|
}
|
||||||
|
if (getSpielerNamen().contains(name)) {
|
||||||
|
throw new DuplicatePlayerException("players must not be identical");
|
||||||
|
}
|
||||||
|
if (name.length() > 30) {
|
||||||
|
throw new InvalidDataException("Zu lang");
|
||||||
|
}
|
||||||
|
Spieler spieler = new Spieler();
|
||||||
|
spieler.setName(name);
|
||||||
|
spieler.setElo1vs1(eloCalculationService.getInitialElo1vs1());
|
||||||
|
spieler.setElo2vs2(eloCalculationService.getInitialElo2vs2());
|
||||||
|
spielerRepository.save(spieler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recalculate and overwrite all 1 vs 1 ELOs.
|
||||||
|
*/
|
||||||
|
public void recalculateAll1vs1() {
|
||||||
|
HashMap<Integer, Spieler> players = new HashMap<>();
|
||||||
|
for (Spieler spieler : spielerRepository.findAll()) {
|
||||||
|
spieler.setElo1vs1(eloCalculationService.getInitialElo1vs1());
|
||||||
|
players.put(spieler.getId(), spieler);
|
||||||
|
}
|
||||||
|
Stream<Ergebnis1vs1> results = ergebnis1vs1Repository.findAll().stream().sorted(new Ergebnis1vs1TimeComparator());
|
||||||
|
results.forEach(r -> {
|
||||||
|
eloCalculationService.updateElo1vs1(players.get(r.getGewinner().getId()),
|
||||||
|
players.get(r.getVerlierer().getId()),
|
||||||
|
r.getToreVerlierer());
|
||||||
|
});
|
||||||
|
spielerRepository.saveAll(players.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recalculate and overwrite all 2 vs 2 ELOs.
|
||||||
|
*/
|
||||||
|
public void recalculateAll2vs2() {
|
||||||
|
HashMap<Integer, Spieler> players = new HashMap<>();
|
||||||
|
for (Spieler spieler : spielerRepository.findAll()) {
|
||||||
|
spieler.setElo2vs2(eloCalculationService.getInitialElo2vs2());
|
||||||
|
players.put(spieler.getId(), spieler);
|
||||||
|
}
|
||||||
|
Stream<Ergebnis2vs2> results = ergebnis2vs2Repository.findAll().stream().sorted(new Ergebnis2vs2TimeComparator());
|
||||||
|
results.forEach(r -> {
|
||||||
|
eloCalculationService.updateElo2vs2(players.get(r.getGewinnerVorn().getId()),
|
||||||
|
players.get(r.getGewinnerHinten().getId()),
|
||||||
|
players.get(r.getVerliererVorn().getId()),
|
||||||
|
players.get(r.getVerliererHinten().getId()),
|
||||||
|
r.getToreVerlierer());
|
||||||
|
});
|
||||||
|
spielerRepository.saveAll(players.values());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.kickerelo.kickerelo.util;
|
||||||
|
|
||||||
|
import org.kickerelo.kickerelo.data.Ergebnis1vs1;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
public class Ergebnis1vs1TimeComparator implements Comparator<Ergebnis1vs1> {
|
||||||
|
@Override
|
||||||
|
public int compare(Ergebnis1vs1 o1, Ergebnis1vs1 o2) {
|
||||||
|
return o1.getTimestamp().compareTo(o2.getTimestamp());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.kickerelo.kickerelo.util;
|
||||||
|
|
||||||
|
import org.kickerelo.kickerelo.data.Ergebnis2vs2;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
public class Ergebnis2vs2TimeComparator implements Comparator<Ergebnis2vs2> {
|
||||||
|
@Override
|
||||||
|
public int compare(Ergebnis2vs2 o1, Ergebnis2vs2 o2) {
|
||||||
|
return o1.getTimestamp().compareTo(o2.getTimestamp());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.kickerelo.kickerelo.util;
|
||||||
|
|
||||||
|
import org.kickerelo.kickerelo.data.Spieler;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
public class Spieler1vs1EloComparator implements Comparator<Spieler> {
|
||||||
|
@Override
|
||||||
|
public int compare(Spieler o1, Spieler o2) {
|
||||||
|
return Float.compare(o2.getElo1vs1(), o1.getElo1vs1());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.kickerelo.kickerelo.util;
|
||||||
|
|
||||||
|
import org.kickerelo.kickerelo.data.Spieler;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
public class Spieler2vs2EloComparator implements Comparator<Spieler> {
|
||||||
|
@Override
|
||||||
|
public int compare(Spieler o1, Spieler o2) {
|
||||||
|
return Float.compare(o2.getElo2vs2(), o1.getElo2vs2());
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/main/java/org/kickerelo/kickerelo/views/AdminView.java
Normal file
52
src/main/java/org/kickerelo/kickerelo/views/AdminView.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package org.kickerelo.kickerelo.views;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.button.Button;
|
||||||
|
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.TextField;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
import org.kickerelo.kickerelo.exception.DuplicatePlayerException;
|
||||||
|
import org.kickerelo.kickerelo.exception.InvalidDataException;
|
||||||
|
import org.kickerelo.kickerelo.exception.PlayerNameNotSetException;
|
||||||
|
import org.kickerelo.kickerelo.service.KickerEloService;
|
||||||
|
|
||||||
|
@Route("admin")
|
||||||
|
public class AdminView extends VerticalLayout {
|
||||||
|
public AdminView(KickerEloService service) {
|
||||||
|
H2 subheader = new H2("Verwaltung");
|
||||||
|
|
||||||
|
TextField spielername = new TextField("Spielername");
|
||||||
|
spielername.addClassName("bordered");
|
||||||
|
|
||||||
|
// Button click listeners can be defined as lambda expressions
|
||||||
|
Button addPlayerButton = new Button("Spieler hinzufügen", e -> {
|
||||||
|
try {
|
||||||
|
service.addSpieler(spielername.getValue());
|
||||||
|
} catch (PlayerNameNotSetException err) {
|
||||||
|
Notification.show("Spielername darf nicht leer sein").addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
|
return;
|
||||||
|
} catch (DuplicatePlayerException err) {
|
||||||
|
Notification.show("Spieler existiert bereits").addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
|
return;
|
||||||
|
} catch (InvalidDataException err) {
|
||||||
|
Notification.show("Name zu lang").addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
|
}
|
||||||
|
Notification.show("Spieler gespeichert").addThemeVariants(NotificationVariant.LUMO_SUCCESS);
|
||||||
|
});
|
||||||
|
|
||||||
|
Button recalc1vs1Button = new Button("1 vs 1 Elo neu berechnen", e -> {
|
||||||
|
Notification.show("Recalculating Elo").addThemeVariants(NotificationVariant.LUMO_WARNING);
|
||||||
|
service.recalculateAll1vs1();
|
||||||
|
Notification.show("Recalculating finished").addThemeVariants(NotificationVariant.LUMO_SUCCESS);
|
||||||
|
});
|
||||||
|
Button recalc2vs2Button = new Button("2 vs 2 Elo neu berechnen", e -> {
|
||||||
|
Notification.show("Recalculating Elo").addThemeVariants(NotificationVariant.LUMO_WARNING);
|
||||||
|
service.recalculateAll2vs2();
|
||||||
|
Notification.show("Recalculating finished").addThemeVariants(NotificationVariant.LUMO_SUCCESS);
|
||||||
|
});
|
||||||
|
|
||||||
|
add(spielername, spielername, addPlayerButton, recalc1vs1Button, recalc2vs2Button);
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/main/java/org/kickerelo/kickerelo/views/Chart1vs1.java
Normal file
50
src/main/java/org/kickerelo/kickerelo/views/Chart1vs1.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
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<Spieler> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/main/java/org/kickerelo/kickerelo/views/Chart2vs2.java
Normal file
41
src/main/java/org/kickerelo/kickerelo/views/Chart2vs2.java
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
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<Spieler> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,47 +1,24 @@
|
|||||||
package org.kickerelo.kickerelo;
|
package org.kickerelo.kickerelo.views;
|
||||||
|
|
||||||
import com.vaadin.flow.component.button.Button;
|
import com.vaadin.flow.component.button.Button;
|
||||||
import com.vaadin.flow.component.button.ButtonVariant;
|
|
||||||
import com.vaadin.flow.component.combobox.ComboBox;
|
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.Notification;
|
||||||
import com.vaadin.flow.component.notification.NotificationVariant;
|
import com.vaadin.flow.component.notification.NotificationVariant;
|
||||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
import com.vaadin.flow.component.textfield.IntegerField;
|
import com.vaadin.flow.component.textfield.IntegerField;
|
||||||
import com.vaadin.flow.component.textfield.TextField;
|
|
||||||
import com.vaadin.flow.router.Route;
|
import com.vaadin.flow.router.Route;
|
||||||
|
import org.kickerelo.kickerelo.exception.DuplicatePlayerException;
|
||||||
|
import org.kickerelo.kickerelo.exception.InvalidDataException;
|
||||||
|
import org.kickerelo.kickerelo.exception.NoSuchPlayerException;
|
||||||
|
import org.kickerelo.kickerelo.exception.PlayerNameNotSetException;
|
||||||
|
import org.kickerelo.kickerelo.service.KickerEloService;
|
||||||
|
|
||||||
/**
|
@Route(value = "enter1vs1")
|
||||||
* A sample Vaadin view class.
|
public class Enter1vs1View extends VerticalLayout {
|
||||||
* <p>
|
|
||||||
* To implement a Vaadin view just extend any Vaadin component and use @Route
|
|
||||||
* annotation to announce it in a URL as a Spring managed bean.
|
|
||||||
* <p>
|
|
||||||
* A new instance of this class is created for every new user and every browser
|
|
||||||
* tab/window.
|
|
||||||
* <p>
|
|
||||||
* The main view contains a text field for getting the user name and a button
|
|
||||||
* that shows a greeting message in a notification.
|
|
||||||
*/
|
|
||||||
@Route
|
|
||||||
public class MainView extends VerticalLayout {
|
|
||||||
|
|
||||||
/**
|
public Enter1vs1View(KickerEloService eloService) {
|
||||||
* Construct a new Vaadin view.
|
H2 subheading = new H2("1 vs 1 Ergebnis");
|
||||||
*/
|
|
||||||
|
|
||||||
public MainView(KickerEloService eloService) {
|
|
||||||
|
|
||||||
|
|
||||||
TextField spielername = new TextField("Spielername");
|
|
||||||
spielername.addClassName("bordered");
|
|
||||||
|
|
||||||
// Button click listeners can be defined as lambda expressions
|
|
||||||
Button button = new Button("Spieler hinzufügen", e -> {
|
|
||||||
eloService.addSpieler(spielername.getValue());
|
|
||||||
Notification.show("Spieler gespeichert").addThemeVariants(NotificationVariant.LUMO_SUCCESS);
|
|
||||||
});
|
|
||||||
|
|
||||||
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
|
||||||
|
|
||||||
ComboBox<String> winnerSelect = new ComboBox<>("Gewinner");
|
ComboBox<String> winnerSelect = new ComboBox<>("Gewinner");
|
||||||
winnerSelect.setItems(eloService.getSpielerNamen());
|
winnerSelect.setItems(eloService.getSpielerNamen());
|
||||||
@@ -62,7 +39,13 @@ public class MainView extends VerticalLayout {
|
|||||||
eloService.enterResult1vs1(winnerSelect.getValue(), loserSelect.getValue(), loserGoals.getValue().shortValue());
|
eloService.enterResult1vs1(winnerSelect.getValue(), loserSelect.getValue(), loserGoals.getValue().shortValue());
|
||||||
Notification.show("Gespeichert").addThemeVariants(NotificationVariant.LUMO_SUCCESS);
|
Notification.show("Gespeichert").addThemeVariants(NotificationVariant.LUMO_SUCCESS);
|
||||||
} catch (NoSuchPlayerException err) {
|
} catch (NoSuchPlayerException err) {
|
||||||
Notification.show("Konnte nicht gespeichert werden").addThemeVariants(NotificationVariant.LUMO_ERROR);
|
Notification.show("Unbekannter Spieler").addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
|
} catch (DuplicatePlayerException err) {
|
||||||
|
Notification.show("Alle Spieler müssen paarweise verschieden sein").addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
|
} catch (PlayerNameNotSetException err) {
|
||||||
|
Notification.show("Alle Spieler müssen gesetzt sein").addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
|
} catch (InvalidDataException err) {
|
||||||
|
Notification.show("Verliertore falsch").addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -72,6 +55,6 @@ public class MainView extends VerticalLayout {
|
|||||||
// styles.css.
|
// styles.css.
|
||||||
addClassName("centered-content");
|
addClassName("centered-content");
|
||||||
|
|
||||||
add(spielername, button, winnerSelect, loserSelect, loserGoals, saveButton);
|
add(subheading, winnerSelect, loserSelect, loserGoals, saveButton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
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.exception.DuplicatePlayerException;
|
||||||
|
import org.kickerelo.kickerelo.exception.InvalidDataException;
|
||||||
|
import org.kickerelo.kickerelo.exception.NoSuchPlayerException;
|
||||||
|
import org.kickerelo.kickerelo.exception.PlayerNameNotSetException;
|
||||||
|
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<String> winnerFrontSelect = new ComboBox<>("Gewinner vorne");
|
||||||
|
winnerFrontSelect.setItems(eloService.getSpielerNamen());
|
||||||
|
winnerFrontSelect.setPlaceholder("Spieler auswählen");
|
||||||
|
|
||||||
|
ComboBox<String> winnerBackSelect = new ComboBox<>("Gewinner hinten");
|
||||||
|
winnerBackSelect.setItems(eloService.getSpielerNamen());
|
||||||
|
winnerBackSelect.setPlaceholder("Spieler auswählen");
|
||||||
|
|
||||||
|
ComboBox<String> loserFrontSelect = new ComboBox<>("Verlierer vorne");
|
||||||
|
loserFrontSelect.setItems(eloService.getSpielerNamen());
|
||||||
|
loserFrontSelect.setPlaceholder("Spieler auswählen");
|
||||||
|
|
||||||
|
ComboBox<String> 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("Unbekannter Spieler").addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
|
} catch (DuplicatePlayerException err) {
|
||||||
|
Notification.show("Alle Spieler müssen paarweise verschieden sein").addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
|
} catch (PlayerNameNotSetException err) {
|
||||||
|
Notification.show("Alle Spieler müssen gesetzt sein").addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||||
|
} catch (InvalidDataException err) {
|
||||||
|
Notification.show("Verliertore falsch").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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package org.kickerelo.kickerelo.views;
|
||||||
|
|
||||||
|
import com.github.appreciated.apexcharts.ApexChartsBuilder;
|
||||||
|
import com.vaadin.flow.component.html.H2;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
import org.kickerelo.kickerelo.service.KickerEloService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
@Route("graph1vs1")
|
||||||
|
public class Graph1vs1View extends VerticalLayout {
|
||||||
|
|
||||||
|
ApexChartsBuilder chart1vs1;
|
||||||
|
public Graph1vs1View(KickerEloService service) {
|
||||||
|
H2 subheading = new H2("1 vs 1 Elo");
|
||||||
|
chart1vs1 = new Chart1vs1(service.getSpielerEntities());
|
||||||
|
add(subheading, chart1vs1.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.kickerelo.kickerelo.views;
|
||||||
|
|
||||||
|
import com.github.appreciated.apexcharts.ApexChartsBuilder;
|
||||||
|
import com.vaadin.flow.component.html.H2;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
import org.kickerelo.kickerelo.service.KickerEloService;
|
||||||
|
|
||||||
|
@Route("graph2vs2")
|
||||||
|
public class Graph2vs2View extends VerticalLayout {
|
||||||
|
ApexChartsBuilder chart2vs2;
|
||||||
|
public Graph2vs2View(KickerEloService service) {
|
||||||
|
H2 subheading = new H2("2 vs 2 Elo");
|
||||||
|
chart2vs2 = new Chart2vs2(service.getSpielerEntities());
|
||||||
|
add(subheading, chart2vs2.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package org.kickerelo.kickerelo.views;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.grid.Grid;
|
||||||
|
import com.vaadin.flow.component.grid.GridSortOrder;
|
||||||
|
import com.vaadin.flow.component.html.H2;
|
||||||
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
|
import com.vaadin.flow.data.provider.SortDirection;
|
||||||
|
import com.vaadin.flow.router.Route;
|
||||||
|
import org.kickerelo.kickerelo.data.Spieler;
|
||||||
|
import org.kickerelo.kickerelo.service.KickerEloService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Route("")
|
||||||
|
public class PlayerListView extends VerticalLayout {
|
||||||
|
public PlayerListView(KickerEloService eloService) {
|
||||||
|
setSizeFull();
|
||||||
|
H2 subheading = new H2("Spielerliste");
|
||||||
|
|
||||||
|
List<Spieler> players = eloService.getSpielerEntities();
|
||||||
|
Grid<Spieler> playerGrid = new Grid<>(Spieler.class);
|
||||||
|
|
||||||
|
playerGrid.setItems(players);
|
||||||
|
playerGrid.removeColumnByKey("id");
|
||||||
|
playerGrid.removeColumnByKey("elo_alt");
|
||||||
|
Grid.Column<Spieler> nameColumn = playerGrid.getColumnByKey("name");
|
||||||
|
Grid.Column<Spieler> elo1vs1Column = playerGrid.getColumnByKey("elo1vs1");
|
||||||
|
Grid.Column<Spieler> elo2vs2Column = playerGrid.getColumnByKey("elo2vs2");
|
||||||
|
nameColumn.setHeader("Name");
|
||||||
|
elo1vs1Column.setHeader("Elo 1 vs 1");
|
||||||
|
|
||||||
|
playerGrid.setColumnOrder(nameColumn, elo1vs1Column, elo2vs2Column);
|
||||||
|
|
||||||
|
GridSortOrder<Spieler> sortOrder = new GridSortOrder<>(elo1vs1Column, SortDirection.DESCENDING);
|
||||||
|
playerGrid.sort(List.of(sortOrder));
|
||||||
|
add(subheading, playerGrid);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,10 +6,9 @@ spring.mustache.check-template-location = false
|
|||||||
vaadin.launch-browser=true
|
vaadin.launch-browser=true
|
||||||
|
|
||||||
spring.datasource.url=jdbc:mariadb://localhost:3306/kickerelo
|
spring.datasource.url=jdbc:mariadb://localhost:3306/kickerelo
|
||||||
spring.datasource.username=
|
spring.datasource.username=root
|
||||||
spring.datasource.password=
|
spring.datasource.password=root
|
||||||
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
|
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
|
||||||
spring.jpa.hibernate.ddl-auto=validate
|
spring.jpa.hibernate.ddl-auto=validate
|
||||||
spring.jpa.show-sql=true
|
spring.jpa.show-sql=false
|
||||||
spring.jpa.format-sql=true
|
|
||||||
spring.jpa.open-in-view=false
|
spring.jpa.open-in-view=false
|
||||||
Reference in New Issue
Block a user