第七节:多维度排行版方案落地(普通版、升级版)
一. 前言
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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。

浙公网安备 33010602011771号