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

Small scenario movement for groups with file actions

parent c6817b8d
/*
* 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 java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import com.fasterxml.jackson.databind.introspect.TypeResolutionContext.Basic;
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.scenario.DefaultConfigurator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.BasicAttractionPoint;
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.util.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.util.Either;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event;
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.Monitor.Level;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.*;
public class ProgrammableSmallScenarioMovement extends ModularMovementModel {
private File actionsFile;
private final double LEADER_GROUP_DISTANCE = 10;
protected MovementGroupContainer groupContainer;
private LinkedHashMap<String, SocialMovementGroup> groups = new LinkedHashMap<>();
@Override
public void initialize() {
if (!initialized) {
groupContainer = MovementGroupContainer.getInstance();
if (modelVisualisation == null) {
modelVisualisation = new ModularMovementModelViz(this);
}
VisualizationInjector.injectComponent(modelVisualisation);
if (mapVisualization != null) {
VisualizationInjector.injectComponent(mapVisualization);
}
if (attractionPointViz != null) {
System.out.println("insert AP viz");
VisualizationInjector.injectComponent(attractionPointViz);
}
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);
attractionAssigment.setAttractionProvider(attractionProvider);
parseActionsFile();
// This adds the mobile hosts (smartphones/users) to the transition
// strategy
for (SimLocationActuator ms : moveableHosts) {
// TODO select hosts for APs and group
// TODO place hosts appopriately
attractionAssigment.addComponent(ms);
IAttractionPoint assignment = attractionAssigment.getAssignment(ms);
ms.updateCurrentLocation(this.addOffset(new PositionVector(assignment),
(assignment.hasRadius() ? Math.max(assignment.getRadius(), 25.0) : 25.0)));
attractionAssigment.updateTargetAttractionPoint(ms, assignment);
}
setTimeBetweenMoveOperations(timeBetweenMoveOperation);
// Inform analyzer of resolved movement
if(Monitor.hasAnalyzer(IAttractionBasedMovementAnalyzer.class)) {
Monitor.getOrNull(IAttractionBasedMovementAnalyzer.class).onAllNodeInitializationCompleted(moveableHosts);
}
// initial move
move();
initialized = true;
}
}
/**
* Returns a random SimLocationActuator component from the set of moveable hosts.
*
* @return SimLocationActuator
*/
private SimLocationActuator getRandomActuator() {
int index = rand.nextInt(moveableHosts.size());
int i = 0;
for(SimLocationActuator actuator : moveableHosts) {
if(i == index) {
return actuator;
}
i++;
}
return null;
}
/**
* The movement model.
* 1) Updates the number of hosts within each attraction point.
* 2) Creates and deletes groups, if necessary.
* 3) Applies encounter action to meeting groups.
* 4) Moves the hosts using doGroupMovement, movement style depends on role of the host (Leader, Participant, Single)
*/
@Override
protected void move() {
for (SocialMovementGroup group : groups.values()) {
doLeaderMovement(group.getLeader(), currentTargets.get(group.getLeader()));
// set location around leader
for (SimLocationActuator host : group.getMembers()) {
followLeader(group.getLeader(), host);
}
}
super.move();
}
private void doLeaderMovement(SimLocationActuator ms, PositionVector destination) {
Either<PositionVector, Boolean> either = localMovementStrategy.nextPosition(ms, destination);
if (either.hasLeft()) {
ms.updateCurrentLocation(either.getLeft());
if(!checkBoundaries(ms.getRealPosition())) {
System.err.println("Modular Movement Model: Host moved outside of simulated area!");
}
}
else {
PositionVector roam = this.addOffset(destination, 5);
ms.setTargetAttractionPoint(new BasicAttractionPoint("Roam", roam));
}
}
@Override
public void updatedAttractionAssignment(SimLocationActuator component,
IAttractionPoint newAssignment) {
if(moveableHosts.contains(component)) {
super.updatedAttractionAssignment(component, newAssignment);
}
else {
currentTargets.put(component, (PositionVector) newAssignment);
}
}
/**
* Host position adapts to leaders position by taking the leader position and adding a small offset
*
* @param SimLocationActuator The host to be moved.
*/
private void followLeader(SimLocationActuator leader, SimLocationActuator host) {
// do nothing if leader is the same as host
if(leader == host)
return;
// Assign small offset to the host depending on the leaders position.
PositionVector leaderPos = leader.getRealPosition();
PositionVector offset = new PositionVector(rand.nextDouble() * LEADER_GROUP_DISTANCE, rand.nextDouble() * LEADER_GROUP_DISTANCE);
PositionVector newPos = leaderPos.plus(offset);
// Update location of host, which will be around the leaders location.
host.updateCurrentLocation(newPos);
}
/*
* =====================================================================================================
* === GETTER AND SETTER FUNCTIONS
* =====================================================================================================
*/
public LocalMovementStrategy getMovementStrategy() {
return localMovementStrategy;
}
public LinkedHashMap<SimLocationActuator, PositionVector> getCurrentTargets(){
return currentTargets;
}
/*
* =====================================================================================================
* === STUFF
* =====================================================================================================
*/
public void setActionFile(String filename) {
actionsFile = new File(filename);
}
private void parseActionsFile() {
// read file with actions, parse them and store as list.
try {
BufferedReader in = new BufferedReader(new FileReader(actionsFile));
String line;
int lineCounter = 0;
int groupNumber = -1;
while ((line = in.readLine()) != null) {
if (line.length() == 0 || line.startsWith("#"))
continue;
else {
String[] tokens = line.split(" ");
if(lineCounter == 0) {
groupNumber = Integer.parseInt(tokens[0]);
System.out.println(groupNumber + " groups");
}
else if(lineCounter >= 1 && lineCounter <= groupNumber) {
String name = tokens[0];
SocialMovementGroup group = new SocialMovementGroup();
int n = Integer.parseInt(tokens[1]);
LinkedList<SimLocationActuator> hosts = new LinkedList<>(moveableHosts.stream().limit(n).toList());
moveableHosts.removeAll(hosts);
// set group members
group.setMembers(new LinkedHashSet<>(hosts));
// pick leader
SimLocationActuator leader = group.getLeader();
// set leader position
int x = Integer.parseInt(tokens[2]);
int y = Integer.parseInt(tokens[3]);
leader.updateCurrentLocation(new PositionVector(x, y));
// set location around leader
for (SimLocationActuator host : group.getMembers()) {
followLeader(leader, host);
}
leader.setTargetAttractionPoint(new BasicAttractionPoint("Group"+name+"Start", new PositionVector(x, y)));
//attractionAssigment.updateTargetAttractionPoint(leader, new BasicAttractionPoint("Group"+name+"Start", new PositionVector(x, y)));
System.out.println("Group " + name + " at " + x + " / " + y);
groups.put(name, group);
}
else {
String name = tokens[0];
long time = DefaultConfigurator.parseNumber(tokens[1], Long.class);
int x = Integer.parseInt(tokens[2]);
int y = Integer.parseInt(tokens[3]);
BasicAttractionPoint target = new BasicAttractionPoint("Group"+name+"-"+Time.getFormattedTime(time), new PositionVector(x, y));
System.out.println("Group " + name + " to " + x + " / " + y + " at " + Time.getFormattedTime(time));
Event.scheduleWithDelay(time, new EventHandler() {
@Override
public void eventOccurred(Object content, int type) {
groups.get(name).getLeader().setTargetAttractionPoint(target);
System.out.println(name + " moving towards " + target);
}
}, target, 0);
}
lineCounter++;
}
}
Monitor.log(ProgrammableSmallScenarioMovement.class, Level.INFO, "Created "
+ groupNumber + " groups");
} catch (IOException e) {
throw new ConfigurationException("Failed to parse " + actionsFile
+ " reason: ", e);
}
}
}
......@@ -52,12 +52,9 @@ public class SocialMovementGroup {
* @param SimLocationActuator New leader of the group
* @param int The ID of the group.
*/
public SocialMovementGroup(SimLocationActuator leader) {
this.groupID = UUID.randomUUID();
this.leader = leader;
this.members = new LinkedHashSet<SimLocationActuator>();
public SocialMovementGroup(SimLocationActuator leader) {
this();
this.leader = leader;
this.members.add(leader);
}
......@@ -68,12 +65,19 @@ public class SocialMovementGroup {
* @param int The ID of the group.
*/
public SocialMovementGroup(LinkedHashSet<SimLocationActuator> participants) {
this.groupID = UUID.randomUUID();
this();
setMembers(participants);
setRandomLeader();
}
/**
* Empty initialization with group ID.
*
*/
public SocialMovementGroup() {
this.groupID = UUID.randomUUID();
this.members = new LinkedHashSet<SimLocationActuator>();
}
/**
* Adds a host to the group. Manually check in {@link ModularMovementModel} class, if group size is exceeded by adding another host.
......@@ -152,7 +156,7 @@ public class SocialMovementGroup {
* @return PositionVector The position of the group leader.
*/
public PositionVector getLeaderPosition() {
return leader.getRealPosition();
return getLeader().getRealPosition();
}
@Override
......@@ -178,6 +182,10 @@ public class SocialMovementGroup {
}
public SimLocationActuator getLeader() {
if(leader == null && members.size() > 0) {
this.setRandomLeader();
}
return leader;
}
......
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