Commit 3ac36ae8 authored by Julian Zobel's avatar Julian Zobel
Browse files

More abstraction to assignment strategies.

parent 0af7a185
...@@ -102,9 +102,9 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -102,9 +102,9 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
"GroupForming: groupFormationSetupDelay must be > 0!"); "GroupForming: groupFormationSetupDelay must be > 0!");
} }
if (groupFormationDelay < 0) { if (groupFormationDelay < -1) {
throw new ConfigurationException( throw new ConfigurationException(
"GroupForming: groupFormationDelay must be >= 1!"); "GroupForming: groupFormationDelay must be >= -1!");
} }
if (groupRejoinWaitTime < 0) { if (groupRejoinWaitTime < 0) {
...@@ -218,14 +218,28 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -218,14 +218,28 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
public void removeGroup(SocialMovementGroup group) { public void removeGroup(SocialMovementGroup group) {
groupCon.removeGroup(group); groupCon.removeGroup(group);
Event.scheduleWithDelay(rndGroupFormationDelay(), new EventHandler() { long delay = 0;
if(groupFormationDelay == -1) {
delay = movementModel.getAttractionAssignmentStrategy().getPauseTime(group.getLeader().getCurrentTargetAttractionPoint());
}
else {
delay = rndGroupFormationDelay();
}
System.out.println(Time.getFormattedTime(delay));
Event.scheduleWithDelay(delay, new EventHandler() {
@Override @Override
public void eventOccurred(Object content, int type) { public void eventOccurred(Object content, int type) {
triggerGroupFormation(); assembleGroup();
} }
}, null, 0); }, null, 0);
} }
protected abstract void assembleGroup();
/** /**
* Returns the first AttractionPoint which contains the host with the greatest stayDuration of all hosts located in AttractionPoints. * Returns the first AttractionPoint which contains the host with the greatest stayDuration of all hosts located in AttractionPoints.
* *
......
...@@ -94,74 +94,79 @@ public class DefaultGroupForming extends AbstractGroupForming { ...@@ -94,74 +94,79 @@ public class DefaultGroupForming extends AbstractGroupForming {
System.out.println(Time.getFormattedTime() + " | group trigger " + groupsToCreate); System.out.println(Time.getFormattedTime() + " | group trigger " + groupsToCreate);
for(int g = 0; g < groupsToCreate; g++) { for(int g = 0; g < groupsToCreate; g++) {
// Get attractionPoint with highest amount of hosts assembleGroup();
hostCounter.updateHostCount(); }
}
@Override
protected void assembleGroup() {
// Get attractionPoint with highest amount of hosts
hostCounter.updateHostCount();
AttractionPoint apCandidate = IAttractionGenerator.attractionPoints.get(rand.nextInt(IAttractionGenerator.attractionPoints.size()));
if(apCandidate == null) {
return;
}
int numberOfHostsInAttractionPoint = hostCounter.getHostCountOfAttractionPoint(apCandidate);
int groupSize = this.rndGroupSize(numberOfHostsInAttractionPoint);
Set<SimLocationActuator> groupCandidates = new LinkedHashSet<>();
// shuffle the hosts at the attraction point (more randomness ftw!)
LinkedList<SimLocationActuator> randomShuffledHostsAtAttractionPoint = new LinkedList<>(hostCounter.getHostsOfAttractionPoint(apCandidate));
Collections.shuffle(randomShuffledHostsAtAttractionPoint, rand);
for (SimLocationActuator m : randomShuffledHostsAtAttractionPoint) {
AttractionPoint apCandidate = IAttractionGenerator.attractionPoints.get(rand.nextInt(IAttractionGenerator.attractionPoints.size())); // skip already added hosts (should never happen)
if(apCandidate == null) { if(groupCandidates.contains(m)) {
break; continue;
} }
int numberOfHostsInAttractionPoint = hostCounter.getHostCountOfAttractionPoint(apCandidate);
int groupSize = this.rndGroupSize(numberOfHostsInAttractionPoint);
Set<SimLocationActuator> groupCandidates = new LinkedHashSet<>();
// shuffle the hosts at the attraction point (more randomness ftw!) // skip single hosts
LinkedList<SimLocationActuator> randomShuffledHostsAtAttractionPoint = new LinkedList<>(hostCounter.getHostsOfAttractionPoint(apCandidate)); if(movementModel.getSingleHosts().contains(m)) {
Collections.shuffle(randomShuffledHostsAtAttractionPoint, rand); continue;
}
for (SimLocationActuator m : randomShuffledHostsAtAttractionPoint) {
// skip already added hosts (should never happen)
if(groupCandidates.contains(m)) {
continue;
}
// skip single hosts
if(movementModel.getSingleHosts().contains(m)) {
continue;
}
// skip hosts that are already part of a group
if(groupCon.isGroupMember(m)) {
continue;
}
// test if the host wants and also is allowed to join this group
if(wantsToJoin()) {
if(!beenInGroup(m) || groupRejoinTimerExpired(m)) {
groupCandidates.add(m);
}
}
// do not continue if enough group members are gathered
if(groupCandidates.size() == groupSize) {
break;
}
}
// if there are no candidates, wait a minute until asking again // skip hosts that are already part of a group
if(groupCandidates.isEmpty() || groupCandidates == null) { if(groupCon.isGroupMember(m)) {
Event.scheduleWithDelay(Time.MINUTE, new EventHandler() { continue;
@Override }
public void eventOccurred(Object content, int type) {
triggerGroupFormation(); // test if the host wants and also is allowed to join this group
} if(wantsToJoin()) {
}, null, 0); if(!beenInGroup(m) || groupRejoinTimerExpired(m)) {
groupCandidates.add(m);
}
}
// do not continue if enough group members are gathered
if(groupCandidates.size() == groupSize) {
break; break;
} }
}
for(SimLocationActuator candidate : groupCandidates) {
INodeID id = candidate.getHost().getId(); // if there are no candidates, wait a minute until asking again
stayDuration.put(id, new Tuple<Long, Long>(0L, Time.getCurrentTime())); // FIXME why? if(groupCandidates.isEmpty() || groupCandidates == null) {
} Event.scheduleWithDelay(Time.MINUTE, new EventHandler() {
@Override
public void eventOccurred(Object content, int type) {
assembleGroup();
}
}, null, 0);
createGroup(groupCandidates); return;
} }
for(SimLocationActuator candidate : groupCandidates) {
INodeID id = candidate.getHost().getId();
stayDuration.put(id, new Tuple<Long, Long>(0L, Time.getCurrentTime())); // FIXME why?
}
createGroup(groupCandidates);
} }
/* /*
* ===================================================================================================== * =====================================================================================================
* === GROUP DELETION PROCESS * === GROUP DELETION PROCESS
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupforming; package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupforming;
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.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
......
...@@ -52,6 +52,14 @@ public abstract class AbstractAttractionBasedAssignmentStrategy implements IAttr ...@@ -52,6 +52,14 @@ public abstract class AbstractAttractionBasedAssignmentStrategy implements IAttr
protected final static int EVENT_PAUSE_ENDED = 1; protected final static int EVENT_PAUSE_ENDED = 1;
public AbstractAttractionBasedAssignmentStrategy(long defaultPauseTimeMin, long defaultPauseTimeMax) {
assert defaultPauseTimeMax >= 0 && defaultPauseTimeMin >= 0;
assert defaultPauseTimeMax >= defaultPauseTimeMin;
this.defaultPauseTimeMax = defaultPauseTimeMax;
this.defaultPauseTimeMin = defaultPauseTimeMin;
}
@Override @Override
public AttractionPoint getAssignment(SimLocationActuator comp) { public AttractionPoint getAssignment(SimLocationActuator comp) {
return assignments.get(comp); return assignments.get(comp);
...@@ -101,7 +109,7 @@ public abstract class AbstractAttractionBasedAssignmentStrategy implements IAttr ...@@ -101,7 +109,7 @@ public abstract class AbstractAttractionBasedAssignmentStrategy implements IAttr
} }
} }
protected long getPauseTime(AttractionPoint attractionPoint) { public long getPauseTime(AttractionPoint attractionPoint) {
return getRandomUniformDistributionPauseTime(attractionPoint); return getRandomUniformDistributionPauseTime(attractionPoint);
} }
......
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition;
import java.util.LinkedHashMap;
import java.util.Map;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
* With this transition strategy, nodes are roaming around {@link AttractionPoint}s, without transitions between them. As the {@link ModularMovementModel}
* uses a Gauss function to add jitter and offsets to the movement, some nodes may also roam outside of the circle's radius (this is intended to make it more realistic)
*
* @author Julian Zobel
* @version 1.0, 24.01.2019
*/
public class AttractionPointRoamingStrategy extends AbstractAttractionBasedAssignmentStrategy implements EventHandler {
public static enum roamingTransitionState {
PAUSE,
ROAMING
}
protected Map<SimLocationActuator, roamingTransitionState> roamingStates = new LinkedHashMap<>();
@XMLConfigurableConstructor({ "defaultPauseTimeMin", "defaultPauseTimeMax" })
public AttractionPointRoamingStrategy(long defaultPauseTimeMin, long defaultPauseTimeMax) {
super(defaultPauseTimeMin, defaultPauseTimeMax);
}
@Override
public void addComponent(SimLocationActuator comp) {
this.roamingStates.put(comp, null);
AttractionPoint nextAP = getNewAttractionPointAssignment(comp);
updateTargetAttractionPoint(comp, nextAP);
}
@Override
public void reachedAttractionPoint(SimLocationActuator comp, AttractionPoint attractionPoint) {
if(roamingStates.get(comp) == roamingTransitionState.PAUSE) {
return;
}
this.roamingStates.put(comp, roamingTransitionState.PAUSE);
// schedule roaming
Event.scheduleWithDelay(Math.max(Time.MINUTE, gaussianDistributionPauseTime(5 * Time.MINUTE, 1 * Time.MINUTE)), this, comp, 0);
}
/**
* Use a gaussian distribution for the pause time interval generation, using a mean value and a standard deviation
*
* @return
*/
private long gaussianDistributionPauseTime(double mean, double std) {
double x = rnd.nextGaussian() * std + mean;
if(x <= 0) return gaussianDistributionPauseTime(mean, std*0.9);
return (long) x;
}
private void roamAroundAttractionPoint(SimLocationActuator comp) {
if(roamingStates.get(comp) == roamingTransitionState.PAUSE) {
AttractionPoint currentAttractionPoint = this.assignments.get(comp);
this.roamingStates.put(comp, roamingTransitionState.ROAMING);
notifyListenersOfAssignmentUpdate(comp, currentAttractionPoint);
}
}
@Override
public void eventOccurred(Object content, int type) {
SimLocationActuator comp = (SimLocationActuator) content;
AttractionPoint currentAttractionPoint = this.assignments.get(comp);
// if the attraction point was removed in the meantime, go directly to transit state
if(currentAttractionPoint == null || !IAttractionGenerator.attractionPoints.contains(currentAttractionPoint)) {
this.addComponent(comp);
}
else {
this.roamAroundAttractionPoint(comp);
}
}
}
...@@ -40,6 +40,10 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction ...@@ -40,6 +40,10 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction
*/ */
public class FixedAssignmentStrategy extends AbstractAttractionBasedAssignmentStrategy { public class FixedAssignmentStrategy extends AbstractAttractionBasedAssignmentStrategy {
public FixedAssignmentStrategy() {
super(0, 0);
}
private List<SimLocationActuator> comps = new LinkedList<SimLocationActuator>(); private List<SimLocationActuator> comps = new LinkedList<SimLocationActuator>();
private Map<SimLocationActuator, SimHost> mappingMSHost = new LinkedHashMap<SimLocationActuator, SimHost>(); private Map<SimLocationActuator, SimHost> mappingMSHost = new LinkedHashMap<SimLocationActuator, SimHost>();
......
...@@ -87,4 +87,5 @@ public interface IAttractionAssigmentStrategy { ...@@ -87,4 +87,5 @@ public interface IAttractionAssigmentStrategy {
public boolean hostInAttractionPointArea(SimLocationActuator host); public boolean hostInAttractionPointArea(SimLocationActuator host);
public long getPauseTime(AttractionPoint attractionPoint);
} }
...@@ -54,11 +54,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedAssi ...@@ -54,11 +54,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedAssi
@XMLConfigurableConstructor({ "defaultPauseTimeMin", "defaultPauseTimeMax" }) @XMLConfigurableConstructor({ "defaultPauseTimeMin", "defaultPauseTimeMax" })
public InAreaRoamingTransitionStrategy(long defaultPauseTimeMin, long defaultPauseTimeMax) { public InAreaRoamingTransitionStrategy(long defaultPauseTimeMin, long defaultPauseTimeMax) {
assert defaultPauseTimeMax >= 0 && defaultPauseTimeMin >= 0; super(defaultPauseTimeMin, defaultPauseTimeMax);
assert defaultPauseTimeMax >= defaultPauseTimeMin;
this.defaultPauseTimeMax = defaultPauseTimeMax;
this.defaultPauseTimeMin = defaultPauseTimeMin;
} }
@Override @Override
...@@ -88,7 +84,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedAssi ...@@ -88,7 +84,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedAssi
} }
@Override @Override
protected long getPauseTime(AttractionPoint attractionPoint) { public long getPauseTime(AttractionPoint attractionPoint) {
if(useGaussianDistributedPauseTime) { if(useGaussianDistributedPauseTime) {
return gaussianDistributionPauseTime(defaultPauseTimeMax - defaultPauseTimeMin, 0.5*(defaultPauseTimeMax - defaultPauseTimeMin)); return gaussianDistributionPauseTime(defaultPauseTimeMax - defaultPauseTimeMin, 0.5*(defaultPauseTimeMax - defaultPauseTimeMin));
} }
...@@ -133,7 +129,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedAssi ...@@ -133,7 +129,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedAssi
// if the transit was triggered beforehand (e.g., attraction point moved), then do nothing. // if the transit was triggered beforehand (e.g., attraction point moved), then do nothing.
if(roamingStates.get(comp) != roamingTransitionState.TRANSITION) { if(roamingStates.get(comp) != roamingTransitionState.TRANSITION) {
this.addComponent(comp); this.addComponent(comp);
} }
} }
else if(type == EVENT_ROAMING_PAUSE_ENDED) { else if(type == EVENT_ROAMING_PAUSE_ENDED) {
......
...@@ -15,7 +15,11 @@ import java.util.*; ...@@ -15,7 +15,11 @@ import java.util.*;
*/ */
public class ManualAssignmentStrategy extends AbstractAttractionBasedAssignmentStrategy public class ManualAssignmentStrategy extends AbstractAttractionBasedAssignmentStrategy
{ {
private LinkedHashSet<AttractionPoint> aPoints = new LinkedHashSet<>(); public ManualAssignmentStrategy() {
super(0, 0);
}
private LinkedHashSet<AttractionPoint> aPoints = new LinkedHashSet<>();
private Map<SimLocationActuator, AttractionPoint> assignments = new HashMap<>(); private Map<SimLocationActuator, AttractionPoint> assignments = new HashMap<>();
......
...@@ -27,7 +27,11 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; ...@@ -27,7 +27,11 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
*/ */
public class RandomInAreaTransitionStrategy extends AbstractAttractionBasedAssignmentStrategy public class RandomInAreaTransitionStrategy extends AbstractAttractionBasedAssignmentStrategy
{ {
/** public RandomInAreaTransitionStrategy() {
super(0, 0);
}
/**
* These are the current spots inside the target area where the client is currently heading. * These are the current spots inside the target area where the client is currently heading.
*/ */
private Map<SimLocationActuator, AttractionPoint> currentTarget = new HashMap<>(); private Map<SimLocationActuator, AttractionPoint> currentTarget = new HashMap<>();
......
...@@ -104,11 +104,7 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedAssignmentS ...@@ -104,11 +104,7 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedAssignmentS
@XMLConfigurableConstructor({ "defaultPauseTimeMin", "defaultPauseTimeMax" }) @XMLConfigurableConstructor({ "defaultPauseTimeMin", "defaultPauseTimeMax" })
public SocialTransitionStrategy(long defaultPauseTimeMin, long defaultPauseTimeMax) { public SocialTransitionStrategy(long defaultPauseTimeMin, long defaultPauseTimeMax) {
assert defaultPauseTimeMax >= 0 && defaultPauseTimeMin >= 0; super(defaultPauseTimeMin, defaultPauseTimeMax);
assert defaultPauseTimeMax >= defaultPauseTimeMin;
this.defaultPauseTimeMax = defaultPauseTimeMax;
this.defaultPauseTimeMin = defaultPauseTimeMin;
} }
......
...@@ -43,11 +43,7 @@ public class WeightedTransitionStrategy extends AbstractAttractionBasedAssignmen ...@@ -43,11 +43,7 @@ public class WeightedTransitionStrategy extends AbstractAttractionBasedAssignmen
@XMLConfigurableConstructor({ "defaultPauseTimeMin", "defaultPauseTimeMax" }) @XMLConfigurableConstructor({ "defaultPauseTimeMin", "defaultPauseTimeMax" })
public WeightedTransitionStrategy(long defaultPauseTimeMin, long defaultPauseTimeMax) { public WeightedTransitionStrategy(long defaultPauseTimeMin, long defaultPauseTimeMax) {
assert defaultPauseTimeMax >= 0 && defaultPauseTimeMin >= 0; super(defaultPauseTimeMin, defaultPauseTimeMax);
assert defaultPauseTimeMax >= defaultPauseTimeMin;
this.defaultPauseTimeMax = defaultPauseTimeMax;
this.defaultPauseTimeMin = defaultPauseTimeMin;
} }
@Override @Override
......
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