package org.spotter.ext.detection.utils; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.aim.api.measurement.dataset.Dataset; import org.aim.api.measurement.dataset.ParameterSelection; import org.aim.artifacts.records.ResponseTimeRecord; import org.lpe.common.util.NumericPairList; import org.spotter.core.detection.AbstractDetectionController; /** * Contains utility functions for analysis of measurement data. * * @author Alexander Wert * */ public final class Utils { private Utils() { } /** * Creates a list of timestamp response time pairs from a response time * dataset. * * @param rtDataSet * dataset to read from * @return list of timestamp response time pairs */ public static NumericPairList<Long, Double> toTimestampRTPairs(Dataset rtDataSet) { NumericPairList<Long, Double> responseTimeSeries = new NumericPairList<>(); for (ResponseTimeRecord rtRecord : rtDataSet.getRecords(ResponseTimeRecord.class)) { responseTimeSeries.add(rtRecord.getTimeStamp(), (double) rtRecord.getResponseTime()); } return responseTimeSeries; } /** * Creates a list of user response time pairs from a response time dataset. * * @param rtDataSet * dataset to read from * @return list of user response time pairs */ public static NumericPairList<Integer, Double> toUserRTPairs(Dataset rtDataSet) { NumericPairList<Integer, Double> responseTimeSeries = new NumericPairList<>(); List<Integer> users = new ArrayList<>(rtDataSet.getValueSet(AbstractDetectionController.NUMBER_OF_USERS_KEY, Integer.class)); Collections.sort(users); for (Integer numUsers : users) { List<Long> respTimes = ParameterSelection.newSelection() .select(AbstractDetectionController.NUMBER_OF_USERS_KEY, numUsers).applyTo(rtDataSet) .getValues(ResponseTimeRecord.PAR_RESPONSE_TIME, Long.class); for (Long val : respTimes) { responseTimeSeries.add(numUsers, (double) val); } } return responseTimeSeries; } /** * Calculates the mean value for the given window of a series. * * @param pairs * list of pairs * @param windowCenter * index of the window center * @param windowSize * window size * @return mean value */ public static double calculateWindowAverage(NumericPairList<Long, Double> pairs, int windowCenter, int windowSize) { double mva = 0.0; int windowStart = Math.max(windowCenter - (windowSize / 2), 0); int windowEnd = Math.min(windowCenter + (windowSize / 2), pairs.size() - 1); for (int j = windowStart; j <= windowEnd; j++) { mva += pairs.get(j).getValue(); } mva = mva / (double) (windowEnd - windowStart + 1); return mva; } /** * Calculates the percentile value for the given window of a series. * * @param pairs * list of pairs * @param percentile * percentile of interest * @param windowCenter * index of the window center * @param windowSize * window size * @return mean value */ public static double calculateWindowPercentile(NumericPairList<Long, Double> pairs, double percentile, int windowCenter, int windowSize) { int windowStart = Math.max(windowCenter - (windowSize / 2), 0); int windowEnd = Math.min(windowCenter + (windowSize / 2), pairs.size() - 1); int actualWindowSize = (windowEnd - windowStart) + 1; int indexPercentile = (int) Math.floor(((double) actualWindowSize) * percentile); List<Double> tmpList = new ArrayList<>(actualWindowSize); for (int j = windowStart; j <= windowEnd; j++) { tmpList.add(pairs.get(j).getValue()); } Collections.sort(tmpList); return tmpList.get(indexPercentile); } public static long meanInterRequestTime(NumericPairList<Long, Double> responsetimeSeries) { long diffSum = 0L; long prevTimestamp = -1; for (Long ts : responsetimeSeries.getKeyList()) { if (prevTimestamp >= 0L) { diffSum += ts - prevTimestamp; } prevTimestamp = ts; } return diffSum / (long) (responsetimeSeries.size() - 1); } }