I am getting my speed from the gps using location.speed() function and the value is getting stored in nCurrentSpeed.
Should i store the nCurrentSpeed value in an Array to get the average speed when the app has stopped? How do i do it?
#Override
public void onLocationChanged(Location location) {
TextView dis =(TextView)findViewById(R.id.distance);
TextView time1 =(TextView)findViewById(R.id.time);
Typeface myTypeface = Typeface.createFromAsset(getAssets(), "SPEEDOFONT.TTF");
text2 = (TextView) findViewById(R.id.text2);
text2.setTypeface(myTypeface);
float speed,time, distance;
if (location == null) {
text2.setText("-.- km/h");
} else {
float nCurrentSpeed = location.getSpeed();
speed = (float) (nCurrentSpeed * 3.6);
text2.setText(String.format("%.2f km/h", speed));
time =location.getTime();
time1.setText("" +time);
distance = speed*time;
dis.setText(String.format("%.2f m/s", distance));
}
}
It may not be spot on to the actual (very specific) question, but you could also use DoubleSummaryStatistics: You can create an instance of this class, then let it accept one value after the other, and finally get the average without doing manual computations - and by the way, you get the computation of the minimum and maximum for free.
private final DoubleSummaryStatistics stats = new DoubleSummaryStatistics();
public void onLocationChanged(Location location)
{
...
float speed = ...;
stats.accept(speed);
}
void printSummary()
{
double average = stats.getAverage();
double min = stats.getMin();
double max = stats.getMax();
...
}
EDIT:
In case you don't use Java 8 yet, you can do
private final List<Float> speeds = new ArrayList<Float>();
public void onLocationChanged(Location location)
{
...
float speed = ...;
speeds.add(speed);
}
private float computeAverage(List<Float> values)
{
float sum = 0;
for (Float v : values)
{
sum += v;
}
return sum / values.size();
}
void printSummary()
{
double average = computeAverage(speeds);
...
}
(Similar to what #AndrewTobilko originally proposed)
Related
new to programming i know i'm doing something that's probably really obviously wrong to do with passing or using the wrong variables but i just can't work out what.
Here is my code:
public class CameraViewActivity extends Activity implements
SurfaceHolder.Callback, OnLocationChangedListener, OnAzimuthChangedListener {
private double mAzimuthReal = 0;
private double mAzimuthTheoretical = 0;
private static double AZIMUTH_ACCURACY = 5;
private double mMyLatitude = 0;
private double mMyLongitude = 0;
private List<Double> calculateAzimuthAccuracy(double azimuth) {
double minAngle = azimuth - AZIMUTH_ACCURACY;
double maxAngle = azimuth + AZIMUTH_ACCURACY;
List<Double> minMax = new ArrayList<Double>();
#Override
public void onAzimuthChanged(float azimuthChangedFrom, float azimuthChangedTo) {
mAzimuthReal = azimuthChangedTo;
mAzimuthTheoretical = calculateTheoreticalAzimuth();
pointerIcon = (ImageView) findViewById(R.id.icon);
double minAngle = calculateAzimuthAccuracy(mAzimuthTheoretical).get(0);
double maxAngle = calculateAzimuthAccuracy(mAzimuthTheoretical).get(1);
if (isBetween(minAngle, maxAngle, mAzimuthReaal) {
pointerIcon.setVisibility(View.VISIBLE);
}
else {
pointerIcon.setVisibility(View.INVISIBLE);
}
updateDescription();
}
Thanks for reading
Use
isRange(mMyLatitude, mMyLongitude, mPoi.getPoiLatitude(), mPoi.getPoiLongitude)
instead of
isRange(MyLatitude, MyLongitude, MpoiLatitude, MpoiLongitude)
FYI, its better to use small letter for naming variable.
In this function you need to pass as paramters either two locations and use their coordinates in the function inRange or you pass four coordinates and use them.
public void onAzimuthChanged(float azimuthChangedFrom, float azimuthChangedTo) {
mAzimuthReal = azimuthChangedTo;
mAzimuthTheoretical = calculateTheoreticalAzimuth();
pointerIcon = (ImageView) findViewById(R.id.icon);
double minAngle = calculateAzimuthAccuracy(mAzimuthTheoretical).get(0);
double maxAngle = calculateAzimuthAccuracy(mAzimuthTheoretical).get(1);
if (isBetween(minAngle, maxAngle, mAzimuthReal) && isRange(MyLatitude, MyLongitude, MpoiLatitude, MpoiLongitude)) {
pointerIcon.setVisibility(View.VISIBLE);
}
else {
pointerIcon.setVisibility(View.INVISIBLE);
}
updateDescription();
}
This has no meaning
isRange(MyLatitude, MyLongitude, MpoiLatitude, MpoiLongitude);
One more thing, adapt a professional naming criteria. Giving your attributes names that start with capital letters is quite MEH.
Writing a program in Android Studio 2.2.2 (MainActivity.java). Basically there are multiple inputs, one button, multiple outputs. However, many of the outputs are cross referenced into many of the other outputs. I'm new to all of this as our professor threw this on us in a non-programming class. Can anyone see some of my errors? I hope that I'm doing the process mostly correct, but the operations are all have issues with string/float/double incompatibilities. Thanks for any insight!
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btnCalc;
private TextView tvaResult;
private TextView tvcResult;
private TextView tvetResult;
private TextView tvphiResult;
private TextView tvMnResult;
private TextView tvphiMnResult;
private TextView tvbeta1Result;
private EditText etB,etD,etH,etAs,etFc,etFy;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
btnCalc = (Button)findViewById(R.id.btnCalc);
etB = (EditText)findViewById(R.id.etB);
etD = (EditText)findViewById(R.id.etD);
etH = (EditText)findViewById(R.id.etH);
etAs = (EditText)findViewById(R.id.etAs);
etFc = (EditText)findViewById(R.id.etFc);
etFy = (EditText)findViewById(R.id.etFy);
tvaResult = (TextView)findViewById(R.id.tvaResult);
tvcResult = (TextView)findViewById(R.id.tvcResult);
tvetResult = (TextView)findViewById(R.id.tvetResult);
tvphiResult = (TextView)findViewById(R.id.tvphiResult);
tvMnResult = (TextView)findViewById(R.id.tvMnResult);
tvphiMnResult = (TextView)findViewById(R.id.tvphiMnResult);
tvbeta1Result = (TextView)findViewById(R.id.tvbeta1Result);
btnCalc.setOnClickListener(this);
}
#Override
public void onClick(View view) {
Float B = Float.parseFloat(etB.getText().toString());
Float D = Float.parseFloat(etD.getText().toString());
Float H = Float.parseFloat(etH.getText().toString());
Float As = Float.parseFloat(etAs.getText().toString());
Float Fc = Float.parseFloat(etFc.getText().toString());
Float Fy = Float.parseFloat(etFy.getText().toString());
Float aResult = Float.parseFloat(tvaResult.getText().toString());
Float cResult = Float.parseFloat(tvcResult.getText().toString());
Float etResult = Float.parseFloat(tvetResult.getText().toString());
Float beta1Result = Float.parseFloat(tvbeta1Result.getText().toString());
Float phiResult = Float.parseFloat(tvphiResult.getText().toString());
switch(view.getId() ) {
case R.id.btnCalc:
tvaResult = (Fy * As) / (0.85 * Fc * B);
tvcResult = aResult / beta1Result;
tvetResult = ((D - cResult) / (cResult)) * 0.003;
if (Fc <= 4000) {
beta1Result = 0.85;
} else if (4000 < Fc <= 8000) {
beta1Result= ((0.85)-(0.05 * ((Fc - 4000) / (1000))));
} else {
beta1Result= 0.65;
}
if (etResult >= 0.005) {
tvphiResult= 0.9;
} else if (0.002 <= etResult < 0.005) {
tvphiResult= 0.65 + ((etResult - 0.002) * ((0.25) / (0.005 - 0.002)));
} else {
tvphiResult= 0.00
}
tvMnResult= (Fy * As) * (etD - (aResult / 2));
tvphiMnResult= phiResult * tvMnResult
}}
}}
To make it short, you need to keep the type of each Variable.
Here for example :
tvaResult = (Fy * As) / (0.85 * Fc * B);
You have
TextView = (Float * Float) / ( Double * Float * Float)
TextView = Double // Not possible
You are trying to put a Float value into a Instance of TextView, this can't be done of course. But you really want to update the text of the Textview, so use the methods setText(String) of TextView like :
tvaResult.setText((Fy * As) / (0.85 * Fc * B) + ""); // Need to be convert into String
To change the text to print
This is basicly always the same mistake done, you need to change the text of the TextView an not trying to change the instance itself.
I don't want to solve an equation and my question is not about Graphs and Trees Data Structures. I am trying to generate Data Points for graph from an equation given by user. I want efficient algorithm, easy to use and easy to maintain data structures. I have two solutions in mind
1: This is trivial and I have seen in many Applications.
String expr = "2*x+3*x";
Evaluator evaluator = new Evaluator();//I have this class
for (int i = start; i < end; i += step)
{
evaluator.setConstant("x", i);
double ans = evaluator.evaluate(expr);
}
This is very slow because each time every step is repeated like tokenzing, verifying, conversion to RPN, preparing stacks and queues and at last result calculation. The possible solution to this problem is somehow caching all stacks and queues but after that a comparison would be required between current expression and previous expression to use last stored state.
2: Currently I am developing second solution. The purpose of this is efficiency and would be used in Symbolic calculation in future.
So far my implementation
Variable.java
import java.text.DecimalFormat;
public class Variable
{
private final double pow;
private final double coefficient;
private final String symbol;
public Variable(String symbol)
{
this.symbol = symbol;
this.pow = 1.0;
this.coefficient = 1.0;
}
public Variable(String symbol, double coefficient, double pow)throws IllegalArgumentException
{
if (coefficient == 0.0)throw new IllegalArgumentException("trying to create variable with coefficient 0");
if (pow == 0.0)throw new IllegalArgumentException("trying to create variable with exponent 0");
this.symbol = symbol;
this.pow = pow;
this.coefficient = coefficient;
}
public final String getSymbol()
{
return this.symbol;
}
public final double getPow()
{
return this.pow;
}
public final double getCoefficient()
{
return this.coefficient;
}
#Override
public String toString()
{
StringBuilder builder = new StringBuilder();
DecimalFormat decimalFormat = new DecimalFormat("#.############");
if (coefficient != 1.0)builder.append(decimalFormat.format(this.coefficient));
builder.append(this.symbol);
if (this.pow != 1.0)builder.append("^").append(decimalFormat.format(this.pow));
return builder.toString();
}
/*
* Stub Method
* Generate some unique hash code
* such that chances of key collision
* become less and easy to identify
* variables with same power and same
* symbol*/
#Override
public int hashCode()
{
return 0;
}
}
Equation.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
public class Equation
{
private final ArrayList<Boolean> operations;
private final HashMap<String, Variable> variableHashMap;
private int typesOfVariables;
public Equation(Variable variable)
{
this.variableHashMap = new HashMap<>();
this.operations = new ArrayList<>();
this.typesOfVariables = 1;
this.variableHashMap.put(variable.getSymbol(), variable);
}
/*Stub Method*/
public void addVariable(Variable variable, boolean multiply)
{
/*
* Currently not covering many cases
* 1: Add two variables which have same name
* and same pow.
* 2: variable which are wrapped inside functions e.g sin(x)
* and many other.*/
if (multiply && variableHashMap.containsKey(variable.getSymbol()))
{
Variable var = variableHashMap.get(variable.getSymbol());
Variable newVar = new Variable(var.getSymbol(), var.getCoefficient() * variable.getCoefficient(), var.getPow() + variable.getPow());
/*
* Collision chances for variables with same name but
* with different powers*/
this.variableHashMap.replace(var.getSymbol(), newVar);
}
else
{
++this.typesOfVariables;
this.variableHashMap.put(variable.getSymbol(), variable);
}
this.operations.add(multiply);
}
/*Stub Method
*Value for every variable at any point will be different*/
public double solveFor(double x)
{
if (typesOfVariables > 1)throw new IllegalArgumentException("provide values for all variables");
Iterator<HashMap.Entry<String, Variable>> entryIterator = this.variableHashMap.entrySet().iterator();
Variable var;
double ans = 0.0;
if (entryIterator.hasNext())
{
var = entryIterator.next().getValue();
ans = var.getCoefficient() * Math.pow(x, var.getPow());
}
for (int i = 0; entryIterator.hasNext(); i++)
{
var = entryIterator.next().getValue();
if (this.operations.get(i))ans *= var.getCoefficient() * Math.pow(x, var.getPow());
else ans += var.getCoefficient() * Math.pow(x, var.getPow());
}
return ans;
}
#Override
public String toString()
{
StringBuilder builder = new StringBuilder();
Iterator<HashMap.Entry<String, Variable>> entryIterator = this.variableHashMap.entrySet().iterator();
if (entryIterator.hasNext())builder.append(entryIterator.next().getValue().toString());
Variable var;
for (int i = 0; entryIterator.hasNext(); i++)
{
var = entryIterator.next().getValue();
if (this.operations.get(i))builder.append("*").append(var.toString());
else builder.append(var.toString());
}
return builder.toString();
}
}
Main.java
class Main
{
public static void main(String[] args)
{
try
{
long t1 = System.nanoTime();
Variable variable = new Variable("x");
Variable variable1 = new Variable("x", -2.0, 1.0);
Variable variable2 = new Variable("x", 3.0, 4.0);
Equation equation = new Equation(variable);
equation.addVariable(variable1, true);//2x+x
equation.addVariable(variable2, true);
for (int i = 0; i < 1000000; i++)equation.solveFor(i);//Calculate Million Data Points
long t2 = System.nanoTime();
System.out.println((t2-t1)/1000/1000);
System.out.println(equation.toString());
}
catch (Exception e)
{
System.out.println("Error: " + e.getMessage());
}
}
}
Am I going in right direction?
Is there any commonly used Algorithm for this problem?
My main goal is efficiency, code cleanness and code maintainability.
Note: I am not native English speaker so please ignore any grammatical mistake.
Thanks.
I do not see any problem with your first code. Yes may be at every step your code "repeat like tokenzing, verifying, conversion to RPN, preparing stacks and queues and at last result calculation", but in the end all of this is just linear number of steps. So I fail to see how it can make it really slow.
One of the biggest screens I have seen was 2560x1440 pixels, which means that most of the time you would need less than 2500 points to draw your graph there.
If you point is code cleanness and code maintainability, then most probably a code consisting of 5 lines is better than the code consisting of 200.
I want to print the three values of each axes(scaledX , scaledY, scaledZ) of accelerometer in three TextView.
Can somebody help me?
thanks.
CODE:
MainActivity.java.
public class MainActivity extends Activity implements BluetoothAdapter.LeScanCallback {
private TextView mAccelerometerx, mAccelerometery, mAccelerometerz;
mAccelerometerx =(TextView) findViewById(R.id.ejex);
mAccelerometery =(TextView) findViewById(R.id.ejey);
mAccelerometerz =(TextView) findViewById(R.id.ejez);
private void updateAccelerometerValue(BluetoothGattCharacteristic characteristic ){
double accelerometerx = SensorTagData.extractAccelerometer(characteristic, mAccelerometerx);
double accelerometery = SensorTagData.extractAccelerometer(characteristic, mAccelerometery);
double accelerometerz = SensorTagData.extractAccelerometer(characteristic, mAccelerometerz);
mAccelerometerx.setText(String.format("%.4f", accelerometerx));
mAccelerometery.setText(String.format("%.4f", accelerometery));
mAccelerometerz.setText(String.format("%.4f", accelerometerz));
}
}
SensorData.java
public class SensorData {
public static double [] extractAccelerometer(BluetoothGattCharacteristic c) {
Integer x = c.getIntValue(FORMAT_SINT8, 0);
Integer y = c.getIntValue(FORMAT_SINT8, 1);
Integer z = c.getIntValue(FORMAT_SINT8, 2) * -1;
double scaledX = x / 64.0;
double scaledY = y / 64.0;
double scaledZ = z / 64.0;
return new double[] {scaledX, scaledY, scaledZ};
}
}
private void updateAccelerometerValue(BluetoothGattCharacteristic characteristic ){
double accelerometerx = SensorTagData.extractAccelerometer(characteristic, mAccelerometerx);
double accelerometery = SensorTagData.extractAccelerometer(characteristic, mAccelerometery);
double accelerometerz = SensorTagData.extractAccelerometer(characteristic, mAccelerometerz);
mAccelerometerx.setText(String.format("%.4f", accelerometerx)); //ERROR HERE
mAccelerometery.setText(String.format("%.4f", accelerometery)); //ERROR HERE
mAccelerometerz.setText(String.format("%.4f", accelerometerz)); //ERROR HERE
}
ERROR Type
The method extractAccelerometer(BluetoothGattCharacteristic) in the type SensorTagData is not applicable for the arguments (BluetoothGattCharacteristic, TextView)
I know I am giving more than two parameters, but if I delete "accelerometerx", "accelerometery" , "accelerometerz" the error disappears but I suppose will not see anything.
My coordinates list:
int[][] coords = {
{3093, 3630 }, {3095, 3632}, {3098, 3633},
{3101, 3633 }, {3104, 3631}, {3106, 3629},
{3107, 3627}, {3108, 3624}, {3109, 3620},
{3108, 3617}, {3106, 3614}, {3102, 3613},
{3099, 3613}, {3097, 3613}, {3093, 3614},
{3090, 3617}, {3087, 3619}
};
Generation part:
int random = Misc.random(coords.length - 1);
handler.move(coords[random][0], coords[random][1], 0);
Basically what I am trying to do, if these coordinates are already taken, then re-generate the coords.
I can't really store these coords into a big arraylist, because I don't always want this feature to function, for example if I have more players than the items in the coords[] array, then this won't be activated.
Therefore I created a arraylist of used coords, and this is my logic on how to do this:
int[][] coords = {
{3093, 3630 }, {3095, 3632}, {3098, 3633},
{3101, 3633 }, {3104, 3631}, {3106, 3629},
{3107, 3627}, {3108, 3624}, {3109, 3620},
{3108, 3617}, {3106, 3614}, {3102, 3613},
{3099, 3613}, {3097, 3613}, {3093, 3614},
{3090, 3617}, {3087, 3619}
};
ArrayList<Integer> coordinates = new ArrayList<Integer>();
int random = Misc.random(coords.length - 1);
if (getPlayersCount() < coords.length) {
if (coordinates.contains(coords[random][0], coords[random][1])) {
random = Misc.random(coords.length - 1);
}
else {
handler.move(coords[random][0], coords[random][1], 0);
coords.add(coords[random][0], coords[random][1]);
}
}
else {
random = Misc.random(coords.length - 1);
handler.move(coords[random][0], coords[random][1], 0);
}
Basically, if there are less players than the array length, process.
If coordinates arraylist contains generated X, Y, regenerate it, else move player and add the coords to the list.
But it seems like I did something wrong, as I get this error: error: no suitable method found for contains(int,int)
How can I do this?
ArrayList#contains compares a Object with those objects contained within the list...
Returns true if this list contains the specified element. More
formally, returns true if and only if this list contains at least one
element e such that (o==null ? e==null : o.equals(e)).
Your list contains arrays of int, which aren't easily comparable.
It would be much easier if you used a Object whose equals method was capable of comparing the coordinates of other similar objects. Something like...
public class Coordinate {
private int latitude;
private int longitude;
public Coordinate(int latitude, int longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
public int getLatitude() {
return latitude;
}
public int getLongitude() {
return longitude;
}
public boolean equals(Object value) {
boolean equals = false;
if (value instanceof Coordinate) {
Coordinate coord = (Coordinate) value;
equals = getLatitude() == coord.getLatitude() && getLongitude() == coord.getLongitude();
}
return equals;
}
//good practice to override hashcode when you override equals
public int hashcode() {
int hash = 7;
hash = 89 * hash + this.latitude;
hash = 89 * hash + this.longitude;
return hash;
}
}
Then you could use something more like...
Coordinate[] coords = {
new Coordinate(3093, 3630 ), new Coordinate(3095, 3632), new Coordinate(3098, 3633),
new Coordinate(3101, 3633 ), new Coordinate(3104, 3631), new Coordinate(3106, 3629),
new Coordinate(3107, 3627), new Coordinate(3108, 3624), new Coordinate(3109, 3620),
new Coordinate(3108, 3617), new Coordinate(3106, 3614), new Coordinate(3102, 3613),
new Coordinate(3099, 3613), new Coordinate(3097, 3613), new Coordinate(3093, 3614),
new Coordinate(3090, 3617), new Coordinate(3087, 3619)
};
ArrayList<Coordinate> coordinates = new ArrayList<Coordinate>();
int random = Misc.random(coords.length - 1);
if (getPlayersCount() < coords.length) {
Coordinate coord = new Coordinate(coords[random].getLatitude(), coords[random].getLongitude());
if (coordinates.contains(coord)) {
random = Misc.random(coords.length - 1);
}
else {
handler.move(coords[random].getLatitude(), coords[random].getLongitude(), 0);
coordinates.add(coords[random]);
}
}
else {
random = Misc.random(coords.length - 1);
handler.move(coords[random].getLatitude(), coords[random].getLongitude(), 0);
}