diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 37a7509..d23e771 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,9 @@
-
+
+
+
+
diff --git a/app/src/androidTest/java/de/hems/trafficsim/ExampleInstrumentedTest.java b/app/src/androidTest/java/de/hems/trafficsim/ExampleInstrumentedTest.java
deleted file mode 100644
index 9c45982..0000000
--- a/app/src/androidTest/java/de/hems/trafficsim/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package de.hems.trafficsim;
-
-import android.content.Context;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.junit.Assert.*;
-
-/**
- * Instrumented test, which will execute on an Android device.
- *
- * @see Testing documentation
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
- @Test
- public void useAppContext() {
- // Context of the app under test.
- Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
- assertEquals("de.hems.trafficsim", appContext.getPackageName());
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/de/hems/trafficsim/MainActivity.java b/app/src/main/java/de/hems/trafficsim/MainActivity.java
index 1fda53f..d23c0fe 100644
--- a/app/src/main/java/de/hems/trafficsim/MainActivity.java
+++ b/app/src/main/java/de/hems/trafficsim/MainActivity.java
@@ -1,7 +1,5 @@
package de.hems.trafficsim;
-import androidx.appcompat.app.AppCompatActivity;
-
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
@@ -9,79 +7,143 @@ import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
-import java.util.Observable;
-import java.util.Observer;
+import androidx.appcompat.app.AppCompatActivity;
+/**
+ * Main user interface class, containing all necessary gui elements and their control flow.
+ */
public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener {
+ /**
+ * default value of the number of vehicles on the track
+ */
public static final int defaultNoOfVehicles = 25;
+
+ /**
+ * default value of the length of the track
+ */
public static final int defaultTrackLength = 100;
+
+ /**
+ * default value of brake probability
+ */
public static final float defaultBrakeProb = 0.3f;
+
+ /**
+ * default value of the maximum velocity of the vehicles
+ */
public static final float defaultMaxVelocity = 5.0f;
+
+ /**
+ * default value of the delay between two simulation steps
+ */
public static final int defaultDelay = 0;
+
+ /**
+ * default value of the number of vehicles on the track
+ */
public static final int defaultHistoryLength = 50;
+
+ /**
+ * default value of the number of vehicles on the track
+ */
public static final int defaultFrameskip = 0;
+
+ /**
+ * the track to show in the activity
+ */
protected Track track;
+
+ /**
+ * the surface view on which the renderer draws the track history
+ */
protected TimeRecordView trackView;
+
+ /**
+ * the thread which runs the simulation and visualization
+ */
protected Worker worker;
+
+ /**
+ * the renderer instance drawing the track history
+ */
protected Renderer renderer;
+
+ /**
+ * the layout which keeps the surface view
+ */
protected LinearLayout viewStack;
+ /**
+ * Utility function to round a float to a given amount of digits.
+ *
+ * @param number number to round
+ * @param digits amount of digits
+ * @return rounded number
+ */
+ public static float round(float number, int digits) {
+ float div = (float) Math.pow(10.0f, digits);
+ return Math.round(number * div) / div;
+ }
+
+ /**
+ * Constructor for MainActivity
+ *
+ * @param savedInstanceState Bundle with previously saved activity state, otherwise null
+ */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.track = new Track(defaultNoOfVehicles, defaultTrackLength, defaultBrakeProb,
defaultMaxVelocity, defaultDelay, defaultHistoryLength);
- this.viewStack = (LinearLayout) findViewById(R.id.trackViewStack);
+ this.viewStack = findViewById(R.id.trackViewStack);
this.trackView = new TimeRecordView(this, track);
viewStack.addView(this.trackView);
this.renderer = new Renderer(track, this.trackView.getHolder());
- SeekBar trackLengthSeekBar = (SeekBar) findViewById(R.id.trackLengthSeekBar);
+ SeekBar trackLengthSeekBar = findViewById(R.id.trackLengthSeekBar);
trackLengthSeekBar.setOnSeekBarChangeListener(this);
trackLengthSeekBar.setProgress(defaultTrackLength);
((TextView)(findViewById(R.id.trackLengthTextView))).setText(String.valueOf(defaultTrackLength));
- SeekBar maxVelocitySeekBar = (SeekBar) findViewById(R.id.maxVelocitySeekBar);
+ SeekBar maxVelocitySeekBar = findViewById(R.id.maxVelocitySeekBar);
maxVelocitySeekBar.setOnSeekBarChangeListener(this);
maxVelocitySeekBar.setProgress((int)defaultMaxVelocity);
((TextView)(findViewById(R.id.maxVeloTextView))).setText(String.valueOf((int)defaultMaxVelocity));
- SeekBar noOfVehiclesSeekBar = (SeekBar) findViewById(R.id.noOfVehiclesSeekBar);
+ SeekBar noOfVehiclesSeekBar = findViewById(R.id.noOfVehiclesSeekBar);
noOfVehiclesSeekBar.setOnSeekBarChangeListener(this);
noOfVehiclesSeekBar.setProgress(defaultNoOfVehicles);
((TextView)(findViewById(R.id.noOfVehiclesTextView))).setText(String.valueOf(defaultNoOfVehicles));
- SeekBar brakeProbabilitySeekBar = (SeekBar) findViewById(R.id.brakeProbabilitySeekBar);
+ SeekBar brakeProbabilitySeekBar = findViewById(R.id.brakeProbabilitySeekBar);
brakeProbabilitySeekBar.setOnSeekBarChangeListener(this);
brakeProbabilitySeekBar.setProgress((int)(defaultBrakeProb*20));
((TextView)(findViewById(R.id.brakeProbTextView))).setText(String.valueOf(defaultBrakeProb));
- SeekBar delaySeekBar = (SeekBar)(findViewById(R.id.simDelaySeekBar));
+ SeekBar delaySeekBar = findViewById(R.id.simDelaySeekBar);
delaySeekBar.setOnSeekBarChangeListener(this);
delaySeekBar.setProgress(defaultDelay);
- ((TextView)(findViewById(R.id.simDelayTextView))).setText(String.valueOf(defaultDelay));
+ ((TextView) (findViewById(R.id.simDelayTextView))).setText(String.valueOf(defaultDelay));
- SeekBar frameskipSeekBar = (SeekBar)(findViewById(R.id.frameskipSeekBar));
+ SeekBar frameskipSeekBar = findViewById(R.id.frameskipSeekBar);
frameskipSeekBar.setOnSeekBarChangeListener(this);
frameskipSeekBar.setProgress(defaultFrameskip);
- ((TextView)(findViewById(R.id.frameSkipTextView))).setText(String.valueOf(defaultFrameskip));
+ ((TextView) (findViewById(R.id.frameSkipTextView))).setText(String.valueOf(defaultFrameskip));
this.updateStats();
}
- public static float round(float number, int digits) {
- float div = (float) Math.pow(10.0f, digits);
- return Math.round(number*div)/div;
- }
-
+ /**
+ * Updates the statistics view.
+ */
public void updateStats() {
final Track trackRef = this.track;
- final TextView lastAvgView = (TextView) findViewById(R.id.avgVeloLastView);
- final TextView overallAvgView = (TextView) findViewById(R.id.avgVeloOverallView);
- final TextView delayedAvgView = (TextView) findViewById(R.id.delayedAvgTextView);
- final TextView stepsView = (TextView) findViewById(R.id.stepsTextView);
+ final TextView lastAvgView = findViewById(R.id.avgVeloLastView);
+ final TextView overallAvgView = findViewById(R.id.avgVeloOverallView);
+ final TextView delayedAvgView = findViewById(R.id.delayedAvgTextView);
+ final TextView stepsView = findViewById(R.id.stepsTextView);
runOnUiThread(new Runnable() {
@Override
public void run() {
@@ -93,46 +155,59 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar
});
}
+ /**
+ * Handler function for clicks on the "Step" button.
+ *
+ * @param view the view the event is generated from
+ */
public void onStepButtonClick(View view) {
this.track.timeElapse();
this.updateStats();
this.renderer.draw();
}
+ /**
+ * Handler function for clicks on the "Play" button.
+ *
+ * @param view the view the event is generated from
+ */
public void onPlayButtonClick(View view) {
- Button playButton = (Button) findViewById(R.id.playButton);
+ Button playButton = findViewById(R.id.playButton);
playButton.setEnabled(false);
- Button stepButton = (Button) findViewById(R.id.stepButton);
+ Button stepButton = findViewById(R.id.stepButton);
stepButton.setEnabled(false);
- Button stopButton = (Button) findViewById(R.id.stopButton);
+ Button stopButton = findViewById(R.id.stopButton);
stopButton.setEnabled(true);
- Button clearButton = (Button) findViewById(R.id.clearButton);
+ Button clearButton = findViewById(R.id.clearButton);
clearButton.setEnabled(false);
- int frameskip = ((SeekBar)(findViewById(R.id.frameskipSeekBar))).getProgress();
+ int frameskip = ((SeekBar) (findViewById(R.id.frameskipSeekBar))).getProgress();
this.worker = new Worker(track, this, renderer, frameskip);
this.worker.start();
}
+ /**
+ * Handler function for clicks on the "Stop" button.
+ *
+ * @param view the view the event is generated from
+ */
public void onStopButtonClick(View view) {
- Button playButton = (Button) findViewById(R.id.playButton);
+ Button playButton = findViewById(R.id.playButton);
playButton.setEnabled(true);
- Button stepButton = (Button) findViewById(R.id.stepButton);
+ Button stepButton = findViewById(R.id.stepButton);
stepButton.setEnabled(true);
- Button stopButton = (Button) findViewById(R.id.stopButton);
+ Button stopButton = findViewById(R.id.stopButton);
stopButton.setEnabled(false);
- Button clearButton = (Button) findViewById(R.id.clearButton);
+ Button clearButton = findViewById(R.id.clearButton);
clearButton.setEnabled(true);
- this.worker.setStop(true);
- try {
- this.worker.join();
- } catch (InterruptedException ex) {
-
- }
+ this.stopWorker();
this.worker = null;
}
+ /**
+ * Stops the current worker thread.
+ */
protected void stopWorker() {
this.worker.setStop(true);
try {
@@ -142,15 +217,20 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar
this.worker = null;
}
+ /**
+ * Handler function for clicks on the "Stop" button.
+ *
+ * @param view the view the event is generated from
+ */
public void onClearButtonClick(View view) {
if (this.worker != null) { // There was a simulation running
this.stopWorker();
}
- Button playButton = (Button) findViewById(R.id.playButton);
+ Button playButton = findViewById(R.id.playButton);
playButton.setEnabled(true);
- Button stepButton = (Button) findViewById(R.id.stepButton);
+ Button stepButton = findViewById(R.id.stepButton);
stepButton.setEnabled(true);
- Button stopButton = (Button) findViewById(R.id.stopButton);
+ Button stopButton = findViewById(R.id.stopButton);
stopButton.setEnabled(false);
this.updateTrack();
this.updateStats();
@@ -158,24 +238,28 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar
}
+ /**
+ * Creates a new track with the current settings. This methods restarts the simulation it
+ * it was running before.
+ */
protected void updateTrack() {
- int newTrackLength = ((SeekBar)(findViewById(R.id.trackLengthSeekBar))).getProgress();
- SeekBar noOfVehiclesSeekBar = (SeekBar)(findViewById(R.id.noOfVehiclesSeekBar));
+ int newTrackLength = ((SeekBar) (findViewById(R.id.trackLengthSeekBar))).getProgress();
+ SeekBar noOfVehiclesSeekBar = findViewById(R.id.noOfVehiclesSeekBar);
int newNoOfVehicles = noOfVehiclesSeekBar.getProgress();
if (newTrackLength < newNoOfVehicles) { // Dont allow values greater than track length!
- newNoOfVehicles = (int) newTrackLength;
+ newNoOfVehicles = newTrackLength;
noOfVehiclesSeekBar.setProgress(newNoOfVehicles);
}
- TextView noOfVehiclesTextView = (TextView)(findViewById(R.id.noOfVehiclesTextView));
+ TextView noOfVehiclesTextView = findViewById(R.id.noOfVehiclesTextView);
noOfVehiclesTextView.setText(String.valueOf(newNoOfVehicles));
- TextView trackLengthTextView = (TextView)(findViewById(R.id.trackLengthTextView));
+ TextView trackLengthTextView = findViewById(R.id.trackLengthTextView);
trackLengthTextView.setText(String.valueOf(newTrackLength));
float newMaxVelocity = ((SeekBar) findViewById(R.id.maxVelocitySeekBar)).getProgress();
- SeekBar brakeProbabilitySeekBar = (SeekBar) findViewById(R.id.brakeProbabilitySeekBar);
- float newBrakeProb = (float)brakeProbabilitySeekBar.getProgress()
+ SeekBar brakeProbabilitySeekBar = findViewById(R.id.brakeProbabilitySeekBar);
+ float newBrakeProb = (float) brakeProbabilitySeekBar.getProgress()
/ (float)brakeProbabilitySeekBar.getMax();
int newDelay = ((SeekBar)(findViewById(R.id.simDelaySeekBar))).getProgress();
@@ -186,7 +270,8 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar
this.worker.setStop(true);
try {
this.worker.join();
- } catch (InterruptedException ex) { }
+ } catch (InterruptedException ex) {
+ }
}
this.track = new Track(newNoOfVehicles, newTrackLength, newBrakeProb, newMaxVelocity,
@@ -199,27 +284,34 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar
}
}
+ /**
+ * Handler function for changes on the seek bars.
+ *
+ * @param seekBar the seek bar changed
+ * @param progress the new progress value of the seek bar
+ * @param fromUser flag if the event is the result of an user action
+ */
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if (seekBar == (SeekBar)(findViewById(R.id.noOfVehiclesSeekBar))) {
+ if (seekBar == findViewById(R.id.noOfVehiclesSeekBar)) {
this.updateTrack();
- } else if (seekBar == (SeekBar)(findViewById(R.id.brakeProbabilitySeekBar))) {
- float newBrakeProb = (float)seekBar.getProgress() / (float)seekBar.getMax();
+ } else if (seekBar == findViewById(R.id.brakeProbabilitySeekBar)) {
+ float newBrakeProb = (float) seekBar.getProgress() / (float) seekBar.getMax();
this.track.setBrakeProb(newBrakeProb);
- TextView newBrakeProbTextView = (TextView)(findViewById(R.id.brakeProbTextView));
+ TextView newBrakeProbTextView = findViewById(R.id.brakeProbTextView);
newBrakeProbTextView.setText(String.valueOf((newBrakeProb)));
- } else if (seekBar == (SeekBar)(findViewById(R.id.maxVelocitySeekBar))) {
+ } else if (seekBar == findViewById(R.id.maxVelocitySeekBar)) {
this.track.setMaxVelocity(seekBar.getProgress());
- TextView tv = (TextView)(findViewById(R.id.maxVeloTextView));
+ TextView tv = findViewById(R.id.maxVeloTextView);
tv.setText(String.valueOf(progress));
- } else if (seekBar == (SeekBar)(findViewById(R.id.trackLengthSeekBar))) {
+ } else if (seekBar == findViewById(R.id.trackLengthSeekBar)) {
this.updateTrack();
- } else if (seekBar == (SeekBar)(findViewById(R.id.simDelaySeekBar))) {
- TextView tv = (TextView)(findViewById(R.id.simDelayTextView));
+ } else if (seekBar == findViewById(R.id.simDelaySeekBar)) {
+ TextView tv = findViewById(R.id.simDelayTextView);
tv.setText(String.valueOf(seekBar.getProgress()));
this.track.setWaitTime(seekBar.getProgress());
- } else if (seekBar == (SeekBar)(findViewById(R.id.frameskipSeekBar))) {
- TextView tv = (TextView)(findViewById(R.id.frameSkipTextView));
+ } else if (seekBar == findViewById(R.id.frameskipSeekBar)) {
+ TextView tv = findViewById(R.id.frameSkipTextView);
tv.setText(String.valueOf(seekBar.getProgress()));
if (this.worker != null) {
this.worker.setFrameskip(seekBar.getProgress());
@@ -227,11 +319,21 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar
}
}
+ /**
+ * Handler function for beginning touch events on a seek bar.
+ *
+ * @param seekBar the seek bar touched
+ */
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
+ /**
+ * Handler function for ending touch events on a seek bar.
+ *
+ * @param seekBar the seek bar touched
+ */
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
diff --git a/app/src/main/java/de/hems/trafficsim/Renderer.java b/app/src/main/java/de/hems/trafficsim/Renderer.java
index 14b1bf8..06787d3 100644
--- a/app/src/main/java/de/hems/trafficsim/Renderer.java
+++ b/app/src/main/java/de/hems/trafficsim/Renderer.java
@@ -9,25 +9,73 @@ import android.view.SurfaceHolder;
import java.util.ConcurrentModificationException;
import java.util.List;
+/**
+ * User interface class rendering the track history on a SurfaceView.
+ */
public class Renderer {
- private List stepRecords;
+ /**
+ * the track to render
+ */
protected Track track;
+ /**
+ * width of a rectangle representing one vehicle
+ */
protected int pixelPerVehicle;
+ /**
+ * height of a rectangle representing one vehicle
+ */
protected int pixelPerLine;
+ /**
+ * amount of pixels per track position which are lost by rounding
+ */
protected float tooShortPerTrackLength;
+ /**
+ * amount of pixels per height which are lost by rounding
+ */
protected float tooShortPerHeight;
+ /**
+ * Paint instance of the renderer
+ */
protected Paint paint;
+ /**
+ * holder of the surface the renderer draws to
+ */
protected SurfaceHolder holder;
- protected Canvas canvas;
+ /**
+ * width of the surface to draw to
+ */
protected int width;
+ /**
+ * height of the surface to draw to
+ */
protected int height;
+ /**
+ * temporary reference to the time records of one simulation step
+ */
+ private List stepRecords;
+ /**
+ * temporary reference to the canvas to draw to
+ */
+ private Canvas canvas;
+ /**
+ * Constuctor for a Renderer.
+ *
+ * @param track the track to render
+ * @param holder the holder of the surface to draw to
+ */
public Renderer(Track track, SurfaceHolder holder) {
this.track = track;
this.holder = holder;
this.paint = new Paint();
}
+ /**
+ * Updates the dimension information of the renderer.
+ *
+ * @param width the width of the SurfaceView
+ * @param height the height of the SurfaceView
+ */
public void setSize(int width, int height) {
if (width > 0 && height > 0) {
this.pixelPerVehicle = width / (int) this.track.getTrackLength();
@@ -36,34 +84,50 @@ public class Renderer {
/ this.track.getTrackLength();
this.pixelPerLine = height / this.track.getHistoryLength();
this.tooShortPerHeight = (height - this.pixelPerLine * this.track.getHistoryLength())
- / (float)height;
- System.out.println("Viewport: "+width+"x"+height);
+ / (float) height;
+ System.out.println("Viewport: " + width + "x" + height);
this.width = width;
this.height = height;
}
}
+ /**
+ * Updates the track of the Surface.
+ *
+ * @param track the new track to render
+ */
public void setTrack(Track track) {
this.track = track;
this.setSize(width, height);
}
+ /**
+ * Utility function which calculates a color from the relation between the current speed of a
+ * vehicle and it's maximum speed (from red over yellow to green).
+ *
+ * @param curVelocity current velocity of the vehicle
+ * @param maxVelocity maximum velocity of the vehilce
+ * @return color encoded as Android color integer
+ */
protected int getColor(float curVelocity, float maxVelocity) {
float perc = curVelocity / maxVelocity;
perc = 1 - perc;
if (perc <= 0.5) {
- int red = ((int) (2*perc*0xFF)) << 16;
+ int red = ((int) (2 * perc * 0xFF)) << 16;
int green = 0xFF << 8;
int blue = 0;
return 0xff000000 | red | green | blue;
} else {
int red = 0xFF << 16;
- int green = ((int)(0xFF-0xFF*(perc-0.5)*2)) << 8;
+ int green = ((int) (0xFF - 0xFF * (perc - 0.5) * 2)) << 8;
int blue = 0;
return 0xff000000 | red | green | blue;
}
}
+ /**
+ * Draws the current state of the track history to the Surface.
+ */
protected void draw() {
try {
if (this.pixelPerVehicle == 0) {
@@ -79,7 +143,7 @@ public class Renderer {
int vCompensateStart = 0;
int vCompensateEnd = 0;
canvas.drawColor(Color.BLACK);
- for (int curStepIdx = this.track.getVtrList().size()-1;curStepIdx >= 0;
+ for (int curStepIdx = this.track.getVtrList().size()-1; curStepIdx >= 0;
curStepIdx--) {
try {
try {
diff --git a/app/src/main/java/de/hems/trafficsim/TimeRecordView.java b/app/src/main/java/de/hems/trafficsim/TimeRecordView.java
index da9aedd..4b3ee7d 100644
--- a/app/src/main/java/de/hems/trafficsim/TimeRecordView.java
+++ b/app/src/main/java/de/hems/trafficsim/TimeRecordView.java
@@ -1,24 +1,26 @@
package de.hems.trafficsim;
-import android.app.ActionBar;
import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.text.Layout;
import android.view.SurfaceView;
-import android.view.View;
import android.view.ViewGroup;
-import java.util.ConcurrentModificationException;
-import java.util.List;
-
+/**
+ * A Surface View which servers as a stage for a renderer.
+ */
public class TimeRecordView extends SurfaceView {
public TimeRecordView(Context context, Track track) {
super(context);
this.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
+ /**
+ * Updates the size information of the SurfaceView, used by the Android SDK.
+ *
+ * @param w new width
+ * @param h new height
+ * @param oldw old width
+ * @param oldh old height
+ */
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
diff --git a/app/src/main/java/de/hems/trafficsim/Track.java b/app/src/main/java/de/hems/trafficsim/Track.java
index d372319..2f139b0 100644
--- a/app/src/main/java/de/hems/trafficsim/Track.java
+++ b/app/src/main/java/de/hems/trafficsim/Track.java
@@ -5,42 +5,92 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Observable;
import java.util.concurrent.Semaphore;
-import java.util.concurrent.locks.LockSupport;
+/**
+ * Main model class of TrafficSim. Represents a round course containing vehicles.
+ */
public class Track extends Observable {
+ /**
+ * list a vehicles on the track
+ */
protected List vehicles;
+
+ /**
+ * list of resulting time records of the simulation
+ */
protected List> vtrList;
+
+ /**
+ * length of the track
+ */
protected float trackLength;
+
+ /**
+ * sum of all vehicle speeds during the simulation, used for average calculation
+ */
protected float sumAvgMemory;
+
+ /**
+ * sum of all vehicle speeds during the simulation ignoring the first ten steps,
+ * used for average calculation
+ */
protected float sumDelAvgMemory;
+
+ /**
+ * length of the history kept
+ */
protected int historyLength;
+
+ /**
+ * average over all velocities in the simulation
+ */
protected float overallAvg;
+
+ /**
+ * average over all velocities in the simulation, ignoring the first ten steps
+ */
protected float delayedAvg;
+
+ /**
+ * average over all velocities in the last step
+ */
protected float lastAvg;
+
+ /**
+ * current configured wait time between two simulation steps
+ */
protected int waitTime;
+
+ /**
+ * currently configured max velocity for all vehicles
+ */
protected float maxVelocity;
+
+ /**
+ * currently configured brake probability for all vehicles
+ */
protected float brakeProb;
+
+ /**
+ * counter for executed simulation steps
+ */
protected long steps;
- protected Semaphore listSemaphore;
- public List> getVtrList() { return vtrList; }
- public float getOverallAvg() {
- return overallAvg;
- }
- public float getLastAvg() {
- return lastAvg;
- }
- public float getDelayedAvg() { return delayedAvg; }
- public List getVehicles() {
- return vehicles;
- }
- public float getTrackLength() {
- return trackLength;
- }
- public long getSteps() { return steps; }
- public Semaphore getListSemaphore() { return listSemaphore; }
- public int getHistoryLength() { return historyLength; }
+ /**
+ * semaphore protecting the vtrlist
+ */
+ protected Semaphore listSemaphore;
+ /**
+ * Constructor for a new Track.
+ *
+ * @param numberVehicles number of vehicles on the Track
+ * @param trackLength length of the new Track
+ * @param brakeProb probability of a vehicle to suddenly brake without reason
+ * @param maxVelocity maxmimum velocity of the vehicles
+ * @param waitTime time between two simulation steps to slow down the simulation artificially
+ * @param historyLength length of the history to keep
+ */
public Track(int numberVehicles, float trackLength, float brakeProb, float maxVelocity, int waitTime, int historyLength) {
this.trackLength = trackLength;
this.brakeProb = brakeProb;
@@ -59,9 +109,96 @@ public class Track extends Observable {
}
- protected List createVehiclesList(int numberVehicles){
+ /**
+ * Getter for vtrList
+ *
+ * @return vtrList
+ */
+ public List> getVtrList() {
+ return vtrList;
+ }
+
+ /**
+ * Getter for overallAvg
+ *
+ * @return overallAvg
+ */
+ public float getOverallAvg() {
+ return overallAvg;
+ }
+
+ /**
+ * Getter for lastAvg
+ *
+ * @return lastAvg
+ */
+ public float getLastAvg() {
+ return lastAvg;
+ }
+
+ /**
+ * Getter for delayedAvg
+ *
+ * @return delayedAvg
+ */
+ public float getDelayedAvg() {
+ return delayedAvg;
+ }
+
+ /**
+ * Getter for vehicles
+ *
+ * @return vehicles
+ */
+ public List getVehicles() {
+ return vehicles;
+ }
+
+ /**
+ * Getter for trackLength
+ *
+ * @return trackLength
+ */
+ public float getTrackLength() {
+ return trackLength;
+ }
+
+ /**
+ * Getter for steps
+ *
+ * @return steps
+ */
+ public long getSteps() {
+ return steps;
+ }
+
+ /**
+ * Getter for listSemaphore
+ *
+ * @return listSemaphore
+ */
+ public Semaphore getListSemaphore() {
+ return listSemaphore;
+ }
+
+ /**
+ * Getter for historyLength
+ *
+ * @return historyLength
+ */
+ public int getHistoryLength() {
+ return historyLength;
+ }
+
+ /**
+ * Utility function to add vehicles to the Track.
+ *
+ * @param numberVehicles number of vehicles to add
+ * @return filled list with vehicles
+ */
+ protected List createVehiclesList(int numberVehicles) {
List result = new ArrayList<>();
- for(int i=0;i= vehicles.size()) {
@@ -94,7 +249,7 @@ public class Track extends Observable {
}
Vehicle forerunner = vehicles.get(forerunnerIndex);
float distanceForerunner = forerunner.getPosition() - v.getPosition() - 1;
- if(distanceForerunner < 0.0){
+ if (distanceForerunner < 0.0) {
distanceForerunner += this.trackLength;
}
v.updateVelocity(distanceForerunner);
@@ -117,25 +272,32 @@ public class Track extends Observable {
this.listSemaphore.release();
update_avg();
- this.setChanged();
- //this.notifyObservers();
- this.clearChanged();
- //LockSupport.parkNanos(1);
- try {
+ try {
Thread.sleep(waitTime);
- } catch (InterruptedException ex) { }
+ } catch (InterruptedException ex) {
+ }
}
- public float avg_step(int step){
+ /**
+ * Returns the average velocity of the given simulation step.
+ *
+ * @param step index of the step in the history list
+ * @return average velocity
+ */
+ public float avg_step(int step) {
float sum_step = 0;
for (VehicleTimeRecord r : vtrList.get(step)) {
- sum_step += r.velocity;
+ sum_step += r.velocity;
}
return sum_step / vehicles.size();
}
- protected void update_avg(){
- lastAvg = avg_step(vtrList.size()-1);
+ /**
+ * Utility function which updates the averages values with the results from the last simulation
+ * step.
+ */
+ protected void update_avg() {
+ lastAvg = avg_step(vtrList.size() - 1);
if (this.steps > 10) {
sumDelAvgMemory += lastAvg;
delayedAvg = sumDelAvgMemory / (this.steps - 10);
@@ -144,13 +306,4 @@ public class Track extends Observable {
overallAvg = sumAvgMemory / this.steps;
}
-
- public float avg_span(int start, int end){
- float sum_span = 0;
- for (int i=start; i
+ *
Increase by one if the vehicle is slower than it's maximum speed
+ *
Random brake by one
+ *
Break if the distance to the forerunner is less than it's speed
+ *
+ *
+ * @param distanceForerunner distance to the forerunner of the vehicle
+ */
public void updateVelocity(float distanceForerunner) {
Random random = new Random();
@@ -53,6 +126,9 @@ public class Vehicle {
}
}
+ /**
+ * Updates the position of the vehicle according to it's previously calculated speed.
+ */
public void timeElapse() {
position = (position + curVelocity) % this.trackLength;
}
diff --git a/app/src/main/java/de/hems/trafficsim/VehicleTimeRecord.java b/app/src/main/java/de/hems/trafficsim/VehicleTimeRecord.java
index 339a9bf..2da5374 100644
--- a/app/src/main/java/de/hems/trafficsim/VehicleTimeRecord.java
+++ b/app/src/main/java/de/hems/trafficsim/VehicleTimeRecord.java
@@ -1,9 +1,27 @@
package de.hems.trafficsim;
+/**
+ * Model class which keeps the previous simulation data for analysis.
+ */
public class VehicleTimeRecord {
+ /**
+ * the id of the vehicle it belongs to
+ */
protected int id;
+
+ /**
+ * the position of the vehicle after the last simulation step
+ */
protected float position;
+
+ /**
+ * the velocity of the vehicle during the last simulation step
+ */
protected float velocity;
+
+ /**
+ * the maximum velocity of the vehicle
+ */
protected float maxVelocity;
public float getMaxVelocity() {
@@ -18,6 +36,14 @@ public class VehicleTimeRecord {
return velocity;
}
+ /**
+ * Construct a new VehicleTimeRecord.
+ *
+ * @param id the id of the vehicle it belongs to
+ * @param position the position of the vehicle after the last simulation step
+ * @param velocity the velocity of the vehicle during the last simulation step
+ * @param maxVelocity the maximum velocity of the vehicle
+ */
public VehicleTimeRecord(int id, float position, float velocity, float maxVelocity) {
this.id = id;
this.position = position;
diff --git a/app/src/main/java/de/hems/trafficsim/Worker.java b/app/src/main/java/de/hems/trafficsim/Worker.java
index 89fdcf8..942e93b 100644
--- a/app/src/main/java/de/hems/trafficsim/Worker.java
+++ b/app/src/main/java/de/hems/trafficsim/Worker.java
@@ -1,17 +1,46 @@
package de.hems.trafficsim;
import android.graphics.Canvas;
-import android.view.SurfaceHolder;
-
-import java.util.ConcurrentModificationException;
+/**
+ * Calculation thread, which runs the simulation itself and also updates the view with a set rate.
+ */
public class Worker extends Thread {
+ /**
+ * the track to simulate
+ */
protected Track track;
+
+ /**
+ * Stop flag, indicating that the worker shall stop
+ */
protected boolean stop;
+
+ /**
+ * the MainActivity of the gui
+ */
protected MainActivity gui;
+
+ /**
+ * the Renderer drawing the Track
+ */
protected Renderer renderer;
+
+ /**
+ * Amount of simulation steps between two frames in the view. Zero means
+ * that every simulation step is drawn.
+ */
protected int frameskip;
+ /**
+ * Construct a new worker.
+ *
+ * @param track the track to simulate
+ * @param gui the MainActivity of the gui
+ * @param renderer the Renderer drawing the Track
+ * @param frameskip Amount of simulation steps between two frames in the view. Zero means
+ * that every simulation step is drawn
+ */
public Worker(Track track, MainActivity gui, Renderer renderer, int frameskip) {
super();
this.track = track;
@@ -21,16 +50,28 @@ public class Worker extends Thread {
this.frameskip = frameskip;
}
+ /**
+ * Sets a flag that causes the worker to stop.
+ *
+ * @param stop flag whether the thread shall stop
+ */
public void setStop(boolean stop) {
this.stop = stop;
}
+ /**
+ * Updates the amount of simulation steps between to view frames.
+ *
+ * @param frames amount of steps
+ */
public void setFrameskip(int frames) {
this.frameskip = frames;
}
- public int getFrameskip() { return this.frameskip; }
-
+ /**
+ * Method which is automatically executed when the thread is started. It alternates between
+ * updating the simulation and drawing a new frame in the view.
+ */
@Override
public void run() {
Canvas canvas = null;
@@ -40,7 +81,7 @@ public class Worker extends Thread {
this.gui.updateStats();
if (i >= this.frameskip) {
this.renderer.draw();
- i=0;
+ i = 0;
}
i++;
}
diff --git a/app/src/test/java/de/hems/trafficsim/ExampleUnitTest.java b/app/src/test/java/de/hems/trafficsim/ExampleUnitTest.java
deleted file mode 100644
index 0b68bb6..0000000
--- a/app/src/test/java/de/hems/trafficsim/ExampleUnitTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package de.hems.trafficsim;
-
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * @see Testing documentation
- */
-public class ExampleUnitTest {
- @Test
- public void addition_isCorrect() {
- assertEquals(4, 2 + 2);
- }
-}
\ No newline at end of file