/******************************************************************************* * Copyright 2015 alladin-IT GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package at.alladin.rmbt.shared.model; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import at.alladin.rmbt.shared.smoothing.Smoothable; import com.google.gson.annotations.SerializedName; public class SpeedItems { public static class SpeedItem implements Comparable<SpeedItem>, Smoothable { @SerializedName("t") protected long time; @SerializedName("b") protected long bytes; public SpeedItem() { } public SpeedItem(long time, long bytes) { this.time = time; this.bytes = bytes; } public long getTime() { return time; } public void setTime(long time) { this.time = time; } public long getBytes() { return bytes; } public void setBytes(long bytes) { this.bytes = bytes; } @Override public double getXValue() { return getTime(); } @Override public double getYValue() { return getBytes(); } @Override public int compareTo(SpeedItem o) { if (o == null) return -1; return Long.compare(time, o.time); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("SpeedItem [time=").append(time).append(", bytes=").append(bytes).append("]"); return builder.toString(); } } protected Map<Integer, List<SpeedItem>> download; protected Map<Integer, List<SpeedItem>> upload; protected static Map<Integer, List<SpeedItem>> addSpeedItem(SpeedItem si, int thread, Map<Integer, List<SpeedItem>> target) { if (target == null) target = new HashMap<>(); List<SpeedItem> speedThread = target.get(thread); if (speedThread == null) { speedThread = new ArrayList<>(); target.put(thread, speedThread); } speedThread.add(si); return target; } public void addSpeedItemDownload(SpeedItem si, int thread) { download = addSpeedItem(si, thread, download); } public void addSpeedItemUpload(SpeedItem si, int thread) { upload = addSpeedItem(si, thread, upload); } public Map<Integer, List<SpeedItem>> getDownload() { return download; } public Map<Integer, List<SpeedItem>> getUpload() { return upload; } protected static void sortItems(Map<Integer, List<SpeedItem>> items) { if (items == null) return; for (List<SpeedItem> list : items.values()) Collections.sort(list); } public void sortItems() { sortItems(download); sortItems(upload); } public List<SpeedItem> getAccumulatedSpeedItemsDownload() { return getAccumulatedSpeedItems(download); } public List<SpeedItem> getAccumulatedSpeedItemsUpload() { return getAccumulatedSpeedItems(upload); } public Map<String, Map<Integer, List<SpeedItem>>> getRawJSONData() { HashMap<String, Map<Integer, List<SpeedItem>>> ret = new HashMap<>(); sortItems(); //download ret.put("download", download); //upload ret.put("upload", upload); return ret; } protected static List<SpeedItem> getAccumulatedSpeedItems(Map<Integer, List<SpeedItem>> items) { sortItems(items); if (items == null) { return new ArrayList<>(); } int numItems = 0; for (List<SpeedItem> speedItems : items.values()) numItems += speedItems.size(); final long times[] = new long[numItems]; int i = 0; for (List<SpeedItem> speedItems : items.values()) { for (SpeedItem item : speedItems) times[i++] = item.time; if (i == times.length) break; } numItems = i; Arrays.sort(times); final long bytes[] = new long[times.length]; for (Map.Entry<Integer, List<SpeedItem>> entry : items.entrySet()) { i = 0; long lastTime = 0; long lastBytes = 0; for (SpeedItem si : entry.getValue()) { while (si.time > times[i]) // average times we don't have { bytes[i] += Math.round((double)((times[i] - lastTime) * si.bytes + (si.time - times[i]) * lastBytes) / (si.time - lastTime)); i++; } if (si.time == times[i]) bytes[i++] += si.bytes; lastTime = si.time; lastBytes = si.bytes; } while (i < numItems) bytes[i++] += lastBytes; // assume no transfer after last entry; might not be the case, but assuming otherwise could be worse } final List<SpeedItem> result = new ArrayList<>(); for (int j = 0; j < numItems; j++) result.add(new SpeedItem(times[j], bytes[j])); return result; } }