dev #109
@ -7,6 +7,8 @@ import fr.titionfire.ffsaf.rest.data.ResultCategoryData;
|
||||
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||
import fr.titionfire.ffsaf.utils.*;
|
||||
import io.quarkus.cache.Cache;
|
||||
import io.quarkus.cache.CacheName;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||
import io.smallrye.mutiny.Multi;
|
||||
@ -15,6 +17,7 @@ import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
|
||||
import java.util.*;
|
||||
@ -52,6 +55,10 @@ public class ResultService {
|
||||
@Inject
|
||||
TradService trad;
|
||||
|
||||
@Inject
|
||||
@CacheName("club-classement")
|
||||
Cache cacheClubClassement;
|
||||
|
||||
private static final HashMap<Long, String> combTempIds = new HashMap<>();
|
||||
|
||||
private static String getCombTempId(Long key) {
|
||||
@ -214,7 +221,7 @@ public class ResultService {
|
||||
}
|
||||
|
||||
public void getClassementArray(CategoryModel categoryModel, MembreModel membreModel, List<CardModel> cards,
|
||||
ResultCategoryData out) {
|
||||
ResultCategoryData out) {
|
||||
if ((categoryModel.getType() & 2) != 0) {
|
||||
AtomicInteger rank = new AtomicInteger(0);
|
||||
categoryModel.getTree().stream()
|
||||
@ -231,7 +238,8 @@ public class ResultService {
|
||||
} else {
|
||||
for (List<ResultCategoryData.RankArray> list : out.getRankArray().values()) {
|
||||
for (ResultCategoryData.RankArray r : list) {
|
||||
out.getClassement().add(new ResultCategoryData.ClassementData(r.getRank(), r.getComb(), r.getName()));
|
||||
out.getClassement()
|
||||
.add(new ResultCategoryData.ClassementData(r.getRank(), r.getComb(), r.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -724,6 +732,100 @@ public class ResultService {
|
||||
}
|
||||
}
|
||||
|
||||
public Uni<List<ClubClassement>> getAllClubArray(String uuid) {
|
||||
return getAllClubArray(uuid, true);
|
||||
}
|
||||
|
||||
public Uni<List<ClubClassement>> getAllClubArray(String uuid, SecurityCtx securityCtx) {
|
||||
return hasAccess(uuid, securityCtx).chain(membreModel -> getAllClubArray(uuid, true));
|
||||
}
|
||||
|
||||
public Uni<List<ClubClassement>> getAllClubArray(String uuid, boolean cache) {
|
||||
List<CardModel> cards = new java.util.ArrayList<>();
|
||||
|
||||
//noinspection unchecked
|
||||
cacheClubClassement.invalidateIf(
|
||||
(p) -> ((Pair<Long, List<ClubClassement>>) p).getKey() > System.currentTimeMillis());
|
||||
|
||||
if (!cache)
|
||||
cacheClubClassement.invalidate(uuid);
|
||||
|
||||
return cacheClubClassement.getAsync(uuid, k -> cardRepository.list("competition.uuid = ?1", uuid)
|
||||
.invoke(__ -> System.out.println("Cache miss for club classement with uuid " + uuid))
|
||||
.invoke(cards::addAll)
|
||||
.chain(__ -> matchRepository.list("category.compet.uuid = ?1", uuid))
|
||||
.chain(matchs -> {
|
||||
HashMap<CategoryModel, List<MatchModel>> map = new HashMap<>();
|
||||
for (MatchModel match : matchs) {
|
||||
if (!map.containsKey(match.getCategory()))
|
||||
map.put(match.getCategory(), new java.util.ArrayList<>());
|
||||
map.get(match.getCategory()).add(match);
|
||||
}
|
||||
|
||||
return Multi.createFrom().iterable(map.entrySet())
|
||||
.onItem().call(entry -> Mutiny.fetch(entry.getKey().getTree()))
|
||||
.map(entry -> {
|
||||
ResultCategoryData tmp = new ResultCategoryData();
|
||||
|
||||
getArray2(entry.getValue().stream().map(m -> new MatchModelExtend(m, cards)).toList(),
|
||||
null, tmp);
|
||||
getClassementArray(entry.getKey(), null, cards, tmp);
|
||||
|
||||
return tmp;
|
||||
})
|
||||
.collect().asList();
|
||||
})
|
||||
.map(categoryData -> {
|
||||
HashMap<Long, ClubClassement> clubMap = new HashMap<>();
|
||||
|
||||
categoryData.forEach(c -> c.getClassement().forEach(classementData -> {
|
||||
if (classementData.rank() > 3)
|
||||
return;
|
||||
|
||||
if (classementData.comb() != null) {
|
||||
long clubId = 0L;
|
||||
String clubName = "";
|
||||
if (classementData.comb() instanceof MembreModel membreModel2) {
|
||||
clubId = (membreModel2.getClub() != null) ? membreModel2.getClub().getId() : 0;
|
||||
clubName = (membreModel2.getClub() != null) ? membreModel2.getClub().getName() : "";
|
||||
} else if (classementData.comb() instanceof CompetitionGuestModel guestModel) {
|
||||
if (guestModel.getClub() != null && !guestModel.getClub().isBlank())
|
||||
clubId = getClubTempId(guestModel.getClub());
|
||||
clubName = guestModel.getClub();
|
||||
}
|
||||
|
||||
if (clubId != 0) {
|
||||
clubMap.putIfAbsent(clubId, new ClubClassement(clubName));
|
||||
ClubClassement entity = clubMap.get(clubId);
|
||||
entity.score[classementData.rank() - 1]++;
|
||||
entity.tt_score += 4 - classementData.rank();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
return clubMap.values().stream()
|
||||
.sorted(Comparator.comparingInt((ClubClassement c) -> c.tt_score)
|
||||
.thenComparingInt(c -> c.score[0])
|
||||
.thenComparingInt(c -> c.score[1])
|
||||
.thenComparingInt(c -> c.score[2]).reversed())
|
||||
.toList();
|
||||
})
|
||||
.map(l -> new Pair<>(System.currentTimeMillis() + 60 * 1000L, l))
|
||||
).map(Pair::getValue);
|
||||
}
|
||||
|
||||
@Data
|
||||
@RegisterForReflection
|
||||
public static class ClubClassement {
|
||||
String name;
|
||||
Integer[] score = new Integer[]{0, 0, 0};
|
||||
int tt_score = 0;
|
||||
|
||||
public ClubClassement(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@RegisterForReflection
|
||||
public static class CombStat {
|
||||
public int w;
|
||||
|
||||
@ -8,6 +8,7 @@ import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@Path("api/public/result/{id}")
|
||||
public class ExternalResultEndpoints {
|
||||
@ -73,6 +74,13 @@ public class ExternalResultEndpoints {
|
||||
return resultService.getClubList(id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/club/classement")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Uni<List<ResultService.ClubClassement>> clubClassement() {
|
||||
return resultService.getAllClubArray(id);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/club/data")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
|
||||
@ -47,6 +47,12 @@ public class ResultEndpoints {
|
||||
return resultService.getClubList(uuid, securityCtx);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{uuid}/club/classement")
|
||||
public Uni<List<ResultService.ClubClassement>> getClubClassement(@PathParam("uuid") String uuid) {
|
||||
return resultService.getAllClubArray(uuid, securityCtx);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{uuid}/club/{id}")
|
||||
public Uni<ResultService.ClubArrayData> getClub(@PathParam("uuid") String uuid, @PathParam("id") long id) {
|
||||
|
||||
@ -39,6 +39,9 @@ function setSubPage(name) {
|
||||
case 'club':
|
||||
clubPage(location);
|
||||
break;
|
||||
case 'clubRank':
|
||||
clubRankPage();
|
||||
break;
|
||||
case 'all':
|
||||
combsPage();
|
||||
break;
|
||||
@ -54,6 +57,7 @@ function homePage() {
|
||||
<li><a id="pouleLink" href="javascript:void(0);">${i18next.t('parCatégorie')}</a></li>
|
||||
<li><a id="combLink" href="javascript:void(0);">${i18next.t('parCombattant')}</a></li>
|
||||
<li><a id="clubLink" href="javascript:void(0);">${i18next.t('parClub')}</a></li>
|
||||
<li><a id="clubClassement" href="javascript:void(0);">${i18next.t('classementClub')}</a></li>
|
||||
<li><a id="allLink" href="javascript:void(0);">${i18next.t('tousLesCombattants')}</a></li>
|
||||
</ul>
|
||||
`
|
||||
@ -62,6 +66,7 @@ function homePage() {
|
||||
document.getElementById('pouleLink').addEventListener('click', () => setSubPage('poule'));
|
||||
document.getElementById('combLink').addEventListener('click', () => setSubPage('comb'));
|
||||
document.getElementById('clubLink').addEventListener('click', () => setSubPage('club'));
|
||||
document.getElementById('clubClassement').addEventListener('click', () => setSubPage('clubRank'));
|
||||
document.getElementById('allLink').addEventListener('click', () => setSubPage('all'));
|
||||
}
|
||||
|
||||
@ -640,6 +645,60 @@ function clubPage(location) {
|
||||
rootDiv.append(content)
|
||||
}
|
||||
|
||||
function buildClubsView(clubs) {
|
||||
const pouleDiv = document.createElement('div');
|
||||
let arrayContent = `
|
||||
<h3>${i18next.t('classementDesClub')} :</h3>
|
||||
|
||||
<figure class="wp-block-table is-style-stripes" style="font-size: 16px">
|
||||
<table style="width: 1200px;overflow: auto"><thead>
|
||||
<tr>
|
||||
<th class="has-text-align-center" data-align="center">${i18next.t('club')}</th>
|
||||
<th class="has-text-align-center" data-align="center">${i18next.t('1er')}</th>
|
||||
<th class="has-text-align-center" data-align="center">${i18next.t('2eme')}</th>
|
||||
<th class="has-text-align-center" data-align="center">${i18next.t('3eme')}</th>
|
||||
<th class="has-text-align-center" data-align="center">${i18next.t('scores')}</th>
|
||||
</tr>
|
||||
</thead><tbody>`
|
||||
for (const club of clubs) {
|
||||
arrayContent += `
|
||||
<tr>
|
||||
<td class="has-text-align-center" data-align="center">${club.name}</td>
|
||||
<td class="has-text-align-center" data-align="center">${club.score[0]}</td>
|
||||
<td class="has-text-align-center" data-align="center">${club.score[1]}</td>
|
||||
<td class="has-text-align-center" data-align="center">${club.score[2]}</td>
|
||||
<td class="has-text-align-center" data-align="center">${club.tt_score}</td>
|
||||
</tr>`
|
||||
}
|
||||
arrayContent += `</tbody></table></figure>`
|
||||
pouleDiv.innerHTML = arrayContent;
|
||||
return pouleDiv;
|
||||
}
|
||||
|
||||
function clubRankPage() {
|
||||
rootDiv.innerHTML = `<h4>${i18next.t('résultatDeLaCompétition')} :</h4><a id="homeLink" href="javascript:void(0);">${i18next.t('back')}</a>`;
|
||||
document.getElementById('homeLink').addEventListener('click', () => setSubPage('home'));
|
||||
|
||||
const content = document.createElement('div');
|
||||
content.style.marginTop = '1em';
|
||||
|
||||
const dataContainer = document.createElement('div');
|
||||
dataContainer.id = 'data-container';
|
||||
|
||||
const loading = startLoading(content);
|
||||
fetch(`${apiUrlRoot}/club/classement`)
|
||||
.then(response => response.json())
|
||||
.then(clubs => {
|
||||
console.log(clubs);
|
||||
dataContainer.replaceChildren(buildClubsView(clubs));
|
||||
})
|
||||
.catch(() => dataContainer.replaceChildren(new Text(i18next.t('erreurDeChargementDeLaListe'))))
|
||||
.finally(() => stopLoading(loading));
|
||||
|
||||
content.append(dataContainer);
|
||||
rootDiv.append(content)
|
||||
}
|
||||
|
||||
function buildCombsView(combs) {
|
||||
const pouleDiv = document.createElement('div');
|
||||
let arrayContent = `
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
"--sélectionnerUnClub--": "--Select a club--",
|
||||
"--sélectionnerUnCombattant--": "--Select a fighter--",
|
||||
"--sélectionnerUneCatégorie--": "--Select a category--",
|
||||
"1er": "Gold medal",
|
||||
"2eme": "Silver medal",
|
||||
"3eme": "Bronze medal",
|
||||
"abs.": "abs.",
|
||||
"adversaire": "Opponent",
|
||||
"aujourdhuià": "Today at {{time}}",
|
||||
@ -11,7 +14,9 @@
|
||||
"catégorie": "Category",
|
||||
"chargement": "Loading",
|
||||
"classement": "Ranking",
|
||||
"classementFinal": "Final standings",
|
||||
"classementClub": "Club ranking",
|
||||
"classementDesClub": "Clubs ranking",
|
||||
"classementFinal": "Final ranking",
|
||||
"club": "Club",
|
||||
"combattant": "Fighter",
|
||||
"combattants": "Fighters",
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
"--sélectionnerUnClub--": "--Sélectionner un club--",
|
||||
"--sélectionnerUnCombattant--": "--Sélectionner un combattant--",
|
||||
"--sélectionnerUneCatégorie--": "--Sélectionner une catégorie--",
|
||||
"1er": "Médaille d'or",
|
||||
"2eme": "Médaille d'argent",
|
||||
"3eme": "Médaille de bronze",
|
||||
"abs.": "abs.",
|
||||
"adversaire": "Adversaire",
|
||||
"aujourdhuià": "Aujourd'hui à {{time}}",
|
||||
@ -11,6 +14,8 @@
|
||||
"catégorie": "Catégorie",
|
||||
"chargement": "Chargement",
|
||||
"classement": "Classement",
|
||||
"classementClub": "Classement club",
|
||||
"classementDesClub": "Classement des club",
|
||||
"classementFinal": "Classement final",
|
||||
"club": "Club",
|
||||
"combattant": "Combattant",
|
||||
|
||||
@ -39,7 +39,8 @@ export function ResultView() {
|
||||
{resultShow && resultShow === "cat" && <CategoryList uuid={uuid}/>
|
||||
|| resultShow && resultShow === "club" && <ClubList uuid={uuid}/>
|
||||
|| resultShow && resultShow === "comb" && <CombList uuid={uuid}/>
|
||||
|| resultShow && resultShow === "combs" && <CombsResult uuid={uuid}/>}
|
||||
|| resultShow && resultShow === "combs" && <CombsResult uuid={uuid}/>
|
||||
|| resultShow && resultShow === "clubs" && <ClubsResult uuid={uuid}/>}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
@ -66,6 +67,10 @@ function MenuBar({resultShow, setResultShow}) {
|
||||
<a className={"nav-link my-1" + (resultShow === "combs" ? " active" : "")} aria-current={(resultShow === "combs" ? " page" : "false")}
|
||||
href="#" onClick={_ => setResultShow("combs")}>{t('combattants')}</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className={"nav-link my-1" + (resultShow === "clubs" ? " active" : "")} aria-current={(resultShow === "clubs" ? " page" : "false")}
|
||||
href="#" onClick={_ => setResultShow("clubs")}>{t('classementClub')}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
/*
|
||||
@ -450,6 +455,43 @@ function CombResult({uuid, combId}) {
|
||||
</div>
|
||||
}
|
||||
|
||||
function ClubsResult({uuid}) {
|
||||
const setLoading = useLoadingSwitcher()
|
||||
const {data, error} = useFetch(`/result/${uuid}/club/classement`, setLoading, 1)
|
||||
const {t} = useTranslation('result');
|
||||
|
||||
return <>
|
||||
{data ? <>
|
||||
<h3>{t('classementDesClub')} :</h3>
|
||||
|
||||
<table className="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" style={{textAlign: "center"}}>{t('club')}</th>
|
||||
<th scope="col" style={{textAlign: "center"}}>{t('1er')}</th>
|
||||
<th scope="col" style={{textAlign: "center"}}>{t('2eme')}</th>
|
||||
<th scope="col" style={{textAlign: "center"}}>{t('3eme')}</th>
|
||||
<th scope="col" style={{textAlign: "center"}}>{t('scores')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.map((club, idx) => <tr key={idx}>
|
||||
<td style={{textAlign: "center"}}>{club.name}</td>
|
||||
<td style={{textAlign: "center"}}>{club.score[0]}</td>
|
||||
<td style={{textAlign: "center"}}>{club.score[1]}</td>
|
||||
<td style={{textAlign: "center"}}>{club.score[2]}</td>
|
||||
<td style={{textAlign: "center"}}>{club.tt_score}</td>
|
||||
</tr>)}
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
: error
|
||||
? <AxiosError error={error}/>
|
||||
: <Def/>
|
||||
}
|
||||
</>
|
||||
}
|
||||
|
||||
function CombsResult({uuid}) {
|
||||
const setLoading = useLoadingSwitcher()
|
||||
const {data, error} = useFetch(`/result/${uuid}/comb`, setLoading, 1)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user