Commit 2d730a71 authored by Clemens Krug's avatar Clemens Krug
Browse files

Merge remote-tracking branch 'remotes/origin/nr/monitoring-req-resp' into nr/resAlloc-clemens

parents ed0ccdaf 3174a624
/*
* 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.world;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.HashSet;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JMenu;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.impl.topology.views.FiveGTopologyView;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector.MouseClickListener;
import de.tud.kom.p2psim.impl.topology.views.fiveg.FiveGTopologyDatabase.Entry;
import de.tud.kom.p2psim.impl.topology.views.fiveg.ModelBasedSegmentDatabase;
import de.tud.kom.p2psim.impl.topology.views.fiveg.ModelBasedSegmentDatabase.ModelBasedEntry;
import de.tud.kom.p2psim.impl.topology.views.fiveg.utils.Direction;
import de.tud.kom.p2psim.impl.topology.views.fiveg.utils.ParameterType;
import de.tud.kom.p2psim.impl.topology.views.visualization.ui.VisualizationComponent;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
/**
* Visualization for the {@link FiveGTopologyView} using the
* {@link ModelBasedSegmentDatabase}.
*
* @author Marc Schiller, Nils Richerzhagen
* @version 1.0, Jul 7, 2017
*/
public class ModelFiveGVisualization extends JComponent
implements VisualizationComponent, ActionListener, MouseClickListener {
private static final ModelFiveGVisualization instance = new ModelFiveGVisualization();
private ModelBasedSegmentDatabase database;
private final JMenu menu = new JMenu("FiveG");
protected BufferedImage image;
protected volatile boolean needsRedraw = false;
private Direction selectedDirection = null;
private ParameterType selectedType = null;
private HashSet<JCheckBoxMenuItem> menuItems = new HashSet<>(6);
private Boolean showText = true;
private ModelFiveGVisualization() {
setBounds(0, 0, VisualizationInjector.getWorldX(),
VisualizationInjector.getWorldY());
setOpaque(true);
setVisible(true);
image = new BufferedImage(VisualizationInjector.getWorldX(),
VisualizationInjector.getWorldY(), BufferedImage.TYPE_INT_ARGB);
this.generateMenu();
VisualizationInjector.addMouseListener(this);
}
public static ModelFiveGVisualization getInstance() {
return instance;
}
public void setDatabase(ModelBasedSegmentDatabase database) {
this.database = database;
}
@Override
public String getDisplayName() {
return "FiveG";
}
@Override
public JComponent getComponent() {
return this;
}
@Override
public JMenu getCustomMenu() {
return menu;
}
@Override
public boolean isHidden() {
return false;
}
private void generateMenu() {
String[] entries1 = { "Bandwidth", "Latency", "Droprate" };
String[] entries2 = { "Download", "Upload" };
for (String entry1 : entries1) {
JMenu tmpMenu = new JMenu(entry1);
for (String entry2 : entries2) {
JCheckBoxMenuItem checkbox = new JCheckBoxMenuItem(entry2);
checkbox.setName(entry1 + " " + entry2);
checkbox.addActionListener(this);
tmpMenu.add(checkbox);
menuItems.add(checkbox);
}
menu.add(tmpMenu);
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (needsRedraw) {
redraw();
}
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(image, 0, 0, null);
}
protected void redraw() {
needsRedraw = false;
Graphics2D g2 = (Graphics2D) image.getGraphics();
Composite c = g2.getComposite();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
Rectangle2D.Double rect = new Rectangle2D.Double(0, 0,
VisualizationInjector.getWorldX(),
VisualizationInjector.getWorldY());
g2.fill(rect);
g2.setComposite(c);
try {
drawEntries(g2);
} catch (RuntimeException e) {
e.printStackTrace();
System.exit(0);
needsRedraw = true;
} finally {
// Schedule next redraw
new Thread(() -> {
try {
Thread.sleep(100);
needsRedraw = true;
} catch (InterruptedException e) {
// Ignore any error in Timer
}
}).start();
}
}
private void drawEntries(Graphics2D g2) {
// Iterate over grid coordinates
int stepSize = database.getGridSize();
boolean isUpload = selectedDirection.equals(Direction.UPLOAD) ? true
: false;
try {
// Loop through world
for (int x = 0; x < Binder.getComponent(Topology.class)
.getWorldDimensions().getX(); x += stepSize) {
for (int y = 0; y < Binder.getComponent(Topology.class)
.getWorldDimensions().getY(); y += stepSize) {
// Fetch entry
ModelBasedEntry entry = (ModelBasedEntry) database
.getEntryFor(database.getSegmentID(x, y), false);
// Skip cell if no entry is found
if (entry == null) {
continue;
}
int status = entry.getStatus(selectedType,
selectedDirection);
Color color = null;
if (entry.isAvailable() && status == 0) {
// Cell is ok => green
color = new Color(0, 128, 0, 40);
} else if (entry.isAvailable() && status == 1) {
// Cell is shortly before overload
color = new Color(255, 255, 0, 40);
} else if (!entry.isAvailable() || status == 2) {
// Cell is overloaded or unavailable
color = new Color(255, 0, 0, 100);
}
// Fill with color for given metric
g2.setColor(color);
g2.fillRect(VisualizationInjector.scaleValue(x),
VisualizationInjector.scaleValue(y),
VisualizationInjector.scaleValue(stepSize),
VisualizationInjector.scaleValue(stepSize));
// Draw border
// TODO: Draw red border if segment is overload if
// (entry.isAvailable() && !entry.isOverloaded()) {
if (entry.isAvailable()) {
g2.setColor(new Color(255, 0, 0, 10));
g2.setStroke(new BasicStroke(1));
} else {
g2.setColor(new Color(255, 0, 0, 100));
g2.setStroke(new BasicStroke(5));
}
g2.drawRect(VisualizationInjector.scaleValue(x),
VisualizationInjector.scaleValue(y),
VisualizationInjector.scaleValue(stepSize),
VisualizationInjector.scaleValue(stepSize));
// Write current values to cell
// Set text color for yellow to grey else to white
if (status == 1) {
g2.setColor(new Color(160, 160, 160, 255));
} else {
g2.setColor(new Color(255, 255, 255, 255));
}
if (showText) {
// Latency
if (entry.isAvailable() && !entry.isOverloaded()) {
g2.drawString(
"L: " + entry.getLatency(isUpload) + " ms",
VisualizationInjector.scaleValue(x + 10),
VisualizationInjector.scaleValue(y + 15));
} else {
g2.drawString("L: ∞ ms",
VisualizationInjector.scaleValue(x + 10),
VisualizationInjector.scaleValue(y + 15));
}
// Droprate
g2.drawString(
"D: " + (int) (entry
.getDropProbability(isUpload) * 100)
+ " %",
VisualizationInjector.scaleValue(x + 10),
VisualizationInjector.scaleValue(y + 35));
// Bandwidth
g2.drawString("B: " + entry.getBandwidth(isUpload)
+ " kBit/s",
VisualizationInjector.scaleValue(x + 10),
VisualizationInjector.scaleValue(y + 55));
// SegmentID
g2.drawString("S:" + entry.getSegmentID(),
VisualizationInjector.scaleValue(x + 10),
VisualizationInjector.scaleValue(y + 75));
// Current Hosts in Segment
g2.drawString("H:" + entry.getHostsInSegment(),
VisualizationInjector.scaleValue(x + 10),
VisualizationInjector.scaleValue(y + 95));
}
// Segment is overloaded
if (entry.isOverloaded()) {
g2.drawString("OVERLOAD",
VisualizationInjector.scaleValue(x + 20),
VisualizationInjector.scaleValue(y + 80));
}
// Host has been killed manually
if (!entry.isAvailable()) {
g2.drawString("!DEAD!",
VisualizationInjector.scaleValue(x + 30),
VisualizationInjector.scaleValue(y + 70));
}
}
}
} catch (ComponentNotAvailableException e) {
throw new AssertionError(
"The Topology should be Binded in the TopologyFactory.");
}
}
@Override
public void actionPerformed(ActionEvent e) {
JCheckBoxMenuItem source = (JCheckBoxMenuItem) e.getSource();
String sourceName = source.getName();
switch (sourceName) {
case "Bandwidth Upload":
selectedDirection = Direction.UPLOAD;
selectedType = ParameterType.BANDWIDTH;
break;
case "Bandwidth Download":
selectedDirection = Direction.DOWNLOAD;
selectedType = ParameterType.BANDWIDTH;
break;
case "Latency Upload":
selectedDirection = Direction.UPLOAD;
selectedType = ParameterType.LATENCY;
break;
case "Latency Download":
selectedDirection = Direction.DOWNLOAD;
selectedType = ParameterType.LATENCY;
break;
case "Droprate Upload":
selectedDirection = Direction.UPLOAD;
selectedType = ParameterType.DROPRATE;
break;
case "Droprate Download":
selectedDirection = Direction.DOWNLOAD;
selectedType = ParameterType.DROPRATE;
break;
default:
break;
}
needsRedraw = true;
for (JCheckBoxMenuItem item : menuItems) {
item.setSelected(false);
}
source.setSelected(true);
}
@Override
public void mouseClicked(int x, int y, int modifier) {
// 17 == Shift
if (modifier == 17) {
int segID = database.getSegmentID(
VisualizationInjector.originalValue(x),
VisualizationInjector.originalValue(y));
Entry entry = database.getEntryFor(segID, false);
entry.setAvailability(!entry.isAvailable());
needsRedraw = true;
}
// 18 == STRG || CMD
if (modifier == 18) {
showText = !showText;
needsRedraw = true;
}
}
}
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