第七节:多维度排行版方案落地(普通版、升级版)

一. 前言

1. 背景

(1) 船员系统主要有船管公司 和 船员公司,每个公司下都有很多船员,现在需要对船员进行积分排名。

(2) 主要用于: 薪酬激励、船员晋升、任务分配、需求培训 等等。

 

2. 积分规则

 (1).需要 主动 或 被动的将船员加入"积分排行体系",记录加入时间。

 (2).工龄核算:比如每满1年加10分

 (3).职位等级核算:船长100分、大副80分

 (4).教育背景:本科30分、硕士50分

 (5):证书核算:高级证书、操作证书 对应不同积分

 (6):履历核算:航行里程和航行时间核算积分

PS:加入的时候会核算一下积分,然后每天都会刷新一下积分

 

二. 需求1

1 说明

     统计加入积分排行体系船员个数、然后按照积分由高到低进行排序

2 原理

     使用ZSET结构,形如key-member-score, key为"px1",member为userId,score对应积分,然后使用ZRevRangeByScore方法,  获取从高到低的排序即可。

3 代码实操

  //key为船员Id,value为船员积分
  public Dictionary<string, long> CrewList = [];
  //key为船员Id,value为船员加入"积分体系"的时间戳
  public Dictionary<string, long> CrewList_JoinTime = [];

  /// <summary>
  /// 初始化船员信息1
  /// </summary>
  /// <returns></returns>
  [HttpPost]
  public IActionResult InitJoinCrewInfo1()
  {
      CrewList.Add("1001", 100);
      CrewList.Add("1002", 200);
      CrewList.Add("1003", 200);
      CrewList.Add("1004", 400);

      //使用ZSET结构
      foreach (var item in CrewList)
      {
          RedisHelper.ZAdd("px1", (item.Value, item.Key));
      }
      return Json(new { status = "ok", msg = "初始化成功", data = new { CrewList, CrewList_JoinTime } });
  }

  /// <summary>
  /// 根据积分由大到小排序
  /// </summary>
  /// <returns></returns>
  [HttpPost]
  public IActionResult RankByScore()
  {
      var list = RedisHelper.ZRevRangeByScore("px1", 10000000000, -1);
      return Json(new { status = "ok", msg = "查询成功", data = list });
  }

 

 

三. 需求2

1 说明

  在需求1的基础上,如果积分相同,按照“加入积分体系的时间”继续排序,先加入的(时间早的)排在上面

2 原理

   A. 将加入时间转换为13位时间戳,然后÷ 1e13, 转换成小数 (1e13表示1后面13个0)

   B. 时间越晚,转换成的小数的值越大, 而上述需求是时间早的排在上面,所以需要  1-timeStr/1e13

   C. 然后作为score的小数部分加入积分体系

   D. 使用ZRevRangeByScore方法,获取从高低排序即可

3 代码实操

    //key为船员Id,value为船员积分
    public Dictionary<string, long> CrewList = [];
    //key为船员Id,value为船员加入"积分体系"的时间戳
    public Dictionary<string, long> CrewList_JoinTime = [];

    /// <summary>
    /// 初始化船员信息2
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    public IActionResult InitJoinCrewInfo2()
    {
        CrewList.Add("1001", 100);
        CrewList.Add("1002", 200);
        CrewList.Add("1003", 200);
        CrewList.Add("1004", 400);

        DateTime nowTime = DateTime.Now;
        CrewList_JoinTime.Add("1001", ToUnixTimeMilliseconds(nowTime.AddDays(-80)));
        CrewList_JoinTime.Add("1002", ToUnixTimeMilliseconds(nowTime));
        CrewList_JoinTime.Add("1003", ToUnixTimeMilliseconds(nowTime.AddYears(3)));
        CrewList_JoinTime.Add("1004", ToUnixTimeMilliseconds(nowTime.AddDays(5)));

        //使用ZSET结构
        foreach (var item in CrewList)
        {
            var tempTime = CrewList_JoinTime.Where(u => u.Key.Equals(item.Key)).FirstOrDefault().Value;
            var score = item.Value + (1 - tempTime / 1e13);   //1e13表示 1后面13个0
            RedisHelper.ZAdd("px2", ((decimal)score, item.Key));
        }

        return Json(new { status = "初始化成功", msg = "", data = new { CrewList, CrewList_JoinTime } });
    }

    /// <summary>
    /// 04-根据积分由大到小排序,分数相同,先加入的在前面
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    public IActionResult RankByScore2()
    {

        var list = RedisHelper.ZRevRangeByScore("px2", 10000000000, -1);
        return Json(new { status = "ok", msg = "查询成功", data = list });
    } 

    /// <summary>
    /// 将时间转换为13位的时间戳
    /// </summary>
    /// <param name="dateTime">需要转换的时间</param>
    /// <returns></returns>
    public static long ToUnixTimeMilliseconds(DateTime dateTime)
    {
        // 转换为毫秒
        long unixMilliseconds = new DateTimeOffset(dateTime).ToUnixTimeMilliseconds();
        return unixMilliseconds;
    }

 

 

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2025-06-15 20:38  Yaopengfei  阅读(17)  评论(0)    收藏  举报