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

wip

parent 6ccbc90e
...@@ -837,6 +837,10 @@ public class DefaultConfigurator implements Configurator { ...@@ -837,6 +837,10 @@ public class DefaultConfigurator implements Configurator {
public static <T extends Number> T parseNumber(String value, public static <T extends Number> T parseNumber(String value,
Class<T> targetClass) { Class<T> targetClass) {
assert value != null; assert value != null;
if(value == null)
System.out.println("");
String number = value; String number = value;
double factor = 1; double factor = 1;
// Time // Time
......
...@@ -105,7 +105,6 @@ public class DefaultTopologyComponent extends AbstractTopologyComponent { ...@@ -105,7 +105,6 @@ public class DefaultTopologyComponent extends AbstractTopologyComponent {
public void setTargetAttractionPoint(AttractionPoint targetAttractionPoint) public void setTargetAttractionPoint(AttractionPoint targetAttractionPoint)
throws UnsupportedOperationException { throws UnsupportedOperationException {
movementModel.changeTargetLocation(this, targetAttractionPoint); movementModel.changeTargetLocation(this, targetAttractionPoint);
// NodeDebugMonitor.update(this.getClass(), getHost().getId(), "Target Location", targetAttractionPoint);
} }
@Override @Override
......
...@@ -38,8 +38,8 @@ import de.tud.kom.p2psim.impl.simengine.Simulator; ...@@ -38,8 +38,8 @@ import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.TopologyFactory; import de.tud.kom.p2psim.impl.topology.TopologyFactory;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator; import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.mapvisualization.IMapVisualization; import de.tud.kom.p2psim.impl.topology.movement.modularosm.mapvisualization.IMapVisualization;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy; import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.IAttractionAssigmentStrategy;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy.AttractionAssignmentListener; import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.IAttractionAssigmentStrategy.AttractionAssignmentListener;
import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector; import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
...@@ -61,7 +61,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction ...@@ -61,7 +61,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction
* M1: A general {@link MovementModel} is not used, because we use static * M1: A general {@link MovementModel} is not used, because we use static
* attraction points. * attraction points.
* <p> * <p>
* M2: The {@link ITransitionStrategy}! It takes the Hosts, which should be moved * M2: The {@link IAttractionAssigmentStrategy}! It takes the Hosts, which should be moved
* around, but calculates only the assignment to the {@link AttractionPoint}s. * 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! * It doesn't move the Hosts! It will be only assignment a new AttractionPoint!
* *
...@@ -99,7 +99,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -99,7 +99,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
protected PositionVector worldDimensions; protected PositionVector worldDimensions;
protected ITransitionStrategy transition; protected IAttractionAssigmentStrategy attractionAssigment;
protected IAttractionGenerator attractionGenerator; protected IAttractionGenerator attractionGenerator;
...@@ -136,9 +136,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -136,9 +136,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
public void initialize() { public void initialize() {
if (!initialized) { if (!initialized) {
System.out.println("init modular movement model");
if (modelVisualisation == null) { if (modelVisualisation == null) {
modelVisualisation = new ModularMovementModelViz(this); modelVisualisation = new ModularMovementModelViz(this);
} }
...@@ -161,12 +159,12 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -161,12 +159,12 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
localMovementStrategy localMovementStrategy
.setScaleFactor(timeBetweenMoveOperation / (double) Time.SECOND); .setScaleFactor(timeBetweenMoveOperation / (double) Time.SECOND);
transition.addAttractionAssignmentListener(this); attractionAssigment.addAttractionAssignmentListener(this);
// This adds the mobile hosts (smartphones/users) to the transition // This adds the mobile hosts (smartphones/users) to the transition
// strategy // strategy
for (SimLocationActuator ms : moveableHosts) { for (SimLocationActuator ms : moveableHosts) {
transition.addComponent(ms); attractionAssigment.addComponent(ms);
} }
setTimeBetweenMoveOperations(timeBetweenMoveOperation); setTimeBetweenMoveOperations(timeBetweenMoveOperation);
...@@ -189,7 +187,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -189,7 +187,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
@Override @Override
public void changeTargetLocation(SimLocationActuator actuator, AttractionPoint ap) { public void changeTargetLocation(SimLocationActuator actuator, AttractionPoint ap) {
transition.updateTargetAttractionPoint(actuator, ap); attractionAssigment.updateTargetAttractionPoint(actuator, ap);
} }
private void checkConfiguration() { private void checkConfiguration() {
...@@ -197,7 +195,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -197,7 +195,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
throw new ConfigurationException( throw new ConfigurationException(
"LocalMovementStrategy is missing in ModularMovementModel!"); "LocalMovementStrategy is missing in ModularMovementModel!");
} }
if (transition == null) { if (attractionAssigment == null) {
throw new ConfigurationException( throw new ConfigurationException(
"TransitionStrategy is missing in ModularMovementModel!"); "TransitionStrategy is missing in ModularMovementModel!");
} }
...@@ -218,6 +216,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -218,6 +216,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
@Override @Override
public void updatedAttractionAssignment(SimLocationActuator component, public void updatedAttractionAssignment(SimLocationActuator component,
AttractionPoint newAssignment) { AttractionPoint newAssignment) {
/* /*
* Use this method to calculate the offset and target location for a * Use this method to calculate the offset and target location for a
* host. * host.
...@@ -227,7 +226,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -227,7 +226,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
/* /*
* Even if an AP does not have a radius, we slightly offset * Even if an AP does not have a radius, we slightly offset
*/ */
double apRadius = Math.max(newAssignment.getRadius(), 25.0); double apRadius = (newAssignment.hasRadius() ? Math.max(newAssignment.getRadius(), 25.0) : 25.0);
int tries = 0; int tries = 0;
do { do {
...@@ -238,13 +237,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -238,13 +237,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
rand.nextGaussian() * apRadius / 3); rand.nextGaussian() * apRadius / 3);
destination.add(offset); destination.add(offset);
// Check constraints // Check constraints
if (destination.getX() < 0.0 if (!checkBoundaries(destination)) {
|| destination.getX() > Binder
.getComponentOrNull(Topology.class)
.getWorldDimensions().getX() || destination.getY() < 0.0
|| destination.getY() > Binder
.getComponentOrNull(Topology.class)
.getWorldDimensions().getY()) {
destination = null; destination = null;
if (tries > 100) { if (tries > 100) {
throw new AssertionError("Unable to find a valid target destination within <100 tries."); throw new AssertionError("Unable to find a valid target destination within <100 tries.");
...@@ -252,7 +245,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -252,7 +245,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
} }
tries++; tries++;
} while (destination == null); } while (destination == null);
currentTargets.put(component, destination); currentTargets.put(component, destination);
} }
...@@ -279,10 +272,12 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -279,10 +272,12 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
if (either.hasLeft()) { if (either.hasLeft()) {
ms.updateCurrentLocation(either.getLeft()); ms.updateCurrentLocation(either.getLeft());
checkBoundaries(ms); if(!checkBoundaries(ms.getRealPosition())) {
System.err.println("Modular Movement Model: Host moved outside of simulated area!");
}
} }
else { else {
transition.reachedAttractionPoint(ms, ms.getCurrentTargetAttractionPoint()); attractionAssigment.reachedAttractionPoint(ms, ms.getCurrentTargetAttractionPoint());
} }
} }
...@@ -295,17 +290,15 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -295,17 +290,15 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
* Notifies the user if a hosts position lies outside of the specified world size. * Notifies the user if a hosts position lies outside of the specified world size.
* Enable asserts to get the notification * Enable asserts to get the notification
* *
* @param SimLocationActuator The host to be checked
*/ */
public void checkBoundaries(SimLocationActuator ms) { public boolean checkBoundaries(PositionVector position) {
assert ms.getRealPosition().getX() >= 0.0 if(position.getX() >= 0.0
&& ms.getRealPosition().getX() <= Binder && position.getX() <= Binder.getComponentOrNull(Topology.class).getWorldDimensions().getX()
.getComponentOrNull(Topology.class) && position.getY() >= 0.0
.getWorldDimensions().getX(); && position.getY() <= Binder.getComponentOrNull(Topology.class).getWorldDimensions().getY())
assert ms.getRealPosition().getY() >= 0.0 return true;
&& ms.getRealPosition().getY() <= Binder else
.getComponentOrNull(Topology.class) return false;
.getWorldDimensions().getY();
} }
@Override @Override
...@@ -353,12 +346,12 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -353,12 +346,12 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
this.localMovementStrategy = localMovementStrategy; this.localMovementStrategy = localMovementStrategy;
} }
public void setITransitionStrategy(ITransitionStrategy transition) { public void setITransitionStrategy(IAttractionAssigmentStrategy transition) {
if (transition == null) { if (transition == null) {
throw new ConfigurationException( throw new ConfigurationException(
"TransitionStrategy is missing in ModularMovementModel!"); "TransitionStrategy is missing in ModularMovementModel!");
} }
this.transition = transition; this.attractionAssigment = transition;
} }
public void setIMapVisualization(IMapVisualization mapVisualization) { public void setIMapVisualization(IMapVisualization mapVisualization) {
...@@ -373,7 +366,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -373,7 +366,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
@Override @Override
public AttractionPoint getTargetLocation(SimLocationActuator actuator) { public AttractionPoint getTargetLocation(SimLocationActuator actuator) {
return transition.getAssignment(actuator); return attractionAssigment.getAssignment(actuator);
} }
/** /**
......
...@@ -4,7 +4,7 @@ import de.tud.kom.p2psim.api.topology.Topology; ...@@ -4,7 +4,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.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.local.RouteImpl; import de.tud.kom.p2psim.impl.topology.movement.local.RouteImpl;
import de.tud.kom.p2psim.impl.topology.movement.local.RealWorldStreetsMovement; import de.tud.kom.p2psim.impl.topology.movement.local.RealWorldStreetsMovement;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy; import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.IAttractionAssigmentStrategy;
import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.Binder;
...@@ -18,9 +18,9 @@ import java.util.List; ...@@ -18,9 +18,9 @@ import java.util.List;
/** /**
* This class is meant to be used with the RealWorldStreetsMovement * This class is meant to be used with the RealWorldStreetsMovement
* and allows changes of the movement type and the used {@link ITransitionStrategy} mid-simulation * and allows changes of the movement type and the used {@link IAttractionAssigmentStrategy} mid-simulation
* on a per-host basis. It acts like the {@link ModularMovementModel}, but each of the {@link SimLocationActuator}s * on a per-host basis. It acts like the {@link ModularMovementModel}, but each of the {@link SimLocationActuator}s
* can have a different movement type and {@link ITransitionStrategy}. All routes and targets will be * can have a different movement type and {@link IAttractionAssigmentStrategy}. All routes and targets will be
* calculated accordingly. <BR><BR> * calculated accordingly. <BR><BR>
* *
* Originally the whole movement system within the simonstrator platform was not intended to be manipulable * Originally the whole movement system within the simonstrator platform was not intended to be manipulable
...@@ -38,7 +38,7 @@ import java.util.List; ...@@ -38,7 +38,7 @@ import java.util.List;
* (besides selecting this model in your config) call the {@link #setMovementType(SimLocationActuator, String)} * (besides selecting this model in your config) call the {@link #setMovementType(SimLocationActuator, String)}
* for each of your components.<BR> * for each of your components.<BR>
* *
* The used {@link ITransitionStrategy} can be changed on runtime, too. However, the first * The used {@link IAttractionAssigmentStrategy} can be changed on runtime, too. However, the first
* TransitionStrategy specified in the config will be used as default, and will be applied if there is * TransitionStrategy specified in the config will be used as default, and will be applied if there is
* no further strategy specified for a specific host. To use multiple strategies, add them to your * no further strategy specified for a specific host. To use multiple strategies, add them to your
* config just as the first one. To set a specific strategy for a specific host, call the {@link #setTransitionForComponent(SimLocationActuator, Class)} * config just as the first one. To set a specific strategy for a specific host, call the {@link #setTransitionForComponent(SimLocationActuator, Class)}
...@@ -54,12 +54,12 @@ import java.util.List; ...@@ -54,12 +54,12 @@ import java.util.List;
public class ModularMultiTypeMovementModel extends ModularMovementModel public class ModularMultiTypeMovementModel extends ModularMovementModel
{ {
private HashMap<SimLocationActuator, String> movementTypes; private HashMap<SimLocationActuator, String> movementTypes;
private HashMap<SimLocationActuator, ITransitionStrategy> transitions; private HashMap<SimLocationActuator, IAttractionAssigmentStrategy> transitions;
private HashMap<Class, ITransitionStrategy> supportedTransitions; private HashMap<Class, IAttractionAssigmentStrategy> supportedTransitions;
private LinkedList<MultiTypeMovementListener> movementListeners = new LinkedList<>(); private LinkedList<MultiTypeMovementListener> movementListeners = new LinkedList<>();
/** /**
* Suppresses notifications to {@link de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy.AttractionAssignmentListener}s. * Suppresses notifications to {@link de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.IAttractionAssigmentStrategy.AttractionAssignmentListener}s.
*/ */
private boolean suppressListenerNotify = false; private boolean suppressListenerNotify = false;
...@@ -77,7 +77,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel ...@@ -77,7 +77,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
super.initialize(); super.initialize();
suppressListenerNotify = true; suppressListenerNotify = true;
for(ITransitionStrategy strategy : supportedTransitions.values()) for(IAttractionAssigmentStrategy strategy : supportedTransitions.values())
{ {
strategy.addAttractionAssignmentListener(this); strategy.addAttractionAssignmentListener(this);
for (SimLocationActuator ms : moveableHosts) { for (SimLocationActuator ms : moveableHosts) {
...@@ -118,7 +118,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel ...@@ -118,7 +118,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
transitions.get(ms).reachedAttractionPoint(ms, ms.getCurrentTargetAttractionPoint()); transitions.get(ms).reachedAttractionPoint(ms, ms.getCurrentTargetAttractionPoint());
} }
else { else {
transition.reachedAttractionPoint(ms, ms.getCurrentTargetAttractionPoint()); attractionAssigment.reachedAttractionPoint(ms, ms.getCurrentTargetAttractionPoint());
} }
movementListeners.forEach(l -> l.onTransition(ms)); movementListeners.forEach(l -> l.onTransition(ms));
} }
...@@ -150,7 +150,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel ...@@ -150,7 +150,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
* @param ms the component * @param ms the component
* @return the current transition strategy * @return the current transition strategy
*/ */
public ITransitionStrategy getTransitionForComponent(SimLocationActuator ms) public IAttractionAssigmentStrategy getTransitionForComponent(SimLocationActuator ms)
{ {
return transitions.get(ms); return transitions.get(ms);
} }
...@@ -160,9 +160,9 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel ...@@ -160,9 +160,9 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
* @param strategy The class of the strategy which should be returned. * @param strategy The class of the strategy which should be returned.
* @return The specified strategy * @return The specified strategy
*/ */
public ITransitionStrategy getTransitionStrategy(Class strategy) public IAttractionAssigmentStrategy getTransitionStrategy(Class strategy)
{ {
ITransitionStrategy selectedStrategy = supportedTransitions.get(strategy); IAttractionAssigmentStrategy selectedStrategy = supportedTransitions.get(strategy);
if(selectedStrategy == null) if(selectedStrategy == null)
{ {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
...@@ -173,7 +173,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel ...@@ -173,7 +173,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
} }
/** /**
* Sets the {@link ITransitionStrategy} for the specified {@link SimLocationActuator}. Used strategies * Sets the {@link IAttractionAssigmentStrategy} for the specified {@link SimLocationActuator}. Used strategies
* need to be registered in the config. * need to be registered in the config.
* @param ms The SimLocationActuator * @param ms The SimLocationActuator
* @param strategy the strategy to use * @param strategy the strategy to use
...@@ -188,9 +188,9 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel ...@@ -188,9 +188,9 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
* @param ms The SimLocationActuator * @param ms The SimLocationActuator
* @param newStrategy the new strategy to use * @param newStrategy the new strategy to use
*/ */
private void changeTransitionStrategy(SimLocationActuator ms, ITransitionStrategy newStrategy) private void changeTransitionStrategy(SimLocationActuator ms, IAttractionAssigmentStrategy newStrategy)
{ {
ITransitionStrategy usedStrategy = transitions.containsKey(ms) ? transitions.get(ms) : transition; IAttractionAssigmentStrategy usedStrategy = transitions.containsKey(ms) ? transitions.get(ms) : attractionAssigment;
newStrategy.updateTargetAttractionPoint(ms, usedStrategy.getAssignment(ms)); newStrategy.updateTargetAttractionPoint(ms, usedStrategy.getAssignment(ms));
transitions.put(ms, newStrategy); transitions.put(ms, newStrategy);
Monitor.log(ModularMultiTypeMovementModel.class, Monitor.Level.DEBUG, String.format("Client %s changed his transition strategy from %s to %s", ms.getHost().getId().toString(), usedStrategy.getClass(), newStrategy.getClass())); Monitor.log(ModularMultiTypeMovementModel.class, Monitor.Level.DEBUG, String.format("Client %s changed his transition strategy from %s to %s", ms.getHost().getId().toString(), usedStrategy.getClass(), newStrategy.getClass()));
...@@ -213,7 +213,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel ...@@ -213,7 +213,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
} }
/** /**
* Sets the default {@link ITransitionStrategy} for the specified {@link SimLocationActuator}. * Sets the default {@link IAttractionAssigmentStrategy} for the specified {@link SimLocationActuator}.
* @param ms The SimLocationActuator * @param ms The SimLocationActuator
*/ */
public void returnToDefaultTransition(SimLocationActuator ms) public void returnToDefaultTransition(SimLocationActuator ms)
...@@ -224,19 +224,19 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel ...@@ -224,19 +224,19 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
@Override @Override
public void changeTargetLocation(SimLocationActuator actuator, AttractionPoint ap) { public void changeTargetLocation(SimLocationActuator actuator, AttractionPoint ap) {
if(transitions.containsKey(actuator)) transitions.get(actuator).updateTargetAttractionPoint(actuator, ap); if(transitions.containsKey(actuator)) transitions.get(actuator).updateTargetAttractionPoint(actuator, ap);
else transition.updateTargetAttractionPoint(actuator, ap); else attractionAssigment.updateTargetAttractionPoint(actuator, ap);
} }
@Override @Override
public void setITransitionStrategy(ITransitionStrategy transition) { public void setITransitionStrategy(IAttractionAssigmentStrategy transition) {
if(supportedTransitions.size() == 0) this.transition = transition; if(supportedTransitions.size() == 0) this.attractionAssigment = transition;
supportedTransitions.put(transition.getClass(), transition); supportedTransitions.put(transition.getClass(), transition);
} }
@Override @Override
public AttractionPoint getTargetLocation(SimLocationActuator actuator) { public AttractionPoint getTargetLocation(SimLocationActuator actuator) {
if(transitions.containsKey(actuator)) return transitions.get(actuator).getAssignment(actuator); if(transitions.containsKey(actuator)) return transitions.get(actuator).getAssignment(actuator);
else return transition.getAssignment(actuator); else return attractionAssigment.getAssignment(actuator);
} }
@Override @Override
......
...@@ -43,8 +43,8 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovement ...@@ -43,8 +43,8 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovement
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounter.IGroupEncounterBehavior; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounter.IGroupEncounterBehavior;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupforming.IGroupFormingBehavior; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupforming.IGroupFormingBehavior;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.mapvisualization.IMapVisualization; import de.tud.kom.p2psim.impl.topology.movement.modularosm.mapvisualization.IMapVisualization;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy; import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.IAttractionAssigmentStrategy;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy.AttractionAssignmentListener; import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.IAttractionAssigmentStrategy.AttractionAssignmentListener;
import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector; import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
...@@ -74,9 +74,6 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -74,9 +74,6 @@ public class SocialGroupMovementModel extends ModularMovementModel {
public void initialize() { public void initialize() {
if (!initialized) { if (!initialized) {
System.out.println("init social group movement");
groupContainer = MovementGroupContainer.getInstance(); groupContainer = MovementGroupContainer.getInstance();
attractionPointHostCounter.initialize(this); attractionPointHostCounter.initialize(this);
groupFormingBehavior.initialize(this); groupFormingBehavior.initialize(this);
...@@ -124,9 +121,7 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -124,9 +121,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
* @author Marcel Verst * @author Marcel Verst
*/ */
@Override @Override
protected void move() { protected void move() {
System.out.println("social group : move");
// Update the number of hosts within each attraction point. // Update the number of hosts within each attraction point.
attractionPointHostCounter.updateHostCount(); attractionPointHostCounter.updateHostCount();
...@@ -162,8 +157,7 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -162,8 +157,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
*/ */
protected void doGroupMovement(SimLocationActuator host, PositionVector destination) { protected void doGroupMovement(SimLocationActuator host, PositionVector destination) {
// Single Host Movement // Single Host Movement
if(singleHosts.contains(host) && !groupContainer.isGroupMember(host)) { if(singleHosts.contains(host) || !groupContainer.isGroupMember(host)) {
System.out.println("local movement");
doLocalMovement(host, destination); doLocalMovement(host, destination);
} }
...@@ -178,7 +172,7 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -178,7 +172,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
group.setMeetingPoint(currDest); group.setMeetingPoint(currDest);
for(SimLocationActuator participant : group.getMembers()) { for(SimLocationActuator participant : group.getMembers()) {
transition.updateTargetAttractionPoint(participant, currAp); attractionAssigment.updateTargetAttractionPoint(participant, currAp);
} }
} }
} }
...@@ -191,7 +185,7 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -191,7 +185,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
// MP reached. Move to destination. // MP reached. Move to destination.
else { else {
if(groupContainer.isLeader(host)) { if(groupContainer.isLeader(host)) {
if(!groupContainer.isWaiting(groupContainer.getGroupOfHost(host))) { if(!groupContainer.isWaiting(groupContainer.getGroupOfHost(host))) {
doLocalMovement(host, destination); doLocalMovement(host, destination);
} }
} }
...@@ -241,7 +235,7 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -241,7 +235,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
counter++; counter++;
} }
} }
if(counter == participants.size()) { if(counter == participants.size()) {
return true; return true;
} }
return false; return false;
...@@ -262,7 +256,7 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -262,7 +256,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
// Setting the required distance to the meeting point to maximum of 2 meters // Setting the required distance to the meeting point to maximum of 2 meters
// This is equivalent to a distance of group members in real life // This is equivalent to a distance of group members in real life
double distance = host.getLastLocation().distanceTo(currMP); double distance = host.getLastLocation().distanceTo(currMP);
if(distance <= 2) { if(distance <= 2) {
return true; return true;
} }
return false; return false;
...@@ -284,17 +278,24 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -284,17 +278,24 @@ public class SocialGroupMovementModel extends ModularMovementModel {
*/ */
private void followLeader(SimLocationActuator host) { private void followLeader(SimLocationActuator host) {
SimLocationActuator leader = groupContainer.getGroupOfHost(host).getLeader(); SimLocationActuator leader = groupContainer.getGroupOfHost(host).getLeader();
if(leader.getCurrentTargetAttractionPoint() == null) {
System.out.println();
}
AttractionPoint leaderDestination = leader.getCurrentTargetAttractionPoint(); AttractionPoint leaderDestination = leader.getCurrentTargetAttractionPoint();
AttractionPoint hostDestination = host.getCurrentTargetAttractionPoint(); AttractionPoint hostDestination = host.getCurrentTargetAttractionPoint();
// Update target attraction point if not already done // Update target attraction point if not already done
if(hostDestination != leaderDestination) { if(leaderDestination != null && hostDestination != leaderDestination) {
transition.updateTargetAttractionPoint(host, leaderDestination); attractionAssigment.updateTargetAttractionPoint(host, leaderDestination);
} }
int o = 10;
// Assign small offset to the host depending on the leaders position. // Assign small offset to the host depending on the leaders position.
PositionVector leaderPos = leader.getRealPosition(); PositionVector leaderPos = leader.getRealPosition();
PositionVector offset = new PositionVector(rand.nextInt(2), rand.nextInt(2)); PositionVector offset = new PositionVector(rand.nextInt(o), rand.nextInt(o));
PositionVector newPos = leaderPos.plus(offset); PositionVector newPos = leaderPos.plus(offset);
// Update location of host, which will be around the leaders location. // Update location of host, which will be around the leaders location.
...@@ -332,8 +333,12 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -332,8 +333,12 @@ public class SocialGroupMovementModel extends ModularMovementModel {
this.attractionPointHostCounter = attractionPointHostCounter; this.attractionPointHostCounter = attractionPointHostCounter;
} }
public ITransitionStrategy getTransition() { public IAttractionAssigmentStrategy getAttractionAssignmentStrategy() {
return transition; return attractionAssigment;
}
public IGroupFormingBehavior getGroupFormingBehavior() {
return groupFormingBehavior;
} }
public LocalMovementStrategy getMovementStrategy() { public LocalMovementStrategy getMovementStrategy() {
......
...@@ -42,22 +42,15 @@ public class MovementGroupContainer { ...@@ -42,22 +42,15 @@ public class MovementGroupContainer {
// Mappings // Mappings
private Map<SimLocationActuator, Long> leftGroupAtTime; private Map<SimLocationActuator, Long> leftGroupAtTime;
private Map<SimLocationActuator, Boolean> hasBeenInAGroup;
private Map<SimLocationActuator, Boolean> hasMerged; private Map<SimLocationActuator, Boolean> hasMerged;
private Map<SimLocationActuator, Long> mergedAtTime; private Map<SimLocationActuator, Long> mergedAtTime;
// Config variables
private int minGroupSize;
private int maxGroupSize;
private long waitTime;
// Waiting Groups, used for encounter strategy Wait. Includes remaining waiting time and last update time // Waiting Groups, used for encounter strategy Wait. Includes remaining waiting time and last update time
public Map<SocialMovementGroup, Tuple<Long, Long>> waitingGroups; public Map<SocialMovementGroup, Tuple<Long, Long>> waitingGroups;
private MovementGroupContainer() { private MovementGroupContainer() {
groups = new LinkedHashSet<>(); groups = new LinkedHashSet<>();
leftGroupAtTime = new LinkedHashMap<>(); leftGroupAtTime = new LinkedHashMap<>();
hasBeenInAGroup = new LinkedHashMap<>();
hasMerged = new LinkedHashMap<>(); hasMerged = new LinkedHashMap<>();
mergedAtTime = new LinkedHashMap<>(); mergedAtTime = new LinkedHashMap<>();
waitingGroups = new LinkedHashMap<SocialMovementGroup, Tuple<Long,Long>>(); waitingGroups = new LinkedHashMap<SocialMovementGroup, Tuple<Long,Long>>();
...@@ -138,17 +131,7 @@ public class MovementGroupContainer { ...@@ -138,17 +131,7 @@ public class MovementGroupContainer {
if(leftGroupAtTime.containsKey(host)) { if(leftGroupAtTime.containsKey(host)) {
leftGroupAtTime.remove(host); leftGroupAtTime.remove(host);
} }
} }
public void addHasBeenInGroupEntry(SimLocationActuator host, Boolean value) {
hasBeenInAGroup.put(host, value);
}
public void removeHasBeenInGroupEntry(SimLocationActuator host) {
if(hasBeenInAGroup.containsKey(host)) {
hasBeenInAGroup.remove(host);
}
}
public void addHasMergedEntry(SimLocationActuator host, Boolean value) { public void addHasMergedEntry(SimLocationActuator host, Boolean value) {
hasMerged.put(host, value); hasMerged.put(host, value);
...@@ -299,6 +282,10 @@ public class MovementGroupContainer { ...@@ -299,6 +282,10 @@ public class MovementGroupContainer {
this.groups = groups; this.groups = groups;
} }
public boolean getHostWasGroupMember(SimLocationActuator host) {
return this.leftGroupAtTime.containsKey(host);
}
public Map<SimLocationActuator, Long> getLeftGroupAtTime() { public Map<SimLocationActuator, Long> getLeftGroupAtTime() {
return leftGroupAtTime; return leftGroupAtTime;
} }
...@@ -307,22 +294,6 @@ public class MovementGroupContainer { ...@@ -307,22 +294,6 @@ public class MovementGroupContainer {
this.leftGroupAtTime = leftGroupAtTime; this.leftGroupAtTime = leftGroupAtTime;
} }
public Map<SimLocationActuator, Boolean> getHasBeenInAGroup() {
return hasBeenInAGroup;
}
public void setHasBeenInAGroup(Map<SimLocationActuator, Boolean> hasBeenInAGroup) {
this.hasBeenInAGroup = hasBeenInAGroup;
}
public long getWaitTime() {
return waitTime;
}
public void setWaitTime(long waitTime) {
this.waitTime = waitTime;
}
public Map<SimLocationActuator, Boolean> getHasMerged() { public Map<SimLocationActuator, Boolean> getHasMerged() {
return hasMerged; return hasMerged;
} }
...@@ -338,20 +309,4 @@ public class MovementGroupContainer { ...@@ -338,20 +309,4 @@ public class MovementGroupContainer {
public void setMergedAtTime(Map<SimLocationActuator, Long> mergedAtTime) { public void setMergedAtTime(Map<SimLocationActuator, Long> mergedAtTime) {
this.mergedAtTime = mergedAtTime; this.mergedAtTime = mergedAtTime;
} }
public int getMinGroupSize() {
return minGroupSize;
}
public void setMinGroupSize(int minGroupSize) {
this.minGroupSize = minGroupSize;
}
public int getMaxGroupSize() {
return maxGroupSize;
}
public void setMaxGroupSize(int maxGroupSize) {
this.maxGroupSize = maxGroupSize;
}
} }
\ No newline at end of file
...@@ -94,7 +94,7 @@ public class SocialMovementGroup { ...@@ -94,7 +94,7 @@ public class SocialMovementGroup {
*/ */
public SimLocationActuator getRandomMember() { public SimLocationActuator getRandomMember() {
if(members.size() >= 1) { if(members.size() > 1) {
Random rand = Randoms.getRandom(SocialMovementGroup.class); Random rand = Randoms.getRandom(SocialMovementGroup.class);
int item = rand.nextInt(members.size() - 1); int item = rand.nextInt(members.size() - 1);
int i = 0; int i = 0;
...@@ -106,6 +106,9 @@ public class SocialMovementGroup { ...@@ -106,6 +106,9 @@ public class SocialMovementGroup {
i++; i++;
} }
} }
else if(members.size() == 1) {
return members.iterator().next();
}
return null; return null;
} }
......
...@@ -32,6 +32,7 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovement ...@@ -32,6 +32,7 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovement
import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
* This class contains methods used by all encounter strategies. * This class contains methods used by all encounter strategies.
...@@ -43,7 +44,8 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -43,7 +44,8 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
//--- COMMON VARIABLES TO BE DECLARED IN CONFIG --- //--- COMMON VARIABLES TO BE DECLARED IN CONFIG ---
protected boolean enableGroupEncounters; protected boolean enableGroupEncounters;
protected double meetingDistance; protected double groupEncounterMeetingDistance;
protected long groupReencounterWaitTime;
//------------------------------------------------- //-------------------------------------------------
protected final int DECISION_NONE = 0; protected final int DECISION_NONE = 0;
...@@ -55,6 +57,26 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -55,6 +57,26 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
protected MovementGroupContainer groupCon; protected MovementGroupContainer groupCon;
protected Random rand = Randoms.getRandom(AbstractGroupEncounter.class); protected Random rand = Randoms.getRandom(AbstractGroupEncounter.class);
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public AbstractGroupEncounter(boolean enableGroupEncounters, double groupEncounterMeetingDistance, long groupReencounterWaitTime) {
if(enableGroupEncounters) {
if (groupEncounterMeetingDistance < 0) {
throw new ConfigurationException(
"AbstractGroupEncounter: Variable groupEncounterMeetingDistance must be >= 0!");
}
if(groupReencounterWaitTime < 0) {
throw new ConfigurationException(
"AbstractGroupEncounter: Variable groupReencounterWaitTime must be >= 0!");
}
}
this.enableGroupEncounters = enableGroupEncounters;
this.groupEncounterMeetingDistance = groupEncounterMeetingDistance;
this.groupReencounterWaitTime = groupReencounterWaitTime;
}
@Override @Override
public void initialize(SocialGroupMovementModel movementModel) { public void initialize(SocialGroupMovementModel movementModel) {
groupCon = MovementGroupContainer.getInstance(); groupCon = MovementGroupContainer.getInstance();
...@@ -65,18 +87,30 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -65,18 +87,30 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
} }
public Set<SocialMovementGroup[]> getEncounteringGroups() { public Set<SocialMovementGroup[]> getEncounteringGroups() {
if(!enableGroupEncounters)
return null;
Set<SocialMovementGroup[]> encounteringGroups = new LinkedHashSet<>(); Set<SocialMovementGroup[]> encounteringGroups = new LinkedHashSet<>();
Set<SocialMovementGroup> alreadyProcessed = new LinkedHashSet<>(); Set<SocialMovementGroup> alreadyProcessed = new LinkedHashSet<>();
if(enableGroupEncounters) { Set<SocialMovementGroup> allGroups = groupCon.getGroups();
Set<SocialMovementGroup> allGroups = groupCon.getGroups(); for(SocialMovementGroup group1 : allGroups) {
for(SocialMovementGroup group1 : allGroups) { for(SocialMovementGroup group2 : allGroups) {
for(SocialMovementGroup group2 : allGroups) { if(group1 != group2) {
if(group1 != group2) { if(!(alreadyProcessed.contains(group1) && alreadyProcessed.contains(group2))) {
if(!(alreadyProcessed.contains(group1) && alreadyProcessed.contains(group2))) { if(getDistanceBetweenGroups(group1, group2) <= groupEncounterMeetingDistance) {
if(getDistanceBetweenGroups(group1, group2) <= meetingDistance) { SimLocationActuator g1Leader = group1.getLeader();
SimLocationActuator g1Leader = group1.getLeader(); if(!groupCon.getHasMerged().get(g1Leader)) {
if(!groupCon.getHasMerged().get(g1Leader)) { SocialMovementGroup[] groups = new SocialMovementGroup[2];
groups[0] = group1;
groups[1] = group2;
encounteringGroups.add(groups);
alreadyProcessed.add(group1);
alreadyProcessed.add(group2);
}
else {
if(waitedLongEnoughAfterMerging(g1Leader)) {
SocialMovementGroup[] groups = new SocialMovementGroup[2]; SocialMovementGroup[] groups = new SocialMovementGroup[2];
groups[0] = group1; groups[0] = group1;
groups[1] = group2; groups[1] = group2;
...@@ -85,23 +119,13 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -85,23 +119,13 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
alreadyProcessed.add(group1); alreadyProcessed.add(group1);
alreadyProcessed.add(group2); alreadyProcessed.add(group2);
} }
else {
if(waitedLongEnoughAfterMerging(g1Leader, groupCon.getWaitTime())) {
SocialMovementGroup[] groups = new SocialMovementGroup[2];
groups[0] = group1;
groups[1] = group2;
encounteringGroups.add(groups);
alreadyProcessed.add(group1);
alreadyProcessed.add(group2);
}
}
} }
} }
} }
} }
} }
} }
return encounteringGroups; return encounteringGroups;
} }
...@@ -180,22 +204,9 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -180,22 +204,9 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
* *
* @author Marcel Verst * @author Marcel Verst
*/ */
protected boolean waitedLongEnoughAfterMerging(SimLocationActuator host, long waitTime) { protected boolean waitedLongEnoughAfterMerging(SimLocationActuator host) {
return ((Time.getCurrentTime() - groupCon.getMergedAtTime().get(host)) >= waitTime); return ((Time.getCurrentTime() - groupCon.getMergedAtTime().get(host)) >= groupReencounterWaitTime);
} }
public void setMeetingDistance(double meetingDistance) {
if (meetingDistance < 0) {
throw new ConfigurationException(
"AbstractGroupEncounter: Variable meetingDistance must be >= 0!");
}
this.meetingDistance = meetingDistance;
}
public void setEnableGroupEncounters(boolean enableGroupEncounters) {
this.enableGroupEncounters = enableGroupEncounters;
}
/** /**
* Removes both groups on encounter. * Removes both groups on encounter.
...@@ -253,7 +264,7 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -253,7 +264,7 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
SocialMovementGroup large = getLargerGroup(group1, group2); SocialMovementGroup large = getLargerGroup(group1, group2);
SocialMovementGroup small = getSmallerGroup(group1, group2); SocialMovementGroup small = getSmallerGroup(group1, group2);
if((large.getGroupSize() - numberOfHostsToLeave) >= groupCon.getMinGroupSize()) { if((large.getGroupSize() - numberOfHostsToLeave) >= movementModel.getGroupFormingBehavior().getMinGroupSize()) {
groupCon.updateMergeVars(group1, group2); groupCon.updateMergeVars(group1, group2);
for(int i = 0; i < numberOfHostsToLeave; i++) { for(int i = 0; i < numberOfHostsToLeave; i++) {
......
...@@ -22,6 +22,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounte ...@@ -22,6 +22,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounte
import de.tud.kom.p2psim.api.scenario.ConfigurationException; import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
* This class checks if there is any pair of groups which encounter each other. Randomly decides * This class checks if there is any pair of groups which encounter each other. Randomly decides
...@@ -31,6 +32,15 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovement ...@@ -31,6 +32,15 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovement
* @version 1.0, 22.11.2018 * @version 1.0, 22.11.2018
*/ */
public class Dissolve extends AbstractGroupEncounter { public class Dissolve extends AbstractGroupEncounter {
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public Dissolve(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
//--- VARIABLES TO BE DECLARED IN CONFIG --- //--- VARIABLES TO BE DECLARED IN CONFIG ---
private double probabilityToDissolve; private double probabilityToDissolve;
//------------------------------------------ //------------------------------------------
......
...@@ -22,6 +22,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounte ...@@ -22,6 +22,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounte
import de.tud.kom.p2psim.api.scenario.ConfigurationException; import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
* This class checks if there is any pair of groups which encounter each other. Randomly decides * This class checks if there is any pair of groups which encounter each other. Randomly decides
...@@ -35,6 +36,14 @@ public class Fully extends AbstractGroupEncounter { ...@@ -35,6 +36,14 @@ public class Fully extends AbstractGroupEncounter {
private double probabilityToMergeFully; private double probabilityToMergeFully;
//------------------------------------------ //------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public Fully(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
/** /**
* {@inheritDoc} * {@inheritDoc}
* Lets both groups merge fully with a certain probability in case they encounter. * Lets both groups merge fully with a certain probability in case they encounter.
......
...@@ -23,6 +23,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounte ...@@ -23,6 +23,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounte
import de.tud.kom.p2psim.api.scenario.ConfigurationException; import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementModel; import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
* This class checks if there is any pair of groups which encounter each other. Randomly decides * This class checks if there is any pair of groups which encounter each other. Randomly decides
...@@ -37,6 +38,14 @@ public class FullyDissolve extends AbstractGroupEncounter { ...@@ -37,6 +38,14 @@ public class FullyDissolve extends AbstractGroupEncounter {
private double probabilityToDissolve; private double probabilityToDissolve;
//------------------------------------------ //------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public FullyDissolve(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
@Override @Override
public void initialize(SocialGroupMovementModel movementModel) { public void initialize(SocialGroupMovementModel movementModel) {
super.initialize(movementModel); super.initialize(movementModel);
......
...@@ -25,6 +25,7 @@ import de.tud.kom.p2psim.api.scenario.ConfigurationException; ...@@ -25,6 +25,7 @@ import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel; import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementModel; import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
...@@ -41,6 +42,14 @@ public class FullyPartially extends AbstractGroupEncounter { ...@@ -41,6 +42,14 @@ public class FullyPartially extends AbstractGroupEncounter {
private int numberOfHostsToLeave; private int numberOfHostsToLeave;
//------------------------------------------ //------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public FullyPartially(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
@Override @Override
public void initialize(SocialGroupMovementModel movementModel) { public void initialize(SocialGroupMovementModel movementModel) {
super.initialize(movementModel); super.initialize(movementModel);
......
...@@ -24,6 +24,7 @@ import de.tud.kom.p2psim.api.scenario.ConfigurationException; ...@@ -24,6 +24,7 @@ import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel; import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementModel; import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
...@@ -41,6 +42,14 @@ public class FullyPartiallyDissolve extends AbstractGroupEncounter { ...@@ -41,6 +42,14 @@ public class FullyPartiallyDissolve extends AbstractGroupEncounter {
private int numberOfHostsToLeave; private int numberOfHostsToLeave;
//------------------------------------------ //------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public FullyPartiallyDissolve(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
@Override @Override
public void initialize(SocialGroupMovementModel movementModel) { public void initialize(SocialGroupMovementModel movementModel) {
super.initialize(movementModel); super.initialize(movementModel);
......
...@@ -21,6 +21,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounte ...@@ -21,6 +21,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounte
import de.tud.kom.p2psim.api.scenario.ConfigurationException; import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
...@@ -36,6 +37,14 @@ public class Partially extends AbstractGroupEncounter { ...@@ -36,6 +37,14 @@ public class Partially extends AbstractGroupEncounter {
private int numberOfHostsToLeave; private int numberOfHostsToLeave;
//------------------------------------------ //------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public Partially(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
/** /**
* *
* Lets both groups merge partially with a certain probability in case they encounter. * Lets both groups merge partially with a certain probability in case they encounter.
......
...@@ -24,6 +24,7 @@ import de.tud.kom.p2psim.api.scenario.ConfigurationException; ...@@ -24,6 +24,7 @@ import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel; import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementModel; import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
* This class checks if there is any pair of groups which encounter each other. Randomly decides * This class checks if there is any pair of groups which encounter each other. Randomly decides
...@@ -39,6 +40,14 @@ public class PartiallyDissolve extends AbstractGroupEncounter { ...@@ -39,6 +40,14 @@ public class PartiallyDissolve extends AbstractGroupEncounter {
private int numberOfHostsToLeave; private int numberOfHostsToLeave;
//------------------------------------------ //------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public PartiallyDissolve(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
@Override @Override
public void initialize(SocialGroupMovementModel movementModel) { public void initialize(SocialGroupMovementModel movementModel) {
super.initialize(movementModel); super.initialize(movementModel);
......
...@@ -24,6 +24,7 @@ import de.tud.kom.p2psim.api.scenario.ConfigurationException; ...@@ -24,6 +24,7 @@ import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tud.kom.p2psim.impl.util.Tuple; import de.tud.kom.p2psim.impl.util.Tuple;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
...@@ -39,6 +40,14 @@ public class Wait extends AbstractGroupEncounter{ ...@@ -39,6 +40,14 @@ public class Wait extends AbstractGroupEncounter{
private long timeToWait; private long timeToWait;
//------------------------------------------ //------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public Wait(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
@Override @Override
public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) { public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) {
if(rand.nextDouble() <= probabilityToWait) { if(rand.nextDouble() <= probabilityToWait) {
......
...@@ -20,11 +20,12 @@ ...@@ -20,11 +20,12 @@
package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupforming; package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupforming;
import java.util.LinkedHashSet; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementModel; import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.BasicAttractionPoint; import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.BasicAttractionPoint;
...@@ -32,13 +33,16 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractio ...@@ -32,13 +33,16 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractio
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.hostcount.IAttractionPointHostCounter; import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.hostcount.IAttractionPointHostCounter;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.MovementGroupContainer; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.MovementGroupContainer;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy; import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.IAttractionAssigmentStrategy;
import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.util.Tuple; import de.tud.kom.p2psim.impl.util.Tuple;
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.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID; import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
* Abstract class implementation for implementing GroupFormingStrategies. * Abstract class implementation for implementing GroupFormingStrategies.
...@@ -54,18 +58,96 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -54,18 +58,96 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
// Holds time information of nodes for the groups (stay duration, last update) // Holds time information of nodes for the groups (stay duration, last update)
protected Map<INodeID, Tuple<Long,Long>> stayDuration; protected Map<INodeID, Tuple<Long,Long>> stayDuration;
// GROUP VARIABLES FROM CONFIGS // GROUP VARIABLES FROM CONFIGS
protected boolean enableGroups; protected boolean enableGroups;
protected int minGroupSize; protected int minGroupSize;
protected int maxGroupSize; protected int maxGroupSize;
protected double probabilityToJoin; protected double probabilityToJoin;
protected int maxNumberOfGroups; protected int maxNumberOfGroups;
protected long waitTime;
protected long setupTime; protected long groupRejoinWaitTime;
protected long groupFormationSetupDelay;
protected long groupFormationDelay;
protected IAttractionPointHostCounter hostCounter; protected IAttractionPointHostCounter hostCounter;
@XMLConfigurableConstructor({"enableGroups", "maxNumberOfGroups", "minGroupSize", "maxGroupSize", "probabilityToJoin", "groupFormationSetupDelay", "groupFormationDelay","groupRejoinWaitTime"})
public AbstractGroupForming(boolean enableGroups, int maxNumberOfGroups, int minGroupSize, int maxGroupSize, double probabilityToJoin, long groupFormationSetupDelay, long groupFormationDelay, long groupRejoinWaitTime) {
this.enableGroups = enableGroups;
if(enableGroups) {
if (probabilityToJoin < 0 || probabilityToJoin > 1.0) {
throw new ConfigurationException(
"GroupForming: probabilityToJoin must be between 0.0 and 1.0!");
}
if (maxNumberOfGroups <= 0) {
throw new ConfigurationException(
"GroupForming: maxNumberOfGroups must be >= 1!");
}
if (minGroupSize < 0) {
throw new ConfigurationException(
"GroupForming: minGroupSize must be >= 1!");
}
if (maxGroupSize < minGroupSize) {
throw new ConfigurationException(
"GroupForming: maxGroupSize cannot be bigger than minGroupSize!");
}
if (groupFormationSetupDelay <= 0) {
throw new ConfigurationException(
"GroupForming: groupFormationSetupDelay must be > 0!");
}
if (groupFormationDelay < 0) {
throw new ConfigurationException(
"GroupForming: groupFormationDelay must be >= 1!");
}
if (groupRejoinWaitTime < 0) {
throw new ConfigurationException(
"GroupForming: groupRejoinWaitTime must be >= 1!");
}
}
this.maxNumberOfGroups = maxNumberOfGroups;
this.minGroupSize = minGroupSize;
this.maxGroupSize = maxGroupSize;
this.probabilityToJoin = probabilityToJoin;
this.groupFormationSetupDelay = groupFormationSetupDelay;
this.groupFormationDelay = groupFormationDelay;
this.groupRejoinWaitTime = groupRejoinWaitTime;
}
@Override
public void initialize(SocialGroupMovementModel movementModel) {
this.movementModel = movementModel;
groupCon = MovementGroupContainer.getInstance();
// Initialize instances of other classes
this.hostCounter = movementModel.getAttractionPointHostCounter();
stayDuration = new LinkedHashMap<INodeID, Tuple<Long,Long>>();
for(SimLocationActuator host : movementModel.getAllLocationActuators()) {
stayDuration.put(host.getHost().getId(), new Tuple<Long, Long>(0L, Time.getCurrentTime()));
}
Event.scheduleWithDelay(groupFormationSetupDelay, new EventHandler() {
@Override
public void eventOccurred(Object content, int type) {
triggerGroupFormation();
}
}, null, 0);
}
protected abstract void triggerGroupFormation();
/** /**
* Creates a group with the given set of participants. * Creates a group with the given set of participants.
* *
...@@ -73,7 +155,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -73,7 +155,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
* *
* @author Marcel Verst * @author Marcel Verst
*/ */
public void createGroup(Set<SimLocationActuator> candidates) { protected void createGroup(Set<SimLocationActuator> candidates) {
SocialMovementGroup group = new SocialMovementGroup(candidates); SocialMovementGroup group = new SocialMovementGroup(candidates);
// Guarantee that the new destination of a group is not equal to the current AttractionPoint where the group is created // Guarantee that the new destination of a group is not equal to the current AttractionPoint where the group is created
// This would be the case if the destination of the group leader is the current position of the group. // This would be the case if the destination of the group leader is the current position of the group.
...@@ -91,17 +173,15 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -91,17 +173,15 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
destination.plus(offset); destination.plus(offset);
group.setDestination(destination); group.setDestination(destination);
setMP(group); setGroupMeetingPoint(group);
for(SimLocationActuator member : group.getMembers()) { for(SimLocationActuator member : group.getMembers()) {
member.setTargetAttractionPoint(poiDestination); member.setTargetAttractionPoint(poiDestination);
groupCon.addHasBeenInGroupEntry(member, true);
if(groupCon.getLeftGroupAtTime().containsKey(member)) { if(groupCon.getLeftGroupAtTime().containsKey(member)) {
// System.out.println(groupCon.getLeftGroupAtTime().get(member));
groupCon.removeLeftGroupAtTimeEntry(member); groupCon.removeLeftGroupAtTimeEntry(member);
} }
} }
groupCon.addGroup(group); groupCon.addGroup(group);
} }
...@@ -124,7 +204,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -124,7 +204,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
* *
* @author Marcel Verst * @author Marcel Verst
*/ */
public void removeGroup(SocialMovementGroup group) { protected void removeGroup(SocialMovementGroup group) {
groupCon.removeGroup(group); groupCon.removeGroup(group);
} }
...@@ -162,7 +242,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -162,7 +242,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
* *
* @author Marcel Verst * @author Marcel Verst
*/ */
public SimLocationActuator[] getHostsSortedByStayDurationAscending(Set<SimLocationActuator> candidates) { protected SimLocationActuator[] getHostsSortedByStayDurationAscending(Set<SimLocationActuator> candidates) {
int size = candidates.size(); int size = candidates.size();
SimLocationActuator[] youngestHostsSorted = new SimLocationActuator[size]; SimLocationActuator[] youngestHostsSorted = new SimLocationActuator[size];
...@@ -191,7 +271,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -191,7 +271,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
* *
* @author Marcel Verst * @author Marcel Verst
*/ */
public SimLocationActuator[] getHostsSortedByStayDurationDescending(Set<SimLocationActuator> candidates) { protected SimLocationActuator[] getHostsSortedByStayDurationDescending(Set<SimLocationActuator> candidates) {
int size = candidates.size(); int size = candidates.size();
SimLocationActuator[] oldestHostsSorted = new SimLocationActuator[size]; SimLocationActuator[] oldestHostsSorted = new SimLocationActuator[size];
...@@ -229,54 +309,6 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -229,54 +309,6 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
return apCandidate; return apCandidate;
} }
/**
* Checks for a set of candidates which candidate is able to join a group. Returns a subset of group candidates which
* are able to form a group with other candidates.
*
* @param Set<SimLocationActuator> Set of candidates.
* @return Set<SimLocationActuator> Set of group candidates.
*
* @author Marcel Verst
*/
public Set<SimLocationActuator> getGroupCandidates(Set<SimLocationActuator> candidates){
Set<SimLocationActuator> groupCandidates = new LinkedHashSet<>();
for(SimLocationActuator candidate : candidates) {
// Candidate can only be a group candidate if he is not yet in a group
if(!groupCon.isGroupMember(candidate)){
// Further check if the candidate even wants to join (based on probability)
if(wantsToJoin()) {
/*
* Candidate is not in a group yet and wants to be in a group:
* Check if the candidate has been in a group before.
*/
// If not, add the candidate to the set of group candidates.
if(!beenInGroup(candidate)) {
groupCandidates.add(candidate);
}
// Host has already been in a group. Check if the host has waited long enough to join another group.
else {
if(waitedLongEnough(candidate, Time.getCurrentTime() / 1000000)) {
groupCandidates.add(candidate);
}
}
}
else {
/*
* The host does not want to join. This decision is counted as an action which has the impact,
* that the host can not perform any other action until he waited for a specified amount of time.
* This procedure ensures that the host is not asked again every second if he wants to join a group.
*/
groupCon.addHasBeenInGroupEntry(candidate, true);
groupCon.addLeftGroupAtTimeEntry(candidate, Time.getCurrentTime() / 1000000);
}
}
}
return groupCandidates;
}
/** /**
* Checks if a host wants to join a group or not based on a given probability. * Checks if a host wants to join a group or not based on a given probability.
* Returns true if willing to join, false else. * Returns true if willing to join, false else.
...@@ -299,8 +331,14 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -299,8 +331,14 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
* *
* @author Marcel Verst * @author Marcel Verst
*/ */
protected boolean waitedLongEnough(SimLocationActuator host, long time) { protected boolean groupRejoinTimerExpired(SimLocationActuator host) {
return (getWaitingTime(host, time) >= waitTime); long t = getWaitingTime(host, Time.getCurrentTime());
System.out.println(host.getHost().getId() + " | Wait for:" +Time.getFormattedTime(t) + ", req is " + Time.getFormattedTime(groupRejoinWaitTime) );
boolean dec = t >= groupRejoinWaitTime;
return dec;
} }
/** /**
...@@ -312,7 +350,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -312,7 +350,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
* *
* @author Marcel Verst * @author Marcel Verst
*/ */
private long getWaitingTime(SimLocationActuator host, long currentTime) { protected long getWaitingTime(SimLocationActuator host, long currentTime) {
return currentTime - groupCon.getLeftGroupAtTime().get(host); return currentTime - groupCon.getLeftGroupAtTime().get(host);
} }
...@@ -325,10 +363,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -325,10 +363,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
* @author Marcel Verst * @author Marcel Verst
*/ */
protected boolean beenInGroup(SimLocationActuator host) { protected boolean beenInGroup(SimLocationActuator host) {
if(!groupCon.getHasBeenInAGroup().containsKey(host)) { return groupCon.getHostWasGroupMember(host);
groupCon.addHasBeenInGroupEntry(host, false);
}
return groupCon.getHasBeenInAGroup().get(host);
} }
/* /*
...@@ -344,7 +379,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -344,7 +379,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
* *
* @author Marcel Verst, Julian Zobel * @author Marcel Verst, Julian Zobel
*/ */
public void setMP(SocialMovementGroup group) { protected void setGroupMeetingPoint(SocialMovementGroup group) {
PositionVector leaderPos = group.getLeader().getRealPosition(); PositionVector leaderPos = group.getLeader().getRealPosition();
BasicAttractionPoint meetingPoint = new BasicAttractionPoint("Group Movement Meeting Point of Leader #"+group.getLeader().getHost().getId(), leaderPos); BasicAttractionPoint meetingPoint = new BasicAttractionPoint("Group Movement Meeting Point of Leader #"+group.getLeader().getHost().getId(), leaderPos);
...@@ -353,10 +388,19 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -353,10 +388,19 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
// Update target for all group members to meeting point // Update target for all group members to meeting point
for(SimLocationActuator participant : group.getMembers()) { for(SimLocationActuator participant : group.getMembers()) {
ITransitionStrategy transition = movementModel.getTransition(); IAttractionAssigmentStrategy transition = movementModel.getAttractionAssignmentStrategy();
transition.updateTargetAttractionPoint(participant, meetingPoint); transition.updateTargetAttractionPoint(participant, meetingPoint);
} }
} }
@Override
public int getMinGroupSize() {
return minGroupSize;
}
@Override
public int getMaxGroupSize() {
return maxGroupSize;
}
} }
...@@ -32,17 +32,17 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementMo ...@@ -32,17 +32,17 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementMo
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator; import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.MovementGroupContainer; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.MovementGroupContainer;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy; import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.IAttractionAssigmentStrategy;
import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
import de.tud.kom.p2psim.impl.util.Tuple; import de.tud.kom.p2psim.impl.util.Tuple;
import de.tudarmstadt.maki.simonstrator.api.Host; import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.Oracle; import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID; import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID;
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
* This class is responsible for creating or deleting groups. Therefore the amount of hosts in each POI * This class is responsible for creating or deleting groups. Therefore the amount of hosts in each POI
...@@ -54,142 +54,109 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; ...@@ -54,142 +54,109 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
* *
* *
* Updated the group forming to use the simulation time units instead of integer +1 counters. * Updated the group forming to use the simulation time units instead of integer +1 counters.
* Simplified code and bug fixes.
* *
* @author Julian Zobel * @author Julian Zobel
* * @version 1.1, 29.01.2020
*/ */
public class DefaultGroupForming extends AbstractGroupForming { public class DefaultGroupForming extends AbstractGroupForming {
private Map<SimLocationActuator, AttractionPoint> lastAPs;
private int nextGroupSize;
public void initialize(SocialGroupMovementModel movementModel) {
this.movementModel = movementModel; @XMLConfigurableConstructor({"enableGroups", "maxNumberOfGroups", "minGroupSize", "maxGroupSize", "probabilityToJoin", "groupFormationSetupDelay", "groupFormationDelay", "groupRejoinWaitTime"})
public DefaultGroupForming(boolean enableGroups, int maxNumberOfGroups, int minGroupSize, int maxGroupSize, double probabilityToJoin,
nextGroupSize = nextGroupSize(); long groupFormationSetupDelay, long groupFormationDelay, long groupRejoinWaitTime) {
lastAPs = new LinkedHashMap<>();
groupCon = MovementGroupContainer.getInstance();
groupCon.setWaitTime(waitTime);
groupCon.setMinGroupSize(minGroupSize);
groupCon.setMaxGroupSize(maxGroupSize);
// Initialize instances of other classes
this.hostCounter = movementModel.getAttractionPointHostCounter();
stayDuration = new LinkedHashMap<INodeID, Tuple<Long,Long>>(); super(enableGroups, maxNumberOfGroups, minGroupSize, maxGroupSize,
probabilityToJoin, groupFormationSetupDelay, groupFormationDelay,
for(SimLocationActuator host : movementModel.getAllLocationActuators()) { groupRejoinWaitTime);
groupCon.addHasBeenInGroupEntry(host, false);
lastAPs.put(host, host.getCurrentTargetAttractionPoint());
stayDuration.put(host.getHost().getId(), new Tuple<Long, Long>(0L, Time.getCurrentTime()));
}
} }
/* public void manageGroups() {
* =====================================================================================================
* === GROUP HANDLING
* =====================================================================================================
*/
/**
* {@inheritDoc}
*/
public void manageGroups() {
long currentTime = Time.getCurrentTime();
if(enableGroups && (currentTime >= setupTime) && probabilityToJoin > 0.0) { // group forming may be deactivated
runGroupBuildingProcess(); if(!enableGroups || probabilityToJoin == 0) {
runGroupDeletionProcess(); return;
} }
// setup delay before forming the first group...
if(Time.getCurrentTime() <= groupFormationSetupDelay) {
return;
}
runGroupDeletionProcess();
} }
/* /*
* ===================================================================================================== * =====================================================================================================
* === GROUP BUILDING PROCESS * === GROUP BUILDING PROCESS
* ===================================================================================================== * =====================================================================================================
*/ */
/** protected void triggerGroupFormation() {
* {@inheritDoc}
*/
public void runGroupBuildingProcess() {
updateStayDuration(); updateStayDuration();
int groupsToCreate = maxNumberOfGroups - groupCon.getGroups().size(); int groupsToCreate = maxNumberOfGroups - groupCon.getGroups().size();
for(int i = 0; i < groupsToCreate; i++) { System.out.println("group trigger " + groupsToCreate);
for(int g = 0; g < groupsToCreate; g++) {
// Get attractionPoint with highest amount of hosts // Get attractionPoint with highest amount of hosts
hostCounter.updateHostCount(); hostCounter.updateHostCount();
AttractionPoint apCandidate = getAttractionPointWithOldestHost(); AttractionPoint apCandidate = getRandomAttractionPoint();
if(apCandidate == null) { if(apCandidate == null) {
break; break;
} }
int numberOfHostsInAttractionPoint = hostCounter.getHostCountOfAttractionPoint(apCandidate); int numberOfHostsInAttractionPoint = hostCounter.getHostCountOfAttractionPoint(apCandidate);
int groupSize = Math.min(Math.max(minGroupSize, rand.nextInt(maxGroupSize)), numberOfHostsInAttractionPoint);
// Adapt nextGroupSize to AP conditions
while(numberOfHostsInAttractionPoint < nextGroupSize && nextGroupSize >= 2) { if(groupSize > numberOfHostsInAttractionPoint) {
nextGroupSize--; throw new UnsupportedOperationException("Math Genius you are not!");
} }
if(numberOfHostsInAttractionPoint >= nextGroupSize) {
Set<SimLocationActuator> hostsOfPoi = hostCounter.getHostsOfAttractionPoint(apCandidate);
SimLocationActuator[] hostsSorted = getHostsSortedByStayDurationDescending(hostsOfPoi);
Set<SimLocationActuator> groupCandidates = new LinkedHashSet<>();
if(hostsSorted.length > 0) { Set<SimLocationActuator> groupCandidates = new LinkedHashSet<>();
for(int tmp = 0; tmp <= nextGroupSize; tmp++) {
for(int index = 0; index < hostsSorted.length; index++) { Set<SimLocationActuator> hostsOfPoi = hostCounter.getHostsOfAttractionPoint(apCandidate);
SimLocationActuator hostToAdd = hostsSorted[index];
if(hostToAdd != null) { for (SimLocationActuator m : hostsOfPoi) {
if(!groupCandidates.contains(hostToAdd)) { if(groupCandidates.contains(m)) {
if(!movementModel.getSingleHosts().contains(hostToAdd)) { System.err.println("Cannot be???");
if(wantsToJoin()) { continue;
if(!beenInGroup(hostToAdd)) {
groupCandidates.add(hostToAdd);
break;
}
// Host has already been in a group. Check if the host has waited long enough to join another group.
else {
if(waitedLongEnough(hostToAdd, Time.getCurrentTime())) {
groupCandidates.add(hostToAdd);
break;
}
}
}
else {
/*
* The host does not want to join. This decision is counted as an action which has the impact,
* that the host can not perform any other action until he waited for a specified amount of time.
* This procedure ensures that the host is not asked again every second if he wants to join a group.
*/
groupCon.addHasBeenInGroupEntry(hostToAdd, true);
groupCon.addLeftGroupAtTimeEntry(hostToAdd, Time.getCurrentTime());
}
}
}
}
}
}
} }
if(groupCandidates.isEmpty() || groupCandidates == null) { if(movementModel.getSingleHosts().contains(m)) {
break; System.out.println("ACM Single Host is not added");
continue;
} }
while(groupCandidates.size() < nextGroupSize && nextGroupSize >= 2) { if(groupCon.isGroupMember(m)) {
nextGroupSize--; System.out.println("No members allowed");
continue;
} }
if(groupCandidates.size() >= nextGroupSize) { if(wantsToJoin()) {
for(SimLocationActuator candidate : groupCandidates) { if(!beenInGroup(m) || groupRejoinTimerExpired(m)) {
INodeID id = candidate.getHost().getId(); groupCandidates.add(m);
stayDuration.put(id, new Tuple<Long, Long>(0L, Time.getCurrentTime())); }
} }
createGroup(groupCandidates);
nextGroupSize = nextGroupSize(); if(groupCandidates.size() == groupSize) {
System.out.println("Group full, now go!");
break;
} }
}
if(groupCandidates.isEmpty() || groupCandidates == null) {
System.out.println("--no cands");
break;
}
System.out.println("Group creation: " + groupCandidates.size() + " => " + apCandidate);
for(SimLocationActuator candidate : groupCandidates) {
INodeID id = candidate.getHost().getId();
stayDuration.put(id, new Tuple<Long, Long>(0L, Time.getCurrentTime())); // FIXME why?
} }
createGroup(groupCandidates);
} }
} }
...@@ -202,7 +169,7 @@ public class DefaultGroupForming extends AbstractGroupForming { ...@@ -202,7 +169,7 @@ public class DefaultGroupForming extends AbstractGroupForming {
public void runGroupDeletionProcess() { public void runGroupDeletionProcess() {
LocalMovementStrategy movementStrategy = movementModel.getMovementStrategy(); LocalMovementStrategy movementStrategy = movementModel.getMovementStrategy();
ITransitionStrategy transition = movementModel.getTransition(); IAttractionAssigmentStrategy transition = movementModel.getAttractionAssignmentStrategy();
Set<SocialMovementGroup> groupsToRemove = new LinkedHashSet<>(); Set<SocialMovementGroup> groupsToRemove = new LinkedHashSet<>();
...@@ -223,6 +190,15 @@ public class DefaultGroupForming extends AbstractGroupForming { ...@@ -223,6 +190,15 @@ public class DefaultGroupForming extends AbstractGroupForming {
for(SocialMovementGroup group : groupsToRemove) { for(SocialMovementGroup group : groupsToRemove) {
removeGroup(group); removeGroup(group);
System.out.println("Removed group, schedule new formation in " + groupFormationDelay);
Event.scheduleWithDelay(groupFormationDelay, new EventHandler() {
@Override
public void eventOccurred(Object content, int type) {
triggerGroupFormation();
}
}, null, 0);
} }
} }
...@@ -235,140 +211,34 @@ public class DefaultGroupForming extends AbstractGroupForming { ...@@ -235,140 +211,34 @@ public class DefaultGroupForming extends AbstractGroupForming {
* Updates the stayDuration of each Host * Updates the stayDuration of each Host
*/ */
public void updateStayDuration() { public void updateStayDuration() {
for(Host host : Oracle.getAllHosts()) { for(SimLocationActuator component : movementModel.getAllLocationActuators()) {
try { INodeID id = component.getHost().getId();
SimLocationActuator component = host.getComponent(SimLocationActuator.class);
INodeID id = component.getHost().getId(); // Check if host is in an AP area
boolean isInAp = false;
// Check if host is in an AP area for(AttractionPoint ap : IAttractionGenerator.attractionPoints) {
boolean isInAp = false; Location hostLocation = component.getLastLocation();
for(AttractionPoint ap : IAttractionGenerator.attractionPoints) { if(ap.distanceTo(hostLocation) <= ap.getRadius()) {
Location hostLocation = component.getLastLocation(); isInAp = true;
if(ap.distanceTo(hostLocation) <= ap.getRadius()) {
isInAp = true;
}
}
// In AP, increase stayDuration
if(isInAp) {
Tuple<Long, Long> timeInfo = stayDuration.get(id);
long delta = Time.getCurrentTime() - timeInfo.getB();
// update information (increase overall stay duration and set current time as update time)
stayDuration.put(id, new Tuple<Long, Long>(timeInfo.getA() + delta, Time.getCurrentTime()));
}
// Not in AP, reset stayDuration
else {
stayDuration.put(id, new Tuple<Long, Long>(0L, Time.getCurrentTime()));
} }
} catch (ComponentNotAvailableException e) {
e.printStackTrace();
} }
}
}
/*
private Set<SimLocationActuator> getRandomSubSet(Set<SimLocationActuator> candidates){
Set<SimLocationActuator> candidatesSubSet = new LinkedHashSet<>();
for(int i = 0; i < nextGroupSize; i++) {
SimLocationActuator randomCandidate = getRandomCandidate(candidates);
candidatesSubSet.add(randomCandidate);
}
return candidatesSubSet;
}
*/
/* // In AP, increase stayDuration
private SimLocationActuator getRandomCandidate(Set<SimLocationActuator> candidates) { if(isInAp) {
int size = candidates.size();
int item = rand.nextInt(size-1); Tuple<Long, Long> timeInfo = stayDuration.get(id);
int i = 0; long delta = Time.getCurrentTime() - timeInfo.getB();
SimLocationActuator actuator = null;
for(SimLocationActuator host : candidates) { // update information (increase overall stay duration and set current time as update time)
if(i == item) { stayDuration.put(id, new Tuple<Long, Long>(timeInfo.getA() + delta, Time.getCurrentTime()));
actuator = host; }
// Not in AP, reset stayDuration
else {
stayDuration.put(id, new Tuple<Long, Long>(0L, Time.getCurrentTime()));
} }
i++;
}
candidates.remove(actuator);
return actuator;
}
*/
/**
* Returns the next randomly generated number of Hosts required to form a group.
*
* @return Integer
*
* @author Marcel Verst
*/
private int nextGroupSize() {
int nextGroupSize = rand.nextInt(maxGroupSize+1);
if(nextGroupSize < minGroupSize) {
nextGroupSize = minGroupSize;
}
return nextGroupSize;
}
/*
* =====================================================================================================
* === GETTERS AND SETTERS
* =====================================================================================================
*/
public void setEnableGroups(boolean enableGroups) {
this.enableGroups = enableGroups;
}
public void setMinGroupSize(int minGroupSize) {
if (minGroupSize < 0) {
throw new ConfigurationException(
"minGroupSize should be greater or equal than 3!");
}
this.minGroupSize = minGroupSize;
}
public void setMaxGroupSize(int maxGroupSize) {
if (maxGroupSize < 0) {
throw new ConfigurationException(
"maxGroupSize should be greater or equal than 3!");
}
this.maxGroupSize = maxGroupSize;
}
public void setMaxNumberOfGroups(int maxNumberOfGroups) {
if (maxNumberOfGroups < 0) {
throw new ConfigurationException(
"maxNumberOfGroups should be greater or equal than 0!");
}
this.maxNumberOfGroups = maxNumberOfGroups;
}
public void setProbabilityToJoin(double probabilityToJoin) {
if (probabilityToJoin < 0 || probabilityToJoin > 1.0) {
throw new ConfigurationException(
"probabilityToJoin should be between 0.0 and 1.0!");
}
this.probabilityToJoin = probabilityToJoin;
}
public void setWaitTime(long waitTime) {
if (waitTime < 0) {
throw new ConfigurationException(
"waitTime should be greater or equal than 0!");
}
this.waitTime = waitTime;
}
public void setSetupTime(long setupTime) {
if (setupTime < 0) {
throw new ConfigurationException(
"setupTime should be greater or equal than 0!");
} }
this.setupTime = setupTime;
} }
public double getProbabilityToJoin() {
return probabilityToJoin;
}
} }
...@@ -47,17 +47,7 @@ public interface IGroupFormingBehavior { ...@@ -47,17 +47,7 @@ public interface IGroupFormingBehavior {
* *
* @author Marcel Verst * @author Marcel Verst
*/ */
void manageGroups(); void manageGroups();
/**
* Checks for each POI how many hosts are currently present. Selects out of all present hosts per POI a set of group
* candidates which is then used to create a group.
*
* @param SimLocationActuator The current host.
*
* @author Marcel Verst
*/
void runGroupBuildingProcess();
/** /**
* Checks if the given host is a leader and reached the its destination. If the destination is reached, * Checks if the given host is a leader and reached the its destination. If the destination is reached,
...@@ -69,5 +59,7 @@ public interface IGroupFormingBehavior { ...@@ -69,5 +59,7 @@ public interface IGroupFormingBehavior {
* @author Marcel Verst * @author Marcel Verst
*/ */
void runGroupDeletionProcess(); void runGroupDeletionProcess();
double getProbabilityToJoin();
public int getMinGroupSize();
public int getMaxGroupSize();
} }
\ No newline at end of file
...@@ -20,29 +20,24 @@ ...@@ -20,29 +20,24 @@
package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition; package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; 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.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
* Abstract base class for Transition Strategies ({@link ITransitionStrategy}s) using {@link AttractionPoint}s. * Abstract base class for Transition Strategies ({@link IAttractionAssigmentStrategy}s) using {@link AttractionPoint}s.
* *
* @author Julian Zobel * @author Julian Zobel
* @version 1.0, 23.01.2019 * @version 1.0, 23.01.2019
*/ */
public abstract class AbstractAttractionBasedTransitionStrategy implements ITransitionStrategy { public abstract class AbstractAttractionBasedTransitionStrategy implements IAttractionAssigmentStrategy {
protected Random rnd = Randoms.getRandom(AbstractAttractionBasedTransitionStrategy.class); protected Random rnd = Randoms.getRandom(AbstractAttractionBasedTransitionStrategy.class);
...@@ -109,4 +104,28 @@ public abstract class AbstractAttractionBasedTransitionStrategy implements ITran ...@@ -109,4 +104,28 @@ public abstract class AbstractAttractionBasedTransitionStrategy implements ITran
protected long getPauseTime(AttractionPoint attractionPoint) { protected long getPauseTime(AttractionPoint attractionPoint) {
return getRandomUniformDistributionPauseTime(attractionPoint); return getRandomUniformDistributionPauseTime(attractionPoint);
} }
protected AttractionPoint getNewAttractionPointAssignment(SimLocationActuator component) {
double score = rnd.nextDouble();
List<AttractionPoint> candidates = new LinkedList<>();
for (AttractionPoint ap : IAttractionGenerator.attractionPoints) {
if(ap == null) {
continue;
}
if (ap.getWeight() >= score) {
if(lastAssignments.get(component) == null || !ap.equals(lastAssignments.get(component))) {
candidates.add(ap);
}
}
}
if (candidates.isEmpty()) {
candidates.addAll(IAttractionGenerator.attractionPoints);
}
AttractionPoint assignment = candidates.get(rnd.nextInt(candidates.size()));
return 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