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

Attraction Analyzer and Social Group Movement ANalyzer

parent 7b723ca7
...@@ -333,6 +333,6 @@ public abstract class AbstractTopologyComponent implements TopologyComponent { ...@@ -333,6 +333,6 @@ public abstract class AbstractTopologyComponent implements TopologyComponent {
@Override @Override
public String toString() { public String toString() {
return "TopoComp: " + getHost().getId() + " at " + position.toString(); return "Topology Component #" + getHost().getId() + " at pos " + position.toString();
} }
} }
...@@ -23,9 +23,10 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm; ...@@ -23,9 +23,10 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm;
import java.util.Set; import java.util.Set;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tudarmstadt.maki.simonstrator.api.component.core.MonitorComponent.Analyzer;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
public interface IAttractionBasedMovementMonitor { public interface IAttractionBasedMovementAnalyzer extends Analyzer {
public void onAllNodeMovementCompleted(Set<SimLocationActuator> nodes); public void onAllNodeMovementCompleted(Set<SimLocationActuator> nodes);
...@@ -36,5 +37,6 @@ public interface IAttractionBasedMovementMonitor { ...@@ -36,5 +37,6 @@ public interface IAttractionBasedMovementMonitor {
public void onUpdateAttractionAssignment(SimLocationActuator node, IAttractionPoint attractionpoint); public void onUpdateAttractionAssignment(SimLocationActuator node, IAttractionPoint attractionpoint);
public void onNodeReachedAttractionPoint(SimLocationActuator node, IAttractionPoint 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;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
public interface ISocialGroupMovementAnalyzer extends IAttractionBasedMovementAnalyzer {
public void onGroupForming(SocialMovementGroup group);
public void onGroupDisbanding(SocialMovementGroup group);
public void onGroupMerge(SocialMovementGroup group1, SocialMovementGroup group2);
public void onGroupWait(SocialMovementGroup group);
public void onGroupMovesToAttractionPoint(SocialMovementGroup group);
public void onMoveToMeetingPoint(SocialMovementGroup group, SimLocationActuator node);
public void onMemberWaitAtMeetingPoint(SocialMovementGroup group, SimLocationActuator node);
public void onGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2);
}
...@@ -46,6 +46,7 @@ import de.tud.kom.p2psim.impl.util.Either; ...@@ -46,6 +46,7 @@ import de.tud.kom.p2psim.impl.util.Either;
import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event; import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler; import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
...@@ -173,6 +174,12 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -173,6 +174,12 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
move(); move();
initialized = true; initialized = true;
// Inform analyzer of resolved movement
if(Monitor.hasAnalyzer(IAttractionBasedMovementAnalyzer.class)) {
Monitor.getOrNull(IAttractionBasedMovementAnalyzer.class).onAllNodeMovementCompleted(moveableHosts);
}
} }
} }
...@@ -249,6 +256,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -249,6 +256,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
assert currentTargets.containsKey(component); assert currentTargets.containsKey(component);
doLocalMovement(component, currentTargets.get(component)); doLocalMovement(component, currentTargets.get(component));
} }
Event.scheduleWithDelay(timeBetweenMoveOperation, this, null, Event.scheduleWithDelay(timeBetweenMoveOperation, this, null,
EVENT_MOVE); EVENT_MOVE);
} }
......
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
package de.tud.kom.p2psim.impl.topology.movement.modularosm; package de.tud.kom.p2psim.impl.topology.movement.modularosm;
import java.net.UnknownHostException;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -42,6 +40,7 @@ import de.tud.kom.p2psim.impl.topology.util.PositionVector; ...@@ -42,6 +40,7 @@ import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector; import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event; import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
...@@ -52,6 +51,9 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractio ...@@ -52,6 +51,9 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractio
*/ */
public class SocialGroupMovementModel extends ModularMovementModel { public class SocialGroupMovementModel extends ModularMovementModel {
private final double MEETING_POINT_DISTANCE = 5;
private final double LEADER_GROUP_DISTANCE = 10;
protected MovementGroupContainer groupContainer; protected MovementGroupContainer groupContainer;
protected IGroupFormingBehavior groupFormingBehavior; protected IGroupFormingBehavior groupFormingBehavior;
protected IGroupEncounterBehavior groupEncounterBehavior; protected IGroupEncounterBehavior groupEncounterBehavior;
...@@ -69,6 +71,7 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -69,6 +71,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
public void initialize() { public void initialize() {
if (!initialized) { if (!initialized) {
groupContainer = MovementGroupContainer.getInstance(); groupContainer = MovementGroupContainer.getInstance();
groupFormingBehavior.initialize(this); groupFormingBehavior.initialize(this);
groupEncounterBehavior.initialize(this); groupEncounterBehavior.initialize(this);
...@@ -116,6 +119,8 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -116,6 +119,8 @@ public class SocialGroupMovementModel extends ModularMovementModel {
} }
} }
setTimeBetweenMoveOperations(timeBetweenMoveOperation); setTimeBetweenMoveOperations(timeBetweenMoveOperation);
// initial move // initial move
...@@ -123,6 +128,11 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -123,6 +128,11 @@ public class SocialGroupMovementModel extends ModularMovementModel {
initialized = true; initialized = true;
// Inform analyzer of resolved movement
if(Monitor.hasAnalyzer(IAttractionBasedMovementAnalyzer.class)) {
Monitor.getOrNull(IAttractionBasedMovementAnalyzer.class).onAllNodeMovementCompleted(moveableHosts);
}
} }
} }
...@@ -167,7 +177,7 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -167,7 +177,7 @@ public class SocialGroupMovementModel extends ModularMovementModel {
*/ */
for (SimLocationActuator host : moveableHosts) { for (SimLocationActuator host : moveableHosts) {
assert currentTargets.containsKey(host); assert currentTargets.containsKey(host);
// Single Host Movement // Single Host Movement
if(singleHosts.contains(host) || !groupContainer.isGroupMember(host)) { if(singleHosts.contains(host) || !groupContainer.isGroupMember(host)) {
doLocalMovement(host, currentTargets.get(host)); doLocalMovement(host, currentTargets.get(host));
...@@ -178,9 +188,12 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -178,9 +188,12 @@ public class SocialGroupMovementModel extends ModularMovementModel {
else { else {
throw new UnsupportedOperationException("SimLocationActuator " + host + " is neither in a group nor a single node"); throw new UnsupportedOperationException("SimLocationActuator " + host + " is neither in a group nor a single node");
} }
// TODO maybe remodel the group movement to do a whole group?
} }
Event.scheduleWithDelay(timeBetweenMoveOperation, this, null, EVENT_MOVE); Event.scheduleWithDelay(timeBetweenMoveOperation, this, null, EVENT_MOVE);
} }
...@@ -195,34 +208,58 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -195,34 +208,58 @@ public class SocialGroupMovementModel extends ModularMovementModel {
* @param PositionVector Destination of the host. * @param PositionVector Destination of the host.
*/ */
protected void doGroupMovement(SimLocationActuator host, PositionVector destination) { protected void doGroupMovement(SimLocationActuator host, PositionVector destination) {
// This host is a member of a group, thus...
SocialMovementGroup group = groupContainer.getGroupOfHost(host);
// if the group is currently gathering at a meeting point...
if(movesToGroupMeetingPoint(host)) { if(movesToGroupMeetingPoint(host)) {
// if this host has already arrived at the group meeting point..
if(hostIsAtMeetingPoint(host)) { if(hostIsAtMeetingPoint(host)) {
if(groupAtMP(host)) { // ... and if the whole group is also at the meeting point...
SocialMovementGroup group = groupContainer.getGroupOfHost(host); if(groupGatheredAtMeetingPoint(group)) {
IAttractionPoint currAp = group.getLeader().getCurrentTargetAttractionPoint(); // remove the meeting point and thus, start moving towards the actual destination
PositionVector currDest = group.getDestination(); group.setMeetingPoint(null);
group.setMeetingPoint(currDest);
for(SimLocationActuator participant : group.getMembers()) {
attractionAssigment.updateTargetAttractionPoint(participant, currAp);
}
} }
// ... but the group is not gathered at the meeting point, do nothing and wait for the rest.
else {
// inform analyzer of waiting group members
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onMemberWaitAtMeetingPoint(group, host);
}
}
} }
// MP not reached. Move to MP. // if the host has not reached the group meeting point, move towards it.
else { else {
PositionVector mp = groupContainer.getGroupOfHost(host).getMeetingPoint(); PositionVector mp = groupContainer.getGroupOfHost(host).getMeetingPoint();
doLocalMovement(host, mp); doLocalMovement(host, mp);
// inform analyzer group member moves to meeting point
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onMoveToMeetingPoint(group, host);
}
} }
} }
// MP reached. Move to destination. // ... but if the group is currently on their way to the destination
else { else {
// the leader does a local movement
if(groupContainer.isLeader(host)) { if(groupContainer.isLeader(host)) {
if(!groupContainer.isWaiting(groupContainer.getGroupOfHost(host))) { if(!groupContainer.isWaiting(groupContainer.getGroupOfHost(host))) {
doLocalMovement(host, destination); doLocalMovement(host, destination);
// inform analyzer of movement to attraction point
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupMovesToAttractionPoint(group);
}
}
else {
// inform analyzer of waiting group
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupWait(group);
}
} }
} }
else { else {
// while other nodes just follow the group leader
followLeader(host); followLeader(host);
} }
} }
...@@ -242,12 +279,14 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -242,12 +279,14 @@ public class SocialGroupMovementModel extends ModularMovementModel {
* @return Boolean * @return Boolean
*/ */
private boolean movesToGroupMeetingPoint(SimLocationActuator host) { private boolean movesToGroupMeetingPoint(SimLocationActuator host) {
PositionVector mp = groupContainer.getGroupOfHost(host).getMeetingPoint(); PositionVector meetingpoint = groupContainer.getGroupOfHost(host).getMeetingPoint();
PositionVector dest = groupContainer.getGroupOfHost(host).getDestination();
if(mp != dest) { if(meetingpoint == null)
return false;
else if(meetingpoint != groupContainer.getGroupOfHost(host).getDestination())
return true; return true;
} else
return false; return false;
} }
/** /**
...@@ -256,18 +295,15 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -256,18 +295,15 @@ public class SocialGroupMovementModel extends ModularMovementModel {
* @param SimLocationActuator The host to be checked. * @param SimLocationActuator The host to be checked.
* @return Boolean * @return Boolean
*/ */
private boolean groupAtMP(SimLocationActuator host) { private boolean groupGatheredAtMeetingPoint(SocialMovementGroup group) {
Set<SimLocationActuator> participants = groupContainer.getGroupMembers(host);
int counter = 0; for(SimLocationActuator participant : group.getMembers()) {
for(SimLocationActuator participant : participants) { if(!hostIsAtMeetingPoint(participant)) {
if(hostIsAtMeetingPoint(participant)) { return false;
counter++;
} }
} }
if(counter == participants.size()) {
return true; return true;
}
return false;
} }
/** /**
...@@ -278,16 +314,12 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -278,16 +314,12 @@ public class SocialGroupMovementModel extends ModularMovementModel {
* *
*/ */
private boolean hostIsAtMeetingPoint(SimLocationActuator host) { private boolean hostIsAtMeetingPoint(SimLocationActuator host) {
PositionVector meetingpoint = groupContainer.getGroupOfHost(host).getMeetingPoint();
PositionVector currMP = groupContainer.getGroupOfHost(host).getMeetingPoint();
if(host.getLastLocation().distanceTo(meetingpoint) <= MEETING_POINT_DISTANCE)
// 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 <= 5) {
return true; return true;
} else
return false; return false;
} }
/* /*
...@@ -304,24 +336,10 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -304,24 +336,10 @@ public class SocialGroupMovementModel extends ModularMovementModel {
*/ */
private void followLeader(SimLocationActuator host) { private void followLeader(SimLocationActuator host) {
SimLocationActuator leader = groupContainer.getGroupOfHost(host).getLeader(); SimLocationActuator leader = groupContainer.getGroupOfHost(host).getLeader();
if(leader.getCurrentTargetAttractionPoint() == null) {
System.out.println();
}
IAttractionPoint leaderDestination = leader.getCurrentTargetAttractionPoint();
IAttractionPoint hostDestination = host.getCurrentTargetAttractionPoint();
// Update target attraction point if not already done
if(leaderDestination != null && hostDestination != leaderDestination) {
attractionAssigment.updateTargetAttractionPoint(host, leaderDestination);
}
int o = 10;
// Assign small offset to the host depending on the leaders position. // Assign small offset to the host depending on the leaders position.
PositionVector leaderPos = leader.getRealPosition(); PositionVector leaderPos = leader.getRealPosition();
PositionVector offset = new PositionVector(rand.nextInt(o), rand.nextInt(o)); PositionVector offset = new PositionVector(rand.nextDouble() * LEADER_GROUP_DISTANCE, rand.nextDouble() * LEADER_GROUP_DISTANCE);
PositionVector newPos = leaderPos.plus(offset); PositionVector newPos = leaderPos.plus(offset);
// Update location of host, which will be around the leaders location. // Update location of host, which will be around the leaders location.
......
...@@ -24,7 +24,10 @@ import java.util.LinkedHashMap; ...@@ -24,7 +24,10 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.IAttractionBasedMovementAnalyzer;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ISocialGroupMovementAnalyzer;
import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
...@@ -55,6 +58,10 @@ public class AttractionPointImpl extends BasicAttractionPoint { ...@@ -55,6 +58,10 @@ public class AttractionPointImpl extends BasicAttractionPoint {
throw new AssertionError("Name "+name+" already in use for an attraction point."); throw new AssertionError("Name "+name+" already in use for an attraction point.");
} }
instances.put(name, this); instances.put(name, this);
if(Monitor.hasAnalyzer(IAttractionBasedMovementAnalyzer.class)) {
Monitor.getOrNull(IAttractionBasedMovementAnalyzer.class).onAttractionPointAdded(this);
}
} }
public AttractionPointImpl(String name, PositionVector posVec, double weight, double radius, long pauseTimeMin, long pauseTimeMax) { public AttractionPointImpl(String name, PositionVector posVec, double weight, double radius, long pauseTimeMin, long pauseTimeMax) {
...@@ -168,4 +175,9 @@ public class AttractionPointImpl extends BasicAttractionPoint { ...@@ -168,4 +175,9 @@ public class AttractionPointImpl extends BasicAttractionPoint {
public boolean hasRadius() { public boolean hasRadius() {
return true; return true;
} }
@Override
public String toString() {
return getName();
}
} }
...@@ -26,7 +26,9 @@ import java.util.Map; ...@@ -26,7 +26,9 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ISocialGroupMovementAnalyzer;
import de.tud.kom.p2psim.impl.util.Tuple; import de.tud.kom.p2psim.impl.util.Tuple;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
/** /**
...@@ -103,10 +105,10 @@ public class MovementGroupContainer { ...@@ -103,10 +105,10 @@ public class MovementGroupContainer {
*/ */
public void removeGroup(SocialMovementGroup group) { public void removeGroup(SocialMovementGroup group) {
for(SimLocationActuator participant : group.getMembers()) { for(SimLocationActuator participant : group.getMembers()) {
leftGroupAtTime.put(participant, Time.getCurrentTime()); leftGroupAtTime.put(participant, Time.getCurrentTime());
} }
waitingGroups.remove(group); waitingGroups.remove(group);
groups.remove(group); groups.remove(group);
} }
/** /**
......
...@@ -26,6 +26,7 @@ import java.util.Set; ...@@ -26,6 +26,7 @@ import java.util.Set;
import de.tud.kom.p2psim.api.scenario.ConfigurationException; import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ISocialGroupMovementAnalyzer;
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.MovementGroupContainer; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.MovementGroupContainer;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
...@@ -33,6 +34,7 @@ import de.tud.kom.p2psim.impl.topology.util.PositionVector; ...@@ -33,6 +34,7 @@ import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.util.Tuple; import de.tud.kom.p2psim.impl.util.Tuple;
import de.tudarmstadt.maki.simonstrator.api.Event; import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler; import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.common.datastructures.Pair; import de.tudarmstadt.maki.simonstrator.api.common.datastructures.Pair;
...@@ -91,8 +93,13 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -91,8 +93,13 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
} }
} }
@Override /**
public Set<Pair<SocialMovementGroup>> getEncounteringGroups() { * Checks if any of the current groups come in a close range which is equivalent to a group meeting.
* Calls the handleGroupEncounters(Group, Group) method to define the group behavior.
*
* @return
*/
private Set<Pair<SocialMovementGroup>> getEncounteringGroups() {
if(!enableGroupEncounters) if(!enableGroupEncounters)
return null; return null;
...@@ -147,7 +154,13 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -147,7 +154,13 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
} }
for(Pair<SocialMovementGroup> encounter : encounteringGroups) { for(Pair<SocialMovementGroup> encounter : encounteringGroups) {
if(groupCon.hasGroup(encounter.getFirst()) && groupCon.hasGroup(encounter.getSecond())) { if(groupCon.hasGroup(encounter.getFirst()) && groupCon.hasGroup(encounter.getSecond())) {
// Inform analyzer of resolved movement
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupEncounter(encounter.getFirst(), encounter.getSecond());
}
handleGroupEncounter(encounter.getFirst(), encounter.getSecond()); handleGroupEncounter(encounter.getFirst(), encounter.getSecond());
} }
} }
...@@ -230,21 +243,13 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -230,21 +243,13 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
* *
*/ */
protected void dissolveGroups(SocialMovementGroup group1, SocialMovementGroup group2) { protected void dissolveGroups(SocialMovementGroup group1, SocialMovementGroup group2) {
groupCon.updateMergeVars(group1, group2); groupCon.updateMergeVars(group1, group2);
if(groupCon.getGroups().contains(group1) && groupCon.getGroups().contains(group2)) { if(groupCon.getGroups().contains(group1)) {
for(SimLocationActuator participant : group1.getMembers()) {
groupCon.addLeftGroupAtTimeEntry(participant, Time.getCurrentTime());
movementModel.getAttractionAssignmentStrategy().addComponent(participant);
}
for(SimLocationActuator participant : group2.getMembers()) {
groupCon.addLeftGroupAtTimeEntry(participant, Time.getCurrentTime());
movementModel.getAttractionAssignmentStrategy().addComponent(participant);
}
movementModel.getGroupFormingBehavior().removeGroup(group1); movementModel.getGroupFormingBehavior().removeGroup(group1);
}
if(groupCon.getGroups().contains(group2)) {
movementModel.getGroupFormingBehavior().removeGroup(group2); movementModel.getGroupFormingBehavior().removeGroup(group2);
} }
} }
...@@ -260,6 +265,11 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -260,6 +265,11 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
protected SocialMovementGroup mergeGroupsFully(SocialMovementGroup group1, SocialMovementGroup group2) { protected SocialMovementGroup mergeGroupsFully(SocialMovementGroup group1, SocialMovementGroup group2) {
groupCon.updateMergeVars(group1, group2); groupCon.updateMergeVars(group1, group2);
// Inform analyzer of resolved movement
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupMerge(group1, group2);
}
SocialMovementGroup large = getLargerGroup(group1, group2); SocialMovementGroup large = getLargerGroup(group1, group2);
SocialMovementGroup small = getSmallerGroup(group1, group2); SocialMovementGroup small = getSmallerGroup(group1, group2);
...@@ -272,7 +282,7 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -272,7 +282,7 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
} }
movementModel.getGroupFormingBehavior().removeGroup(small); movementModel.getGroupFormingBehavior().removeGroup(small);
return large; return large;
} }
...@@ -302,13 +312,24 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -302,13 +312,24 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
groupCon.updateGroupEntry(small); groupCon.updateGroupEntry(small);
groupCon.updateGroupEntry(large); groupCon.updateGroupEntry(large);
} }
// Inform analyzer of resolved movement
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupMerge(group1, group2);
}
} }
} }
protected void wait(SocialMovementGroup group, long timeToWait) { protected void wait(SocialMovementGroup group, long timeToWait) {
// only start the waiting process if not already waiting (duh!) // only start the waiting process if not already waiting (duh!)
if(!groupCon.waitingGroups.containsKey(group)) { if(!groupCon.waitingGroups.containsKey(group)) {
// Inform analyzer of resolved movement
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupWait(group);
}
groupCon.waitingGroups.put(group, new Tuple<Long, Long>(timeToWait, Time.getCurrentTime())); groupCon.waitingGroups.put(group, new Tuple<Long, Long>(timeToWait, Time.getCurrentTime()));
Event.scheduleWithDelay(timeToWait, new EventHandler() { Event.scheduleWithDelay(timeToWait, new EventHandler() {
@Override @Override
......
...@@ -39,14 +39,7 @@ public interface IGroupEncounterBehavior { ...@@ -39,14 +39,7 @@ public interface IGroupEncounterBehavior {
* *
*/ */
void initialize(SocialGroupMovementModel movementModel); void initialize(SocialGroupMovementModel movementModel);
/**
* Checks if any of the current groups come in a close range which is equivalent to a group meeting.
* Calls the handleGroupEncounters(Group, Group) method to define the group behavior.
*
* @return
*/
Set<Pair<SocialMovementGroup>> getEncounteringGroups();
/** /**
* Applies an encountering action to each detected encountering groups. * Applies an encountering action to each detected encountering groups.
......
...@@ -27,6 +27,7 @@ import java.util.Set; ...@@ -27,6 +27,7 @@ import java.util.Set;
import de.tud.kom.p2psim.api.scenario.ConfigurationException; import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ISocialGroupMovementAnalyzer;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementModel; import de.tud.kom.p2psim.impl.topology.movement.modularosm.SocialGroupMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.BasicAttractionPoint; import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.BasicAttractionPoint;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator; import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
...@@ -37,6 +38,7 @@ import de.tud.kom.p2psim.impl.topology.util.PositionVector; ...@@ -37,6 +38,7 @@ import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.util.Tuple; import de.tud.kom.p2psim.impl.util.Tuple;
import de.tudarmstadt.maki.simonstrator.api.Event; import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler; import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID; import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID;
...@@ -183,8 +185,8 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -183,8 +185,8 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
protected void createGroup(Set<SimLocationActuator> members) { protected void createGroup(Set<SimLocationActuator> members) {
SocialMovementGroup group = new SocialMovementGroup(members); SocialMovementGroup group = new SocialMovementGroup(members);
movementModel.getAttractionAssignmentStrategy().addComponent(group.getLeader()); // FIXME move to movement model
movementModel.getAttractionAssignmentStrategy().addComponent(group.getLeader());
IAttractionPoint nextDestination = movementModel.getAttractionAssignmentStrategy().getAssignment(group.getLeader()); IAttractionPoint nextDestination = movementModel.getAttractionAssignmentStrategy().getAssignment(group.getLeader());
// Add Offset to group destination // Add Offset to group destination
...@@ -202,6 +204,11 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -202,6 +204,11 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
} }
groupCon.addGroup(group); groupCon.addGroup(group);
// Inform analyzer of new group
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupForming(group);
}
} }
/** /**
...@@ -212,6 +219,22 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -212,6 +219,22 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
*/ */
@Override @Override
public void removeGroup(SocialMovementGroup group) { public void removeGroup(SocialMovementGroup group) {
// Inform analyzer of group removal
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupDisbanding(group);
}
// If this group is removed, reassign the group target attraction point as new target attraction point
// for each former group member (prevents errors when routing was not reset correctly)
if(group.getGroupSize() > 0 || group.getLeader() != null) {
IAttractionPoint currentAP = group.getLeader().getCurrentTargetAttractionPoint();
for (SimLocationActuator host : group.getMembers()) {
movementModel.updatedAttractionAssignment(host, currentAP);
}
}
groupCon.removeGroup(group); groupCon.removeGroup(group);
long delay = 0; long delay = 0;
...@@ -227,17 +250,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -227,17 +250,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
else { else {
delay = rndGroupFormationDelay(); delay = rndGroupFormationDelay();
} }
if(group.getGroupSize() > 0 || group.getLeader() != null) {
IAttractionPoint currentAP = group.getLeader().getCurrentTargetAttractionPoint();
for (SimLocationActuator host : group.getMembers()) {
movementModel.updatedAttractionAssignment(host, currentAP);
}
}
Event.scheduleWithDelay(delay, new EventHandler() { Event.scheduleWithDelay(delay, new EventHandler() {
@Override @Override
public void eventOccurred(Object content, int type) { public void eventOccurred(Object content, int type) {
...@@ -339,7 +352,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -339,7 +352,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
// Update target for all group members to meeting point // Update target for all group members to meeting point
for(SimLocationActuator participant : group.getMembers()) { for(SimLocationActuator participant : group.getMembers()) {
movementModel.getAttractionAssignmentStrategy().updateTargetAttractionPoint(participant, meetingPoint); //movementModel.getAttractionAssignmentStrategy().updateTargetAttractionPoint(participant, meetingPoint);
} }
} }
......
...@@ -149,7 +149,8 @@ public class DefaultGroupForming extends AbstractGroupForming { ...@@ -149,7 +149,8 @@ public class DefaultGroupForming extends AbstractGroupForming {
} }
// if there are no candidates, wait a minute until asking again // if there are no candidates, wait a minute until asking again
if(groupCandidates.isEmpty() || groupCandidates == null) { if(groupCandidates.isEmpty() || groupCandidates == null || groupCandidates.size() < minGroupSize) {
Event.scheduleWithDelay(Time.MINUTE, new EventHandler() { Event.scheduleWithDelay(Time.MINUTE, new EventHandler() {
@Override @Override
public void eventOccurred(Object content, int type) { public void eventOccurred(Object content, int type) {
......
...@@ -27,7 +27,9 @@ import java.util.Map; ...@@ -27,7 +27,9 @@ import java.util.Map;
import java.util.Random; import java.util.Random;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.IAttractionBasedMovementAnalyzer;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator; import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
...@@ -86,6 +88,11 @@ public abstract class AbstractAttractionBasedAssignmentStrategy implements IAttr ...@@ -86,6 +88,11 @@ public abstract class AbstractAttractionBasedAssignmentStrategy implements IAttr
protected void notifyListenersOfAssignmentUpdate(SimLocationActuator comp, protected void notifyListenersOfAssignmentUpdate(SimLocationActuator comp,
IAttractionPoint attractionPoint) { IAttractionPoint attractionPoint) {
listeners.forEach(listener -> listener.updatedAttractionAssignment(comp, attractionPoint)); listeners.forEach(listener -> listener.updatedAttractionAssignment(comp, attractionPoint));
// also iInform analyzer of assigment update
if(Monitor.hasAnalyzer(IAttractionBasedMovementAnalyzer.class)) {
Monitor.getOrNull(IAttractionBasedMovementAnalyzer.class).onUpdateAttractionAssignment(comp, attractionPoint);
}
} }
@Override @Override
...@@ -95,7 +102,7 @@ public abstract class AbstractAttractionBasedAssignmentStrategy implements IAttr ...@@ -95,7 +102,7 @@ public abstract class AbstractAttractionBasedAssignmentStrategy implements IAttr
this.lastAssignments.put(comp, this.assignments.remove(comp)); this.lastAssignments.put(comp, this.assignments.remove(comp));
} }
this.assignments.put(comp, attractionPoint); this.assignments.put(comp, attractionPoint);
notifyListenersOfAssignmentUpdate(comp, attractionPoint); notifyListenersOfAssignmentUpdate(comp, attractionPoint);
} }
private long getRandomUniformDistributionPauseTime(IAttractionPoint attractionPoint) { private long getRandomUniformDistributionPauseTime(IAttractionPoint attractionPoint) {
......
...@@ -23,10 +23,12 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition; ...@@ -23,10 +23,12 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ISocialGroupMovementAnalyzer;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel; import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator; import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tudarmstadt.maki.simonstrator.api.Event; import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler; import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
...@@ -66,10 +68,13 @@ public class AttractionPointRoamingStrategy extends AbstractAttractionBasedAssig ...@@ -66,10 +68,13 @@ public class AttractionPointRoamingStrategy extends AbstractAttractionBasedAssig
return; return;
} }
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onNodeReachedAttractionPoint(comp, attractionPoint);
}
this.roamingStates.put(comp, roamingTransitionState.PAUSE); this.roamingStates.put(comp, roamingTransitionState.PAUSE);
// schedule roaming // schedule roaming
Event.scheduleWithDelay(Math.max(Time.MINUTE, gaussianDistributionPauseTime(5 * Time.MINUTE, 1 * Time.MINUTE)), this, comp, 0); Event.scheduleWithDelay(Math.max(Time.MINUTE, gaussianDistributionPauseTime(5 * Time.MINUTE, 1 * Time.MINUTE)), this, comp, 0);
} }
/** /**
...@@ -87,8 +92,7 @@ public class AttractionPointRoamingStrategy extends AbstractAttractionBasedAssig ...@@ -87,8 +92,7 @@ public class AttractionPointRoamingStrategy extends AbstractAttractionBasedAssig
if(roamingStates.get(comp) == roamingTransitionState.PAUSE) { if(roamingStates.get(comp) == roamingTransitionState.PAUSE) {
IAttractionPoint currentAttractionPoint = this.assignments.get(comp); IAttractionPoint currentAttractionPoint = this.assignments.get(comp);
this.roamingStates.put(comp, roamingTransitionState.ROAMING); this.roamingStates.put(comp, roamingTransitionState.ROAMING);
notifyListenersOfAssignmentUpdate(comp, currentAttractionPoint); notifyListenersOfAssignmentUpdate(comp, currentAttractionPoint);
} }
} }
...@@ -106,7 +110,4 @@ public class AttractionPointRoamingStrategy extends AbstractAttractionBasedAssig ...@@ -106,7 +110,4 @@ public class AttractionPointRoamingStrategy extends AbstractAttractionBasedAssig
this.roamAroundAttractionPoint(comp); this.roamAroundAttractionPoint(comp);
} }
} }
}
\ No newline at end of file
}
...@@ -23,10 +23,12 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition; ...@@ -23,10 +23,12 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ISocialGroupMovementAnalyzer;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel; import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator; import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tudarmstadt.maki.simonstrator.api.Event; import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler; import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
...@@ -71,6 +73,11 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedAssi ...@@ -71,6 +73,11 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedAssi
return; return;
} }
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onNodeReachedAttractionPoint(comp, attractionPoint);
}
// start roaming if the AP was reached // start roaming if the AP was reached
if(roamingStates.get(comp) == roamingTransitionState.TRANSITION) { if(roamingStates.get(comp) == roamingTransitionState.TRANSITION) {
// schedule the end of the roaming phase, which will make a new transition // schedule the end of the roaming phase, which will make a new transition
......
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