feat(TournamentPlacementsTab): implement knockout round ranking logic for non-qualified players
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 56s
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 56s
This commit is contained in:
@@ -368,6 +368,69 @@ export default {
|
||||
unique.push(p);
|
||||
}
|
||||
|
||||
// Bei einer K.-o.-Endrunde folgen die nicht qualifizierten Spieler
|
||||
// ihrer Vorrundenplatzierung. Gleiche Gruppenplätze teilen sich
|
||||
// dabei auch den Endplatz (z. B. beide Gruppendritten auf Platz 5).
|
||||
const preliminaryRankings = (this.groups || [])
|
||||
.filter(group =>
|
||||
(group.stageId === null || group.stageId === undefined)
|
||||
&& String(group.classId ?? 'null') === classKey
|
||||
)
|
||||
.flatMap(group => this.groupRankings[group.groupId] || []);
|
||||
|
||||
if (preliminaryRankings.length > 0) {
|
||||
const normalizedName = (firstName, lastName) =>
|
||||
`${firstName || ''} ${lastName || ''}`.trim().toLocaleLowerCase('de');
|
||||
const placedNames = new Set((byClass[classKey] || [])
|
||||
.map(entry => entry.displayName || normalizedName(entry.member?.firstName, entry.member?.lastName))
|
||||
.filter(Boolean)
|
||||
.map(name => String(name).trim().toLocaleLowerCase('de')));
|
||||
const knockoutEntrantNames = new Set((matchesByClass[classKey] || [])
|
||||
.flatMap(match => [match.player1, match.player2])
|
||||
.map(player => player?.member || player)
|
||||
.map(player => normalizedName(player?.firstName, player?.lastName))
|
||||
.filter(Boolean));
|
||||
const remainingByGroupPlace = new Map();
|
||||
|
||||
preliminaryRankings.forEach(ranking => {
|
||||
const name = String(ranking.name || '').trim();
|
||||
const normalizedRankingName = name.toLocaleLowerCase('de');
|
||||
if (!name || placedNames.has(normalizedRankingName) || knockoutEntrantNames.has(normalizedRankingName)) return;
|
||||
const groupPlace = Number(ranking.position);
|
||||
if (!Number.isFinite(groupPlace) || groupPlace < 1) return;
|
||||
if (!remainingByGroupPlace.has(groupPlace)) {
|
||||
remainingByGroupPlace.set(groupPlace, []);
|
||||
}
|
||||
remainingByGroupPlace.get(groupPlace).push(ranking);
|
||||
});
|
||||
|
||||
let nextPosition = Math.max(
|
||||
(byClass[classKey] || []).length,
|
||||
knockoutEntrantNames.size
|
||||
) + 1;
|
||||
[...remainingByGroupPlace.keys()].sort((a, b) => a - b).forEach(groupPlace => {
|
||||
const rankingsAtPlace = remainingByGroupPlace.get(groupPlace) || [];
|
||||
rankingsAtPlace.forEach(ranking => {
|
||||
const nameParts = String(ranking.name || '').trim().split(/\s+/);
|
||||
(byClass[classKey] ||= []).push({
|
||||
position: nextPosition,
|
||||
member: {
|
||||
id: ranking.id,
|
||||
firstName: nameParts.slice(0, -1).join(' '),
|
||||
lastName: nameParts.slice(-1).join(' '),
|
||||
},
|
||||
displayName: ranking.name,
|
||||
classId: classKey === 'null' ? null : Number(classKey),
|
||||
isExternal: ranking.isExternal || false,
|
||||
});
|
||||
});
|
||||
nextPosition += rankingsAtPlace.length;
|
||||
});
|
||||
|
||||
byClass[classKey] = (byClass[classKey] || []).sort((a, b) => Number(a.position) - Number(b.position));
|
||||
return;
|
||||
}
|
||||
|
||||
const maxPos = Math.max(0, ...(byClass[classKey] || []).map(e => Number(e.position) || 0));
|
||||
let nextPos = maxPos + 1;
|
||||
|
||||
@@ -765,4 +828,3 @@ table tbody td:first-child {
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user