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

wip

parent 6ccbc90e
......@@ -837,6 +837,10 @@ public class DefaultConfigurator implements Configurator {
public static <T extends Number> T parseNumber(String value,
Class<T> targetClass) {
assert value != null;
if(value == null)
System.out.println("");
String number = value;
double factor = 1;
// Time
......
......@@ -105,7 +105,6 @@ public class DefaultTopologyComponent extends AbstractTopologyComponent {
public void setTargetAttractionPoint(AttractionPoint targetAttractionPoint)
throws UnsupportedOperationException {
movementModel.changeTargetLocation(this, targetAttractionPoint);
// NodeDebugMonitor.update(this.getClass(), getHost().getId(), "Target Location", targetAttractionPoint);
}
@Override
......
......@@ -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.movement.modularosm.attraction.IAttractionGenerator;
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.ITransitionStrategy.AttractionAssignmentListener;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.IAttractionAssigmentStrategy;
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.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.util.Either;
......@@ -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
* attraction points.
* <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.
* 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
protected PositionVector worldDimensions;
protected ITransitionStrategy transition;
protected IAttractionAssigmentStrategy attractionAssigment;
protected IAttractionGenerator attractionGenerator;
......@@ -136,9 +136,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
public void initialize() {
if (!initialized) {
System.out.println("init modular movement model");
if (modelVisualisation == null) {
modelVisualisation = new ModularMovementModelViz(this);
}
......@@ -161,12 +159,12 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
localMovementStrategy
.setScaleFactor(timeBetweenMoveOperation / (double) Time.SECOND);
transition.addAttractionAssignmentListener(this);
attractionAssigment.addAttractionAssignmentListener(this);
// This adds the mobile hosts (smartphones/users) to the transition
// strategy
for (SimLocationActuator ms : moveableHosts) {
transition.addComponent(ms);
attractionAssigment.addComponent(ms);
}
setTimeBetweenMoveOperations(timeBetweenMoveOperation);
......@@ -189,7 +187,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
@Override
public void changeTargetLocation(SimLocationActuator actuator, AttractionPoint ap) {
transition.updateTargetAttractionPoint(actuator, ap);
attractionAssigment.updateTargetAttractionPoint(actuator, ap);
}
private void checkConfiguration() {
......@@ -197,7 +195,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
throw new ConfigurationException(
"LocalMovementStrategy is missing in ModularMovementModel!");
}
if (transition == null) {
if (attractionAssigment == null) {
throw new ConfigurationException(
"TransitionStrategy is missing in ModularMovementModel!");
}
......@@ -218,6 +216,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
@Override
public void updatedAttractionAssignment(SimLocationActuator component,
AttractionPoint newAssignment) {
/*
* Use this method to calculate the offset and target location for a
* host.
......@@ -227,7 +226,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
/*
* 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;
do {
......@@ -238,13 +237,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
rand.nextGaussian() * apRadius / 3);
destination.add(offset);
// Check constraints
if (destination.getX() < 0.0
|| destination.getX() > Binder
.getComponentOrNull(Topology.class)
.getWorldDimensions().getX() || destination.getY() < 0.0
|| destination.getY() > Binder
.getComponentOrNull(Topology.class)
.getWorldDimensions().getY()) {
if (!checkBoundaries(destination)) {
destination = null;
if (tries > 100) {
throw new AssertionError("Unable to find a valid target destination within <100 tries.");
......@@ -252,7 +245,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
}
tries++;
} while (destination == null);
currentTargets.put(component, destination);
}
......@@ -279,10 +272,12 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
if (either.hasLeft()) {
ms.updateCurrentLocation(either.getLeft());
checkBoundaries(ms);
if(!checkBoundaries(ms.getRealPosition())) {
System.err.println("Modular Movement Model: Host moved outside of simulated area!");
}
}
else {
transition.reachedAttractionPoint(ms, ms.getCurrentTargetAttractionPoint());
attractionAssigment.reachedAttractionPoint(ms, ms.getCurrentTargetAttractionPoint());
}
}
......@@ -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.
* Enable asserts to get the notification
*
* @param SimLocationActuator The host to be checked
*/
public void checkBoundaries(SimLocationActuator ms) {
assert ms.getRealPosition().getX() >= 0.0
&& ms.getRealPosition().getX() <= Binder
.getComponentOrNull(Topology.class)
.getWorldDimensions().getX();
assert ms.getRealPosition().getY() >= 0.0
&& ms.getRealPosition().getY() <= Binder
.getComponentOrNull(Topology.class)
.getWorldDimensions().getY();
public boolean checkBoundaries(PositionVector position) {
if(position.getX() >= 0.0
&& position.getX() <= Binder.getComponentOrNull(Topology.class).getWorldDimensions().getX()
&& position.getY() >= 0.0
&& position.getY() <= Binder.getComponentOrNull(Topology.class).getWorldDimensions().getY())
return true;
else
return false;
}
@Override
......@@ -353,12 +346,12 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
this.localMovementStrategy = localMovementStrategy;
}
public void setITransitionStrategy(ITransitionStrategy transition) {
public void setITransitionStrategy(IAttractionAssigmentStrategy transition) {
if (transition == null) {
throw new ConfigurationException(
"TransitionStrategy is missing in ModularMovementModel!");
}
this.transition = transition;
this.attractionAssigment = transition;
}
public void setIMapVisualization(IMapVisualization mapVisualization) {
......@@ -373,7 +366,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
@Override
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;
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.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.util.Either;
import de.tudarmstadt.maki.simonstrator.api.Binder;
......@@ -18,9 +18,9 @@ import java.util.List;
/**
* 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
* 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>
*
* Originally the whole movement system within the simonstrator platform was not intended to be manipulable
......@@ -38,7 +38,7 @@ import java.util.List;
* (besides selecting this model in your config) call the {@link #setMovementType(SimLocationActuator, String)}
* 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
* 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)}
......@@ -54,12 +54,12 @@ import java.util.List;
public class ModularMultiTypeMovementModel extends ModularMovementModel
{
private HashMap<SimLocationActuator, String> movementTypes;
private HashMap<SimLocationActuator, ITransitionStrategy> transitions;
private HashMap<Class, ITransitionStrategy> supportedTransitions;
private HashMap<SimLocationActuator, IAttractionAssigmentStrategy> transitions;
private HashMap<Class, IAttractionAssigmentStrategy> supportedTransitions;
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;
......@@ -77,7 +77,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
super.initialize();
suppressListenerNotify = true;
for(ITransitionStrategy strategy : supportedTransitions.values())
for(IAttractionAssigmentStrategy strategy : supportedTransitions.values())
{
strategy.addAttractionAssignmentListener(this);
for (SimLocationActuator ms : moveableHosts) {
......@@ -118,7 +118,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
transitions.get(ms).reachedAttractionPoint(ms, ms.getCurrentTargetAttractionPoint());
}
else {
transition.reachedAttractionPoint(ms, ms.getCurrentTargetAttractionPoint());
attractionAssigment.reachedAttractionPoint(ms, ms.getCurrentTargetAttractionPoint());
}
movementListeners.forEach(l -> l.onTransition(ms));
}
......@@ -150,7 +150,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
* @param ms the component
* @return the current transition strategy
*/
public ITransitionStrategy getTransitionForComponent(SimLocationActuator ms)
public IAttractionAssigmentStrategy getTransitionForComponent(SimLocationActuator ms)
{
return transitions.get(ms);
}
......@@ -160,9 +160,9 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
* @param strategy The class of the strategy which should be returned.
* @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)
{
throw new UnsupportedOperationException(
......@@ -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.
* @param ms The SimLocationActuator
* @param strategy the strategy to use
......@@ -188,9 +188,9 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
* @param ms The SimLocationActuator
* @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));
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()));
......@@ -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
*/
public void returnToDefaultTransition(SimLocationActuator ms)
......@@ -224,19 +224,19 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
@Override
public void changeTargetLocation(SimLocationActuator actuator, AttractionPoint ap) {
if(transitions.containsKey(actuator)) transitions.get(actuator).updateTargetAttractionPoint(actuator, ap);
else transition.updateTargetAttractionPoint(actuator, ap);
else attractionAssigment.updateTargetAttractionPoint(actuator, ap);
}
@Override
public void setITransitionStrategy(ITransitionStrategy transition) {
if(supportedTransitions.size() == 0) this.transition = transition;
public void setITransitionStrategy(IAttractionAssigmentStrategy transition) {
if(supportedTransitions.size() == 0) this.attractionAssigment = transition;
supportedTransitions.put(transition.getClass(), transition);
}
@Override
public AttractionPoint getTargetLocation(SimLocationActuator actuator) {
if(transitions.containsKey(actuator)) return transitions.get(actuator).getAssignment(actuator);
else return transition.getAssignment(actuator);
else return attractionAssigment.getAssignment(actuator);
}
@Override
......
......@@ -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.groupforming.IGroupFormingBehavior;
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.ITransitionStrategy.AttractionAssignmentListener;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.IAttractionAssigmentStrategy;
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.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.util.Either;
......@@ -74,9 +74,6 @@ public class SocialGroupMovementModel extends ModularMovementModel {
public void initialize() {
if (!initialized) {
System.out.println("init social group movement");
groupContainer = MovementGroupContainer.getInstance();
attractionPointHostCounter.initialize(this);
groupFormingBehavior.initialize(this);
......@@ -124,9 +121,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
* @author Marcel Verst
*/
@Override
protected void move() {
System.out.println("social group : move");
protected void move() {
// Update the number of hosts within each attraction point.
attractionPointHostCounter.updateHostCount();
......@@ -162,8 +157,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
*/
protected void doGroupMovement(SimLocationActuator host, PositionVector destination) {
// Single Host Movement
if(singleHosts.contains(host) && !groupContainer.isGroupMember(host)) {
System.out.println("local movement");
if(singleHosts.contains(host) || !groupContainer.isGroupMember(host)) {
doLocalMovement(host, destination);
}
......@@ -178,7 +172,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
group.setMeetingPoint(currDest);
for(SimLocationActuator participant : group.getMembers()) {
transition.updateTargetAttractionPoint(participant, currAp);
attractionAssigment.updateTargetAttractionPoint(participant, currAp);
}
}
}
......@@ -191,7 +185,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
// MP reached. Move to destination.
else {
if(groupContainer.isLeader(host)) {
if(!groupContainer.isWaiting(groupContainer.getGroupOfHost(host))) {
if(!groupContainer.isWaiting(groupContainer.getGroupOfHost(host))) {
doLocalMovement(host, destination);
}
}
......@@ -241,7 +235,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
counter++;
}
}
if(counter == participants.size()) {
if(counter == participants.size()) {
return true;
}
return false;
......@@ -262,7 +256,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
// 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
double distance = host.getLastLocation().distanceTo(currMP);
if(distance <= 2) {
if(distance <= 2) {
return true;
}
return false;
......@@ -284,17 +278,24 @@ public class SocialGroupMovementModel extends ModularMovementModel {
*/
private void followLeader(SimLocationActuator host) {
SimLocationActuator leader = groupContainer.getGroupOfHost(host).getLeader();
if(leader.getCurrentTargetAttractionPoint() == null) {
System.out.println();
}
AttractionPoint leaderDestination = leader.getCurrentTargetAttractionPoint();
AttractionPoint hostDestination = host.getCurrentTargetAttractionPoint();
// Update target attraction point if not already done
if(hostDestination != leaderDestination) {
transition.updateTargetAttractionPoint(host, leaderDestination);
if(leaderDestination != null && hostDestination != leaderDestination) {
attractionAssigment.updateTargetAttractionPoint(host, leaderDestination);
}
int o = 10;
// Assign small offset to the host depending on the leaders position.
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);
// Update location of host, which will be around the leaders location.
......@@ -332,8 +333,12 @@ public class SocialGroupMovementModel extends ModularMovementModel {
this.attractionPointHostCounter = attractionPointHostCounter;
}
public ITransitionStrategy getTransition() {
return transition;
public IAttractionAssigmentStrategy getAttractionAssignmentStrategy() {
return attractionAssigment;
}
public IGroupFormingBehavior getGroupFormingBehavior() {
return groupFormingBehavior;
}
public LocalMovementStrategy getMovementStrategy() {
......
......@@ -42,22 +42,15 @@ public class MovementGroupContainer {
// Mappings
private Map<SimLocationActuator, Long> leftGroupAtTime;
private Map<SimLocationActuator, Boolean> hasBeenInAGroup;
private Map<SimLocationActuator, Boolean> hasMerged;
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
public Map<SocialMovementGroup, Tuple<Long, Long>> waitingGroups;
private MovementGroupContainer() {
groups = new LinkedHashSet<>();
leftGroupAtTime = new LinkedHashMap<>();
hasBeenInAGroup = new LinkedHashMap<>();
leftGroupAtTime = new LinkedHashMap<>();
hasMerged = new LinkedHashMap<>();
mergedAtTime = new LinkedHashMap<>();
waitingGroups = new LinkedHashMap<SocialMovementGroup, Tuple<Long,Long>>();
......@@ -138,17 +131,7 @@ public class MovementGroupContainer {
if(leftGroupAtTime.containsKey(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) {
hasMerged.put(host, value);
......@@ -299,6 +282,10 @@ public class MovementGroupContainer {
this.groups = groups;
}
public boolean getHostWasGroupMember(SimLocationActuator host) {
return this.leftGroupAtTime.containsKey(host);
}
public Map<SimLocationActuator, Long> getLeftGroupAtTime() {
return leftGroupAtTime;
}
......@@ -307,22 +294,6 @@ public class MovementGroupContainer {
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() {
return hasMerged;
}
......@@ -338,20 +309,4 @@ public class MovementGroupContainer {
public void setMergedAtTime(Map<SimLocationActuator, Long> 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 {
*/
public SimLocationActuator getRandomMember() {
if(members.size() >= 1) {
if(members.size() > 1) {
Random rand = Randoms.getRandom(SocialMovementGroup.class);
int item = rand.nextInt(members.size() - 1);
int i = 0;
......@@ -106,6 +106,9 @@ public class SocialMovementGroup {
i++;
}
}
else if(members.size() == 1) {
return members.iterator().next();
}
return null;
}
......
......@@ -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.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
* This class contains methods used by all encounter strategies.
......@@ -43,7 +44,8 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
//--- COMMON VARIABLES TO BE DECLARED IN CONFIG ---
protected boolean enableGroupEncounters;
protected double meetingDistance;
protected double groupEncounterMeetingDistance;
protected long groupReencounterWaitTime;
//-------------------------------------------------
protected final int DECISION_NONE = 0;
......@@ -55,6 +57,26 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
protected MovementGroupContainer groupCon;
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
public void initialize(SocialGroupMovementModel movementModel) {
groupCon = MovementGroupContainer.getInstance();
......@@ -65,18 +87,30 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
}
public Set<SocialMovementGroup[]> getEncounteringGroups() {
if(!enableGroupEncounters)
return null;
Set<SocialMovementGroup[]> encounteringGroups = new LinkedHashSet<>();
Set<SocialMovementGroup> alreadyProcessed = new LinkedHashSet<>();
if(enableGroupEncounters) {
Set<SocialMovementGroup> allGroups = groupCon.getGroups();
for(SocialMovementGroup group1 : allGroups) {
for(SocialMovementGroup group2 : allGroups) {
if(group1 != group2) {
if(!(alreadyProcessed.contains(group1) && alreadyProcessed.contains(group2))) {
if(getDistanceBetweenGroups(group1, group2) <= meetingDistance) {
SimLocationActuator g1Leader = group1.getLeader();
if(!groupCon.getHasMerged().get(g1Leader)) {
Set<SocialMovementGroup> allGroups = groupCon.getGroups();
for(SocialMovementGroup group1 : allGroups) {
for(SocialMovementGroup group2 : allGroups) {
if(group1 != group2) {
if(!(alreadyProcessed.contains(group1) && alreadyProcessed.contains(group2))) {
if(getDistanceBetweenGroups(group1, group2) <= groupEncounterMeetingDistance) {
SimLocationActuator g1Leader = group1.getLeader();
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];
groups[0] = group1;
groups[1] = group2;
......@@ -85,23 +119,13 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
alreadyProcessed.add(group1);
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;
}
......@@ -180,22 +204,9 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
*
* @author Marcel Verst
*/
protected boolean waitedLongEnoughAfterMerging(SimLocationActuator host, long waitTime) {
return ((Time.getCurrentTime() - groupCon.getMergedAtTime().get(host)) >= waitTime);
}
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;
}
protected boolean waitedLongEnoughAfterMerging(SimLocationActuator host) {
return ((Time.getCurrentTime() - groupCon.getMergedAtTime().get(host)) >= groupReencounterWaitTime);
}
/**
* Removes both groups on encounter.
......@@ -253,7 +264,7 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
SocialMovementGroup large = getLargerGroup(group1, group2);
SocialMovementGroup small = getSmallerGroup(group1, group2);
if((large.getGroupSize() - numberOfHostsToLeave) >= groupCon.getMinGroupSize()) {
if((large.getGroupSize() - numberOfHostsToLeave) >= movementModel.getGroupFormingBehavior().getMinGroupSize()) {
groupCon.updateMergeVars(group1, group2);
for(int i = 0; i < numberOfHostsToLeave; i++) {
......
......@@ -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.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
......@@ -31,6 +32,15 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovement
* @version 1.0, 22.11.2018
*/
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 ---
private double probabilityToDissolve;
//------------------------------------------
......
......@@ -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.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
......@@ -35,6 +36,14 @@ public class Fully extends AbstractGroupEncounter {
private double probabilityToMergeFully;
//------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public Fully(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
/**
* {@inheritDoc}
* 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
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.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
......@@ -37,6 +38,14 @@ public class FullyDissolve extends AbstractGroupEncounter {
private double probabilityToDissolve;
//------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public FullyDissolve(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
@Override
public void initialize(SocialGroupMovementModel movementModel) {
super.initialize(movementModel);
......
......@@ -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.SocialGroupMovementModel;
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 {
private int numberOfHostsToLeave;
//------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public FullyPartially(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
@Override
public void initialize(SocialGroupMovementModel movementModel) {
super.initialize(movementModel);
......
......@@ -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.SocialGroupMovementModel;
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 {
private int numberOfHostsToLeave;
//------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public FullyPartiallyDissolve(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
@Override
public void initialize(SocialGroupMovementModel movementModel) {
super.initialize(movementModel);
......
......@@ -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.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
......@@ -36,6 +37,14 @@ public class Partially extends AbstractGroupEncounter {
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.
......
......@@ -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.SocialGroupMovementModel;
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
......@@ -39,6 +40,14 @@ public class PartiallyDissolve extends AbstractGroupEncounter {
private int numberOfHostsToLeave;
//------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public PartiallyDissolve(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
@Override
public void initialize(SocialGroupMovementModel movementModel) {
super.initialize(movementModel);
......
......@@ -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.util.Tuple;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
......@@ -39,6 +40,14 @@ public class Wait extends AbstractGroupEncounter{
private long timeToWait;
//------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public Wait(boolean enableGroupEncounters,
double groupEncounterMeetingDistance,
long groupReencounterWaitTime) {
super(enableGroupEncounters, groupEncounterMeetingDistance,
groupReencounterWaitTime);
}
@Override
public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) {
if(rand.nextDouble() <= probabilityToWait) {
......
......@@ -20,11 +20,12 @@
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.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.impl.topology.movement.modularosm.SocialGroupMovementModel;
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
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.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.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.Time;
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.util.XMLConfigurableConstructor;
/**
* Abstract class implementation for implementing GroupFormingStrategies.
......@@ -54,18 +58,96 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
// Holds time information of nodes for the groups (stay duration, last update)
protected Map<INodeID, Tuple<Long,Long>> stayDuration;
// GROUP VARIABLES FROM CONFIGS
protected boolean enableGroups;
protected int minGroupSize;
protected int maxGroupSize;
protected double probabilityToJoin;
protected int maxNumberOfGroups;
protected long waitTime;
protected long setupTime;
protected int maxNumberOfGroups;
protected long groupRejoinWaitTime;
protected long groupFormationSetupDelay;
protected long groupFormationDelay;
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.
*
......@@ -73,7 +155,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
*
* @author Marcel Verst
*/
public void createGroup(Set<SimLocationActuator> candidates) {
protected void createGroup(Set<SimLocationActuator> 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
// 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 {
destination.plus(offset);
group.setDestination(destination);
setMP(group);
setGroupMeetingPoint(group);
for(SimLocationActuator member : group.getMembers()) {
member.setTargetAttractionPoint(poiDestination);
groupCon.addHasBeenInGroupEntry(member, true);
member.setTargetAttractionPoint(poiDestination);
if(groupCon.getLeftGroupAtTime().containsKey(member)) {
// System.out.println(groupCon.getLeftGroupAtTime().get(member));
groupCon.removeLeftGroupAtTimeEntry(member);
}
}
groupCon.addGroup(group);
}
......@@ -124,7 +204,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
*
* @author Marcel Verst
*/
public void removeGroup(SocialMovementGroup group) {
protected void removeGroup(SocialMovementGroup group) {
groupCon.removeGroup(group);
}
......@@ -162,7 +242,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
*
* @author Marcel Verst
*/
public SimLocationActuator[] getHostsSortedByStayDurationAscending(Set<SimLocationActuator> candidates) {
protected SimLocationActuator[] getHostsSortedByStayDurationAscending(Set<SimLocationActuator> candidates) {
int size = candidates.size();
SimLocationActuator[] youngestHostsSorted = new SimLocationActuator[size];
......@@ -191,7 +271,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
*
* @author Marcel Verst
*/
public SimLocationActuator[] getHostsSortedByStayDurationDescending(Set<SimLocationActuator> candidates) {
protected SimLocationActuator[] getHostsSortedByStayDurationDescending(Set<SimLocationActuator> candidates) {
int size = candidates.size();
SimLocationActuator[] oldestHostsSorted = new SimLocationActuator[size];
......@@ -229,54 +309,6 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
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.
* Returns true if willing to join, false else.
......@@ -299,8 +331,14 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
*
* @author Marcel Verst
*/
protected boolean waitedLongEnough(SimLocationActuator host, long time) {
return (getWaitingTime(host, time) >= waitTime);
protected boolean groupRejoinTimerExpired(SimLocationActuator host) {
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 {
*
* @author Marcel Verst
*/
private long getWaitingTime(SimLocationActuator host, long currentTime) {
protected long getWaitingTime(SimLocationActuator host, long currentTime) {
return currentTime - groupCon.getLeftGroupAtTime().get(host);
}
......@@ -325,10 +363,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
* @author Marcel Verst
*/
protected boolean beenInGroup(SimLocationActuator host) {
if(!groupCon.getHasBeenInAGroup().containsKey(host)) {
groupCon.addHasBeenInGroupEntry(host, false);
}
return groupCon.getHasBeenInAGroup().get(host);
return groupCon.getHostWasGroupMember(host);
}
/*
......@@ -344,7 +379,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
*
* @author Marcel Verst, Julian Zobel
*/
public void setMP(SocialMovementGroup group) {
protected void setGroupMeetingPoint(SocialMovementGroup group) {
PositionVector leaderPos = group.getLeader().getRealPosition();
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 {
// Update target for all group members to meeting point
for(SimLocationActuator participant : group.getMembers()) {
ITransitionStrategy transition = movementModel.getTransition();
IAttractionAssigmentStrategy transition = movementModel.getAttractionAssignmentStrategy();
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
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.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.util.Either;
import de.tud.kom.p2psim.impl.util.Tuple;
import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Oracle;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Time;
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.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
......@@ -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.
* Simplified code and bug fixes.
*
* @author Julian Zobel
*
* @version 1.1, 29.01.2020
*/
public class DefaultGroupForming extends AbstractGroupForming {
private Map<SimLocationActuator, AttractionPoint> lastAPs;
private int nextGroupSize;
public void initialize(SocialGroupMovementModel movementModel) {
this.movementModel = movementModel;
nextGroupSize = nextGroupSize();
lastAPs = new LinkedHashMap<>();
groupCon = MovementGroupContainer.getInstance();
groupCon.setWaitTime(waitTime);
groupCon.setMinGroupSize(minGroupSize);
groupCon.setMaxGroupSize(maxGroupSize);
// Initialize instances of other classes
this.hostCounter = movementModel.getAttractionPointHostCounter();
@XMLConfigurableConstructor({"enableGroups", "maxNumberOfGroups", "minGroupSize", "maxGroupSize", "probabilityToJoin", "groupFormationSetupDelay", "groupFormationDelay", "groupRejoinWaitTime"})
public DefaultGroupForming(boolean enableGroups, int maxNumberOfGroups, int minGroupSize, int maxGroupSize, double probabilityToJoin,
long groupFormationSetupDelay, long groupFormationDelay, long groupRejoinWaitTime) {
stayDuration = new LinkedHashMap<INodeID, Tuple<Long,Long>>();
for(SimLocationActuator host : movementModel.getAllLocationActuators()) {
groupCon.addHasBeenInGroupEntry(host, false);
lastAPs.put(host, host.getCurrentTargetAttractionPoint());
stayDuration.put(host.getHost().getId(), new Tuple<Long, Long>(0L, Time.getCurrentTime()));
}
super(enableGroups, maxNumberOfGroups, minGroupSize, maxGroupSize,
probabilityToJoin, groupFormationSetupDelay, groupFormationDelay,
groupRejoinWaitTime);
}
/*
* =====================================================================================================
* === GROUP HANDLING
* =====================================================================================================
*/
/**
* {@inheritDoc}
*/
public void manageGroups() {
long currentTime = Time.getCurrentTime();
public void manageGroups() {
if(enableGroups && (currentTime >= setupTime) && probabilityToJoin > 0.0) {
runGroupBuildingProcess();
runGroupDeletionProcess();
// group forming may be deactivated
if(!enableGroups || probabilityToJoin == 0) {
return;
}
// setup delay before forming the first group...
if(Time.getCurrentTime() <= groupFormationSetupDelay) {
return;
}
runGroupDeletionProcess();
}
/*
* =====================================================================================================
* === GROUP BUILDING PROCESS
* =====================================================================================================
*/
/**
* {@inheritDoc}
*/
public void runGroupBuildingProcess() {
*/
protected void triggerGroupFormation() {
updateStayDuration();
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
hostCounter.updateHostCount();
AttractionPoint apCandidate = getAttractionPointWithOldestHost();
AttractionPoint apCandidate = getRandomAttractionPoint();
if(apCandidate == null) {
break;
}
int numberOfHostsInAttractionPoint = hostCounter.getHostCountOfAttractionPoint(apCandidate);
// Adapt nextGroupSize to AP conditions
while(numberOfHostsInAttractionPoint < nextGroupSize && nextGroupSize >= 2) {
nextGroupSize--;
}
if(numberOfHostsInAttractionPoint >= nextGroupSize) {
Set<SimLocationActuator> hostsOfPoi = hostCounter.getHostsOfAttractionPoint(apCandidate);
SimLocationActuator[] hostsSorted = getHostsSortedByStayDurationDescending(hostsOfPoi);
Set<SimLocationActuator> groupCandidates = new LinkedHashSet<>();
int numberOfHostsInAttractionPoint = hostCounter.getHostCountOfAttractionPoint(apCandidate);
int groupSize = Math.min(Math.max(minGroupSize, rand.nextInt(maxGroupSize)), numberOfHostsInAttractionPoint);
if(groupSize > numberOfHostsInAttractionPoint) {
throw new UnsupportedOperationException("Math Genius you are not!");
}
if(hostsSorted.length > 0) {
for(int tmp = 0; tmp <= nextGroupSize; tmp++) {
for(int index = 0; index < hostsSorted.length; index++) {
SimLocationActuator hostToAdd = hostsSorted[index];
if(hostToAdd != null) {
if(!groupCandidates.contains(hostToAdd)) {
if(!movementModel.getSingleHosts().contains(hostToAdd)) {
if(wantsToJoin()) {
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());
}
}
}
}
}
}
Set<SimLocationActuator> groupCandidates = new LinkedHashSet<>();
Set<SimLocationActuator> hostsOfPoi = hostCounter.getHostsOfAttractionPoint(apCandidate);
for (SimLocationActuator m : hostsOfPoi) {
if(groupCandidates.contains(m)) {
System.err.println("Cannot be???");
continue;
}
if(groupCandidates.isEmpty() || groupCandidates == null) {
break;
if(movementModel.getSingleHosts().contains(m)) {
System.out.println("ACM Single Host is not added");
continue;
}
while(groupCandidates.size() < nextGroupSize && nextGroupSize >= 2) {
nextGroupSize--;
if(groupCon.isGroupMember(m)) {
System.out.println("No members allowed");
continue;
}
if(groupCandidates.size() >= nextGroupSize) {
for(SimLocationActuator candidate : groupCandidates) {
INodeID id = candidate.getHost().getId();
stayDuration.put(id, new Tuple<Long, Long>(0L, Time.getCurrentTime()));
}
createGroup(groupCandidates);
nextGroupSize = nextGroupSize();
if(wantsToJoin()) {
if(!beenInGroup(m) || groupRejoinTimerExpired(m)) {
groupCandidates.add(m);
}
}
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 {
public void runGroupDeletionProcess() {
LocalMovementStrategy movementStrategy = movementModel.getMovementStrategy();
ITransitionStrategy transition = movementModel.getTransition();
IAttractionAssigmentStrategy transition = movementModel.getAttractionAssignmentStrategy();
Set<SocialMovementGroup> groupsToRemove = new LinkedHashSet<>();
......@@ -223,6 +190,15 @@ public class DefaultGroupForming extends AbstractGroupForming {
for(SocialMovementGroup group : groupsToRemove) {
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 {
* Updates the stayDuration of each Host
*/
public void updateStayDuration() {
for(Host host : Oracle.getAllHosts()) {
try {
SimLocationActuator component = host.getComponent(SimLocationActuator.class);
INodeID id = component.getHost().getId();
// Check if host is in an AP area
boolean isInAp = false;
for(AttractionPoint ap : IAttractionGenerator.attractionPoints) {
Location hostLocation = component.getLastLocation();
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()));
for(SimLocationActuator component : movementModel.getAllLocationActuators()) {
INodeID id = component.getHost().getId();
// Check if host is in an AP area
boolean isInAp = false;
for(AttractionPoint ap : IAttractionGenerator.attractionPoints) {
Location hostLocation = component.getLastLocation();
if(ap.distanceTo(hostLocation) <= ap.getRadius()) {
isInAp = true;
}
} 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;
}
*/
/*
private SimLocationActuator getRandomCandidate(Set<SimLocationActuator> candidates) {
int size = candidates.size();
int item = rand.nextInt(size-1);
int i = 0;
SimLocationActuator actuator = null;
for(SimLocationActuator host : candidates) {
if(i == item) {
actuator = host;
// 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()));
}
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 {
*
* @author Marcel Verst
*/
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();
void manageGroups();
/**
* 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 {
* @author Marcel Verst
*/
void runGroupDeletionProcess();
double getProbabilityToJoin();
public int getMinGroupSize();
public int getMaxGroupSize();
}
\ No newline at end of file
......@@ -20,29 +20,24 @@
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.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
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.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
* 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
* @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);
......@@ -109,4 +104,28 @@ public abstract class AbstractAttractionBasedTransitionStrategy implements ITran
protected long getPauseTime(AttractionPoint 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