package com.m2pool.pool.task;

import com.m2pool.common.core.text.Convert;
import com.m2pool.common.core.utils.DateUtils;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.redis.service.RedisService;
import com.m2pool.pool.context.BlockDataContext;
import com.m2pool.pool.dto.*;
import com.m2pool.pool.entity.PoolPower;
import com.m2pool.pool.enums.PoolCalParamConfig;
import com.m2pool.pool.enums.PoolUnits;
import com.m2pool.pool.enums.Pools;
import com.m2pool.pool.mapper.PoolMapper;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description 矿池、矿机定时任务 主要处理算力数据和幸运值计算
 * 新增币种则新增定时任务 注意岔开处理时间
 * @Date 2024/6/14 14:03
 * @Author dy
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "task.data")
@EnableScheduling
public class DataTask {

    private boolean enable;

    @Autowired
    private PoolMapper poolMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private BlockDataContext blockDataContext;

    private static final Logger log = LoggerFactory.getLogger(DataTask.class);


     @Scheduled(cron = "20 1,3,10,31,33,40 * * * ?")
    public void NEXA30mDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
         if(!enable){
             System.out.println("DataTask 定时任务已关闭，请在nacos修改配置");
             return;
         }
        Date now = new Date();
        int minute = (now.getMinutes() / 30) * 30;
        now.setMinutes( minute);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        System.out.println("nexa 30分钟定时任务执行时间:"+now);
        System.out.println("格式化后的时间:"+nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.NEXA.getMhs() + "30m", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getHourMinerDataList(Pools.NEXA.getMhs()+"_realv2",nowStr);
            if(list.size() > 0){
                List<MinerDataDto> offlineList = new ArrayList<>();
                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.NEXA.getFac());
                    }
                    if("offline".equals(e.getState())){
                        offlineList.add(e);
                    }
                });
                list = filterList(list,now);

                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.NEXA.getMhs() + "30m", getToHourDBListByMinerDataList(list));

                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.NEXA.getPoolTable() + "_30m", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.NEXA.getPoolTable() + "_30m", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    System.out.println("构造写入user算力表数据");
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );
                    System.out.println("user算力表入库数据条数："+userList.size());
                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.NEXA.getName() + "_users_30m", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.NEXA.getName() + "_users_30m", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }




                });

                Map<String, List<MinerDataDto>> userMap = list.stream().collect(Collectors.groupingBy(MinerDataDto::getMiner));
                if (result) {
                    System.out.println(DateUtils.dateTimeNow() + "nexa小时数据存入数据成功");
                } else {
                    System.out.println(DateUtils.dateTimeNow() + "nexa小时数据存入数据失败");
                }

                if(offlineList.size() >0){
                    CompletableFuture.runAsync(()->{

                        //根据挖矿账户分组、统计离线矿机名单、离线矿机数

                        //对比redis中该挖矿账户上一次离线矿机数
                            //有redis数据 需要判断 上一次离线矿机数<本次矿机离线数 才执行通知 否则跳过
                            //无redis数据 说明是第一次 执行通知
                    });

                }

            }
            else{
                //重来一次！
                CompletableFuture.runAsync(()->{
                    System.out.println("nexa 30分钟定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.NEXA.getMhs() + "30m", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getHourMinerDataList(Pools.NEXA.getMhs()+"_realv2",nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.NEXA.getFac());
                                }
                            });
                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.NEXA.getMhs() + "30m", getToHourDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.NEXA.getPoolTable() + "_30m", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.NEXA.getPoolTable() + "_30m", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                System.out.println("延迟任务 构造写入user算力表数据");
                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );
                                System.out.println("延迟任务 user算力表入库数据条数："+userList.size());
                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.NEXA.getName() + "_users_30m", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.NEXA.getName() + "_users_30m", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });
                            if (newResult) {
                                System.out.println(DateUtils.dateTimeNow() + "nexa30m数据 延迟存入数据成功");
                            } else {
                                System.out.println(DateUtils.dateTimeNow() + "nexa30m数据 延迟存入数据失败");

                            }

                        }
                    }
                });

            }
        }

    }

     @Scheduled(cron = "0 1,3,5 0 * * ?")
    public void NEXADailyDataToDB(){
         if(!enable){
             return;
         }
        String nowStr = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
        Date now = DateUtils.parseDate( nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.NEXA.getMhs() + "24h", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getDailyMinerDataList(Pools.NEXA.getMhs()+"_realv2", nowStr);
            if(list.size() > 0){
                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.NEXA.getFac());
                    }
                });
                list = filterList(list,now);
                //list.stream().forEach(e ->{
                //    e.setDate(DateUtils.addDays(e.getDate(),-1));
                //});
                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.NEXA.getMhs() + "24h", getToDailyDBListByMinerDataList(list));
                //todo 统计矿池数据写入矿池数据库 $coin_pool_24h
                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.NEXA.getPoolTable() + "_24h", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.NEXA.getPoolTable() + "_24h", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    //写入数据到coin_users表中
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );

                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.NEXA.getName() + "_users_24h", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.NEXA.getName() + "_users_24h", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });
                if(result){
                    System.out.println(DateUtils.dateTimeNow()+"nexa每日存入数据成功");
                }else {
                    System.out.println(DateUtils.dateTimeNow()+"nexa每日存入数据失败");

                }

            }else {
                CompletableFuture.runAsync(()->{
                    System.out.println("nexa 每日矿池定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.NEXA.getMhs() + "24h", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getDailyMinerDataList(Pools.NEXA.getMhs()+"_realv2", nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.NEXA.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.NEXA.getMhs() + "24h", getToDailyDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.NEXA.getPoolTable() + "_24h", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.NEXA.getPoolTable() + "_24h", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );

                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.NEXA.getName() + "_users_24h", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.NEXA.getName() + "_users_24h", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });


                        }else {
                            PoolPower poolPower  = new PoolPower();
                            poolPower.setDate(now);
                            poolPower.setMhs(BigDecimal.ZERO);
                            poolPower.setMiners(0);
                            poolPower.setOnline(0);
                            poolPower.setOffline(0);
                            boolean poolResult = poolMapper.insertPoolPower(Pools.NEXA.getPoolTable() + "_24h", poolPower);
                            System.out.println("延时任务未查到 构造0数据入库,结果:"+poolPower);
                        }
                    }
                });
            }
        }
    }

     @Scheduled(cron = "50 0,1,30,31 * * * ?")
    public void NEXAUserPowerRatioDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
         if(!enable){
             return;
         }
        Date now = new Date();
        now.setHours(0);
        now.setMinutes(0);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        BigDecimal poolMhs = poolMapper.getPoolTodayTotalPower("nexa", nowStr);
        List<UserPowerDto> userMhsList = poolMapper.getUserTodayTotalPower("nexa", nowStr);
        HashMap<String,BigDecimal> map = new HashMap<>();
        userMhsList.stream().forEach(e ->{
            map.put(e.getUser(),e.getMhs().divide(poolMhs,8,BigDecimal.ROUND_HALF_UP));
        });

        if(map.size() >0){
            redisService.deleteObject("NEXAUserPowerRatio");
            redisService.setCacheMap("NEXAUserPowerRatio",map);
        }

    }



     @Scheduled(cron = "30 3 0/1 * * ?")
    //@Scheduled(cron = "0 0/2 * * * ?")
    public void NEXALuckyDataToDB(){
         if(!enable){
             return;
         }
        log.info("nexa幸运值---定时任务开始");
        LuckDto dto = new LuckDto();
        Date end =  DateUtils.parseDate(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS));
        //幸运值 = 矿池实际报块/矿池理论报块
        //矿池实际报块 = distribution数据库查询表名为 币名_blkreportprofitv2
        //矿池理论报块 =  (矿池过去N段时间的平均算力 / 全网过去N段时间平均算力) * 全网过去N段时间实际报块
        Date start3d = DateUtils.addDays(end,-3);
        Date start7d = DateUtils.addDays(end,-7);
        Date start30d = DateUtils.addDays(end,-30);
        Date start90d = DateUtils.addDays(end,-90);

        //获取全网实际90天内的报块数(v2)
        List<BlockInfoDto> blockPerDays = poolMapper.selectNetBlock("nexa_net_block");
        boolean useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start3d);
        //获取3天内全网的实际报块数
        BlockTimeAndNumberDto blockData = blockDataContext.getBlockData("nexa",start3d, end,blockPerDays, useAggregated);
        //3天矿池理论报块数
        BigDecimal throreticalBlocks = getTheoreticalBlocks("nexa",PoolUnits.NEXA.gethRate(),start3d, end, blockData);
        //3天矿池实际报块数
        int actualBlocks = poolMapper.selectPoolBlock(start3d, end,"nexa",3);
        log.info("nexa 3天实际报块数{},理论报块数{},全网实际报块数{},开始时间{},结束时间{}",actualBlocks,throreticalBlocks,blockData.getHeight(),start3d,end);
        //3天幸运值
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck3d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //7天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start7d);

        blockData = blockDataContext.getBlockData("nexa",start7d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("nexa",PoolUnits.NEXA.gethRate(),start7d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start7d, end,"nexa",7);
        log.info("nexa 7天实际报块数{},理论报块数{}",actualBlocks,throreticalBlocks);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck7d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        //30天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start30d);

        blockData = blockDataContext.getBlockData("nexa",start30d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("nexa",PoolUnits.NEXA.gethRate(),start30d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start30d, end,"nexa",30);
        log.info("nexa 30天实际报块数{},理论报块数{}",actualBlocks,throreticalBlocks);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck30d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        //90天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start90d);

        blockData = blockDataContext.getBlockData("nexa",start90d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("nexa",PoolUnits.NEXA.gethRate(),start90d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start90d, end,"nexa",90);
        log.info("nexa 90天实际报块数{},理论报块数{}",actualBlocks,throreticalBlocks);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck90d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        redisService.deleteObject("NEXALuck");
        redisService.setCacheObject("NEXALuck",dto);
        log.info("nexa幸运值入库完成---幸运值3天：{},幸运值7天：{},幸运值30天：{},幸运值90天：{},",
                dto.getLuck3d(),dto.getLuck7d(),dto.getLuck30d(),dto.getLuck90d());
    }

    /**
     * 币种 理论出块数
     * @param coin 币种名
     * @param start 开始时间
     * @param end 结束时间（当前时间）
     * @param blockData
     * @return
     */
    public BigDecimal getTheoreticalBlocks(String coin,int hRate,Date start,Date end,BlockTimeAndNumberDto blockData){

        //查询一段时间内矿池平均算力
        DateBigDecimalDto avgPowerForPool = poolMapper.getAvgPowerForPool(coin, start, end);
        //查询一段时间段内全网平均算力
        DateBigDecimalDto avgPowerForNet = poolMapper.getAvgPowerForNet(coin, start, end);

        log.info("{}币种 {} 到 {} 时间段内,矿池平均算力为{}，全网平均算力为{}",coin,start,end,avgPowerForPool.getValue(),avgPowerForNet.getValue());
        if(avgPowerForNet.getValue().equals(BigDecimal.ZERO)){
            return BigDecimal.ZERO;
        }

        return avgPowerForPool.getValue().multiply(BigDecimal.valueOf(hRate)).divide(BigDecimal.valueOf(0.985),3, RoundingMode.HALF_UP).divide(avgPowerForNet.getValue(),8, RoundingMode.HALF_UP)
                .multiply(BigDecimal.valueOf(blockData.getHeight())).setScale(4, RoundingMode.HALF_UP);

    }

     @Scheduled(cron = "11 1,3,11,31,33,41 * * * ?")
    public void GRS30mDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
         if(!enable){
             return;
         }
        Date now = new Date();
        int minute = (now.getMinutes() / 30) * 30;
        now.setMinutes( minute);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        System.out.println("grs 30分钟定时任务执行时间:"+nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.GRS.getMhs() + "30m", nowStr);

        System.out.println("二级表当前时间点数据条数："+count);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getHourMinerDataList(Pools.GRS.getMhs()+"_realv2",nowStr);

            if(list.size() > 0){

                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.GRS.getFac());
                    }
                });

                list = filterList(list,now);

                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.GRS.getMhs() + "30m", getToHourDBListByMinerDataList(list));

                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.GRS.getPoolTable() + "_30m", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.GRS.getPoolTable() + "_30m", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    System.out.println("构造写入user算力表数据");
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );
                    System.out.println("GRS user算力表入库数据条数："+userList.size());
                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.GRS.getName() + "_users_30m", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.GRS.getName() + "_users_30m", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });

                Map<String, List<MinerDataDto>> userMap = list.stream().collect(Collectors.groupingBy(MinerDataDto::getMiner));
                if (result) {
                    System.out.println(DateUtils.dateTimeNow() + "grs小时数据存入数据成功");
                } else {
                    System.out.println(DateUtils.dateTimeNow() + "grs小时数据存入数据失败");

                }

            }
            else{
                //重来一次！
                CompletableFuture.runAsync(()->{
                    System.out.println("grs 30分钟定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.GRS.getMhs() + "30m", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getHourMinerDataList(Pools.GRS.getMhs()+"_realv2",nowStr);
                        if(newList.size() > 0){


                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.GRS.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.GRS.getMhs() + "30m", getToHourDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.GRS.getPoolTable() + "_30m", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.GRS.getPoolTable() + "_30m", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                System.out.println("延迟任务 构造写入user算力表数据");
                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );
                                System.out.println("延迟任务 user算力表入库数据条数："+userList.size());
                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.GRS.getName() + "_users_30m", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.GRS.getName() + "_users_30m", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });
                            if (newResult) {
                                System.out.println(DateUtils.dateTimeNow() + "grs30m数据 延迟存入数据成功");
                            } else {
                                System.out.println(DateUtils.dateTimeNow() + "grs数据 延迟存入数据失败");

                            }

                        }
                    }
                });

            }
        }

    }

     @Scheduled(cron = "1 1,3,5 0 * * ?")
    public void GRSDailyDataToDB(){
         if(!enable){
             return;
         }
        String nowStr = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
        Date now = DateUtils.parseDate( nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.GRS.getMhs() + "24h", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getDailyMinerDataList(Pools.GRS.getMhs()+"_realv2", nowStr);
            if(list.size() > 0){
                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.GRS.getFac());
                    }
                });
                list = filterList(list,now);
                //list.stream().forEach(e ->{
                //    e.setDate(DateUtils.addDays(e.getDate(),-1));
                //});
                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.GRS.getMhs() + "24h", getToDailyDBListByMinerDataList(list));
                //todo 统计矿池数据写入矿池数据库 $coin_pool_24h
                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.GRS.getPoolTable() + "_24h", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.GRS.getPoolTable() + "_24h", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    //写入数据到coin_users表中
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );

                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.GRS.getName() + "_users_24h", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.GRS.getName() + "_users_24h", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });
                if(result){
                    System.out.println(DateUtils.dateTimeNow()+"grs每日存入数据成功");
                }else {
                    System.out.println(DateUtils.dateTimeNow()+"grs每日存入数据失败");

                }

            }else {
                CompletableFuture.runAsync(()->{
                    System.out.println("grs 每日矿池定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.GRS.getMhs() + "24h", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getDailyMinerDataList(Pools.GRS.getMhs()+"_realv2", nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.GRS.getFac());
                                }
                            });

                            newList = filterList(newList,now);


                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.GRS.getMhs() + "24h", getToDailyDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.GRS.getPoolTable() + "_24h", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.GRS.getPoolTable() + "_24h", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );

                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.GRS.getName() + "_users_24h", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.GRS.getName() + "_users_24h", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });


                        }else {
                            PoolPower poolPower  = new PoolPower();
                            poolPower.setDate(now);
                            poolPower.setMhs(BigDecimal.ZERO);
                            poolPower.setMiners(0);
                            poolPower.setOnline(0);
                            poolPower.setOffline(0);
                            boolean poolResult = poolMapper.insertPoolPower(Pools.GRS.getPoolTable() + "_24h", poolPower);
                            System.out.println("延时任务未查到 构造0数据入库,结果:"+poolPower);
                        }
                    }
                });
            }
        }
    }

     @Scheduled(cron = "51 0,1,30,31 * * * ?")
    public void GRSUserPowerRatioDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
         if(!enable){
             return;
         }
        Date now = new Date();
        now.setHours(0);
        now.setMinutes(0);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        BigDecimal poolMhs = Convert.toBigDecimal( poolMapper.getPoolTodayTotalPower("grs", nowStr),BigDecimal.ONE);

        List<UserPowerDto> userMhsList = poolMapper.getUserTodayTotalPower("grs", nowStr);
        HashMap<String,BigDecimal> map = new HashMap<>();
        userMhsList.stream().forEach(e ->{
            if(StringUtils.isNull(e.getMhs())){
                map.put(e.getUser(),BigDecimal.ZERO.setScale(8).stripTrailingZeros());
            }else {
                map.put(e.getUser(),e.getMhs().divide(poolMhs,8,BigDecimal.ROUND_HALF_UP));
            }
        });

        if(map.size() >0){
            redisService.deleteObject("GRSUserPowerRatio");
            redisService.setCacheMap("GRSUserPowerRatio",map);
        }

    }


     @Scheduled(cron = "31 3 0/1 * * ?")
    //@Scheduled(cron = "0 0/2 * * * ?")
    public void GRSLuckyDataToDB(){
         if(!enable){
             return;
         }
        log.info("GRS幸运值---定时任务开始");
        LuckDto dto = new LuckDto();
        Date end =  DateUtils.parseDate(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS));
        //幸运值 = 矿池实际报块/矿池理论报块
        //矿池实际报块 = 数据库查询表名为币名_pool_blkstats
        //矿池理论报块 =  (矿池过去N段时间的平均算力 / 全网过去N段时间平均算力) * 全网过去N段时间实际报块
        Date start3d = DateUtils.addDays(end,-3);
        Date start7d = DateUtils.addDays(end,-7);
        Date start30d = DateUtils.addDays(end,-30);
        Date start90d = DateUtils.addDays(end,-90);


        //获取全网实际90天内的报块数(v2)
        List<BlockInfoDto> blockPerDays = poolMapper.selectNetBlock("grs_net_block");
        boolean useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start3d);
        //获取3天内全网的实际报块数
        BlockTimeAndNumberDto blockData = blockDataContext.getBlockData("grs",start3d, end,blockPerDays, useAggregated);
        //3天矿池理论报块数
        BigDecimal throreticalBlocks= getTheoreticalBlocks("grs",PoolUnits.GRS.gethRate(),start3d, end, blockData);
        //3天矿池实际报块数
        int actualBlocks = poolMapper.selectPoolBlock(start3d, end,"grs",3);
        //3天幸运值
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck3d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //7天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start7d);

        blockData = blockDataContext.getBlockData("grs",start7d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("grs",PoolUnits.GRS.gethRate(),start7d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start7d, end,"grs",7);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck7d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //30天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start30d);

        blockData = blockDataContext.getBlockData("grs",start30d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("grs",PoolUnits.GRS.gethRate(),start30d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start30d, end,"grs",30);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck30d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        //90天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start90d);
        blockData = blockDataContext.getBlockData("grs",start90d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("grs",PoolUnits.GRS.gethRate(),start90d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start90d, end,"grs",90);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck90d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }


        redisService.deleteObject("GRSLuck");
        redisService.setCacheObject("GRSLuck",dto);
        log.info("grs幸运值入库完成---幸运值3天：{},幸运值7天：{},幸运值30天：{},幸运值90天：{},",
                dto.getLuck3d(),dto.getLuck7d(),dto.getLuck30d(),dto.getLuck90d());;
    }

     @Scheduled(cron = "12 1,3,12,31,33,42 * * * ?")
    public void MONA30mDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
         if(!enable){
             return;
         }
        Date now = new Date();
        int minute = (now.getMinutes() / 30) * 30;
        now.setMinutes( minute);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        System.out.println("mona 30分钟定时任务执行时间:"+now);
        System.out.println("格式化后的时间:"+nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.MONA.getMhs() + "30m", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getHourMinerDataList(Pools.MONA.getMhs()+"_realv2",nowStr);
            if(list.size() > 0){

                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.MONA.getFac());
                    }
                });

                list = filterList(list,now);

                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.MONA.getMhs() + "30m", getToHourDBListByMinerDataList(list));

                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.MONA.getPoolTable() + "_30m", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.MONA.getPoolTable() + "_30m", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    System.out.println("构造写入user算力表数据");
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );
                    System.out.println("MONA user算力表入库数据条数："+userList.size());
                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONA.getName() + "_users_30m", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONA.getName() + "_users_30m", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });

                Map<String, List<MinerDataDto>> userMap = list.stream().collect(Collectors.groupingBy(MinerDataDto::getMiner));
                if (result) {
                    System.out.println(DateUtils.dateTimeNow() + "mona小时数据存入数据成功");
                } else {
                    System.out.println(DateUtils.dateTimeNow() + "mona小时数据存入数据失败");

                }

            }
            else{
                //重来一次！
                CompletableFuture.runAsync(()->{
                    System.out.println("mona 30分钟定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.MONA.getMhs() + "30m", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getHourMinerDataList(Pools.MONA.getMhs()+"_realv2",nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.MONA.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.MONA.getMhs() + "30m", getToHourDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.MONA.getPoolTable() + "_30m", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.MONA.getPoolTable() + "_30m", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                System.out.println("延迟任务 构造写入user算力表数据");
                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );
                                System.out.println("延迟任务 user算力表入库数据条数："+userList.size());
                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONA.getName() + "_users_30m", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONA.getName() + "_users_30m", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });
                            if (newResult) {
                                System.out.println(DateUtils.dateTimeNow() + "mona30m数据 延迟存入数据成功");
                            } else {
                                System.out.println(DateUtils.dateTimeNow() + "mona30m数据 延迟存入数据失败");

                            }

                        }
                    }
                });

            }
        }

    }

     @Scheduled(cron = "2 1,3,5 0 * * ?")
    public void MONADailyDataToDB(){
         if(!enable){
             return;
         }
        String nowStr = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
        Date now = DateUtils.parseDate( nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.MONA.getMhs() + "24h", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getDailyMinerDataList(Pools.MONA.getMhs()+"_realv2", nowStr);
            if(list.size() > 0){

                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.MONA.getFac());
                    }
                });

                list = filterList(list,now);
                //list.stream().forEach(e ->{
                //    e.setDate(DateUtils.addDays(e.getDate(),-1));
                //});
                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.MONA.getMhs() + "24h", getToDailyDBListByMinerDataList(list));
                //todo 统计矿池数据写入矿池数据库 $coin_pool_24h
                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    System.out.println("date:"+date);
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.MONA.getPoolTable() + "_24h", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.MONA.getPoolTable() + "_24h", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    //写入数据到coin_users表中
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );

                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONA.getName() + "_users_24h", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONA.getName() + "_users_24h", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });
                if(result){
                    System.out.println(DateUtils.dateTimeNow()+"mona每日存入数据成功");
                }else {
                    System.out.println(DateUtils.dateTimeNow()+"mona每日存入数据失败");

                }

            }else {
                CompletableFuture.runAsync(()->{
                    System.out.println("mona 每日矿池定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.MONA.getMhs() + "24h", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getDailyMinerDataList(Pools.MONA.getMhs()+"_realv2", nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.MONA.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.MONA.getMhs() + "24h", getToDailyDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.MONA.getPoolTable() + "_24h", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.MONA.getPoolTable() + "_24h", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );

                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONA.getName() + "_users_24h", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONA.getName() + "_users_24h", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });


                        }else {
                            PoolPower poolPower  = new PoolPower();
                            poolPower.setDate(now);
                            poolPower.setMhs(BigDecimal.ZERO);
                            poolPower.setMiners(0);
                            poolPower.setOnline(0);
                            poolPower.setOffline(0);
                            boolean poolResult = poolMapper.insertPoolPower(Pools.MONA.getPoolTable() + "_24h", poolPower);
                            System.out.println("延时任务未查到 构造0数据入库,结果:"+poolPower);
                        }
                    }
                });
            }
        }
    }

      @Scheduled(cron = "52 0,1,30,31 * * * ?")
    public void MONAUserPowerRatioDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
          if(!enable){
              return;
          }
        Date now = new Date();
        now.setHours(0);
        now.setMinutes(0);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        BigDecimal poolMhs = Convert.toBigDecimal( poolMapper.getPoolTodayTotalPower("mona", nowStr),BigDecimal.ONE);

        List<UserPowerDto> userMhsList = poolMapper.getUserTodayTotalPower("mona", nowStr);
        HashMap<String,BigDecimal> map = new HashMap<>();
        userMhsList.stream().forEach(e ->{
            if(StringUtils.isNull(e.getMhs())){
                map.put(e.getUser(),BigDecimal.ZERO.setScale(8).stripTrailingZeros());
            }else {
                map.put(e.getUser(),e.getMhs().divide(poolMhs,8,BigDecimal.ROUND_HALF_UP));
            }
        });

        if(map.size() >0){
            redisService.deleteObject("MONAUserPowerRatio");
            redisService.setCacheMap("MONAUserPowerRatio",map);
        }

    }

    @Scheduled(cron = "32 3 0/1 * * ?")
    //@Scheduled(cron = "0 0/2 * * * ?")
    public void MONALuckyDataToDB(){
        if(!enable){
            return;
        }
        log.info("MONA幸运值---定时任务开始");
        LuckDto dto = new LuckDto();
        Date end =  DateUtils.parseDate(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS));
        //幸运值 = 矿池实际报块/矿池理论报块
        //矿池实际报块 = 数据库查询表名为币名_pool_blkstats
        //矿池理论报块 =  (矿池过去N段时间的平均算力 / 全网过去N段时间平均算力) * 全网过去N段时间实际报块
        Date start3d = DateUtils.addDays(end,-3);
        Date start7d = DateUtils.addDays(end,-7);
        Date start30d = DateUtils.addDays(end,-30);
        Date start90d = DateUtils.addDays(end,-90);


        //获取全网实际90天内的报块数(v2)
        List<BlockInfoDto> blockPerDays = poolMapper.selectNetBlock("mona_net_block");


        boolean useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start3d);
        //获取3天内全网的实际报块数

        BlockTimeAndNumberDto blockData = blockDataContext.getBlockData("mona",start3d, end,blockPerDays, useAggregated);
        //3天矿池理论报块数
        BigDecimal throreticalBlocks= getTheoreticalBlocks("mona",PoolUnits.MONA.gethRate(),start3d, end, blockData);

        //3天矿池实际报块数
        int actualBlocks = poolMapper.selectPoolBlock(start3d, end,"mona",3);
        //3天幸运值
     if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck3d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //7天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start7d);

        blockData = blockDataContext.getBlockData("mona",start7d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("mona",PoolUnits.MONA.gethRate(),start7d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start7d, end,"mona",7);
     if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck7d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //30天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start30d);

        blockData = blockDataContext.getBlockData("mona",start30d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("mona",PoolUnits.MONA.gethRate(),start30d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start30d, end,"mona",30);
     if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck30d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        //90天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start90d);

        blockData = blockDataContext.getBlockData("mona",start90d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("mona",PoolUnits.MONA.gethRate(),start90d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start90d, end,"mona",90);
     if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck90d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        redisService.deleteObject("MONALuck");
        redisService.setCacheObject("MONALuck",dto);
        log.info("MONA幸运值入库完成---幸运值3天：{},幸运值7天：{},幸运值30天：{},幸运值90天：{},",
                dto.getLuck3d(),dto.getLuck7d(),dto.getLuck30d(),dto.getLuck90d());
    }

    @Scheduled(cron = "14 1,3,9,31,33,39 * * * ?")
    public void DGBO30mDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        int minute = (now.getMinutes() / 30) * 30;
        now.setMinutes( minute);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        System.out.println("DGBO 30分钟定时任务执行时间:"+now);
        System.out.println("格式化后的时间:"+nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.DGBO.getMhs() + "30m", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getHourMinerDataList(Pools.DGBO.getMhs()+"_realv2",nowStr);
            if(list.size() > 0){

                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.DGBO.getFac());
                    }
                });

                list = filterList(list,now);

                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.DGBO.getMhs() + "30m", getToHourDBListByMinerDataList(list));

                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.DGBO.getPoolTable() + "_30m", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.DGBO.getPoolTable() + "_30m", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    System.out.println("DGBO 构造写入user算力表数据");
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );
                    System.out.println("DGBO user算力表入库数据条数："+userList.size());
                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBO.getCoin() + "_users_30m", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBO.getCoin() + "_users_30m", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });

                Map<String, List<MinerDataDto>> userMap = list.stream().collect(Collectors.groupingBy(MinerDataDto::getMiner));
                if (result) {
                    System.out.println(DateUtils.dateTimeNow() + "DGBO 30m数据存入数据成功");
                } else {
                    System.out.println(DateUtils.dateTimeNow() + "DGBO 30m数据存入数据失败");

                }

            }
            else{
                //重来一次！
                CompletableFuture.runAsync(()->{
                    System.out.println("DGBO 30分钟定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.DGBO.getMhs() + "30m", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getHourMinerDataList(Pools.DGBO.getMhs()+"_realv2",nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.DGBO.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.DGBO.getMhs() + "30m", getToHourDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.DGBO.getPoolTable() + "_30m", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.DGBO.getPoolTable() + "_30m", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                System.out.println("延迟任务 DGBO构造写入user算力表数据");
                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );
                                System.out.println("延迟任务 DGBO user算力表入库数据条数："+userList.size());
                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBO.getCoin() + "_users_30m", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBO.getCoin() + "_users_30m", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });
                            if (newResult) {
                                System.out.println(DateUtils.dateTimeNow() + "DGBO 30m数据 延迟存入数据成功");
                            } else {
                                System.out.println(DateUtils.dateTimeNow() + "DGBO 30m数据 延迟存入数据失败");

                            }

                        }
                    }
                });

            }
        }

    }

    @Scheduled(cron = "4 1,3,5 0 * * ?")
    public void DGBODailyDataToDB(){
        if(!enable){
            return;
        }
        String nowStr = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
        Date now = DateUtils.parseDate( nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.DGBO.getMhs() + "24h", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getDailyMinerDataList(Pools.DGBO.getMhs()+"_realv2", nowStr);
            if(list.size() > 0){

                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.DGBO.getFac());
                    }
                });

                list = filterList(list,now);
                //list.stream().forEach(e ->{
                //    e.setDate(DateUtils.addDays(e.getDate(),-1));
                //});
                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.DGBO.getMhs() + "24h", getToDailyDBListByMinerDataList(list));
                //todo 统计矿池数据写入矿池数据库 $coin_pool_24h
                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    System.out.println("date:"+date);
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.DGBO.getPoolTable() + "_24h", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.DGBO.getPoolTable() + "_24h", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    //写入数据到coin_users表中
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );

                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBO.getCoin() + "_users_24h", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBO.getCoin() + "_users_24h", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });
                if(result){
                    System.out.println(DateUtils.dateTimeNow()+"DGBO 每日存入数据成功");
                }else {
                    System.out.println(DateUtils.dateTimeNow()+"DGBO 每日存入数据失败");

                }

            }else {
                CompletableFuture.runAsync(()->{
                    System.out.println("DGBO 每日矿池定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.DGBO.getMhs() + "24h", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getDailyMinerDataList(Pools.DGBO.getMhs()+"_realv2", nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.DGBO.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.DGBO.getMhs() + "24h", getToDailyDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.DGBO.getPoolTable() + "_24h", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.DGBO.getPoolTable() + "_24h", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );

                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBO.getCoin() + "_users_24h", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBO.getCoin() + "_users_24h", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });


                        }else {
                            PoolPower poolPower  = new PoolPower();
                            poolPower.setDate(now);
                            poolPower.setMhs(BigDecimal.ZERO);
                            poolPower.setMiners(0);
                            poolPower.setOnline(0);
                            poolPower.setOffline(0);
                            boolean poolResult = poolMapper.insertPoolPower(Pools.DGBO.getPoolTable() + "_24h", poolPower);
                            System.out.println("DGBO延时任务未查到 构造0数据入库,结果:"+poolPower);
                        }
                    }
                });
            }
        }
    }

    @Scheduled(cron = "54 0,1,30,31 * * * ?")
    public void DGBOUserPowerRatioDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        now.setHours(0);
        now.setMinutes(0);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        BigDecimal poolMhs = Convert.toBigDecimal( poolMapper.getPoolTodayTotalPower("dgbo", nowStr),BigDecimal.ONE);

        List<UserPowerDto> userMhsList = poolMapper.getUserTodayTotalPower("dgbo", nowStr);
        HashMap<String,BigDecimal> map = new HashMap<>();
        userMhsList.stream().forEach(e ->{
            if(StringUtils.isNull(e.getMhs())){
                map.put(e.getUser(),BigDecimal.ZERO.setScale(8).stripTrailingZeros());
            }else {
                map.put(e.getUser(),e.getMhs().divide(poolMhs,8,BigDecimal.ROUND_HALF_UP));
            }
        });

        if(map.size() >0){
            redisService.deleteObject("DGBOUserPowerRatio");
            redisService.setCacheMap("DGBOUserPowerRatio",map);
        }

    }


    @Scheduled(cron = "34 3 0/1 * * ?")
    //@Scheduled(cron = "0 0/2 * * * ?")
    public void DGBOLuckyDataToDB(){
        if(!enable){
            return;
        }
        log.info("DGBO幸运值---定时任务开始");
        LuckDto dto = new LuckDto();
        Date end =  DateUtils.parseDate(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS));
        //幸运值 = 矿池实际报块/矿池理论报块
        //矿池实际报块 = 数据库查询表名为币名_pool_blkstats
        //矿池理论报块 =  (矿池过去N段时间的平均算力 / 全网过去N段时间平均算力) * 全网过去N段时间实际报块
        Date start3d = DateUtils.addDays(end,-3);
        Date start7d = DateUtils.addDays(end,-7);
        Date start30d = DateUtils.addDays(end,-30);
        Date start90d = DateUtils.addDays(end,-90);


        //获取全网实际90天内的报块数(v2)
        List<BlockInfoDto> blockPerDays = poolMapper.selectNetBlock("dgbo_net_block");


        boolean useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start3d);
        //获取3天内全网的实际报块数

        BlockTimeAndNumberDto blockData = blockDataContext.getBlockData("dgbo",start3d, end,blockPerDays, useAggregated);
        //3天矿池理论报块数
        BigDecimal throreticalBlocks= getTheoreticalBlocks("dgbo",PoolUnits.DGBO.gethRate(),start3d, end, blockData);

        //3天矿池实际报块数
        int actualBlocks = poolMapper.selectPoolBlock(start3d, end,"dgbo",3);
        //3天幸运值
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck3d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //7天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start7d);

        blockData = blockDataContext.getBlockData("dgbo",start7d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("dgbo",PoolUnits.MONA.gethRate(),start7d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start7d, end,"dgbo",7);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck7d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //30天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start30d);

        blockData = blockDataContext.getBlockData("dgbo",start30d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("dgbo",PoolUnits.MONA.gethRate(),start30d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start30d, end,"dgbo",30);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck30d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        //90天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start90d);

        blockData = blockDataContext.getBlockData("dgbo",start90d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("dgbo",PoolUnits.MONA.gethRate(),start90d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start90d, end,"dgbo",90);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck90d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        redisService.deleteObject("DGBOLuck");
        redisService.setCacheObject("DGBOLuck",dto);
        log.info("DGBO幸运值入库完成---幸运值3天：{},幸运值7天：{},幸运值30天：{},幸运值90天：{},",
                dto.getLuck3d(),dto.getLuck7d(),dto.getLuck30d(),dto.getLuck90d());
    }

    @Scheduled(cron = "16 1,3,8,31,33,38 * * * ?")
    public void DGBQ30mDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        int minute = (now.getMinutes() / 30) * 30;
        now.setMinutes( minute);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        System.out.println("DGBQ 30分钟定时任务执行时间:"+now);
        System.out.println("格式化后的时间:"+nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.DGBQ.getMhs() + "30m", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getHourMinerDataList(Pools.DGBQ.getMhs()+"_realv2",nowStr);
            if(list.size() > 0){

                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.DGBQ.getFac());
                    }
                });

                list = filterList(list,now);

                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.DGBQ.getMhs() + "30m", getToHourDBListByMinerDataList(list));

                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.DGBQ.getPoolTable() + "_30m", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.DGBQ.getPoolTable() + "_30m", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    System.out.println("DGBQ 构造写入user算力表数据");
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );
                    System.out.println("DGBQ user算力表入库数据条数："+userList.size());
                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBQ.getCoin() + "_users_30m", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBQ.getCoin() + "_users_30m", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });

                Map<String, List<MinerDataDto>> userMap = list.stream().collect(Collectors.groupingBy(MinerDataDto::getMiner));
                if (result) {
                    System.out.println(DateUtils.dateTimeNow() + "DGBQ 30m数据存入数据成功");
                } else {
                    System.out.println(DateUtils.dateTimeNow() + "DGBQ 30m数据存入数据失败");

                }

            }
            else{
                //重来一次！
                CompletableFuture.runAsync(()->{
                    System.out.println(DateUtils.dateTimeNow()+"DGBQ 30分钟定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.DGBQ.getMhs() + "30m", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getHourMinerDataList(Pools.DGBQ.getMhs()+"_realv2",nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.DGBQ.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.DGBQ.getMhs() + "30m", getToHourDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.DGBQ.getPoolTable() + "_30m", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.DGBQ.getPoolTable() + "_30m", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                System.out.println("延迟任务 DGBQ构造写入user算力表数据");
                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );
                                System.out.println("延迟任务 DGBQ user算力表入库数据条数："+userList.size());
                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBQ.getCoin() + "_users_30m", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBQ.getCoin() + "_users_30m", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });
                            if (newResult) {
                                System.out.println(DateUtils.dateTimeNow() + "DGBQ 30m数据 延迟存入数据成功");
                            } else {
                                System.out.println(DateUtils.dateTimeNow() + "DGBO 30m数据 延迟存入数据失败");

                            }

                        }
                    }
                });

            }
        }

    }

    @Scheduled(cron = "6 1,3,5 0 * * ?")
    public void DGBQDailyDataToDB(){
        if(!enable){
            return;
        }
        String nowStr = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
        Date now = DateUtils.parseDate( nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.DGBQ.getMhs() + "24h", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getDailyMinerDataList(Pools.DGBQ.getMhs()+"_realv2", nowStr);
            if(list.size() > 0){

                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.DGBQ.getFac());
                    }
                });

                list = filterList(list,now);
                //list.stream().forEach(e ->{
                //    e.setDate(DateUtils.addDays(e.getDate(),-1));
                //});
                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.DGBQ.getMhs() + "24h", getToDailyDBListByMinerDataList(list));
                //todo 统计矿池数据写入矿池数据库 $coin_pool_24h
                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    System.out.println("date:"+date);
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.DGBQ.getPoolTable() + "_24h", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.DGBQ.getPoolTable() + "_24h", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    //写入数据到coin_users表中
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );

                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBQ.getCoin() + "_users_24h", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBQ.getCoin() + "_users_24h", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });
                if(result){
                    System.out.println(DateUtils.dateTimeNow()+"DGBQ 每日存入数据成功");
                }else {
                    System.out.println(DateUtils.dateTimeNow()+"DGBQ 每日存入数据失败");

                }

            }else {
                CompletableFuture.runAsync(()->{
                    System.out.println("DGBQ 每日矿池定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.DGBQ.getMhs() + "24h", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getDailyMinerDataList(Pools.DGBQ.getMhs()+"_realv2", nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.DGBQ.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.DGBQ.getMhs() + "24h", getToDailyDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.DGBQ.getPoolTable() + "_24h", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.DGBQ.getPoolTable() + "_24h", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );

                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBQ.getCoin() + "_users_24h", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBQ.getCoin() + "_users_24h", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });


                        }else {
                            PoolPower poolPower  = new PoolPower();
                            poolPower.setDate(now);
                            poolPower.setMhs(BigDecimal.ZERO);
                            poolPower.setMiners(0);
                            poolPower.setOnline(0);
                            poolPower.setOffline(0);
                            boolean poolResult = poolMapper.insertPoolPower(Pools.DGBQ.getPoolTable() + "_24h", poolPower);
                            System.out.println("DGBQ延时任务未查到 构造0数据入库,结果:"+poolPower);
                        }
                    }
                });
            }
        }
    }

    @Scheduled(cron = "56 0,1,30,31 * * * ?")
    public void DGBQUserPowerRatioDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        now.setHours(0);
        now.setMinutes(0);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        BigDecimal poolMhs = Convert.toBigDecimal( poolMapper.getPoolTodayTotalPower("dgbq", nowStr),BigDecimal.ONE);

        List<UserPowerDto> userMhsList = poolMapper.getUserTodayTotalPower("dgbq", nowStr);
        HashMap<String,BigDecimal> map = new HashMap<>();
        userMhsList.stream().forEach(e ->{
            if(StringUtils.isNull(e.getMhs())){
                map.put(e.getUser(),BigDecimal.ZERO.setScale(8).stripTrailingZeros());
            }else {
                map.put(e.getUser(),e.getMhs().divide(poolMhs,8,BigDecimal.ROUND_HALF_UP));
            }
        });

        if(map.size() >0){
            redisService.deleteObject("DGBQUserPowerRatio");
            redisService.setCacheMap("DGBQUserPowerRatio",map);
        }

    }

    @Scheduled(cron = "36 3 0/1 * * ?")
    //@Scheduled(cron = "0 0/2 * * * ?")
    public void DGBQLuckyDataToDB(){
        if(!enable){
            return;
        }
        log.info("DGBQ幸运值---定时任务开始");
        LuckDto dto = new LuckDto();
        Date end =  DateUtils.parseDate(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS));
        //幸运值 = 矿池实际报块/矿池理论报块
        //矿池实际报块 = 数据库查询表名为币名_pool_blkstats
        //矿池理论报块 =  (矿池过去N段时间的平均算力 / 全网过去N段时间平均算力) * 全网过去N段时间实际报块
        Date start3d = DateUtils.addDays(end,-3);
        Date start7d = DateUtils.addDays(end,-7);
        Date start30d = DateUtils.addDays(end,-30);
        Date start90d = DateUtils.addDays(end,-90);


        //获取全网实际90天内的报块数(v2)
        List<BlockInfoDto> blockPerDays = poolMapper.selectNetBlock("dgbq_net_block");


        boolean useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start3d);
        //获取3天内全网的实际报块数

        BlockTimeAndNumberDto blockData = blockDataContext.getBlockData("dgbq",start3d, end,blockPerDays, useAggregated);
        //3天矿池理论报块数
        BigDecimal throreticalBlocks= getTheoreticalBlocks("dgbq",PoolUnits.DGBQ.gethRate(),start3d, end, blockData);

        //3天矿池实际报块数
        int actualBlocks = poolMapper.selectPoolBlock(start3d, end,"dgbq",3);
        //3天幸运值
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck3d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //7天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start7d);

        blockData = blockDataContext.getBlockData("dgbq",start7d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("dgbq",PoolUnits.MONA.gethRate(),start7d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start7d, end,"dgbq",7);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck7d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //30天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start30d);

        blockData = blockDataContext.getBlockData("dgbq",start30d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("dgbq",PoolUnits.MONA.gethRate(),start30d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start30d, end,"dgbq",30);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck30d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        //90天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start90d);

        blockData = blockDataContext.getBlockData("dgbq",start90d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("dgbq",PoolUnits.MONA.gethRate(),start90d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start90d, end,"dgbq",90);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck90d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        redisService.deleteObject("DGBQLuck");
        redisService.setCacheObject("DGBQLuck",dto);
        log.info("DGBQ幸运值入库完成---幸运值3天：{},幸运值7天：{},幸运值30天：{},幸运值90天：{},",
                dto.getLuck3d(),dto.getLuck7d(),dto.getLuck30d(),dto.getLuck90d());
    }

    @Scheduled(cron = "18 1,3,7,31,33,37 * * * ?")
    public void DGBS30mDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        int minute = (now.getMinutes() / 30) * 30;
        now.setMinutes( minute);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        System.out.println("DGBS 30分钟定时任务执行时间:"+now);
        System.out.println("格式化后的时间:"+nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.DGBS.getMhs() + "30m", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getHourMinerDataList(Pools.DGBS.getMhs()+"_realv2",nowStr);
            if(list.size() > 0){

                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.DGBS.getFac());
                    }
                });

                list = filterList(list,now);

                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.DGBS.getMhs() + "30m", getToHourDBListByMinerDataList(list));

                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.DGBS.getPoolTable() + "_30m", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.DGBS.getPoolTable() + "_30m", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    System.out.println("DGBS 构造写入user算力表数据");
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );
                    System.out.println("DGBS user算力表入库数据条数："+userList.size());
                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBS.getCoin() + "_users_30m", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBS.getCoin() + "_users_30m", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });

                Map<String, List<MinerDataDto>> userMap = list.stream().collect(Collectors.groupingBy(MinerDataDto::getMiner));
                if (result) {
                    System.out.println(DateUtils.dateTimeNow() + "DGBS 30m数据存入数据成功");
                } else {
                    System.out.println(DateUtils.dateTimeNow() + "DGBS 30m数据存入数据失败");

                }

            }
            else{
                //重来一次！
                CompletableFuture.runAsync(()->{
                    System.out.println("DGBS 30分钟定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.DGBS.getMhs() + "30m", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getHourMinerDataList(Pools.DGBS.getMhs()+"_realv2",nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.DGBS.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.DGBS.getMhs() + "30m", getToHourDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.DGBS.getPoolTable() + "_30m", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.DGBS.getPoolTable() + "_30m", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                System.out.println("延迟任务 DGBS构造写入user算力表数据");
                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );
                                System.out.println("延迟任务 DGBS user算力表入库数据条数："+userList.size());
                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBS.getCoin() + "_users_30m", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBS.getCoin() + "_users_30m", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });
                            if (newResult) {
                                System.out.println(DateUtils.dateTimeNow() + "DGBS 30m数据 延迟存入数据成功");
                            } else {
                                System.out.println(DateUtils.dateTimeNow() + "DGBS 30m数据 延迟存入数据失败");

                            }

                        }
                    }
                });

            }
        }

    }

    @Scheduled(cron = "8 1,3,5 0 * * ?")
    public void DGBSDailyDataToDB(){
        if(!enable){
            return;
        }
        String nowStr = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
        Date now = DateUtils.parseDate( nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.DGBS.getMhs() + "24h", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getDailyMinerDataList(Pools.DGBS.getMhs()+"_realv2", nowStr);
            if(list.size() > 0){

                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.DGBS.getFac());
                    }
                });

                list = filterList(list,now);

                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.DGBS.getMhs() + "24h", getToDailyDBListByMinerDataList(list));
                //todo 统计矿池数据写入矿池数据库 $coin_pool_24h
                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    System.out.println("date:"+date);
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.DGBS.getPoolTable() + "_24h", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.DGBS.getPoolTable() + "_24h", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    //写入数据到coin_users表中
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );

                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBS.getCoin() + "_users_24h", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBS.getCoin() + "_users_24h", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });
                if(result){
                    System.out.println(DateUtils.dateTimeNow()+"DGBS 每日存入数据成功");
                }else {
                    System.out.println(DateUtils.dateTimeNow()+"DGBS 每日存入数据失败");

                }

            }else {
                CompletableFuture.runAsync(()->{
                    System.out.println("DGBS 每日矿池定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.DGBS.getMhs() + "24h", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getDailyMinerDataList(Pools.DGBS.getMhs()+"_realv2", nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.DGBS.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.DGBS.getMhs() + "24h", getToDailyDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.DGBS.getPoolTable() + "_24h", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.DGBS.getPoolTable() + "_24h", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );

                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBS.getCoin() + "_users_24h", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.DGBS.getCoin() + "_users_24h", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });


                        }else {
                            PoolPower poolPower  = new PoolPower();
                            poolPower.setDate(now);
                            poolPower.setMhs(BigDecimal.ZERO);
                            poolPower.setMiners(0);
                            poolPower.setOnline(0);
                            poolPower.setOffline(0);
                            boolean poolResult = poolMapper.insertPoolPower(Pools.DGBS.getPoolTable() + "_24h", poolPower);
                            System.out.println("DGBS延时任务未查到 构造0数据入库,结果:"+poolPower);
                        }
                    }
                });
            }
        }
    }

    @Scheduled(cron = "58 0,1,30,31 * * * ?")
    public void DGBSUserPowerRatioDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        now.setHours(0);
        now.setMinutes(0);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        BigDecimal poolMhs = Convert.toBigDecimal( poolMapper.getPoolTodayTotalPower("dgbs", nowStr),BigDecimal.ONE);

        List<UserPowerDto> userMhsList = poolMapper.getUserTodayTotalPower("dgbs", nowStr);
        HashMap<String,BigDecimal> map = new HashMap<>();
        userMhsList.stream().forEach(e ->{
            if(StringUtils.isNull(e.getMhs())){
                map.put(e.getUser(),BigDecimal.ZERO.setScale(8).stripTrailingZeros());
            }else {
                map.put(e.getUser(),e.getMhs().divide(poolMhs,8,BigDecimal.ROUND_HALF_UP));
            }
        });

        if(map.size() >0){
            redisService.deleteObject("DGBSUserPowerRatio");
            redisService.setCacheMap("DGBSUserPowerRatio",map);
        }

    }

    @Scheduled(cron = "38 3 0/1 * * ?")
    //@Scheduled(cron = "0 0/2 * * * ?")
    public void DGBSLuckyDataToDB(){
        if(!enable){
            return;
        }
        log.info("DGBS幸运值---定时任务开始");
        LuckDto dto = new LuckDto();
        Date end =  DateUtils.parseDate(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS));
        //幸运值 = 矿池实际报块/矿池理论报块
        //矿池实际报块 = 数据库查询表名为币名_pool_blkstats
        //矿池理论报块 =  (矿池过去N段时间的平均算力 / 全网过去N段时间平均算力) * 全网过去N段时间实际报块
        Date start3d = DateUtils.addDays(end,-3);
        Date start7d = DateUtils.addDays(end,-7);
        Date start30d = DateUtils.addDays(end,-30);
        Date start90d = DateUtils.addDays(end,-90);


        //获取全网实际90天内的报块数(v2)
        List<BlockInfoDto> blockPerDays = poolMapper.selectNetBlock("dgbs_net_block");


        boolean useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start3d);
        //获取3天内全网的实际报块数

        BlockTimeAndNumberDto blockData = blockDataContext.getBlockData("dgbs",start3d, end,blockPerDays, useAggregated);
        //3天矿池理论报块数
        BigDecimal throreticalBlocks= getTheoreticalBlocks("dgbs",PoolUnits.DGBS.gethRate(),start3d, end, blockData);

        //3天矿池实际报块数
        int actualBlocks = poolMapper.selectPoolBlock(start3d, end,"dgbs",3);
        //3天幸运值
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck3d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //7天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start7d);

        blockData = blockDataContext.getBlockData("dgbs",start7d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("dgbs",PoolUnits.DGBS.gethRate(),start7d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start7d, end,"dgbs",7);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck7d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //30天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start30d);

        blockData = blockDataContext.getBlockData("dgbs",start30d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("dgbs",PoolUnits.DGBS.gethRate(),start30d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start30d, end,"dgbs",30);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck30d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        //90天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start90d);

        blockData = blockDataContext.getBlockData("dgbs",start90d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("dgbs",PoolUnits.DGBS.gethRate(),start90d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start90d, end,"dgbs",90);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck90d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        redisService.deleteObject("DGBSLuck");
        redisService.setCacheObject("DGBSLuck",dto);
        log.info("DGBS幸运值入库完成---幸运值3天：{},幸运值7天：{},幸运值30天：{},幸运值90天：{},",
                dto.getLuck3d(),dto.getLuck7d(),dto.getLuck30d(),dto.getLuck90d());
    }

    @Scheduled(cron = "19 1,3,13,31,33,43 * * * ?")
    public void RXD30mDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        int minute = (now.getMinutes() / 30) * 30;
        now.setMinutes( minute);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        System.out.println("rxd 30分钟定时任务执行时间:"+now);
        System.out.println("格式化后的时间:"+nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.RXD.getMhs() + "30m", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getHourMinerDataList(Pools.RXD.getMhs()+"_realv2",nowStr);
            if(list.size() > 0){

                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.RXD.getFac());
                    }
                });
                list = filterList(list,now);

                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.RXD.getMhs() + "30m", getToHourDBListByMinerDataList(list));

                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.RXD.getPoolTable() + "_30m", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.RXD.getPoolTable() + "_30m", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    System.out.println("rxd 构造写入user算力表数据");
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );
                    System.out.println("rxd user算力表入库数据条数："+userList.size());
                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.RXD.getCoin() + "_users_30m", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.RXD.getCoin() + "_users_30m", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });

                Map<String, List<MinerDataDto>> userMap = list.stream().collect(Collectors.groupingBy(MinerDataDto::getMiner));
                if (result) {
                    System.out.println(DateUtils.dateTimeNow() + "rxd 小时数据存入数据成功");
                } else {
                    System.out.println(DateUtils.dateTimeNow() + "rxd 小时数据存入数据失败");

                }

            }
            else{
                //重来一次！
                CompletableFuture.runAsync(()->{
                    System.out.println("rxd 30分钟定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.RXD.getMhs() + "30m", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getHourMinerDataList(Pools.RXD.getMhs()+"_realv2",nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.RXD.getFac());
                                }
                            });
                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.RXD.getMhs() + "30m", getToHourDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.RXD.getPoolTable() + "_30m", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.RXD.getPoolTable() + "_30m", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                System.out.println("rxd 延迟任务 构造写入user算力表数据");
                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );
                                System.out.println("rxd 延迟任务 user算力表入库数据条数："+userList.size());
                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.RXD.getCoin() + "_users_30m", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.RXD.getCoin() + "_users_30m", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });
                            if (newResult) {
                                System.out.println(DateUtils.dateTimeNow() + "rxd 30m数据 延迟存入数据成功");
                            } else {
                                System.out.println(DateUtils.dateTimeNow() + "rxd 30m数据 延迟存入数据失败");

                            }

                        }
                    }
                });

            }
        }

    }

    @Scheduled(cron = "9 1,3,5 0 * * ?")
    public void RXDDailyDataToDB(){
        if(!enable){
            return;
        }
        String nowStr = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
        Date now = DateUtils.parseDate( nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.RXD.getMhs() + "24h", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getDailyMinerDataList(Pools.RXD.getMhs()+"_realv2", nowStr);
            if(list.size() > 0){
                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.RXD.getFac());
                    }
                });
                list = filterList(list,now);
                //list.stream().forEach(e ->{
                //    e.setDate(DateUtils.addDays(e.getDate(),-1));
                //});
                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.RXD.getMhs() + "24h", getToDailyDBListByMinerDataList(list));
                //todo 统计矿池数据写入矿池数据库 $coin_pool_24h
                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.RXD.getPoolTable() + "_24h", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.RXD.getPoolTable() + "_24h", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    //写入数据到coin_users表中
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );

                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.RXD.getCoin() + "_users_24h", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.RXD.getCoin() + "_users_24h", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });
                if(result){
                    System.out.println(DateUtils.dateTimeNow()+"rxd 每日存入数据成功");
                }else {
                    System.out.println(DateUtils.dateTimeNow()+"rxd 每日存入数据失败");

                }

            }else {
                CompletableFuture.runAsync(()->{
                    System.out.println("rxd 每日矿池定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.RXD.getMhs() + "24h", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getDailyMinerDataList(Pools.RXD.getMhs()+"_realv2", nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.RXD.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.RXD.getMhs() + "24h", getToDailyDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.RXD.getPoolTable() + "_24h", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.RXD.getPoolTable() + "_24h", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );

                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.RXD.getCoin() + "_users_24h", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.RXD.getCoin() + "_users_24h", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });


                        }else {
                            PoolPower poolPower  = new PoolPower();
                            poolPower.setDate(now);
                            poolPower.setMhs(BigDecimal.ZERO);
                            poolPower.setMiners(0);
                            poolPower.setOnline(0);
                            poolPower.setOffline(0);
                            boolean poolResult = poolMapper.insertPoolPower(Pools.RXD.getPoolTable() + "_24h", poolPower);
                            System.out.println("rxd 延时任务未查到 构造0数据入库,结果:"+poolPower);
                        }
                    }
                });
            }
        }
    }

    @Scheduled(cron = "59 0,1,30,31 * * * ?")
    public void RXDUserPowerRatioDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        now.setHours(0);
        now.setMinutes(0);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        BigDecimal poolMhs = poolMapper.getPoolTodayTotalPower("rxd", nowStr);
        List<UserPowerDto> userMhsList = poolMapper.getUserTodayTotalPower("rxd", nowStr);
        HashMap<String,BigDecimal> map = new HashMap<>();
        userMhsList.stream().forEach(e ->{
            map.put(e.getUser(),e.getMhs().divide(poolMhs,8,BigDecimal.ROUND_HALF_UP));
        });

        if(map.size() >0){
            redisService.deleteObject("RXDUserPowerRatio");
            redisService.setCacheMap("RXDUserPowerRatio",map);
        }

    }

    @Scheduled(cron = "39 3 0/1 * * ?")
    //@Scheduled(cron = "0 0/2 * * * ?")
    public void RXDLuckyDataToDB(){
        if(!enable){
            return;
        }
        log.info("rxd幸运值---定时任务开始");
        LuckDto dto = new LuckDto();
        Date end =  DateUtils.parseDate(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS));
        //幸运值 = 矿池实际报块/矿池理论报块
        //矿池实际报块 = 数据库查询表名为币名_pool_blkstats
        //矿池理论报块 =  (矿池过去N段时间的平均算力 / 全网过去N段时间平均算力) * 全网过去N段时间实际报块
        Date start3d = DateUtils.addDays(end,-3);
        Date start7d = DateUtils.addDays(end,-7);
        Date start30d = DateUtils.addDays(end,-30);
        Date start90d = DateUtils.addDays(end,-90);

        //获取全网实际90天内的报块数(v2)
        List<BlockInfoDto> blockPerDays = poolMapper.selectNetBlock("rxd_net_block");

        boolean useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start3d);
        //获取3天内全网的实际报块数
        BlockTimeAndNumberDto blockData = blockDataContext.getBlockData("rxd",start3d, end,blockPerDays, useAggregated);
        //3天矿池理论报块数
        BigDecimal throreticalBlocks= getTheoreticalBlocks("rxd",PoolUnits.RXD.gethRate(),start3d, end, blockData);
        log.info("全网实际报块数{}，矿池理论报块数{}",blockData.getHeight(),throreticalBlocks);
        //3天矿池实际报块数
        int actualBlocks = poolMapper.selectPoolBlock(start3d, end,"rxd",3);
        //3天幸运值
     if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck3d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //7天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start7d);

        blockData = blockDataContext.getBlockData("rxd",start7d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("rxd",PoolUnits.RXD.gethRate(),start7d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start7d, end,"rxd",7);
     if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck7d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //30天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start30d);

        blockData = blockDataContext.getBlockData("rxd",start30d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("rxd",PoolUnits.RXD.gethRate(),start30d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start30d, end,"rxd",30);
     if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck30d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        //90天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start90d);

        blockData = blockDataContext.getBlockData("rxd",start90d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("rxd",PoolUnits.RXD.gethRate(),start90d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start90d, end,"rxd",90);
     if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck90d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        redisService.deleteObject("RXDLuck");
        redisService.setCacheObject("RXDLuck",dto);
        log.info("rxd幸运值入库完成---幸运值3天：{},幸运值7天：{},幸运值30天：{},幸运值90天：{},",
                dto.getLuck3d(),dto.getLuck7d(),dto.getLuck30d(),dto.getLuck90d());
    }

    @Scheduled(cron = "21 1,3,13,31,33,43 * * * ?")
    public void ENX30mDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        int minute = (now.getMinutes() / 30) * 30;
        now.setMinutes( minute);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        System.out.println("enx 30分钟定时任务执行时间:"+now);
        System.out.println("格式化后的时间:"+nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.ENX.getMhs() + "30m", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getHourMinerDataList(Pools.ENX.getMhs()+"_realv2",nowStr);
            if(list.size() > 0){

                //list.stream().forEach(e -> {
                //    if(StringUtils.isNotNull(e.getMhs())){
                //        e.setMhs(e.getMhs() * Pools.ENX.getFac());
                //    }
                //});
                list = filterList(list,now);

                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.ENX.getMhs() + "30m", getToHourDBListByMinerDataList(list));

                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.ENX.getPoolTable() + "_30m", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.ENX.getPoolTable() + "_30m", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    System.out.println("rxd 构造写入user算力表数据");
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );
                    System.out.println("rxd user算力表入库数据条数："+userList.size());
                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ENX.getCoin() + "_users_30m", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ENX.getCoin() + "_users_30m", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });

                Map<String, List<MinerDataDto>> userMap = list.stream().collect(Collectors.groupingBy(MinerDataDto::getMiner));
                if (result) {
                    System.out.println(DateUtils.dateTimeNow() + "enx 小时数据存入数据成功");
                } else {
                    System.out.println(DateUtils.dateTimeNow() + "enx 小时数据存入数据失败");

                }

            }
            else{
                //重来一次！
                CompletableFuture.runAsync(()->{
                    System.out.println("enx 30分钟定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.ENX.getMhs() + "30m", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getHourMinerDataList(Pools.ENX.getMhs()+"_realv2",nowStr);
                        if(newList.size() > 0){

                            //newList.stream().forEach(e -> {
                            //    if(StringUtils.isNotNull(e.getMhs())){
                            //        e.setMhs(e.getMhs() * Pools.ENX.getFac());
                            //    }
                            //});
                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.ENX.getMhs() + "30m", getToHourDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.ENX.getPoolTable() + "_30m", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.ENX.getPoolTable() + "_30m", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                System.out.println("enx 延迟任务 构造写入user算力表数据");
                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );
                                System.out.println("enx 延迟任务 user算力表入库数据条数："+userList.size());
                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ENX.getCoin() + "_users_30m", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ENX.getCoin() + "_users_30m", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });
                            if (newResult) {
                                System.out.println(DateUtils.dateTimeNow() + "enx 30m数据 延迟存入数据成功");
                            } else {
                                System.out.println(DateUtils.dateTimeNow() + "enx 30m数据 延迟存入数据失败");

                            }

                        }
                    }
                });

            }
        }

    }

    @Scheduled(cron = "10 1,3,5 0 * * ?")
    public void ENXDailyDataToDB(){
        if(!enable){
            return;
        }
        String nowStr = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
        Date now = DateUtils.parseDate( nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.ENX.getMhs() + "24h", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getDailyMinerDataList(Pools.ENX.getMhs()+"_realv2", nowStr);
            if(list.size() > 0){
                //list.stream().forEach(e -> {
                //    if(StringUtils.isNotNull(e.getMhs())){
                //        e.setMhs(e.getMhs() * Pools.ENX.getFac());
                //    }
                //});
                list = filterList(list,now);
                //list.stream().forEach(e ->{
                //    e.setDate(DateUtils.addDays(e.getDate(),-1));
                //});
                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.ENX.getMhs() + "24h", getToDailyDBListByMinerDataList(list));
                //todo 统计矿池数据写入矿池数据库 $coin_pool_24h
                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.ENX.getPoolTable() + "_24h", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.ENX.getPoolTable() + "_24h", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    //写入数据到coin_users表中
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );

                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ENX.getCoin() + "_users_24h", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ENX.getCoin() + "_users_24h", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });
                if(result){
                    System.out.println(DateUtils.dateTimeNow()+"enx 每日存入数据成功");
                }else {
                    System.out.println(DateUtils.dateTimeNow()+"enx 每日存入数据失败");

                }

            }else {
                CompletableFuture.runAsync(()->{
                    System.out.println("enx 每日矿池定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.ENX.getMhs() + "24h", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getDailyMinerDataList(Pools.ENX.getMhs()+"_realv2", nowStr);
                        if(newList.size() > 0){

                            //newList.stream().forEach(e -> {
                            //    if(StringUtils.isNotNull(e.getMhs())){
                            //        e.setMhs(e.getMhs() * Pools.ENX.getFac());
                            //    }
                            //});

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.ENX.getMhs() + "24h", getToDailyDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.ENX.getPoolTable() + "_24h", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.ENX.getPoolTable() + "_24h", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );

                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ENX.getCoin() + "_users_24h", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ENX.getCoin() + "_users_24h", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });


                        }else {
                            PoolPower poolPower  = new PoolPower();
                            poolPower.setDate(now);
                            poolPower.setMhs(BigDecimal.ZERO);
                            poolPower.setMiners(0);
                            poolPower.setOnline(0);
                            poolPower.setOffline(0);
                            boolean poolResult = poolMapper.insertPoolPower(Pools.ENX.getPoolTable() + "_24h", poolPower);
                            System.out.println("enx 延时任务未查到 构造0数据入库,结果:"+poolPower);
                        }
                    }
                });
            }
        }
    }

    @Scheduled(cron = "53 0,1,30,31 * * * ?")
    public void ENXUserPowerRatioDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        now.setHours(0);
        now.setMinutes(0);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        BigDecimal poolMhs = poolMapper.getPoolTodayTotalPower("enx", nowStr);
        List<UserPowerDto> userMhsList = poolMapper.getUserTodayTotalPower("enx", nowStr);
        HashMap<String,BigDecimal> map = new HashMap<>();
        userMhsList.stream().forEach(e ->{
            if(poolMhs != BigDecimal.ZERO){
                map.put(e.getUser(),e.getMhs().divide(poolMhs,8, RoundingMode.HALF_UP));
            }
        });

        if(map.size() >0){
            redisService.deleteObject("ENXUserPowerRatio");
            redisService.setCacheMap("ENXUserPowerRatio",map);
        }

    }

    //@Scheduled(cron = "30 2,7 0,12 * * ?")
    //@Scheduled(cron = "41 2,5 0/12 * * ?")
    public void ENXLuckyDataToDB(){
        if(!enable){
            return;
        }
        int time = 0;
        LuckDto dto = new LuckDto();
        Date end =  DateUtils.parseDate(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD));
        do {
            //幸运值
            // N天应出块数量 = N天矿池平均算力/ N天全网平均算力 * 币种每日出块数 * N天  取同一时间点的矿池算力/全网算力
            // 币种每日出块数 = 720        数值来源: 每日分钟数(24*60) / 出一个块需要的时间(根据具体币种 nexa是2分钟)
            // N天实际出块量 数据库查询N天实际出块量
            // N天幸运值 = N天实际出块量 / N天应出块量 * 100  结果即百分比数字%
            /** 全网每日出块数 */
            BigDecimal rxdCount = PoolCalParamConfig.ENX.getCount();

            //计算矿池每日实际应出块数  block中算力单位是H/s
            int hRate = PoolUnits.ENX.gethRate();
            //先把矿池算力单位转换为H/s 再除以全网算力 得到比值 再乘以每日全网出块数 得到矿池每日应出块数
            List<DateBigDecimalDto> netPowerList = poolMapper.getDailyNetPower("enx");
            if(netPowerList.isEmpty()){
                continue;
            }

            List<DateBigDecimalDto> poolPowerList = poolMapper.getDailyPoolPower("enx");

            //拿报块list 筛选实际出块数
            List<BlockInfoDto> list = poolMapper.getENXBlockInfoList();

            if (list.isEmpty()){
                continue;
            }

            //第一条报块数据的时间
            Date poolStart = list.get(list.size() - 1).getDate();
            Date start3d = DateUtils.addDays(end,-3);
            Date start7d = DateUtils.addDays(end,-7);
            Date start30d = DateUtils.addDays(end,-30);
            Date start90d = DateUtils.addDays(end,-90);
            //(矿池平均/全网平均) * (全网计算平均的时间/矿池计算平均的时间) * 每日全网出块数 = 矿池每日应出块数
            long pDay3d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start3d) || e.getPDate().equals(start3d))).count();

            //矿池单位转换
            BigDecimal pPow3d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start3d) || e.getPDate().equals(start3d)))
                    .map(DateBigDecimalDto::getValue).reduce(BigDecimal.ZERO, BigDecimal::add)
                    .multiply(BigDecimal.valueOf(hRate));

            long nDay3d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start3d) || e.getPDate().equals(start3d))).count();

            BigDecimal nPow3d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start3d) || e.getPDate().equals(start3d)))
                    .map(DateBigDecimalDto::getValue).reduce(BigDecimal.ZERO, BigDecimal::add);

            if(pDay3d == 0 || nDay3d == 0){
                continue;
            }
            //计算3天 每日出块量
            BigDecimal dayChunk3d = pPow3d
                    .multiply(BigDecimal.valueOf(nDay3d * nDay3d))
                    .divide(nPow3d.multiply(BigDecimal.valueOf(pDay3d * pDay3d)),8,BigDecimal.ROUND_HALF_UP)
                    .multiply(rxdCount)
                    .setScale(8, BigDecimal.ROUND_HALF_UP);

            long pDay7d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start7d) || e.getPDate().equals(start7d))).count();

            BigDecimal pPow7d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start7d) || e.getPDate().equals(start7d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add)
                    .multiply(BigDecimal.valueOf(hRate));

            long nDay7d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start7d) || e.getPDate().equals(start7d))).count();

            BigDecimal nPow7d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start7d) || e.getPDate().equals(start7d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add);

            if(pDay7d == 0 || nDay7d == 0){
                continue;
            }

            //计算7d 每日应出块量
            BigDecimal dayChunk7d = pPow7d
                    .multiply(BigDecimal.valueOf(nDay7d * nDay7d))
                    .divide(nPow7d.multiply(BigDecimal.valueOf(pDay7d * pDay7d)),8,BigDecimal.ROUND_HALF_UP)
                    .multiply(rxdCount)
                    .setScale(8, BigDecimal.ROUND_HALF_UP);

            long pDay30d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start30d) || e.getPDate().equals(start30d))).count();

            BigDecimal pPow30d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start30d) || e.getPDate().equals(start30d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add)
                    .multiply(BigDecimal.valueOf(hRate));

            long nDay30d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start30d) || e.getPDate().equals(start30d))).count();

            BigDecimal nPow30d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start30d) || e.getPDate().equals(start30d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add);

            if(pDay30d == 0 || nDay30d == 0){
                continue;
            }

            //计算30d 每日应出块量
            BigDecimal dayChunk30d = pPow30d
                    .multiply(BigDecimal.valueOf(nDay30d * nDay30d))
                    .divide(nPow30d.multiply(BigDecimal.valueOf(pDay30d * pDay30d)),8,BigDecimal.ROUND_HALF_UP)
                    .multiply(rxdCount)
                    .setScale(8, BigDecimal.ROUND_HALF_UP);

            long pDay90d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start90d) || e.getPDate().equals(start90d))).count();

            BigDecimal pPow90d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start90d) || e.getPDate().equals(start90d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add)
                    .multiply(BigDecimal.valueOf(hRate));

            long nDay90d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start90d) || e.getPDate().equals(start90d))).count();

            BigDecimal nPow90d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start90d) || e.getPDate().equals(start90d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add);

            if(pDay90d == 0 || nDay90d == 0){
                continue;
            }

            //计算90d 每日应出块量
            BigDecimal dayChunk90d = pPow90d
                    .multiply(BigDecimal.valueOf(nDay90d * nDay90d))
                    .divide(nPow90d.multiply(BigDecimal.valueOf(pDay90d * pDay90d)),8,BigDecimal.ROUND_HALF_UP)
                    .multiply(rxdCount)
                    .setScale(8, BigDecimal.ROUND_HALF_UP);

            //3天时间出块数
            long count3d = list.stream()
                    .filter(e -> (e.getDate().before(end)))
                    .filter(e -> (e.getDate().after(start3d) || e.getDate().equals(start3d)))
                    .count();
            BigDecimal chunk3d = BigDecimal.valueOf(count3d);
            //7天时间出块数
            long count7d = list.stream()
                    .filter(e -> (e.getDate().before(end)))
                    .filter(e -> (e.getDate().after(start7d) || e.getDate().equals(start7d)))
                    .count();
            BigDecimal chunk7d = BigDecimal.valueOf(count7d);
            //30天时间出块数
            long count30d = list.stream()
                    .filter(e -> (e.getDate().before(end)))
                    .filter(e -> (e.getDate().after(start30d) || e.getDate().equals(start30d)))
                    .count();
            BigDecimal chunk30d = BigDecimal.valueOf(count30d);
            //90天时间出块数
            long count90d = list.stream()
                    .filter(e -> (e.getDate().before(end)))
                    .filter(e -> (e.getDate().after(start90d) || e.getDate().equals(start90d)))
                    .count();
            BigDecimal chunk90d = BigDecimal.valueOf(count90d);

            if(poolStart.after(start3d)){
                System.out.println("不足3天");
                long needTime = poolStart.getTime()-start3d.getTime();
                chunk3d = chunk3d
                        .add(dayChunk3d.multiply(BigDecimal.valueOf(needTime).divide(BigDecimal.valueOf(86400000),8,BigDecimal.ROUND_HALF_UP)));
            }
            System.out.println("3天出块量"+chunk3d);
            dto.setLuck3d(chunk3d.divide(dayChunk3d.multiply(BigDecimal.valueOf(3)),4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).doubleValue());

            if(poolStart.after(start7d)){
                System.out.println("不足7天");
                long needTime = poolStart.getTime()-start7d.getTime();
                chunk7d = chunk7d
                        .add(dayChunk7d.multiply(BigDecimal.valueOf(needTime).divide(BigDecimal.valueOf(86400000),8,BigDecimal.ROUND_HALF_UP)));
            }
            System.out.println("7天出块量"+chunk7d);
            dto.setLuck7d(chunk7d.divide(dayChunk7d.multiply(BigDecimal.valueOf(7)),4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).doubleValue());


            if(poolStart.after(start30d)){
                System.out.println("不足30天");
                long needTime = poolStart.getTime()-start30d.getTime();
                chunk30d = chunk30d
                        .add(dayChunk30d.multiply(BigDecimal.valueOf(needTime).divide(BigDecimal.valueOf(86400000),8,BigDecimal.ROUND_HALF_UP)));
            }
            System.out.println("30天出块量"+chunk30d);
            dto.setLuck30d(chunk30d.divide(dayChunk30d.multiply(BigDecimal.valueOf(30)),4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).doubleValue());

            if(poolStart.after(start90d)){
                System.out.println("不足90天");
                long needTime = poolStart.getTime()-start90d.getTime();
                chunk90d = chunk90d
                        .add(dayChunk90d.multiply(BigDecimal.valueOf(needTime).divide(BigDecimal.valueOf(86400000),8,BigDecimal.ROUND_HALF_UP)));
            }
            System.out.println("90天出块量"+chunk90d);
            dto.setLuck90d(chunk90d.divide(dayChunk90d.multiply(BigDecimal.valueOf(90)),4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).doubleValue());

            break;
        }while (time < 4);

        redisService.deleteObject("ENXLuck");
        redisService.setCacheObject("ENXLuck",dto);
    }

    @Scheduled(cron = "23 1,3,13,31,33,43 * * * ?")
    public void ALPH30mDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        int minute = (now.getMinutes() / 30) * 30;
        now.setMinutes( minute);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        System.out.println("alph 30分钟定时任务执行时间:"+now);
        System.out.println("格式化后的时间:"+nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.ALPH.getMhs() + "30m", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getHourMinerDataList(Pools.ALPH.getMhs()+"_realv2",nowStr);
            if(list.size() > 0){
                List<MinerDataDto> offlineList = new ArrayList<>();
                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.ALPH.getFac());
                    }
                    if("offline".equals(e.getState())){
                        offlineList.add(e);
                    }
                });
                list = filterList(list,now);

                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.ALPH.getMhs() + "30m", getToHourDBListByMinerDataList(list));

                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.ALPH.getPoolTable() + "_30m", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.ALPH.getPoolTable() + "_30m", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    System.out.println("构造写入user算力表数据");
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );
                    System.out.println("user算力表入库数据条数："+userList.size());
                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ALPH.getCoin() + "_users_30m", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ALPH.getCoin() + "_users_30m", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });

                if (result) {
                    System.out.println(DateUtils.dateTimeNow() + "alph小时数据存入数据成功");
                } else {
                    System.out.println(DateUtils.dateTimeNow() + "alph小时数据存入数据失败");
                }
            }
            else{
                //重来一次！
                CompletableFuture.runAsync(()->{
                    System.out.println("alph 30分钟定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.ALPH.getMhs() + "30m", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getHourMinerDataList(Pools.ALPH.getMhs()+"_realv2",nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.ALPH.getFac());
                                }
                            });
                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.ALPH.getMhs() + "30m", getToHourDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.ALPH.getPoolTable() + "_30m", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.ALPH.getPoolTable() + "_30m", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                System.out.println("延迟任务 构造写入user算力表数据");
                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );
                                System.out.println("延迟任务 user算力表入库数据条数："+userList.size());
                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ALPH.getCoin() + "_users_30m", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ALPH.getCoin() + "_users_30m", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });
                            if (newResult) {
                                System.out.println(DateUtils.dateTimeNow() + "alph30m数据 延迟存入数据成功");
                            } else {
                                System.out.println(DateUtils.dateTimeNow() + "alph30m数据 延迟存入数据失败");

                            }

                        }
                    }
                });

            }
        }

    }

    @Scheduled(cron = "12 1,3,5 0 * * ?")
    public void ALPHDailyDataToDB(){
        if(!enable){
            return;
        }
        String nowStr = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
        Date now = DateUtils.parseDate( nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.ALPH.getMhs() + "24h", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getDailyMinerDataList(Pools.ALPH.getMhs()+"_realv2", nowStr);
            if(list.size() > 0){
                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.ALPH.getFac());
                    }
                });
                list = filterList(list,now);
                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.ALPH.getMhs() + "24h", getToDailyDBListByMinerDataList(list));
                //todo 统计矿池数据写入矿池数据库 $coin_pool_24h
                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.ALPH.getPoolTable() + "_24h", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.ALPH.getPoolTable() + "_24h", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    //写入数据到coin_users表中
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );

                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ALPH.getCoin() + "_users_24h", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ALPH.getCoin() + "_users_24h", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });
                if(result){
                    System.out.println(DateUtils.dateTimeNow()+"alph每日存入数据成功");
                }else {
                    System.out.println(DateUtils.dateTimeNow()+"alph每日存入数据失败");

                }

            }else {
                CompletableFuture.runAsync(()->{
                    System.out.println("alph 每日矿池定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.ALPH.getMhs() + "24h", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getDailyMinerDataList(Pools.ALPH.getMhs()+"_realv2", nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.ALPH.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            //boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.ALPH.getMhs() + "24h", getToDailyDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.ALPH.getPoolTable() + "_24h", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.ALPH.getPoolTable() + "_24h", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );

                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ALPH.getCoin() + "_users_24h", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.ALPH.getCoin() + "_users_24h", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });


                        }else {
                            PoolPower poolPower  = new PoolPower();
                            poolPower.setDate(now);
                            poolPower.setMhs(BigDecimal.ZERO);
                            poolPower.setMiners(0);
                            poolPower.setOnline(0);
                            poolPower.setOffline(0);
                            //boolean poolResult = poolMapper.insertPoolPower(Pools.ALPH.getPoolTable() + "_24h", poolPower);
                            System.out.println("延时任务未查到 构造0数据入库,结果:"+poolPower);
                        }
                    }
                });
            }
        }
    }

    @Scheduled(cron = "52 0,1,30,31 * * * ?")
    public void ALPHUserPowerRatioDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        now.setHours(0);
        now.setMinutes(0);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        BigDecimal poolMhs = poolMapper.getPoolTodayTotalPower("alph", nowStr);
        List<UserPowerDto> userMhsList = poolMapper.getUserTodayTotalPower("alph", nowStr);
        HashMap<String,BigDecimal> map = new HashMap<>();
        userMhsList.stream().forEach(e ->{
            if(poolMhs.compareTo(BigDecimal.ZERO) != 0){
                map.put(e.getUser(),e.getMhs().divide(poolMhs,8, RoundingMode.HALF_UP));
            }
        });

        if(map.size() >0){
            redisService.deleteObject("ALPHUserPowerRatio");
            redisService.setCacheMap("ALPHUserPowerRatio",map);
        }

    }

    //@Scheduled(cron = "30 2,7 0,12 * * ?")
    @Scheduled(cron = "42 2,5 0/12 * * ?")
    public void ALPHLuckyDataToDB(){
        if(!enable){
            return;
        }
        int time = 0;
        LuckDto dto = new LuckDto();
        Date end =  DateUtils.parseDate(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD));
        do {
            //幸运值
            // N天应出块数量 = N天矿池平均算力/ N天全网平均算力 * 币种每日出块数 * N天  取同一时间点的矿池算力/全网算力
            // 币种每日出块数 = 720        数值来源: 每日分钟数(24*60) / 出一个块需要的时间(根据具体币种 nexa是2分钟)
            // N天实际出块量 数据库查询N天实际出块量
            // N天幸运值 = N天实际出块量 / N天应出块量 * 100  结果即百分比数字%
            /** 全网每日出块数 */
            BigDecimal nexaCount = PoolCalParamConfig.ALPH.getCount();

            //计算矿池每日实际应出块数  block中算力单位是H/s
            int hRate = PoolUnits.ALPH.gethRate();
            //先把矿池算力单位转换为H/s 再除以全网算力 得到比值 再乘以每日全网出块数 得到矿池每日应出块数
            List<DateBigDecimalDto> netPowerList = poolMapper.getDailyNetPower("alph");
            if(netPowerList.size() < 1){
                continue;
            }

            List<DateBigDecimalDto> poolPowerList = poolMapper.getDailyPoolPower("alph");

            //拿报块list 筛选实际出块数
            List<BlockInfoDto> list = poolMapper.getNEXABlockInfoList();

            if (list.size() < 1){
                continue;
            }

            //第一条报块数据的时间
            Date poolStart = list.get(list.size() - 1).getDate();
            Date start3d = DateUtils.addDays(end,-3);
            Date start7d = DateUtils.addDays(end,-7);
            Date start30d = DateUtils.addDays(end,-30);
            Date start90d = DateUtils.addDays(end,-90);
            //(矿池平均/全网平均) * (全网计算平均的时间/矿池计算平均的时间) * 每日全网出块数 = 矿池每日应出块数
            long pDay3d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start3d) || e.getPDate().equals(start3d))).count();

            //矿池单位转换
            BigDecimal pPow3d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start3d) || e.getPDate().equals(start3d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add)
                    .multiply(BigDecimal.valueOf(hRate));

            long nDay3d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start3d) || e.getPDate().equals(start3d))).count();

            BigDecimal nPow3d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start3d) || e.getPDate().equals(start3d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add);

            if(pDay3d == 0 || nDay3d == 0){
                continue;
            }
            //计算3天 每日出块量
            BigDecimal dayChunk3d = pPow3d
                    .multiply(BigDecimal.valueOf(nDay3d * nDay3d))
                    .divide(nPow3d.multiply(BigDecimal.valueOf(pDay3d * pDay3d)),8,BigDecimal.ROUND_HALF_UP)
                    .multiply(nexaCount)
                    .setScale(8, BigDecimal.ROUND_HALF_UP);

            long pDay7d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start7d) || e.getPDate().equals(start7d))).count();

            BigDecimal pPow7d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start7d) || e.getPDate().equals(start7d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add)
                    .multiply(BigDecimal.valueOf(hRate));

            long nDay7d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start7d) || e.getPDate().equals(start7d))).count();

            BigDecimal nPow7d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start7d) || e.getPDate().equals(start7d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add);

            if(pDay7d == 0 || nDay7d == 0){
                continue;
            }

            //计算7d 每日应出块量
            BigDecimal dayChunk7d = pPow7d
                    .multiply(BigDecimal.valueOf(nDay7d * nDay7d))
                    .divide(nPow7d.multiply(BigDecimal.valueOf(pDay7d * pDay7d)),8,BigDecimal.ROUND_HALF_UP)
                    .multiply(nexaCount)
                    .setScale(8, BigDecimal.ROUND_HALF_UP);

            long pDay30d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start30d) || e.getPDate().equals(start30d))).count();

            BigDecimal pPow30d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start30d) || e.getPDate().equals(start30d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add)
                    .multiply(BigDecimal.valueOf(hRate));

            long nDay30d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start30d) || e.getPDate().equals(start30d))).count();

            BigDecimal nPow30d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start30d) || e.getPDate().equals(start30d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add);

            if(pDay30d == 0 || nDay30d == 0){
                continue;
            }

            //计算30d 每日应出块量
            BigDecimal dayChunk30d = pPow30d
                    .multiply(BigDecimal.valueOf(nDay30d * nDay30d))
                    .divide(nPow30d.multiply(BigDecimal.valueOf(pDay30d * pDay30d)),8,BigDecimal.ROUND_HALF_UP)
                    .multiply(nexaCount)
                    .setScale(8, BigDecimal.ROUND_HALF_UP);

            long pDay90d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start90d) || e.getPDate().equals(start90d))).count();

            BigDecimal pPow90d = poolPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start90d) || e.getPDate().equals(start90d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add)
                    .multiply(BigDecimal.valueOf(hRate));

            long nDay90d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start90d) || e.getPDate().equals(start90d))).count();

            BigDecimal nPow90d = netPowerList.stream()
                    .filter(e -> (e.getPDate().before(end)))
                    .filter(e -> (e.getPDate().after(start90d) || e.getPDate().equals(start90d)))
                    .map(e -> e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add);

            if(pDay90d == 0 || nDay90d == 0){
                continue;
            }

            //计算90d 每日应出块量
            BigDecimal dayChunk90d = pPow90d
                    .multiply(BigDecimal.valueOf(nDay90d * nDay90d))
                    .divide(nPow90d.multiply(BigDecimal.valueOf(pDay90d * pDay90d)),8,BigDecimal.ROUND_HALF_UP)
                    .multiply(nexaCount)
                    .setScale(8, BigDecimal.ROUND_HALF_UP);

            //3天时间出块数
            long count3d = list.stream()
                    .filter(e -> (e.getDate().before(end)))
                    .filter(e -> (e.getDate().after(start3d) || e.getDate().equals(start3d)))
                    .count();
            BigDecimal chunk3d = BigDecimal.valueOf(count3d);
            //7天时间出块数
            long count7d = list.stream()
                    .filter(e -> (e.getDate().before(end)))
                    .filter(e -> (e.getDate().after(start7d) || e.getDate().equals(start7d)))
                    .count();
            BigDecimal chunk7d = BigDecimal.valueOf(count7d);
            //30天时间出块数
            long count30d = list.stream()
                    .filter(e -> (e.getDate().before(end)))
                    .filter(e -> (e.getDate().after(start30d) || e.getDate().equals(start30d)))
                    .count();
            BigDecimal chunk30d = BigDecimal.valueOf(count30d);
            //90天时间出块数
            long count90d = list.stream()
                    .filter(e -> (e.getDate().before(end)))
                    .filter(e -> (e.getDate().after(start90d) || e.getDate().equals(start90d)))
                    .count();
            BigDecimal chunk90d = BigDecimal.valueOf(count90d);

            if(poolStart.after(start3d)){
                System.out.println("不足3天");
                long needTime = poolStart.getTime()-start3d.getTime();
                chunk3d = chunk3d
                        .add(dayChunk3d.multiply(BigDecimal.valueOf(needTime).divide(BigDecimal.valueOf(86400000),8,BigDecimal.ROUND_HALF_UP)));
            }
            System.out.println("3天出块量"+chunk3d);
            dto.setLuck3d(chunk3d.divide(dayChunk3d.multiply(BigDecimal.valueOf(3)),4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).doubleValue());

            if(poolStart.after(start7d)){
                System.out.println("不足7天");
                long needTime = poolStart.getTime()-start7d.getTime();
                chunk7d = chunk7d
                        .add(dayChunk7d.multiply(BigDecimal.valueOf(needTime).divide(BigDecimal.valueOf(86400000),8,BigDecimal.ROUND_HALF_UP)));
            }
            System.out.println("7天出块量"+chunk7d);
            dto.setLuck7d(chunk7d.divide(dayChunk7d.multiply(BigDecimal.valueOf(7)),4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).doubleValue());


            if(poolStart.after(start30d)){
                System.out.println("不足30天");
                long needTime = poolStart.getTime()-start30d.getTime();
                chunk30d = chunk30d
                        .add(dayChunk30d.multiply(BigDecimal.valueOf(needTime).divide(BigDecimal.valueOf(86400000),8,BigDecimal.ROUND_HALF_UP)));
            }
            System.out.println("30天出块量"+chunk30d);
            dto.setLuck30d(chunk30d.divide(dayChunk30d.multiply(BigDecimal.valueOf(30)),4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).doubleValue());

            if(poolStart.after(start90d)){
                System.out.println("不足90天");
                long needTime = poolStart.getTime()-start90d.getTime();
                chunk90d = chunk90d
                        .add(dayChunk90d.multiply(BigDecimal.valueOf(needTime).divide(BigDecimal.valueOf(86400000),8,BigDecimal.ROUND_HALF_UP)));
            }
            System.out.println("90天出块量"+chunk90d);
            dto.setLuck90d(chunk90d.divide(dayChunk90d.multiply(BigDecimal.valueOf(90)),4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).doubleValue());

            break;
        }while (time < 4);

        redisService.deleteObject("ALPHLuck");
        redisService.setCacheObject("ALPHLuck",dto);
    }

    //@Scheduled(cron = "5 2,4,6 0/1 * * ?")
    //public void NEXAHourUserDataToDB(){
    //    String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:00:00");
    //    Date now = DateUtils.parseDate( nowStr);
    //
    //    System.out.println("执行时间:"+now);
    //
    //    //检查二级表是否有当前时间数据
    //    int count = poolMapper.getLastDataTime(Pools.NEXA.getCoin() + "_users" +"_1h", nowStr);
    //
    //    if(count == 0) {
    //        List<MinerDataDto> list = poolMapper.getUserHourMinerDataList(Pools.NEXA.getCoin() + "_users" +"_stats");
    //
    //        if(list.size() > 0){
    //            //处理list 1、根据时间筛选 2、根据状态筛选 3、数据时间格式化'
    //            list = filterList(list,now);
    //
    //            boolean result = poolMapper.batchInsertUserMhsDataToDB(Pools.NEXA.getCoin() + "_users" + "_1h", getToHourDBListByMinerDataList(list));
    //            if (result) {
    //                System.out.println(DateUtils.dateTimeNow() + "nexa小时数据存入数据成功");
    //            } else {
    //                System.out.println(DateUtils.dateTimeNow() + "nexa小时数据存入数据失败");
    //
    //            }
    //
    //        }
    //    }
    //
    //}
    //
    //@Scheduled(cron = "0 2,3,4 0 * * ?")
    //public void NEXADailyUserDataToDB(){
    //    String nowStr = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
    //    Date now = DateUtils.parseDate( nowStr);
    //    //检查二级表是否有当前时间数据
    //    int count = poolMapper.getLastDataTime(Pools.NEXA.getCoin() + "_users" + "_1d", nowStr);
    //
    //    if(count == 0) {
    //        List<MinerDataDto> list = poolMapper.getUserDailyMinerDataList(Pools.NEXA.getCoin() + "_users" + "_stats");
    //        if(list.size() > 0){
    //
    //            list = filterList(list,now);
    //
    //            list.stream().forEach(e ->{
    //                e.setDate(DateUtils.addDays(e.getDate(),-1));
    //            });
    //
    //            boolean result = poolMapper.batchInsertUserMhsDataToDB(Pools.NEXA.getCoin() + "_users" + "_1d", getToDailyDBListByMinerDataList(list));
    //            if(result){
    //                System.out.println(DateUtils.dateTimeNow()+"nexa用户每日统计存入数据成功");
    //            }else {
    //                System.out.println(DateUtils.dateTimeNow()+"nexa用户每日统计存入数据失败");
    //
    //            }
    //
    //        }
    //    }
    //}

    /**
     * 格式化list中对象的日期
     * @param list
     * @return
     */
    public static List<MinerDataInsertDBDto> getToHourDBListByMinerDataList(List<MinerDataDto> list){
        List<MinerDataInsertDBDto> dbList = list.stream().map(e -> {
            MinerDataInsertDBDto dto = new MinerDataInsertDBDto();
            BeanUtils.copyProperties(e, dto);
            dto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,e.getDate()));
            if(StringUtils.isNotNull(e.getLastSubmit())){
                dto.setLastSubmit(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,e.getLastSubmit()));
            }
            return dto;
        }).collect(Collectors.toList());

        return dbList;
    }

    /**
     *格式化对象 日期属性为YYYY_MM_DD
     * @param list
     * @return
     */
    public static List<MinerDataInsertDBDto> getToDailyDBListByMinerDataList(List<MinerDataDto> list){
        List<MinerDataInsertDBDto> dbList = list.stream().map(e -> {
            MinerDataInsertDBDto dto = new MinerDataInsertDBDto();
            BeanUtils.copyProperties(e, dto);
            dto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,e.getDate()));
            if(StringUtils.isNotNull(e.getLastSubmit())){
                dto.setLastSubmit(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,e.getLastSubmit()));
            }
            return dto;
        }).collect(Collectors.toList());

        return dbList;
    }

    /**
     * 过滤重复数据
     * @param list
     * @param now
     * @return
     */
    public static List<MinerDataDto> filterList(List<MinerDataDto> list,Date now){

        if(list.size()<1){
            return list;
        }

        list = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getUser() + ":" + o.getMiner()))), ArrayList::new));

        //list user:miner 重复拿date最新的数据
        list = list.stream().
                collect(Collectors.toMap(
                        e -> e.getUser()+":"+ e.getMiner(),
                        Function.identity(),
                        (p1,p2) -> p1.getDate().after(p2.getDate()) ? p1 : p2)).values().stream().collect(Collectors.toList());

        list.stream().forEach(e ->{
            if (!DateUtils.isSameDate(e.getDate(),now)){
                System.out.println(e.getDate().getTime()+" before "+now.getTime());
                e.setAccepts(0);
                e.setRejects(0);
                e.setRejectsRatio(0);
                e.setMhs(0);
                e.setMhs24h(0);
            }

            e.setDate(now);

        });

        return list;
    }



    @Scheduled(cron = "20 1,3,10,31,33,40 * * * ?")
    public void MONERO30mDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            System.out.println("DataTask 定时任务已关闭，请在nacos修改配置");
            return;
        }
        Date now = new Date();
        int minute = (now.getMinutes() / 30) * 30;
        now.setMinutes( minute);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        System.out.println("MONERO 30分钟定时任务执行时间:"+now);
        System.out.println("格式化后的时间:"+nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.MONERO.getMhs() + "30m", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getHourMinerDataList(Pools.MONERO.getMhs()+"_realv2",nowStr);
            if(list.size() > 0){
                List<MinerDataDto> offlineList = new ArrayList<>();
                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.MONERO.getFac());
                    }
                    if("offline".equals(e.getState())){
                        offlineList.add(e);
                    }
                });
                list = filterList(list,now);

                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.MONERO.getMhs() + "30m", getToHourDBListByMinerDataList(list));

                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.MONERO.getPoolTable() + "_30m", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.MONERO.getPoolTable() + "_30m", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    System.out.println("构造写入user算力表数据");
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );
                    System.out.println("user算力表入库数据条数："+userList.size());
                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONERO.getName() + "_users_30m", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONERO.getName() + "_users_30m", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }




                });

                Map<String, List<MinerDataDto>> userMap = list.stream().collect(Collectors.groupingBy(MinerDataDto::getMiner));
                if (result) {
                    System.out.println(DateUtils.dateTimeNow() + "MONERO 小时数据存入数据成功");
                } else {
                    System.out.println(DateUtils.dateTimeNow() + "MONERO 小时数据存入数据失败");
                }

                if(offlineList.size() >0){
                    CompletableFuture.runAsync(()->{

                        //根据挖矿账户分组、统计离线矿机名单、离线矿机数

                        //对比redis中该挖矿账户上一次离线矿机数
                        //有redis数据 需要判断 上一次离线矿机数<本次矿机离线数 才执行通知 否则跳过
                        //无redis数据 说明是第一次 执行通知
                    });

                }

            }
            else{
                //重来一次！
                CompletableFuture.runAsync(()->{
                    System.out.println("MONERO 30分钟定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.MONERO.getMhs() + "30m", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getHourMinerDataList(Pools.MONERO.getMhs()+"_realv2",nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.MONERO.getFac());
                                }
                            });
                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.MONERO.getMhs() + "30m", getToHourDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.MONERO.getPoolTable() + "_30m", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.MONERO.getPoolTable() + "_30m", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                System.out.println("延迟任务 构造写入user算力表数据");
                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );
                                System.out.println("延迟任务 user算力表入库数据条数："+userList.size());
                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONERO.getName() + "_users_30m", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONERO.getName() + "_users_30m", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });
                            if (newResult) {
                                System.out.println(DateUtils.dateTimeNow() + "MONERO 30m数据 延迟存入数据成功");
                            } else {
                                System.out.println(DateUtils.dateTimeNow() + "MONERO 30m数据 延迟存入数据失败");

                            }

                        }
                    }
                });

            }
        }

    }

    @Scheduled(cron = "0 1,3,5 0 * * ?")
    public void MONERODailyDataToDB(){
        if(!enable){
            return;
        }
        String nowStr = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
        Date now = DateUtils.parseDate( nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.MONERO.getMhs() + "24h", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getDailyMinerDataList(Pools.MONERO.getMhs()+"_realv2", nowStr);
            if(list.size() > 0){
                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.MONERO.getFac());
                    }
                });
                list = filterList(list,now);
                //list.stream().forEach(e ->{
                //    e.setDate(DateUtils.addDays(e.getDate(),-1));
                //});
                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.MONERO.getMhs() + "24h", getToDailyDBListByMinerDataList(list));
                //todo 统计矿池数据写入矿池数据库 $coin_pool_24h
                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.MONERO.getPoolTable() + "_24h", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.MONERO.getPoolTable() + "_24h", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    //写入数据到coin_users表中
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );

                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONERO.getName() + "_users_24h", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONERO.getName() + "_users_24h", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });
                if(result){
                    System.out.println(DateUtils.dateTimeNow()+"MONERO 每日存入数据成功");
                }else {
                    System.out.println(DateUtils.dateTimeNow()+"MONERO 每日存入数据失败");

                }

            }else {
                CompletableFuture.runAsync(()->{
                    System.out.println("MONERO 每日矿池定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.MONERO.getMhs() + "24h", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getDailyMinerDataList(Pools.MONERO.getMhs()+"_realv2", nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.MONERO.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.MONERO.getMhs() + "24h", getToDailyDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.MONERO.getPoolTable() + "_24h", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.MONERO.getPoolTable() + "_24h", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );

                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONERO.getName() + "_users_24h", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.MONERO.getName() + "_users_24h", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });


                        }else {
                            PoolPower poolPower  = new PoolPower();
                            poolPower.setDate(now);
                            poolPower.setMhs(BigDecimal.ZERO);
                            poolPower.setMiners(0);
                            poolPower.setOnline(0);
                            poolPower.setOffline(0);
                            boolean poolResult = poolMapper.insertPoolPower(Pools.MONERO.getPoolTable() + "_24h", poolPower);
                            System.out.println("延时任务未查到 构造0数据入库,结果:"+poolPower);
                        }
                    }
                });
            }
        }
    }

    @Scheduled(cron = "50 0,1,30,31 * * * ?")
    public void MONEROUserPowerRatioDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        now.setHours(0);
        now.setMinutes(0);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        BigDecimal poolMhs = poolMapper.getPoolTodayTotalPower("monero", nowStr);
        List<UserPowerDto> userMhsList = poolMapper.getUserTodayTotalPower("monero", nowStr);
        HashMap<String,BigDecimal> map = new HashMap<>();
        userMhsList.stream().forEach(e ->{
            map.put(e.getUser(),e.getMhs().divide(poolMhs,8,BigDecimal.ROUND_HALF_UP));
        });

        if(map.size() >0){
            redisService.deleteObject("NEXAUserPowerRatio");
            redisService.setCacheMap("NEXAUserPowerRatio",map);
        }

    }



    @Scheduled(cron = "30 3 0/1 * * ?")
    //@Scheduled(cron = "0 0/2 * * * ?")
    public void MONEROLuckyDataToDB(){
        if(!enable){
            return;
        }
        log.info("MONERO 幸运值---定时任务开始");
        LuckDto dto = new LuckDto();
        Date end =  DateUtils.parseDate(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS));
        //幸运值 = 矿池实际报块/矿池理论报块
        //矿池实际报块 = distribution数据库查询表名为 币名_blkreportprofitv2
        //矿池理论报块 =  (矿池过去N段时间的平均算力 / 全网过去N段时间平均算力) * 全网过去N段时间实际报块
        Date start3d = DateUtils.addDays(end,-3);
        Date start7d = DateUtils.addDays(end,-7);
        Date start30d = DateUtils.addDays(end,-30);
        Date start90d = DateUtils.addDays(end,-90);

        //获取全网实际90天内的报块数(v2)
        List<BlockInfoDto> blockPerDays = poolMapper.selectNetBlock("monero_net_block");
        boolean useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start3d);
        //获取3天内全网的实际报块数
        BlockTimeAndNumberDto blockData = blockDataContext.getBlockData("monero",start3d, end,blockPerDays, useAggregated);
        //3天矿池理论报块数
        BigDecimal throreticalBlocks = getTheoreticalBlocks("monero",PoolUnits.MONERO.gethRate(),start3d, end, blockData);
        //3天矿池实际报块数
        int actualBlocks = poolMapper.selectPoolBlock(start3d, end,"monero",3);
        log.info("monero 3天实际报块数{},理论报块数{},全网实际报块数{},开始时间{},结束时间{}",actualBlocks,throreticalBlocks,blockData.getHeight(),start3d,end);
        //3天幸运值
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck3d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //7天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start7d);

        blockData = blockDataContext.getBlockData("monero",start7d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("monero",PoolUnits.MONERO.gethRate(),start7d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start7d, end,"monero",7);
        log.info("monero 7天实际报块数{},理论报块数{}",actualBlocks,throreticalBlocks);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck7d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        //30天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start30d);

        blockData = blockDataContext.getBlockData("monero",start30d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("monero",PoolUnits.MONERO.gethRate(),start30d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start30d, end,"monero",30);
        log.info("monero 30天实际报块数{},理论报块数{}",actualBlocks,throreticalBlocks);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck30d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        //90天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start90d);

        blockData = blockDataContext.getBlockData("monero",start90d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("monero",PoolUnits.MONERO.gethRate(),start90d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start90d, end,"monero",90);
        log.info("monero 90天实际报块数{},理论报块数{}",actualBlocks,throreticalBlocks);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck90d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        redisService.deleteObject("MONEROLuck");
        redisService.setCacheObject("NMONEROLuck",dto);
        log.info("monero幸运值入库完成---幸运值3天：{},幸运值7天：{},幸运值30天：{},幸运值90天：{},",
                dto.getLuck3d(),dto.getLuck7d(),dto.getLuck30d(),dto.getLuck90d());
    }



    @Scheduled(cron = "0 1,3,5 0 * * ?")
    public void XtmDailyDataToDB(){
        if(!enable){
            return;
        }
        String nowStr = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD);
        Date now = DateUtils.parseDate( nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.SHA3X.getMhs() + "24h", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getDailyMinerDataList(Pools.SHA3X.getMhs()+"_realv2", nowStr);
            if(list.size() > 0){
                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.SHA3X.getFac());
                    }
                });
                list = filterList(list,now);
                //list.stream().forEach(e ->{
                //    e.setDate(DateUtils.addDays(e.getDate(),-1));
                //});
                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.SHA3X.getMhs() + "24h", getToDailyDBListByMinerDataList(list));
                //todo 统计矿池数据写入矿池数据库 $coin_pool_24h
                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.SHA3X.getPoolTable() + "_24h", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.SHA3X.getPoolTable() + "_24h", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    //写入数据到coin_users表中
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );

                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.SHA3X.getName() + "_users_24h", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.SHA3X.getName() + "_users_24h", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }
                });
                if(result){
                    System.out.println(DateUtils.dateTimeNow()+"XTM 每日存入数据成功");
                }else {
                    System.out.println(DateUtils.dateTimeNow()+"XTM 每日存入数据失败");

                }

            }else {
                CompletableFuture.runAsync(()->{
                    System.out.println("XTM 每日矿池定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.SHA3X.getMhs() + "24h", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getDailyMinerDataList(Pools.SHA3X.getMhs()+"_realv2", nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.SHA3X.getFac());
                                }
                            });

                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.SHA3X.getMhs() + "24h", getToDailyDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.SHA3X.getPoolTable() + "_24h", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.SHA3X.getPoolTable() + "_24h", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );

                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.SHA3X.getName() + "_users_24h", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.SHA3X.getName() + "_users_24h", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });


                        }else {
                            PoolPower poolPower  = new PoolPower();
                            poolPower.setDate(now);
                            poolPower.setMhs(BigDecimal.ZERO);
                            poolPower.setMiners(0);
                            poolPower.setOnline(0);
                            poolPower.setOffline(0);
                            boolean poolResult = poolMapper.insertPoolPower(Pools.SHA3X.getPoolTable() + "_24h", poolPower);
                            System.out.println("延时任务未查到 构造0数据入库,结果:"+poolPower);
                        }
                    }
                });
            }
        }
    }

    @Scheduled(cron = "50 0,1,30,31 * * * ?")
    public void XtmUserPowerRatioDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        now.setHours(0);
        now.setMinutes(0);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        BigDecimal poolMhs = poolMapper.getPoolTodayTotalPower("sha3x", nowStr);
        List<UserPowerDto> userMhsList = poolMapper.getUserTodayTotalPower("sha3x", nowStr);
        HashMap<String,BigDecimal> map = new HashMap<>();
        userMhsList.stream().forEach(e ->{
            map.put(e.getUser(),e.getMhs().divide(poolMhs,8,BigDecimal.ROUND_HALF_UP));
        });

        if(map.size() >0){
            redisService.deleteObject("sha3xUserPowerRatio");
            redisService.setCacheMap("sha3xUserPowerRatio",map);
        }

    }



    @Scheduled(cron = "30 3 0/1 * * ?")
    //@Scheduled(cron = "0 0/2 * * * ?")
    public void XtmLuckyDataToDB(){
        if(!enable){
            return;
        }
        log.info("sha3x 幸运值---定时任务开始");
        LuckDto dto = new LuckDto();
        Date end =  DateUtils.parseDate(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS));
        //幸运值 = 矿池实际报块/矿池理论报块
        //矿池实际报块 = distribution数据库查询表名为 币名_blkreportprofitv2
        //矿池理论报块 =  (矿池过去N段时间的平均算力 / 全网过去N段时间平均算力) * 全网过去N段时间实际报块
        Date start3d = DateUtils.addDays(end,-3);
        Date start7d = DateUtils.addDays(end,-7);
        Date start30d = DateUtils.addDays(end,-30);
        Date start90d = DateUtils.addDays(end,-90);

        //获取全网实际90天内的报块数(v2)
        List<BlockInfoDto> blockPerDays = poolMapper.selectNetBlock("sha3x_net_block");
        boolean useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start3d);
        //获取3天内全网的实际报块数
        BlockTimeAndNumberDto blockData = blockDataContext.getBlockData("sha3x",start3d, end,blockPerDays, useAggregated);
        //3天矿池理论报块数
        BigDecimal throreticalBlocks = getTheoreticalBlocks("sha3x",PoolUnits.SHA3X.gethRate(),start3d, end, blockData);
        //3天矿池实际报块数
        int actualBlocks = poolMapper.selectPoolBlock(start3d, end,"sha3x",3);
        log.info("sha3x 3天实际报块数{},理论报块数{},全网实际报块数{},开始时间{},结束时间{}",actualBlocks,throreticalBlocks,blockData.getHeight(),start3d,end);
        //3天幸运值
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck3d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }
        //7天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start7d);

        blockData = blockDataContext.getBlockData("sha3x",start7d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("sha3x",PoolUnits.SHA3X.gethRate(),start7d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start7d, end,"sha3x",7);
        log.info("sha3x 7天实际报块数{},理论报块数{}",actualBlocks,throreticalBlocks);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck7d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        //30天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start30d);

        blockData = blockDataContext.getBlockData("sha3x",start30d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("sha3x",PoolUnits.SHA3X.gethRate(),start30d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start30d, end,"sha3x",30);
        log.info("sha3x 30天实际报块数{},理论报块数{}",actualBlocks,throreticalBlocks);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck30d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        //90天幸运值
        useAggregated = blockPerDays.get(blockPerDays.size()-1).getDate().before(start90d);

        blockData = blockDataContext.getBlockData("sha3x",start90d, end,blockPerDays, useAggregated);
        throreticalBlocks= getTheoreticalBlocks("sha3x",PoolUnits.SHA3X.gethRate(),start90d, end, blockData);
        actualBlocks = poolMapper.selectPoolBlock(start90d, end,"sha3x",90);
        log.info("sha3x 90天实际报块数{},理论报块数{}",actualBlocks,throreticalBlocks);
        if(!BigDecimal.ZERO.equals(throreticalBlocks)){
            dto.setLuck90d(BigDecimal.valueOf(actualBlocks).multiply(BigDecimal.valueOf(100)).divide(throreticalBlocks,2, RoundingMode.HALF_UP).doubleValue());
        }

        redisService.deleteObject("SHA3XLuck");
        redisService.setCacheObject("SHA3XLuck",dto);
        log.info("sha3x 幸运值入库完成---幸运值3天：{},幸运值7天：{},幸运值30天：{},幸运值90天：{},",
                dto.getLuck3d(),dto.getLuck7d(),dto.getLuck30d(),dto.getLuck90d());
    }


    @Scheduled(cron = "20 1,3,10,31,33,40 * * * ?")
    public void Sha3x30mDataToDB(){
        //String nowStr = DateUtils.dateTimeNow("yyyy-MM-dd HH:mm:00");
        if(!enable){
            return;
        }
        Date now = new Date();
        int minute = (now.getMinutes() / 30) * 30;
        now.setMinutes( minute);
        now.setSeconds(0);
        String nowStr = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now);

        System.out.println("SHA3X 30分钟定时任务执行时间:"+now);
        System.out.println("格式化后的时间:"+nowStr);

        //检查二级表是否有当前时间数据
        int count = poolMapper.getLastDataTime(Pools.SHA3X.getMhs() + "30m", nowStr);

        if(count == 0) {
            List<MinerDataDto> list = poolMapper.getHourMinerDataList(Pools.SHA3X.getMhs()+"_realv2",nowStr);
            if(list.size() > 0){
                List<MinerDataDto> offlineList = new ArrayList<>();
                list.stream().forEach(e -> {
                    if(StringUtils.isNotNull(e.getMhs())){
                        e.setMhs(e.getMhs() * Pools.SHA3X.getFac());
                    }
                    if("offline".equals(e.getState())){
                        offlineList.add(e);
                    }
                });
                list = filterList(list,now);

                boolean result = poolMapper.batchInsertMhsDataToDB(Pools.SHA3X.getMhs() + "30m", getToHourDBListByMinerDataList(list));

                Map<Date, List<MinerDataDto>> map = list.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                map.forEach((date,dList) -> {
                    PoolPower poolPower  = new PoolPower();
                    //poolPower.setDate(date);
                    poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                    Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                    poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                    poolPower.setMiners(dList.size());
                    poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                    poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                    boolean poolResult = poolMapper.insertPoolPower(Pools.SHA3X.getPoolTable() + "_30m", poolPower);
                    int time =0;
                    while (!poolResult){
                        poolResult = poolMapper.insertPoolPower(Pools.SHA3X.getPoolTable() + "_30m", poolPower);
                        if (time > 5) {
                            break;
                        }
                        time ++;
                    }

                    System.out.println("构造写入user算力表数据");
                    Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                    List<MinerDataInsertDBDto> userList = new ArrayList<>();
                    userMap.forEach((user,uList)->{
                        MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                        uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                        uDto.setUser(user);
                        uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                        userList.add(uDto);
                    } );
                    System.out.println("user算力表入库数据条数："+userList.size());
                    boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.SHA3X.getName() + "_users_30m", userList);
                    int uTime =0;
                    while (!userResult){
                        userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.SHA3X.getName() + "_users_30m", userList);
                        if (uTime > 5) {
                            break;
                        }
                        uTime ++;
                    }

                });

                Map<String, List<MinerDataDto>> userMap = list.stream().collect(Collectors.groupingBy(MinerDataDto::getMiner));
                if (result) {
                    System.out.println(DateUtils.dateTimeNow() + "SHA3X 小时数据存入数据成功");
                } else {
                    System.out.println(DateUtils.dateTimeNow() + "SHA3X 小时数据存入数据失败");
                }

                if(offlineList.size() >0){
                    CompletableFuture.runAsync(()->{

                        //根据挖矿账户分组、统计离线矿机名单、离线矿机数

                        //对比redis中该挖矿账户上一次离线矿机数
                        //有redis数据 需要判断 上一次离线矿机数<本次矿机离线数 才执行通知 否则跳过
                        //无redis数据 说明是第一次 执行通知
                    });

                }

            }
            else{
                //重来一次！
                CompletableFuture.runAsync(()->{
                    System.out.println("SHA3X 30分钟定时任务执行失败 延时一分钟时间重新查询");
                    System.out.println("延迟后使用的查询时间:"+now);
                    System.out.println("延迟后 格式化后的时间:"+nowStr);

                    //检查二级表是否有当前时间数据
                    int newCount = poolMapper.getLastDataTime(Pools.SHA3X.getMhs() + "30m", nowStr);
                    if(newCount == 0){
                        List<MinerDataDto> newList = poolMapper.getHourMinerDataList(Pools.SHA3X.getMhs()+"_realv2",nowStr);
                        if(newList.size() > 0){

                            newList.stream().forEach(e -> {
                                if(StringUtils.isNotNull(e.getMhs())){
                                    e.setMhs(e.getMhs() * Pools.SHA3X.getFac());
                                }
                            });
                            newList = filterList(newList,now);

                            boolean newResult = poolMapper.batchInsertMhsDataToDB(Pools.SHA3X.getMhs() + "30m", getToHourDBListByMinerDataList(newList));

                            Map<Date, List<MinerDataDto>> map2 = newList.stream().collect(Collectors.groupingBy(MinerDataDto::getDate));
                            map2.forEach((date,dList) -> {
                                PoolPower poolPower  = new PoolPower();
                                //poolPower.setDate(date);
                                poolPower.setDateStr(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                Map<String, Long> stateCount = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getState, Collectors.counting()));
                                poolPower.setMhs(dList.stream().map(e -> BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().stripTrailingZeros());
                                poolPower.setMiners(dList.size());
                                poolPower.setOnline(Convert.toInt(stateCount.get("online"),0));
                                poolPower.setOffline(Convert.toInt(stateCount.get("offline"),0));

                                boolean poolResult2 = poolMapper.insertPoolPower(Pools.SHA3X.getPoolTable() + "_30m", poolPower);
                                int time =0;
                                while (!poolResult2){
                                    poolResult2 = poolMapper.insertPoolPower(Pools.SHA3X.getPoolTable() + "_30m", poolPower);
                                    if (time > 5) {
                                        break;
                                    }
                                    time ++;
                                }

                                System.out.println("延迟任务 构造写入user算力表数据");
                                Map<String, List<MinerDataDto>> userMap = dList.stream().collect(Collectors.groupingBy(MinerDataDto::getUser));
                                List<MinerDataInsertDBDto> userList = new ArrayList<>();
                                userMap.forEach((user,uList)->{
                                    MinerDataInsertDBDto uDto = new MinerDataInsertDBDto();
                                    uDto.setDate(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,date));
                                    uDto.setUser(user);
                                    uDto.setMhs(uList.stream().map(e->BigDecimal.valueOf(e.getMhs())).reduce(BigDecimal::add).get().doubleValue());
                                    userList.add(uDto);
                                } );
                                System.out.println("延迟任务 user算力表入库数据条数："+userList.size());
                                boolean userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.SHA3X.getName() + "_users_30m", userList);
                                int uTime =0;
                                while (!userResult){
                                    userResult = poolMapper.batchInsertUserMhsDateToDB(Pools.SHA3X.getName() + "_users_30m", userList);
                                    if (uTime > 5) {
                                        break;
                                    }
                                    uTime ++;
                                }
                            });
                            if (newResult) {
                                System.out.println(DateUtils.dateTimeNow() + "SHA3X 30m数据 延迟存入数据成功");
                            } else {
                                System.out.println(DateUtils.dateTimeNow() + "SHA3X 30m数据 延迟存入数据失败");

                            }

                        }
                    }
                });

            }
        }

    }

}
