Compare commits
	
		
			2 Commits
		
	
	
		
			4761cd3916
			...
			7d5be6ee31
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7d5be6ee31 | |||
|  | ada569035d | 
							
								
								
									
										6
									
								
								.idea/compiler.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.idea/compiler.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="CompilerConfiguration"> | ||||||
|  |     <bytecodeTargetLevel target="1.8" /> | ||||||
|  |   </component> | ||||||
|  | </project> | ||||||
| @ -1,6 +1,9 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <project version="4"> | <project version="4"> | ||||||
|   <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK"> |   <component name="JavadocGenerationManager"> | ||||||
|  |     <option name="OUTPUT_DIRECTORY" value="$USER_HOME$/Desktop/TrafficSimDoc" /> | ||||||
|  |   </component> | ||||||
|  |   <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> | ||||||
|     <output url="file://$PROJECT_DIR$/build/classes" /> |     <output url="file://$PROJECT_DIR$/build/classes" /> | ||||||
|   </component> |   </component> | ||||||
|   <component name="ProjectType"> |   <component name="ProjectType"> | ||||||
|  | |||||||
| @ -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 <a href="http://d.android.com/tools/testing">Testing documentation</a> |  | ||||||
|  */ |  | ||||||
| @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()); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,7 +1,5 @@ | |||||||
| package de.hems.trafficsim; | package de.hems.trafficsim; | ||||||
| 
 | 
 | ||||||
| import androidx.appcompat.app.AppCompatActivity; |  | ||||||
| 
 |  | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
| import android.view.View; | import android.view.View; | ||||||
| import android.widget.Button; | import android.widget.Button; | ||||||
| @ -9,79 +7,143 @@ import android.widget.LinearLayout; | |||||||
| import android.widget.SeekBar; | import android.widget.SeekBar; | ||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
| 
 | 
 | ||||||
| import java.util.Observable; | import androidx.appcompat.app.AppCompatActivity; | ||||||
| import java.util.Observer; |  | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Main user interface class, containing all necessary gui elements and their control flow. | ||||||
|  |  */ | ||||||
| public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener { | public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener { | ||||||
|  |     /** | ||||||
|  |      * default value of the number of vehicles on the track | ||||||
|  |      */ | ||||||
|     public static final int defaultNoOfVehicles = 25; |     public static final int defaultNoOfVehicles = 25; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * default value of the length of the track | ||||||
|  |      */ | ||||||
|     public static final int defaultTrackLength = 100; |     public static final int defaultTrackLength = 100; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * default value of brake probability | ||||||
|  |      */ | ||||||
|     public static final float defaultBrakeProb = 0.3f; |     public static final float defaultBrakeProb = 0.3f; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * default value of the maximum velocity of the vehicles | ||||||
|  |      */ | ||||||
|     public static final float defaultMaxVelocity = 5.0f; |     public static final float defaultMaxVelocity = 5.0f; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * default value of the delay between two simulation steps | ||||||
|  |      */ | ||||||
|     public static final int defaultDelay = 0; |     public static final int defaultDelay = 0; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * default value of the number of vehicles on the track | ||||||
|  |      */ | ||||||
|     public static final int defaultHistoryLength = 50; |     public static final int defaultHistoryLength = 50; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * default value of the number of vehicles on the track | ||||||
|  |      */ | ||||||
|     public static final int defaultFrameskip = 0; |     public static final int defaultFrameskip = 0; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * the track to show in the activity | ||||||
|  |      */ | ||||||
|     protected Track track; |     protected Track track; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * the surface view on which the renderer draws the track history | ||||||
|  |      */ | ||||||
|     protected TimeRecordView trackView; |     protected TimeRecordView trackView; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * the thread which runs the simulation and visualization | ||||||
|  |      */ | ||||||
|     protected Worker worker; |     protected Worker worker; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * the renderer instance drawing the track history | ||||||
|  |      */ | ||||||
|     protected Renderer renderer; |     protected Renderer renderer; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * the layout which keeps the surface view | ||||||
|  |      */ | ||||||
|     protected LinearLayout viewStack; |     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 |     @Override | ||||||
|     protected void onCreate(Bundle savedInstanceState) { |     protected void onCreate(Bundle savedInstanceState) { | ||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
|         setContentView(R.layout.activity_main); |         setContentView(R.layout.activity_main); | ||||||
|         this.track = new Track(defaultNoOfVehicles, defaultTrackLength, defaultBrakeProb, |         this.track = new Track(defaultNoOfVehicles, defaultTrackLength, defaultBrakeProb, | ||||||
|                 defaultMaxVelocity, defaultDelay, defaultHistoryLength); |                 defaultMaxVelocity, defaultDelay, defaultHistoryLength); | ||||||
|         this.viewStack = (LinearLayout) findViewById(R.id.trackViewStack); |         this.viewStack = findViewById(R.id.trackViewStack); | ||||||
|         this.trackView = new TimeRecordView(this, track); |         this.trackView = new TimeRecordView(this, track); | ||||||
| 
 | 
 | ||||||
|         viewStack.addView(this.trackView); |         viewStack.addView(this.trackView); | ||||||
|         this.renderer = new Renderer(track, this.trackView.getHolder()); |         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.setOnSeekBarChangeListener(this); | ||||||
|         trackLengthSeekBar.setProgress(defaultTrackLength); |         trackLengthSeekBar.setProgress(defaultTrackLength); | ||||||
|         ((TextView)(findViewById(R.id.trackLengthTextView))).setText(String.valueOf(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.setOnSeekBarChangeListener(this); | ||||||
|         maxVelocitySeekBar.setProgress((int)defaultMaxVelocity); |         maxVelocitySeekBar.setProgress((int)defaultMaxVelocity); | ||||||
|         ((TextView)(findViewById(R.id.maxVeloTextView))).setText(String.valueOf((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.setOnSeekBarChangeListener(this); | ||||||
|         noOfVehiclesSeekBar.setProgress(defaultNoOfVehicles); |         noOfVehiclesSeekBar.setProgress(defaultNoOfVehicles); | ||||||
|         ((TextView)(findViewById(R.id.noOfVehiclesTextView))).setText(String.valueOf(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.setOnSeekBarChangeListener(this); | ||||||
|         brakeProbabilitySeekBar.setProgress((int)(defaultBrakeProb*20)); |         brakeProbabilitySeekBar.setProgress((int)(defaultBrakeProb*20)); | ||||||
|         ((TextView)(findViewById(R.id.brakeProbTextView))).setText(String.valueOf(defaultBrakeProb)); |         ((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.setOnSeekBarChangeListener(this); | ||||||
|         delaySeekBar.setProgress(defaultDelay); |         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.setOnSeekBarChangeListener(this); | ||||||
|         frameskipSeekBar.setProgress(defaultFrameskip); |         frameskipSeekBar.setProgress(defaultFrameskip); | ||||||
|         ((TextView)(findViewById(R.id.frameSkipTextView))).setText(String.valueOf(defaultFrameskip)); |         ((TextView) (findViewById(R.id.frameSkipTextView))).setText(String.valueOf(defaultFrameskip)); | ||||||
| 
 | 
 | ||||||
|         this.updateStats(); |         this.updateStats(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static float round(float number, int digits) { |     /** | ||||||
|         float div = (float) Math.pow(10.0f, digits); |      * Updates the statistics view. | ||||||
|         return Math.round(number*div)/div; |      */ | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void updateStats() { |     public void updateStats() { | ||||||
|         final Track trackRef = this.track; |         final Track trackRef = this.track; | ||||||
|         final TextView lastAvgView = (TextView) findViewById(R.id.avgVeloLastView); |         final TextView lastAvgView = findViewById(R.id.avgVeloLastView); | ||||||
|         final TextView overallAvgView = (TextView) findViewById(R.id.avgVeloOverallView); |         final TextView overallAvgView = findViewById(R.id.avgVeloOverallView); | ||||||
|         final TextView delayedAvgView = (TextView) findViewById(R.id.delayedAvgTextView); |         final TextView delayedAvgView = findViewById(R.id.delayedAvgTextView); | ||||||
|         final TextView stepsView = (TextView) findViewById(R.id.stepsTextView); |         final TextView stepsView = findViewById(R.id.stepsTextView); | ||||||
|         runOnUiThread(new Runnable() { |         runOnUiThread(new Runnable() { | ||||||
|             @Override |             @Override | ||||||
|             public void run() { |             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) { |     public void onStepButtonClick(View view) { | ||||||
|         this.track.timeElapse(); |         this.track.timeElapse(); | ||||||
|         this.updateStats(); |         this.updateStats(); | ||||||
|         this.renderer.draw(); |         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) { |     public void onPlayButtonClick(View view) { | ||||||
|         Button playButton = (Button) findViewById(R.id.playButton); |         Button playButton = findViewById(R.id.playButton); | ||||||
|         playButton.setEnabled(false); |         playButton.setEnabled(false); | ||||||
|         Button stepButton = (Button) findViewById(R.id.stepButton); |         Button stepButton = findViewById(R.id.stepButton); | ||||||
|         stepButton.setEnabled(false); |         stepButton.setEnabled(false); | ||||||
|         Button stopButton = (Button) findViewById(R.id.stopButton); |         Button stopButton = findViewById(R.id.stopButton); | ||||||
|         stopButton.setEnabled(true); |         stopButton.setEnabled(true); | ||||||
|         Button clearButton = (Button) findViewById(R.id.clearButton); |         Button clearButton = findViewById(R.id.clearButton); | ||||||
|         clearButton.setEnabled(false); |         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 = new Worker(track, this, renderer, frameskip); | ||||||
|         this.worker.start(); |         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) { |     public void onStopButtonClick(View view) { | ||||||
|         Button playButton = (Button) findViewById(R.id.playButton); |         Button playButton = findViewById(R.id.playButton); | ||||||
|         playButton.setEnabled(true); |         playButton.setEnabled(true); | ||||||
|         Button stepButton = (Button) findViewById(R.id.stepButton); |         Button stepButton = findViewById(R.id.stepButton); | ||||||
|         stepButton.setEnabled(true); |         stepButton.setEnabled(true); | ||||||
|         Button stopButton = (Button) findViewById(R.id.stopButton); |         Button stopButton = findViewById(R.id.stopButton); | ||||||
|         stopButton.setEnabled(false); |         stopButton.setEnabled(false); | ||||||
|         Button clearButton = (Button) findViewById(R.id.clearButton); |         Button clearButton = findViewById(R.id.clearButton); | ||||||
|         clearButton.setEnabled(true); |         clearButton.setEnabled(true); | ||||||
| 
 | 
 | ||||||
|         this.worker.setStop(true); |         this.stopWorker(); | ||||||
|         try { |  | ||||||
|             this.worker.join(); |  | ||||||
|         } catch (InterruptedException ex) { |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
|         this.worker = null; |         this.worker = null; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Stops the current worker thread. | ||||||
|  |      */ | ||||||
|     protected void stopWorker() { |     protected void stopWorker() { | ||||||
|         this.worker.setStop(true); |         this.worker.setStop(true); | ||||||
|         try { |         try { | ||||||
| @ -142,15 +217,20 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar | |||||||
|         this.worker = null; |         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) { |     public void onClearButtonClick(View view) { | ||||||
|         if (this.worker != null) { // There was a simulation running |         if (this.worker != null) { // There was a simulation running | ||||||
|             this.stopWorker(); |             this.stopWorker(); | ||||||
|         } |         } | ||||||
|         Button playButton = (Button) findViewById(R.id.playButton); |         Button playButton = findViewById(R.id.playButton); | ||||||
|         playButton.setEnabled(true); |         playButton.setEnabled(true); | ||||||
|         Button stepButton = (Button) findViewById(R.id.stepButton); |         Button stepButton = findViewById(R.id.stepButton); | ||||||
|         stepButton.setEnabled(true); |         stepButton.setEnabled(true); | ||||||
|         Button stopButton = (Button) findViewById(R.id.stopButton); |         Button stopButton = findViewById(R.id.stopButton); | ||||||
|         stopButton.setEnabled(false); |         stopButton.setEnabled(false); | ||||||
|         this.updateTrack(); |         this.updateTrack(); | ||||||
|         this.updateStats(); |         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() { |     protected void updateTrack() { | ||||||
|         int newTrackLength = ((SeekBar)(findViewById(R.id.trackLengthSeekBar))).getProgress(); |         int newTrackLength = ((SeekBar) (findViewById(R.id.trackLengthSeekBar))).getProgress(); | ||||||
|         SeekBar noOfVehiclesSeekBar = (SeekBar)(findViewById(R.id.noOfVehiclesSeekBar)); |         SeekBar noOfVehiclesSeekBar = findViewById(R.id.noOfVehiclesSeekBar); | ||||||
|         int newNoOfVehicles = noOfVehiclesSeekBar.getProgress(); |         int newNoOfVehicles = noOfVehiclesSeekBar.getProgress(); | ||||||
|         if (newTrackLength < newNoOfVehicles) { // Dont allow values greater than track length! |         if (newTrackLength < newNoOfVehicles) { // Dont allow values greater than track length! | ||||||
|             newNoOfVehicles = (int) newTrackLength; |             newNoOfVehicles = newTrackLength; | ||||||
|             noOfVehiclesSeekBar.setProgress(newNoOfVehicles); |             noOfVehiclesSeekBar.setProgress(newNoOfVehicles); | ||||||
| 
 | 
 | ||||||
|         } |         } | ||||||
|         TextView noOfVehiclesTextView = (TextView)(findViewById(R.id.noOfVehiclesTextView)); |         TextView noOfVehiclesTextView = findViewById(R.id.noOfVehiclesTextView); | ||||||
|         noOfVehiclesTextView.setText(String.valueOf(newNoOfVehicles)); |         noOfVehiclesTextView.setText(String.valueOf(newNoOfVehicles)); | ||||||
| 
 | 
 | ||||||
|         TextView trackLengthTextView = (TextView)(findViewById(R.id.trackLengthTextView)); |         TextView trackLengthTextView = findViewById(R.id.trackLengthTextView); | ||||||
|         trackLengthTextView.setText(String.valueOf(newTrackLength)); |         trackLengthTextView.setText(String.valueOf(newTrackLength)); | ||||||
| 
 | 
 | ||||||
|         float newMaxVelocity = ((SeekBar) findViewById(R.id.maxVelocitySeekBar)).getProgress(); |         float newMaxVelocity = ((SeekBar) findViewById(R.id.maxVelocitySeekBar)).getProgress(); | ||||||
|         SeekBar brakeProbabilitySeekBar = (SeekBar) findViewById(R.id.brakeProbabilitySeekBar); |         SeekBar brakeProbabilitySeekBar = findViewById(R.id.brakeProbabilitySeekBar); | ||||||
|         float newBrakeProb = (float)brakeProbabilitySeekBar.getProgress() |         float newBrakeProb = (float) brakeProbabilitySeekBar.getProgress() | ||||||
|                 / (float)brakeProbabilitySeekBar.getMax(); |                 / (float)brakeProbabilitySeekBar.getMax(); | ||||||
| 
 | 
 | ||||||
|         int newDelay = ((SeekBar)(findViewById(R.id.simDelaySeekBar))).getProgress(); |         int newDelay = ((SeekBar)(findViewById(R.id.simDelaySeekBar))).getProgress(); | ||||||
| @ -186,7 +270,8 @@ public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBar | |||||||
|             this.worker.setStop(true); |             this.worker.setStop(true); | ||||||
|             try { |             try { | ||||||
|                 this.worker.join(); |                 this.worker.join(); | ||||||
|             } catch (InterruptedException ex) { } |             } catch (InterruptedException ex) { | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         this.track = new Track(newNoOfVehicles, newTrackLength, newBrakeProb, newMaxVelocity, |         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 |     @Override | ||||||
|     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { |     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { | ||||||
|         if (seekBar == (SeekBar)(findViewById(R.id.noOfVehiclesSeekBar))) { |         if (seekBar == findViewById(R.id.noOfVehiclesSeekBar)) { | ||||||
|             this.updateTrack(); |             this.updateTrack(); | ||||||
|         } else if (seekBar == (SeekBar)(findViewById(R.id.brakeProbabilitySeekBar))) { |         } else if (seekBar == findViewById(R.id.brakeProbabilitySeekBar)) { | ||||||
|             float newBrakeProb = (float)seekBar.getProgress() / (float)seekBar.getMax(); |             float newBrakeProb = (float) seekBar.getProgress() / (float) seekBar.getMax(); | ||||||
|             this.track.setBrakeProb(newBrakeProb); |             this.track.setBrakeProb(newBrakeProb); | ||||||
|             TextView newBrakeProbTextView = (TextView)(findViewById(R.id.brakeProbTextView)); |             TextView newBrakeProbTextView = findViewById(R.id.brakeProbTextView); | ||||||
|             newBrakeProbTextView.setText(String.valueOf((newBrakeProb))); |             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()); |             this.track.setMaxVelocity(seekBar.getProgress()); | ||||||
|             TextView tv = (TextView)(findViewById(R.id.maxVeloTextView)); |             TextView tv = findViewById(R.id.maxVeloTextView); | ||||||
|             tv.setText(String.valueOf(progress)); |             tv.setText(String.valueOf(progress)); | ||||||
|         } else if (seekBar == (SeekBar)(findViewById(R.id.trackLengthSeekBar))) { |         } else if (seekBar == findViewById(R.id.trackLengthSeekBar)) { | ||||||
|             this.updateTrack(); |             this.updateTrack(); | ||||||
|         } else if (seekBar == (SeekBar)(findViewById(R.id.simDelaySeekBar))) { |         } else if (seekBar == findViewById(R.id.simDelaySeekBar)) { | ||||||
|             TextView tv = (TextView)(findViewById(R.id.simDelayTextView)); |             TextView tv = findViewById(R.id.simDelayTextView); | ||||||
|             tv.setText(String.valueOf(seekBar.getProgress())); |             tv.setText(String.valueOf(seekBar.getProgress())); | ||||||
|             this.track.setWaitTime(seekBar.getProgress()); |             this.track.setWaitTime(seekBar.getProgress()); | ||||||
|         } else if (seekBar == (SeekBar)(findViewById(R.id.frameskipSeekBar))) { |         } else if (seekBar == findViewById(R.id.frameskipSeekBar)) { | ||||||
|             TextView tv = (TextView)(findViewById(R.id.frameSkipTextView)); |             TextView tv = findViewById(R.id.frameSkipTextView); | ||||||
|             tv.setText(String.valueOf(seekBar.getProgress())); |             tv.setText(String.valueOf(seekBar.getProgress())); | ||||||
|             if (this.worker != null) { |             if (this.worker != null) { | ||||||
|                 this.worker.setFrameskip(seekBar.getProgress()); |                 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 |     @Override | ||||||
|     public void onStartTrackingTouch(SeekBar seekBar) { |     public void onStartTrackingTouch(SeekBar seekBar) { | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Handler function for ending touch events on a seek bar. | ||||||
|  |      * | ||||||
|  |      * @param seekBar the seek bar touched | ||||||
|  |      */ | ||||||
|     @Override |     @Override | ||||||
|     public void onStopTrackingTouch(SeekBar seekBar) { |     public void onStopTrackingTouch(SeekBar seekBar) { | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -9,25 +9,73 @@ import android.view.SurfaceHolder; | |||||||
| import java.util.ConcurrentModificationException; | import java.util.ConcurrentModificationException; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * User interface class rendering the track history on a SurfaceView. | ||||||
|  |  */ | ||||||
| public class Renderer { | public class Renderer { | ||||||
|     private List<VehicleTimeRecord> stepRecords; |     /** | ||||||
|  |      * the track to render | ||||||
|  |      */ | ||||||
|     protected Track track; |     protected Track track; | ||||||
|  |     /** | ||||||
|  |      * width of a rectangle representing one vehicle | ||||||
|  |      */ | ||||||
|     protected int pixelPerVehicle; |     protected int pixelPerVehicle; | ||||||
|  |     /** | ||||||
|  |      * height of a rectangle representing one vehicle | ||||||
|  |      */ | ||||||
|     protected int pixelPerLine; |     protected int pixelPerLine; | ||||||
|  |     /** | ||||||
|  |      * amount of pixels per track position which are lost by rounding | ||||||
|  |      */ | ||||||
|     protected float tooShortPerTrackLength; |     protected float tooShortPerTrackLength; | ||||||
|  |     /** | ||||||
|  |      * amount of pixels per height which are lost by rounding | ||||||
|  |      */ | ||||||
|     protected float tooShortPerHeight; |     protected float tooShortPerHeight; | ||||||
|  |     /** | ||||||
|  |      * Paint instance of the renderer | ||||||
|  |      */ | ||||||
|     protected Paint paint; |     protected Paint paint; | ||||||
|  |     /** | ||||||
|  |      * holder of the surface the renderer draws to | ||||||
|  |      */ | ||||||
|     protected SurfaceHolder holder; |     protected SurfaceHolder holder; | ||||||
|     protected Canvas canvas; |     /** | ||||||
|  |      * width of the surface to draw to | ||||||
|  |      */ | ||||||
|     protected int width; |     protected int width; | ||||||
|  |     /** | ||||||
|  |      * height of the surface to draw to | ||||||
|  |      */ | ||||||
|     protected int height; |     protected int height; | ||||||
|  |     /** | ||||||
|  |      * temporary reference to the time records of one simulation step | ||||||
|  |      */ | ||||||
|  |     private List<VehicleTimeRecord> 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) { |     public Renderer(Track track, SurfaceHolder holder) { | ||||||
|         this.track = track; |         this.track = track; | ||||||
|         this.holder = holder; |         this.holder = holder; | ||||||
|         this.paint = new Paint(); |         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) { |     public void setSize(int width, int height) { | ||||||
|         if (width > 0 && height > 0) { |         if (width > 0 && height > 0) { | ||||||
|             this.pixelPerVehicle = width / (int) this.track.getTrackLength(); |             this.pixelPerVehicle = width / (int) this.track.getTrackLength(); | ||||||
| @ -36,34 +84,50 @@ public class Renderer { | |||||||
|                             / this.track.getTrackLength(); |                             / this.track.getTrackLength(); | ||||||
|             this.pixelPerLine = height / this.track.getHistoryLength(); |             this.pixelPerLine = height / this.track.getHistoryLength(); | ||||||
|             this.tooShortPerHeight = (height - this.pixelPerLine * this.track.getHistoryLength()) |             this.tooShortPerHeight = (height - this.pixelPerLine * this.track.getHistoryLength()) | ||||||
|                     / (float)height; |                     / (float) height; | ||||||
|             System.out.println("Viewport: "+width+"x"+height); |             System.out.println("Viewport: " + width + "x" + height); | ||||||
|             this.width = width; |             this.width = width; | ||||||
|             this.height = height; |             this.height = height; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Updates the track of the Surface. | ||||||
|  |      * | ||||||
|  |      * @param track the new track to render | ||||||
|  |      */ | ||||||
|     public void setTrack(Track track) { |     public void setTrack(Track track) { | ||||||
|         this.track = track; |         this.track = track; | ||||||
|         this.setSize(width, height); |         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) { |     protected int getColor(float curVelocity, float maxVelocity) { | ||||||
|         float perc = curVelocity / maxVelocity; |         float perc = curVelocity / maxVelocity; | ||||||
|         perc = 1 - perc; |         perc = 1 - perc; | ||||||
|         if (perc <= 0.5) { |         if (perc <= 0.5) { | ||||||
|             int red = ((int) (2*perc*0xFF)) << 16; |             int red = ((int) (2 * perc * 0xFF)) << 16; | ||||||
|             int green = 0xFF << 8; |             int green = 0xFF << 8; | ||||||
|             int blue = 0; |             int blue = 0; | ||||||
|             return 0xff000000 | red | green | blue; |             return 0xff000000 | red | green | blue; | ||||||
|         } else { |         } else { | ||||||
|             int red = 0xFF << 16; |             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; |             int blue = 0; | ||||||
|             return 0xff000000 | red | green | blue; |             return 0xff000000 | red | green | blue; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Draws the current state of the track history to the Surface. | ||||||
|  |      */ | ||||||
|     protected void draw() { |     protected void draw() { | ||||||
|         try { |         try { | ||||||
|             if (this.pixelPerVehicle == 0) { |             if (this.pixelPerVehicle == 0) { | ||||||
| @ -79,7 +143,7 @@ public class Renderer { | |||||||
|                 int vCompensateStart = 0; |                 int vCompensateStart = 0; | ||||||
|                 int vCompensateEnd = 0; |                 int vCompensateEnd = 0; | ||||||
|                 canvas.drawColor(Color.BLACK); |                 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--) { |                      curStepIdx--) { | ||||||
|                     try { |                     try { | ||||||
|                         try { |                         try { | ||||||
|  | |||||||
| @ -1,24 +1,26 @@ | |||||||
| package de.hems.trafficsim; | package de.hems.trafficsim; | ||||||
| 
 | 
 | ||||||
| import android.app.ActionBar; |  | ||||||
| import android.content.Context; | 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.SurfaceView; | ||||||
| import android.view.View; |  | ||||||
| import android.view.ViewGroup; | 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 class TimeRecordView extends SurfaceView { | ||||||
|     public TimeRecordView(Context context, Track track) { |     public TimeRecordView(Context context, Track track) { | ||||||
|         super(context); |         super(context); | ||||||
|         this.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); |         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 |     @Override | ||||||
|     protected void onSizeChanged(int w, int h, int oldw, int oldh) { |     protected void onSizeChanged(int w, int h, int oldw, int oldh) { | ||||||
|         super.onSizeChanged(w, h, oldw, oldh); |         super.onSizeChanged(w, h, oldw, oldh); | ||||||
|  | |||||||
| @ -5,42 +5,92 @@ import java.util.LinkedList; | |||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Observable; | import java.util.Observable; | ||||||
| import java.util.concurrent.Semaphore; | 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 { | public class Track extends Observable { | ||||||
|  |     /** | ||||||
|  |      * list a vehicles on the track | ||||||
|  |      */ | ||||||
|     protected List<Vehicle> vehicles; |     protected List<Vehicle> vehicles; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * list of resulting time records of the simulation | ||||||
|  |      */ | ||||||
|     protected List<List<VehicleTimeRecord>> vtrList; |     protected List<List<VehicleTimeRecord>> vtrList; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * length of the track | ||||||
|  |      */ | ||||||
|     protected float trackLength; |     protected float trackLength; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * sum of all vehicle speeds during the simulation, used for average calculation | ||||||
|  |      */ | ||||||
|     protected float sumAvgMemory; |     protected float sumAvgMemory; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * sum of all vehicle speeds during the simulation ignoring the first ten steps, | ||||||
|  |      * used for average calculation | ||||||
|  |      */ | ||||||
|     protected float sumDelAvgMemory; |     protected float sumDelAvgMemory; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * length of the history kept | ||||||
|  |      */ | ||||||
|     protected int historyLength; |     protected int historyLength; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * average over all velocities in the simulation | ||||||
|  |      */ | ||||||
|     protected float overallAvg; |     protected float overallAvg; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * average over all velocities in the simulation, ignoring the first ten steps | ||||||
|  |      */ | ||||||
|     protected float delayedAvg; |     protected float delayedAvg; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * average over all velocities in the last step | ||||||
|  |      */ | ||||||
|     protected float lastAvg; |     protected float lastAvg; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * current configured wait time between two simulation steps | ||||||
|  |      */ | ||||||
|     protected int waitTime; |     protected int waitTime; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * currently configured max velocity for all vehicles | ||||||
|  |      */ | ||||||
|     protected float maxVelocity; |     protected float maxVelocity; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * currently configured brake probability for all vehicles | ||||||
|  |      */ | ||||||
|     protected float brakeProb; |     protected float brakeProb; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * counter for executed simulation steps | ||||||
|  |      */ | ||||||
|     protected long steps; |     protected long steps; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * semaphore protecting the vtrlist | ||||||
|  |      */ | ||||||
|     protected Semaphore listSemaphore; |     protected Semaphore listSemaphore; | ||||||
| 
 | 
 | ||||||
|     public List<List<VehicleTimeRecord>> getVtrList() { return vtrList; } |     /** | ||||||
|     public float getOverallAvg() { |      * Constructor for a new Track. | ||||||
|         return overallAvg; |      * | ||||||
|     } |      * @param numberVehicles number of vehicles on the Track | ||||||
|     public float getLastAvg() { |      * @param trackLength    length of the new Track | ||||||
|         return lastAvg; |      * @param brakeProb      probability of a vehicle to suddenly brake without reason | ||||||
|     } |      * @param maxVelocity    maxmimum velocity of the vehicles | ||||||
|     public float getDelayedAvg() { return delayedAvg; } |      * @param waitTime       time between two simulation steps to slow down the simulation artificially | ||||||
|     public List<Vehicle> getVehicles() { |      * @param historyLength  length of the history to keep | ||||||
|         return vehicles; |      */ | ||||||
|     } |  | ||||||
|     public float getTrackLength() { |  | ||||||
|         return trackLength; |  | ||||||
|     } |  | ||||||
|     public long getSteps() { return steps; } |  | ||||||
|     public Semaphore getListSemaphore() { return listSemaphore; } |  | ||||||
|     public int getHistoryLength() { return historyLength; } |  | ||||||
| 
 |  | ||||||
|     public Track(int numberVehicles, float trackLength, float brakeProb, float maxVelocity, int waitTime, int historyLength) { |     public Track(int numberVehicles, float trackLength, float brakeProb, float maxVelocity, int waitTime, int historyLength) { | ||||||
|         this.trackLength = trackLength; |         this.trackLength = trackLength; | ||||||
|         this.brakeProb = brakeProb; |         this.brakeProb = brakeProb; | ||||||
| @ -59,9 +109,96 @@ public class Track extends Observable { | |||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     protected List<Vehicle> createVehiclesList(int numberVehicles){ |     /** | ||||||
|  |      * Getter for vtrList | ||||||
|  |      * | ||||||
|  |      * @return vtrList | ||||||
|  |      */ | ||||||
|  |     public List<List<VehicleTimeRecord>> 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<Vehicle> 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<Vehicle> createVehiclesList(int numberVehicles) { | ||||||
|         List<Vehicle> result = new ArrayList<>(); |         List<Vehicle> result = new ArrayList<>(); | ||||||
|         for(int i=0;i<numberVehicles;i++){ |         for (int i = 0; i < numberVehicles; i++) { | ||||||
|             Vehicle vehicle = new Vehicle(i, i, this.maxVelocity, this.brakeProb, this.trackLength); |             Vehicle vehicle = new Vehicle(i, i, this.maxVelocity, this.brakeProb, this.trackLength); | ||||||
|             result.add(vehicle); |             result.add(vehicle); | ||||||
|         } |         } | ||||||
| @ -69,24 +206,42 @@ public class Track extends Observable { | |||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Update the wait time of the simulation. | ||||||
|  |      * | ||||||
|  |      * @param waitTime new wait time in ms | ||||||
|  |      */ | ||||||
|     public void setWaitTime(int waitTime) { |     public void setWaitTime(int waitTime) { | ||||||
|         this.waitTime = waitTime; |         this.waitTime = waitTime; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Update the brake probability of all vehicles. | ||||||
|  |      * | ||||||
|  |      * @param brakeProb new brake probability | ||||||
|  |      */ | ||||||
|     public void setBrakeProb(float brakeProb) { |     public void setBrakeProb(float brakeProb) { | ||||||
|         for (Vehicle v : this.vehicles) { |         for (Vehicle v : this.vehicles) { | ||||||
|             v.setBrakeProb(brakeProb); |             v.setBrakeProb(brakeProb); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Update the maximum velocity of all vehicles. | ||||||
|  |      * | ||||||
|  |      * @param maxVelocity new maximum velocity | ||||||
|  |      */ | ||||||
|     public void setMaxVelocity(float maxVelocity) { |     public void setMaxVelocity(float maxVelocity) { | ||||||
|         for (Vehicle v : this.vehicles) { |         for (Vehicle v : this.vehicles) { | ||||||
|             v.setMaxVelocity(maxVelocity); |             v.setMaxVelocity(maxVelocity); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Calculates on simulation step ahead and then waits for the configured wait time. | ||||||
|  |      */ | ||||||
|     public void timeElapse() { |     public void timeElapse() { | ||||||
|         for(int i=0; i<vehicles.size();i++) { |         for (int i = 0; i < vehicles.size(); i++) { | ||||||
|             Vehicle v = vehicles.get(i); |             Vehicle v = vehicles.get(i); | ||||||
|             int forerunnerIndex = i + 1; |             int forerunnerIndex = i + 1; | ||||||
|             if (forerunnerIndex >= vehicles.size()) { |             if (forerunnerIndex >= vehicles.size()) { | ||||||
| @ -94,7 +249,7 @@ public class Track extends Observable { | |||||||
|             } |             } | ||||||
|             Vehicle forerunner = vehicles.get(forerunnerIndex); |             Vehicle forerunner = vehicles.get(forerunnerIndex); | ||||||
|             float distanceForerunner = forerunner.getPosition() - v.getPosition() - 1; |             float distanceForerunner = forerunner.getPosition() - v.getPosition() - 1; | ||||||
|             if(distanceForerunner < 0.0){ |             if (distanceForerunner < 0.0) { | ||||||
|                 distanceForerunner += this.trackLength; |                 distanceForerunner += this.trackLength; | ||||||
|             } |             } | ||||||
|             v.updateVelocity(distanceForerunner); |             v.updateVelocity(distanceForerunner); | ||||||
| @ -117,25 +272,32 @@ public class Track extends Observable { | |||||||
|         this.listSemaphore.release(); |         this.listSemaphore.release(); | ||||||
| 
 | 
 | ||||||
|         update_avg(); |         update_avg(); | ||||||
|         this.setChanged(); |         try { | ||||||
|         //this.notifyObservers(); |  | ||||||
|         this.clearChanged(); |  | ||||||
|         //LockSupport.parkNanos(1); |  | ||||||
|         try  { |  | ||||||
|             Thread.sleep(waitTime); |             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; |         float sum_step = 0; | ||||||
|         for (VehicleTimeRecord r : vtrList.get(step)) { |         for (VehicleTimeRecord r : vtrList.get(step)) { | ||||||
|             sum_step +=  r.velocity; |             sum_step += r.velocity; | ||||||
|         } |         } | ||||||
|         return sum_step / vehicles.size(); |         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) { |         if (this.steps > 10) { | ||||||
|             sumDelAvgMemory += lastAvg; |             sumDelAvgMemory += lastAvg; | ||||||
|             delayedAvg = sumDelAvgMemory / (this.steps - 10); |             delayedAvg = sumDelAvgMemory / (this.steps - 10); | ||||||
| @ -144,13 +306,4 @@ public class Track extends Observable { | |||||||
|         overallAvg = sumAvgMemory / this.steps; |         overallAvg = sumAvgMemory / this.steps; | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     public float avg_span(int start, int end){ |  | ||||||
|         float sum_span = 0; |  | ||||||
|         for (int i=start; i <end;i++){ |  | ||||||
|             sum_span += avg_step(i); |  | ||||||
|         } |  | ||||||
|         return sum_span / (end-start+1); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,15 +2,49 @@ package de.hems.trafficsim; | |||||||
| 
 | 
 | ||||||
| import java.util.Random; | import java.util.Random; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Model class which represents a vehicle in the simulation. | ||||||
|  |  */ | ||||||
| public class Vehicle { | public class Vehicle { | ||||||
|  |     /** | ||||||
|  |      * a number to index the vehicle | ||||||
|  |      */ | ||||||
|     protected int id; |     protected int id; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * current position of the vehicle on the track | ||||||
|  |      */ | ||||||
|     protected float position; |     protected float position; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * current velocity of the vehicle | ||||||
|  |      */ | ||||||
|     protected float curVelocity; |     protected float curVelocity; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * maximum velocity of the vehicle | ||||||
|  |      */ | ||||||
|     protected float maxVelocity; |     protected float maxVelocity; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * probability of the vehicle to brake without reason | ||||||
|  |      */ | ||||||
|     protected float brakeProb; |     protected float brakeProb; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * length of the track the vehicle is placed on | ||||||
|  |      */ | ||||||
|     protected float trackLength; |     protected float trackLength; | ||||||
| 
 | 
 | ||||||
| 
 |     /** | ||||||
|  |      * Constructs a new vehicle. | ||||||
|  |      * | ||||||
|  |      * @param id          a number to index the vehicle | ||||||
|  |      * @param position    current position of the vehicle on the track | ||||||
|  |      * @param maxVelocity maximum velocity of the vehicle | ||||||
|  |      * @param brakeProb   probability of the vehicle to brake without reason | ||||||
|  |      * @param trackLength length of the track the vehicle is placed on | ||||||
|  |      */ | ||||||
|     public Vehicle(int id, int position, float maxVelocity, float brakeProb, float trackLength) { |     public Vehicle(int id, int position, float maxVelocity, float brakeProb, float trackLength) { | ||||||
|         this.id = id; |         this.id = id; | ||||||
|         this.position = position; |         this.position = position; | ||||||
| @ -21,22 +55,61 @@ public class Vehicle { | |||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Getter for position | ||||||
|  |      * | ||||||
|  |      * @return position | ||||||
|  |      */ | ||||||
|     public float getPosition() { |     public float getPosition() { | ||||||
|         return position; |         return position; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Getter for curVelocity | ||||||
|  |      * | ||||||
|  |      * @return curVelocity | ||||||
|  |      */ | ||||||
|     public float getCurVelocity() { |     public float getCurVelocity() { | ||||||
|         return curVelocity; |         return curVelocity; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Getter for maxVelocity | ||||||
|  |      * | ||||||
|  |      * @return maxVelocity | ||||||
|  |      */ | ||||||
|     public float getMaxVelocity() { |     public float getMaxVelocity() { | ||||||
|         return maxVelocity; |         return maxVelocity; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void setBrakeProb(float brakeProb) { this.brakeProb = brakeProb; } |     /** | ||||||
|  |      * Setter for maxVelocity | ||||||
|  |      * | ||||||
|  |      * @return maxVelocity | ||||||
|  |      */ | ||||||
|  |     public void setMaxVelocity(float maxVelocity) { | ||||||
|  |         this.maxVelocity = maxVelocity; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     public void setMaxVelocity(float maxVelocity) { this.maxVelocity = maxVelocity; } |     /** | ||||||
|  |      * Setter for brakeProb | ||||||
|  |      * | ||||||
|  |      * @return brakeProb | ||||||
|  |      */ | ||||||
|  |     public void setBrakeProb(float brakeProb) { | ||||||
|  |         this.brakeProb = brakeProb; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Calculates the new velocity of the vehicle based on the following rules: | ||||||
|  |      * <ol> | ||||||
|  |      *     <li>Increase by one if the vehicle is slower than it's maximum speed</li> | ||||||
|  |      *     <li>Random brake by one</li> | ||||||
|  |      *     <li>Break if the distance to the forerunner is less than it's speed</li> | ||||||
|  |      * </ol> | ||||||
|  |      * | ||||||
|  |      * @param distanceForerunner distance to the forerunner of the vehicle | ||||||
|  |      */ | ||||||
|     public void updateVelocity(float distanceForerunner) { |     public void updateVelocity(float distanceForerunner) { | ||||||
|         Random random = new Random(); |         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() { |     public void timeElapse() { | ||||||
|         position = (position + curVelocity) % this.trackLength; |         position = (position + curVelocity) % this.trackLength; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -1,9 +1,27 @@ | |||||||
| package de.hems.trafficsim; | package de.hems.trafficsim; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Model class which keeps the previous simulation data for analysis. | ||||||
|  |  */ | ||||||
| public class VehicleTimeRecord { | public class VehicleTimeRecord { | ||||||
|  |     /** | ||||||
|  |      * the id of the vehicle it belongs to | ||||||
|  |      */ | ||||||
|     protected int id; |     protected int id; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * the position of the vehicle after the last simulation step | ||||||
|  |      */ | ||||||
|     protected float position; |     protected float position; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * the velocity of the vehicle during the last simulation step | ||||||
|  |      */ | ||||||
|     protected float velocity; |     protected float velocity; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * the maximum velocity of the vehicle | ||||||
|  |      */ | ||||||
|     protected float maxVelocity; |     protected float maxVelocity; | ||||||
| 
 | 
 | ||||||
|     public float getMaxVelocity() { |     public float getMaxVelocity() { | ||||||
| @ -18,6 +36,14 @@ public class VehicleTimeRecord { | |||||||
|         return velocity; |         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) { |     public VehicleTimeRecord(int id, float position, float velocity, float maxVelocity) { | ||||||
|         this.id = id; |         this.id = id; | ||||||
|         this.position = position; |         this.position = position; | ||||||
|  | |||||||
| @ -1,17 +1,46 @@ | |||||||
| package de.hems.trafficsim; | package de.hems.trafficsim; | ||||||
| 
 | 
 | ||||||
| import android.graphics.Canvas; | 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 { | public class Worker extends Thread { | ||||||
|  |     /** | ||||||
|  |      * the track to simulate | ||||||
|  |      */ | ||||||
|     protected Track track; |     protected Track track; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Stop flag, indicating that the worker shall stop | ||||||
|  |      */ | ||||||
|     protected boolean stop; |     protected boolean stop; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * the MainActivity of the gui | ||||||
|  |      */ | ||||||
|     protected MainActivity gui; |     protected MainActivity gui; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * the Renderer drawing the Track | ||||||
|  |      */ | ||||||
|     protected Renderer renderer; |     protected Renderer renderer; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Amount of simulation steps between two frames in the view. Zero means | ||||||
|  |      * that every simulation step is drawn. | ||||||
|  |      */ | ||||||
|     protected int frameskip; |     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) { |     public Worker(Track track, MainActivity gui, Renderer renderer, int frameskip) { | ||||||
|         super(); |         super(); | ||||||
|         this.track = track; |         this.track = track; | ||||||
| @ -21,16 +50,28 @@ public class Worker extends Thread { | |||||||
|         this.frameskip = frameskip; |         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) { |     public void setStop(boolean stop) { | ||||||
|         this.stop = stop; |         this.stop = stop; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Updates the amount of simulation steps between to view frames. | ||||||
|  |      * | ||||||
|  |      * @param frames amount of steps | ||||||
|  |      */ | ||||||
|     public void setFrameskip(int frames) { |     public void setFrameskip(int frames) { | ||||||
|         this.frameskip = 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 |     @Override | ||||||
|     public void run() { |     public void run() { | ||||||
|         Canvas canvas = null; |         Canvas canvas = null; | ||||||
| @ -40,7 +81,7 @@ public class Worker extends Thread { | |||||||
|             this.gui.updateStats(); |             this.gui.updateStats(); | ||||||
|             if (i >= this.frameskip) { |             if (i >= this.frameskip) { | ||||||
|                 this.renderer.draw(); |                 this.renderer.draw(); | ||||||
|                 i=0; |                 i = 0; | ||||||
|             } |             } | ||||||
|             i++; |             i++; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -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 <a href="http://d.android.com/tools/testing">Testing documentation</a> |  | ||||||
|  */ |  | ||||||
| public class ExampleUnitTest { |  | ||||||
|     @Test |  | ||||||
|     public void addition_isCorrect() { |  | ||||||
|         assertEquals(4, 2 + 2); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user