...
 
Commits (2)
......@@ -41,7 +41,7 @@ public class StageSerialization extends AbstractEntitySerializer<Stage> {
final StageType type = stage.getType();
stageSerialization.put("type", type.toString());
if (type == StageType.GR) {
if (type.isGroup()) {
stageSerialization.put(
"groups",
stage.getGroups().stream().map(group -> groupSerialization.serialize(group, uuid))
......
package de.fearnixx.jeak.tournament.encounter;
import de.fearnixx.jeak.tournament.entities.encounter.Encounter;
import de.fearnixx.jeak.tournament.entities.encounter.EncounterParticipation;
import de.fearnixx.jeak.tournament.entities.stage.Stage;
import de.fearnixx.jeak.tournament.entities.team.Team;
import java.util.List;
import java.util.stream.Collectors;
public abstract class AbstractStageCreator {
......@@ -19,8 +16,4 @@ public abstract class AbstractStageCreator {
public abstract void createStage(List<Team> participatingTeams, Stage stage);
protected abstract boolean validateParams(List<Integer> params);
protected List<EncounterParticipation> generateEncounterParticipation(Encounter encounter, List<Team> participatingTeams) {
return participatingTeams.stream().map(encounter::createEncounterParticipation).collect(Collectors.toList());
}
}
......@@ -39,6 +39,7 @@ public class GroupStageCreator extends AbstractStageCreator {
generateGroupsByTeamsPerGroup(participatingTeams, stage);
}
stage.setWinningTeamsPerEncounter(winningTeamsPerEncounter);
generateStageFromGroups(stage);
}
......@@ -85,11 +86,9 @@ public class GroupStageCreator extends AbstractStageCreator {
}
}
private void generateStageFromGroups(Stage stage) {
protected void generateStageFromGroups(Stage stage) {
final List<Group> groups = stage.getGroups();
stage.setWinningTeamsPerEncounter(winningTeamsPerEncounter);
for (Group group : groups) {
List<Team> teamsOfGroup = group.getTeams();
......
......@@ -15,6 +15,8 @@ public class StageCreatorFactory {
return new KoStageCreator(params);
case GR:
return new GroupStageCreator(params);
case TFT:
return new TftStageCreator(params);
default:
throw new IllegalArgumentException("StageType not known!");
}
......
package de.fearnixx.jeak.tournament.encounter;
import de.fearnixx.jeak.tournament.entities.encounter.Encounter;
import de.fearnixx.jeak.tournament.entities.stage.Group;
import de.fearnixx.jeak.tournament.entities.stage.Stage;
import java.util.List;
public class TftStageCreator extends GroupStageCreator {
public TftStageCreator(List<Integer> params) {
super(params);
}
@Override
protected void generateStageFromGroups(Stage stage) {
for (Group group : stage.getGroups()) {
final Encounter encounter = stage.createEncounter();
encounter.createEncounterParticipations(group.getTeams());
}
}
}
......@@ -169,6 +169,10 @@ public class Encounter {
}
public void forfeit(Team team) {
if (getTeams().size() > 2) {
throw new IllegalStateException("Cannot forfeit an encounter with more than 2 participants. Enter a score of 0 instead!");
}
final List<Team> otherTeams = getTeams().stream()
.filter(otherTeam -> !otherTeam.equals(team))
.collect(Collectors.toList());
......
......@@ -137,7 +137,7 @@ public class Match implements Serializable {
private void refreshGroup() {
final Stage stage = encounter.getStage();
if (stage.getType() == StageType.GR) {
if (stage.getType().isGroup()) {
final Team team = matchScores.get(0).getEncounterParticipation().getTeam();
final Group group = stage.optGroup(team).orElseThrow(
......
package de.fearnixx.jeak.tournament.entities.stage;
import de.fearnixx.jeak.tournament.entities.team.Team;
import de.fearnixx.jeak.tournament.entities.tournament.TournamentParameter;
import javax.persistence.*;
import java.util.ArrayList;
......@@ -59,30 +60,7 @@ public class Group {
public List<GroupMembership> getMembershipsSorted() {
final ArrayList<GroupMembership> groupMemberships = new ArrayList<>(memberships);
groupMemberships.sort(
(a, b) -> {
int compA = a.getPoints();
int compB = b.getPoints();
if (compA != compB) {
return compB - compA;
}
compA = a.getEncountersWon();
compB = b.getEncountersWon();
if (compA != compB) {
return compB - compA;
}
compA = a.getMatchesWon();
compB = b.getMatchesWon();
if (compA != compB) {
return compB - compA;
}
return b.getRoundsWon() - a.getRoundsWon();
}
);
sortMemberships(groupMemberships);
return groupMemberships;
}
......@@ -118,6 +96,13 @@ public class Group {
}
final ArrayList<GroupMembership> groupMembers = new ArrayList<>(getMemberships());
sortMemberships(groupMembers);
groupMembers.subList(0, winningTeamCount).forEach(gm -> gm.setGroupWon(true));
groupMembers.subList(winningTeamCount, groupMembers.size()).forEach(gm -> gm.setGroupWon(false));
}
private void sortMemberships(ArrayList<GroupMembership> groupMembers) {
groupMembers.sort(
(a, b) -> {
int compA = a.getPoints();
......@@ -138,12 +123,24 @@ public class Group {
return compB - compA;
}
if (stage.getTournament().optParameter(TournamentParameter.GAME_TIME_TRACKING).isPresent()) {
//Game-Time-Tracking-Mode: Lower Avg. Round-Score of won games is better.
//Precondition: Only won matches contain a score (the game time)
if (compA == 0) {
//Nobody won any match => no sort
return 0;
}
float compTimeA = (float) a.getRoundsWon() / a.getMatchesWon();
float compTimeB = (float) b.getRoundsWon() / b.getMatchesWon();
return Float.compare(compTimeA, compTimeB);
}
return b.getRoundsWon() - a.getRoundsWon();
}
);
groupMembers.subList(0, winningTeamCount).forEach(gm -> gm.setGroupWon(true));
groupMembers.subList(winningTeamCount, groupMembers.size()).forEach(gm -> gm.setGroupWon(false));
}
public List<Team> getTeams() {
......
......@@ -115,7 +115,7 @@ public class Stage {
}
public List<Group> getGroups() {
if (this.getType() != StageType.GR) {
if (!this.getType().isGroup()) {
throw new IllegalStateException("Tried to access a group in a stage which is not a group stage!");
}
......@@ -123,7 +123,7 @@ public class Stage {
}
public Optional<Group> optGroup(Team team) {
if (this.getType() != StageType.GR) {
if (!this.getType().isGroup()) {
throw new IllegalStateException("Tried to access a group in a stage which is not a group stage!");
}
......
......@@ -7,6 +7,7 @@ import javax.persistence.*;
public class TournamentParameter {
public static final String STAGE_PATTERN = "stage_pattern";
public static final String GAME_TIME_TRACKING = "game_time_tracking";
public static final String MIN_TEAM_SIZE = "min_team_size";
public static final String MAX_TEAM_SIZE = "max_team_size";
......
......@@ -2,6 +2,20 @@ package de.fearnixx.jeak.tournament.enums;
public enum StageType {
KO,
GR,
UNDEFINED
GR(true),
TFT(true),
UNDEFINED;
boolean isGroup;
StageType() {
}
StageType(boolean isGroup) {
this.isGroup = isGroup;
}
public boolean isGroup() {
return isGroup;
}
}
\ No newline at end of file
......@@ -8,6 +8,7 @@ import de.fearnixx.jeak.tournament.entities.encounter.Match;
import de.fearnixx.jeak.tournament.entities.encounter.MatchScore;
import de.fearnixx.jeak.tournament.entities.team.Team;
import de.fearnixx.jeak.tournament.entities.tournament.Tournament;
import de.fearnixx.jeak.tournament.entities.tournament.TournamentParameter;
import de.fearnixx.jeak.tournament.enums.EncounterState;
import de.fearnixx.jeak.tournament.enums.StageState;
......@@ -247,6 +248,11 @@ public class EncounterManagement extends AbstractManagement {
return errors;
}
if (tournament.optParameter(TournamentParameter.GAME_TIME_TRACKING).isPresent() && scores.stream().filter(s -> s > 0).count() != 1) {
errors.put(POINTS_KEY, Collections.singletonList("There must exactly one non-zero score in game time tracking mode!"));
return errors;
}
Match match = encounter.createMatch();
List<MatchScore> matchScores = new ArrayList<>();
......@@ -281,7 +287,7 @@ public class EncounterManagement extends AbstractManagement {
final Optional<Match> optMatch = encounter.getMatches().stream().filter(m -> m.getId() == matchId).findFirst();
if(optMatch.isEmpty()){
if (optMatch.isEmpty()) {
return createSingleResult(MATCH_ID_KEY, "The encounter does not contain a match with the given index!");
}
......@@ -448,6 +454,7 @@ public class EncounterManagement extends AbstractManagement {
return getNotAllowedResponse();
}
final Optional<EncounterParticipation> optEncounterParticipation = encounter.optEncounterParticipation(team);
if (optEncounterParticipation.isEmpty()) {
......
......@@ -522,7 +522,7 @@ public class TournamentManagement extends AbstractManagement {
}
);
if (currentStage.getType() == StageType.GR) {
if (currentStage.getType().isGroup()) {
List<Group> groups = new ArrayList<>(currentStage.getGroups());
groups.forEach(
......
......@@ -20,7 +20,7 @@ public class StageProgressionDecider {
public void processStageProgression() {
if (stage.getState() != StageState.FINISHED) {
throw new IllegalStateException("Can't process a state progression of an unfinished state!");
throw new IllegalStateException("Can't process a state progression of an unfinished stage!");
}
List<TournamentParticipation> knockedOutTeams;
......@@ -35,6 +35,7 @@ public class StageProgressionDecider {
break;
case GR:
case TFT:
knockedOutTeams = stage.getGroups().stream()
.flatMap(group -> group.getMemberships().stream())
.filter(GroupMembership::isGroupLost)
......
......@@ -3,6 +3,7 @@ package de.fearnixx.jeak.tournament.management.services;
import de.fearnixx.jeak.reflect.Inject;
import de.fearnixx.jeak.tournament.entities.encounter.Encounter;
import de.fearnixx.jeak.tournament.entities.encounter.EncounterParticipation;
import de.fearnixx.jeak.tournament.entities.stage.GroupMembership;
import de.fearnixx.jeak.tournament.entities.stage.Stage;
import de.fearnixx.jeak.tournament.entities.team.Team;
import de.fearnixx.jeak.tournament.entities.tournament.Tournament;
......@@ -98,6 +99,21 @@ public class TournamentStageGenerationService {
)
);
if (stage.getType().isGroup()) {
stage.getGroups().forEach(
g -> {
final List<GroupMembership> groupResults = g.getMembershipsSorted();
for (int i = 1; i < groupResults.size(); i++) {
final TournamentParticipation tournamentParticipation = groupResults.get(i).getTournamentParticipation();
tournamentParticipation.setState(ParticipationState.KNOCKED_OUT);
tournamentParticipation.setLostStage(stage);
}
}
);
}
tournament.getTournamentParticipations().stream()
.filter(tp -> tp.getState() == ParticipationState.ACTIVE)
.forEach(tp -> tp.setState(ParticipationState.WON));
......