Skip to content

Commit

Permalink
Merge pull request #396 from softwaremagico/164-research-to-create-a-…
Browse files Browse the repository at this point in the history
…ranking-where-time-is-involved

164 research to create a ranking where time is involved
  • Loading branch information
softwaremagico authored May 5, 2024
2 parents 551eef0 + ef301b2 commit 0103400
Show file tree
Hide file tree
Showing 26 changed files with 154 additions and 61 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ default_data.sql
.attach_*
.env_bak
target/*
*.properties_bak
*.properties_bak
*.properties.mysql
*.properties.postgres
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-603h-blueviolet.svg)]()
[![Time](https://img.shields.io/badge/development-605h-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 @@ -262,20 +262,20 @@ public List<ScoreOfCompetitorDTO> getCompetitorsGlobalScoreRankingByClub(Integer
final List<Role> competitorRoles = roleProvider.get(participants, RoleType.COMPETITOR);
participants.retainAll(competitorRoles.stream().map(Role::getParticipant).collect(Collectors.toSet()));
return getCompetitorsGlobalScoreRanking(participantConverter.convertAll(participants.stream()
.map(participant -> new ParticipantConverterRequest(participant, clubConverter.convert(new ClubConverterRequest(club)))).toList()));
.map(participant -> new ParticipantConverterRequest(participant, clubConverter.convert(new ClubConverterRequest(club)))).toList()), null);
}

public List<ScoreOfCompetitorDTO> getCompetitorsGlobalScoreRanking(Collection<ParticipantDTO> competitors) {
return getCompetitorsGlobalScoreRanking(competitors, ScoreType.DEFAULT);
public List<ScoreOfCompetitorDTO> getCompetitorsGlobalScoreRanking(Collection<ParticipantDTO> competitors, Integer fromNumberOfDays) {
return getCompetitorsGlobalScoreRanking(competitors, ScoreType.DEFAULT, fromNumberOfDays);
}


public List<ScoreOfCompetitorDTO> getCompetitorsGlobalScoreRanking(Collection<ParticipantDTO> competitors, ScoreType scoreType) {
public List<ScoreOfCompetitorDTO> getCompetitorsGlobalScoreRanking(Collection<ParticipantDTO> competitors, ScoreType scoreType, Integer fromNumberOfDays) {
final Map<Integer, ClubDTO> clubsById = competitors.stream()
.map(ParticipantDTO::getClub).collect(Collectors.toMap(ClubDTO::getId, Function.identity(), (r1, r2) -> r1));
return scoreOfCompetitorConverter.convertAll(rankingProvider.getCompetitorsGlobalScoreRanking(
participantConverter.reverseAll(competitors),
scoreType
scoreType, fromNumberOfDays
)
.stream().map(scoreOfCompetitor -> new ScoreOfCompetitorConverterRequest(scoreOfCompetitor,
clubsById.get(scoreOfCompetitor.getCompetitor().getClub().getId()))).toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
import com.softwaremagico.kt.persistence.values.TournamentType;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
Expand Down Expand Up @@ -206,13 +208,21 @@ public List<ScoreOfCompetitor> getCompetitorGlobalRanking(ScoreType scoreType) {
return scores;
}

public List<ScoreOfCompetitor> getCompetitorsGlobalScoreRanking(Collection<Participant> competitors, ScoreType scoreType) {
public List<ScoreOfCompetitor> getCompetitorsGlobalScoreRanking(Collection<Participant> competitors, ScoreType scoreType, Integer fromNumberOfDays) {
if (competitors == null || competitors.isEmpty()) {
competitors = participantProvider.getAll();
}
//Get number since when is read the data.
final LocalDateTime from = fromNumberOfDays != null && fromNumberOfDays != 0 ? LocalDate.now().minusDays(fromNumberOfDays).atStartOfDay() : null;
final List<ScoreOfCompetitor> scores = new ArrayList<>();
final List<Fight> fights = fightProvider.getBy(competitors);
final List<Duel> unties = duelProvider.getUnties(competitors);
final List<Fight> fights = fightProvider.getBy(competitors).stream().filter(fight ->
from == null || fight.getCreatedAt().isAfter(from)).toList();
final List<Duel> unties = duelProvider.getUnties(competitors).stream().filter(duel ->
from == null || duel.getCreatedAt().isAfter(from)).toList();

final Set<Participant> participantsInFights = fights.stream().flatMap(fight -> fight.getTeam1().getMembers().stream()).collect(Collectors.toSet());
participantsInFights.addAll(fights.stream().flatMap(fight -> fight.getTeam2().getMembers().stream()).collect(Collectors.toSet()));
competitors.retainAll(participantsInFights);
for (final Participant competitor : competitors) {
scores.add(new ScoreOfCompetitor(competitor, fights, unties, false));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ tournament.type.championship=Championship
tournament.type.tree=Tree Championship
tournament.type.league=League
tournament.type.loop=Loop
tournament.type.custom.championship=Custom Championship
tournament.type.king.of.the.mountain=King of the Mountain
tournament.type.custom_championship=Custom Championship
tournament.type.king_of_the_mountain=King of the Mountain
tournament.type.customized=Customized
club.list=Clubs list
fight.list=List of fightss
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ tournament.type.championship=Campeonat
tournament.type.tree=Campeonat en Arbre
tournament.type.league=Lliga
tournament.type.loop=Bucle
tournament.type.custom.championship=Campeonat Personalizat
tournament.type.king.of.the.mountain=Rei de la muntanya
tournament.type.custom_championship=Campeonat Personalizat
tournament.type.king_of_the_mountain=Rei de la muntanya
tournament.type.customized=Personalizat
club.list=Llista de clubs
fight.list=Llista de partits
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ tournament.type.championship=
tournament.type.tree=
tournament.type.league=
tournament.type.loop=
tournament.type.custom.championship=
tournament.type.king.of.the.mountain=
tournament.type.custom_championship=
tournament.type.king_of_the_mountain=
tournament.type.customized=
club.list=Liste der Klubs
fight.list=Liste der Kämpfe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ tournament.type.championship=Campeonato
tournament.type.tree=Campeonato en Árbol
tournament.type.league=Liga
tournament.type.loop=Bucle
tournament.type.custom.championship=Campeonato Personalizado
tournament.type.king.of.the.mountain=Rey de la Montaña
tournament.type.custom_championship=Campeonato Personalizado
tournament.type.king_of_the_mountain=Rey de la Montaña
tournament.type.customized=Personalizado
club.list=Lista de clubes
fight.list=Lista de partidos
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ tournament.type.championship=Campionato
tournament.type.tree=Campionato
tournament.type.league=Liga
tournament.type.loop=Bucle
tournament.type.custom.championship=Campionato Personalizzato
tournament.type.king.of.the.mountain=Il Re della Montagna
tournament.type.custom_championship=Campionato Personalizzato
tournament.type.king_of_the_mountain=Il Re della Montagna
tournament.type.customized=Personalizzato
club.list=Lista dei club
fight.list=Lista degli incontri
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ tournament.type.championship=Poule
tournament.type.tree=Poule
tournament.type.league=League
tournament.type.loop=Loop
tournament.type.custom.championship=Custom
tournament.type.king.of.the.mountain=King of the Mountain
tournament.type.custom_championship=Custom
tournament.type.king_of_the_mountain=King of the Mountain
tournament.type.customized=Custom
club.list=Overzicht van de clubs
fight.list=Overzicht wedstrijden
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;

@RestController
Expand Down Expand Up @@ -92,6 +94,7 @@ public RankingServices(RankingController rankingController, PdfController pdfCon
this.zipController = zipController;
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets participants' ranking.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/competitors/groups/{groupId}", produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -101,6 +104,7 @@ public List<ScoreOfCompetitorDTO> getCompetitorsScoreRankingGroup(@Parameter(des
return rankingController.getCompetitorsScoreRankingFromGroup(groupId);
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN', 'ROLE_GUEST')")
@Operation(summary = "Gets participants' ranking.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/competitors/tournaments/{tournamentId}", produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -110,27 +114,33 @@ public List<ScoreOfCompetitorDTO> getCompetitorsScoreRankingTournament(@Paramete
return rankingController.getCompetitorsScoreRankingFromTournament(tournamentId);
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets participants' global ranking.", security = @SecurityRequirement(name = "bearerAuth"))
@PostMapping(value = "/competitors", produces = MediaType.APPLICATION_JSON_VALUE)
public List<ScoreOfCompetitorDTO> getCompetitorsGlobalScoreRanking(@RequestBody(required = false) Set<ParticipantDTO> participants,
public List<ScoreOfCompetitorDTO> getCompetitorsGlobalScoreRanking(@RequestParam(name = "from") Optional<Integer> from,
@RequestBody(required = false) Set<ParticipantDTO> participants,
HttpServletRequest request) {
return rankingController.getCompetitorsGlobalScoreRanking(participants != null ? participants : new ArrayList<>());
return rankingController.getCompetitorsGlobalScoreRanking(participants != null ? participants : new ArrayList<>(), from.orElse(null));
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN', 'ROLE_PARTICIPANT')")
@Operation(summary = "Gets participant global ranking.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/competitors/{competitorId}", produces = MediaType.APPLICATION_JSON_VALUE)
public CompetitorRanking getCompetitorsRanking(@PathVariable("competitorId") Integer competitorId, HttpServletRequest request) {
return rankingController.getCompetitorRanking(participantController.get(competitorId));
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets participants' global ranking.", security = @SecurityRequirement(name = "bearerAuth"))
@PostMapping(value = "/competitors/pdf", produces = MediaType.APPLICATION_JSON_VALUE)
public byte[] getCompetitorsGlobalScoreRankingAsPdf(@RequestBody(required = false) Set<ParticipantDTO> participants,
public byte[] getCompetitorsGlobalScoreRankingAsPdf(@RequestParam(name = "from") Optional<Integer> from,
@RequestBody(required = false) Set<ParticipantDTO> participants,
Locale locale, HttpServletResponse response, HttpServletRequest request) {
final List<ScoreOfCompetitorDTO> scores = rankingController.getCompetitorsGlobalScoreRanking(participants != null ? participants : new ArrayList<>());
final List<ScoreOfCompetitorDTO> scores = rankingController.getCompetitorsGlobalScoreRanking(participants != null ? participants : new ArrayList<>(),
from.orElse(null));
try {
final ContentDisposition contentDisposition = ContentDisposition.builder("attachment")
.filename("competitors score.pdf").build();
Expand All @@ -152,6 +162,7 @@ public List<ScoreOfCompetitorDTO> getCompetitorsGlobalScoreRanking(@Parameter(de
return rankingController.getCompetitorsGlobalScoreRankingByClub(clubId);
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets participants' global ranking.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/competitors/clubs/{clubId}/pdf", produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -170,6 +181,7 @@ public byte[] getCompetitorsGlobalScoreRankingByClubAsPdf(@Parameter(description
}
}


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


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets teams' ranking.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/teams/groups/{groupId}", produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -198,6 +211,7 @@ public List<ScoreOfTeamDTO> getTeamsScoreRankingFromGroup(@Parameter(description
return rankingController.getTeamsScoreRankingFromGroup(groupId);
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN', 'ROLE_GUEST')")
@Operation(summary = "Gets teams' ranking.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/teams/tournaments/{tournamentId}", produces = MediaType.APPLICATION_JSON_VALUE)
Expand All @@ -207,6 +221,7 @@ public List<ScoreOfTeamDTO> getTeamsScoreRankingFromTournament(@Parameter(descri
return rankingController.getTeamsScoreRankingFromTournament(tournamentId);
}


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


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets teams' ranking in a pdf file.", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/teams/groups/{groupId}/pdf", produces = MediaType.APPLICATION_PDF_VALUE)
Expand All @@ -246,6 +262,7 @@ public byte[] getTeamsScoreRankingFromGroupAsPdf(@Parameter(description = "Id of
}
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Gets complete tournament summary as html", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/summary/{tournamentId}/html", produces = MediaType.TEXT_PLAIN_VALUE)
Expand All @@ -260,6 +277,7 @@ public byte[] getTournamentsSummaryAsHtml(@Parameter(description = "Id of an exi
return htmlController.generateBlogCode(locale, tournament).getWordpressFormat().getBytes(StandardCharsets.UTF_8);
}


@PreAuthorize("hasAnyRole('ROLE_VIEWER', 'ROLE_EDITOR', 'ROLE_ADMIN')")
@Operation(summary = "Download all files as a zip", security = @SecurityRequirement(name = "bearerAuth"))
@GetMapping(value = "/tournament/{tournamentId}/zip")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ spring.messages.basename=language/language

#Database Access
spring.jpa.open-in-view=false
spring.kendo.datasource.jpa.hibernate.ddl-auto=update
spring.kendo.datasource.platform=mysql
spring.usermanager.datasource.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.usermanager.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.kendo.datasource.jdbc-url=jdbc:mysql://localhost:3306/kendotournament?useSSL=false&autoReconnect=true
spring.kendo.datasource.username=user
spring.kendo.datasource.password=asd123
spring.kendo.datasource.jpa.hibernate.ddl-auto=create-drop
spring.kendo.datasource.platform=h2
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.kendo.datasource.jdbc-url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE;DATABASE_TO_UPPER=false
spring.kendo.datasource.username=sa
spring.kendo.datasource.password=
spring.kendo.datasource.initialize=true
spring.kendo.datasource.test-while-idle=true

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
<app-mat-spinner-overlay [overlay]="true"></app-mat-spinner-overlay>
<div class="table-container">
<div class="days-selector">
<input *ngIf="!this.club && !this.tournament" class="day-input" type="number" matInput min="0" max="10000" [(ngModel)]="numberOfDays"
placeholder="{{'daysFrom' | translate}}" [matTooltipShowDelay]="1000" matTooltip="{{'daysFrom' | translate}}"
required (keyup.enter)="daysChanged()">
<button (click)="daysChanged()" color="secondary" class="day-input"
mat-button>
<mat-icon>refresh</mat-icon>
</button>
</div>
<table class="competitor-ranking-table">
<caption class="table-caption">{{'competitorsRanking' | translate}}</caption>
<thead>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.table-container {
position: relative;
overflow: auto;
max-height: 70vh;
}
Expand All @@ -9,7 +10,7 @@
}

.competitor-ranking-table {
margin: 2vw;
margin: 2vw -190px 2vm 2vm;
}

.competitor-ranking-table thead th {
Expand Down Expand Up @@ -58,3 +59,16 @@
display: flex;
justify-content: center;
}

.days-selector {
position: absolute;
top: 0;
right: 16px;
width: 200px;
display: flex;
}

.day-input {
padding: 0 10px 0 0;
min-width: 0;
}
Loading

0 comments on commit 0103400

Please sign in to comment.