@@ -202,50 +202,69 @@ export const augmentStandingsWithIRating = (
202202 * @param driverClass - The class of the player
203203 * @param options.buffer - The number of drivers to include before and after the player
204204 * @param options.numNonClassDrivers - The number of drivers to include in classes outside of the player's class
205+ * @param options.minPlayerClassDrivers - The minimum number of drivers to include in the player's class
206+ * @param options.numTopDrivers - The number of top drivers to always include in the player's class
205207 * @returns The sliced standings
206208 */
207209export const sliceRelevantDrivers = < T extends { isPlayer ?: boolean } > (
208210 groupedStandings : [ string , T [ ] ] [ ] ,
209211 driverClass : string | number | undefined ,
210- { buffer = 3 , numNonClassDrivers = 3 } = { }
212+ {
213+ buffer = 3 ,
214+ numNonClassDrivers = 3 ,
215+ minPlayerClassDrivers = 10 ,
216+ numTopDrivers = 3 ,
217+ } = { }
211218) : [ string , T [ ] ] [ ] => {
212- // this is honestly a bit too complicated to maintain so after some testing will
213- // probably simplify it so its a bit more readable
214219 return groupedStandings . map ( ( [ classIdx , standings ] ) => {
215220 const playerIndex = standings . findIndex ( ( driver ) => driver . isPlayer ) ;
216221 if ( String ( driverClass ) !== classIdx ) {
217- // if player is not in this class, return only top 3 drivers in that class
222+ // if player is not in this class, return only top N drivers in that class
218223 return [ classIdx , standings . slice ( 0 , numNonClassDrivers ) ] ;
219224 }
220225
221- // if there are less than 10 drivers, return all
222- if ( standings . length <= 10 ) return [ classIdx , standings ] ;
226+ // if there are less than minPlayerClassDrivers drivers, return all of them
227+ if ( standings . length <= minPlayerClassDrivers ) {
228+ return [ classIdx , standings ] ;
229+ }
223230
224- // take the player and a buffer of drivers before and after the player
225- const start = Math . max ( playerIndex - buffer , 0 ) ;
226- let end = Math . min ( playerIndex + buffer + 1 , standings . length ) ;
231+ // when no player is found, just return the top `minPlayerClassDrivers`
232+ if ( playerIndex === - 1 ) {
233+ return [ classIdx , standings . slice ( 0 , minPlayerClassDrivers ) ] ;
234+ }
227235
228- if ( playerIndex <= 3 ) {
229- // if player is in top 3, include more drivers at the end
230- end = Math . min (
231- playerIndex + buffer + 3 - playerIndex + 1 ,
232- standings . length
233- ) ;
236+ const relevantDrivers = new Set < T > ( ) ;
237+
238+ // Add top drivers
239+ for ( let i = 0 ; i < numTopDrivers ; i ++ ) {
240+ if ( standings [ i ] ) {
241+ relevantDrivers . add ( standings [ i ] ) ;
242+ }
234243 }
235244
236- const sliced = standings . slice ( start , end ) ;
237-
238- if ( playerIndex > 3 ) {
239- // add back top 3 but don't include overlapping indexes
240- // reverse to add in correct order when doing array unshift
241- standings
242- . slice ( 0 , 3 )
243- . reverse ( )
244- . forEach ( ( driver ) => {
245- if ( ! sliced . includes ( driver ) ) sliced . unshift ( driver ) ;
246- } ) ;
245+ // Add drivers around the player
246+ const start = Math . max ( 0 , playerIndex - buffer ) ;
247+ const end = Math . min ( standings . length , playerIndex + buffer + 1 ) ;
248+ for ( let i = start ; i < end ; i ++ ) {
249+ if ( standings [ i ] ) {
250+ relevantDrivers . add ( standings [ i ] ) ;
251+ }
252+ }
253+
254+ // Ensure we have at least `minPlayerClassDrivers`
255+ let lastIndex = end ;
256+ while (
257+ relevantDrivers . size < minPlayerClassDrivers &&
258+ lastIndex < standings . length
259+ ) {
260+ relevantDrivers . add ( standings [ lastIndex ] ) ;
261+ lastIndex ++ ;
247262 }
248263
249- return [ classIdx , sliced ] ;
264+ const sortedDrivers = [ ...relevantDrivers ] . sort (
265+ ( a , b ) => standings . indexOf ( a ) - standings . indexOf ( b )
266+ ) ;
267+
268+ return [ classIdx , sortedDrivers ] ;
250269 } ) ;
251270} ;
0 commit comments