mirror of
https://github.com/AJMicke/KickerELO.git
synced 2026-03-11 13:31:02 +01:00
Show player elo change in match history
This commit is contained in:
committed by
AJMicke
parent
4ed29fb20e
commit
0e64e0fd02
@@ -12,13 +12,19 @@ public class EloCalculationService {
|
||||
private final float initialElo1vs1 = 1500;
|
||||
private final float initialElo2vs2 = 1500;
|
||||
|
||||
private final EloChangeService eloChangeService;
|
||||
|
||||
EloCalculationService(EloChangeService eloChangeService) {
|
||||
this.eloChangeService = eloChangeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
public void updateElo1vs1(long gameId, Spieler gewinner, Spieler verlierer, short toreVerlierer) {
|
||||
final float baseK = 50;
|
||||
final float reductionPerGoal = 0.1f * baseK;
|
||||
final float finalK = baseK - (reductionPerGoal * toreVerlierer);
|
||||
@@ -28,17 +34,20 @@ public class EloCalculationService {
|
||||
|
||||
gewinner.setElo1vs1(gewinner.getElo1vs1() + eloChange);
|
||||
verlierer.setElo1vs1(verlierer.getElo1vs1() - eloChange);
|
||||
|
||||
eloChangeService.put1vs1Result(gameId, eloChange, -eloChange);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the 2 vs 2 ELOs of the players according to the result of the game
|
||||
* @param gameId ID 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) {
|
||||
public void updateElo2vs2(long gameId, Spieler gewinnerVorn, Spieler gewinnerHinten, Spieler verliererVorn, Spieler verliererHinten, short toreVerlierer) {
|
||||
final float baseK = 100;
|
||||
final double adjustedK = baseK * (1 - (0.1 * toreVerlierer));
|
||||
var totalWinnerElo = gewinnerVorn.getElo2vs2() + gewinnerHinten.getElo2vs2();
|
||||
@@ -60,6 +69,8 @@ public class EloCalculationService {
|
||||
gewinnerHinten.setElo2vs2((float) (gewinnerHinten.getElo2vs2() + winner2EloChange));
|
||||
verliererVorn.setElo2vs2((float) (verliererVorn.getElo2vs2() + loser1EloChange));
|
||||
verliererHinten.setElo2vs2((float) (verliererHinten.getElo2vs2() + loser2EloChange));
|
||||
|
||||
eloChangeService.put2vs2Result(gameId, winner1EloChange, winner2EloChange, loser1EloChange, loser2EloChange);
|
||||
}
|
||||
|
||||
public float getInitialElo1vs1() {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.kickerelo.kickerelo.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class EloChangeService {
|
||||
public record UpdateElo1vs1Change(double winnerEloChange, double loserEloChange) {
|
||||
}
|
||||
public record UpdateElo2vs2Change(double winnerFrontEloChange, double winnerBackEloChange, double loserFrontEloChange, double loserBackEloChange) {
|
||||
}
|
||||
|
||||
Map<Long, UpdateElo1vs1Change> changes1vs1 = new HashMap<>();
|
||||
Map<Long, UpdateElo2vs2Change> changes2vs2 = new HashMap<>();
|
||||
|
||||
public void put1vs1Result(long gameId, double winnerEloChange, double loserEloChange) {
|
||||
changes1vs1.put(gameId, new UpdateElo1vs1Change(winnerEloChange, loserEloChange));
|
||||
}
|
||||
|
||||
public void put2vs2Result(long gameId, double winnerFrontEloChange, double winnerBackEloChange, double loserFrontEloChange, double loserBackEloChange) {
|
||||
changes2vs2.put(gameId, new UpdateElo2vs2Change(winnerFrontEloChange, winnerBackEloChange, loserFrontEloChange, loserBackEloChange));
|
||||
}
|
||||
|
||||
public UpdateElo1vs1Change get1vs1Result(long gameId) {
|
||||
var result = changes1vs1.get(gameId);
|
||||
assert result != null;
|
||||
return result;
|
||||
}
|
||||
|
||||
public UpdateElo2vs2Change get2vs2Result(long gameId) {
|
||||
var result = changes2vs2.get(gameId);
|
||||
assert result != null;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -24,15 +24,23 @@ import java.util.stream.Stream;
|
||||
*/
|
||||
@Service
|
||||
public class KickerEloService {
|
||||
@Autowired
|
||||
private Ergebnis1vs1Repository ergebnis1vs1Repository;
|
||||
@Autowired
|
||||
private Ergebnis2vs2Repository ergebnis2vs2Repository;
|
||||
@Autowired
|
||||
private SpielerRepository spielerRepository;
|
||||
@Autowired
|
||||
private EloCalculationService eloCalculationService;
|
||||
|
||||
public KickerEloService(Ergebnis1vs1Repository ergebnis1vs1Repository,
|
||||
Ergebnis2vs2Repository ergebnis2vs2Repository,
|
||||
SpielerRepository spielerRepository,
|
||||
EloCalculationService eloCalculationService) {
|
||||
this.ergebnis1vs1Repository = ergebnis1vs1Repository;
|
||||
this.ergebnis2vs2Repository = ergebnis2vs2Repository;
|
||||
this.spielerRepository = spielerRepository;
|
||||
this.eloCalculationService = eloCalculationService;
|
||||
recalculateAll1vs1();
|
||||
recalculateAll2vs2();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return List of all player names sorted alphabetically
|
||||
*/
|
||||
@@ -70,7 +78,7 @@ public class KickerEloService {
|
||||
Ergebnis1vs1 ergebnis = new Ergebnis1vs1(gewinner, verlierer, toreVerlierer);
|
||||
ergebnis1vs1Repository.save(ergebnis);
|
||||
|
||||
eloCalculationService.updateElo1vs1(gewinner, verlierer, toreVerlierer);
|
||||
eloCalculationService.updateElo1vs1(ergebnis.getId(), gewinner, verlierer, toreVerlierer);
|
||||
spielerRepository.save(gewinner);
|
||||
spielerRepository.save(verlierer);
|
||||
}
|
||||
@@ -108,7 +116,7 @@ public class KickerEloService {
|
||||
Ergebnis2vs2 ergebnis = new Ergebnis2vs2(gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer);
|
||||
ergebnis2vs2Repository.save(ergebnis);
|
||||
|
||||
eloCalculationService.updateElo2vs2(gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer);
|
||||
eloCalculationService.updateElo2vs2(ergebnis.getId(), gewinnerVorn, gewinnerHinten, verliererVorn, verliererHinten, toreVerlierer);
|
||||
spielerRepository.save(gewinnerVorn);
|
||||
spielerRepository.save(gewinnerHinten);
|
||||
spielerRepository.save(verliererVorn);
|
||||
@@ -148,7 +156,8 @@ public class KickerEloService {
|
||||
}
|
||||
Stream<Ergebnis1vs1> results = ergebnis1vs1Repository.findAll().stream().sorted(new Ergebnis1vs1TimeComparator());
|
||||
results.forEach(r -> {
|
||||
eloCalculationService.updateElo1vs1(players.get(r.getGewinner().getId()),
|
||||
eloCalculationService.updateElo1vs1(r.getId(),
|
||||
players.get(r.getGewinner().getId()),
|
||||
players.get(r.getVerlierer().getId()),
|
||||
r.getToreVerlierer());
|
||||
});
|
||||
@@ -166,7 +175,8 @@ public class KickerEloService {
|
||||
}
|
||||
Stream<Ergebnis2vs2> results = ergebnis2vs2Repository.findAll().stream().sorted(new Ergebnis2vs2TimeComparator());
|
||||
results.forEach(r -> {
|
||||
eloCalculationService.updateElo2vs2(players.get(r.getGewinnerVorn().getId()),
|
||||
eloCalculationService.updateElo2vs2(r.getId(),
|
||||
players.get(r.getGewinnerVorn().getId()),
|
||||
players.get(r.getGewinnerHinten().getId()),
|
||||
players.get(r.getVerliererVorn().getId()),
|
||||
players.get(r.getVerliererHinten().getId()),
|
||||
|
||||
@@ -10,18 +10,30 @@ import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.data.provider.SortDirection;
|
||||
import com.vaadin.flow.data.renderer.ComponentRenderer;
|
||||
import com.vaadin.flow.data.renderer.LocalDateTimeRenderer;
|
||||
import com.vaadin.flow.data.value.ValueChangeMode;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import org.kickerelo.kickerelo.data.Ergebnis1vs1;
|
||||
import org.kickerelo.kickerelo.repository.Ergebnis1vs1Repository;
|
||||
import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository;
|
||||
import org.kickerelo.kickerelo.service.EloChangeService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.kickerelo.kickerelo.views.HistoryCommonView.formatEloChange;
|
||||
|
||||
@Route("history1vs1")
|
||||
public class History1vs1View extends VerticalLayout {
|
||||
|
||||
private final Ergebnis1vs1Repository repo;
|
||||
private final EloChangeService eloChangeService;
|
||||
|
||||
List<Ergebnis1vs1> res;
|
||||
public History1vs1View(Ergebnis1vs1Repository repo) {
|
||||
public History1vs1View(Ergebnis1vs1Repository repo, EloChangeService eloChangeService) {
|
||||
this.repo = repo;
|
||||
this.eloChangeService = eloChangeService;
|
||||
|
||||
setSizeFull();
|
||||
H2 subheading = new H2("Spiele 1 vs 1");
|
||||
res = repo.findAll();
|
||||
@@ -49,8 +61,10 @@ public class History1vs1View extends VerticalLayout {
|
||||
grid.removeColumnByKey("id");
|
||||
Grid.Column<Ergebnis1vs1> winnerColumn = grid.getColumnByKey("gewinner");
|
||||
winnerColumn.setHeader("Gewinner");
|
||||
winnerColumn.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis.getGewinner(), eloChangeService.get1vs1Result(ergebnis.getId()).winnerEloChange())));
|
||||
Grid.Column<Ergebnis1vs1> loserColumn = grid.getColumnByKey("verlierer");
|
||||
loserColumn.setHeader("Verlierer");
|
||||
loserColumn.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis.getVerlierer(), eloChangeService.get1vs1Result(ergebnis.getId()).loserEloChange())));
|
||||
Grid.Column<Ergebnis1vs1> goals = grid.getColumnByKey("toreVerlierer");
|
||||
goals.setHeader("Verlierertore");
|
||||
Grid.Column<Ergebnis1vs1> timestamp = grid.getColumnByKey("timestamp");
|
||||
|
||||
@@ -11,17 +11,27 @@ import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.component.textfield.TextField;
|
||||
import com.vaadin.flow.data.provider.SortDirection;
|
||||
import com.vaadin.flow.data.renderer.ComponentRenderer;
|
||||
import com.vaadin.flow.data.renderer.LocalDateTimeRenderer;
|
||||
import com.vaadin.flow.data.value.ValueChangeMode;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import org.kickerelo.kickerelo.data.Ergebnis2vs2;
|
||||
import org.kickerelo.kickerelo.repository.Ergebnis2vs2Repository;
|
||||
import org.kickerelo.kickerelo.service.EloChangeService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.kickerelo.kickerelo.views.HistoryCommonView.formatEloChange;
|
||||
|
||||
@Route("history2vs2")
|
||||
public class History2vs2View extends VerticalLayout {
|
||||
public History2vs2View(Ergebnis2vs2Repository repo) {
|
||||
|
||||
private final Ergebnis2vs2Repository repo;
|
||||
private final EloChangeService eloChangeService;
|
||||
|
||||
public History2vs2View(Ergebnis2vs2Repository repo, EloChangeService eloChangeService) {
|
||||
this.repo = repo;
|
||||
this.eloChangeService = eloChangeService;
|
||||
setSizeFull();
|
||||
H2 subheading = new H2("Spiele 2 vs 2");
|
||||
List<Ergebnis2vs2> res = repo.findAll();
|
||||
@@ -63,12 +73,16 @@ public class History2vs2View extends VerticalLayout {
|
||||
grid.removeColumnByKey("id");
|
||||
Grid.Column<Ergebnis2vs2> winnerFront = grid.getColumnByKey("gewinnerVorn");
|
||||
winnerFront.setHeader("Gewinner vorne");
|
||||
winnerFront.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis.getGewinnerVorn(), eloChangeService.get2vs2Result(ergebnis.getId()).winnerFrontEloChange())));
|
||||
Grid.Column<Ergebnis2vs2> winnerBack = grid.getColumnByKey("gewinnerHinten");
|
||||
winnerBack.setHeader("Gewinner hinten");
|
||||
winnerBack.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis.getGewinnerHinten(), eloChangeService.get2vs2Result(ergebnis.getId()).winnerBackEloChange())));
|
||||
Grid.Column<Ergebnis2vs2> loserFront = grid.getColumnByKey("verliererVorn");
|
||||
loserFront.setHeader("Verlierer vorne");
|
||||
loserFront.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis.getVerliererVorn(), eloChangeService.get2vs2Result(ergebnis.getId()).loserFrontEloChange())));
|
||||
Grid.Column<Ergebnis2vs2> loserBack = grid.getColumnByKey("verliererHinten");
|
||||
loserBack.setHeader("Verlierer hinten");
|
||||
loserBack.setRenderer(new ComponentRenderer<>(ergebnis -> formatEloChange(ergebnis.getVerliererHinten(), eloChangeService.get2vs2Result(ergebnis.getId()).loserBackEloChange())));
|
||||
Grid.Column<Ergebnis2vs2> goals = grid.getColumnByKey("toreVerlierer");
|
||||
goals.setHeader("Verlierertore");
|
||||
Grid.Column<Ergebnis2vs2> timestamp = grid.getColumnByKey("timestamp");
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.kickerelo.kickerelo.views;
|
||||
|
||||
import com.vaadin.flow.component.html.Div;
|
||||
import com.vaadin.flow.component.html.Span;
|
||||
import org.kickerelo.kickerelo.data.Spieler;
|
||||
|
||||
public class HistoryCommonView {
|
||||
private HistoryCommonView() {}
|
||||
|
||||
static Div formatEloChange(Spieler spieler, double change) {
|
||||
Div div = new Div();
|
||||
|
||||
Span nameSpan = new Span(spieler.getName() + " ");
|
||||
String formattedChange = String.format("%+.2f", change);
|
||||
Span changeSpan = new Span(formattedChange);
|
||||
|
||||
changeSpan.getStyle().set("color", "var(--lumo-secondary-text-color)");
|
||||
changeSpan.getStyle().set("font-style", "italic");
|
||||
|
||||
div.add(nameSpan, changeSpan);
|
||||
|
||||
return div;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user