@@ -270,6 +270,11 @@ export default {
270270 type: Array ,
271271 default : () => [],
272272 },
273+ // The finished tournament's placements, for its final stage only.
274+ placements: {
275+ type: Array ,
276+ default : () => [],
277+ },
273278 },
274279 data() {
275280 return {
@@ -284,6 +289,15 @@ export default {
284289 if (this .onlyGroup != null ) return false ;
285290 return this .forceGroupHeading || this .totalGroups > 1 ;
286291 },
292+ placementByTeam() {
293+ const map = new Map <string , number >();
294+ for (const step of (this .placements as any []) || []) {
295+ if (step ?.tournament_team_id && Number (step .placement ) > 0 ) {
296+ map .set (String (step .tournament_team_id ), Number (step .placement ));
297+ }
298+ }
299+ return map ;
300+ },
287301 statsByPlayer() {
288302 const map = new Map <string , any >();
289303 for (const s of (this .playerStats as any []) || []) {
@@ -318,11 +332,21 @@ export default {
318332 for (const gn of numbers ) {
319333 if (this .onlyGroup != null && this .onlyGroup !== gn ) continue ;
320334 const rows = grouped .get (gn ) || [];
321- const sorted = rows
322- .slice ()
323- .sort (
324- (a : any , b : any ) => (Number (a .rank ) || 0 ) - (Number (b .rank ) || 0 ),
335+ const placementOf = (row : any ) =>
336+ this .placementByTeam .get (
337+ String (row .tournament_team_id || row .team ?.id ),
325338 );
339+ // A placed team ranks by its placement, which is what the podium
340+ // shows; the tiebreakers only order the teams after them.
341+ const sorted = rows .slice ().sort ((a : any , b : any ) => {
342+ const placedA = placementOf (a );
343+ const placedB = placementOf (b );
344+ if (placedA !== placedB ) {
345+ return (placedA ?? Infinity ) - (placedB ?? Infinity );
346+ }
347+ return (Number (a .rank ) || 0 ) - (Number (b .rank ) || 0 );
348+ });
349+ const placed = sorted .filter ((row : any ) => placementOf (row )).length ;
326350
327351 // Tied iff multiple teams share the same `placement` (RANK with ties)
328352 // from the API. `rank` itself is a deterministic ROW_NUMBER and never
@@ -336,20 +360,26 @@ export default {
336360 placementCounts .set (p , (placementCounts .get (p ) || 0 ) + 1 );
337361 }
338362
339- const entries = sorted .map ((row : any ) => ({
340- rank: Number (row .rank ) || 0 ,
341- teamId: row .tournament_team_id || row .team ?.id ,
342- teamLinkId: row .team ?.team ?.id || null ,
343- teamName: this .displayTeamName (
344- row .team ,
345- row .tournament_team_id || row .team ?.id ,
346- ),
347- wins: Number (row .wins ) || 0 ,
348- losses: Number (row .losses ) || 0 ,
349- matchesPlayed: Number (row .matches_played ) || 0 ,
350- tied: (placementCounts .get (Number (row .placement ) || 0 ) || 0 ) > 1 ,
351- roster: (row .team ?.roster || []).filter ((m : any ) => m ?.player ),
352- }));
363+ const entries = sorted .map ((row : any , index : number ) => {
364+ const placement = placementOf (row );
365+ return {
366+ rank: placement ?? (placed ? index + 1 : Number (row .rank ) || 0 ),
367+ teamId: row .tournament_team_id || row .team ?.id ,
368+ teamLinkId: row .team ?.team ?.id || null ,
369+ teamName: this .displayTeamName (
370+ row .team ,
371+ row .tournament_team_id || row .team ?.id ,
372+ ),
373+ wins: Number (row .wins ) || 0 ,
374+ losses: Number (row .losses ) || 0 ,
375+ matchesPlayed: Number (row .matches_played ) || 0 ,
376+ tied: placement
377+ ? sorted .filter ((other : any ) => placementOf (other ) === placement )
378+ .length > 1
379+ : (placementCounts .get (Number (row .placement ) || 0 ) || 0 ) > 1 ,
380+ roster: (row .team ?.roster || []).filter ((m : any ) => m ?.player ),
381+ };
382+ });
353383 out .push ({
354384 number: gn ,
355385 display: this .groupDisplay (gn ),
0 commit comments