@@ -495,6 +495,50 @@ impl GamesRepository {
495495 }
496496 } ) ;
497497 }
498+
499+ /// BGM 排名排序:优先按评分排序,同分时用官方排名补充排序。
500+ fn sort_by_bgm_rank ( games : & mut [ games:: Model ] , sort_order : SortOrder ) {
501+ let rank_desc = matches ! ( sort_order, SortOrder :: Desc ) ;
502+ games. sort_unstable_by ( |a, b| {
503+ let score_a = a
504+ . bgm_data
505+ . as_ref ( )
506+ . and_then ( |d| d. score )
507+ . filter ( |& s| s > 0.0 ) ;
508+ let score_b = b
509+ . bgm_data
510+ . as_ref ( )
511+ . and_then ( |d| d. score )
512+ . filter ( |& s| s > 0.0 ) ;
513+ let rank_a = a. bgm_data . as_ref ( ) . and_then ( |d| d. rank ) . filter ( |& r| r != 0 ) ;
514+ let rank_b = b. bgm_data . as_ref ( ) . and_then ( |d| d. rank ) . filter ( |& r| r != 0 ) ;
515+
516+ let rank_order = || match ( rank_a, rank_b) {
517+ ( Some ( ra) , Some ( rb) ) => {
518+ let ord = ra. cmp ( & rb) ;
519+ if rank_desc { ord. reverse ( ) } else { ord }
520+ }
521+ ( Some ( _) , None ) => std:: cmp:: Ordering :: Less ,
522+ ( None , Some ( _) ) => std:: cmp:: Ordering :: Greater ,
523+ ( None , None ) => std:: cmp:: Ordering :: Equal ,
524+ } ;
525+
526+ match ( score_a, score_b) {
527+ ( Some ( sa) , Some ( sb) ) => {
528+ let ord = match sort_order {
529+ SortOrder :: Asc => sb. partial_cmp ( & sa) ,
530+ SortOrder :: Desc => sa. partial_cmp ( & sb) ,
531+ }
532+ . unwrap_or ( std:: cmp:: Ordering :: Equal ) ;
533+ ord. then_with ( rank_order) . then_with ( || a. id . cmp ( & b. id ) )
534+ }
535+ ( Some ( _) , None ) => std:: cmp:: Ordering :: Less ,
536+ ( None , Some ( _) ) => std:: cmp:: Ordering :: Greater ,
537+ ( None , None ) => rank_order ( ) . then_with ( || a. id . cmp ( & b. id ) ) ,
538+ }
539+ } ) ;
540+ }
541+
498542 /// 从游戏记录中提取用于排序的显示名称
499543 ///
500544 /// 优先级与前端 `getGameDisplayName` 保持一致:
@@ -648,12 +692,9 @@ impl GamesRepository {
648692 . await
649693 }
650694 SortOption :: BGMRank => {
651- // bgm_data.rank:数值越小排名越靠前,无 rank 或 rank=0 置末尾
695+ // bgm_data.score:按“排名”语义排序,升序时高分靠前, rank 作为同分补充依据
652696 let mut games = Self :: build_base_query ( game_type) . all ( db) . await ?;
653- let desc = matches ! ( sort_order, SortOrder :: Desc ) ;
654- Self :: sort_by_optional_key ( & mut games, desc, |g| {
655- g. bgm_data . as_ref ( ) . and_then ( |d| d. rank ) . filter ( |& r| r != 0 )
656- } ) ;
697+ Self :: sort_by_bgm_rank ( & mut games, sort_order) ;
657698 Ok ( games)
658699 }
659700 SortOption :: VNDBRank => {
0 commit comments