@@ -274,10 +274,63 @@ const getContestParticipantsData = async (contest) => {
274274            return  [ ] ; 
275275        } 
276276        let  total  =  contest . rankings . length ; 
277+ 
278+         let  participantsMap  =  new  Map ( ) ; 
279+         contest . rankings . forEach ( ( rank ,  index )  =>  { 
280+             const  id  =  getUserId ( rank . _id ,  rank . data_region ) ; 
281+             participantsMap . set ( id ,  index ) ; 
282+         } ) ; 
277283        let  result  =  new  Array ( total ) , 
278284            failed  =  [ ] ; 
279285        let  limit  =  500 ; 
280286
287+         // if there was a contest withing last 24 hours then most probably ratings for last contest are not going to be updated on leetcode 
288+         // so it's better to use our predicted ratings for those participants who participated in the last contest 
289+         const  lowLimit  =  contest . startTime  -  24  *  60  *  60  *  1000 ;  // within 24 hours 
290+         const  upLimit  =  contest . startTime ; 
291+         const  lastContest  =  await  Contest . findOne ( 
292+             {  startTime : {  $gte : lowLimit ,  $lt : upLimit  }  } , 
293+             {  _id : 1  } 
294+         ) . sort ( {  startTime : - 1  } ) ; 
295+ 
296+         // if there was a contest within last 24 hours 
297+         if  ( lastContest )  { 
298+             // participants' username list 
299+             const  handles  =  contest . rankings . map ( ( rank )  =>  { 
300+                 return  rank . _id ; 
301+             } ) ; 
302+ 
303+             // get rating predictions from last contest 
304+             const  predictedRatings  =  await  Contest . aggregate ( [ 
305+                 { 
306+                     $project : { 
307+                         _id : 1 , 
308+                         "rankings._id" : 1 , 
309+                         "rankings.current_rating" : 1 , 
310+                         "rankings.delta" : 1 , 
311+                         "rankings.data_region" : 1 , 
312+                     } , 
313+                 } , 
314+                 {  $match : {  _id : lastContest . _id  }  } , 
315+                 {  $unwind : "$rankings"  } , 
316+                 {  $match : {  "rankings._id" : {  $in : handles  }  }  } , 
317+             ] ) ; 
318+ 
319+             // add predicted ratings'data in result 
320+             if  ( predictedRatings )  { 
321+                 predictedRatings . map ( ( itm )  =>  { 
322+                     itm  =  itm . rankings ; 
323+                     const  id  =  getUserId ( itm . _id ,  itm . data_region ) ; 
324+                     if  ( participantsMap . has ( id ) )  { 
325+                         result [ participantsMap . get ( id ) ]  =  { 
326+                             isFirstContest : false ,  // always false because user participated in minimum two contests 
327+                             rating : itm . current_rating  +  itm . delta , 
328+                         } ; 
329+                     } 
330+                 } ) ; 
331+             } 
332+         } 
333+ 
281334        const  getCurrentRatingHelper  =  async  ( index ,  isFailed  =  false )  =>  { 
282335            let  userData  =  await  getCurrentRating ( 
283336                contest . rankings [ index ] . user_slug , 
@@ -289,15 +342,21 @@ const getContestParticipantsData = async (contest) => {
289342                failed . push ( index ) ; 
290343            } 
291344        } ; 
345+ 
346+         // get progress in percentage 
292347        const  getPercentage  =  ( done ,  total )  =>  { 
293348            if  ( total  <=  0 )  { 
294349                return  - 1 ; 
295350            } 
296351            return  Math . round ( ( ( done  *  100 )  /  total )  *  100 )  /  100 ; 
297352        } ; 
353+ 
354+         // TODO: fetch ratings in one query for all the users who are already saved in db 
355+ 
298356        for  ( let  i  =  0 ;  i  <  total ;  i  +=  limit )  { 
299357            let  promises  =  [ ] ; 
300358            for  ( let  j  =  0 ;  j  <  limit  &&  i  +  j  <  total ;  j ++ )  { 
359+                 if  ( result [ i  +  j ] )  continue ;  // skip if already fetched 
301360                promises . push ( getCurrentRatingHelper ( i  +  j ) ) ; 
302361            } 
303362            await  Promise . all ( promises ) ; 
@@ -308,6 +367,7 @@ const getContestParticipantsData = async (contest) => {
308367                ) }  %)`
309368            ) ; 
310369        } 
370+ 
311371        let  failedRanks ; 
312372        const  retry  =  async  ( limit )  =>  { 
313373            console . log ( "Total failed: " ,  failedRanks . length ,  "limit: " ,  limit ) ; 
0 commit comments