Skip to content

Commit

Permalink
Merge pull request #444 from softwaremagico/443-show-all-fights-from-…
Browse files Browse the repository at this point in the history
…a-competitor

443 show all fights from a competitor
  • Loading branch information
softwaremagico authored May 20, 2024
2 parents 15dbf29 + 0133040 commit babe617
Show file tree
Hide file tree
Showing 31 changed files with 460 additions and 28 deletions.
7 changes: 4 additions & 3 deletions 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-619.5h-blueviolet.svg)]()
[![Time](https://img.shields.io/badge/development-622h-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 Expand Up @@ -59,7 +59,7 @@ one for the backend.
#### Deploy the frontend

For the frontend, you can use any web server you are familiar with (Apache, Nginx, ...).
Simply uncompress the file `kendo-tournament-frontend.zip` on the server as a standard web page.
Decompress the file `kendo-tournament-frontend.zip` on the server as a standard web page.

#### Deploy the backend

Expand Down Expand Up @@ -131,7 +131,8 @@ application and probably the easiest way if you feel comfortable using docker.
### Hosting

The application has been tested in a Raspberry Pi 3 model B with 1GB of RAM, with a great response for a small to
medium size event. For a bigger events, please consider to adquire some more specific hardware hosted on the cloud.
medium size event.
For a bigger events, please consider acquiring some more specific hardware hosted in the cloud.

### Client Side

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,16 @@
import com.softwaremagico.kt.core.converters.models.FightConverterRequest;
import com.softwaremagico.kt.core.converters.models.TournamentConverterRequest;
import com.softwaremagico.kt.core.exceptions.FightNotFoundException;
import com.softwaremagico.kt.core.exceptions.ParticipantNotFoundException;
import com.softwaremagico.kt.core.exceptions.TournamentNotFoundException;
import com.softwaremagico.kt.core.exceptions.ValidateBadRequestException;
import com.softwaremagico.kt.core.providers.DuelProvider;
import com.softwaremagico.kt.core.providers.FightProvider;
import com.softwaremagico.kt.core.providers.ParticipantProvider;
import com.softwaremagico.kt.core.providers.TournamentProvider;
import com.softwaremagico.kt.persistence.entities.Duel;
import com.softwaremagico.kt.persistence.entities.Fight;
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.values.Score;
Expand All @@ -61,6 +64,8 @@ public class DuelController extends BasicInsertableController<Duel, DuelDTO, Due

private final TournamentProvider tournamentProvider;

private final ParticipantProvider participantProvider;

private final Set<ShiaijoFinishedListener> shiaijoFinishedListeners = new HashSet<>();
private final Set<FightUpdatedListener> fightsUpdatedListeners = new HashSet<>();

Expand All @@ -76,12 +81,15 @@ public interface FightUpdatedListener {
public DuelController(DuelProvider provider,
DuelConverter converter,
TournamentConverter tournamentConverter,
FightProvider fightProvider, FightConverter fightConverter, TournamentProvider tournamentProvider) {
FightProvider fightProvider, FightConverter fightConverter,
TournamentProvider tournamentProvider,
ParticipantProvider participantProvider) {
super(provider, converter);
this.tournamentConverter = tournamentConverter;
this.fightProvider = fightProvider;
this.fightConverter = fightConverter;
this.tournamentProvider = tournamentProvider;
this.participantProvider = participantProvider;
}

public void addShiaijoFinishedListener(ShiaijoFinishedListener listener) {
Expand Down Expand Up @@ -152,6 +160,13 @@ public List<DuelDTO> getUntiesFromTournament(Integer tournamentId) {
return convertAll(getProvider().getUntiesFromTournament(tournamentId));
}

public List<DuelDTO> getUntiesFromParticipant(Integer participantId) {
final Participant participant = participantProvider.get(participantId).orElseThrow(() ->
new ParticipantNotFoundException(this.getClass(), "No participant found with id '" + participantId + "'."));

return convertAll(getProvider().getUntiesFromParticipant(participant));
}

public long count(TournamentDTO tournament) {
return getProvider().count(tournamentConverter.reverse(tournament));
}
Expand All @@ -160,4 +175,15 @@ public void delete(TournamentDTO tournamentDTO) {
getProvider().delete(tournamentConverter.reverse(tournamentDTO));
}

public List<DuelDTO> getBy(Integer participantId) {
final Participant participant = participantProvider.get(participantId).orElseThrow(() ->
new ParticipantNotFoundException(this.getClass(), "No participant found with id '" + participantId + "'."));

return getBy(participant);
}

public List<DuelDTO> getBy(Participant participant) {
return convertAll(getProvider().get(participant));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,21 @@
import com.softwaremagico.kt.core.converters.TournamentConverter;
import com.softwaremagico.kt.core.converters.models.FightConverterRequest;
import com.softwaremagico.kt.core.converters.models.TournamentConverterRequest;
import com.softwaremagico.kt.core.exceptions.ParticipantNotFoundException;
import com.softwaremagico.kt.core.exceptions.TournamentNotFoundException;
import com.softwaremagico.kt.core.exceptions.ValidateBadRequestException;
import com.softwaremagico.kt.core.managers.TeamsOrder;
import com.softwaremagico.kt.core.providers.FightProvider;
import com.softwaremagico.kt.core.providers.GroupProvider;
import com.softwaremagico.kt.core.providers.ParticipantProvider;
import com.softwaremagico.kt.core.providers.TournamentExtraPropertyProvider;
import com.softwaremagico.kt.core.providers.TournamentProvider;
import com.softwaremagico.kt.core.tournaments.ITournamentManager;
import com.softwaremagico.kt.core.tournaments.TournamentHandlerSelector;
import com.softwaremagico.kt.logger.ExceptionType;
import com.softwaremagico.kt.persistence.entities.Fight;
import com.softwaremagico.kt.persistence.entities.Group;
import com.softwaremagico.kt.persistence.entities.Participant;
import com.softwaremagico.kt.persistence.entities.Team;
import com.softwaremagico.kt.persistence.entities.Tournament;
import com.softwaremagico.kt.persistence.entities.TournamentExtraProperty;
Expand All @@ -64,6 +67,7 @@ public class FightController extends BasicInsertableController<Fight, FightDTO,
private final TournamentHandlerSelector tournamentHandlerSelector;
private final Set<FightsAddedListener> fightsAddedListeners = new HashSet<>();
private final TournamentExtraPropertyProvider tournamentExtraPropertyProvider;
private final ParticipantProvider participantProvider;

private final GroupProvider groupProvider;
private final TeamConverter teamConverter;
Expand All @@ -76,13 +80,15 @@ public interface FightsAddedListener {
@Autowired
public FightController(FightProvider provider, FightConverter converter, TournamentConverter tournamentConverter,
TournamentProvider tournamentProvider, TournamentHandlerSelector tournamentHandlerSelector,
TournamentExtraPropertyProvider tournamentExtraPropertyProvider, GroupProvider groupProvider,
TournamentExtraPropertyProvider tournamentExtraPropertyProvider,
ParticipantProvider participantProvider, GroupProvider groupProvider,
TeamConverter teamConverter) {
super(provider, converter);
this.tournamentConverter = tournamentConverter;
this.tournamentProvider = tournamentProvider;
this.tournamentHandlerSelector = tournamentHandlerSelector;
this.tournamentExtraPropertyProvider = tournamentExtraPropertyProvider;
this.participantProvider = participantProvider;
this.groupProvider = groupProvider;
this.teamConverter = teamConverter;
}
Expand Down Expand Up @@ -229,4 +235,15 @@ public List<FightDTO> createNextFights(Integer tournamentId, String createdBy) {
return new ArrayList<>();
}

public List<FightDTO> getBy(Integer participantId) {
final Participant participant = participantProvider.get(participantId).orElseThrow(() ->
new ParticipantNotFoundException(this.getClass(), "No participant found with id '" + participantId + "'."));

return getBy(participant);
}

public List<FightDTO> getBy(Participant participant) {
return convertAll(getProvider().getBy(Collections.singletonList(participant)));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,8 @@ public List<Duel> getUntiesFromGroup(Integer groupId) {
return group.getUnties();
}

public List<Duel> getUntiesFromParticipant(Participant participant) {
return getRepository().findUntiesByParticipantIn(Collections.singletonList(participant));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ private PdfPTable fightTable(FightDTO fightDTO, boolean first) throws DocumentEx
name = NameUtils.getLastnameNameIni(competitor);
}

final PdfPCell team1NameCell = getCell(name, FIGHT_BORDER, PdfTheme.getHandwrittenFont(), PdfTheme.SCORE_LIST_SIZE, Color.WHITE, 1, Element.ALIGN_LEFT);
final PdfPCell team1NameCell = getCell(name, FIGHT_BORDER, PdfTheme.getHandwrittenFont(),
PdfTheme.SCORE_LIST_SIZE, Color.WHITE, 1, Element.ALIGN_LEFT);
team1NameCell.setBorder(PdfPCell.BOTTOM);
table.addCell(team1NameCell);

Expand Down Expand Up @@ -165,7 +166,8 @@ private PdfPTable fightTable(FightDTO fightDTO, boolean first) throws DocumentEx
}

public PdfPCell getTeamHeader(String text, int colspan) {
final PdfPCell cell = getCell(text, 0, colspan, Element.ALIGN_CENTER, Color.WHITE, PdfTheme.getTitleFont(), PdfTheme.FONT_SIZE + FONT_SMALL_EXTRA_SIZE, Font.BOLD);
final PdfPCell cell = getCell(text, 0, colspan, Element.ALIGN_CENTER, Color.WHITE,
PdfTheme.getTitleFont(), PdfTheme.FONT_SIZE + FONT_SMALL_EXTRA_SIZE, Font.BOLD);
cell.setPaddingBottom(BOTTOM_PADDING);
return cell;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ SELECT SUM(CASE WHEN d.competitor1Fault=:status THEN 1 ELSE 0 END) + SUM(CASE WH
List<Duel> findByTournamentAndCompetitor1ScoreTimeLessThanEqualOrCompetitor2ScoreTimeLessThanEqual(Tournament tournament,
int score1MaxDuration, int score2MaxDuration);

@Query("SELECT d FROM Duel d WHERE d.competitor1=:participant OR d.competitor2=:participant")
@Query("SELECT d FROM Duel d WHERE d.competitor1=:participant OR d.competitor2=:participant ORDER BY d.createdAt DESC")
List<Duel> findByParticipant(@Param("participant") Participant participant);

@Query("SELECT d FROM Duel d WHERE (d.competitor1=:participant1 AND d.competitor2=:participant2) "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ public List<DuelDTO> getUntiesFromGroup(@Parameter(description = "Id of the grou
return getController().getUntiesFromGroup(groupId);
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets all duels from competitor.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/competitor/{competitorId}", produces = MediaType.APPLICATION_JSON_VALUE)
public List<DuelDTO> getByCompetitor(@Parameter(description = "Id of the competitor.", required = true)
@PathVariable("competitorId")
Integer competitorId,
HttpServletRequest request) {
return getController().getBy(competitorId);
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets all untie duel.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/tournaments/{tournamentId}/unties", produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -68,4 +80,14 @@ public List<DuelDTO> getUntiesFromTournament(@Parameter(description = "Id of the
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets all untie duel where one participant is involved.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/participant/{participantId}/unties", produces = MediaType.APPLICATION_JSON_VALUE)
public List<DuelDTO> getUntiesFromParticipant(@Parameter(description = "Id of the participant.", required = true)
@PathVariable("participantId") Integer participantId,
HttpServletRequest request) {
return getController().getUntiesFromParticipant(participantId);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public FightServices(FightController fightController, PdfController pdfControlle
this.tournamentController = tournamentController;
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets all fights from a tournament.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/tournaments/{tournamentId}", produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -83,6 +84,7 @@ public List<FightDTO> getAll(@Parameter(description = "Id of an existing tournam
return getController().getByTournamentId(tournamentId);
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets all fights.", security = @SecurityRequirement(name = "bearerAuth"))
@PostMapping(value = "/tournaments", produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -91,6 +93,7 @@ public List<FightDTO> getAll(@RequestBody TournamentDTO tournamentDTO,
return getController().get(tournamentDTO);
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets all fights summary in a pdf file.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/tournaments/{tournamentId}/pdf", produces = MediaType.APPLICATION_PDF_VALUE)
Expand All @@ -109,6 +112,7 @@ public byte[] getTeamsScoreRankingFromTournamentAsPdf(@Parameter(description = "
}
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets current fight.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/tournaments/{tournamentId}/current", produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -117,6 +121,7 @@ public FightDTO getCurrent(@Parameter(description = "Id of an existing tournamen
return getController().getCurrent(tournamentId);
}


@Operation(summary = "Deletes a fight.", security = @SecurityRequirement(name = "bearerAuth"))
@ResponseStatus(HttpStatus.NO_CONTENT)
@DeleteMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -125,6 +130,7 @@ public void delete(@Parameter(description = "Id of an existing fight", required
getController().deleteById(id, authentication.getName());
}


@PreAuthorize("hasAnyRole('ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Deletes all fights from a tournament.", security = @SecurityRequirement(name = "bearerAuth"))
@ResponseStatus(HttpStatus.NO_CONTENT)
Expand All @@ -133,6 +139,7 @@ public void delete(@RequestBody TournamentDTO tournamentDTO, HttpServletRequest
getController().delete(tournamentDTO);
}


@PreAuthorize("hasAnyRole('ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Generate duels on a fight.", security = @SecurityRequirement(name = "bearerAuth"))
@PutMapping(value = "/duels", produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -147,6 +154,7 @@ public FightDTO generateDuels(@RequestBody FightDTO fightDto, Authentication aut
return getController().generateDuels(fightDto, authentication.getName());
}


@PreAuthorize("hasAnyRole('ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Updates a fight.", security = @SecurityRequirement(name = "bearerAuth"))
@PutMapping(value = "/create/tournaments/{tournamentId}/levels/{levelId}", produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -168,4 +176,15 @@ public List<FightDTO> createNext(@Parameter(description = "Id of an existing tou
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets all fights from competitor.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/competitor/{competitorId}", produces = MediaType.APPLICATION_JSON_VALUE)
public List<FightDTO> getByCompetitor(@Parameter(description = "Id of the competitor.", required = true)
@PathVariable("competitorId")
Integer competitorId,
HttpServletRequest request) {
return getController().getBy(competitorId);
}


}
2 changes: 2 additions & 0 deletions frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ import {RxStompService} from "./websockets/rx-stomp.service";
import {rxStompServiceFactory} from "./websockets/rx-stomp-service-factory";
import {TournamentQrCodeModule} from './components/tournament-qr-code/tournament-qr-code.module';
import {ParticipantQrCodeModule} from './components/participant-qr-code/participant-qr-code.module';
import {ParticipantFightListModule} from './views/participant-fight-list/participant-fight-list.module';


registerLocaleData(localeES, "es");
Expand Down Expand Up @@ -229,6 +230,7 @@ registerLocaleData(localeNL, "nl");
TournamentGeneratorModule,
TournamentQrCodeModule,
ParticipantQrCodeModule,
ParticipantFightListModule,
],
providers: [
CookieService, {
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/app/components/fight/duel/duel.component.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
<user-score (cdkDropListDropped)="drop($event, true)" [cdkDropListEnterPredicate]="dropListEnterPredicate(fight, true)"
[duelIndex]="duelIndex" [duel]="duel" [left]="true"
[showAvatar]="showAvatars"
[locked]="locked"
[highlightedParticipantId]="highlightedParticipantId"
[swapTeams]="swapTeams" cdkDropList
class="user-score"></user-score>
<draw [duel]="duel" class="draw-score"></draw>
<user-score (cdkDropListDropped)="drop($event, false)"
[cdkDropListEnterPredicate]="dropListEnterPredicate(fight, false)" [duelIndex]="duelIndex" [duel]="duel"
[left]="false"
[showAvatar]="showAvatars"
[locked]="locked"
[highlightedParticipantId]="highlightedParticipantId"
[swapTeams]="swapTeams" cdkDropList
class="user-score"></user-score>

6 changes: 6 additions & 0 deletions frontend/src/app/components/fight/duel/duel.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export class DuelComponent extends KendoComponent implements OnInit {
@Input()
duel: Duel;

@Input()
locked: boolean;

@Input()
duelIndex: number;

Expand All @@ -33,6 +36,9 @@ export class DuelComponent extends KendoComponent implements OnInit {
@Input()
showAvatars: boolean = false;

@Input()
highlightedParticipantId: number | undefined;

constructor(private duelChangedService: DuelChangedService, private membersOrderChangedService: MembersOrderChangedService) {
super();
}
Expand Down
Loading

0 comments on commit babe617

Please sign in to comment.