Optimize view update Add semaphore to TimeRecordList Add waiting timer to model updatetags/Release_1
@@ -18,6 +18,7 @@ public class MainActivity extends AppCompatActivity implements Observer, SeekBar | |||||
public static final float defaultBrakeProb = 0.3f; | public static final float defaultBrakeProb = 0.3f; | ||||
public static final float defaultMaxVelocity = 5.0f; | public static final float defaultMaxVelocity = 5.0f; | ||||
public static final int defaultDelay = 0; | public static final int defaultDelay = 0; | ||||
public static final int defaultHistoryLength = 50; | |||||
protected Track track; | protected Track track; | ||||
protected TimeRecordView trackView; | protected TimeRecordView trackView; | ||||
protected Worker worker; | protected Worker worker; | ||||
@@ -28,9 +29,11 @@ public class MainActivity extends AppCompatActivity implements Observer, SeekBar | |||||
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); | |||||
defaultMaxVelocity, defaultDelay, defaultHistoryLength); | |||||
this.track.addObserver(this); | this.track.addObserver(this); | ||||
this.viewStack = (LinearLayout) findViewById(R.id.trackViewStack); | this.viewStack = (LinearLayout) findViewById(R.id.trackViewStack); | ||||
this.trackView = new TimeRecordView(this, track, defaultHistoryLength); | |||||
viewStack.addView(this.trackView); | |||||
SeekBar trackLengthSeekBar = (SeekBar) findViewById(R.id.trackLengthSeekBar); | SeekBar trackLengthSeekBar = (SeekBar) findViewById(R.id.trackLengthSeekBar); | ||||
trackLengthSeekBar.setOnSeekBarChangeListener(this); | trackLengthSeekBar.setOnSeekBarChangeListener(this); | ||||
@@ -73,18 +76,22 @@ public class MainActivity extends AppCompatActivity implements Observer, SeekBar | |||||
final TextView overallAvgView = (TextView) findViewById(R.id.avgVeloOverallView); | final TextView overallAvgView = (TextView) findViewById(R.id.avgVeloOverallView); | ||||
final TextView delayedAvgView = (TextView) findViewById(R.id.delayedAvgTextView); | final TextView delayedAvgView = (TextView) findViewById(R.id.delayedAvgTextView); | ||||
final TextView stepsView = (TextView) findViewById(R.id.stepsTextView); | final TextView stepsView = (TextView) findViewById(R.id.stepsTextView); | ||||
final TimeRecordView view = this.trackView; | |||||
runOnUiThread(new Runnable() { | runOnUiThread(new Runnable() { | ||||
@Override | @Override | ||||
public void run() { | public void run() { | ||||
TimeRecordView newTrView = new TimeRecordView(mainActivity, trackRef); | |||||
if (viewStackRef.getChildCount() > 0) | |||||
viewStackRef.removeViewAt(0); | |||||
viewStackRef.addView(newTrView); | |||||
//TimeRecordView newTrView = new TimeRecordView(mainActivity, trackRef); | |||||
trackView.invalidate(); | |||||
//if (viewStackRef.getChildCount() > 0) | |||||
// viewStackRef.removeViewAt(0); | |||||
//viewStackRef.addView(newTrView); | |||||
lastAvgView.setText(String.valueOf(round(trackRef.getLastAvg(), 2))); | lastAvgView.setText(String.valueOf(round(trackRef.getLastAvg(), 2))); | ||||
overallAvgView.setText(String.valueOf(round(trackRef.getOverallAvg(), 2))); | overallAvgView.setText(String.valueOf(round(trackRef.getOverallAvg(), 2))); | ||||
stepsView.setText(String.valueOf(trackRef.getVtrList().size())); | |||||
stepsView.setText(String.valueOf(trackRef.getSteps())); | |||||
delayedAvgView.setText(String.valueOf(round(trackRef.getDelayedAvg(), 2))); | delayedAvgView.setText(String.valueOf(round(trackRef.getDelayedAvg(), 2))); | ||||
} | } | ||||
}); | }); | ||||
} | } | ||||
@@ -172,7 +179,8 @@ public class MainActivity extends AppCompatActivity implements Observer, SeekBar | |||||
int newDelay = ((SeekBar)(findViewById(R.id.simDelaySeekBar))).getProgress(); | int newDelay = ((SeekBar)(findViewById(R.id.simDelaySeekBar))).getProgress(); | ||||
this.track = new Track(newNoOfVehicles, newTrackLength, newBrakeProb, newMaxVelocity, newDelay); | |||||
this.track = new Track(newNoOfVehicles, newTrackLength, newBrakeProb, newMaxVelocity, newDelay, defaultHistoryLength); | |||||
this.trackView.setTrack(this.track); | |||||
this.track.addObserver(this); | this.track.addObserver(this); | ||||
if (this.worker != null) { // There was a simulation running already | if (this.worker != null) { // There was a simulation running already | ||||
this.stopWorker(); | this.stopWorker(); | ||||
@@ -14,11 +14,13 @@ public class TimeRecordView extends View { | |||||
protected Track track; | protected Track track; | ||||
protected int pixelPerVehicle; | protected int pixelPerVehicle; | ||||
protected float tooShortPerTrackLength; | protected float tooShortPerTrackLength; | ||||
protected int historyLength; | |||||
public TimeRecordView(Context context, Track track) { | |||||
public TimeRecordView(Context context, Track track, int historyLength) { | |||||
super(context); | super(context); | ||||
this.track = track; | this.track = track; | ||||
this.paint = new Paint(); | this.paint = new Paint(); | ||||
this.historyLength = historyLength; | |||||
paint.setColor(Color.BLACK); | paint.setColor(Color.BLACK); | ||||
paint.setStyle(Paint.Style.FILL_AND_STROKE); | paint.setStyle(Paint.Style.FILL_AND_STROKE); | ||||
this.setBackgroundColor(Color.BLACK); | this.setBackgroundColor(Color.BLACK); | ||||
@@ -26,6 +28,10 @@ public class TimeRecordView extends View { | |||||
this.tooShortPerTrackLength = (this.getWidth() - this.pixelPerVehicle*this.track.getTrackLength())/this.track.getTrackLength(); | this.tooShortPerTrackLength = (this.getWidth() - this.pixelPerVehicle*this.track.getTrackLength())/this.track.getTrackLength(); | ||||
} | } | ||||
public void setTrack(Track track) { | |||||
this.track = track; | |||||
} | |||||
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; | ||||
@@ -60,18 +66,25 @@ public class TimeRecordView extends View { | |||||
protected void onDraw(Canvas canvas) { | protected void onDraw(Canvas canvas) { | ||||
int y = 0; | int y = 0; | ||||
List<List<VehicleTimeRecord>> stepList = this.track.getVtrList(); | List<List<VehicleTimeRecord>> stepList = this.track.getVtrList(); | ||||
for (int curStepIdx = stepList.size()-1; curStepIdx >= stepList.size()-1-50 && curStepIdx >= 0; curStepIdx--) { | |||||
for (int curStepIdx = this.historyLength-1; | |||||
curStepIdx >= 0 && stepList.size() >= curStepIdx; | |||||
curStepIdx--) { | |||||
try { | try { | ||||
try { | |||||
track.getListSemaphore().acquire(); | |||||
} catch (InterruptedException ex) { return; } | |||||
List<VehicleTimeRecord> step = stepList.get(curStepIdx); | List<VehicleTimeRecord> step = stepList.get(curStepIdx); | ||||
int i = 0; | int i = 0; | ||||
for (VehicleTimeRecord r : step) { | for (VehicleTimeRecord r : step) { | ||||
int left = (int) (this.pixelPerVehicle * r.getPosition()); | int left = (int) (this.pixelPerVehicle * r.getPosition()); | ||||
int compensate = Math.round(r.getPosition()*this.tooShortPerTrackLength); | int compensate = Math.round(r.getPosition()*this.tooShortPerTrackLength); | ||||
this.paint.setColor(getColor(r.getVelocity(), r.getMaxVelocity())); | this.paint.setColor(getColor(r.getVelocity(), r.getMaxVelocity())); | ||||
canvas.drawRect(left+compensate, y, left + this.pixelPerVehicle - 1+compensate, | |||||
canvas.drawRect(left+compensate, y, | |||||
left + this.pixelPerVehicle - 1+compensate, | |||||
y + 10, this.paint); | y + 10, this.paint); | ||||
i++; | i++; | ||||
} | } | ||||
track.getListSemaphore().release(); | |||||
y += 10; | y += 10; | ||||
} catch (ConcurrentModificationException ex) { | } catch (ConcurrentModificationException ex) { | ||||
System.out.println("Concurrent Exception occured, skipping record"); | System.out.println("Concurrent Exception occured, skipping record"); | ||||
@@ -4,6 +4,8 @@ import java.util.ArrayList; | |||||
import java.util.LinkedList; | 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.locks.LockSupport; | |||||
public class Track extends Observable { | public class Track extends Observable { | ||||
protected List<Vehicle> vehicles; | protected List<Vehicle> vehicles; | ||||
@@ -18,6 +20,8 @@ public class Track extends Observable { | |||||
protected int waitTime; | protected int waitTime; | ||||
protected float maxVelocity; | protected float maxVelocity; | ||||
protected float brakeProb; | protected float brakeProb; | ||||
protected long steps; | |||||
protected Semaphore listSemaphore; | |||||
public List<List<VehicleTimeRecord>> getVtrList() { return vtrList; } | public List<List<VehicleTimeRecord>> getVtrList() { return vtrList; } | ||||
public float getOverallAvg() { | public float getOverallAvg() { | ||||
@@ -33,8 +37,10 @@ public class Track extends Observable { | |||||
public float getTrackLength() { | public float getTrackLength() { | ||||
return trackLength; | return trackLength; | ||||
} | } | ||||
public long getSteps() { return steps; } | |||||
public Semaphore getListSemaphore() { return listSemaphore; } | |||||
public Track(int numberVehicles, float trackLength, float brakeProb, float maxVelocity, int waitTime) { | |||||
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; | ||||
this.maxVelocity = maxVelocity; | this.maxVelocity = maxVelocity; | ||||
@@ -45,8 +51,10 @@ public class Track extends Observable { | |||||
this.overallAvg = 0; | this.overallAvg = 0; | ||||
this.delayedAvg = 0; | this.delayedAvg = 0; | ||||
this.lastAvg = 0; | this.lastAvg = 0; | ||||
this.historyLength = 25; | |||||
this.historyLength = historyLength; | |||||
this.waitTime = waitTime; | this.waitTime = waitTime; | ||||
this.steps = 0; | |||||
this.listSemaphore = new Semaphore(1); | |||||
} | } | ||||
@@ -90,17 +98,28 @@ public class Track extends Observable { | |||||
} | } | ||||
v.updateVelocity(distanceForerunner); | v.updateVelocity(distanceForerunner); | ||||
} | } | ||||
try { | |||||
this.listSemaphore.acquire(); | |||||
} catch (InterruptedException ex) {return;} | |||||
List <VehicleTimeRecord> records = new ArrayList<>(vehicles.size()); | List <VehicleTimeRecord> records = new ArrayList<>(vehicles.size()); | ||||
this.vtrList.add(records); | this.vtrList.add(records); | ||||
if (this.vtrList.size() > this.historyLength) { | |||||
this.vtrList.remove(0); | |||||
} | |||||
for(Vehicle v: vehicles){ | for(Vehicle v: vehicles){ | ||||
v.timeElapse(); | v.timeElapse(); | ||||
VehicleTimeRecord vtr = new VehicleTimeRecord(v.id, v.position, v.curVelocity, v.maxVelocity); | VehicleTimeRecord vtr = new VehicleTimeRecord(v.id, v.position, v.curVelocity, v.maxVelocity); | ||||
records.add(vtr); | records.add(vtr); | ||||
} | } | ||||
steps++; | |||||
this.listSemaphore.release(); | |||||
update_avg(); | update_avg(); | ||||
this.setChanged(); | this.setChanged(); | ||||
this.notifyObservers(); | this.notifyObservers(); | ||||
this.clearChanged(); | this.clearChanged(); | ||||
LockSupport.parkNanos(1); | |||||
try { | try { | ||||
Thread.sleep(waitTime); | Thread.sleep(waitTime); | ||||
} catch (InterruptedException ex) { } | } catch (InterruptedException ex) { } | ||||
@@ -116,12 +135,12 @@ public class Track extends Observable { | |||||
protected void update_avg(){ | protected void update_avg(){ | ||||
lastAvg = avg_step(vtrList.size()-1); | lastAvg = avg_step(vtrList.size()-1); | ||||
if (this.vtrList.size() > 10) { | |||||
if (this.steps > 10) { | |||||
sumDelAvgMemory += lastAvg; | sumDelAvgMemory += lastAvg; | ||||
delayedAvg = sumDelAvgMemory / (vtrList.size() - 10); | |||||
delayedAvg = sumDelAvgMemory / (this.steps - 10); | |||||
} | } | ||||
sumAvgMemory += lastAvg; | sumAvgMemory += lastAvg; | ||||
overallAvg = sumAvgMemory / vtrList.size(); | |||||
overallAvg = sumAvgMemory / this.steps; | |||||
} | } | ||||
@@ -46,7 +46,6 @@ public class Vehicle { | |||||
curVelocity = curVelocity + 1; | curVelocity = curVelocity + 1; | ||||
} | } | ||||
if (r < brakeProb && curVelocity > 0) { | if (r < brakeProb && curVelocity > 0) { | ||||
System.out.println("vehicle: "+brakeProb); | |||||
curVelocity = curVelocity - 1; | curVelocity = curVelocity - 1; | ||||
} | } | ||||
if (curVelocity > distanceForerunner) { | if (curVelocity > distanceForerunner) { | ||||