mirror of
https://github.com/AJMicke/KickerELO.git
synced 2026-03-12 22:11:08 +01:00
Tuning
This commit is contained in:
@@ -1,79 +0,0 @@
|
||||
package org.kickerelo.kickerelo;
|
||||
|
||||
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.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.component.textfield.TextField;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import org.kickerelo.kickerelo.exception.NoSuchPlayerException;
|
||||
import org.kickerelo.kickerelo.service.KickerEloService;
|
||||
|
||||
/**
|
||||
* A sample Vaadin view class.
|
||||
* <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 {
|
||||
|
||||
/**
|
||||
* Construct a new Vaadin view.
|
||||
*/
|
||||
|
||||
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");
|
||||
winnerSelect.setItems(eloService.getSpielerNamen());
|
||||
winnerSelect.setPlaceholder("Spieler auswählen");
|
||||
|
||||
ComboBox<String> 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(spielername, button, winnerSelect, loserSelect, loserGoals, saveButton);
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,10 @@ 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.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.*;
|
||||
|
||||
@Layout
|
||||
@@ -33,9 +29,7 @@ public class KickerAppLayout extends AppLayout {
|
||||
RouterLink graph2vs2 = new RouterLink("Graph 2 vs 2", Graph2vs2View.class);
|
||||
RouterLink admin = new RouterLink("Verwaltung", AdminView.class);
|
||||
|
||||
|
||||
|
||||
Tabs tabs = new Tabs(new Tab(enter1vs1), new Tab(enter2vs2), new Tab(playerList), new Tab(graph1vs1), new Tab(graph2vs2), new Tab(admin));
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package org.kickerelo.kickerelo.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.kickerelo.kickerelo.data.Ergebnis1vs1;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@@ -4,8 +4,6 @@ import org.kickerelo.kickerelo.data.Ergebnis2vs2;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Repository
|
||||
public interface Ergebnis2vs2Repository extends JpaRepository<Ergebnis2vs2, Long> {
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import org.kickerelo.kickerelo.data.Spieler;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
|
||||
@@ -4,17 +4,34 @@ import org.kickerelo.kickerelo.data.Spieler;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This contains the math for calculating ELO only.
|
||||
*/
|
||||
@Service
|
||||
public class EloCalculationService {
|
||||
// Default ELOs for a player with 0 games
|
||||
final float initialElo1vs1 = 1500;
|
||||
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) {
|
||||
gewinner.setElo1vs1(gewinner.getElo1vs1() + 10 - toreVerlierer);
|
||||
verlierer.setElo1vs1(verlierer.getElo1vs1() - 10 + toreVerlierer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
@@ -20,6 +20,9 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Provides all functions for the application
|
||||
*/
|
||||
@Service
|
||||
public class KickerEloService {
|
||||
@Autowired
|
||||
@@ -31,16 +34,29 @@ public class KickerEloService {
|
||||
@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");
|
||||
}
|
||||
@@ -60,7 +76,6 @@ public class KickerEloService {
|
||||
|
||||
|
||||
Ergebnis1vs1 ergebnis = new Ergebnis1vs1(gewinner, verlierer, toreVerlierer);
|
||||
|
||||
ergebnis1vs1Repository.save(ergebnis);
|
||||
|
||||
eloCalculationService.updateElo1vs1(gewinner, verlierer, toreVerlierer);
|
||||
@@ -69,10 +84,18 @@ public class KickerEloService {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
@@ -104,7 +127,6 @@ public class KickerEloService {
|
||||
.orElseThrow(() -> new NoSuchPlayerException(verliererNameHinten));
|
||||
|
||||
Ergebnis2vs2 ergebnis = new Ergebnis2vs2(gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer);
|
||||
|
||||
ergebnis2vs2Repository.save(ergebnis);
|
||||
|
||||
eloCalculationService.updateElo2vs2(gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer);
|
||||
@@ -114,13 +136,21 @@ public class KickerEloService {
|
||||
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());
|
||||
@@ -128,6 +158,9 @@ public class KickerEloService {
|
||||
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()) {
|
||||
@@ -143,6 +176,9 @@ public class KickerEloService {
|
||||
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()) {
|
||||
|
||||
@@ -8,6 +8,7 @@ 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;
|
||||
|
||||
@@ -26,10 +27,11 @@ public class AdminView extends VerticalLayout {
|
||||
} catch (PlayerNameNotSetException err) {
|
||||
Notification.show("Spielername darf nicht leer sein").addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||
return;
|
||||
}
|
||||
catch (DuplicatePlayerException err) {
|
||||
} 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);
|
||||
});
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
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;
|
||||
|
||||
@@ -19,13 +26,17 @@ import java.util.List;
|
||||
|
||||
public class Chart1vs1 extends ApexChartsBuilder {
|
||||
public Chart1vs1(List<Spieler> l) {
|
||||
Style style = new Style();
|
||||
style.setColors(List.of("#80C3FC"));
|
||||
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);
|
||||
labels.setStyle(style);
|
||||
|
||||
|
||||
withChart(ChartBuilder.get().withType(Type.SCATTER)
|
||||
.withZoom(ZoomBuilder.get().withEnabled(true).withType(ZoomType.XY).build()).build())
|
||||
.withSeries(new Series<>("ELO",
|
||||
@@ -33,6 +44,7 @@ public class Chart1vs1 extends ApexChartsBuilder {
|
||||
))
|
||||
.withXaxis(XAxisBuilder.get().withCategories(l.stream().sorted(new Spieler1vs1EloComparator())
|
||||
.map(Spieler::getName).toList()).withLabels(labels).build())
|
||||
.withYaxis(YAxisBuilder.get().build());
|
||||
.withYaxis(YAxisBuilder.get().build())
|
||||
.withTheme(theme);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
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;
|
||||
@@ -15,12 +19,23 @@ 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()).build())
|
||||
.withYaxis(YAxisBuilder.get().build());
|
||||
.withXaxis(XAxisBuilder.get().withCategories(l.stream().sorted(new Spieler2vs2EloComparator()).map(Spieler::getName).toList()).withLabels(labels).build())
|
||||
.withYaxis(YAxisBuilder.get().build())
|
||||
.withTheme(theme);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,10 @@ import org.kickerelo.kickerelo.service.KickerEloService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Route("playerlist")
|
||||
@Route("")
|
||||
public class PlayerListView extends VerticalLayout {
|
||||
public PlayerListView(KickerEloService eloService) {
|
||||
setSizeFull();
|
||||
H2 subheading = new H2("Spielerliste");
|
||||
|
||||
List<Spieler> players = eloService.getSpielerEntities();
|
||||
|
||||
Reference in New Issue
Block a user