*************************************************************************************************************
package movement;
import java.util.Random;
public static double random()
- 返回帶正號的
double
值,該值大於等於 0.0
且小於 1.0
。返回值是一個僞隨機選擇的數,在該範圍內(近似)均勻分佈。
import core.Coord;
//Class to hold 2D coordinates and perform simple arithmetics and transformations
import core.DTNSim;
//Simulator's main class
import core.ModuleCommunicationBus;
//Intermodule communication bus. Works as a blackboard where modules can post data, subscribe to data changes and also poll for data values. This is fairly similar to Message class' property interface, but these values
are shared for a node instead of message
import core.Settings;
//Interface for simulation settings stored in setting file(s).
import core.SimClock;
/ /Wall clock for checking the simulation time
import core.SimError;
//Error in the simulation
/**
* <P> Superclass for all movement models.
* 滿足三個條件:
* 1. All subclasses must contain at least a constructor(構造函數) with one
{@link Settings} parameter and also a copy-constructor.
* 2. They must also implement the { @link #replicate()} method, which should return
* an instance of the movement model class with same parameters as the object
* (immutable fields can be shared, but mutable fields must be copied).</P>
* 3. To make a new movement model do something useful, also at least
* { @link #getInitialLocation()} and {
@link #getPath()} are worthwhile to
* override.</P>
*/
public abstract class MovementModel {
/** node's speed CSV (min, max) -setting id ({@value})*/
public
static final String SPEED = "speed";
/** node's wait time CSV (min, max) -setting id ({@value})*/
public static final String WAIT_TIME = "waitTime";
/** default setting for speed distribution */
public static final double[] DEF_SPEEDS = {1,1};
/** default setting for wait time distribution */
public static final double[] DEF_WAIT_TIMES = {0,0};
/** MovementModel namespace (where world size and rng seed settings
* are looked from ({@value})*/
public static final String MOVEMENT_MODEL_NS = "MovementModel";
/** world's size CSV (width, height) -setting id ({@value})*/
public static final String WORLD_SIZE = "worldSize";
/** movement models' rng seed -setting id ({@value})*/
public static final String RNG_SEED = "rngSeed";
/** common rng for all movement models in the simulation */
protected static
Random rng;
// 被protected修飾的變量,可以被本類,本包中的其他類,和它的子類訪問。rng是一個隨機產生的值
private
ActivenessHandler ah;
// Object of this class tell the movement models when a node belonging to a certain group is active and when not.
protected double minSpeed;
protected double maxSpeed;
protected double minWaitTime;
protected double maxWaitTime;
private int maxX;
private int maxY;
protected
ModuleCommunicationBus comBus;
//前部分首先對變量進行初始化
// static initialization of all movement models' random number generator
static {
DTNSim.registerForReset(MovementModel.class.
getCanonicalName());
reset();
}
//String java.lang.Class.getCanonicalName():Returns the canonical name of the underlying
class as defined by the Java Language Specification
//以上對移動模型初始化
/**
* Checks that the minimum setting is not bigger than the maximum and
* that both are positive
* @param name Name of the setting
* @param min The minimum setting
* @param max The maximum setting
*/
private static void checkMinAndMaxSetting(String name,
double min, double max) {
if (min < 0 || max < 0) {
throw new SimError("MovementModel." + name + " (in Settings)" +
" has a value less than zero ("+min+", "+max+")");
}
if (min > max) {
throw new SimError("MovementModel." + name + " (in Settings)" +
" min is bigger than max ("+min+", "+max+")");
}
}
/**
* Empty constructor for testing purposes.
*/
public MovementModel() {
super();
}
//MovementModel方法的重載
/**
* Creates a new MovementModel
based on a Settings object's settings.
* @param settings The Settings object where the settings are read from
*/
public MovementModel(
Settings settings) {
double[] speeds;
double[] times;
ah = new ActivenessHandler(settings);
if (settings.contains(SPEED)) {
speeds = settings.getCsvDoubles(SPEED, 2);
}
else {
speeds = DEF_SPEEDS;
}
minSpeed = speeds[0];
maxSpeed = speeds[1];
checkMinAndMaxSetting(SPEED,minSpeed,maxSpeed);
if(settings.contains(WAIT_TIME)) {
times = settings.getCsvDoubles(WAIT_TIME, 2);
}
else {
times = DEF_WAIT_TIMES;
}
minWaitTime = times[0];
maxWaitTime = times[1];
checkMinAndMaxSetting(WAIT_TIME,minWaitTime,maxWaitTime);
settings.setNameSpace(MOVEMENT_MODEL_NS);
int [] worldSize = settings.getCsvInts(WORLD_SIZE,2);
this.maxX = worldSize[0];
this.maxY = worldSize[1];
settings.restoreNameSpace();
}
//以上將setting中的參數取出:速度最大最小值,等待時間最大最小,
和仿真空間x,y軸最大值(注意檢查)
//滿足了條件1
/**
* Copyconstructor.
Creates a new MovementModel based on the given
* prototype.
* @param mm The MovementModel prototype to base the new object to
*/
public MovementModel(MovementModel mm) {
this.maxSpeed = mm.maxSpeed;
this.minSpeed = mm.minSpeed;
this.maxWaitTime = mm.maxWaitTime;
this.minWaitTime = mm.minWaitTime;
this.maxX = mm.maxX;
this.maxY = mm.maxY;
this.ah = mm.ah;
this.comBus = null;
}
/**
* Returns the largest X coordinate value this model uses
* @return Maximum of X coordinate values
*/
public int getMaxX() {
return this.maxX;
}
/**
* Returns the largest Y coordinate value this model uses
* @return Maximum of Y coordinate values
*/
public int getMaxY() {
return this.maxY;
}
//以上創建新的移動模型
(複製建構)
//條件1
/**
* Generates and returns a speed value between min and max of the
* {@link #WAIT_TIME} setting.
* @return A new speed between min and max values
*/
protected double generateSpeed() {
if (rng == null) {
return 1;
}
return (maxSpeed - minSpeed) * rng.nextDouble() + minSpeed;
}
//public double
nextDouble()
- 返回下一個僞隨機數,它是取自此隨機數生成器序列的、在
0.0
和
1.0
之間均勻分佈的 double
值
/**
* Generates and returns a suitable waiting time at the end of a path.
* (i.e. random variable whose value is between min and max of the
* {@link #WAIT_TIME} setting).
* @return The time as a double
*/
protected double generateWaitTime() {
if (rng == null) {
return 0;
}
return (maxWaitTime - minWaitTime) * rng.nextDouble() +
minWaitTime;
}
//以上利用隨機數產生速度和等待時間
/**
* Returns a new path by this movement model or null if no new path could
* be constructed at the moment (node should wait where it is). A new
* path should not be requested before the destination of the previous
* path has been reached.
* @return A new path or null
*/
public abstract
Path getPath();
/**
* Returns a new initial placement for a node
* @return The initial coordinates for a node
*/
public abstract
Coord getInitialLocation();
// 以上兩種方法需要在子類中覆寫
//條件3
/**
* Returns true if this node is active at the moment (false if not)
* @return true if this node is active (false if not)
*/
public boolean isActive() {
return
ah.isActive();
}
//節點當前是否激活
/**
* Returns a sim time when the next path is available. This implementation
* returns a random time in future that is {@link #WAIT_TIME} from now.
* @return The sim time when node should ask the next time for a path
*/
public double nextPathAvailable() {
return SimClock.getTime() + generateWaitTime();
}
//返回允許下一條路徑的時間
/**
* Sets the module communication bus for this movement model
* @param comBus The communications bus to set
*/
public void setComBus(ModuleCommunicationBus comBus) {
this.comBus = comBus;
}
// 爲這個移動模型設置模塊通信總線
/**
* Returns the module communication bus of this movement model (if any)
* @return The communications bus or null if one is not set
*/
public ModuleCommunicationBus getComBus() {
return this.comBus;
}
// 返回
/**
* Returns simply the name of the movement model class
* @return the name of the movement model class
*/
public String toString() {
return this.getClass().getSimpleName();
}
//返回移動模型類的簡單名字
Returns the simple name of the underlying class as given in the source code. Returns an empty string if the underlying class is anonymous
/**
* Creates a replicate of the movement model.
* @return A new movement model with the same settings as this model
*/
public abstract
MovementModel replicate();
//建立一個移動模型的複製
條件2
/**
* Resets all static fields to default values
*/
public static void reset() {
Settings s = new Settings(MOVEMENT_MODEL_NS);
if (s.contains(RNG_SEED)) {
int seed = s.getInt(RNG_SEED);
rng = new Random(seed);
}
else {
rng = new Random(0);
}
}
}