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

Now multiple groups can meet each other and wait (+smart merge). Wait Time is...

Now multiple groups can meet each other and wait (+smart merge). Wait Time is adapted to the encountered group and not reset to full time (prevents single group waiting).

Problems in Routing?
parent 4b8eaefe
......@@ -190,7 +190,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
attractionAssigment.updateTargetAttractionPoint(actuator, ap);
}
private void checkConfiguration() {
protected void checkConfiguration() {
if (localMovementStrategy == null) {
throw new ConfigurationException(
"LocalMovementStrategy is missing in ModularMovementModel!");
......
......@@ -28,6 +28,7 @@ import java.util.Set;
import java.util.Vector;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.movement.local.LocalMovementStrategy;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
......@@ -38,7 +39,10 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounter
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupforming.IGroupFormingBehavior;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.IAttractionAssigmentStrategy;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
/**
......@@ -55,10 +59,16 @@ public class SocialGroupMovementModel extends ModularMovementModel {
private Set<SimLocationActuator> singleHosts = new LinkedHashSet<SimLocationActuator>();
private int numberOfSingleHosts;
private boolean placeNodesAtAP = false;
public void setPlaceNodes(boolean placeNodes) {
this.placeNodesAtAP = placeNodes;
}
@Override
public void initialize() {
if (!initialized) {
groupContainer = MovementGroupContainer.getInstance();
attractionPointHostCounter.initialize(this);
......@@ -72,10 +82,53 @@ public class SocialGroupMovementModel extends ModularMovementModel {
} while(singleHosts.size() < numberOfSingleHosts);
}
super.initialize();
if (modelVisualisation == null) {
modelVisualisation = new ModularMovementModelViz(this);
}
VisualizationInjector.injectComponent(modelVisualisation);
if (mapVisualization != null) {
VisualizationInjector.injectComponent(mapVisualization);
}
checkConfiguration();
// setWayPointModel
localMovementStrategy.setObstacleModel(Binder
.getComponentOrNull(Topology.class).getObstacleModel());
localMovementStrategy.setWaypointModel(Binder
.getComponentOrNull(Topology.class).getWaypointModel());
/*
* Scale depending on calculation interval, if interval != 1 Second.
*/
localMovementStrategy
.setScaleFactor(timeBetweenMoveOperation / (double) Time.SECOND);
attractionAssigment.addAttractionAssignmentListener(this);
// This adds the mobile hosts (smartphones/users) to the transition
// strategy
for (SimLocationActuator ms : moveableHosts) {
attractionAssigment.addComponent(ms);
if(placeNodesAtAP)
ms.updateCurrentLocation(attractionAssigment.getAssignment(ms));
}
setTimeBetweenMoveOperations(timeBetweenMoveOperation);
// initial move
move();
initialized = true;
}
}
/**
* Returns a random SimLocationActuator component from the set of moveable hosts.
*
......@@ -119,6 +172,18 @@ public class SocialGroupMovementModel extends ModularMovementModel {
*/
for (SimLocationActuator component : moveableHosts) {
assert currentTargets.containsKey(component);
if(component.getHost().getId().value() == 74) {
if(component.getCurrentTargetAttractionPoint().distanceTo(component.getRealPosition())
> component.getCurrentTargetAttractionPoint().getRadius()) {
System.out.println(currentTargets.get(component));
System.out.println(component.getRealPosition());
System.out.println(component.getCurrentTargetAttractionPoint());
System.out.println(component.getCurrentTargetAttractionPoint().distanceTo(component.getRealPosition()));
System.out.println("==");
}
}
doGroupMovement(component, currentTargets.get(component));
}
Event.scheduleWithDelay(timeBetweenMoveOperation, this, null, EVENT_MOVE);
......
......@@ -105,6 +105,7 @@ public class MovementGroupContainer {
for(SimLocationActuator participant : group.getMembers()) {
leftGroupAtTime.put(participant, Time.getCurrentTime());
}
waitingGroups.remove(group);
groups.remove(group);
}
......@@ -233,13 +234,18 @@ public class MovementGroupContainer {
* @param SocialMovementGroup The first group.
* @param SocialMovementGroup The second group.
*
* @author Marcel Verst
*/
public void updateMergeVars(SocialMovementGroup group1, SocialMovementGroup group2) {
Set<SimLocationActuator> all = new LinkedHashSet<>();
all.addAll(group1.getMembers());
all.addAll(group2.getMembers());
for(SimLocationActuator host : all) {
updateMergeVars(group1);
updateMergeVars(group2);
}
public void updateMergeVars(SocialMovementGroup group) {
if(group == null || group.getMembers().isEmpty()) {
return;
}
for(SimLocationActuator host : group.getMembers()) {
addHasMergedEntry(host, true);
addMergedAtTimeEntry(host, Time.getCurrentTime());
}
......
......@@ -135,6 +135,12 @@ public class SocialMovementGroup {
return leader.getRealPosition();
}
@Override
public String toString() {
return "Social Group of #" + leader.getHost().getId() + " ("+ members.size() +")";
}
// ===================
// Getters and Setters
// ===================
......
......@@ -31,6 +31,8 @@ import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.MovementGroupC
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
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.datastructures.Pair;
......@@ -253,11 +255,12 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
* @param SocialMovementGroup The first group.
* @param SocialMovementGroup The second group.
*
* @return Returns the merged group
*/
protected void mergeGroupsFully(SocialMovementGroup group1, SocialMovementGroup group2) {
protected SocialMovementGroup mergeGroupsFully(SocialMovementGroup group1, SocialMovementGroup group2) {
groupCon.updateMergeVars(group1, group2);
System.out.println("merge groups!");
System.out.println("merge groups | " + group1 + "| " + group2 );
SocialMovementGroup large = getLargerGroup(group1, group2);
SocialMovementGroup small = getSmallerGroup(group1, group2);
......@@ -271,6 +274,8 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
}
movementModel.getGroupFormingBehavior().removeGroup(small);
return large;
}
/**
......@@ -302,45 +307,50 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
}
}
/**
* Assigns two groups the role to wait for a specified amount of time. After waiting for this time,
* the groups are released from the waiting role and can continue their trip.
*
* @param SocialMovementGroup The first group.
* @param SocialMovementGroup The second group.
*/
protected void wait(SocialMovementGroup group1, SocialMovementGroup group2, long timeToWait) {
// Do not apply waiting process if one of both groups is already waiting
if(groupCon.waitingGroups.containsKey(group1) ^ groupCon.waitingGroups.containsKey(group2)) {
return;
}
// If both groups are not waiting, declare them as waiting groups for a duration of timeToWait
if(!groupCon.waitingGroups.containsKey(group1) && !groupCon.waitingGroups.containsKey(group2)) {
groupCon.waitingGroups.put(group1, new Tuple<Long, Long>(timeToWait, Time.getCurrentTime()));
groupCon.waitingGroups.put(group2, new Tuple<Long, Long>(timeToWait, Time.getCurrentTime()));
}
// If both groups are already waiting
if(groupCon.waitingGroups.containsKey(group1) && groupCon.waitingGroups.containsKey(group2)) {
long timerGroup1 = groupCon.waitingGroups.get(group1).getA();
long timerGroup2 = groupCon.waitingGroups.get(group2).getA();
// Remove groups if they have waited long enough
if(timerGroup1 <= 0 && timerGroup2 <= 0) {
groupCon.updateMergeVars(group1, group2);
groupCon.waitingGroups.remove(group1);
groupCon.waitingGroups.remove(group2);
}
// Decrement timer of both groups if they have to wait more
else {
long deltaGroup1 = Time.getCurrentTime() - groupCon.waitingGroups.get(group1).getB();
groupCon.waitingGroups.put(group1, new Tuple<Long, Long>(timerGroup1 - deltaGroup1, Time.getCurrentTime()));
protected void wait(SocialMovementGroup group, long timeToWait) {
// Do not apply waiting process if one of both groups is already waiting
if(!groupCon.waitingGroups.containsKey(group)) {
// long timer = groupCon.waitingGroups.get(group).getA();
// long delta = Time.getCurrentTime() - groupCon.waitingGroups.get(group).getB();
// System.out.println("Group " + group.getLeader().getHost().getId());
// System.out.println(Time.getFormattedTime(timer) + " TTW");
// System.out.println(Time.getFormattedTime(delta) + " delta");
//
// // Remove groups if they have waited long enough
// if(delta >= timer) {
// System.out.println(" Delta >= Timer --- remove...");
// groupCon.updateMergeVars(group);
// groupCon.waitingGroups.remove(group);
// }
// else {
// System.out.println(" wait more... ");
// }
//
// System.out.println(" == ");
// }
// else {
System.out.println("new Waiting group : " + group.getLeader().getHost().getId() );
groupCon.waitingGroups.put(group, new Tuple<Long, Long>(timeToWait, Time.getCurrentTime()));
Event.scheduleWithDelay(timeToWait, new EventHandler() {
long deltaGroup2 = Time.getCurrentTime() - groupCon.waitingGroups.get(group2).getB();
groupCon.waitingGroups.put(group2, new Tuple<Long, Long>(timerGroup2 - deltaGroup2, Time.getCurrentTime()));
}
@Override
public void eventOccurred(Object content, int type) {
SocialMovementGroup g = (SocialMovementGroup) content;
if(!groupCon.hasGroup(g)) {
System.out.println("group NULL");
return;
}
System.out.println(" Timer expired for " + g);
groupCon.updateMergeVars(g);
groupCon.waitingGroups.remove(g);
}
}, group, 0);
}
}
......
......@@ -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.Time;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
......@@ -34,8 +35,8 @@ import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
*/
public class Wait extends AbstractGroupEncounter{
//--- VARIABLES TO BE DECLARED IN CONFIG ---
private double probabilityToWait;
private long timeToWait;
protected double probabilityToWait;
protected long timeToWait;
//------------------------------------------
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
......@@ -49,10 +50,15 @@ public class Wait extends AbstractGroupEncounter{
@Override
public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) {
if(rand.nextDouble() <= probabilityToWait) {
wait(group1, group2, timeToWait);
long waittime = getRandomWaitTime();
wait(group1, waittime);
wait(group2, waittime);
}
}
protected long getRandomWaitTime() {
return (long) Math.max(Time.MINUTE, (rand.nextDouble() + 0.5) * timeToWait);
}
/*
* GETTERS AND SETTERS
......
......@@ -20,8 +20,8 @@
package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.groupencounter;
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.Time;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
......@@ -30,11 +30,7 @@ import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
* @author Julian Zobel
* @version 1.0, 04.02.2020
*/
public class WaitSmartMerge extends AbstractGroupEncounter{
//--- VARIABLES TO BE DECLARED IN CONFIG ---
private double probabilityToWait;
private long timeToWait;
//------------------------------------------
public class WaitSmartMerge extends Wait{
@XMLConfigurableConstructor({"enableGroupEncounters","groupEncounterMeetingDistance","groupReencounterWaitTime"})
public WaitSmartMerge(boolean enableGroupEncounters,
......@@ -47,31 +43,42 @@ public class WaitSmartMerge extends AbstractGroupEncounter{
@Override
public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) {
long pauseTime = getRandomWaitTime();
if(groupCon.waitingGroups.containsKey(group1) && !groupCon.waitingGroups.containsKey(group2)) {
pauseTime =getRemainingGroupWaitTime(group1);
}
else if(!groupCon.waitingGroups.containsKey(group1) && groupCon.waitingGroups.containsKey(group2)) {
pauseTime =getRemainingGroupWaitTime(group2);
}
if(group1.getLeader().getCurrentTargetAttractionPoint() == group2.getLeader().getCurrentTargetAttractionPoint()) {
mergeGroupsFully(group1, group2);
SocialMovementGroup merged = mergeGroupsFully(group1, group2);
wait(merged, getRandomWaitTime());
}
else if(rand.nextDouble() <= probabilityToWait) {
wait(group1, group2, timeToWait);
long time = getRandomWaitTime();
wait(group1, time);
wait(group2, time);
}
}
/*
* GETTERS AND SETTERS
*/
public void setProbabilityToWait(double probabilityToWait) {
if (probabilityToWait < 0 || probabilityToWait > 1.0) {
throw new ConfigurationException(
"probabilityToWait should be between 0.0 and 1.0!");
}
this.probabilityToWait = probabilityToWait;
}
public void setTimeToWait(long timeToWait) {
if(timeToWait < 0) {
throw new ConfigurationException(
"timeToWait should be greater or equal than 0!");
}
this.timeToWait = timeToWait;
private long getRemainingGroupWaitTime(SocialMovementGroup group) {
long pausetime = groupCon.waitingGroups.get(group).getA();
long issueTime = groupCon.waitingGroups.get(group).getB();
long remaining = issueTime + pausetime - Time.getCurrentTime();
System.out.println(Time.getFormattedTime(remaining) + " remaining of " + group);
return remaining;
}
}
......@@ -26,7 +26,6 @@ import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
......@@ -130,9 +129,7 @@ public class JSONPlacement implements PlacementModel {
}
public void setPlacementJsonFile(String placementJsonFile) {
this.placementJsonFile = placementJsonFile;
this.placementJsonFile = placementJsonFile;
}
......
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