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

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

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

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

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

Fil的区块奖励

Fil的区块奖励

总奖励已超38万,2021万向区块链黑客松赛题及奖励详解!

块奖励计数及其状态平衡