From 1cbbde650698f3d655d3eabe57c0e99169520bb3 Mon Sep 17 00:00:00 2001 From: Thibaut Valentin Date: Sun, 18 Jan 2026 15:10:38 +0100 Subject: [PATCH] feat: add team support to result --- .../data/model/CompetitionGuestModel.java | 21 +++++++ .../ffsaf/data/model/MatchModel.java | 6 ++ .../ffsaf/domain/service/ResultService.java | 55 +++++++++++++------ src/main/webapp/public/competition.js | 6 +- .../webapp/src/pages/result/ResultView.jsx | 6 +- 5 files changed, 70 insertions(+), 24 deletions(-) diff --git a/src/main/java/fr/titionfire/ffsaf/data/model/CompetitionGuestModel.java b/src/main/java/fr/titionfire/ffsaf/data/model/CompetitionGuestModel.java index 0e7d596..42f2a4a 100644 --- a/src/main/java/fr/titionfire/ffsaf/data/model/CompetitionGuestModel.java +++ b/src/main/java/fr/titionfire/ffsaf/data/model/CompetitionGuestModel.java @@ -12,6 +12,8 @@ import lombok.Setter; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; @Getter @Setter @@ -71,6 +73,8 @@ public class CompetitionGuestModel implements CombModel { @Override public String getName() { + if (this.isTeam()) + return this.fname; return this.fname + " " + this.lname; } @@ -78,4 +82,21 @@ public class CompetitionGuestModel implements CombModel { public String getName(MembreModel model, ResultPrivacy privacy) { return getName(); } + + public boolean isTeam() { + return "__team".equals(this.lname); + } + + public boolean isInTeam(Object comb_) { + if (!this.isTeam()) + return false; + + if (comb_ instanceof Long id_) { + if (id_ >= 0) + return comb.stream().anyMatch(membre -> Objects.equals(membre.getId(), id_)); + else + return guest.stream().anyMatch(guestModel -> Objects.equals(guestModel.getId(), -id_)); + } + return Stream.concat(comb.stream(), guest.stream()).anyMatch(c -> Objects.equals(c, comb_)); + } } diff --git a/src/main/java/fr/titionfire/ffsaf/data/model/MatchModel.java b/src/main/java/fr/titionfire/ffsaf/data/model/MatchModel.java index 7fb7b9a..e017810 100644 --- a/src/main/java/fr/titionfire/ffsaf/data/model/MatchModel.java +++ b/src/main/java/fr/titionfire/ffsaf/data/model/MatchModel.java @@ -114,6 +114,9 @@ public class MatchModel { } public boolean isC1(Object comb) { + if (this.c1_guest != null && this.c1_guest.isInTeam(comb)) + return true; + if (comb instanceof Long id_) { if (id_ >= 0) return Objects.equals(this.c1_id != null ? this.c1_id.getId() : null, id_); @@ -124,6 +127,9 @@ public class MatchModel { } public boolean isC2(Object comb) { + if (this.c2_guest != null && this.c2_guest.isInTeam(comb)) + return true; + if (comb instanceof Long id_) { if (id_ >= 0) return Objects.equals(this.c2_id != null ? this.c2_id.getId() : null, id_); diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/ResultService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/ResultService.java index 0156acb..1f61f08 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/ResultService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/ResultService.java @@ -291,7 +291,11 @@ public class ResultService { builder.nb_insc(combs.size()); builder.tt_match((int) matchModels.stream().filter(MatchModel::isEnd).count()); - builder.point(combs.stream().mapToInt(CombsArrayData.CombsData::pointMake).sum()); + builder.point(matchModels.stream() + .filter(MatchModel::isEnd) + .flatMap(m -> m.getScores().stream()) + .filter(s -> s.getS1() > -900 && s.getS2() > -900) + .mapToInt(s -> s.getS1() + s.getS2()).sum()); builder.combs(combs); return builder.build(); @@ -312,12 +316,12 @@ public class ResultService { .map(models -> { HashMap map = new HashMap<>(); models.forEach( - r -> map.put(Utils.getFullName(r.getMembre()), getCombTempId(r.getMembre().getId()))); + r -> map.put(r.getMembre().getName(), getCombTempId(r.getMembre().getId()))); return map; }) - .chain(map -> competitionGuestRepository.list("competition.uuid = ?1", uuid) + .chain(map -> competitionGuestRepository.list("competition.uuid = ?1 AND lname != \"__team\"", uuid) .map(models -> { - models.forEach(guestModel -> map.put(Utils.getFullName(guestModel), + models.forEach(guestModel -> map.put(guestModel.getName(), getCombTempId(guestModel.getId() * -1))); return map; }) @@ -355,8 +359,10 @@ public class ResultService { builder.cat((registerModel.getCategorie2() == null) ? "---" : registerModel.getCategorie2().getName(trad)); - return matchRepository.list("category.compet.uuid = ?1 AND (c1_id = ?2 OR c2_id = ?2)", uuid, - registerModel.getMembre()); + return matchRepository.list( + "SELECT DISTINCT m FROM MatchModel m LEFT JOIN m.c1_guest.comb c1g LEFT JOIN m.c2_guest.comb c2g " + + "WHERE m.category.compet.uuid = ?1 AND (m.c1_id = ?2 OR m.c2_id = ?2 OR c1g = ?2 OR c2g = ?2)", + uuid, registerModel.getMembre()); })); } else { uni = competitionGuestRepository.find("id = ?1 AND competition.uuid = ?2", -id, uuid).firstResult() @@ -366,7 +372,9 @@ public class ResultService { builder.cat( (guestModel.getCategorie() == null) ? "---" : guestModel.getCategorie().getName(trad)); - return matchRepository.list("category.compet.uuid = ?1 AND (c1_guest = ?2 OR c2_guest = ?2)", + return matchRepository.list( + "SELECT DISTINCT m FROM MatchModel m LEFT JOIN m.c1_guest.guest c1g LEFT JOIN m.c2_guest.guest c2g " + + "WHERE m.category.compet.uuid = ?1 AND (m.c1_guest = ?2 OR m.c2_guest = ?2 OR c1g = ?2 OR c2g = ?2)", uuid, guestModel); }); } @@ -389,12 +397,13 @@ public class ResultService { builder2.date(matchModel.getDate()); builder2.poule(pouleModels.stream().filter(p -> p.equals(matchModel.getCategory())) .map(CategoryModel::getName).findFirst().orElse("")); + builder2.end(matchModel.isEnd()); AtomicInteger pointMake = new AtomicInteger(); AtomicInteger pointTake = new AtomicInteger(); if (matchModel.isC1(id)) { - builder2.adv(Utils.getFullName(matchModel.getC2_id(), matchModel.getC2_guest())); + builder2.adv(matchModel.getC2Name()); if (matchModel.isEnd()) { matchModel.getScores().stream() .filter(s -> s.getS1() > -900 && s.getS2() > -900) @@ -409,7 +418,7 @@ public class ResultService { } builder2.win(matchModel.isEnd() && matchModel.win() > 0); } else { - builder2.adv(Utils.getFullName(matchModel.getC1_id(), matchModel.getC1_guest())); + builder2.adv(matchModel.getC1Name()); if (matchModel.isEnd()) { matchModel.getScores().stream() .filter(s -> s.getS1() > -900 && s.getS2() > -900) @@ -468,7 +477,7 @@ public class ResultService { @Builder @RegisterForReflection public static record MatchsData(Date date, String poule, String adv, List score, float ratio, - boolean win, boolean eq) { + boolean win, boolean eq, boolean end) { } } @@ -513,14 +522,19 @@ public class ResultService { return Uni.createFrom().voidItem(); }) .chain(guests -> matchRepository.list( - "category.compet.uuid = ?1 AND (c1_guest IN ?2 OR c2_guest IN ?2)", uuid, guests) + "SELECT DISTINCT m FROM MatchModel m LEFT JOIN m.c1_guest.guest c1g LEFT JOIN m.c2_guest.guest c2g " + + "WHERE m.category.compet.uuid = ?1 AND (m.c1_guest IN ?2 OR m.c2_guest IN ?2 OR c1g IN ?2 OR c2g IN ?2)", + uuid, guests) .map(matchModels -> getClubArray2(clubName, guests.stream().map(o -> (CombModel) o).toList(), matchModels, new ArrayList<>(), membreModel))); } else { return clubRepository.findById(id).chain(clubModel -> registerRepository.list("competition.uuid = ?1 AND membre.club = ?2", uuid, clubModel) - .chain(registers -> matchRepository.list("category.compet.uuid = ?1", uuid) + .chain(registers -> matchRepository.list( + "SELECT DISTINCT m FROM MatchModel m LEFT JOIN m.c1_guest.comb c1g LEFT JOIN m.c2_guest.comb c2g " + + "WHERE m.category.compet.uuid = ?1 AND (m.c1_id IN ?2 OR m.c2_id IN ?2 OR c1g IN ?2 OR c2g IN ?2)", + uuid, registers.stream().map(RegisterModel::getMembre).toList()) .map(matchModels -> getClubArray2(clubModel.getName(), registers.stream().map(o -> (CombModel) o.getMembre()).toList(), @@ -534,8 +548,8 @@ public class ResultService { builder.name(name); builder.nb_insc(combs.size()); - AtomicInteger tt_win = new AtomicInteger(0); - AtomicInteger tt_match = new AtomicInteger(0); + ArrayList win_ids = new ArrayList<>(); + ArrayList match_ids = new ArrayList<>(); List combData = combs.stream().map(comb -> { var builder2 = ClubArrayData.CombData.builder(); @@ -562,16 +576,16 @@ public class ResultService { builder2.pointTake(stat.pointTake); builder2.ratioPoint(stat.getPointRate()); - tt_win.addAndGet(stat.w); - tt_match.addAndGet(stat.w + stat.l); + win_ids.addAll(stat.win_ids); + match_ids.addAll(stat.match_ids); return builder2.build(); }) .sorted(Comparator.comparing(ClubArrayData.CombData::name)) .toList(); - builder.nb_match(tt_match.get()); - builder.match_w(tt_win.get()); + builder.nb_match((int) match_ids.stream().distinct().count()); + builder.match_w((int) win_ids.stream().distinct().count()); builder.ratioVictoire((float) combData.stream().filter(c -> c.l + c.w != 0) .mapToDouble(ClubArrayData.CombData::ratioVictoire).average().orElse(0L)); builder.pointMake(combData.stream().mapToInt(ClubArrayData.CombData::pointMake).sum()); @@ -588,11 +602,14 @@ public class ResultService { matchModels.stream() .filter(m -> m.isEnd() && (m.isC1(comb) || m.isC2(comb))) .forEach(matchModel -> { + stat.match_ids.add(matchModel.getId()); + int win = matchModel.win(); if (win == 0) { stat.score += 1; } else if ((matchModel.isC1(comb) && win > 0) || matchModel.isC2(comb) && win < 0) { stat.w++; + stat.win_ids.add(matchModel.getId()); stat.score += 3; } else { stat.l++; @@ -631,6 +648,8 @@ public class ResultService { public int score; public int pointMake; public int pointTake; + public ArrayList win_ids = new ArrayList<>(); + public ArrayList match_ids = new ArrayList<>(); public CombStat() { this.w = 0; diff --git a/src/main/webapp/public/competition.js b/src/main/webapp/public/competition.js index 6f14d9c..e593364 100644 --- a/src/main/webapp/public/competition.js +++ b/src/main/webapp/public/competition.js @@ -393,9 +393,9 @@ function buildCombView(comb) {

${i18next.t('statistique')} :

  • ${i18next.t('tauxDeVictoire2', { - nb: comb.matchs.length === 0 ? "---" : (comb.totalWin / comb.matchs.length * 100).toFixed(0), + nb: comb.matchs.length === 0 ? "---" : (comb.totalWin / comb.matchs.filter(m => m.end).length * 100).toFixed(0), victoires: comb.totalWin, - matchs: comb.matchs.length + matchs: comb.matchs.filter(m => m.end).length })}
  • ${i18next.t('pointsMarqués2', {nb: comb.pointMake})}
  • @@ -423,7 +423,7 @@ function buildCombView(comb) { ${match.poule} ${match.adv} ${scoreToString(match.score)} - ${match.ratio.toFixed(3)} + ${match.end ? match.ratio.toFixed(3) : ""} ${match.win ? cupImg : (match.eq ? cupImg2 : "")} ` } diff --git a/src/main/webapp/src/pages/result/ResultView.jsx b/src/main/webapp/src/pages/result/ResultView.jsx index b5aed60..8beddfb 100644 --- a/src/main/webapp/src/pages/result/ResultView.jsx +++ b/src/main/webapp/src/pages/result/ResultView.jsx @@ -373,9 +373,9 @@ function CombResult({uuid, combId}) {

    {t('statistique')} :

    • {t('tauxDeVictoire2', { - nb: data.matchs.length === 0 ? "---" : (data.totalWin / data.matchs.length * 100).toFixed(0), + nb: data.matchs.length === 0 ? "---" : (data.totalWin / data.matchs.filter(m => m.end).length * 100).toFixed(0), victoires: data.totalWin, - matchs: data.matchs.length + matchs: data.matchs.filter(m => m.end).length })}
    • {t('pointsMarqués2', {nb: data.pointMake})}
    • @@ -401,7 +401,7 @@ function CombResult({uuid, combId}) { {match.poule} {match.adv} {scoreToString(match.score)} - {match.ratio.toFixed(3)} + {match.end && match.ratio.toFixed(3)} {match.win ? : (match.eq ? : "")} )}