Commit 82c106d1 authored by Julian Zobel's avatar Julian Zobel
Browse files

Merge remote-tracking branch 'origin/jz/dev' into jz/dev-metrics

parents e5d67938 f70651e0
......@@ -158,10 +158,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
*/
localMovementStrategy
.setScaleFactor(timeBetweenMoveOperation / (double) Time.SECOND);
List<AttractionPoint> attractionPoints = attractionGenerator
.getAttractionPoints();
transition.setAttractionPoints(attractionPoints);
transition.addAttractionAssignmentListener(this);
// This adds the mobile hosts (smartphones/users) to the transition
......@@ -197,13 +194,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
public AttractionPoint getTargetLocation(SimLocationActuator actuator) {
return transition.getAssignment(actuator);
}
@Override
public Set<AttractionPoint> getAllAttractionPoints()
throws UnsupportedOperationException {
return transition.getAllAttractionPoints();
}
private void checkConfiguration() {
if (localMovementStrategy == null) {
throw new ConfigurationException(
......@@ -362,6 +353,6 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
* @return
*/
public List<AttractionPoint> getAttractionPoints() {
return new Vector<AttractionPoint>(transition.getAllAttractionPoints());
return new Vector<AttractionPoint>(IAttractionGenerator.attractionPoints);
}
}
......@@ -78,8 +78,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
suppressListenerNotify = true;
for(ITransitionStrategy strategy : supportedTransitions.values())
{
strategy.setAttractionPoints(transition.getAllAttractionPoints());
{
strategy.addAttractionAssignmentListener(this);
for (SimLocationActuator ms : moveableHosts) {
strategy.addComponent(ms);
......
......@@ -103,13 +103,19 @@ public class RandomAttractionGenerator implements IAttractionGenerator {
if(c < 20)
{
// if not within the world dimensions, directly go back to calculation
if(posVec.getX() + radius > worldDimension.getX() || posVec.getY() + radius > worldDimension.getY()
|| posVec.getX() - radius < 0 || posVec.getY() - radius < 0) {
i--;
c++;
continue create;
}
for (AttractionPoint ap : result) {
// if this point is closer than the given minimum distance to another point, or the radii of the points would overlap,
// or if the radius would exceed the simulation area
// then discard this attraction point and create a new one
if(posVec.distanceTo(ap) < minimumDistance || (posVec.distanceTo(ap) - radius - ap.getRadius()) < 0
|| posVec.getX() + radius > worldDimension.getX() || posVec.getY() + radius > worldDimension.getY()
|| posVec.getX() - radius < 0 || posVec.getY() - radius < 0) {
if(posVec.distanceTo(ap) < minimumDistance || (posVec.distanceTo(ap) - radius - ap.getRadius()) < 0 ) {
i--;
c++;
continue create;
......
/*
* 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;
import java.util.Random;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
* Implementation of the interface {@link AttractionGenerator}.
*
* Generates a random number (out of a given interval) of attraction points. The radius is chosen randomly from a given interval.
* Generated attraction points will most likely not overlay and be completely within the world dimensions.
* With a certain lifetime chosen from a given lifetime interval, attraction points are removed after time and the number of
* attraction points that will be in the area are recalculated. If necessary, attraction points are either removed
* or added.
*
* @author Julian Zobel
* @version 1.0, March 2019
*/
public class RandomDynamicAttractionGenerator implements IAttractionGenerator {
private Random rand;
private PositionVector worldDimension;
private int minNumberOfAttractionPoints;
private int maxNumberOfAttractionPoints;
private long minDynamicIntervall;
private long maxDynamicIntervall;
private double minimumDistance = 100;
private double maximumRadius = 100;
private double minimumRadius = 10;
@XMLConfigurableConstructor({"minNumberOfAttractionPoints", "maxNumberOfAttractionPoints", "minimumRadius",
"maximumRadius", "minDynamicIntervall", "maxDynamicIntervall", "minimumDistance" })
public RandomDynamicAttractionGenerator(int minNumberOfAttractionPoints, int maxNumberOfAttractionPoints,
double minimumRadius, double maximumRadius, long minDynamicIntervall, long maxDynamicIntervall,
double minimumDistance) {
this.rand = Randoms.getRandom(RandomDynamicAttractionGenerator.class);
this.worldDimension = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions();
if (minNumberOfAttractionPoints <= 0) {
throw new ConfigurationException(
"NumberOfAttractionPoints should be at least 1!");
}
if(minNumberOfAttractionPoints > maxNumberOfAttractionPoints) {
throw new ConfigurationException(
"Minimum and maximum numbers of attraction points not correctly set!");
}
this.minNumberOfAttractionPoints = minNumberOfAttractionPoints;
this.maxNumberOfAttractionPoints = maxNumberOfAttractionPoints;
this.minimumRadius = minimumRadius;
this.maximumRadius = maximumRadius;
this.minimumDistance = minimumDistance;
this.minDynamicIntervall = minDynamicIntervall;
this.maxDynamicIntervall = maxDynamicIntervall;
attractionPoints.clear();
updateAttractionPoints();
}
@Override
public List<AttractionPoint> getAttractionPoints() {
return attractionPoints;
}
private int randomNumberOfAttractionPoints() {
return minNumberOfAttractionPoints + rand.nextInt((maxNumberOfAttractionPoints - minNumberOfAttractionPoints) + 1);
}
private void scheduleDynamicEvent(AttractionPoint attractionPoint) {
long r = (long) (rand.nextDouble() * (maxDynamicIntervall - minDynamicIntervall)) + minDynamicIntervall;
Event.scheduleWithDelay(r, new EventHandler() {
@Override
public void eventOccurred(Object content, int type) {
// maybe was already removed...
if(attractionPoints.contains(attractionPoint)) {
attractionPoints.remove(attractionPoint);
updateAttractionPoints();
}
}
}, null, 0);
}
protected void updateAttractionPoints() {
int numberOfAttractionPoints = randomNumberOfAttractionPoints();
// do nothing if this is the required amount of attraction points
if(numberOfAttractionPoints == attractionPoints.size()) {
return;
}
// remove until this number fits
else if(numberOfAttractionPoints < attractionPoints.size()) {
int deltaAP = attractionPoints.size() - numberOfAttractionPoints;
for(int i = 0; i < deltaAP; i++) {
int random = rand.nextInt(attractionPoints.size());
attractionPoints.remove(random);
}
return;
}
// add more attraction points until it fits
else {
int deltaAP = numberOfAttractionPoints - attractionPoints.size();
for(int i = 0; i < deltaAP; i++) {
AttractionPoint newAP = createAttractionPoint();
scheduleDynamicEvent(newAP);
attractionPoints.add(newAP);
}
}
}
/**
* Create an attraction point that is conform to all other currently saved attraction points.
*
* @return
*/
private AttractionPoint createAttractionPoint() {
// make a break counter to prevent more than 10 iterations and an infinity loop in general.
int c = 20;
create: for(int i = 0; i < c; i++) {
PositionVector posVec = createPosVec();
// set the radius of this attraction point
// minimum radius is 10 meters
double radius = Math.max(minimumRadius, rand.nextDouble() * maximumRadius);
if(i < c) {
// check if the attraction points would be completely within world dimensions (including radius!)
if((posVec.getX() + radius) >= worldDimension.getX() || (posVec.getY() + radius) >= worldDimension.getY()
|| (posVec.getX() - radius) <= 0 || (posVec.getY() - radius) <= 0) {
continue create;
}
// if within world dimensions, continue checking against other attraction points
for (AttractionPoint ap : attractionPoints) {
// if this point is closer than the given minimum distance to another point, or the radii of the points would overlap,
// or if the radius would exceed the simulation area
// then discard this attraction point and create a new one
if(posVec.distanceTo(ap) < minimumDistance || (posVec.distanceTo(ap) - radius - ap.getRadius()) < 0) {
continue create;
}
}
}
else {
radius = 0;
}
AttractionPoint aPoint = new AttractionPointImpl("AP-" + rand.nextInt(), posVec);
aPoint.setRadius(radius);
return aPoint;
}
return null;
}
private PositionVector createPosVec() {
double x = rand.nextDouble() * worldDimension.getX();
double y = rand.nextDouble() * worldDimension.getY();
return new PositionVector(x, y);
}
}
......@@ -44,9 +44,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction
public abstract class AbstractAttractionBasedTransitionStrategy implements ITransitionStrategy {
protected Random rnd = Randoms.getRandom(AbstractAttractionBasedTransitionStrategy.class);
protected Set<AttractionPoint> attractionPoints = new LinkedHashSet<>();
protected Map<SimLocationActuator, AttractionPoint> assignments = new LinkedHashMap<>();
protected Map<SimLocationActuator, AttractionPoint> lastAssignments = new LinkedHashMap<>();
......@@ -76,18 +74,6 @@ public abstract class AbstractAttractionBasedTransitionStrategy implements ITran
listeners.remove(listener);
}
@Override
public void setAttractionPoints(
Collection<AttractionPoint> attractionPoints) {
this.attractionPoints.clear();
this.attractionPoints.addAll(attractionPoints);
}
@Override
public Set<AttractionPoint> getAllAttractionPoints() {
return Collections.unmodifiableSet(attractionPoints);
}
/**
* Notify all listeners of an updated attraction point assignment for the given component
*
......
......@@ -28,6 +28,7 @@ import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.common.SimHostComponent;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
/**
......@@ -57,14 +58,14 @@ public class FixedAssignmentStrategy extends AbstractAttractionBasedTransitionSt
// No assignments been done before.
if (assignments.isEmpty()) {
AttractionPoint aPoint = attractionPoints.iterator().next();
AttractionPoint aPoint = IAttractionGenerator.attractionPoints.iterator().next();
assignments.put(ms, aPoint);
mappingGroupId(ms, aPoint);
}
// GroupId is not mapped.
else if (!mappingGroupIdAP.containsKey(mappingMSHost.get(ms)
.getProperties().getGroupID())) {
for (AttractionPoint actAP : attractionPoints) {
for (AttractionPoint actAP : IAttractionGenerator.attractionPoints) {
if (!mappingAPGroupId.containsKey(actAP)) {
assignments.put(ms, actAP);
mappingGroupId(ms, actAP);
......
......@@ -46,21 +46,6 @@ public interface ITransitionStrategy {
public void removeAttractionAssignmentListener(AttractionAssignmentListener listener);
/**
* Should be called first, to add the Attraction Points for the assignment!
*
* @param attractionPoints
*/
public void setAttractionPoints(
Collection<AttractionPoint> attractionPoints);
/**
* Return a set of all attraction points
*
* @return
*/
public Set<AttractionPoint> getAllAttractionPoints();
/**
* Add the object and assign the MS to an {@link AttractionPoint}.
*
......
......@@ -26,6 +26,7 @@ import java.util.List;
import java.util.Map;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Time;
......@@ -94,13 +95,26 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedTran
@Override
public void eventOccurred(Object content, int type) {
if(type == EVENT_PAUSE_ENDED) {
SimLocationActuator comp = (SimLocationActuator) content;
this.addComponent(comp);
if(type == EVENT_PAUSE_ENDED) {
SimLocationActuator comp = (SimLocationActuator) content;
// if the transit was triggered beforehand (e.g., attraction point moved), then do nothing.
if(roamingStates.get(comp) != roamingTransitionState.TRANSITION) {
this.addComponent(comp);
}
}
else if(type == EVENT_ROAMING_PAUSE_ENDED) {
SimLocationActuator comp = (SimLocationActuator) content;
this.roamAroundAttractionPoint(comp);
AttractionPoint currentAttractionPoint = this.assignments.get(comp);
// if the attraction point was removed in the meantime, go directly to transit state
if(!IAttractionGenerator.attractionPoints.contains(currentAttractionPoint)) {
this.addComponent(comp);
}
else {
this.roamAroundAttractionPoint(comp);
}
}
}
......@@ -108,7 +122,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedTran
private AttractionPoint getNewAttractionPoint(SimLocationActuator component) {
double score = rnd.nextDouble();
List<AttractionPoint> candidates = new LinkedList<>();
for (AttractionPoint ap : attractionPoints) {
for (AttractionPoint ap : IAttractionGenerator.attractionPoints) {
if (ap.getWeight() >= score) {
if(lastAssignments.get(component) == null || !ap.equals(lastAssignments.get(component))) {
candidates.add(ap);
......@@ -116,7 +130,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedTran
}
}
if (candidates.isEmpty()) {
candidates.addAll(attractionPoints);
candidates.addAll(IAttractionGenerator.attractionPoints);
}
AttractionPoint assignment = candidates.get(rnd.nextInt(candidates.size()));
return assignment;
......
......@@ -40,12 +40,10 @@ public class ManualAssignmentStrategy implements ITransitionStrategy
listeners.remove(listener);
}
@Override
public void setAttractionPoints(Collection<AttractionPoint> attractionPoints) {
aPoints.addAll(attractionPoints);
}
@Override
public Set<AttractionPoint> getAllAttractionPoints() {
return aPoints;
}
......
......@@ -5,6 +5,7 @@ import java.util.Map;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.BasicAttractionPoint;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
......@@ -48,7 +49,7 @@ public class RandomInAreaTransitionStrategy extends AbstractAttractionBasedTrans
if(!assignments.containsKey(ms))
{
AttractionPoint aPoint = attractionPoints.iterator().next();
AttractionPoint aPoint = IAttractionGenerator.attractionPoints.iterator().next();
assignments.put(ms, aPoint);
currentTarget.put(ms, nextRandomPosition(aPoint, defaultRadius));
currentSearchRadius.put(ms, defaultRadius);
......
......@@ -38,6 +38,7 @@ import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.social.SocialView;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event;
......@@ -131,12 +132,6 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS
public void setSocialId(String socialId) {
this.socialId = socialId;
}
@Override
public void setAttractionPoints(Collection<AttractionPoint> attractionPoints) {
init();
super.setAttractionPoints(attractionPoints);
}
@Override
public void addComponent(SimLocationActuator ms) {
......@@ -146,8 +141,8 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS
// position.
// TODO: needed? We do Transition as next, and this will delete the
// assignment..
AttractionPoint nearest = attractionPoints.iterator().next();
for (AttractionPoint aPoint : attractionPoints) {
AttractionPoint nearest = IAttractionGenerator.attractionPoints.iterator().next();
for (AttractionPoint aPoint : IAttractionGenerator.attractionPoints) {
if (nearest.distanceTo(ms.getRealPosition()) > aPoint
.distanceTo(ms.getRealPosition())) {
nearest = aPoint;
......@@ -181,7 +176,7 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS
List<AttractionPoint> apFriends = getFriendsPlaces(ms);
List<AttractionPoint> apClusters = getClusterPlaces(ms);
List<AttractionPoint> apRandom = getRandomPlaces(ms,
(int) Math.max(attractionPoints.size() * 0.2, 5));
(int) Math.max(IAttractionGenerator.attractionPoints.size() * 0.2, 5));
AttractionPoint ap = null;
if (rnd.nextDouble() < socialFactor) {
......@@ -299,7 +294,7 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS
private List<AttractionPoint> getRandomPlaces(SimLocationActuator ms,
int number) {
List<AttractionPoint> result = new Vector<AttractionPoint>(attractionPoints);
List<AttractionPoint> result = new Vector<AttractionPoint>(IAttractionGenerator.attractionPoints);
Collections.shuffle(result, rnd);
return result.subList(0, Math.min(result.size(), number));
}
......@@ -339,7 +334,7 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS
private void assignFavoritePlaces(SimLocationActuator ms) {
Set<AttractionPoint> msFavoritePlaces = new LinkedHashSet<AttractionPoint>();
LinkedList<AttractionPoint> temp = new LinkedList<AttractionPoint>(
attractionPoints);
IAttractionGenerator.attractionPoints);
Collections.shuffle(temp, rnd);
for (int i = 0; i < numberOfFavoritePlaces; i++) {
if (!temp.isEmpty()) {
......
......@@ -23,6 +23,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition;
import java.util.LinkedList;
import java.util.List;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
......@@ -50,13 +51,13 @@ public class WeightedTransitionStrategy extends AbstractAttractionBasedTransitio
private AttractionPoint getNewAssignment(SimLocationActuator component) {
double score = rnd.nextDouble();
List<AttractionPoint> candidates = new LinkedList<>();
for (AttractionPoint ap : attractionPoints) {
for (AttractionPoint ap : IAttractionGenerator.attractionPoints) {
if (ap.getWeight() >= score) {
candidates.add(ap);
}
}
if (candidates.isEmpty()) {
candidates.addAll(attractionPoints);
candidates.addAll(IAttractionGenerator.attractionPoints);
}
AttractionPoint assignment = candidates.get(rnd.nextInt(candidates.size()));
notifyListenersOfAssignmentUpdate(component, assignment);
......
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