日拱一卒:时间统计图之坐标拾取

2023-02-01  本文已影响0人  Tinyspot

练习:统计当天时间段内的值
横坐标值是连续有间隔的时间段(暂定从 00:00 开始)
纵坐标是当前时间段的累加值

/**
 * 时间统计,按日期分割
 * 注:时间段是连续的,例:00:00  00:10  00:20  00:30 ...... 12:00
 */
public class TimeWindow {
    /**
     * 分钟数
     */
    private static final String MINUTES = "minutes";
    private static final String COUNT = "count";

    private List<Map<String, Object>> datas = new ArrayList<>();

    @Before
    public void before() {
        // 数据需有序
        Map<String, Object> map = new HashMap<String, Object>() {{
            put(MINUTES, "20");
            put(COUNT, 1);
        }};
        Map<String, Object> map2 = new HashMap<String, Object>() {{
            put(MINUTES, "32");
            put(COUNT, 2);
        }};
        Map<String, Object> map3 = new HashMap<String, Object>() {{
            put(MINUTES, "40");
            put(COUNT, 4);
        }};
        Map<String, Object> map4 = new HashMap<String, Object>() {{
            put(MINUTES, "48");
            put(COUNT, 8);
        }};
        datas.add(map);
        datas.add(map2);
        datas.add(map3);
        datas.add(map4);
    }

    @Test
    public void test() {
        List<CycleResult> cycleResultList = collectCoordinate(10);
        System.out.println(JSON.toJSONString(cycleResultList));
        // [{"count":0,"minutesTime":"00:00"},{"count":0,"minutesTime":"00:10"},{"count":1,"minutesTime":"00:20"},{"count":0,"minutesTime":"00:30"},{"count":6,"minutesTime":"00:40"},{"count":8,"minutesTime":"00:50"}]
    }

    /**
     * 坐标拾取
     * @param step 步长
     */
    public List<CycleResult> collectCoordinate(Integer step) {
        List<CycleResult> cycleResults = new ArrayList<>();

        // 初始值 00:00
        cycleResults.add(new CycleResult("00:00", 0L));

        TimeCycle timeCycle = TimeCycle.of(step);

        for (Map<String, Object> data : datas) {
            Long minutes = data.get(MINUTES) == null ? 0L : Long.parseLong(String.valueOf(data.get(MINUTES)));

            if (timeCycle.getTotalIndex() < minutes) {
                while (timeCycle.getTotalIndex() < minutes) {
                    // 时间段内无值时补0
                    dealData(timeCycle, 0L, cycleResults);
                }
            }

            if (timeCycle.getTotalIndex().equals(minutes)) {
                long count = data.get(COUNT) == null ? 0L : Long.parseLong(String.valueOf(data.get(COUNT)));
                dealData(timeCycle, count, cycleResults);
            }
        }

        // 补全最后一批数据
        if (timeCycle.hasData()) {
            CycleResult cycleResult = new CycleResult();
            cycleResult.setMinutesTime(timeCycle.calculateTime());
            cycleResult.setCount(timeCycle.getCycleCount());
            cycleResults.add(cycleResult);

            timeCycle.reset();
        }
        return cycleResults;
    }

    private void dealData(TimeCycle timeCycle, Long count, List<CycleResult> cycleResults) {
        if (cycleResults == null) {
            cycleResults = new ArrayList<>();
        }

        // 累加
        timeCycle.addCycleCount(count);

        // 达到步长值(cycleIndex == step),就记录一个 TimeCycle
        if (timeCycle.needRecord()) {
            CycleResult result = new CycleResult();
            result.setMinutesTime(timeCycle.calculateTime());
            result.setCount(timeCycle.getCycleCount());
            cycleResults.add(result);

            timeCycle.reset();
        } else {
            timeCycle.increaseCycleIndex();
            timeCycle.increaseTotalIndex();
        }
    }
}
@Data
public class TimeCycle {

    private Integer step;
    /**
     * 步长周期里的索引
     */
    private Integer cycleIndex = 0;
    private Long cycleCount = 0L;
    /**
     * 从0开始自增,一直与值做比较,直到最一个数
     */
    private Long totalIndex = 0L;

    private Calendar calendar;

    /**
     * 工厂方法
     * @param step 步长
     */
    public static TimeCycle of(Integer step) {
        TimeCycle timeCycle = new TimeCycle();
        timeCycle.setStep(step);
        return timeCycle;
    }

    public void increaseCycleIndex() {
        this.cycleIndex++;
    }

    public void increaseTotalIndex() {
        this.totalIndex++;
    }

    public void addCycleCount(Long currentCount) {
        if (currentCount == null) {
            return;
        }
        this.cycleCount += currentCount;
    }

    public Calendar getCalendar() {
        if (this.calendar == null) {
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            this.calendar = calendar;
        }
        return this.calendar;
    }

    /**
     * 转为时间格式 00:00
     */
    public String calculateTime() {
        return calculateTime(this.getRightStep());
    }

    private String calculateTime(Integer step) {
        Calendar calendar = this.getCalendar();
        calendar.add(Calendar.MINUTE, step);
        // HOUR_OF_DAY is used for the 24-hour clock.
        return padStart(calendar.get(Calendar.HOUR_OF_DAY)) + ":" + padStart(calendar.get(Calendar.MINUTE));
    }

    private String padStart(int time) {
        // 24小时制是两位数,不够左边补0
        if (time < 10) {
            return "0" + time;
        }
        return String.valueOf(time);
    }

    /**
     * Math.ceil() 向上取整
     * Math.floor() 向下取整
     * Math.round()  四舍五入取整
     */
    private Integer getLeftStep() {
        return (int) Math.floor(totalIndex / (step * 1.0D)) * step;
    }

    private Integer getRightStep() {
        return (int) Math.ceil(totalIndex / (step * 1.0D)) * step;
    }

    public boolean needRecord() {
        return Objects.equals(this.getCycleIndex(), this.getStep());
    }

    public boolean hasData() {
        return !(this.getCycleIndex() == 0 && this.getCycleCount() == 0L);
    }

    public void reset() {
        this.setCycleIndex(0);
        this.setCycleCount(0L);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
    }
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CycleResult {
    private String minutesTime;
    private Long count;
}

构建测试数据

public class TimeWindow {
    private static final String MINUTES = "minutes";
    private static final String COUNT = "count";

    private List<Map<String, Object>> datas = new ArrayList<>();

    @Before
    public void before() {
        datas = buildData(1, 100);
        System.out.println(datas);
    }

    private List<Map<String, Object>> buildData(int start, int end) {
        List<Map<String, Object>> list = new ArrayList<>();
        for (int i = start; i <= end; i++) {
            list.add(buildMap(i));
        }
        // Collections.sort(list, new Comparator<Map<String, Object>>() {
        //     @Override
        //     public int compare(Map<String, Object> o1, Map<String, Object> o2) {
        //         int number1 = (int) o1.get(MINUTES);
        //         int number2 = (int) o2.get(MINUTES);
        //         return number1 - number2;
        //     }
        // });
        return list;
    }

    private Map<String, Object> buildMap(int i) {
        Map<String, Object> maps = new HashMap<>();
        maps.put(COUNT, 1);
        maps.put(MINUTES, i);
        return maps;
    }
}
上一篇 下一篇

猜你喜欢

热点阅读