上一章节我们已经编写了核心的预言机合约,并且部署测试成功,现在我们就来写基于# 前言 上一章节我们已经编写了核心的预言机合约,并且部署测试成功,现在我们就来写基于
抽奖接口主要是保证投票数和中奖率的正比关系。代码如下所示: 下图是模拟测试的抽奖结果展示: 如果合约被定时执行了,那么我们可以在Truora中看到如下图所示的信息: https://gitee.com/bckj_1/csdn 我们的抽奖的项目核心就是抽奖的逻辑和页面的展示以及最关键的智能合约的调用。到本篇文章就完结了,项目代码已经开源到了gitee, 方便大家研究,有兴趣的小伙伴可以关注一下!/** * 展示页面 * @param request * @return */ @RequestMapping("blockchain") public String index(HttpServletRequest request){ csdnService.getCsdnContent(); request.setAttribute("lst",csdnService.csdnList); request.setAttribute("sum",csdnService.sum); request.setAttribute("userName",csdnService.userName); return "2020csdn"; } /** * 获取csdn投票相关数据 */ public void getCsdnContent() { csdnList=new ArrayList<Csdn>(); sum=0; Map<String, Object> params = new HashMap<String, Object>(); params.put("username" , "ws327443752"); params.put("page" , "1"); params.put("pageSize" , "200"); String json = HttpUtil.post("https://bss.csdn.net/m/topic/blog_star2020/getRanking", params); JSONObject jsonObject= JSONUtil.parseObj(json); JSONArray ja= jsonObject.getJSONArray("data"); for (int i = 0; i < ja.size(); i++) { Csdn csdn=new Csdn(); JSON jsonStr = (JSON) ja.get(i); String uName = jsonStr.getByPath("nick_name").toString(); csdn.setName(uName); String voteNum = jsonStr.getByPath("voteNum").toString(); csdn.setVote(Integer.parseInt(voteNum)); sum+=csdn.getVote(); String level = jsonStr.getByPath("level").toString(); csdn.setLevel(Integer.parseInt(level)); String codeLevel = jsonStr.getByPath("codeLevel").toString(); csdn.setCodeLevel(Integer.parseInt(codeLevel)); int number = Integer.parseInt(jsonStr.getByPath("number").toString()); csdn.setNumber(number); csdnList.add(csdn); } }
1.抽奖接口
/** * 抽奖接口 * @return */ @RequestMapping("lottery") @ResponseBody public String lottery(){ String id = csdnService.handleLottery(); return id; } /** * 抽奖方法 * @param orignalRates 商品中奖概率列表,保证顺序和实际物品对应 * @return 中奖商品索引 */ public int lottery(List<Double> orignalRates) { if (orignalRates == null || orignalRates.isEmpty()) { return -1; } int size = orignalRates.size(); // 计算总概率,这样可以保证不一定总概率是1 double sumRate = 0d; for (double rate : orignalRates) { sumRate += rate; } // 计算每个物品在总概率的基础下的概率情况 List<Double> sortOrignalRates = new ArrayList<>(size); Double tempSumRate = 0d; for (double rate : orignalRates) { tempSumRate += rate; sortOrignalRates.add(tempSumRate / sumRate); } // 根据区块值来获取抽取到的物品索引 double nextDouble = Math.random(); sortOrignalRates.add(nextDouble); Collections.sort(sortOrignalRates); return sortOrignalRates.indexOf(nextDouble); } /** * 触发抽奖逻辑 * @return */ public String handleLottery() { List<NameDTO> nameDTOS = new ArrayList<>(); for (int i = 0; i < csdnList.size(); i++) { double f1 = new BigDecimal((float)csdnList.get(i).getVote()/sum).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue(); nameDTOS.add(new NameDTO(i + 1, csdnList.get(i).getName(), csdnList.get(i).getNumber() + "", f1)); } // 存储概率 List<Double> orignalRates = new ArrayList<>(nameDTOS.size()); for (NameDTO gift : nameDTOS) { double probability = gift.getProbability(); if (probability < 0) { probability = 0; } orignalRates.add(probability); } // 统计 Map<Integer, Integer> count = new HashMap<>(); // 次数 double num = 1; for (int i = 0; i < num; i++) { int orignalIndex = lottery(orignalRates); Integer value = count.get(orignalIndex); count.put(orignalIndex, value == null ? 1 : value + 1); } String id=null; for (Map.Entry<Integer, Integer> entry : count.entrySet()) { id=nameDTOS.get(entry.getKey()).getNo(); } return id; }
3.定时触发 我们宝塔设置指定的时间来访问url触发
4.项目整体代码地址
总结