Skip to content

Commit

Permalink
Merge pull request #526 from softwaremagico/523-add-your-worst-enemy-…
Browse files Browse the repository at this point in the history
…statistic

523 add your worst enemy statistic
  • Loading branch information
softwaremagico authored Jan 8, 2025
2 parents b64f030 + 6277136 commit a0e91c8
Show file tree
Hide file tree
Showing 24 changed files with 457 additions and 19 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
[![GitHub commit activity](https://img.shields.io/github/commit-activity/y/softwaremagico/KendoTournamentManager)](https://github.com/softwaremagico/KendoTournamentManager)
[![GitHub last commit](https://img.shields.io/github/last-commit/softwaremagico/KendoTournamentManager)](https://github.com/softwaremagico/KendoTournamentManager)
[![CircleCI](https://circleci.com/gh/softwaremagico/KendoTournamentManager.svg?style=shield)](https://circleci.com/gh/softwaremagico/KendoTournamentManager)
[![Time](https://img.shields.io/badge/development-655.5h-blueviolet.svg)]()
[![Time](https://img.shields.io/badge/development-657h-blueviolet.svg)]()

[![Powered by](https://img.shields.io/badge/powered%20by%20java-orange.svg?logo=OpenJDK&logoColor=white)]()
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=kendo-tournament-backend&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=kendo-tournament-backend)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.softwaremagico.kt.core.converters.models.ParticipantConverterRequest;
import com.softwaremagico.kt.core.exceptions.TokenExpiredException;
import com.softwaremagico.kt.core.exceptions.UserNotFoundException;
import com.softwaremagico.kt.core.providers.DuelProvider;
import com.softwaremagico.kt.core.providers.ParticipantProvider;
import com.softwaremagico.kt.persistence.entities.Participant;
import com.softwaremagico.kt.persistence.repositories.ParticipantRepository;
Expand All @@ -40,10 +41,13 @@
public class ParticipantController extends BasicInsertableController<Participant, ParticipantDTO, ParticipantRepository,
ParticipantProvider, ParticipantConverterRequest, ParticipantConverter> {

private final DuelProvider duelProvider;


@Autowired
public ParticipantController(ParticipantProvider provider, ParticipantConverter converter) {
public ParticipantController(ParticipantProvider provider, ParticipantConverter converter, DuelProvider duelProvider) {
super(provider, converter);
this.duelProvider = duelProvider;
}

@Override
Expand Down Expand Up @@ -89,4 +93,14 @@ public Token generateToken(String temporalToken) {
}
}


public ParticipantDTO getYourWorstNightmare(ParticipantDTO participant) {
return convert(getProvider().getYourWorstNightmare(reverse(participant)));
}


public ParticipantDTO getYouAreTheWorstNightmareOf(ParticipantDTO participant) {
return convert(getProvider().getYouAreTheWorstNightmareOf(reverse(participant)));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
import com.softwaremagico.kt.core.controller.models.TemporalToken;
import com.softwaremagico.kt.logger.KendoTournamentLogger;
import com.softwaremagico.kt.persistence.entities.Club;
import com.softwaremagico.kt.persistence.entities.Duel;
import com.softwaremagico.kt.persistence.entities.Participant;
import com.softwaremagico.kt.persistence.entities.Tournament;
import com.softwaremagico.kt.persistence.repositories.DuelRepository;
import com.softwaremagico.kt.persistence.repositories.ParticipantRepository;
import com.softwaremagico.kt.persistence.values.AchievementGrade;
import com.softwaremagico.kt.persistence.values.AchievementType;
Expand All @@ -35,8 +37,10 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
Expand All @@ -46,9 +50,12 @@ public class ParticipantProvider extends CrudProvider<Participant, Integer, Part

public static final String TOKEN_NAME_SEPARATOR = "_";

private final DuelRepository duelRepository;

@Autowired
public ParticipantProvider(ParticipantRepository repository) {
public ParticipantProvider(ParticipantRepository repository, DuelRepository duelRepository) {
super(repository);
this.duelRepository = duelRepository;
}

public List<Participant> get(Tournament tournament) {
Expand Down Expand Up @@ -96,6 +103,10 @@ public List<Participant> get(Club club) {
return getRepository().findByClub(club);
}

public Participant getByIdCard(String idCard) {
return getRepository().findByIdCard(idCard);
}

public TemporalToken generateTemporalToken(Participant participant) {
do {
participant.generateTemporalToken();
Expand Down Expand Up @@ -129,4 +140,44 @@ public Optional<Participant> findByTokenUsername(String tokenUsername) {
KendoTournamentLogger.warning(this.getClass(), "Invalid id obtained from '{}'.", tokenUsername.replaceAll("[\n\r\t]", "_"));
return Optional.empty();
}

public Participant getYourWorstNightmare(Participant sourceParticipant) {
if (sourceParticipant == null) {
return null;
}
final List<Duel> duels = duelRepository.findByParticipant(sourceParticipant);
final Map<Participant, Integer> lostBy = new HashMap<>();
for (Duel duel : duels) {
final Participant winner = duel.getCompetitorWinner();
if (!Objects.equals(winner, sourceParticipant)) {
lostBy.put(winner, lostBy.getOrDefault(winner, 0) + 1);
}
}
final List<Map.Entry<Participant, Integer>> sortedLostBy = lostBy.entrySet().stream().sorted(Map.Entry.comparingByValue()).toList();
if (!sortedLostBy.isEmpty()) {
return sortedLostBy.get(0).getKey();
}
return null;
}


public Participant getYouAreTheWorstNightmareOf(Participant sourceParticipant) {
if (sourceParticipant == null) {
return null;
}
final List<Duel> duels = duelRepository.findByParticipant(sourceParticipant);
final Map<Participant, Integer> lostBy = new HashMap<>();
for (Duel duel : duels) {
final Participant winner = duel.getCompetitorWinner();
final Participant looser = duel.getCompetitorLooser();
if (Objects.equals(winner, sourceParticipant)) {
lostBy.put(looser, lostBy.getOrDefault(looser, 0) + 1);
}
}
final List<Map.Entry<Participant, Integer>> sortedLostBy = lostBy.entrySet().stream().sorted(Map.Entry.comparingByValue()).toList();
if (!sortedLostBy.isEmpty()) {
return sortedLostBy.get(0).getKey();
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class ParticipantFightStatistics {
private Long hansokuNumber;

private Long ipponNumber;

private Long fusenGachiNumber;

private Long receivedMenNumber;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
package com.softwaremagico.kt.core.tests;

/*-
* #%L
* Kendo Tournament Manager (Core)
* %%
* Copyright (C) 2021 - 2024 Softwaremagico
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/

import com.softwaremagico.kt.core.TournamentTestUtils;
import com.softwaremagico.kt.core.controller.FightController;
import com.softwaremagico.kt.core.controller.models.FightDTO;
import com.softwaremagico.kt.core.controller.models.TournamentDTO;
import com.softwaremagico.kt.core.managers.TeamsOrder;
import com.softwaremagico.kt.core.providers.ParticipantProvider;
import com.softwaremagico.kt.persistence.entities.Participant;
import com.softwaremagico.kt.persistence.values.Score;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import java.util.List;

@SpringBootTest
@Test(groups = {"worstNightmareTest"})
public class WorstNightmareTest extends TournamentTestUtils {
private static final int MEMBERS = 3;
private static final int TEAMS = 3;
private static final int REFEREES = 0;
private static final int ORGANIZER = 0;
private static final int VOLUNTEER = 0;
private static final int PRESS = 0;

private static final String TOURNAMENT1_NAME = "leagueTest1";
private static final String TOURNAMENT2_NAME = "leagueTest2";

private TournamentDTO tournament1DTO = null;
private TournamentDTO tournament2DTO = null;

@Autowired
private FightController fightController;

@Autowired
private ParticipantProvider participantProvider;

@BeforeClass
public void prepareData() {
addParticipants(MEMBERS, TEAMS, REFEREES, ORGANIZER, VOLUNTEER, PRESS, 0);
}

@BeforeClass(dependsOnMethods = "prepareData")
public void createTournaments() {
//Create Tournament
tournament1DTO = addTournament(TOURNAMENT1_NAME, MEMBERS, TEAMS, REFEREES, ORGANIZER, VOLUNTEER, PRESS, 0);
tournament2DTO = addTournament(TOURNAMENT2_NAME, MEMBERS, TEAMS, REFEREES, ORGANIZER, VOLUNTEER, PRESS, 0);
}

@BeforeClass(dependsOnMethods = "createTournaments")
public void prepareTournament1() {
List<FightDTO> fightDTOs = fightController.createFights(tournament1DTO.getId(), TeamsOrder.SORTED, 0, null);

//P0 vs P3
fightDTOs.get(0).getDuels().get(0).addCompetitor1Score(Score.KOTE);
fightDTOs.get(0).getDuels().get(0).addCompetitor1Score(Score.MEN);
fightDTOs.get(0).getDuels().get(0).setFinished(true);
fightDTOs.set(0, fightController.update(fightDTOs.get(0), null));

//P1 vs P4
fightDTOs.get(0).getDuels().get(1).addCompetitor1Score(Score.KOTE);
fightDTOs.get(0).getDuels().get(1).addCompetitor1Score(Score.MEN);
fightDTOs.get(0).getDuels().get(1).setFinished(true);
fightDTOs.set(0, fightController.update(fightDTOs.get(0), null));

//P2 vs P5
fightDTOs.get(0).getDuels().get(2).addCompetitor1Score(Score.KOTE);
fightDTOs.get(0).getDuels().get(2).addCompetitor1Score(Score.MEN);
fightDTOs.get(0).getDuels().get(2).setFinished(true);
fightDTOs.set(0, fightController.update(fightDTOs.get(0), null));

//P6 vs P3
fightDTOs.get(1).getDuels().get(0).addCompetitor1Score(Score.KOTE);
fightDTOs.get(1).getDuels().get(0).addCompetitor1Score(Score.MEN);
fightDTOs.get(1).getDuels().get(0).setFinished(true);
fightDTOs.set(1, fightController.update(fightDTOs.get(0), null));

//P7 vs P4
fightDTOs.get(1).getDuels().get(1).addCompetitor1Score(Score.KOTE);
fightDTOs.get(1).getDuels().get(1).addCompetitor1Score(Score.MEN);
fightDTOs.get(1).getDuels().get(1).setFinished(true);
fightDTOs.set(1, fightController.update(fightDTOs.get(0), null));

//P8 vs P5
fightDTOs.get(1).getDuels().get(2).addCompetitor1Score(Score.KOTE);
fightDTOs.get(1).getDuels().get(2).addCompetitor1Score(Score.MEN);
fightDTOs.get(1).getDuels().get(2).setFinished(true);
fightDTOs.set(1, fightController.update(fightDTOs.get(0), null));

//P6 vs P0
fightDTOs.get(2).getDuels().get(0).addCompetitor1Score(Score.KOTE);
fightDTOs.get(2).getDuels().get(0).addCompetitor1Score(Score.MEN);
fightDTOs.get(2).getDuels().get(0).setFinished(true);
fightDTOs.set(2, fightController.update(fightDTOs.get(0), null));

//P7 vs P1
fightDTOs.get(2).getDuels().get(1).addCompetitor1Score(Score.KOTE);
fightDTOs.get(2).getDuels().get(1).addCompetitor1Score(Score.MEN);
fightDTOs.get(2).getDuels().get(1).setFinished(true);
fightDTOs.set(2, fightController.update(fightDTOs.get(0), null));

//P8 vs P2
fightDTOs.get(2).getDuels().get(2).addCompetitor1Score(Score.KOTE);
fightDTOs.get(2).getDuels().get(2).addCompetitor1Score(Score.MEN);
fightDTOs.get(2).getDuels().get(2).setFinished(true);
fightDTOs.set(2, fightController.update(fightDTOs.get(0), null));
}

@BeforeClass(dependsOnMethods = "createTournaments")
public void prepareTournament2() {
List<FightDTO> fightDTOs = fightController.createFights(tournament2DTO.getId(), TeamsOrder.SORTED, 0, null);

//P0 vs P3
fightDTOs.get(0).getDuels().get(0).setFinished(true);
fightDTOs.set(0, fightController.update(fightDTOs.get(0), null));

//P1 vs P4
fightDTOs.get(0).getDuels().get(1).addCompetitor1Score(Score.KOTE);
fightDTOs.get(0).getDuels().get(1).addCompetitor1Score(Score.MEN);
fightDTOs.get(0).getDuels().get(1).setFinished(true);
fightDTOs.set(0, fightController.update(fightDTOs.get(0), null));

//P2 vs P5
fightDTOs.get(0).getDuels().get(2).addCompetitor1Score(Score.KOTE);
fightDTOs.get(0).getDuels().get(2).addCompetitor1Score(Score.MEN);
fightDTOs.get(0).getDuels().get(2).setFinished(true);
fightDTOs.set(0, fightController.update(fightDTOs.get(0), null));

//P6 vs P3
fightDTOs.get(1).getDuels().get(0).addCompetitor1Score(Score.KOTE);
fightDTOs.get(1).getDuels().get(0).addCompetitor1Score(Score.MEN);
fightDTOs.get(1).getDuels().get(0).setFinished(true);
fightDTOs.set(1, fightController.update(fightDTOs.get(0), null));

//P7 vs P4
fightDTOs.get(1).getDuels().get(1).addCompetitor2Score(Score.KOTE);
fightDTOs.get(1).getDuels().get(1).setFinished(true);
fightDTOs.set(1, fightController.update(fightDTOs.get(0), null));

//P8 vs P5
fightDTOs.get(1).getDuels().get(2).addCompetitor1Score(Score.KOTE);
fightDTOs.get(1).getDuels().get(2).addCompetitor1Score(Score.MEN);
fightDTOs.get(1).getDuels().get(2).setFinished(true);
fightDTOs.set(1, fightController.update(fightDTOs.get(0), null));

//P6 vs P0
fightDTOs.get(2).getDuels().get(0).addCompetitor1Score(Score.KOTE);
fightDTOs.get(2).getDuels().get(0).addCompetitor1Score(Score.MEN);
fightDTOs.get(2).getDuels().get(0).setFinished(true);
fightDTOs.set(2, fightController.update(fightDTOs.get(0), null));

//P7 vs P1
fightDTOs.get(2).getDuels().get(1).addCompetitor1Score(Score.KOTE);
fightDTOs.get(2).getDuels().get(1).addCompetitor1Score(Score.MEN);
fightDTOs.get(2).getDuels().get(1).setFinished(true);
fightDTOs.set(2, fightController.update(fightDTOs.get(0), null));

//P8 vs P2
fightDTOs.get(2).getDuels().get(2).addCompetitor1Score(Score.KOTE);
fightDTOs.get(2).getDuels().get(2).addCompetitor1Score(Score.MEN);
fightDTOs.get(2).getDuels().get(2).setFinished(true);
fightDTOs.set(2, fightController.update(fightDTOs.get(0), null));
}

@Test
public void checkYourWorstNightmare() {
final Participant participant1 = participantProvider.getByIdCard("0001");
final Participant participant3 = participantProvider.getByIdCard("0003");
final Participant participant4 = participantProvider.getByIdCard("0004");
final Participant participant6 = participantProvider.getByIdCard("0006");
Assert.assertEquals(participantProvider.getYourWorstNightmare(participant3), participant6);
Assert.assertEquals(participantProvider.getYourWorstNightmare(participant4), participant1);
}

@Test
public void checkWorstNightmareOf() {
final Participant participant1 = participantProvider.getByIdCard("0001");
final Participant participant3 = participantProvider.getByIdCard("0003");
final Participant participant4 = participantProvider.getByIdCard("0004");
final Participant participant6 = participantProvider.getByIdCard("0006");
Assert.assertEquals(participantProvider.getYouAreTheWorstNightmareOf(participant6), participant3);
Assert.assertEquals(participantProvider.getYouAreTheWorstNightmareOf(participant1), participant4);
}

@AfterClass(alwaysRun = true)
public void wipeOut() {
super.wipeOut();
}

}
2 changes: 2 additions & 0 deletions backend/kendo-tournament-core/src/test/resources/testng.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<include name="numberOfWinners"/>
<include name="tournamentExtraProperties"/>
<include name="qrTest"/>
<include name="worstNightmareTest"/>
</run>
</groups>
<classes>
Expand Down Expand Up @@ -63,6 +64,7 @@
<class name="com.softwaremagico.kt.core.tests.NumberOfWinnersTest"/>
<class name="com.softwaremagico.kt.core.tests.TournamentExtraPropertiesTest"/>
<class name="com.softwaremagico.kt.core.tests.QrTests"/>
<class name="com.softwaremagico.kt.core.tests.WorstNightmareTest"/>
</classes>
</test>
</suite>
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,15 @@ public Participant getCompetitorWinner() {
return null;
}

public Participant getCompetitorLooser() {
if (getWinner() < 0) {
return getCompetitor2();
} else if (getWinner() > 0) {
return getCompetitor1();
}
return null;
}

public Integer getCompetitor1ScoreValue() {
return (int) competitor1Score.stream().filter(Score::isValidPoint).count();
}
Expand Down
Loading

0 comments on commit a0e91c8

Please sign in to comment.