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 {
"GroupForming: groupFormationSetupDelay must be > 0!");
}
if (groupFormationDelay < 0) {
if (groupFormationDelay < -1) {
throw new ConfigurationException(
"GroupForming: groupFormationDelay must be >= 1!");
"GroupForming: groupFormationDelay must be >= -1!");
}
if (groupRejoinWaitTime < 0) {
......@@ -218,14 +218,28 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
public void removeGroup(SocialMovementGroup 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
public void eventOccurred(Object content, int type) {
triggerGroupFormation();
assembleGroup();
}
}, null, 0);
}
protected abstract void assembleGroup();
/**
* 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 {
System.out.println(Time.getFormattedTime() + " | group trigger " + groupsToCreate);
for(int g = 0; g < groupsToCreate; g++) {
// Get attractionPoint with highest amount of hosts
hostCounter.updateHostCount();
assembleGroup();
}
}
@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()));
if(apCandidate == null) {
break;
// skip already added hosts (should never happen)
if(groupCandidates.contains(m)) {
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!)
LinkedList<SimLocationActuator> randomShuffledHostsAtAttractionPoint = new LinkedList<>(hostCounter.getHostsOfAttractionPoint(apCandidate));
Collections.shuffle(randomShuffledHostsAtAttractionPoint, rand);
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;
}
}
// skip single hosts
if(movementModel.getSingleHosts().contains(m)) {
continue;
}
// if there are no candidates, wait a minute until asking again
if(groupCandidates.isEmpty() || groupCandidates == null) {
Event.scheduleWithDelay(Time.MINUTE, new EventHandler() {
@Override
public void eventOccurred(Object content, int type) {
triggerGroupFormation();
}
}, null, 0);
// 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;
}
for(SimLocationActuator candidate : groupCandidates) {
INodeID id = candidate.getHost().getId();
stayDuration.put(id, new Tuple<Long, Long>(0L, Time.getCurrentTime())); // FIXME why?
}
}
// if there are no candidates, wait a minute until asking again
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
......
......@@ -20,7 +20,6 @@
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.groups.SocialMovementGroup;
......
......@@ -52,6 +52,14 @@ public abstract class AbstractAttractionBasedAssignmentStrategy implements IAttr
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
public AttractionPoint getAssignment(SimLocationActuator comp) {
return assignments.get(comp);
......@@ -101,7 +109,7 @@ public abstract class AbstractAttractionBasedAssignmentStrategy implements IAttr
}
}
protected long getPauseTime(AttractionPoint attractionPoint) {
public long getPauseTime(AttractionPoint 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
*/
public class FixedAssignmentStrategy extends AbstractAttractionBasedAssignmentStrategy {
public FixedAssignmentStrategy() {
super(0, 0);
}
private List<SimLocationActuator> comps = new LinkedList<SimLocationActuator>();
private Map<SimLocationActuator, SimHost> mappingMSHost = new LinkedHashMap<SimLocationActuator, SimHost>();
......
......@@ -87,4 +87,5 @@ public interface IAttractionAssigmentStrategy {
public boolean hostInAttractionPointArea(SimLocationActuator host);
public long getPauseTime(AttractionPoint attractionPoint);
}
......@@ -54,11 +54,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedAssi
@XMLConfigurableConstructor({ "defaultPauseTimeMin", "defaultPauseTimeMax" })
public InAreaRoamingTransitionStrategy(long defaultPauseTimeMin, long defaultPauseTimeMax) {
assert defaultPauseTimeMax >= 0 && defaultPauseTimeMin >= 0;
assert defaultPauseTimeMax >= defaultPauseTimeMin;
this.defaultPauseTimeMax = defaultPauseTimeMax;
this.defaultPauseTimeMin = defaultPauseTimeMin;
super(defaultPauseTimeMin, defaultPauseTimeMax);
}
@Override
......@@ -88,7 +84,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedAssi
}
@Override
protected long getPauseTime(AttractionPoint attractionPoint) {
public long getPauseTime(AttractionPoint attractionPoint) {
if(useGaussianDistributedPauseTime) {
return gaussianDistributionPauseTime(defaultPauseTimeMax - defaultPauseTimeMin, 0.5*(defaultPauseTimeMax - defaultPauseTimeMin));
}
......@@ -133,7 +129,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedAssi
// if the transit was triggered beforehand (e.g., attraction point moved), then do nothing.
if(roamingStates.get(comp) != roamingTransitionState.TRANSITION) {
this.addComponent(comp);
this.addComponent(comp);
}
}
else if(type == EVENT_ROAMING_PAUSE_ENDED) {
......
......@@ -15,7 +15,11 @@ import java.util.*;
*/
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<>();
......
......@@ -27,7 +27,11 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
*/
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.
*/
private Map<SimLocationActuator, AttractionPoint> currentTarget = new HashMap<>();
......
......@@ -104,11 +104,7 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedAssignmentS
@XMLConfigurableConstructor({ "defaultPauseTimeMin", "defaultPauseTimeMax" })
public SocialTransitionStrategy(long defaultPauseTimeMin, long defaultPauseTimeMax) {
assert defaultPauseTimeMax >= 0 && defaultPauseTimeMin >= 0;
assert defaultPauseTimeMax >= defaultPauseTimeMin;
this.defaultPauseTimeMax = defaultPauseTimeMax;
this.defaultPauseTimeMin = defaultPauseTimeMin;
super(defaultPauseTimeMin, defaultPauseTimeMax);
}
......
......@@ -43,11 +43,7 @@ public class WeightedTransitionStrategy extends AbstractAttractionBasedAssignmen
@XMLConfigurableConstructor({ "defaultPauseTimeMin", "defaultPauseTimeMax" })
public WeightedTransitionStrategy(long defaultPauseTimeMin, long defaultPauseTimeMax) {
assert defaultPauseTimeMax >= 0 && defaultPauseTimeMin >= 0;
assert defaultPauseTimeMax >= defaultPauseTimeMin;
this.defaultPauseTimeMax = defaultPauseTimeMax;
this.defaultPauseTimeMin = defaultPauseTimeMin;
super(defaultPauseTimeMin, defaultPauseTimeMax);
}
@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