区块链项目节点奖励逻辑封装
Posted 热心市民刘先生♛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了区块链项目节点奖励逻辑封装相关的知识,希望对你有一定的参考价值。
前言
- 在当下区块链相关的应用项目种,一般会有质押奖励、锁仓奖励、节点奖励等等奖励。最为头疼的就是节点奖励。应为他的逻辑太过于复杂。从树状结构计算又需要拆分链路至上往下计算,从下往上统计数据。
bean 对象
@Data
public class UserBean {
//用户id
String userId;
//节点级别
String nodeRank;
//对应节点的奖励级别比例
String newAddP;
//父类id
String parentId;
//理财宝金额
BigDecimal allMoney;
// 以上为传递参数,以下为计算参数不需要传值
//分摊到每一条链路上的投资总额额度
BigDecimal avgAllMoney;
//该用户链路数
int lineNum;
}
@Data
public class NotPageListBean {
String lcLogId;
}
接口
public interface JdWardData {
//节点奖励-获取所有用户并且与他购买的资产包数据
List<UserBean> getUserList();
//节点奖励-获取最末端用户数据
List<UserBean> getBranchUserList();
//获取当前未计算的理财包数据
List<Map<String, Object>> getNotPageList();
//这次计算完成后,将刚刚未计算的理财包数据记录
void insertNotPageList(List<Map<String, Object>> list);
//发放奖金到待领取表中,等待转账时间进行发放
void insertLogMoeny(int tzDayIntger, String lcLogId, String money, String userId, ZzTypeEnum zzTypeEnum);
}
执行助手类
/**
* 节点奖励逻辑封装
*/
public class JdWardHelper {
//用户列表
List<UserBean> userList;
//记录普通用户父类不包含自己
Map<String, Object> branchUserMap;
//记录从下往上记录节点父类用户 节点大于1的 包括自己
Map<String, Object> branchUserMapNode;
//记录普通用户父类包含自己
Map<String, Object> branchUserMapAll;
JdWardTools jdWardTools;
JdWardData jdWardData;
public JdWardHelper(JdWardData jdWardData) {
this.jdWardData = jdWardData;
initData();
}
/**
* 链路数据
*/
private Map<String, Object> linkData = new HashMap<>();
/**
* 链路数据
*/
private Map<String, Object> linkDataAll = new HashMap<>();
/**
* 初始化数据
*/
public void initData() {
//节点奖励-获取所有用户并且与他购买的资产包数据
userList = jdWardData.getUserList();
//获取需要计算的理财包数据,该数据以在userList allMoney 中合并统计
List<Map<String, Object>> notPageList = jdWardData.getNotPageList();
//计算工具
jdWardTools = new JdWardTools(jdWardData);
//记录链路数据量不包含自己
branchUserMap = new HashMap<>();
//记录链路数据量不包含自己节点数据
branchUserMapNode = new HashMap<>();
//记录链路数据量包含自己
branchUserMapAll = new HashMap<>();
List<UserBean> branchUserList = jdWardData.getBranchUserList();
//从末端数据记录链路数据
for (UserBean userBean : branchUserList) {
//节点用户id
String id = userBean.getUserId();
String parentId = userBean.getParentId();
String parentIds = jdWardTools.getPraentIds(parentId);
parentIds = VerifyUtil.endClear(parentIds);
//记录普通用户父类不包含自己
branchUserMap.put(id, parentIds);
//记录从下往上记录节点父类用户 节点大于1的 包括自己
branchUserMapNode.put(id, id + "," + jdWardTools.getPraentIdsNode(parentId));
//记录普通用户父类包含自己
branchUserMapAll.put(id, id + "," + parentIds);
}
//初始化没个人链路数据,每个用户
initLineMumber();
//计算节点奖励数据
initAward();
System.out.println(VerifyUtil.toJson(linkData));
insertMoney();
//记录计算完后的理财包数据
jdWardData.insertNotPageList(notPageList);
}
/**
* 记录金额
*/
private void insertMoney() {
for (String userId : linkDataAll.keySet()) {
String money = linkDataAll.get(userId) + "";
jdWardData.insertLogMoeny(1, "", money, userId, ZzTypeEnum.DL_MONEY);
}
}
/**
* 计算奖励
* 1.节点数据从下往上算,先算下面的节点收益再往上算节点收益
* 2.计算节点收益从上往下去减
*/
private void initAward() {
/**
* 所有链路
* 便利节点用户
* */
for (String lineCode : branchUserMapNode.keySet()) {
//s链路数据
//链路节点的数据包含自己的
String lineData = branchUserMapNode.get(lineCode) + "";
//1.从下往上顺序
String[] split = lineData.split(",");
for (int i = 0; i < split.length; i++) {
//当前用户
String onUserId = split[i];
insertAddMoney(lineCode, lineData, onUserId);
}
}
}
/**
* 从上往下扣除子类的数据
*
* @param lineCode
* @param onUserId
*/
private void insertAddMoney(String lineCode, String lineData, String onUserId) {
UserBean userBeanByUserId = jdWardTools.getUserBeanByUserId(onUserId);
//用户级别
String onNodeRank = userBeanByUserId.getNodeRank();
if (VerifyUtil.isEmpty(onNodeRank)) onNodeRank = "0";
//当前链路下的平均收益
String onWillSy = getWillSy(lineCode, onUserId);
String newAddP = userBeanByUserId.getNewAddP();
if (VerifyUtil.isEmpty(newAddP)) newAddP = "0";
String newAddLinkNewMoney = MyMath.test("%s*%s", onWillSy, newAddP);
//从上往下链路
String nextClient = lineData.substring(0, lineData.indexOf(onUserId));
String[] split1 = nextClient.split(",");
for (int i1 = split1.length - 1; i1 > 0; i1--) {
//下一级的用户
String nextUserId = split1[i1];
UserBean nextUserBeanByUserId = jdWardTools.getUserBeanByUserId(nextUserId);
//下一级节点用户节点等级
String nextNodeRank = nextUserBeanByUserId.getNodeRank();
if (VerifyUtil.isEmpty(nextNodeRank)) nextNodeRank = "0";
if (MyMath.test2("%s<=%s", onNodeRank, nextNodeRank)) {
String willSy = getWillSy(lineCode, nextUserId);
newAddLinkNewMoney = MyMath.test("%s-%s*%s", newAddLinkNewMoney, willSy, newAddP);
break;
} else {
String linkNewAddItem = getLinkNewAdd(nextUserId, lineCode, "end");
newAddLinkNewMoney = MyMath.test("%s-%s", newAddLinkNewMoney, linkNewAddItem);
}
}
//记录当前链对应的用户数据
if (!MyMath.test2("%s==0", newAddLinkNewMoney)) {
putLinkNewAdd(onUserId, lineCode, newAddLinkNewMoney, "end");
}
}
/**
* 获取支链数据
*
* @param userId
* @param zlCode
* @param str 是否取原始数据
* @return
*/
private String getLinkNewAdd(String userId, String zlCode, String str) {
String s = linkData.get(userId + "_" + zlCode + str) + "";
return VerifyUtil.isEmpty(s) ? "0" : s;
}
/**
* 存入数据
*
* @param userId
* @param zlCode
* @param newAddLinkNewMoney
* @param str 是否存原始数
*/
private void putLinkNewAdd(String userId, String zlCode, String newAddLinkNewMoney, String str) {
linkData.put(userId + "_" + zlCode + str, newAddLinkNewMoney);
if ("end".equals(str)) {
String value = linkDataAll.get(userId) + "";
if (VerifyUtil.isEmpty(value)) value = "0";
linkDataAll.put(userId, MyMath.test("%s+%s", value, newAddLinkNewMoney));
}
}
/**
* 个人
* 获取单链路上以下的收益
*
* @param lineCode
* @param userId
* @return
*/
private String getWillSy(String lineCode, String userId) {
String userIds = branchUserMapAll.get(lineCode) + "";
String allMoney = "0";
String[] split = userIds.split(",");
for (String s : split) {
//从下检测到上,遇到当前自己则跳出
if (s.equals(userId)) break;
UserBean userBeanByUserId = jdWardTools.getUserBeanByUserId(s);
BigDecimal avgAllMoney = userBeanByUserId.getAvgAllMoney();
String avgAllMoneyStr = "0";
if (!VerifyUtil.isEmpty(avgAllMoney)) {
avgAllMoneyStr = avgAllMoney.toString();
}
allMoney = MyMath.test("%s+%s", allMoney, avgAllMoneyStr);
}
return allMoney;
}
/**
* 计算所有人的链路数,将总投资金额平台到每一条链路上,计算使用平摊后的链路
*/
private void initLineMumber() {
//计算每个用户有多少条链路
for (UserBean userBean : userList) {
for (String s : branchUserMapAll.keySet()) {
//链路
String s1 = branchUserMapAll.get(s) + "";
if (s1.contains(userBean.getUserId()))
userBean.setLineNum(userBean.getLineNum() + 1);
}
//计算平摊总投资金额
BigDecimal allMoney = userBean.getAllMoney();
String allMoneyStr = VerifyUtil.isEmpty(allMoney) ? "0" : allMoney.toString();
String avgAllMoney = MyMath.test("%s/%s", allMoneyStr, userBean.getLineNum() + "");
userBean.setAvgAllMoney(new BigDecimal(avgAllMoney));
}
}
}
工具类
/**
* 公用功能
*/
public class JdWardTools {
JdWardData jdWardData;
public JdWardTools(JdWardData jdWardData) {
this.jdWardData = jdWardData;
}
/**
* 递归获取往上用户id数据
* 普通用户
*
* @param parentId
* @return
*/
public String getPraentIds(String parentId) {
String parentIds = "";
for (UserBean userBean : jdWardData.getUserList()) {
if ((parentId + "").equals(userBean.getUserId() + "")) {
String userId = userBean.getUserId();
String parentId1 = userBean.getParentId();
parentIds += (userId + ",");
parentIds += getPraentIds(parentId1);
}
}
return parentIds;
}
/**
* 获取所有节点父类用户数据
* 节点用户
* 从下往上记录节点用户数据
*
* @param parentId
* @return
*/
public String getPraentIdsNode(String parentId) {
String parentIds = "";
for (UserBean userBean : jdWardData.getUserList()) {
if ((parentId + "").equals(userBean.getUserId() + "")) {
String userId = userBean.getUserId();
String parentId1 = userBean.getParentId();
if (MyMath.test2("%s>=2", userBean.getNodeRank()))
parentIds += (userId + ",");
parentIds += getPraentIds(parentId1);
}
}
return parentIds;
}
/**
* 获取用户数据
*
* @param userId
* @return
*/
public UserBean getUserBeanByUserId(String userId) {
for (UserBean userBean : jdWardData.getUserList()) {
if (userBean.getUserId().equals(userId))
return userBean;
}
return null;
}
}
数据装载
@Override
public List<UserBean> getUserList() {
List<UserBean> listUser = new ArrayList<>();
// //节点奖励-获取所有用户并且与他购买的资产包数据
List<Map<String, Object>> list = apiSql.runSqlByParam(new HashMap<String, Object>() {{
}}, "jsUser", "userPagerData");
list.forEach(map -> {
UserBean userBean = new UserBean();
userBean.setAllMoney(new BigDecimal(map.get("allMoney") + ""));
userBean.setUserId(map.get("userId") + "");
userBean.setNodeRank(map.get("gradeType") + "");
userBean.setNewAddP(map.get("syP") + "");
userBean.setParentId(map.get("parentId") + "");
listUser.add(userBean);
});
return listUser;
}
@Override
public List<UserBean> getBranchUserList() {
List<UserBean> listUser = new ArrayList<>();
//初始化节点用户
List<Map<String, Object>> branchUserList = apiSql.runSqlByParam(new HashMap<String, Object>() {{
}}, "jsUser", "userEndBranch");
branchUserList.forEach(map -> {
UserBean userBean = new UserBean();
userBean.setUserId(map.get("id") + "");
userBean.setParentId(map.get("parentId") + "");
listUser.add(userBean);
});
return listUser;
}
@Override
public List<Map<String, Object>> getNotPageList() {
List<Map<String, Object>> list1 = apiSql.runSqlByParam(new HashMap<String, Object>(), "lc", "notPageList");
return list1;
}
@Override
public void insertNotPageList(List<Map<String, Object>> list) {
for (Map<String, Object> map : list) {
apiSql.insertTableMapNotKey(new HashMap<String, Object>() {{
put("id", UUID.randomUUID().toString());
put("cTime", VerifyUtil.getDate());
put("lcLogId", map.get("id"));
}}, "t_node_log");
}
}
@Override
public void insertLogMoeny(int tzDayIntger, String lcLogId, String money, String userId, ZzTypeEnum zzTypeEnum) {
for (int i = 0; i < tzDayIntger; i++) {
Map<String, Object> item = new HashMap<>();
item.put("id", UUID.randomUUID().toString());
item.put("lcLogId", lcLogId);
item.put("userId", userId);
item.put("cTime", VerifyUtil.getDate());
item.put("moneyNum", money);
item.put("payDay", i);
item.put("moneyType", zzTypeEnum.code);
apiSql.exeSql(item, "lc", "insertLcPageItem");
}
}
以上是关于区块链项目节点奖励逻辑封装的主要内容,如果未能解决你的问题,请参考以下文章