|
- package de.hems.trafficsim;
-
- import android.os.Bundle;
- import android.view.View;
- import android.widget.Button;
- import android.widget.LinearLayout;
- import android.widget.SeekBar;
- import android.widget.TextView;
-
- 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 = findViewById(R.id.trackViewStack);
- this.trackView = new TimeRecordView(this);
-
- viewStack.addView(this.trackView);
- this.renderer = new Renderer(track, this.trackView.getHolder());
-
- SeekBar trackLengthSeekBar = findViewById(R.id.trackLengthSeekBar);
- trackLengthSeekBar.setOnSeekBarChangeListener(this);
- trackLengthSeekBar.setProgress(defaultTrackLength);
- ((TextView)(findViewById(R.id.trackLengthTextView))).setText(String.valueOf(defaultTrackLength));
-
- 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 = findViewById(R.id.noOfVehiclesSeekBar);
- noOfVehiclesSeekBar.setOnSeekBarChangeListener(this);
- noOfVehiclesSeekBar.setProgress(defaultNoOfVehicles);
- ((TextView)(findViewById(R.id.noOfVehiclesTextView))).setText(String.valueOf(defaultNoOfVehicles));
-
- 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 = findViewById(R.id.simDelaySeekBar);
- delaySeekBar.setOnSeekBarChangeListener(this);
- delaySeekBar.setProgress(defaultDelay);
- ((TextView) (findViewById(R.id.simDelayTextView))).setText(String.valueOf(defaultDelay));
-
- SeekBar frameskipSeekBar = findViewById(R.id.frameskipSeekBar);
- frameskipSeekBar.setOnSeekBarChangeListener(this);
- frameskipSeekBar.setProgress(defaultFrameskip);
- ((TextView) (findViewById(R.id.frameSkipTextView))).setText(String.valueOf(defaultFrameskip));
-
- this.updateStats();
- }
-
- /**
- * Updates the statistics view.
- */
- public void updateStats() {
- final Track trackRef = this.track;
- 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() {
- lastAvgView.setText(String.valueOf(round(trackRef.getLastAvg(), 2)));
- overallAvgView.setText(String.valueOf(round(trackRef.getOverallAvg(), 2)));
- stepsView.setText(String.valueOf(trackRef.getSteps()));
- delayedAvgView.setText(String.valueOf(round(trackRef.getDelayedAvg(), 2)));
- }
- });
- }
-
- /**
- * 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 = findViewById(R.id.playButton);
- playButton.setEnabled(false);
- Button stepButton = findViewById(R.id.stepButton);
- stepButton.setEnabled(false);
- Button stopButton = findViewById(R.id.stopButton);
- stopButton.setEnabled(true);
- Button clearButton = findViewById(R.id.clearButton);
- clearButton.setEnabled(false);
-
- 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 = findViewById(R.id.playButton);
- playButton.setEnabled(true);
- Button stepButton = findViewById(R.id.stepButton);
- stepButton.setEnabled(true);
- Button stopButton = findViewById(R.id.stopButton);
- stopButton.setEnabled(false);
- Button clearButton = findViewById(R.id.clearButton);
- clearButton.setEnabled(true);
-
- this.stopWorker();
- this.worker = null;
- }
-
- /**
- * Stops the current worker thread.
- */
- protected void stopWorker() {
- this.worker.setStop(true);
- try {
- this.worker.join();
- } catch (InterruptedException ignored) {
- }
- 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 = findViewById(R.id.playButton);
- playButton.setEnabled(true);
- Button stepButton = findViewById(R.id.stepButton);
- stepButton.setEnabled(true);
- Button stopButton = findViewById(R.id.stopButton);
- stopButton.setEnabled(false);
- this.updateTrack();
- this.updateStats();
- this.renderer.draw();
-
- }
-
- /**
- * 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 = findViewById(R.id.noOfVehiclesSeekBar);
- int newNoOfVehicles = noOfVehiclesSeekBar.getProgress();
- if (newTrackLength < newNoOfVehicles) { // Dont allow values greater than track length!
- newNoOfVehicles = newTrackLength;
- noOfVehiclesSeekBar.setProgress(newNoOfVehicles);
-
- }
- TextView noOfVehiclesTextView = findViewById(R.id.noOfVehiclesTextView);
- noOfVehiclesTextView.setText(String.valueOf(newNoOfVehicles));
-
- TextView trackLengthTextView = findViewById(R.id.trackLengthTextView);
- trackLengthTextView.setText(String.valueOf(newTrackLength));
-
- float newMaxVelocity = ((SeekBar) findViewById(R.id.maxVelocitySeekBar)).getProgress();
- SeekBar brakeProbabilitySeekBar = findViewById(R.id.brakeProbabilitySeekBar);
- float newBrakeProb = (float) brakeProbabilitySeekBar.getProgress()
- / (float)brakeProbabilitySeekBar.getMax();
-
- int newDelay = ((SeekBar)(findViewById(R.id.simDelaySeekBar))).getProgress();
- int newFrameskip = ((SeekBar)(findViewById(R.id.frameskipSeekBar))).getProgress();
-
- boolean wasRunning = this.worker != null;
- if (wasRunning) {
- this.worker.setStop(true);
- try {
- this.worker.join();
- } catch (InterruptedException ignored) {
- }
- }
-
- this.track = new Track(newNoOfVehicles, newTrackLength, newBrakeProb, newMaxVelocity,
- newDelay, defaultHistoryLength);
- this.renderer.setTrack(this.track);
-
- if (wasRunning) {
- this.worker = new Worker(track, this, renderer, newFrameskip);
- this.worker.start();
- }
- }
-
- /**
- * 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 == findViewById(R.id.noOfVehiclesSeekBar)) {
- this.updateTrack();
- } else if (seekBar == findViewById(R.id.brakeProbabilitySeekBar)) {
- float newBrakeProb = (float) seekBar.getProgress() / (float) seekBar.getMax();
- this.track.setBrakeProb(newBrakeProb);
- TextView newBrakeProbTextView = findViewById(R.id.brakeProbTextView);
- newBrakeProbTextView.setText(String.valueOf((newBrakeProb)));
- } else if (seekBar == findViewById(R.id.maxVelocitySeekBar)) {
- this.track.setMaxVelocity(seekBar.getProgress());
- TextView tv = findViewById(R.id.maxVeloTextView);
- tv.setText(String.valueOf(progress));
- } else if (seekBar == findViewById(R.id.trackLengthSeekBar)) {
- this.updateTrack();
- } 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 == 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());
- }
- }
- }
-
- /**
- * 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) {
-
- }
- }
|