Commit d995e93c authored by Nils Richerzhagen's avatar Nils Richerzhagen
Browse files

Minor Updates Crater

parent d89b9592
/*
* 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.churn;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import de.tud.kom.p2psim.api.churn.ChurnModel;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.network.SimNetInterface;
import de.tud.kom.p2psim.impl.scenario.DefaultConfigurator;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
* A simple churn model that reads a text file as input to set groups of nodes on- and offline.
* Doing so the path to the text file has to be given in the config.
*
* The file must have the following format:
*
* group_name, time when to go online, time when to go offline, duration
*
* The following example shows the format:
*
* main_noise_peers_8 , 30min, 15min, 45min
* main_noise_peers_8 , 1h, 2h, 1h
* ...
*
* @author Nils Richerzhagen
* @version 1.0, Feb 18, 2015
*/
public class CSVBasedChurnModel implements ChurnModel {
private String filename;
private final String SEP = ",";
private Map<String, LinkedList<ChurnInfo>> churnInfos;
private Map<String, Boolean> usedForDowntime;
/**
*
* @param file
*/
@XMLConfigurableConstructor({ "file" })
public CSVBasedChurnModel(String file) {
this.filename = file;
this.churnInfos = new LinkedHashMap<String, LinkedList<ChurnInfo>>();
this.usedForDowntime = new LinkedHashMap<String, Boolean>();
}
@Override
public long getNextUptime(SimHost host) {
String groupId = host.getProperties().getGroupID();
LinkedList<ChurnInfo> hostChurnInfos = churnInfos.get(groupId);
if(usedForDowntime.containsKey(groupId) && usedForDowntime.get(groupId) == true){
hostChurnInfos.removeFirst();
usedForDowntime.put(groupId, false);
}
else
usedForDowntime.put(groupId, false);
if(hostChurnInfos.isEmpty())
throw new AssertionError("No more churn infos left, is tht possible? " + host.getProperties().getGroupID());
ChurnInfo churnInfo = hostChurnInfos.getFirst();
if(churnInfo == null){
throw new AssertionError("Seems to have not enough entries for group: " + host.getProperties().getGroupID());
}
// if(!notRemovedFirstThisRun){
// notRemovedFirstThisRun = true;
// }
return churnInfo.getStartTime() - Simulator.getCurrentTime();
// // the next interval should be an offline
// if(churnInfo.isOnline()){
// return churnInfo.getDuration();
// }
// else{
// try {
// hostChurnInfos.removeFirst();
// } catch (NoSuchElementException e) {
// throw new AssertionError("Seems to have not enough entries for group: " + host.getProperties().getGroupID());
// }
// churnInfo = hostChurnInfos.getFirst();
// if(churnInfo == null)
// {
// throw new AssertionError("Seems to have not enough entries for group: " + host.getProperties().getGroupID());
// }
// if(!churnInfo.isOnline()){
// throw new AssertionError("There should be an online interval after the offline one: " + host.getProperties().getGroupID());
// }
// return churnInfo.getDuration();
// }
}
@Override
public long getNextDowntime(SimHost host) {
String groupId = host.getProperties().getGroupID();
LinkedList<ChurnInfo> hostChurnInfos = churnInfos.get(groupId);
usedForDowntime.put(groupId, true);
// if(usedForDowntime){
// hostChurnInfos.removeFirst();
// usedForDowntime = false;
// }
ChurnInfo churnInfo = hostChurnInfos.getFirst();
if(churnInfo == null){
throw new AssertionError("Seems to have not enough entries for group: " + host.getProperties().getGroupID());
}
// use churn info
return churnInfo.getEndTime() - Simulator.getCurrentTime();
// // the next interval should be an offline
// if(!churnInfo.isOnline()){
// return churnInfo.getDuration();
// }
// else{
// try {
// hostChurnInfos.removeFirst();
// } catch (NoSuchElementException e) {
// throw new AssertionError("Seems to have not enough entries for group: " + host.getProperties().getGroupID());
// }
// churnInfo = hostChurnInfos.getFirst();
// if(churnInfo == null){
// throw new AssertionError("Seems to have not enough entries for group: " + host.getProperties().getGroupID());
// }
// if(churnInfo.isOnline()){
// throw new AssertionError("There should be an offline interval after the previous online one: " + host.getProperties().getGroupID());
// }
// return churnInfo.getDuration();
// }
}
@Override
public void prepare(List<SimHost> churnHosts) {
for (SimHost host : churnHosts) {
for (SimNetInterface netI : host.getNetworkComponent()
.getSimNetworkInterfaces()) {
if (netI.isOnline()) {
netI.goOffline();
}
}
}
parseTrace(filename);
}
private void parseTrace(String filename) {
System.out.println("==============================");
System.out.println("Reading trace from " + filename);
/*
* This parser works for the following csv file structure.
*
* groupID, startTime, endTime, duration, boolean (true/false)
*
* groupID - describes the group id of the nodes that are affected
*
* startTime - the time when the event should occur
*
* endTime - Insanity Check
*
* duration - how long should the event take
*
* interChrunInterval - defines the time between each leave or join
* action in this group and this event. This is used as it makes the
* behaviour more realistic compared to a simple online/offline at the
* same time action.
*
* boolean - defines if the group should be online or offline during this event
*/
BufferedReader csv = null;
boolean entrySuccessfullyRead = false;
int lines = 0;
try {
csv = new BufferedReader(new FileReader(filename));
String previousGroupId = "";
boolean firstGroup = true;
long previousEndTime = 0;
while (csv.ready()) {
String line = csv.readLine();
lines++;
if (line.indexOf(SEP) > -1) {
String[] parts = line.split(SEP);
if (parts.length == 4) {
try {
String groupID = parts[0].replaceAll("\\s+","");
int a = DefaultConfigurator.parseNumber("20m", Integer.class);
long startTime = DefaultConfigurator.parseNumber(parts[1].replaceAll("\\s+",""), Long.class);
long endTime = DefaultConfigurator.parseNumber(parts[2].replaceAll("\\s+",""), Long.class);
long duration = DefaultConfigurator.parseNumber(parts[3].replaceAll("\\s+",""), Long.class);
// boolean online = Boolean.parseBoolean(parts[4].replaceAll("\\s+", ""));
// String onlineString = parts[5].replaceAll("\\s+","");
if(firstGroup){
previousGroupId = groupID;
// previousEndTime = startTime;
firstGroup = false;
}
// new group id
if(!previousGroupId.equals(groupID)){
previousGroupId = groupID;
// previousEndTime = startTime;
previousEndTime = 0;
}
// Insanity Checks
// if(startTime != previousEndTime){
if(startTime < previousEndTime){
throw new AssertionError("Wrong time in CSV for startTime as previousEndTime is larger.");
}
if(endTime - startTime != duration){
throw new AssertionError("Duration must be the same as endTime - startTime");
}
// if((onlineString.equals("true") && !online)|| (onlineString.equals("false") && online)){
// throw new AssertionError("Boolean should be the same!");
// }
LinkedList<ChurnInfo> infoList = churnInfos.get(groupID);
if(infoList == null){
infoList = new LinkedList<CSVBasedChurnModel.ChurnInfo>();
// infoList.add(new ChurnInfo(startTime, online, endTime));
infoList.add(new ChurnInfo(startTime, endTime));
churnInfos.put(groupID, infoList);
}
else{
// infoList.add(new ChurnInfo(startTime, online, endTime));
infoList.add(new ChurnInfo(startTime, endTime));
}
entrySuccessfullyRead = true;
} catch (NumberFormatException e) {
// Ignore leading comments
if (entrySuccessfullyRead) {
// System.err.println("CSV ParseError " +
// line);
}
}
} else {
throw new AssertionError("To many/few columns in CSV.");
}
}
}
}
catch (Exception e) {
System.err.println("Could not open " + filename);
throw new RuntimeException("Could not open " + filename);
}
finally {
if (csv != null) {
try {
csv.close();
} catch (IOException e) {
//
}
}
}
}
private class ChurnInfo {
long startTime;
long endTime;
// boolean online;
public ChurnInfo(long startTime, long endTime){
// public ChurnInfo(long startTime, boolean online, long endTime){
this.startTime = startTime;
// this.online = online;
this.endTime = endTime;
}
public long getEndTime(){
return endTime;
}
public long getDuration(){
// TODO introduce skew/offset
return (endTime - startTime);
}
public long getStartTime(){
return startTime;
}
//
// /**
// * Returns if this churn interval stands for an online interval
// * @return
// */
// public boolean isOnline(){
// return this.online;
// }
}
}
/*
* 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.energy;
import de.tud.kom.p2psim.api.energy.ComponentType;
import de.tud.kom.p2psim.api.energy.EnergyCommunicationComponent;
import de.tud.kom.p2psim.api.energy.EnergyEventListener;
import de.tud.kom.p2psim.api.energy.EnergyModel;
import de.tud.kom.p2psim.api.energy.EnergyState;
import de.tud.kom.p2psim.api.linklayer.mac.PhyType;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tudarmstadt.maki.simonstrator.api.Message;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
public class SmartphoneCellularCommunicationEnergyComponent implements
EnergyCommunicationComponent {
private PhyType phy;
private EnergyEventListener energyModel;
/**
* The different states of this energy component.
*/
private final EnergyState IDLE, TX, RX, RAMP_TX, RAMP_RX, TAIL_TX, TAIL_RX;
private final long RAMP_RX_DURATION = 1994 * Simulator.MILLISECOND_UNIT;
private final long TAIL_RX_DURATION = 3132 * Simulator.MILLISECOND_UNIT;
private final long RAMP_TX_DURATION = 3096 * Simulator.MILLISECOND_UNIT;
private final long TAIL_TX_DURATION = 4796 * Simulator.MILLISECOND_UNIT;
private int tailCounter;
/**
* Represents the state, this energy component is currently in.
*/
private EnergyState currentState;
/**
* Represents the time, when the energy component entered the current energy
* state.
*/
private long lastStateChange;
public SmartphoneCellularCommunicationEnergyComponent(PhyType phy) {
this.phy = phy;
IDLE = new DefaultEnergyState("IDLE", 0);
TX = new DefaultEnergyState("TX", 1.105 * 1000000);
RAMP_TX = new DefaultEnergyState("RAMP_TX", 0.749 * 1000000);
TAIL_TX = new DefaultEnergyState("TAIL_TX", 0.563 * 1000000);
RX = new DefaultEnergyState("RX", 0.786 * 1000000);
RAMP_RX = new DefaultEnergyState("RAMP_RX", 0.505 * 1000000);
TAIL_RX = new DefaultEnergyState("TAIL_RX", 0.483 * 1000000);
tailCounter = 0;
currentState = IDLE;
lastStateChange = 0;
}
@Override
public ComponentType getType() {
return ComponentType.COMMUNICATION;
}
@Override
public void turnOff() {
if (!currentState.equals(IDLE)) {
doStateChange(IDLE);
}
tailCounter++;
}
@Override
public boolean turnOn() {
return true;
}
@Override
public boolean isOn() {
if (energyModel.turnOn(this)) {
doFakeStateChange();
return true;
}
return false;
}
@Override
public void setEnergyEventListener(EnergyEventListener listener) {
this.energyModel = listener;
}
@Override
public void eventOccurred(Object content, int type) {
if (type == tailCounter) {
assert currentState.equals(TAIL_RX) || currentState.equals(TAIL_TX) : "Assert1 SmartphoneCellularCommunicationEnergy";
long timeInTailState = Simulator.getCurrentTime() - lastStateChange;
if((TAIL_RX_DURATION-timeInTailState)!=0 && currentState.equals(TAIL_RX))
Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.WARN, TAIL_RX_DURATION +" vs. " + timeInTailState);
if((TAIL_TX_DURATION-timeInTailState)!=0 && currentState.equals(TAIL_TX))
Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.WARN,TAIL_TX_DURATION +" vs. " + timeInTailState);
assert timeInTailState==TAIL_TX_DURATION || currentState.equals(TAIL_RX) : "Assert2 SmartphoneCellularCommunicationEnergy";
// assert timeInTailState==TAIL_TX_DURATION || timeInTailState==TAIL_RX_DURATION : "Assert2 SmartphoneCellularCommunicationEnergy";
Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG, Simulator.getFormattedTime(Simulator.getCurrentTime())
+ " "
+ ((EnergyModel) energyModel).getHost().getHostId()
+ " consumed "
+ (currentState.getEnergyConsumption() * (timeInTailState / (double) Simulator.SECOND_UNIT))
+ " uJ in State " + currentState.getName()
+ " after spending "
+ (timeInTailState / (double) Simulator.SECOND_UNIT)
+ " sec there.");
energyModel
.switchedState(this, currentState, null, timeInTailState);
tailCounter++;
currentState = IDLE;
lastStateChange = Simulator.getCurrentTime();
}
}
@Override
public PhyType getPhyType() {
return phy;
}
@Override
public void send(long duration, Message msg, boolean isBroadcast) {
if (currentState.equals(IDLE)) {
/*
* Consume the energy for being in the ramp state. There is not
* explicit ramp state, because the node immediately sends the
* message. However, the energy for the ramp state before sending is
* consumed.
*/
energyModel.switchedState(this, RAMP_TX, null, RAMP_TX_DURATION);
} else {
assert currentState.equals(TAIL_RX) || currentState.equals(TAIL_TX);
long timeInTailState = Simulator.getCurrentTime()
- (lastStateChange + duration);
Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG, Simulator.getFormattedTime(Simulator.getCurrentTime())
+ " "
+ ((EnergyModel) energyModel).getHost().getHostId()
+ " consumed "
+ (currentState.getEnergyConsumption() * (timeInTailState / (double) Simulator.SECOND_UNIT))
+ " uJ in State " + currentState.getName()
+ " after spending "
+ (timeInTailState / (double) Simulator.SECOND_UNIT)
+ " sec there before starting a transmission.");
energyModel
.switchedState(this, currentState, null, timeInTailState);
tailCounter++;
}
/*
* Consume the energy for the transmission of data.
*/
energyModel.switchedState(this, TX, null, duration);
Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG, Simulator.getFormattedTime(Simulator.getCurrentTime())
+ " "
+ ((EnergyModel) energyModel).getHost().getHostId()
+ " consumed "
+ (TX.getEnergyConsumption() * (duration / (double) Simulator.SECOND_UNIT))
+ " uJ in State " + TX.getName() + " after spending "
+ (duration / (double) Simulator.SECOND_UNIT) + " sec there.");
/*
* Jump into the tail state and trigger the event to consume the energy
* for the tail state after the given amount of time if no message must
* be sent or received in the meantime.
*/
currentState = TAIL_TX;
lastStateChange = Simulator.getCurrentTime();
Simulator.getScheduler().scheduleIn(TAIL_TX_DURATION, this,
TAIL_TX, tailCounter);
}
@Override
public void receive(long duration, Message msg, boolean isBroadcast,
boolean isIntendedReceiver) {
if(currentState.equals(IDLE)){
/*
* Consume the energy for being in the ramp state. There is not
* explicit ramp state, because the node immediately receives the
* message. However, the energy for the ramp state before receiving
* is consumed.
*/
energyModel.switchedState(this, RAMP_RX, null, RAMP_RX_DURATION);
} else {
assert currentState.equals(TAIL_RX) || currentState.equals(TAIL_TX);
long timeInTailState = Simulator.getCurrentTime() + duration
- lastStateChange;
Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG,Simulator.getCurrentTime()
+ " "
+ ((EnergyModel) energyModel).getHost().getHostId()
+ " consumed "
+ (currentState.getEnergyConsumption() * (timeInTailState / (double) Simulator.SECOND_UNIT))
+ " uJ in State " + currentState.getName()
+ " after spending "
+ (timeInTailState / (double) Simulator.SECOND_UNIT)
+ " sec there before receiving a message.");
energyModel
.switchedState(this, currentState, null, timeInTailState);
tailCounter++;
}
/*
* Consume the energy for the receiption of data.
*/
energyModel.switchedState(this, RX, null, duration);
Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG,Simulator.getCurrentTime()
+ " "
+ ((EnergyModel) energyModel).getHost().getHostId()
+ " consumed "
+ (RX.getEnergyConsumption() * (duration / (double) Simulator.SECOND_UNIT))
+ " uJ in State " + RX.getName() + " after spending "
+ (duration / (double) Simulator.SECOND_UNIT) + " sec there.");
currentState = TAIL_RX;
lastStateChange = Simulator.getCurrentTime();
Simulator.getScheduler().scheduleIn(TAIL_RX_DURATION, this, TAIL_RX,
tailCounter);
}
@Override
public void doFakeStateChange() {
doStateChange(currentState);
}
private void doStateChange(EnergyState newState){
long timeSpentInState = Simulator.getCurrentTime() - lastStateChange;
Monitor.log(SmartphoneCellularCommunicationEnergyComponent.class, Level.DEBUG,Simulator.getFormattedTime(Simulator.getCurrentTime())
+ " "
+ ((EnergyModel) energyModel).getHost().getHostId()
+ " consumed "
+ (currentState.getEnergyConsumption() * (timeSpentInState/ (double) Simulator.SECOND_UNIT))
+ " uJ in State " + currentState.getName() + " after spending "
+ (timeSpentInState / (double) Simulator.SECOND_UNIT)
+ " sec there.");
energyModel.switchedState(this, currentState, newState,
timeSpentInState);
currentState = newState;
if(!currentState.equals(TAIL_RX) && !currentState.equals(TAIL_TX))
lastStateChange = Simulator.getCurrentTime();
}
}
/*
* 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.energy.configs;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.energy.EnergyConfiguration;
import de.tud.kom.p2psim.api.linklayer.mac.PhyType;
import de.tud.kom.p2psim.impl.energy.SmartphoneCellularCommunicationEnergyComponent;
public class CellularTimeBased implements
EnergyConfiguration<SmartphoneCellularCommunicationEnergyComponent> {
private PhyType phy;
private boolean error = false;
private boolean warning = false;
private final String help = "This is the Time-Based Configuration for the EnergyModel of a cellular connection."
+ "It creates a component for the chosen PHY-Type and each time a message is being sent or received, energy is consumed for the corresponding amount of time, it took to send or receiver the message."
+ "The default parameters for the calculation of the energy consumption are taken from Fabian Kaub's Diploma Thesis.";
private String errorMessage = "";
private String warningMessage = "";
@Override
public SmartphoneCellularCommunicationEnergyComponent getConfiguredEnergyComponent(
SimHost host) {
return new SmartphoneCellularCommunicationEnergyComponent(phy);
}
@Override
public String getHelp() {
if (error) {
return errorMessage;
}
if (warning) {
return warningMessage;
}
return help;
}
@Override
public boolean isWellConfigured() {
if (phy == null) {
error = true;
errorMessage += "\nYou did not specify a PHY-Type for the Time-based Energy Component for cellular communication. Please set the config-parameter \"phy\" to one of "
+ PhyType.printTypes();
}
return !error;
}
public void setPhy(String phy) {
try {
this.phy = Enum.valueOf(PhyType.class, phy.toUpperCase());
} catch (IllegalArgumentException e) {
error = true;
errorMessage += "\nYou did specify an invalid PHY-Type. Allowed types are "
+ PhyType.printTypes();
}
}
}
......@@ -34,7 +34,9 @@ public class TimeBased implements
private boolean warning = false;
private final String help = "This is the MessageBased-Configuration for the EnergyModel. It creates a component for the chosen PHY-Type and each time a message is being sent or received, energy is consumed. The default parameters for the calculation of the energy consumption are taken from Feeneys Paper.";
private final String help = "This is the Time-Based Configuration for the EnergyModel of a Wi-FI ad hoc connection."
+ " It creates a component for the chosen PHY-Type and each time a message is being sent or received, energy is consumed for the corresponding amount of time, it took to send or receiver the message."
+ " The default parameters for the calculation of the energy consumption are taken from Fabian Kaub's Diploma Thesis.";
private String errorMessage = "";
......
......@@ -79,8 +79,8 @@ public class CsvMovement extends AbstractMovementModel {
*
* @param movementPointsFile
*/
@XMLConfigurableConstructor({ "movementPointsFile" })
public CsvMovement(String movementPointsFile) {
@XMLConfigurableConstructor({ "movementPointsFile" , "minMovementSpeed", "maxMovementSpeed" })
public CsvMovement(String movementPointsFile, double minMovementSpeed, double maxMovementSpeed) {
super();
this.worldDimensions = Topology.getWorldDimension();
this.file = movementPointsFile;
......@@ -88,7 +88,7 @@ public class CsvMovement extends AbstractMovementModel {
this.stateInfo = new LinkedHashMap<MovementSupported, CsvMovementInfo>();
this.componentsPathsInfos = new LinkedHashMap<MovementSupported, LinkedList<CsvPathInfo>>();
readData();
readData(minMovementSpeed, maxMovementSpeed);
}
@Override
......@@ -197,7 +197,7 @@ public class CsvMovement extends AbstractMovementModel {
*
* if min speed == max speed = speed
*/
private void readData() {
private void readData(double minMovementSpeed, double maxMovementSpeed) {
readPathInfos.clear();
boolean entrySuccessfullyRead = false;
BufferedReader csv = null;
......@@ -219,10 +219,20 @@ public class CsvMovement extends AbstractMovementModel {
Double x = Double.parseDouble(subParts[0]);
Double y = Double.parseDouble(subParts[1]);
String online = subParts[2];
Double minSpeed = Double
.parseDouble(subParts[3]);
Double maxSpeed = Double
.parseDouble(subParts[4]);
online = online.replaceAll("\\s+","");
Double minSpeed;
Double maxSpeed;
if(online.equals("OFFLINE")){
minSpeed = Double
.parseDouble(subParts[3]);
maxSpeed = Double
.parseDouble(subParts[4]);
}
else{
minSpeed = minMovementSpeed;
maxSpeed = maxMovementSpeed;
}
// log.error("Min speed: " + minSpeed + " max speed " + maxSpeed );
if (x > worldDimensions.getX()
|| y > worldDimensions.getY() || x < 0
......
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