@@ -259,17 +259,21 @@ func (s *server) GetPlayerTopTimes(ctx context.Context, request GetPlayerTopTime
259259 }
260260
261261 // Use a redis pipeline to avoid network rtt
262+ // Use ZCOUNT to count players with strictly lower times (to handle ties).
263+ // E.g. if 6 players share the same time, ZCOUNT returns 0 for all of them, so they all get rank 1.
262264 cmds := make (rueidis.Commands , len (bestTimes ))
263265 for i , bt := range bestTimes {
264266 leaderboardKey := mapLeaderboardKey (bt .MapID , "playtime" )
265- cmds [i ] = s .redis .B ().Zrank ().Key (leaderboardKey ).
266- Member (string (common .UUIDToBin (request .PlayerId ))).Build ()
267+ roundedPlaytime := int (math .Round (float64 (bt .Playtime )/ 50.0 )) * 50
268+ threshold := roundedPlaytime - 25
269+ cmds [i ] = s .redis .B ().Zcount ().Key (leaderboardKey ).
270+ Min ("-inf" ).Max (fmt .Sprintf ("(%d" , threshold )).Build ()
267271 }
268272
269273 // Exec pipeline
270274 results := s .redis .DoMulti (ctx , cmds ... )
271275
272- // Collect only entries with valid ranks (!= -1)
276+ // Collect entries - ZCOUNT returns the count of players with better times
273277 type rankedEntry struct {
274278 MapID string
275279 PublishedID int
@@ -279,11 +283,7 @@ func (s *server) GetPlayerTopTimes(ctx context.Context, request GetPlayerTopTime
279283 }
280284 var entries []rankedEntry
281285 for i , resp := range results {
282- rank , err := resp .AsInt64 ()
283- if errors .Is (err , rueidis .Nil ) {
284- // Player not on this leaderboard, skip
285- continue
286- }
286+ betterCount , err := resp .AsInt64 ()
287287 if err != nil {
288288 s .log .Warnw ("failed to get rank for map" , "mapId" , bestTimes [i ].MapID , "error" , err )
289289 continue
@@ -299,12 +299,14 @@ func (s *server) GetPlayerTopTimes(ctx context.Context, request GetPlayerTopTime
299299 publishedID = * bestTimes [i ].PublishedID
300300 }
301301
302+ // Round playtime to 50ms for display (consistent with rank calculation)
303+ roundedPlaytime := int (math .Round (float64 (bestTimes [i ].Playtime )/ 50.0 )) * 50
302304 entries = append (entries , rankedEntry {
303305 MapID : bestTimes [i ].MapID ,
304306 PublishedID : publishedID ,
305307 MapName : mapName ,
306- Playtime : bestTimes [ i ]. Playtime ,
307- Rank : int (rank ) + 1 , // Convert 0-indexed to 1-indexed
308+ Playtime : roundedPlaytime ,
309+ Rank : int (betterCount ) + 1 , // Rank = count of better times + 1
308310 })
309311 }
310312
0 commit comments