1- import { Competition , Cutoff , Round , parseActivityCode } from '@wca/helpers' ;
1+ import { Cutoff , Round , parseActivityCode } from '@wca/helpers' ;
22import classNames from 'classnames' ;
33import { useMemo , useState } from 'react' ;
44import { Trans , useTranslation } from 'react-i18next' ;
55import { Link } from 'react-router-dom' ;
66import { Popover } from 'react-tiny-popover' ;
77import { renderCentiseconds , renderCutoff } from '@/lib/results' ;
8+ import { getEventRoundsForRound , joinLabels } from '@/lib/roundLabels' ;
89import { CompatibleRound , getAdvancementConditionForRound , ResultCondition } from '@/lib/wcif' ;
910import { useWCIF } from '@/providers/WCIFProvider' ;
1011
@@ -92,7 +93,7 @@ export function CutoffTimeLimitPanel({
9293 </ div >
9394 { advancement && (
9495 < div className = "px-2" >
95- { renderAdvancementText ( t , advancement . sourceType , advancement ) }
96+ { renderAdvancementText ( t , eventRounds , advancement . sourceType , advancement ) }
9697 </ div >
9798 ) }
9899 </ div >
@@ -103,117 +104,108 @@ export function CutoffTimeLimitPanel({
103104 ) ;
104105}
105106
106- function getEventRoundsForRound ( events : Competition [ 'events' ] | undefined , roundId : string ) {
107- const { eventId } = parseActivityCode ( roundId ) ;
108-
109- return (
110- events
111- ?. find ( ( event ) => event . id === eventId )
112- ?. rounds ?. map ( ( candidate ) => candidate as CompatibleRound ) || [ ]
113- ) ;
114- }
115-
116107function getCumulativeRoundIds ( timeLimit : Round [ 'timeLimit' ] , roundId : string ) {
117108 return timeLimit ?. cumulativeRoundIds . filter ( ( activityCode ) => activityCode !== roundId ) || [ ] ;
118109}
119110
120111function renderAdvancementText (
121112 t : ReturnType < typeof useTranslation > [ 't' ] ,
113+ eventRounds : CompatibleRound [ ] ,
122114 sourceType : 'registrations' | 'round' | 'linkedRounds' ,
123115 advancement : NonNullable < ReturnType < typeof getAdvancementConditionForRound > > ,
124116) {
125- const isLinkedRounds = sourceType === 'linkedRounds' ;
117+ if ( sourceType === 'linkedRounds' ) {
118+ return renderLinkedRoundsAdvancementText ( t , eventRounds , advancement ) ;
119+ }
120+
121+ return renderSingleRoundAdvancementText ( t , eventRounds , advancement ) ;
122+ }
123+
124+ function renderLinkedRoundsAdvancementText (
125+ t : ReturnType < typeof useTranslation > [ 't' ] ,
126+ eventRounds : CompatibleRound [ ] ,
127+ advancement : NonNullable < ReturnType < typeof getAdvancementConditionForRound > > ,
128+ ) {
126129 const { resultCondition } = advancement ;
127- const sourceRoundNames = advancement . sourceRoundIds . map ( ( roundId ) =>
128- activityCodeToRoundName ( t , roundId ) ,
129- ) ;
130+ const sourceRoundNames = advancement . sourceRoundIds . map ( ( roundId ) => {
131+ const roundNumber = parseActivityCode ( roundId ) . roundNumber ;
132+ return roundNumber ? roundNumber . toString ( ) : '' ;
133+ } ) ;
130134 const sourceRoundsLabel = joinLabels ( sourceRoundNames ) ;
135+ const targetLabel = getAdvancementTargetLabel ( t , eventRounds , advancement . targetRoundId ) ;
131136
132137 switch ( resultCondition . type ) {
133138 case 'ranking' :
134- return isLinkedRounds ? (
135- < >
136- { t ( 'common.wca.advancement.linkedRanking' , {
137- defaultValue : 'Top {{level}} combined across {{rounds}} advance to next round' ,
138- level : resultCondition . value ,
139- rounds : sourceRoundsLabel ,
140- } ) }
141- </ >
142- ) : (
143- < Trans
144- i18nKey = { 'common.wca.advancement.ranking' }
145- values = { { level : resultCondition . value } }
146- components = { { b : < span className = "font-semibold" /> } }
147- />
148- ) ;
139+ return t ( 'common.wca.advancement.linkedRanking' , {
140+ level : resultCondition . value ,
141+ rounds : sourceRoundsLabel ,
142+ what : targetLabel ,
143+ } ) ;
149144 case 'percent' :
150- return isLinkedRounds ? (
151- < >
152- { t ( 'common.wca.advancement.linkedPercent' , {
153- defaultValue : 'Top {{level}}% combined across {{rounds}} advance to next round' ,
154- level : resultCondition . value ,
155- rounds : sourceRoundsLabel ,
156- } ) }
157- </ >
158- ) : (
159- < Trans
160- i18nKey = { 'common.wca.advancement.percent' }
161- values = { { level : resultCondition . value } }
162- components = { { b : < span className = "font-semibold" /> } }
163- />
164- ) ;
165- case 'resultAchieved' : {
166- const thresholdCondition = resultCondition as Extract <
167- ResultCondition ,
168- { type : 'resultAchieved' }
169- > ;
170- const scopeLabel = t ( `common.wca.resultType.${ thresholdCondition . scope } ` , {
171- defaultValue : thresholdCondition . scope ,
172- } ) . toLowerCase ( ) ;
173- const resultValue =
174- thresholdCondition . value === null
175- ? t ( 'common.wca.advancement.resultThresholdUnknown' , {
176- defaultValue : 'an unknown result' ,
177- } )
178- : renderCentiseconds ( thresholdCondition . value ) ;
179-
180- return (
181- < >
182- { t (
183- isLinkedRounds
184- ? 'common.wca.advancement.linkedResultAchieved'
185- : 'common.wca.advancement.resultAchieved' ,
186- {
187- scope : scopeLabel ,
188- result : resultValue ,
189- rounds : sourceRoundsLabel ,
190- } ,
191- ) }
192- </ >
193- ) ;
194- }
145+ return t ( 'common.wca.advancement.linkedPercent' , {
146+ level : resultCondition . value ,
147+ rounds : sourceRoundsLabel ,
148+ what : targetLabel ,
149+ } ) ;
150+ case 'resultAchieved' :
151+ return t ( 'common.wca.advancement.linkedResultAchieved' , {
152+ scope : t ( `common.wca.advancement.scope.${ resultCondition . scope } ` ) ,
153+ result :
154+ resultCondition . value === null
155+ ? t ( 'common.wca.advancement.resultThresholdUnknown' )
156+ : renderCentiseconds ( resultCondition . value ) ,
157+ rounds : sourceRoundsLabel ,
158+ what : targetLabel ,
159+ } ) ;
195160 }
196161}
197162
198- function activityCodeToRoundName ( t : ReturnType < typeof useTranslation > [ 't' ] , roundId : string ) {
199- const { roundNumber } = parseActivityCode ( roundId ) ;
163+ function renderSingleRoundAdvancementText (
164+ t : ReturnType < typeof useTranslation > [ 't' ] ,
165+ eventRounds : CompatibleRound [ ] ,
166+ advancement : NonNullable < ReturnType < typeof getAdvancementConditionForRound > > ,
167+ ) {
168+ const { resultCondition } = advancement ;
169+ const targetLabel = getAdvancementTargetLabel ( t , eventRounds , advancement . targetRoundId ) ;
200170
201- return t ( 'common.activityCodeToName.round' , {
202- defaultValue : `Round ${ roundNumber } ` ,
203- roundNumber,
204- } ) ;
171+ switch ( resultCondition . type ) {
172+ case 'ranking' :
173+ return t ( 'common.wca.advancement.ranking' , {
174+ level : resultCondition . value ,
175+ what : targetLabel ,
176+ } ) ;
177+ case 'percent' :
178+ return t ( 'common.wca.advancement.percent' , {
179+ level : resultCondition . value ,
180+ what : targetLabel ,
181+ } ) ;
182+ case 'resultAchieved' :
183+ return t ( 'common.wca.advancement.resultAchieved' , {
184+ scope : t ( `common.wca.advancement.scope.${ resultCondition . scope } ` ) ,
185+ result :
186+ resultCondition . value === null
187+ ? t ( 'common.wca.advancement.resultThresholdUnknown' )
188+ : renderCentiseconds ( resultCondition . value ) ,
189+ what : targetLabel ,
190+ } ) ;
191+ }
205192}
206193
207- function joinLabels ( labels : string [ ] ) {
208- if ( labels . length <= 1 ) {
209- return labels [ 0 ] || '' ;
194+ function getAdvancementTargetLabel (
195+ t : ReturnType < typeof useTranslation > [ 't' ] ,
196+ eventRounds : CompatibleRound [ ] ,
197+ targetRoundId : string | null | undefined ,
198+ ) {
199+ if ( ! targetRoundId ) {
200+ return t ( 'common.wca.advancement.unknown' ) ;
210201 }
211202
212- if ( labels . length === 2 ) {
213- return `${ labels [ 0 ] } and ${ labels [ 1 ] } ` ;
203+ const targetRoundIndex = eventRounds . findIndex ( ( candidate ) => candidate . id === targetRoundId ) ;
204+ if ( targetRoundIndex === eventRounds . length - 1 ) {
205+ return t ( 'common.wca.advancement.final' ) ;
214206 }
215207
216- return ` ${ labels . slice ( 0 , - 1 ) . join ( ', ' ) } , and ${ labels [ labels . length - 1 ] } ` ;
208+ return t ( 'common.wca.advancement.nextRound' ) ;
217209}
218210
219211function CutoffTimeLimitPopover ( { cutoff } : { cutoff : Cutoff | null } ) {
0 commit comments