区块链项目节点奖励逻辑封装

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(String date);

    //节点奖励-获取最末端用户数据
    List<UserBean> getBranchUserList(String date);

    //获取当前未计算的理财包数据
    List<Map<String, Object>> getNotPageList(String date);

    //这次计算完成后,将刚刚未计算的理财包数据记录
    void insertNotPageList(List<Map<String, Object>> list,String date);

    //发放奖金到待领取表中,等待转账时间进行发放
    void insertLogMoeny(List<Map<String,Object>> maps25,List<Map<String,Object>> maps75);


执行助手类

package com.ruoyi.business.jdreward;

import com.ruoyi.business.jdreward.bean.UserBean;
import com.ruoyi.common.enums.ZzTypeEnum;
import com.utils.MyMath;
import com.utils.VerifyUtil;
import com.utils.exceptinos.OutException;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 节点奖励逻辑封装
 */
public class JdWardHelper 
    //用户列表
    List<UserBean> userList;
    //记录普通用户父类不包含自己
    Map<String, Object> branchUserMap;
    //记录从下往上记录节点父类用户 节点大于1的 包括自己
    Map<String, Object> branchUserMapNode;
    //记录普通用户父类包含自己
    Map<String, Object> branchUserMapAll;
    JdWardTools jdWardTools;

    JdWardData jdWardData;

    boolean isDeBug;
    String date;

    public JdWardHelper(JdWardData jdWardData, boolean isDeBug, String dateStr) 
        this.jdWardData = jdWardData;
        this.isDeBug = isDeBug;
        this.date = dateStr;
        initData();
    

    /**
     * 链路数据
     */
    private Map<String, Object> linkData = new HashMap<>();
    /**
     * 链路数据
     */
    private Map<String, Object> linkDataAll = new HashMap<>();

    public static String getDate(String dateStr) 
        if (VerifyUtil.isEmpty(dateStr)) 
            return VerifyUtil.getDate();
         else 
            dateStr=dateStr+" 23:59:59";
            System.out.println(dateStr);
            //创建SimpleDateFormat对象实例并定义好转换格式
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
//            System.out.println("把当前时间转换成字符串:" + sdf.format(new Date()));
            Date date = null;
            try 
                // 注意格式需要与上面一致,不然会出现异常
                date = sdf.parse(dateStr);
             catch (ParseException e) 
                e.printStackTrace();
                System.out.println("=====================时间格式不正确yyyyMMdd");
                return VerifyUtil.getDate();
//                throw new OutException("时间格式不正确yyyyMMdd");
            
            String dataFromYMDHMS = VerifyUtil.getDataFromYMDHMS(date);
            return dataFromYMDHMS;
        
    

    public static void main(String[] args) 
        System.out.println(getDate("20210620"));
        System.out.println(getDate("20210520"));
        System.out.println(getDate("20210610"));
        System.out.println(getDate("20210612"));
        System.out.println(getDate("2020"));
        System.out.println(getDate("2024550"));
    

    /**
     * 初始化数据
     */
    public void initData() 
        //节点奖励-获取所有用户并且与他购买的资产包数据
        userList = jdWardData.getUserList(date);
        //获取需要计算的理财包数据,该数据以在userList allMoney 中合并统计
        List<Map<String, Object>> notPageList = jdWardData.getNotPageList(date);
        //计算工具
        jdWardTools = new JdWardTools(userList);
        //记录链路数据量不包含自己
        branchUserMap = new HashMap<>();
        //记录链路数据量不包含自己节点数据
        branchUserMapNode = new HashMap<>();
        //记录链路数据量包含自己
        branchUserMapAll = new HashMap<>();
        List<UserBean> branchUserList = jdWardData.getBranchUserList(date);
        //从末端数据记录链路数据
        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(linkDataAll));
        insertMoney();
        if (!isDeBug) 
            //记录计算完后的理财包数据
            jdWardData.insertNotPageList(notPageList, date);
        

    

    /**
     * 记录金额
     */
    private void insertMoney() 
        List<Map<String, Object>> list25 = new ArrayList<>();
        List<Map<String, Object>> list75 = new ArrayList<>();
        for (String userId : linkDataAll.keySet()) 
            String money = linkDataAll.get(userId) + "";
            System.out.println("userId:" + userId + "____money:" + money);
            String money25 = MyMath.testToFixed("%s*0.25", 8, money);
            String money75 = MyMath.testToFixed("%s*0.75", 8, money);
            Map<String, Object> map25 = new HashMap<>();
            map25.put("id", UUID.randomUUID().toString());
            map25.put("lcLogId", "");
            map25.put("userId", userId);
            map25.put("cTime", date);
            map25.put("moneyNum", money25);
            map25.put("payDate", date);
            map25.put("moneyType", ZzTypeEnum.DL_25_MONEY.code);
            map25.put("moneyTypeDes", ZzTypeEnum.DL_25_MONEY.des);
            list25.add(map25);

            Map<String, Object> map75 = new HashMap<>();
            map75.put("id", UUID.randomUUID().toString());
            map75.put("lcLogId", "");
            map75.put("userId", userId);
            map75.put("lcId", "");
            map75.put("cTime", date);
            map75.put("payTime", date);
            map75.put("allNum", money75);
            map75.put("lcNumber", "");
            map75.put("moneyType", ZzTypeEnum.DL_75_MONEY.code);
            map75.put("moneyTypeDes", ZzTypeEnum.DL_75_MONEY.des);
            list75.add(map75);
        
        if (!isDeBug) 
            jdWardData.insertLogMoeny(list25,list75);
        
    


    /**
     * 计算奖励
     * 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(userList, 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.testToFixed("%s*%s", 8, 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(userList, 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.testToFixed("%s-%s*%s", 8, newAddLinkNewMoney, willSy, newAddP);
                break;
             else 
                String linkNewAddItem = getLinkNewAdd(nextUserId, lineCode, "end");
                newAddLinkNewMoney = MyMath.testToFixed("%s-%s", 8, 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(userList, s);
            BigDecimal avgAllMoney = userBeanByUserId.getAvgAllMoney();
            String avgAllMoneyStr = "0";
            if (!VerifyUtil.isEmpty(avgAllMoney)) 
                avgAllMoneyStr = avgAllMoney.toString();
            
            allMoney = MyMath.testToFixed("%s+%s", 8, 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.testToFixed("%s/%s", 8, allMoneyStr, userBean.getLineNum() + "");
            userBean.setAvgAllMoney(new BigDecimal(avgAllMoney));
        
    



工具类

package com.ruoyi.business.jdreward;

import com.ruoyi.business.jdreward.bean.UserBean;
import com.utils.MyMath;
import com.utils.VerifyUtil;

import java.util.List;
import java.util.Map;

/**
 * 公用功能
 */
public class JdWardTools 
    List<UserBean> userList;

    public JdWardTools(List<UserBean> userList) 
        this.userList=userList;
    

    /**
     * 递归获取往上用户id数据
     * 普通用户
     *
     * @param parentId
     * @return
     */
    public String getPraentIds(String parentId) 
        String parentIds = "";
        for (UserBean userBean : userList) 
            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 : userList) 
            if ((parentId + "").equals(userBean.getUserId() + "")) 
                String userId = userBean.getUserId();
                String parentId1 = userBean.getParentId();
                String nodeRank = userBean.getNodeRank();
                if ((!VerifyUtil.isEmpty(nodeRank)) && MyMath.test2("%s>1", nodeRank))
                    parentIds += (userId + ",");
                parentIds += getPraentIds(parentId1);
            
        
        return parentIds;
    


    /**
     * 获取用户数据
     *
     * @param userId
     * @return
     */
    public UserBean getUserBeanByUserId(List<UserBean> userList, String userId) 
        for (UserBean userBean : userList) 
            if (userBean.getUserId().equals(userId))
                return userBean;
        
        return null;
    



数据装载

  @Override
    public List<UserBean> getUserList(String date) 
        List<UserBean> listUser = new ArrayList<>();
        // //节点奖励-获取所有用户并且与他购买的资产包数据
        Map<String, Object> param = new HashMap<>();
        param.put("baseDate", date);
        List<Map<String, Object>> list = apiSql.runSqlByParam(param, "jsUser", "userPagerData");
        list.forEach(map -> 
            UserBean userBean = new UserBean();
            userBean.setAllMoney(new BigDecimal(VerifyUtil.isEmpty(map.get("allMoney") + "") ? "0" : 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(String date) 
        List<UserBean> listUser = new ArrayList<>();
        Map<String, Object> param = new HashMap<>();
        param.put("baseDate", date);
        //初始化节点用户
        List<Map<String, Object>> branchUserList = apiSql.runSqlByParam(param, "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(String date) 
        Map<String, Object> param = new HashMap<>();
        param.put("baseDate", date);
        List<Map<String, Object>> list1 = apiSql.runSqlByParam(param, "lc", "notPageList");
        return list1;
    

    @Override
    public void insertNotPageList(List<Map<String, Object>> list, String date) 
//        for (Map<String, Object> map : list) 
//            apiSql.insertTableMapNotKey(new HashMap<String, Object>() 
//                put("id", UUID.randomUUID().toString());
//                put("cTime", date);
//                put("lcLogId", map.get("id"));
//            , "t_node_log");
//        
        List<Map<String, Object>> list2 = new ArrayList<>();
        for (Map<String, Object> stringObjectMap : list) 
            Map<String, Object> item = new HashMap<>();
            item.put("id", UUID.randomUUID().toString());
            item.put("cTime", date);
            item.put("lcLogId", stringObjectMap.get("id"));
            list2.add(item);
        
        apiSql.insertListTableMapNotKey(list2, "t_node_log");
    

    @Override
    public void insertLogMoeny(List<Map<String, Object>> maps25, List<Map<String, Object>> maps75) 
        apiSql.insertListTableMapNotKey(maps25, "t_lc_package_item");
        apiSql.insertListTableMapNotKey(maps75, "t_lc_locked");

    

以上是关于区块链项目节点奖励逻辑封装的主要内容,如果未能解决你的问题,请参考以下文章

区块链项目节点奖励逻辑封装

链创未来——2018迅雷全球区块链应用大赛

Moledao web3.0 Hackathon 开启报名!超百万美元奖金等你拿

陪伴成长|区块链工程师能力认证项目启动BSV奖励计划

Fil的区块奖励

Fil的区块奖励