Commit ef423c3a authored by Julian Zobel's avatar Julian Zobel
Browse files

Merge branch 'jz/merge-disasterPrio' into jz/master

parents c3680c6a e24ded46
......@@ -303,11 +303,15 @@ public abstract class AbstractFilter<M extends MetricValue<?>>
* @param blacklist
*/
public void setBlacklist(String blacklist) {
this.blacklist = blacklist.split(";");
this.blacklist = blacklist.split(";|;\\n");
for (String string : this.blacklist)
string = string.replaceAll("\\s+", "");
}
public void setWhitelist(String whitelist) {
this.whitelist = whitelist.split(";");
this.whitelist = whitelist.split(";|;\\n");
for (int i = 0; i < this.whitelist.length; i++)
this.whitelist[i] = this.whitelist[i].replaceAll("\\s+", "");
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.analyzer.metric.filter;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric.MetricValue;
/**
* calculates the delivery ratio, which is the percent of actual transferred
* messages. (1 - overhead). Uses the duplicate and message count metrics and
* merge them. Used metrics are in DELIVERY_RATIO_LIST and duplicate metric must
* end with "Dup".
*
* @author Simon Luser
* @version 1.0, 08.03.2017
*/
public class MergeDeliveryRatioFilter
extends AbstractFilter<MetricValue<Double>> {
@Override
public void onStop() {
// nothing to do
}
@Override
public String getName() {
return "DeliveryRatio";
}
@Override
protected void onInitialize(List<Metric<?>> incomingMetrics) {
// get the pairing metrics
Set<Metric<?>> duplicateMetrics = incomingMetrics.stream().filter(
m -> m.getName().endsWith("Dup") && !m.isOverallMetric())
.collect(Collectors.toSet());
Set<Metric<?>> nonDuplicateMetrics = incomingMetrics.stream().filter(
m -> !m.getName().endsWith("Dup") && !m.isOverallMetric())
.collect(Collectors.toSet());
// generate the matches and create derived metric
for (Metric<?> met : nonDuplicateMetrics) {
List<Metric<?>> matches = duplicateMetrics.stream()
.filter(m -> met.getName()
.startsWith(m.getName().substring(0,
m.getName().lastIndexOf("Dup"))))
.collect(Collectors.toList());
if (matches.size() > 1)
Monitor.log(MergeDeliveryRatioFilter.class, Level.ERROR,
"Config Error!");
else if (matches.size() == 1) {
matches.add(met);
createDerivedMetric(matches, false, met.getUnit(),
"Delivery Ratio", false);
}
}
}
@Override
protected String getNameForDerivedMetric(List<Metric<?>> inputs) {
String str = getName();
if (inputs.size() >= 1) {
str += "_";
String firstName = inputs.get(0).getName();
if (firstName.contains("Dup"))
str += firstName.substring(0, firstName.lastIndexOf("Dup"));
else
str += firstName;
}
return str;
}
@Override
protected MetricValue<Double> getDerivedMetricValueFor(
Metric<?> derivedMetric, List<Metric<?>> inputs, Host host) {
// separate the values
if (inputs.size() == 2) {
try {
MetricValue<?> duplicateVal = inputs.stream()
.filter(m -> m.getName().endsWith("Dup"))
.collect(Collectors.toList()).get(0)
.getPerHostMetric(host.getId());
MetricValue<?> receiveVal = inputs.stream()
.filter(m -> !m.getName().endsWith("Dup"))
.collect(Collectors.toList()).get(0)
.getPerHostMetric(host.getId());
if (duplicateVal == null || receiveVal == null) {
return null;
}
return new DeliveryRatioMetricValue(duplicateVal, receiveVal);
} catch (IndexOutOfBoundsException e) {
return null;
}
} else
return null;
}
/**
* calculates the delivery ratio.
*
* @author Simon Luser
* @version 1.0, 08.03.2017
*/
private class DeliveryRatioMetricValue implements MetricValue<Double> {
private MetricValue<?> duplicateVal, receiveVal;
private boolean valid;
public DeliveryRatioMetricValue(MetricValue<?> duplicateVal,
MetricValue<?> receiveVal) {
this.duplicateVal = duplicateVal;
this.receiveVal = receiveVal;
}
@Override
public Double getValue() {
Object oDup = duplicateVal.getValue();
Object oRec = receiveVal.getValue();
double nDup;
if (oDup instanceof Number) {
nDup = ((Number) oDup).doubleValue();
} else {
throw new AssertionError();
}
double nRec;
if (oRec instanceof Number) {
nRec = ((Number) oRec).doubleValue();
} else {
throw new AssertionError();
}
this.valid = duplicateVal.isValid() && receiveVal.isValid()
&& nRec > 0;
return 1 - nDup / nRec;
}
@Override
public boolean isValid() {
return valid;
}
}
}
......@@ -100,11 +100,15 @@ public abstract class AbstractOutput implements MetricOutput {
* @param blacklist
*/
public void setBlacklist(String blacklist) {
this.blacklist = blacklist.split(";");
this.blacklist = blacklist.split(";|;\\n");
for (int i = 0; i < this.blacklist.length; i++)
this.blacklist[i] = this.blacklist[i].replaceAll("\\s+", "");
}
public void setWhitelist(String whitelist) {
this.whitelist = whitelist.split(";");
this.whitelist = whitelist.split(";|;\\n");
for (int i = 0; i < this.whitelist.length; i++)
this.whitelist[i] = this.whitelist[i].replaceAll("\\s+", "");
}
}
......@@ -24,12 +24,14 @@ import java.util.LinkedList;
import java.util.List;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.topology.views.visualization.ui.DisasterMetricChartAdapter;
import de.tud.kom.p2psim.impl.topology.views.visualization.ui.MetricCDFAdapter;
import de.tud.kom.p2psim.impl.topology.views.visualization.ui.MetricChartAdapter;
import de.tud.kom.p2psim.impl.topology.views.visualization.ui.MetricPlotAdapter;
import de.tud.kom.p2psim.impl.topology.views.visualization.ui.PlottingView;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.MessageWithDisasterType.MessageDisasterType;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
......@@ -41,6 +43,13 @@ import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
public class MetricOutputLivePlot extends AbstractOutput implements
EventHandler {
/**
* appended in metric description to separate from normal metrics, these
* metrics have a {@link MessageDisasterType} to plot, which are visualized
* in only one graph.
*/
public static final String DRAW_ONCE = "_DRAW_ONCE_";
private List<MetricPlotAdapter> charts = new LinkedList<MetricPlotAdapter>();
protected int upperPercentile = -1;
......@@ -70,8 +79,28 @@ public class MetricOutputLivePlot extends AbstractOutput implements
if (pView == null) {
pView = VisualizationInjector.createPlottingView("Metrics");
}
MetricChartAdapter mca = new MetricChartAdapter(metric, pView,
lowerPercentile, upperPercentile, maxItemCount);
// extended by choosing disaster adapter, if it is a disaster metric
boolean isMessageDisasterMetric = false;
for (MessageDisasterType type : MessageDisasterType.values())
if (metric.getName().contains(DRAW_ONCE)
&& metric.getName().contains(type.name())) {
isMessageDisasterMetric = true;
break;
}
if (isMessageDisasterMetric)
continue;
MetricPlotAdapter mca;
if (metric.getName().contains(DRAW_ONCE))
mca = new DisasterMetricChartAdapter(metric, pView,
maxItemCount);
else
mca = new MetricChartAdapter(metric, pView, lowerPercentile,
upperPercentile, maxItemCount);
charts.add(mca);
if (enableCDF && !metric.isOverallMetric()) {
if (pViewCdf == null) {
......
......@@ -370,8 +370,6 @@ public class MaxPeerCountChurnGenerator
// Insanity Checks
assert startTime >= previousEndTime : "Start time for next fluctuation must be greater than previous end time.";
assert burstLength >= _minBurstLength : "The minimal length of the burst must be at least 1m.";
assert numberOfClients > 0 : "Number of nodes must be positive.";
assert numberOfClients <= maxNumberOfNodes : "Cannot configure more nodes than configured in configuration.";
......
......@@ -215,7 +215,7 @@ public class DefaultMonitor implements MonitorComponent, EventHandler,
analyzer.stop(output);
}
output.write("*******************************************************\n");
// output.close();
output.close();
} catch (IOException e) {
throw new AssertionError();
}
......
......@@ -383,7 +383,8 @@ public class DefaultConfigurator implements Configurator {
}
} else {
// component cannot be created and has not been registered
Monitor.log(DefaultConfigurator.class, Level.WARN,
if (!name.equals("Description"))
Monitor.log(DefaultConfigurator.class, Level.WARN,
"Skip element " + name);
}
return component;
......
......@@ -141,7 +141,7 @@ public class RangedTopologyView extends AbstractTopologyView<RangedLink> {
* @return max distance between hosts to still be able to communicate (ie.
* wireless range)
*/
protected double getRange() {
public double getRange() {
return range;
}
......
......@@ -40,7 +40,6 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
......@@ -386,64 +385,26 @@ public class VisualizationTopologyView extends JFrame
* @author Bjoern Richerzhagen
* @version 1.0, 19.03.2012
*/
protected class WorldPanel extends JLayeredPane {
public class WorldPanel extends JLayeredPane {
protected ConcurrentHashMap<INodeID, VisNodeInformation> nodeInformation = new ConcurrentHashMap<INodeID, VisNodeInformation>();
protected final static int PADDING = 16;
public final static int PADDING = 16;
protected final static int NODE_PAD = 2;
public final static int NODE_PAD = 2;
private static final long serialVersionUID = -3023020559483652110L;
public WorldPanel() {
this.setLayout(null);
this.setDoubleBuffered(true);
this.addMouseListener(new MouseAdapter() {
/**
* Stores the mouse position, if the mouse button is pressed
*/
@Override
public void mousePressed(MouseEvent e) {
boolean turnedSomeoneOff = false;
for (VisNodeInformation node : nodeInformation.values()) {
// Make it easier to turn things off.
if (node.clicked && node.position
.distance(e.getPoint()) < PADDING + 2) {
node.clicked = !node.clicked;
VisualizationInjector
.notifyInteractionListenersOnClick(
node.hostId, node.clicked);
turnedSomeoneOff = true;
}
}
if (!turnedSomeoneOff) {
// Turn sth on (limit to one node)
for (VisNodeInformation node : nodeInformation.values()) {
if (node.disableClickListener) {
continue;
}
if (!node.clicked && node.position
.distance(e.getPoint()) < PADDING) {
node.clicked = !node.clicked;
VisualizationInjector
.notifyInteractionListenersOnClick(
node.hostId, node.clicked);
break;
}
}
}
}
});
}
public void addTopologyComponent(TopologyComponent comp) {
if (!nodeInformation.containsKey(comp.getHost().getId())) {
VisNodeInformation tVis = new VisNodeInformation(comp);
comp.requestLocationUpdates(null, tVis);
nodeInformation.put(comp.getHost().getId(), tVis);
nodeInformation.putIfAbsent(comp.getHost().getId(), tVis);
}
}
......@@ -455,32 +416,8 @@ public class VisualizationTopologyView extends JFrame
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
paintNodes(g2);
super.paintComponent(g);
}
private void paintNodes(Graphics2D g2) {
for (VisNodeInformation node : nodeInformation.values()) {
if (node.clicked) {
g2.setColor(Color.MAGENTA);
g2.fillOval((int) node.position.getX() - PADDING,
(int) node.position.getY() - PADDING,
PADDING * 2 + 1, PADDING * 2 + 1);
} else {
if (showNodes) {
// Draw nodes
g2.setColor(Color.DARK_GRAY);
g2.fillOval((int) node.position.getX() - NODE_PAD,
(int) node.position.getY() - NODE_PAD,
NODE_PAD * 2 + 1, NODE_PAD * 2 + 1);
}
}
}
}
}
public void notifyInteractionListenersOnClick(long hostid,
......
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.views.visualization.ui;
import java.util.HashMap;
import java.util.Map.Entry;
import org.jfree.data.xy.YIntervalSeries;
import de.tud.kom.p2psim.impl.analyzer.metric.MetricAnalyzer;
import de.tudarmstadt.maki.simonstrator.api.MessageWithDisasterType.MessageDisasterType;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric.MetricUnit;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric.MetricValue;
public class DisasterMetricChartAdapter implements MetricPlotAdapter {
/** the overall metric */
private final Metric metric;
/** the average of all {@link MessageDisasterType} */
private MetricValue<Number> avg = null;
private YIntervalSeries avgSeries = null;
/** each type of {@link MessageDisasterType} */
private HashMap<MessageDisasterType, MetricValue<Number>> subMsgTypeValues;
private HashMap<YIntervalSeries, MetricValue<Number>> subMsgTypeSeries;
public DisasterMetricChartAdapter(Metric metric, PlottingView view,
int maxItems) {
this.metric = metric;
// fill subMsgTypeValues
if (metric.isOverallMetric()) {
MetricValue<?> mv = metric.getOverallMetric();
avg = (MetricValue<Number>) mv;
subMsgTypeValues = new HashMap<>();
for (MessageDisasterType type : MessageDisasterType.values()) {
Metric emergencyM = MetricAnalyzer
.getMetric(metric.getName() + type);
if (emergencyM != null && emergencyM.isOverallMetric())
subMsgTypeValues.put(type, emergencyM.getOverallMetric());
}
}
// fill series
if (avg != null) {
XYChart chart = view.createPlot(
metric.getName() + " -- " + metric.getDescription(),
"Average");
avgSeries = chart.getDataset().getSeries(0);
if (maxItems > 0)
avgSeries.setMaximumItemCount(maxItems);
subMsgTypeSeries = new HashMap<>();
for (Entry<MessageDisasterType, MetricValue<Number>> e : subMsgTypeValues
.entrySet()) {
YIntervalSeries tempSerie = new YIntervalSeries(e.getKey());
if (maxItems > 0)
tempSerie.setMaximumItemCount(maxItems);
chart.getDataset().addSeries(tempSerie);
subMsgTypeSeries.put(tempSerie, e.getValue());
}
}
}
@Override
public void refresh() {
double seconds = (double) Time.getCurrentTime() / (double) Time.SECOND;
if (avgSeries != null) {
double avgVal = scaledValue(avg);
if (avg.isValid())
avgSeries.add(seconds, avgVal, avgVal, avgVal);
}
for (Entry<YIntervalSeries, MetricValue<Number>> series : subMsgTypeSeries
.entrySet()) {
double tempVal = scaledValue(series.getValue());
if (series.getValue().isValid())
series.getKey().add(seconds, tempVal, tempVal, tempVal);
}
}
/**
* For {@link Time}.
*
* @param mv
* @return
*/
private double scaledValue(MetricValue<Number> mv) {
if (metric.getUnit() == MetricUnit.TIME) {
return mv.getValue().doubleValue() / Time.SECOND;
}
return mv.getValue().doubleValue();
}
}
......@@ -112,6 +112,9 @@ public class MetricChartAdapter implements MetricPlotAdapter {
+ metric.getDescription());
series = chart.getDataset().getSeries(0);
// add, otherwise re-range is not working
series.add(0, 0, 0, 0);
if (maxItems > 0) {
series.setMaximumItemCount(maxItems);
}
......@@ -159,8 +162,9 @@ public class MetricChartAdapter implements MetricPlotAdapter {
varDown = 0;
}
}
series.add(seconds, avgVal, Math.max(0, avgVal - varDown), avgVal
+ varUp);
if (avg.isValid())
series.add(seconds, avgVal, Math.max(0, avgVal - varDown), avgVal
+ varUp);
}
if (minSeries != null) {
double minV = scaledValue(min);
......
......@@ -26,6 +26,9 @@ import java.awt.Point;
import java.awt.Polygon;
import java.awt.geom.Point2D;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.util.Triple;
/**
* Helpers for your own visualization components
*
......@@ -76,4 +79,24 @@ public class VisHelper {
drawArrow(g2, from.getX(), from.getY(), to.getX(), to.getY(), thickness);
}
/**
* uses the start-/end position and the percentage and determines with
* vector addition the new position on the line between start and end
* according to the percentage of already traveled distance.
*
* @param messageBall
* @return the current position of the message.
*/
public static PositionVector determineNewMessageBallPosition(
Triple<PositionVector, PositionVector, Integer> messageBall) {
double distance = messageBall.getA().distanceTo(messageBall.getB());
PositionVector differenceVector = messageBall.getB()
.minus(messageBall.getA());
differenceVector.normalize();
differenceVector.multiplyScalar(
messageBall.getC().doubleValue() / 100d * distance);
PositionVector pos = messageBall.getA().clone();
pos.add(differenceVector);
return pos;
}
}
......@@ -121,6 +121,10 @@ public class LogDistancePropagationLossModel extends PropagationLossModel {
return exponent;
}
protected double getReferenceLoss() {
return referenceLoss;
}
/**
* The lamba and the referenceLoss is depending of the frequency and the
* referenceDistance. If one of this values changed, then should be updated
......
package de.tud.kom.p2psim.impl.topology.views.wifi.phy.propagation.loss;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/**
* A model suited for connections between antennas at heights of 0.5-3m. Defined
* in:
* <p>
* Konstantinou, K., Kang, S., & Tzaras, C. (2007). A measurement-based model for
* mobile-to-mobile UMTS links. IEEE Vehicular Technology Conference, 529–533.
* http://doi.org/10.1109/VETECS.2007.120
* <p>
* The model defines path loss for line of sight (LOS) and non light of sight (NLOS)
* propagation.
* <pre>
* PLOS = 4.62 + 20 * log10(4π/λ) - 2.24ht - 4.9hr + 29.6 * log10(d)
* PNLOS = 20 * log10(4π/λ) - 2 *hr + 40 * log10(d) + C
*
* C = 0 if dense urban (HB > 18m), -4 else (HB < 12m)
* </pre>
* <p>
* with λ the wavelength, HB average building height, ht and hr the height of
* the transmitting and receiving antenna above ground, d the distance.
* <p>
* The average path loss is estimated as <code>PL = α PLLOS + (1-α)PLNLOS</code>, where
* α is the probability that there is a LOS connection between transmitter and
* receiver.
*
* @author Tim Feuerbach
*/
public class SurreyPropagationLossModel extends LogDistancePropagationLossModel {
private double C = 0;
private double alpha = 0.098601797632;
private double transmitterHeight = 1.6;
private double receiverHeight = 1.6;
/**
* Distance below which the model will always return the TX power.
*/
private double minDistance = 0.5d;
@Override
public double getRxPowerDbm(double txPowerDbm, Location a, Location b) {
return getRxPowerDbm(txPowerDbm, a.distanceTo(b));
}
@Override
public double getRxPowerDbm(double txPowerDbm, double distance) {
if (distance < minDistance) return txPowerDbm;
double pLOS = 4.62 + getReferenceLoss() - 2.24 * transmitterHeight - 4.9 * receiverHeight + 29.6 *
Math.log10(distance);
double pNLOS = getReferenceLoss() - 2 * receiverHeight + 40 * Math.log10(distance) + C;
double loss = alpha * pLOS + (1 - alpha) * pNLOS;
return txPowerDbm - Math.max(0, loss);
}
@Override
public double getDistance(double txPowerDbm, double rxPowerDbm) {
double p = Math.abs(rxPowerDbm - txPowerDbm);
// TODO use less obscure formulation, this one was obtained from Wolfram Alpha by solving for d
return Math.exp((-285379588546205536L * alpha * C - 827600806783996032L * alpha *
receiverHeight - 639250278343500416L * alpha * transmitterHeight + 1318453699083469568L
* alpha + 285379588546205536L * C - 285379588546205536L * p - 570759177092411072L *
receiverHeight + 285379588546205536L * getReferenceLoss()) / (1288963317755749376L *
alpha - 4957551222137499648L));
}
public void setIsUrban(boolean isUrban) {
C = (isUrban) ? 0 : -4;
}
public void setLosProbability(double losProbability) {
this.alpha = losProbability;
}
public void setTransmitterHeight(double transmitterHeight) {
this.transmitterHeight = transmitterHeight;
}
public void setReceiverHeight(double receiverHeight) {
this.receiverHeight = receiverHeight;
}
}
......@@ -39,7 +39,7 @@ public abstract class CSVReader<T>
while (csv.ready()) {
String line = csv.readLine();
if (line.contains(SEP)) {
if (line != null && line.contains(SEP)) {
String[] parts = line.split(SEP);
T entry = parse(parts);
......
......@@ -40,6 +40,7 @@ import de.tud.kom.p2psim.impl.util.db.metric.MeasurementPairList;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementSingle;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementSpatial;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementStatistic;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementStatisticMsgType;
import de.tud.kom.p2psim.impl.util.db.metric.Metric;
import de.tud.kom.p2psim.impl.util.db.metric.MetricDescription;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
......@@ -148,6 +149,7 @@ public class DAO {
cfg.addAnnotatedClass(MeasurementSingle.class);
cfg.addAnnotatedClass(MeasurementSpatial.class);
cfg.addAnnotatedClass(MeasurementStatistic.class);
cfg.addAnnotatedClass(MeasurementStatisticMsgType.class);
cfg.addAnnotatedClass(Metric.class);
cfg.addAnnotatedClass(MetricDescription.class);
......
......@@ -34,9 +34,11 @@ import de.tud.kom.p2psim.impl.util.db.metric.MeasurementPairList;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementSingle;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementSpatial;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementStatistic;
import de.tud.kom.p2psim.impl.util.db.metric.MeasurementStatisticMsgType;
import de.tud.kom.p2psim.impl.util.db.metric.Metric;
import de.tud.kom.p2psim.impl.util.db.metric.MetricDescription;
import de.tud.kom.p2psim.impl.util.stats.StatisticComputation;
import de.tudarmstadt.maki.simonstrator.api.MessageWithDisasterType.MessageDisasterType;
/**
* This class provides methods to persist measurements in a database.
......@@ -229,7 +231,77 @@ public class MeasurementDAO extends DAO {
addToPersistQueue(measurement);
}
/**
* Stores a statistical description of a series of values for group of
* hosts.
*
* @param metricDesc
* The {@link MetricDescription} which describes the metric.
* @param groupName
* The host group
* @param time
* A time for the measurement in simulation time
* @param stats
* the {@link DescriptiveStatistics} object used as input
* @param observationDuration
* duration of this observation in simulation time
* @param describesWholeSimulation
* true, if this measurement is a description of the WHOLE
* simulation
* @param msgType
* the message type this statistic is for
*/
public static void storeGroupStatisticsMeasurement(
MetricDescription metricDesc, String groupName, long time,
DescriptiveStatistics stats, long observationDuration,
boolean describesWholeSimulation, MessageDisasterType msgType) {
Metric metric = MetricDAO.lookupStatisticsMetric(metricDesc);
GroupMetric groupMetric = GroupMetricDAO.lookupGroupMetric(metric,
groupName);
MeasurementStatisticMsgType measurement = new MeasurementStatisticMsgType(time, stats,
groupMetric, observationDuration, describesWholeSimulation,
msgType);
addToPersistQueue(measurement);
}
/**
* Stores a statistical description of a series of values for group of hosts
* and a given spatial coordinate.
*
* @param metricDesc
* The {@link MetricDescription} which describes the metric.
* @param groupName
* The host group
* @param time
* A time for the measurement in simulation time
* @param stats
* the {@link DescriptiveStatistics} object used as input
* @param observationDuration
* duration of this observation in simulation time
* @param describesWholeSimulation
* true, if this measurement is a description of the WHOLE
* simulation
* @param locationX
* x coordinate for spatial sampling
* @param locationY
* y coordinate for spatial sampling
* @param msgType
* the message type this statistic is for
*/
public static void storeSpatialGroupStatisticsMeasurement(
MetricDescription metricDesc, String groupName, long time,
DescriptiveStatistics stats, long observationDuration,
boolean describesWholeSimulation, int locationX, int locationY,
MessageDisasterType msgType) {
Metric metric = MetricDAO.lookupStatisticsMetric(metricDesc);
GroupMetric groupMetric = GroupMetricDAO.lookupGroupMetric(metric,
groupName);
MeasurementStatisticMsgType measurement = new MeasurementStatisticMsgType(time, stats,
groupMetric, observationDuration, describesWholeSimulation,
locationX, locationY, msgType);
addToPersistQueue(measurement);
}
/**
* Store a list-based measurement with a key (i.e., as a
* {@link MeasurementPairList}).
......
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.util.db.metric;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import de.tudarmstadt.maki.simonstrator.api.MessageWithDisasterType.MessageDisasterType;
/**
* adapted {@link MeasurementStatistic} with also stores the types
*
* @author Simon Luser
*/
@Entity
@Table(name = "measurements_statistics_msg", indexes = {
@Index(columnList = "id", name = "id") })
public class MeasurementStatisticMsgType implements GroupMetricBound {
/**
* The id of this table
*/
@Id
@GeneratedValue
private int id;
/**
* The simulation time for to this measurement in simulator time, that is,
* microseconds.
*/
@Column(nullable = true, name = "[time]")
private long time;
@Column(nullable = false, name = "[describesWholeSimulation]")
private boolean describesWholeSimulation;
/**
* The simulation time for to this measurement in simulator time, that is,
* microseconds.
*/
@Column(nullable = true, name = "[observationDuration]")
private long observationDuration;
/**
* The number of values
*/
@Column(nullable = true, name = "[values]")
private Double values;
@Column(nullable = true, name = "[std]")
private Double std;
@Column(nullable = true, name = "[sum]")
private Double sum;
@Column(nullable = true, name = "[sum2]")
private Double sum2;
/**
* The minimum of all values for this measurement
*/
@Column(nullable = true, name = "[min]")
private Double min;
/**
* The maximum of all values for this measurement
*/
@Column(nullable = true, name = "[max]")
private Double max;
@Column(nullable = true, name = "[mean]")
private Double mean;
@Column(nullable = true, name = "[median]")
private Double median;
@Column(nullable = true, name = "[perc25]")
private Double perc25;
@Column(nullable = true, name = "[perc75]")
private Double perc75;
@Column(nullable = true, name = "[perc97]")
private Double perc97; // 97,7
@Column(nullable = true, name = "[perc2]")
private Double perc2; // 2,3
@Column(nullable = true, name = "[perc95]")
private Double perc95; // 95
@Column(nullable = true, name = "[perc5]")
private Double perc5; // 5
@Column(nullable = true, name = "[locationX]")
private Integer locationX;
@Column(nullable = true, name = "[locationY]")
private Integer locationY;
@Column(nullable = true, name = "[isSpatial]")
private boolean isSpatial;
@Column(nullable = true, name = "[messageType]")
private String msgType;
/**
* Mapping to group metric
*/
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "groupMetricId")
GroupMetric groupMetric;
/**
* Creates a {@link Measurement}-Object using the provided
* {@link DescriptiveStatistics} object.
*
* @param time
* The simulation time for to this measurement as Date
* @param stats
* the {@link DescriptiveStatistics} object
* @param hostMetric
* The reference to the {@link HostMetric}-Object, which
* describes this metric. Is used for the mapping.
* @param observationDuration
* duration of the observation
* @param describesWholeSimulation
* true, if this measurement describes the whole simulation
*/
public MeasurementStatisticMsgType(long time, DescriptiveStatistics stats,
GroupMetric groupMetric, long observationDuration,
boolean describesWholeSimulation, MessageDisasterType msgType) {
this(time, stats, observationDuration, describesWholeSimulation,
msgType);
this.groupMetric = groupMetric;
}
/**
* Creates a {@link Measurement}-Object using the provided
* {@link DescriptiveStatistics} object, with spatial data attached.
*
* @param time
* The simulation time for to this measurement as Date
* @param stats
* the {@link DescriptiveStatistics} object
* @param hostMetric
* The reference to the {@link HostMetric}-Object, which
* describes this metric. Is used for the mapping.
* @param observationDuration
* duration of the observation
* @param describesWholeSimulation
* true, if this measurement describes the whole simulation
* @param locationX
* x coordinate for spatial sampling
* @param locationY
* y coordinate for spatial sampling
*/
public MeasurementStatisticMsgType(long time, DescriptiveStatistics stats,
GroupMetric groupMetric, long observationDuration,
boolean describesWholeSimulation, int locationX, int locationY,
MessageDisasterType msgType) {
this(time, stats, observationDuration, describesWholeSimulation,
msgType);
this.groupMetric = groupMetric;
this.locationX = locationX;
this.locationY = locationY;
this.isSpatial = true;
}
/**
* Internal - write statistics
*
* @param time
* @param stats
* @param observationDuration
* duration covered by this measurement in simulation units
* @param msgType
*/
private MeasurementStatisticMsgType(long time, DescriptiveStatistics stats,
long observationDuration, boolean describesWholeSimulation,
MessageDisasterType msgType) {
super();
this.time = time;
this.observationDuration = observationDuration;
this.describesWholeSimulation = describesWholeSimulation;
this.values = checkForSpecialNumbers((double) stats.getN());
this.sum = checkForSpecialNumbers(stats.getSum());
this.sum2 = checkForSpecialNumbers(stats.getSumsq());
this.min = checkForSpecialNumbers(stats.getMin());
this.max = checkForSpecialNumbers(stats.getMax());
this.mean = checkForSpecialNumbers(stats.getMean());
this.median = checkForSpecialNumbers(stats.getPercentile(50));
this.perc2 = checkForSpecialNumbers(stats.getPercentile(2.3));
this.perc25 = checkForSpecialNumbers(stats.getPercentile(25));
this.perc75 = checkForSpecialNumbers(stats.getPercentile(75));
this.perc97 = checkForSpecialNumbers(stats.getPercentile(97.7));
this.perc5 = checkForSpecialNumbers(stats.getPercentile(5));
this.perc95 = checkForSpecialNumbers(stats.getPercentile(95));
this.std = checkForSpecialNumbers(stats.getStandardDeviation());
this.isSpatial = false;
if (msgType != null)
this.msgType = msgType.name();
}
/**
* Check for special numbers, like infinity or NaN. If the given value is
* equals this numbers then will be return null, otherwise will be returned
* the given value.
*
* @param value
* The value, which should be checked.
* @return The value or null, if it is a special number.
*/
private Double checkForSpecialNumbers(Double value) {
if (value == null)
return value;
if (value.equals(Double.NEGATIVE_INFINITY)
|| value.equals(Double.POSITIVE_INFINITY)
|| value.equals(Double.NaN)) {
return null;
} else {
return value;
}
}
@Override
public GroupMetric getGroupMetric() {
return groupMetric;
}
@Override
public void setGroupMetric(GroupMetric metric) {
this.groupMetric = metric;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment