package net.iponweb.disthene.reader.utils; import net.iponweb.disthene.reader.beans.TimeSeries; import java.util.ArrayList; import java.util.List; /** * @author Andrei Ivanov */ public class TimeSeriesUtils { public static boolean checkAlignment(List<TimeSeries> timeSeries) { if (timeSeries.size() == 0) return true; long from = timeSeries.get(0).getFrom(); long to = timeSeries.get(0).getTo(); long step = timeSeries.get(0).getStep(); int length = timeSeries.get(0).getValues().length; boolean result = true; for(TimeSeries ts : timeSeries) { if (ts.getFrom() != from || ts.getTo() != to || ts.getStep() != step || ts.getValues().length != length) result = false; } if (!result) { align(timeSeries); } return true; } private static void align(List<TimeSeries> timeSeries) { //todo: we assume that steps are multiples of each other. So, basically, we are selecting the largest step. Not sure if this needs be fixed //todo: we also assume that time series should start and end at even steps //todo: one more assumption: we are taking an intersection of resulting ranges int step = Integer.MIN_VALUE; for (TimeSeries ts : timeSeries) { step = Math.max(step, ts.getStep()); } long from = Long.MIN_VALUE; long to = Long.MAX_VALUE; for (TimeSeries ts : timeSeries) { long potentialFrom; if (ts.getFrom() % step == 0) { potentialFrom = ts.getFrom(); } else { potentialFrom = ts.getFrom() - ts.getFrom() % step + step; } from = Math.max(from, potentialFrom); long potentialTo; if (ts.getTo() % step == 0) { potentialTo = ts.getTo(); } else { potentialTo = ts.getTo() - ts.getTo() % step; } to = Math.min(to, potentialTo); } // we have a new step, let's consolidate each time series one by one for (TimeSeries ts : timeSeries) { consolidate(ts, step, from, to); } } // todo: pretty awkward - rework? // todo: think about different consolidation functions? // todo: assuming timeSeries.from <= from <= to <= timeSeries.to - has to be checked? // todo: from % step == 0 && to % step == 0 private static void consolidate(TimeSeries timeSeries, int step, long from, long to) { List<Double> consolidated = new ArrayList<>(); List<Double> buffer = new ArrayList<>(); int index = 0; while (timeSeries.getFrom() + index * timeSeries.getStep() <= to) { buffer.add(timeSeries.getValues()[index]); if ((timeSeries.getFrom() + index * timeSeries.getStep()) % step == 0) { consolidated.add(CollectionUtils.average(buffer)); buffer.clear(); } index++; } timeSeries.setFrom(from); timeSeries.setTo(to); timeSeries.setStep(step); timeSeries.setValues(consolidated.toArray(new Double[1])); } }