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

3 篇文章 1 订阅
2 篇文章 0 订阅
本文档描述了一种复杂的情况,即在区块链应用中处理节点奖励的计算问题。涉及的数据对象包括UserBean和NotPageListBean,以及相关的接口和辅助类。计算过程包括从树状结构自底向上拆分链路计算,自顶向下统计,同时处理链路上的分摊投资总额和用户链路数。此外,还展示了如何初始化和计算数据,以及如何插入和发放奖金到待领取表中。整个计算逻辑涉及到多个步骤和条件判断,确保了节点奖励的准确分配。
摘要由CSDN通过智能技术生成

前言

  • 在当下区块链相关的应用项目种,一般会有质押奖励、锁仓奖励、节点奖励等等奖励。最为头疼的就是节点奖励。应为他的逻辑太过于复杂。从树状结构计算又需要拆分链路至上往下计算,从下往上统计数据。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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");

    }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值