Commit cffdfb8d authored by Martin Hellwig's avatar Martin Hellwig Committed by Björn Richerzhagen
Browse files

First version of osm-data integration

parent c9a213fb
/*
* 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.movement.modularosm;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.Vector;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.movement.MovementListener;
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.api.topology.movement.local.LocalMovementStrategy;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.Topology;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.AttractionPoint;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.util.Either;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
/**
* Modular Movement Model uses different models/strategies to create a movement
* model. In this implementation, it has 4 different models/strategies.
* <p>
* M0: AttractionGenerator -> Generates the {@link AttractionPoint}s and place
* them on the map. The {@link AttractionPoint}s can be moved!
* <p>
* M1: A general {@link MovementModel} is not used, because we use static attraction points.
* <p>
* M2: The {@link TransitionStrategy}! It takes the Hosts, which should be moved
* around, but calculates only the assignment to the {@link AttractionPoint}s.
* It doesn't move the Hosts! It will be only assignment a new AttractionPoint!
*
* <p>
* M3: The {@link LocalMovementStrategy} is responsible for the movement of the
* Hosts. It moves the hosts to the assigned AttractionPoint, and if the
* AttractionPoint has moved, then will be followed. The
* {@link LocalMovementStrategy} will be called from the
* {@link ModularMovementModel} to do a Movement!
* <p>
* This class contains all four components and manage the data exchange.
* Additionally it contains an periodic operation, which handle the movement of
* all hosts. This mean, that it will be call the {@link LocalMovementStrategy}
* with the destination. Please take care, that the handling of the movement of
* the AttractionPoints will be handled by the movement model in M1! <br>
* Further it contains an offset for every Host, which will be added to the
* destination point (AttractionPoint), so that not all hosts, which are
* assigned to one {@link AttractionPoint}, lies on the same point.<br>
*
*
*
* @author Christoph Muenker
* @version 1.0, 02.07.2013
*/
public class ModularMovementModel implements MovementModel, EventHandler {
private final int EVENT_MOVE = 1;
private final int EVENT_INIT = 2;
protected PositionVector worldDimensions;
protected ITransitionStrategy transition;
protected IAttractionGenerator attractionGenerator;
protected LocalMovementStrategy localMovementStrategy;
private Set<MovementListener> movementListeners = new LinkedHashSet<MovementListener>();
private Set<MovementSupported> moveableHosts = new LinkedHashSet<MovementSupported>();
private Map<MovementSupported, PositionVector> offsetPosition = new LinkedHashMap<MovementSupported, PositionVector>();
private boolean initialized = false;
private long timeBetweenMoveOperation = Simulator.SECOND_UNIT;
private Random rand;
public ModularMovementModel() {
this.worldDimensions = Topology.getWorldDimension();
this.rand = Randoms.getRandom(ModularMovementModel.class);
// scheduling initalization!
Event.scheduleImmediately(this, null, EVENT_INIT);
}
/**
* This Method will be not called from the Components. So we call this
* manually!
*/
public void initialize() {
if (!initialized) {
VisualizationInjector.injectComponent("AttractionPoints", -1,
new ModularMovementModelViz(this), false);
checkConfiguration();
// setWayPointModel
localMovementStrategy.setObstacleModel(Topology.getTopology()
.getObstacleModel());
localMovementStrategy.setWaypointModel(Topology.getTopology()
.getWaypointModel());
List<AttractionPoint> attractionPoints = attractionGenerator.getAttractionPoints();
transition.setAttractionPoints(attractionPoints);
for (MovementSupported ms : moveableHosts) {
transition.addComponent(ms);
}
setTimeBetweenMoveOperations(timeBetweenMoveOperation);
// initial move
move();
initialized = true;
}
}
private void checkConfiguration() {
if (localMovementStrategy == null) {
throw new ConfigurationException(
"LocalMovementStrategy is missing in ModularMovementModel!");
}
if (transition == null) {
throw new ConfigurationException(
"TransitionStrategy is missing in ModularMovementModel!");
}
if (attractionGenerator == null) {
throw new ConfigurationException(
"AttractionGenerator is missing in ModularMovementModel!");
}
}
@Override
public void addComponent(MovementSupported comp) {
moveableHosts.add(comp);
offsetPosition.put(comp, randomOffsetVector());
}
@Override
public void addMovementListener(MovementListener listener) {
movementListeners.add(listener);
}
@Override
public void removeMovementListener(MovementListener listener) {
movementListeners.add(listener);
}
@Override
public void setTimeBetweenMoveOperations(long time) {
if (time > 0) {
this.timeBetweenMoveOperation = time;
} else {
throw new ConfigurationException(
"time is negative for the Move Operations");
}
}
private PositionVector randomOffsetVector() {
double x = rand.nextGaussian() * 6;
double y = rand.nextGaussian() * 6;
return new PositionVector(x, y);
}
protected void move() {
Map<MovementSupported, AttractionPoint> assigns = transition
.getAssignments();
for (Entry<MovementSupported, AttractionPoint> entry : assigns
.entrySet()) {
MovementSupported ms = entry.getKey();
PositionVector attractionCenter = entry.getValue()
.getRealPosition();
PositionVector destination = new PositionVector(attractionCenter);
destination.add(offsetPosition.get(ms));
doLocalMovement(ms, destination);
}
Event.scheduleWithDelay(timeBetweenMoveOperation, this, null,
EVENT_MOVE);
notifyRoundEnd();
}
/**
*
* Ask the local movement strategy for the next position. It may return the
* next position or a boolean with true to notify the movement model that it
* can't get any closer to the current way point.
*
* @param ms
* @param destination
*/
private void doLocalMovement(MovementSupported ms,
PositionVector destination) {
Either<PositionVector, Boolean> either = localMovementStrategy
.nextPosition(ms, destination);
if (either.hasLeft()) {
ms.getRealPosition().replace(either.getLeft());
notifyPositionChange(ms);
}
}
/**
* Notify Listeners
*/
protected void notifyRoundEnd() {
for (MovementListener listener : movementListeners) {
listener.afterComponentsMoved();
}
}
protected void notifyPositionChange(MovementSupported comp) {
for (MovementListener listener : movementListeners) {
listener.afterComponentMoved(comp);
}
comp.positionChanged();
}
public void setIAttractionGenerator(IAttractionGenerator attractionGenerator) {
this.attractionGenerator = attractionGenerator;
}
public void setLocalMovementStrategy(
LocalMovementStrategy localMovementStrategy) {
this.localMovementStrategy = localMovementStrategy;
}
public void setITransitionStrategy(ITransitionStrategy transition) {
this.transition = transition;
}
@Override
public void eventOccurred(Object content, int type) {
if (type == EVENT_INIT) {
initialize();
} else if (type == EVENT_MOVE) {
move();
}
}
/**
* Only for visualization!
*
* @return
*/
protected List<AttractionPoint> getAttractionPoints() {
return attractionGenerator.getAttractionPoints();
//return new Vector<AttractionPoint>(transition.getAssignments().values());
}
}
/*
* Copyright (c) 2005-2015 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.movement.modularosm;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.AttractionPoint;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
/**
* Visualization Component of the Attraction Points in the Modular Movement Model.
*
*
* @author Martin Hellwig
* @version 1.0, 02.07.2015
*/
public class ModularMovementModelViz extends JComponent {
private ModularMovementModel movementModel;
public ModularMovementModelViz(ModularMovementModel model) {
setBounds(0, 0, VisualizationInjector.WORLD_X,
VisualizationInjector.WORLD_Y);
setOpaque(true);
setVisible(true);
this.movementModel = model;
}
@Override
public void paint(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (AttractionPoint aPoint : movementModel.getAttractionPoints()) {
Point point = aPoint.getRealPosition().asPoint();
// draw border
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(1f));
g2.drawOval(point.x - 15, point.y - 15, 30, 30);
g2.drawString(aPoint.getName(), point.x - 15, point.y - 15);
//System.out.println(movementModel.getAttractionPoints().size() + ";" + aPoint.getRealPosition().toString() + ";" + aPoint.getName());
g2.setColor(new Color(0.2f, 0.8f, 0.2f, 0.6f));
g2.fillOval(point.x - 15, point.y - 15, 30, 30);
}
}
}
/*
* Copyright (c) 2005-2015 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.movement.modularosm.attraction;
import java.util.Random;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
/**
* This is the implementation of a AttractionPoint. This type of {@link AttractionPoint} has not the
* ability to be moved. Its data come from osm-POIs, which are static locations
*
* @author Martin Hellwig
* @version 1.0, 02.07.2015
*/
public class AttractionPoint {
protected static Random rnd = Randoms.getRandom(AttractionPoint.class);
private PositionVector posVec;
private String name;
public AttractionPoint(PositionVector posVec, String name) {
this.posVec = posVec;
this.name = name;
}
public PositionVector getRealPosition() {
return posVec;
}
public String getName() {
return name;
}
}
/*
* 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.movement.modularosm.attraction;
import java.util.List;
/**
* This is the interface for the generator of the {@link AttractionPoint}s. It
* gets the set number of AttractionPoints back. This mean, it will be generate
* them and set the Position of them.
*
* @author Christoph Muenker
* @version 1.0, 02.07.2013
*/
public interface IAttractionGenerator {
public void setNumberOfAttractionPoints(int maxNumberOfAttractionPoints);
public List<AttractionPoint> getAttractionPoints();
}
/*
* 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.movement.modularosm.attraction;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.Topology;
/**
* Generates attraction points out of real data from osm
* The maximal number of attraction points can be set
*
* @author Martin Hellwig
* @version 1.0, 02.07.2015
*/
public class JSONAttractionGenerator implements IAttractionGenerator {
private PositionVector worldDimensions;
private List<AttractionPoint> attractionPoints;
private int maxNumberOfAttractionPoints;
private String placementJsonFile;
private double latLeft; //Values from -90 to 90; always smaller than latRight
private double latRight; //Values from -90 to 90
private double lonLeft; //Values from -180 to 180; Always smaller than lonRight
private double lonRight; //Values from -180 to 180
/**
*
* @param file
*/
public JSONAttractionGenerator() {
this.worldDimensions = Topology.getWorldDimension();
}
/**
* Projects the gps coordinates in the given gps window to the world-coordinates given in world-dimensions
* @param lat
* @param lon
* @return The projected position in world-dimensions
*/
private PositionVector transformGPSWindowToOwnWorld(double lat, double lon) {
double x = worldDimensions.getX() * (lon - lonLeft)/(lonRight - lonLeft);
double y = worldDimensions.getY() * (lat - latLeft)/(latRight - latLeft);
return new PositionVector(x, y);
}
@Override
public void setNumberOfAttractionPoints(int numberOfAttractionPoints) {
this.maxNumberOfAttractionPoints = numberOfAttractionPoints;
}
@Override
public List<AttractionPoint> getAttractionPoints() {
attractionPoints = new LinkedList<AttractionPoint>();
if(attractionPoints.size() == 0) {
String poiString = "";
JSONArray allPOI = null;
FileInputStream inputStream;
try {
inputStream = new FileInputStream(placementJsonFile);
poiString = IOUtils.toString(inputStream);
JSONObject poiData = new JSONObject(poiString);
allPOI = poiData.getJSONArray("elements");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
if(allPOI != null) {
for(int i = 0; i < allPOI.length(); i++) {
try {
String barname = allPOI.getJSONObject(i).getJSONObject("tags").getString("name");
double lat = allPOI.getJSONObject(i).getDouble("lat");
double lon = allPOI.getJSONObject(i).getDouble("lon");
attractionPoints.add(new AttractionPoint(transformGPSWindowToOwnWorld(lat, lon), barname));
}
catch (JSONException e) {
//This bar had no name defined, so there was an error. Not so bad
}
}
}
}
System.out.println(attractionPoints.size());
if(maxNumberOfAttractionPoints == 0) maxNumberOfAttractionPoints = Integer.MAX_VALUE;
List<AttractionPoint> result = new LinkedList<AttractionPoint>();
for (int i = 0; (i < attractionPoints.size() && i < maxNumberOfAttractionPoints); i++) {
result.add(attractionPoints.get(i));
}
return result;
}
public void setPlacementJsonFile(String placementJsonFile) {
this.placementJsonFile = placementJsonFile;
}
public void setLatLeft(double latLeft) {
this.latLeft = latLeft;
}
public void setLatRight(double latRight) {
this.latRight = latRight;
}
public void setLonLeft(double lonLeft) {
this.lonLeft = lonLeft;
}
public void setLonRight(double lonRight) {
this.lonRight = lonRight;
}
}
/*
* 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.movement.modularosm.transition;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.common.SimHostComponent;
import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.CsvMovement;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
/**
* A {@link TransitionStrategy} for a case in which nodes (
* {@link MovementSupported}) are affiliated to an {@link AttractionPoint} only
* in the beginning. No further transition will take place.
*
* @author Nils Richerzhagen
* @version 1.0, 04.08.2014
*/
public class FixedAssignmentStrategy implements ITransitionStrategy {
private Random rnd;
private List<MovementSupported> comps = new LinkedList<MovementSupported>();
private List<AttractionPoint> aPoints = new LinkedList<AttractionPoint>();
private Map<MovementSupported, AttractionPoint> assignments = new LinkedHashMap<MovementSupported, AttractionPoint>();
private Map<MovementSupported, SimHost> mappingMSHost = new LinkedHashMap<MovementSupported, SimHost>();
private Map<SimHost, MovementSupported> mappingHostMS = new LinkedHashMap<SimHost, MovementSupported>();
private Map<String, AttractionPoint> mappingGroupIdAP = new LinkedHashMap<String, AttractionPoint>();
private Map<AttractionPoint, String> mappingAPGroupId = new LinkedHashMap<AttractionPoint, String>();
public FixedAssignmentStrategy() {
rnd = Randoms.getRandom(FixedAssignmentStrategy.class);
}
@Override
public Map<MovementSupported, AttractionPoint> getAssignments() {
return new HashMap<MovementSupported, AttractionPoint>(assignments);
}
@Override
public void setAttractionPoints(List<AttractionPoint> attractionPoints) {
aPoints.addAll(attractionPoints);
}
@Override
public void addComponent(MovementSupported ms) {
comps.add(ms);
mappingHost(ms);
// No assignments been done before.
if (assignments.isEmpty()) {
AttractionPoint aPoint = aPoints.iterator().next();
assignments.put(ms, aPoint);
mappingGroupId(ms, aPoint);
setStartPosition(ms, aPoint.getRealPosition());
}
// GroupId is not mapped.
else if (!mappingGroupIdAP.containsKey(mappingMSHost.get(ms)
.getProperties().getGroupID())) {
for (AttractionPoint actAP : aPoints) {
if (!mappingAPGroupId.containsKey(actAP)) {
assignments.put(ms, actAP);
mappingGroupId(ms, actAP);
setStartPosition(ms, actAP.getRealPosition());
break;
}
}
}
// GroupId is already mapped.
else if (mappingGroupIdAP.containsKey(mappingMSHost.get(ms)
.getProperties().getGroupID())) {
AttractionPoint aPoint = mappingGroupIdAP.get(mappingMSHost.get(ms)
.getProperties().getGroupID());
assignments.put(ms, aPoint);
setStartPosition(ms, aPoint.getRealPosition());
} else {
throw new Error("Should not happen.");
}
}
private void mappingHost(MovementSupported ms) {
SimHostComponent comp = (SimHostComponent) ms;
SimHost host = comp.getHost();
assert host != null;
mappingHostMS.put(host, ms);
mappingMSHost.put(ms, host);
}
private void mappingGroupId(MovementSupported ms, AttractionPoint AP) {
SimHostComponent comp = (SimHostComponent) ms;
SimHost host = comp.getHost();
assert host != null;
mappingAPGroupId.put(AP, mappingMSHost.get(ms).getProperties()
.getGroupID());
mappingGroupIdAP.put(
mappingMSHost.get(ms).getProperties().getGroupID(), AP);
}
private void setStartPosition(MovementSupported ms,
PositionVector aPointReferencePosition) {
double minJitter = 50.0;
double maxJitter = 100.0;
PositionVector nodePosition = ms.getRealPosition();
nodePosition.replace(aPointReferencePosition);
double xJitter = (rnd.nextDouble() * (maxJitter - minJitter)) + minJitter;
double yJitter = (rnd.nextDouble() * (maxJitter - minJitter)) + minJitter;
PositionVector jitterVector = new PositionVector(xJitter, yJitter);
nodePosition.add(jitterVector);
ms.positionChanged();
}
/**
* Used by the MobilityModel (M1) of the {@link ModularMovementModel} to get
* the groupId of the affiliated nodes to that {@link AttractionPoint}. Once
* the groupId is known nodes can be set <b>offline</b> or <b>online</b>.
*
* @param attractionPoint
* @return
*/
public String getGroupIdOfAttractionPoint(AttractionPoint attractionPoint) {
return mappingAPGroupId.get(attractionPoint);
}
}
/*
* 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.movement.modularosm.transition;
import java.util.List;
import java.util.Map;
import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.AttractionPoint;
/**
* This is the interface for the Transition Strategy.<br>
*
* @author Martin Hellwig
* @version 1.0, 03.07.2015
*/
public interface ITransitionStrategy {
/**
* Returns the assignments of the MovementSupported Objects to the
* AttractionPoints
*
* @return
*/
public Map<MovementSupported, AttractionPoint> getAssignments();
/**
* Should be called first, to add the Attraction Points for the assignment!
*
* @param attractionPoints
*/
public void setAttractionPoints(List<AttractionPoint> attractionPoints);
/**
* Add the {@link MovementSupported} object and assign the MS to an
* {@link AttractionPoint}.
*
* @param ms
*/
public void addComponent(MovementSupported ms);
}
/*
* 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.movement.modularosm.transition;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.Vector;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.common.SimHostComponent;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.api.topology.social.SocialView;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.Topology;
import de.tud.kom.p2psim.impl.topology.movement.modular.attraction.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
/**
* This is a {@link TransitionStrategy} for the Social Case. It will be try to
* build groups based on the {@link SocialView} information. For this, it tries
* to assignment the given {@link MovementSupported} objects to the given
* {@link AttractionPoint}s. For the {@link SocialView}, it is required a
* {@link #socialId}, to find the right {@link SocialView}.
*
* <br>
*
* The Strategy has the parameter of {@link #socialFactor},
* {@link #minPauseTime} and {@link #maxPauseTime}. The socialFactor should be a
* value between 0 and 1. It gives the probability for a social based transition
* or the transition to a random {@link AttractionPoint}. If the social based
* transition is selected, then will be used a scoring to find the right
* {@link AttractionPoint}. For that, it will be used only the AttractionPoints,
* of the hosts, which are in the same SocialCluster or are SocialNeighbors. For
* this AttractionPoints it will be find the highest scoring, which is to found
* in {@link #score(MovementSupported, AttractionPoint, List, List, List, List)}
* .
*
* <br>
*
* After the finding of the next {@link AttractionPoint}, it will be scheduled
* an Event, with a delay between min- and maxPauseTime. After this delay, it
* will be tried to assign a new {@link AttractionPoint} like the described
* above.
*
*
* @author Christoph Muenker
* @version 1.0, 02.07.2013
*/
public class SocialTransitionStrategy implements TransitionStrategy,
EventHandler {
private String socialId = null;
private SocialView socialView;
private List<MovementSupported> comps = new Vector<MovementSupported>();
private List<AttractionPoint> aPoints = new Vector<AttractionPoint>();
private Map<MovementSupported, AttractionPoint> assignments = new HashMap<MovementSupported, AttractionPoint>();
private Map<MovementSupported, Set<AttractionPoint>> favoritePlaces = new HashMap<MovementSupported, Set<AttractionPoint>>();
private Map<MovementSupported, SimHost> mapMsHost = new HashMap<MovementSupported, SimHost>();
private Map<SimHost, MovementSupported> mapHostMs = new HashMap<SimHost, MovementSupported>();
private double minPauseTime = Simulator.MINUTE_UNIT * 0.5;
private double maxPauseTime = Simulator.MINUTE_UNIT * 100;
private double socialFactor = 0.8;
private long numberOfFavoritePlaces = 4;
private Random rand;
private PositionVector worldDimension;
private boolean init = false;
public SocialTransitionStrategy() {
this.rand = Randoms.getRandom(SocialTransitionStrategy.class);
}
private void init() {
if (!init) {
if (socialId == null) {
throw new ConfigurationException(
"SocialId is not set, to find the needed SocialView!");
}
socialView = Topology.getTopology().getSocialView(socialId);
if (socialView == null) {
throw new ConfigurationException(
"Cannot find the right socialView. Is the socialId correct?");
}
if (minPauseTime > maxPauseTime) {
throw new ConfigurationException(
"MinPauseTime should be smaller then maxPauseTime.");
}
worldDimension = Topology.getWorldDimension();
init = true;
}
}
public void setSocialId(String socialId) {
this.socialId = socialId;
}
@Override
public Map<MovementSupported, AttractionPoint> getAssignments() {
return new HashMap<MovementSupported, AttractionPoint>(assignments);
}
@Override
public void setAttractionPoints(List<AttractionPoint> attractionPoints) {
init();
aPoints.addAll(attractionPoints);
}
@Override
public void addComponent(MovementSupported ms) {
comps.add(ms);
mappingHost(ms);
// assign the ms to an attractionPoint, which is near to the ms
// position.
// TODO: needed? We do Transition as next, and this will delete the
// assignment..
AttractionPoint nearest = aPoints.iterator().next();
for (AttractionPoint aPoint : aPoints) {
if (nearest.getRealPosition().getDistance(ms.getRealPosition()) > aPoint
.getRealPosition().getDistance(ms.getRealPosition())) {
nearest = aPoint;
}
}
assignments.put(ms, nearest);
assignFavoritePlaces(ms);
doTransition(ms);
}
public void doTransition(MovementSupported ms) {
List<AttractionPoint> apFavorites = getFavoritePlaces(ms);
List<AttractionPoint> apFriends = getFriendsPlaces(ms);
List<AttractionPoint> apClusters = getClusterPlaces(ms);
List<AttractionPoint> apRandom = getRandomPlaces(ms,
(int) Math.max(aPoints.size() * 0.2, 5));
AttractionPoint ap = null;
if (rand.nextDouble() < socialFactor) {
ap = findHighestScore(ms, apFavorites, apFriends, apClusters,
apRandom);
} else {
List<AttractionPoint> aps = new ArrayList<AttractionPoint>();
aps.addAll(apRandom);
aps.addAll(apFavorites);
ap = aps.get(rand.nextInt(apRandom.size()));
}
assignments.put(ms, ap);
Event.scheduleWithDelay(getPauseTime(), this, ms, 0);
}
private AttractionPoint findHighestScore(MovementSupported ms,
List<AttractionPoint> apFavorites, List<AttractionPoint> apFriends,
List<AttractionPoint> apClusters, List<AttractionPoint> apRandom) {
Set<AttractionPoint> aps = new HashSet<AttractionPoint>();
aps.addAll(apFavorites);
aps.addAll(apFriends);
aps.addAll(apClusters);
aps.addAll(apRandom);
double maxScore = 0;
AttractionPoint maxAp = null;
for (AttractionPoint ap : aps) {
double score = score(ms, ap, apFavorites, apFriends, apClusters,
apRandom);
// System.out.println(score);
if (score > maxScore) {
maxScore = score;
maxAp = ap;
}
}
return maxAp;
}
/**
* Score the given AttractionPoint for the given {@link MovementSupported}. <br>
* (clusterScore/#NodesInAp + friendsScore + 1/#NodesInAp) * socialFactor +
* (distanceScore + penalty) + (1-socialFactor) <br>
*
* clusterScore = 1 if one is in the same cluster in this AP<br>
* friendsScore = 1 if one friend is in the same AP<br>
* penalty = -1 if AP the actually AP is <br>
* distance = 1 - (distance / maxDistance)
*
* @param ms
* @param ap
* @param apFavorites
* @param apFriends
* @param apClusters
* @param apRandom
* @return
*/
private double score(MovementSupported ms, AttractionPoint ap,
List<AttractionPoint> apFavorites, List<AttractionPoint> apFriends,
List<AttractionPoint> apClusters, List<AttractionPoint> apRandom) {
double distance = ms.getRealPosition()
.getDistance(ap.getRealPosition());
double distanceScore = 1 - (distance / worldDimension.getLength());
double clusterScore = 0;
double friendsScore = 0;
if (apClusters.contains(ap)) {
if (occurence(ap, apClusters) > 3) {
// occurence give the number of other peers in this AP
clusterScore = 1.0 / (occurence(ap, apClusters) - 1);
} else {
clusterScore = 1.0;
}
}
if (apFriends.contains(ap)) {
if (occurence(ap, apFriends) > 3) {
// occurence give the number of other peers in this AP
friendsScore = 1.0 / (occurence(ap, apFriends) - 1);
} else {
friendsScore = 1.0;
}
}
// penalty for distance
double penalty = 0;
if (ap.equals(assignments.get(ms))) {
penalty = -1;
}
return (clusterScore / assignedToAp(ap) + friendsScore + 1.0 / assignedToAp(ap))
* socialFactor
+ (distanceScore + penalty) * (1 - socialFactor);
}
// counts the number of the AttractionPoint in the list
private int occurence(AttractionPoint ap, List<AttractionPoint> aps) {
int i = 0;
for (AttractionPoint a : aps) {
if (a.equals(ap)) {
i++;
}
}
return i;
}
private int assignedToAp(AttractionPoint ap) {
int i = 1;
for (Entry<MovementSupported, AttractionPoint> entry : assignments
.entrySet()) {
if (entry.getValue().equals(ap)) {
i++;
}
}
return i;
}
private List<AttractionPoint> getRandomPlaces(MovementSupported ms,
int number) {
Collections.shuffle(aPoints);
List<AttractionPoint> result = new Vector<AttractionPoint>();
Iterator<AttractionPoint> iAP = aPoints.iterator();
for (int i = 0; i < number && iAP.hasNext(); i++) {
result.add(iAP.next());
}
return result;
}
private List<AttractionPoint> getClusterPlaces(MovementSupported ms) {
List<AttractionPoint> result = new Vector<AttractionPoint>();
SimHost msHost = mapMsHost.get(ms);
for (SimHost host : socialView.getCluster(msHost)) {
MovementSupported temp = mapHostMs.get(host);
if (assignments.get(temp) != null) {
result.add(assignments.get(temp));
}
}
return result;
}
private List<AttractionPoint> getFriendsPlaces(MovementSupported ms) {
List<AttractionPoint> result = new Vector<AttractionPoint>();
SimHost msHost = mapMsHost.get(ms);
for (SimHost host : socialView.getNeighbors(msHost)) {
MovementSupported temp = mapHostMs.get(host);
if (assignments.get(temp) != null) {
result.add(assignments.get(temp));
}
}
return result;
}
private List<AttractionPoint> getFavoritePlaces(MovementSupported ms) {
return new Vector<AttractionPoint>(favoritePlaces.get(ms));
}
private AttractionPoint getRandomPlace(MovementSupported ms) {
Collections.shuffle(aPoints);
return aPoints.iterator().next();
}
private AttractionPoint getNearestPlace(MovementSupported ms,
List<AttractionPoint> aps) {
if (aps.isEmpty()) {
return null;
}
AttractionPoint nearest = aps.iterator().next();
for (AttractionPoint aPoint : aps) {
if (nearest.getRealPosition().getDistance(ms.getRealPosition()) > aPoint
.getRealPosition().getDistance(ms.getRealPosition())
&& !assignments.get(ms).equals(aPoint)) {
nearest = aPoint;
}
}
return nearest;
}
private AttractionPoint getNearestFavoritePlace(MovementSupported ms) {
Set<AttractionPoint> fps = favoritePlaces.get(ms);
AttractionPoint nearest = fps.iterator().next();
for (AttractionPoint aPoint : fps) {
if (nearest.getRealPosition().getDistance(ms.getRealPosition()) > aPoint
.getRealPosition().getDistance(ms.getRealPosition())
&& !assignments.get(ms).equals(aPoint)) {
nearest = aPoint;
}
}
return nearest;
}
private void assignFavoritePlaces(MovementSupported ms) {
Set<AttractionPoint> msFavoritePlaces = new HashSet<AttractionPoint>();
LinkedList<AttractionPoint> temp = new LinkedList<AttractionPoint>(
aPoints);
Collections.shuffle(temp, rand);
for (int i = 0; i < numberOfFavoritePlaces; i++) {
if (!temp.isEmpty()) {
msFavoritePlaces.add(temp.removeFirst());
}
}
favoritePlaces.put(ms, msFavoritePlaces);
}
private void mappingHost(MovementSupported ms) {
SimHostComponent comp = (SimHostComponent) ms;
SimHost host = comp.getHost();
assert host != null;
mapHostMs.put(host, ms);
mapMsHost.put(ms, host);
}
protected long getPauseTime() {
return (long) ((rand.nextDouble() * (maxPauseTime - minPauseTime)) + minPauseTime);
}
public void setMinPauseTime(long minPauseTime) {
if (minPauseTime < 0) {
throw new ConfigurationException(
"MinPauseTime should be bigger then 0!");
}
this.minPauseTime = minPauseTime;
}
public void setMaxPauseTime(long maxPauseTime) {
if (maxPauseTime < 0) {
throw new ConfigurationException(
"MaxPauseTime should be bigger then 0!");
}
this.maxPauseTime = maxPauseTime;
}
@Override
public void eventOccurred(Object se, int type) {
doTransition((MovementSupported) se);
}
public void setSocialFactor(double socialFactor) {
if (socialFactor < 0 || socialFactor > 1) {
throw new ConfigurationException(
"socialFactor should be between 0 and 1!");
}
this.socialFactor = socialFactor;
}
}
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