mirror of
https://github.com/AJMicke/KickerELO.git
synced 2026-03-11 13:31:02 +01:00
Merge branch 'AJMicke:master' into sso
This commit is contained in:
@@ -62,7 +62,8 @@ public class KickerAppLayout extends AppLayout {
|
|||||||
nav2.setCollapsible(true);
|
nav2.setCollapsible(true);
|
||||||
nav2.addItem(new SideNavItem("Ergebnis eintragen", Enter2vs2View.class, VaadinIcon.EDIT.create()),
|
nav2.addItem(new SideNavItem("Ergebnis eintragen", Enter2vs2View.class, VaadinIcon.EDIT.create()),
|
||||||
new SideNavItem("ELO-Graph", Graph2vs2View.class, VaadinIcon.BAR_CHART.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");
|
Image githubLogo = new Image("github-mark.png", "Github");
|
||||||
|
|||||||
@@ -1,9 +1,18 @@
|
|||||||
package org.kickerelo.kickerelo.repository;
|
package org.kickerelo.kickerelo.repository;
|
||||||
|
|
||||||
import org.kickerelo.kickerelo.data.Ergebnis2vs2;
|
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.JpaRepository;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface Ergebnis2vs2Repository extends JpaRepository<Ergebnis2vs2, Long> {
|
public interface Ergebnis2vs2Repository extends JpaRepository<Ergebnis2vs2, Long> {
|
||||||
|
int countByGewinnerHinten(Spieler gewinnerHinten);
|
||||||
|
int countByGewinnerVorn(Spieler gewinnerVon);
|
||||||
|
int countByVerliererHinten(Spieler verliererHinten);
|
||||||
|
int countByVerliererVorn(Spieler verlierVon);
|
||||||
|
|
||||||
|
int countByGewinnerVornOrGewinnerHinten(Spieler gewinnerVon, Spieler gewinnerHinten);
|
||||||
|
int countByGewinnerVornOrGewinnerHintenOrVerliererVornOrVerliererHinten(Spieler gewinnerVon, Spieler gewinnerHinten,
|
||||||
|
Spieler verliererVon, Spieler verliererHinten);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,13 +21,13 @@ public class EloCalculationService {
|
|||||||
public void updateElo1vs1(Spieler gewinner, Spieler verlierer, short toreVerlierer) {
|
public void updateElo1vs1(Spieler gewinner, Spieler verlierer, short toreVerlierer) {
|
||||||
final float baseK = 50;
|
final float baseK = 50;
|
||||||
final float reductionPerGoal = 0.1f * baseK;
|
final float reductionPerGoal = 0.1f * baseK;
|
||||||
|
|
||||||
final float finalK = baseK - (reductionPerGoal * toreVerlierer);
|
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));
|
double x = Math.pow(10, (verlierer.getElo1vs1() - gewinner.getElo1vs1()) / 400);
|
||||||
verlierer.setElo1vs1(verlierer.getElo1vs1() - finalK * expectedScoreLoser);
|
float eloChange = (float) (finalK * x / (x + 1));
|
||||||
|
|
||||||
|
gewinner.setElo1vs1(gewinner.getElo1vs1() + eloChange);
|
||||||
|
verlierer.setElo1vs1(verlierer.getElo1vs1() - eloChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package org.kickerelo.kickerelo.service;
|
||||||
|
|
||||||
|
import org.kickerelo.kickerelo.data.Spieler;
|
||||||
|
import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository;
|
||||||
|
import org.kickerelo.kickerelo.repository.SpielerRepository;
|
||||||
|
import org.kickerelo.kickerelo.util.Position;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@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) wins / (wins+losses);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Float getFrontRate(Spieler s) {
|
||||||
|
int numFront = ergebnis2vs2Repository.countByGewinnerVornOrGewinnerHinten(s, s);
|
||||||
|
int numAll = ergebnis2vs2Repository.countByGewinnerVornOrGewinnerHintenOrVerliererVornOrVerliererHinten(s, s, s, s);
|
||||||
|
return (float) numFront / numAll;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/main/java/org/kickerelo/kickerelo/util/Position.java
Normal file
5
src/main/java/org/kickerelo/kickerelo/util/Position.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package org.kickerelo.kickerelo.util;
|
||||||
|
|
||||||
|
public enum Position {
|
||||||
|
FRONT, BACK
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
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.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.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<Spieler> selector;
|
||||||
|
ProgressBar frontRate = new ProgressBar();
|
||||||
|
NativeLabel frontRateText = new NativeLabel();
|
||||||
|
ProgressBar winRateFront = new ProgressBar();
|
||||||
|
NativeLabel winRateFrontText = new NativeLabel();
|
||||||
|
ProgressBar winRateBack = new ProgressBar();
|
||||||
|
NativeLabel winRateBackText = new NativeLabel();
|
||||||
|
|
||||||
|
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()));
|
||||||
|
add(subheading, selector, frontRateText, frontRate, winRateFrontText, winRateFront, winRateBackText, winRateBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateData(Spieler s) {
|
||||||
|
updateFrontRate(s);
|
||||||
|
updateFrontWinrate(s);
|
||||||
|
updateBackWinrate(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateFrontRate(Spieler s) {
|
||||||
|
String text = "Anteil Spiele vorne: ";
|
||||||
|
Float rateFrontGames = stat2vs2Service.getFrontRate(s);
|
||||||
|
frontRate.setValue(rateFrontGames);
|
||||||
|
frontRateText.setText(rateFrontGames.isNaN() ? text + "-" : text + String.format("%.2f", rateFrontGames * 100) + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateFrontWinrate(Spieler s) {
|
||||||
|
String text = "Winrate vorne: ";
|
||||||
|
Float winRate = stat2vs2Service.getWinrate(s, Position.FRONT);
|
||||||
|
winRateFront.setValue(winRate);
|
||||||
|
winRateFront.removeThemeVariants(ProgressBarVariant.LUMO_SUCCESS, ProgressBarVariant.LUMO_ERROR);
|
||||||
|
winRateFront.addThemeVariants((winRate > 0.5f ? ProgressBarVariant.LUMO_SUCCESS : ProgressBarVariant.LUMO_ERROR));
|
||||||
|
winRateFrontText.setText(winRate.isNaN() ? text + "-" : text + String.format("%.2f", winRate * 100) + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBackWinrate(Spieler s) {
|
||||||
|
String text = "Winrate hinten: ";
|
||||||
|
Float winRate = stat2vs2Service.getWinrate(s, Position.BACK);
|
||||||
|
winRateBack.setValue(winRate);
|
||||||
|
winRateBack.removeThemeVariants(ProgressBarVariant.LUMO_SUCCESS, ProgressBarVariant.LUMO_ERROR);
|
||||||
|
winRateBack.addThemeVariants((winRate > 0.5f ? ProgressBarVariant.LUMO_SUCCESS : ProgressBarVariant.LUMO_ERROR));
|
||||||
|
winRateBackText.setText(winRate.isNaN() ? text + "-" : text + String.format("%.2f", winRate * 100) + "%");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user