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

- Social Movement Monitors

- Smarter Movement classes and analyzers
parent dce6451f
/*
* 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;
import java.io.File;
import java.util.LinkedHashSet;
import java.util.Set;
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.smarter.dataanalyzer.Analyzer;
import de.tud.kom.p2psim.impl.topology.movement.smarter.dataanalyzer.Statistics;
import de.tud.kom.p2psim.impl.topology.movement.smarter.host.SmarterHost;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/**
* Represents the movement model of the acquired SMARTER traces. By calling the class an analyzing procedure is started which analyzes the
* .sqlite database files and creates If files in case they do not exist already.
* Adds and places components to the simulation based on the created If files.
*
* @author MarcelV
* @version 1.0, 12.06.2018
*/
public class SmarterMovementModelNew implements MovementModel, EventHandler {
private static final Location DEFAULT_LOCATION = new PositionVector(Double.NaN, Double.NaN);
public static SmarterMovementModelNew movement;
protected long timeBetweenMoveOperations;
boolean dataAnalyzed;
private Set<SimLocationActuator> actuatorList = new LinkedHashSet<SimLocationActuator>();
/**
* Creates the movement model and checks if the databases should be analyzed
*/
public SmarterMovementModelNew() {
movement = this;
dataAnalyzed = false;
// TODO get bool from xml to decide whether to analyze data or not
if(!dataAnalyzed)
analyzeData();
}
/**
* Returns the instance of this class
* @return instance of this class
*/
public static SmarterMovementModelNew getInstance() {
return movement;
}
/**
* Calculates statistics of the If files and stores them within a line for each host with the following format:
* id;distance;avgSpeed;idleTime;movingTime;phoneOutTime
*/
private void analyzeData() {
// Check if If files have been created in previous simulations. If not, create them.
if(!filesAlreadyExist()) {
// System.out.println("FILES DO NOT EXIST, CREATE NEW FILES.");
Analyzer analyzer = new Analyzer();
analyzer.analyzeTraces();
}else
// System.out.println("FILES ALREADY EXIST, SKIP FILE CREATION STEP.");
// Calculate statistics using the If files.
Statistics.clearFile();
for(int index = 1; index <= 125; index++) {
String filePath = "smarter/traces-mv/mobilityTraceFile-File-Modified-" + index + ".if";
Statistics stats = new Statistics(filePath);
stats.calcStatistics();
}
dataAnalyzed = true;
}
/**
* Checks if all 94 If files have already been created.
* @return true if files have been created, else false
*/
private boolean filesAlreadyExist() {
String folderName = "smarter/traces-mv/";
File folder = new File(folderName);
if (!folder.exists())
folder.mkdir();
int counter = 0;
for(File file : folder.listFiles()) {
String currentFile = file.getName();
for(int index = 1; index <= 125; index++) {
String tempFile = "mobilityTraceFile-File-Modified-" + index + ".if";
if(currentFile.equals(tempFile))
counter++;
}
}
// Total correct files collected from the fieldtest is 93 (removed file 116 due to Staumuehle appearance)!
if(counter == 93)
return true;
else
return false;
}
/**
* Is fired each time an event occured. Updates the location of the host and calculates the next location for the next call of this method
*/
@Override
public void eventOccurred(Object content, int type) {
SmarterHost host = (SmarterHost) content;
Location location = host.getNextLocation();
if (location != null) {
host.getActuator().updateCurrentLocation(location);
}
if (host.tryNextStep()) {
long sleepTime = host.getSleepTime();
// Reschedule next step
Event.scheduleWithDelay(sleepTime, this, host, 0);
}
}
/**
* Called once during simulation setup for each host. Creates a SmarterHost object at a default location.
*/
@Override
public void addComponent(SimLocationActuator actuator) {
actuator.updateCurrentLocation(DEFAULT_LOCATION);
if (!actuatorList.contains(actuator)) {
actuatorList.add(actuator);
Event.scheduleImmediately(this, new SmarterHost(actuator, (int) actuator.getHost().getId().value()), 0);
}
}
/**
* Called once during simulation setup for each host. Creates a SmarterHost object.
*/
@Override
public void placeComponent(SimLocationActuator actuator) {
if (!actuatorList.contains(actuator)) {
actuatorList.add(actuator);
Event.scheduleImmediately(this, new SmarterHost(actuator, (int) actuator.getHost().getId().value()), 0);
}
}
/**
* Set the time between movement operations
* @param time the time between movement operations
*/
@Override
public void setTimeBetweenMoveOperations(long time) {
this.timeBetweenMoveOperations = time;
}
/**
* Returns the time between movement operations
* @return time between movement operations
*/
public long getTimeBetweenMoveOperations() {
return timeBetweenMoveOperations;
}
}
...@@ -22,10 +22,11 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm; ...@@ -22,10 +22,11 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm;
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.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
public interface ISocialGroupMovementAnalyzer extends IAttractionBasedMovementAnalyzer { public interface ISocialGroupMovementAnalyzer extends IAttractionBasedMovementAnalyzer {
public void onGroupForming(SocialMovementGroup group); public void onGroupForming(SocialMovementGroup group, IAttractionPoint currentDestination, IAttractionPoint targetDestination);
public void onGroupDisbanding(SocialMovementGroup group); public void onGroupDisbanding(SocialMovementGroup group);
...@@ -35,6 +36,8 @@ public interface ISocialGroupMovementAnalyzer extends IAttractionBasedMovementAn ...@@ -35,6 +36,8 @@ public interface ISocialGroupMovementAnalyzer extends IAttractionBasedMovementAn
public void onGroupMovesToAttractionPoint(SocialMovementGroup group); public void onGroupMovesToAttractionPoint(SocialMovementGroup group);
public void onGroupArriveAtAttractionPoint(SocialMovementGroup group);
public void onMoveToMeetingPoint(SocialMovementGroup group, SimLocationActuator node); public void onMoveToMeetingPoint(SocialMovementGroup group, SimLocationActuator node);
public void onMemberWaitAtMeetingPoint(SocialMovementGroup group, SimLocationActuator node); public void onMemberWaitAtMeetingPoint(SocialMovementGroup group, SimLocationActuator node);
......
...@@ -243,13 +243,13 @@ public class SocialGroupMovementModel extends ModularMovementModel { ...@@ -243,13 +243,13 @@ public class SocialGroupMovementModel extends ModularMovementModel {
else { else {
// the leader does a local movement // 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);
// inform analyzer of movement to attraction point // inform analyzer of movement to attraction point
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) { if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupMovesToAttractionPoint(group); Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupMovesToAttractionPoint(group);
} }
doLocalMovement(host, destination);
} }
else { else {
// inform analyzer of waiting group // inform analyzer of waiting group
......
...@@ -23,6 +23,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups; ...@@ -23,6 +23,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.groups;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.UUID;
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.util.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
...@@ -37,6 +38,8 @@ import de.tudarmstadt.maki.simonstrator.api.Randoms; ...@@ -37,6 +38,8 @@ import de.tudarmstadt.maki.simonstrator.api.Randoms;
*/ */
public class SocialMovementGroup { public class SocialMovementGroup {
public final UUID groupID;
private SimLocationActuator leader; private SimLocationActuator leader;
private LinkedHashSet<SimLocationActuator> members; private LinkedHashSet<SimLocationActuator> members;
...@@ -49,7 +52,10 @@ public class SocialMovementGroup { ...@@ -49,7 +52,10 @@ public class SocialMovementGroup {
* @param Set<SimLocationActuator> All participants of the group. * @param Set<SimLocationActuator> All participants of the group.
* @param int The ID of the group. * @param int The ID of the group.
*/ */
public SocialMovementGroup(Set<SimLocationActuator> participants){ public SocialMovementGroup(Set<SimLocationActuator> participants) {
this.groupID = UUID.randomUUID();
setMembers(participants); setMembers(participants);
setRandomLeader(); setRandomLeader();
} }
...@@ -176,4 +182,30 @@ public class SocialMovementGroup { ...@@ -176,4 +182,30 @@ public class SocialMovementGroup {
public void setMeetingPoint(PositionVector meetingPoint) { public void setMeetingPoint(PositionVector meetingPoint) {
this.meetingPoint = meetingPoint; this.meetingPoint = meetingPoint;
} }
@Override
public boolean equals(Object obj) {
if(!(obj instanceof SocialMovementGroup)) {
return false;
}
SocialMovementGroup toCompare = (SocialMovementGroup) obj;
if(this.groupID == toCompare.groupID) {
if(this.getLeader() == toCompare.getLeader()) {
return true;
}
else {
System.out.println("Leader seems to be different, but still the same UUID");
return false;
}
}
else return false;
}
@Override
public int hashCode() {
//FIXME hope this is correct -- should we include the leader and/or other fields as well?
return groupID.hashCode();
}
} }
...@@ -58,6 +58,7 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -58,6 +58,7 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
protected final int DECISION_MERGE_FULL = 1; protected final int DECISION_MERGE_FULL = 1;
protected final int DECISION_MERGE_PARTIAL = 2; protected final int DECISION_MERGE_PARTIAL = 2;
protected final int DECISION_DISSOLVE = 3; protected final int DECISION_DISSOLVE = 3;
protected final int DECISION_WAIT = 3;
protected SocialGroupMovementModel movementModel; protected SocialGroupMovementModel movementModel;
protected MovementGroupContainer groupCon; protected MovementGroupContainer groupCon;
...@@ -264,12 +265,7 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -264,12 +265,7 @@ 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);
...@@ -281,6 +277,11 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -281,6 +277,11 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
large.addHostToGroup(participant); large.addHostToGroup(participant);
} }
// Inform analyzer of resolved movement
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupMerge(group1, group2);
}
movementModel.getGroupFormingBehavior().removeGroup(small); movementModel.getGroupFormingBehavior().removeGroup(small);
return large; return large;
...@@ -345,5 +346,7 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior ...@@ -345,5 +346,7 @@ public abstract class AbstractGroupEncounter implements IGroupEncounterBehavior
}, group, 0); }, group, 0);
} }
} }
protected abstract int decide();
} }
...@@ -51,7 +51,7 @@ public class Dissolve extends AbstractGroupEncounter { ...@@ -51,7 +51,7 @@ public class Dissolve extends AbstractGroupEncounter {
*/ */
@Override @Override
public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) { public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) {
if(rand.nextDouble() <= probabilityToDissolve) { if(decide() == DECISION_DISSOLVE) {
System.out.println("Dissolve groups"); System.out.println("Dissolve groups");
dissolveGroups(group1, group2); dissolveGroups(group1, group2);
} }
...@@ -64,4 +64,13 @@ public class Dissolve extends AbstractGroupEncounter { ...@@ -64,4 +64,13 @@ public class Dissolve extends AbstractGroupEncounter {
} }
this.probabilityToDissolve = probabilityToDissolve; this.probabilityToDissolve = probabilityToDissolve;
} }
protected int decide() {
// mergePartially
if(rand.nextDouble() < probabilityToDissolve) {
return DECISION_DISSOLVE;
}
else
return DECISION_NONE;
}
} }
...@@ -50,7 +50,7 @@ public class Merge extends AbstractGroupEncounter { ...@@ -50,7 +50,7 @@ public class Merge extends AbstractGroupEncounter {
*/ */
@Override @Override
public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) { public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) {
if(rand.nextDouble() <= probabilityToMergeFully) { if(decide() == DECISION_MERGE_FULL) {
mergeGroupsFully(group1, group2); mergeGroupsFully(group1, group2);
} }
} }
...@@ -63,4 +63,13 @@ public class Merge extends AbstractGroupEncounter { ...@@ -63,4 +63,13 @@ public class Merge extends AbstractGroupEncounter {
} }
this.probabilityToMergeFully = probabilityToMergeFully; this.probabilityToMergeFully = probabilityToMergeFully;
} }
protected int decide() {
// mergePartially
if(rand.nextDouble() < probabilityToMergeFully) {
return DECISION_MERGE_FULL;
}
else
return DECISION_NONE;
}
} }
...@@ -77,7 +77,7 @@ public class MergeFullOrMergePartial extends AbstractGroupEncounter { ...@@ -77,7 +77,7 @@ public class MergeFullOrMergePartial extends AbstractGroupEncounter {
* *
* @return int * @return int
*/ */
private int decide() { protected int decide() {
double decider = rand.nextDouble(); double decider = rand.nextDouble();
......
...@@ -80,7 +80,7 @@ public class MergeFullOrMergePartialOrDissolve extends AbstractGroupEncounter { ...@@ -80,7 +80,7 @@ public class MergeFullOrMergePartialOrDissolve extends AbstractGroupEncounter {
* *
* @return int * @return int
*/ */
private int decide() { protected int decide() {
double decider = rand.nextDouble(); double decider = rand.nextDouble();
......
...@@ -73,7 +73,7 @@ public class MergeOrDissolve extends AbstractGroupEncounter { ...@@ -73,7 +73,7 @@ public class MergeOrDissolve extends AbstractGroupEncounter {
* *
* @return int * @return int
*/ */
private int decide() { protected int decide() {
double decider = rand.nextDouble(); double decider = rand.nextDouble();
......
...@@ -51,7 +51,7 @@ public class MergePartial extends AbstractGroupEncounter { ...@@ -51,7 +51,7 @@ public class MergePartial extends AbstractGroupEncounter {
*/ */
@Override @Override
public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) { public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) {
if(rand.nextDouble() <= probabilityToMergePartially) { if(decide() == DECISION_MERGE_PARTIAL) {
mergeGroupsPartially(group1, group2, numberOfHostsToLeave); mergeGroupsPartially(group1, group2, numberOfHostsToLeave);
} }
} }
...@@ -71,4 +71,13 @@ public class MergePartial extends AbstractGroupEncounter { ...@@ -71,4 +71,13 @@ public class MergePartial extends AbstractGroupEncounter {
} }
this.numberOfHostsToLeave = numberOfHostsToLeave; this.numberOfHostsToLeave = numberOfHostsToLeave;
} }
protected int decide() {
// mergePartially
if(rand.nextDouble() < probabilityToMergePartially) {
return DECISION_MERGE_PARTIAL;
}
else
return DECISION_NONE;
}
} }
...@@ -75,7 +75,7 @@ public class MergePartialOrDissolve extends AbstractGroupEncounter { ...@@ -75,7 +75,7 @@ public class MergePartialOrDissolve extends AbstractGroupEncounter {
* *
* @return int * @return int
*/ */
private int decide() { protected int decide() {
double decider = rand.nextDouble(); double decider = rand.nextDouble();
......
...@@ -49,7 +49,7 @@ public class Wait extends AbstractGroupEncounter{ ...@@ -49,7 +49,7 @@ public class Wait extends AbstractGroupEncounter{
@Override @Override
public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) { public void handleGroupEncounter(SocialMovementGroup group1, SocialMovementGroup group2) {
if(rand.nextDouble() <= probabilityToWait) { if(decide() == DECISION_WAIT) {
long waittime = getRandomWaitTime(); long waittime = getRandomWaitTime();
wait(group1, waittime); wait(group1, waittime);
wait(group2, waittime); wait(group2, waittime);
...@@ -78,4 +78,14 @@ public class Wait extends AbstractGroupEncounter{ ...@@ -78,4 +78,14 @@ public class Wait extends AbstractGroupEncounter{
} }
this.timeToWait = timeToWait; this.timeToWait = timeToWait;
} }
@Override
protected int decide() {
// mergePartially
if(rand.nextDouble() < probabilityToWait) {
return DECISION_WAIT;
}
else
return DECISION_NONE;
}
} }
...@@ -57,7 +57,7 @@ public class WaitSmartMerge extends Wait{ ...@@ -57,7 +57,7 @@ public class WaitSmartMerge extends Wait{
SocialMovementGroup merged = mergeGroupsFully(group1, group2); SocialMovementGroup merged = mergeGroupsFully(group1, group2);
wait(merged, pauseTime); wait(merged, pauseTime);
} }
else if(rand.nextDouble() <= probabilityToWait) { else if(decide() == DECISION_WAIT) {
wait(group1, pauseTime); wait(group1, pauseTime);
wait(group2, pauseTime); wait(group2, pauseTime);
} }
......
...@@ -185,19 +185,24 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -185,19 +185,24 @@ 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);
// FIXME move to movement model // force a new attraction point assignment on the leader
movementModel.getAttractionAssignmentStrategy().addComponent(group.getLeader()); IAttractionPoint currentDestination = movementModel.getAttractionAssignmentStrategy().getAssignment(group.getLeader());
IAttractionPoint nextDestination = movementModel.getAttractionAssignmentStrategy().getAssignment(group.getLeader()); movementModel.getAttractionAssignmentStrategy().addComponent(group.getLeader());
IAttractionPoint targetDestination = movementModel.getAttractionAssignmentStrategy().getAssignment(group.getLeader());
// Add Offset to group destination // Add Offset to group destination
PositionVector destination = movementModel.addGaussianOffsetToPosition(new PositionVector(nextDestination), PositionVector destination = movementModel.addGaussianOffsetToPosition(new PositionVector(targetDestination),
nextDestination.getRadius() / 3); targetDestination.getRadius() / 3);
group.setDestination(destination); group.setDestination(destination);
setGroupMeetingPoint(group); setGroupMeetingPoint(group);
for(SimLocationActuator member : group.getMembers()) { for(SimLocationActuator member : group.getMembers()) {
member.setTargetAttractionPoint(nextDestination); // only set the attraction point for non-leaders, as the leader was already assigned an attraction point above
if(group.getLeader() != member) {
member.setTargetAttractionPoint(targetDestination);
}
// remove any left-over entries
if(groupCon.hostWasGroupMember(member)) { if(groupCon.hostWasGroupMember(member)) {
groupCon.removeLeftGroupAtTimeEntry(member); groupCon.removeLeftGroupAtTimeEntry(member);
} }
...@@ -207,7 +212,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -207,7 +212,7 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
// Inform analyzer of new group // Inform analyzer of new group
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) { if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupForming(group); Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupForming(group, currentDestination, targetDestination);
} }
} }
...@@ -230,8 +235,8 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -230,8 +235,8 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
if(group.getGroupSize() > 0 || group.getLeader() != null) { if(group.getGroupSize() > 0 || group.getLeader() != null) {
IAttractionPoint currentAP = group.getLeader().getCurrentTargetAttractionPoint(); IAttractionPoint currentAP = group.getLeader().getCurrentTargetAttractionPoint();
for (SimLocationActuator host : group.getMembers()) { for (SimLocationActuator host : group.getMembers()) {
movementModel.updatedAttractionAssignment(host, currentAP); host.setTargetAttractionPoint(currentAP);
} }
} }
...@@ -349,11 +354,6 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior { ...@@ -349,11 +354,6 @@ public abstract class AbstractGroupForming implements IGroupFormingBehavior {
new BasicAttractionPoint("Group Movement Meeting Point of Leader #"+group.getLeader().getHost().getId(), leaderPos); new BasicAttractionPoint("Group Movement Meeting Point of Leader #"+group.getLeader().getHost().getId(), leaderPos);
group.setMeetingPoint(meetingPoint); group.setMeetingPoint(meetingPoint);
// Update target for all group members to meeting point
for(SimLocationActuator participant : group.getMembers()) {
//movementModel.getAttractionAssignmentStrategy().updateTargetAttractionPoint(participant, meetingPoint);
}
} }
@Override @Override
......
...@@ -27,6 +27,7 @@ import java.util.Set; ...@@ -27,6 +27,7 @@ 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.api.topology.movement.local.LocalMovementStrategy; import de.tud.kom.p2psim.api.topology.movement.local.LocalMovementStrategy;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ISocialGroupMovementAnalyzer;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator; import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.hostcount.HostAtAttractionPointCounter; import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.hostcount.HostAtAttractionPointCounter;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup; import de.tud.kom.p2psim.impl.topology.movement.modularosm.groups.SocialMovementGroup;
...@@ -36,6 +37,7 @@ import de.tud.kom.p2psim.impl.util.Either; ...@@ -36,6 +37,7 @@ import de.tud.kom.p2psim.impl.util.Either;
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.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;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
...@@ -193,6 +195,12 @@ public class DefaultGroupForming extends AbstractGroupForming { ...@@ -193,6 +195,12 @@ public class DefaultGroupForming extends AbstractGroupForming {
// Do nothing // Do nothing
} else { } else {
transition.reachedAttractionPoint(leader, leader.getCurrentTargetAttractionPoint()); transition.reachedAttractionPoint(leader, leader.getCurrentTargetAttractionPoint());
// Inform analyzer of group removal
if(Monitor.hasAnalyzer(ISocialGroupMovementAnalyzer.class)) {
Monitor.getOrNull(ISocialGroupMovementAnalyzer.class).onGroupArriveAtAttractionPoint(group);
}
groupsToRemove.add(group); groupsToRemove.add(group);
} }
} }
......
...@@ -157,9 +157,13 @@ public abstract class AbstractAttractionBasedAssignmentStrategy implements IAttr ...@@ -157,9 +157,13 @@ public abstract class AbstractAttractionBasedAssignmentStrategy implements IAttr
} }
// fallback: if no attraction point is considered, randomly select one // fallback: if no attraction point is considered, randomly select one, except the current assignment
if (candidates.isEmpty()) { if (candidates.isEmpty()) {
candidates.addAll(IAttractionGenerator.attractionPoints); candidates.addAll(IAttractionGenerator.attractionPoints);
if(assignments.containsKey(host) && candidates.size() > 1) {
candidates.remove(assignments.get(host));
}
} }
IAttractionPoint assignment = candidates.get(rnd.nextInt(candidates.size())); IAttractionPoint assignment = candidates.get(rnd.nextInt(candidates.size()));
......
...@@ -60,6 +60,13 @@ public class AttractionPointRoamingStrategy extends AbstractAttractionBasedAssig ...@@ -60,6 +60,13 @@ public class AttractionPointRoamingStrategy extends AbstractAttractionBasedAssig
IAttractionPoint nextAP = getNewAttractionPointAssignment(comp); IAttractionPoint nextAP = getNewAttractionPointAssignment(comp);
updateTargetAttractionPoint(comp, nextAP); updateTargetAttractionPoint(comp, nextAP);
} }
@Override
public void updateTargetAttractionPoint(SimLocationActuator comp,
IAttractionPoint attractionPoint) {
this.roamingStates.put(comp, null);
super.updateTargetAttractionPoint(comp, attractionPoint);
}
@Override @Override
public void reachedAttractionPoint(SimLocationActuator comp, IAttractionPoint attractionPoint) { public void reachedAttractionPoint(SimLocationActuator comp, 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.smarter.dataanalyzer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
/**
* Starting point for analyzing SQLite Files.
*
* @author Marcel Verst
* @version 26.05.2018
*/
public class Analyzer {
// Area of Runway = rectangle between the points High and Low
public static double latRunwayHigh = 51.791816;
public static double lonRunwayHigh = 8.781827;
public static double latRunwayLow = 51.790350;
public static double lonRunwayLow = 8.786664;
// Area of Town = rectangle between the points High and Low
public static double latTownHigh = 51.791955;
public static double lonTownHigh = 8.772932;
public static double latTownLow = 51.791039;
public static double lonTownLow = 8.774717;
// Area of TinCity = rectangle between the points High and Low
public static double latTinHigh = 51.818949;
public static double lonTinHigh = 8.807715;
public static double latTinLow = 51.817314;
public static double lonTinLow = 8.813276;
/**
* Checks, if a certain GPS point is within Runway area
*
* @param lat
* Latitude to check
* @param lon
* Longitude to check
* @return true if in Runway area and false if not
*/
public static boolean inRunway(double lat, double lon) {
return (lat >= latRunwayLow && lat <= latRunwayHigh && lon >= lonRunwayHigh && lon <= lonRunwayLow);
}
/**
* Checks, if a certain GPS point is within Town area
*
* @param lat
* Latitude to check
* @param lon
* Longitude to check
* @return true if in Town area and false if not
*/
public static boolean inTown(double lat, double lon) {
return (lat >= latTownLow && lat <= latTownHigh && lon >= lonTownHigh && lon <= lonTownLow);
}
/**
* Checks, if a certain GPS point is within TinCity area
*
* @param lat
* Latitude to check
* @param lon
* Longitude to check
* @return true if in TinCity area and false if not
*/
public static boolean inTinCity(double lat, double lon) {
return (lat >= latTinLow && lat <= latTinHigh && lon >= lonTinHigh && lon <= lonTinLow);
}
/**
* Checks, if a certain GPS point is within one of the start areas
*
* @param lat
* Latitude to check
* @param lon
* Longitude to check
* @return true if in one of the three areas, false if not
*/
public static boolean inStartArea(double lat, double lon) {
return (inRunway(lat, lon) || inTown(lat, lon) || inTinCity(lat, lon));
}
/**
* Returns a list of full file paths of a given directory
*
* @param directory
* The
* @return
*/
public ArrayList<String> getFilePaths(String directory) {
File folder = new File(directory);
File[] listOfFiles = folder.listFiles();
ArrayList<String> filePaths = new ArrayList<String>();
if (listOfFiles.length == 0) {
System.out.println("No files in directory");
return null;
}
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
filePaths.add(directory + listOfFiles[i].getName());
}
}
return filePaths;
}
/**
* Creates an .if File which has the following format for a line: timestamp
* x-coordinate y-coordinate
*
* @param fileName
* The file name of the database
* @param listOfEntries
* all entries of the current database
* @param startID
* The startID on which we start with the first entry for the .if
* file
*/
private static void createIFFile(String fileName, ArrayList<DBEntry> listOfEntries, int startID) {
// filename = gps_data-192.168.0.10.db
// 0 1 2 3 4
int fileID = Integer.parseInt(fileName.split("\\.")[3]);
try {
System.out.println("Creating file: mobilityTraceFile-File-Modified-" + fileID + ".if");
PrintWriter writer = new PrintWriter("smarter/traces-mv/mobilityTraceFile-File-Modified-" + fileID + ".if",
"UTF-8");
for (DBEntry entry : listOfEntries) {
if (entry.get_id() >= startID) {
double lat = entry.getLatitude();
double lon = entry.getLongitude();
String timestamp = entry.getTimestamp();
// timestamp format: 2017-09-02 10:21:02
// 0 1
String time = timestamp.split(" ")[1];
// time format: 10:21:02
// 0 1 2
String[] values = time.split(":");
int hours = Integer.parseInt(values[0]);
int minutes = Integer.parseInt(values[1]);
int seconds = Integer.parseInt(values[2]);
// Example: 13:42:10 = 3*3600s + 42*60s + 10*1s
int time_for_file = (hours - 10) * 3600 + minutes * 60 + seconds * 1;
writer.println(time_for_file + " " + lat + " " + lon);
}
}
writer.close();
} catch (FileNotFoundException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* Creates a modified version of the .if file. Calculates based on the timestamp
* the first relevant ID and from then on copies the lines from the original .if
* file. This procedure ensures that the modified .if files only contains the
* relevant entries, meaning the starting point, when a person reached one of
* the start areas (Runway, Town or TinCity). The timestamp parameter is the
* timestamp on which a person first entered one of the three start areas. Time
* conversion from timestamp to seconds is also applied.
*
* @param fileName
* The file name of the database
*/
private static void createModifiedIFFile(String fileName, String timestamp) {
// filename = gps_data-192.168.0.10.db
// 0 1 2 3 4
int fileID = Integer.parseInt(fileName.split("\\.")[3]);
// timestamp format: 2017-09-02 10:21:02
// 0 1
String time = timestamp.split(" ")[1];
// time format: 10:21:02
// 0 1 2
String[] values = time.split(":");
int hours = Integer.parseInt(values[0]);
int minutes = Integer.parseInt(values[1]);
int seconds = Integer.parseInt(values[2]);
// Example: 13:42:10 = 3*3600s + 42*60s + 10*1s
int startID = (hours - 10) * 3600 + minutes * 60 + seconds * 1;
try {
System.out.println("Creating file: mobilityTraceFile-File-Modified-" + fileID + ".if");
PrintWriter writer = new PrintWriter("smarter/traces-mv/mobilityTraceFile-File-Modified-" + fileID + ".if",
"UTF-8");
File file = new File("smarter/trace/mobilityTraceFile-File-" + fileID + ".if");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
// line format: 1234 450 123
// 0 1 2
String[] split = line.split(" ");
int lineID = Integer.parseInt(split[0]);
if (lineID >= startID)
writer.println(line);
}
fileReader.close();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Connects to all .sqlite databases in a given directory and analyzes the
* entries.
*/
public static void analyzeTraces() {
// Objects
Analyzer analyzer = new Analyzer();
DataGrabber grabber = new DataGrabber();
// Set the path to folder containing the .sqlite files here
String sqliteFolderPath = "C:/Users/MarcelV/Desktop/Uni Programme/Feldtest/DB Gefiltert/";
// Initialize counters
int counterRunway = 0;
int counterTown = 0;
int counterTinCity = 0;
boolean foundStartID;
boolean createModifiedIFFile = true;
ArrayList<String> filePaths = analyzer.getFilePaths(sqliteFolderPath);
try {
PrintWriter writer = new PrintWriter("smarter/start_ids.txt", "UTF-8");
for (String filePath : filePaths) {
foundStartID = false;
// Get data
grabber.connect(filePath);
ArrayList<DBEntry> listOfEntries = grabber.select("SELECT * FROM gps_data");
grabber.disconnect();
// C:/Users/Marcel/Desktop/Uni Programme/Feldtest/DB
// Gefiltert/gps_data-192.168.0.10.db
String[] split = filePath.split("/");
String fileName = split[7];
// Analyze data
for (DBEntry entry : listOfEntries) {
if (!foundStartID) {
double lat = entry.getLatitude();
double lon = entry.getLongitude();
if (inRunway(lat, lon)) {
System.out.println("Entered Runway at ID: " + entry.get_id() + " at time: "
+ entry.getTimestamp());
writer.println(fileName + ": Entered Runway at ID: " + entry.get_id() + " at time: "
+ entry.getTimestamp());
// Create of the files
if (createModifiedIFFile)
createModifiedIFFile(fileName, entry.getTimestamp());
else
createIFFile(fileName, listOfEntries, entry.get_id());
counterRunway++;
foundStartID = true;
} else if (inTown(lat, lon)) {
System.out.println(
"Entered Town at ID: " + entry.get_id() + " at time: " + entry.getTimestamp());
writer.println(fileName + ": Entered Town at ID: " + entry.get_id() + " at time: "
+ entry.getTimestamp());
// Create of the files
if (createModifiedIFFile)
createModifiedIFFile(fileName, entry.getTimestamp());
else
createIFFile(fileName, listOfEntries, entry.get_id());
counterTown++;
foundStartID = true;
} else if (inTinCity(lat, lon)) {
System.out.println("Entered TinCity at ID: " + entry.get_id() + " at time: "
+ entry.getTimestamp());
writer.println(fileName + ": Entered TinCity at ID: " + entry.get_id() + " at time: "
+ entry.getTimestamp());
// Create of the files
if (createModifiedIFFile)
createModifiedIFFile(fileName, entry.getTimestamp());
else
createIFFile(fileName, listOfEntries, entry.get_id());
counterTinCity++;
foundStartID = true;
}
}
}
}
writer.println("Counter Runway : " + counterRunway);
writer.println("Counter Town : " + counterTown);
writer.println("Counter TinCity : " + counterTinCity);
writer.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println("\nCounter Runway: " + counterRunway + "\nCounter Town : " + counterTown
+ "\nCounter TinCity : " + counterTinCity);
}
}
\ No newline at end of file
/*
* 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.smarter.dataanalyzer;
/**
* Represents a row of the gps_data table from a database
*
* @author Marcel Verst
* @version 26.05.2018
*/
public class DBEntry {
// All columns of the row
public int _id;
double longitude;
double latitude;
double altitude;
double accuracy;
String timestamp;
/**
* Creates DBEntry object
*
* @param _id
* the id entry
* @param longitude
* the longitude entry
* @param latitude
* the latitude entry
* @param altitude
* the altitude entry
* @param accuracy
* the accuracy entry
* @param timestamp
* the timestamp entry
*/
public DBEntry(int _id, double longitude, double latitude, double altitude, double accuracy, String timestamp) {
super();
this._id = _id;
this.longitude = longitude;
this.latitude = latitude;
this.altitude = altitude;
this.accuracy = accuracy;
this.timestamp = timestamp;
}
/**
* Print entry
*
* @return String containing all entries of the row
*/
@Override
public String toString() {
return "DBEntry [_id=" + _id + ", longitude=" + longitude + ", latitude=" + latitude + ", altitude=" + altitude
+ ", accuracy=" + accuracy + ", timestamp=" + timestamp + "]";
}
/**
* Gets the ID
*
* @return _id
*/
public int get_id() {
return _id;
}
/**
* Sets the ID
*
* @param _id
*/
public void set_id(int _id) {
this._id = _id;
}
/**
* Gets the longitude
*
* @return longitude
*/
public double getLongitude() {
return longitude;
}
/**
* Sets the longitude
*
* @param longitude
*/
public void setLongitude(double longitude) {
this.longitude = longitude;
}
/**
* Gets the latitude
*
* @return latitude
*/
public double getLatitude() {
return latitude;
}
/**
* Sets the latitude
*
* @param latitude
*/
public void setLatitude(double latitude) {
this.latitude = latitude;
}
/**
* Gets the altitude
*
* @return altitude
*/
public double getAltitude() {
return altitude;
}
/**
* Sets the altitude
*
* @param altitude
*/
public void setAltitude(double altitude) {
this.altitude = altitude;
}
/**
* Gets the accuracy
*
* @return accuracy of GPS signal
*/
public double getAccuracy() {
return accuracy;
}
/**
* Sets the accuracy
*
* @param accuracy
*/
public void setAccuracy(double accuracy) {
this.accuracy = accuracy;
}
/**
* Gets the timestamp
*
* @return timestamp
*/
public String getTimestamp() {
return timestamp;
}
/**
* Sets the timestamp
*
* @param timestamp
*/
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
}
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