Solution for very long (if statement) - android

I am new for programming and android development, I'm trying to make an app for length unit conversions. I used two spinner(from unit and to unit), so I need to check what user have selected in the both spinner and then return the value. My problem is I have got very long if statement, so I wonder if there is better solution for this.
Sorry for my poor english, I hope you understand what I mean.
here is the function for length:
public double lengthConversion() {
double res = 0.0;
num = Double.parseDouble(editTextNum.getText().toString());
// first spinner is mm, second spinner is mm
if (posFrom == 0 && posTo == 0) {
res = num;
} else if (posFrom == 0 && posTo == 1) { //second spinner is cm
res = num / 10;
} else if (posFrom == 0 && posTo == 2) { // dm
res = num / 100;
} else if (posFrom == 0 && posTo == 3) { // m
res = num / 1000;
} else if (posFrom == 0 && posTo == 4) { // km
res = num / 1000000;
}
if (posFrom == 1 && posTo == 0) {
....
} else if (posFrom == 1 && posTo == 1) {
....
} else if (posFrom == 1 && posTo == 2) {
....
} else if (posFrom == 1 && posTo == 3) {
....
} else if (posFrom == 1 && posTo == 4) {
....
}
.
.
.
if (posFrom == 4 && posTo == 0) {
...
} else if (posFrom == 4 && posTo == 1) {
...
} else if (posFrom == 4 && posTo == 2) {
...
} else if (posFrom == 4 && posTo == 3) {
...
} else if (posFrom == 4 && posTo == 4) {
...
}
return res;
}
and that is the string array I use:
<string-array name="array_length">
<item>mm</item>
<item>cm</item>
<item>dm</item>
<item>m</item>
<item>km</item>
</string-array>

In your first else if tree, posTo is really just a power of ten, so make the calculation instead of passing it through all those if else statements.
if (posFrom == 0)
res = num / Math.Pow(10, posTo);
All of your other units:
<string-array name="array_length">
<item>mm</item>
<item>cm</item>
<item>dm</item>
<item>m</item>
<item>km</item>
</string-array>
are just variations on powers of ten, so perform a further calculation adjusting your values based on the selected units (compared to a reference unit, probably meters), and you should need no more than 5 cases or if elses.

You can have an enum with the base unit (meter for instance).
Then you can have each other units (kms, mms, etc) as fields of that enum. I was going to draw up an example but there's an answer that does this well:
https://stackoverflow.com/a/17549248/447842

You can use the nested switch:
Switch(posFrom)
{
case 0 :
switch(posTo)
{
case 0: /*do*/ break;
case 1: /*do*/ break;
}
break;
case 1:
switch(postTo)
{
...
}
break;
...
default: /*how did i land here?*/
}

Sounds like you are doing unit conversion.
Now assuming pos 0 = mm, pos 1 = cm and so on.
int myFrom = posFrom;
int myTo = posTo;
if(myFrom == 4) then myFrom = 6;
if(myTo== 4) then myTo= 6;
num = res * math.pow(10, myFrom - myTo);
realize 1km = 1000000mm that's why when pos = 4, you need to change it to 6 since 10^6 = 1000000

Related

RxJava combineLatest - observable from changes

I create form with 15 inputs and I want observe those inputs to check if something was changed, I compare results of inputs with current userModel. How can I reduce that code because seems to be little bit complicated. It looks like that:
Observable.combineLatest(fieldsViewHolder.observableInputsChanges(), new FuncN<Boolean>() {
#Override
public Boolean call(Object... args) {
if(userModel != null) {
return args[0].toString().equals(userModel.getFirstName()) && args[1].toString().equals(userModel.getLastName()) && args[2].toString().equals(userModel.getEmail()) &&
args[3].toString().equals(userModel.getMobilePhone()) && args[4].toString().equals(userModel.getCompanyPlace()) && args[5].toString().equals(userModel.getCompanyName()) &&
args[6].toString().equals(userModel.getCountry()) && args[7].toString().equals(userModel.getCompanyPosition()) && args[8].toString().equals(userModel.getPhone()) &&
args[9].toString().equals(userModel.getPostalCode()) && args[10].toString().equals(userModel.getStreet1()) && args[11].toString().equals(userModel.getStreet2()) &&
args[12].toString().equals(userModel.getFirstName()) && args[13].toString().equals(userModel.getWebPage()) && args[14].toString().equals(userModel.getCity());
}
return args[0].toString().isEmpty() && args[1].toString().isEmpty() && args[2].toString().isEmpty() &&
args[3].toString().isEmpty() && args[4].toString().isEmpty() && args[5].toString().isEmpty() &&
args[6].toString().isEmpty() && args[7].toString().isEmpty() && args[8].toString().isEmpty() &&
args[9].toString().isEmpty() && args[10].toString().isEmpty() && args[11].toString().isEmpty() &&
args[12].toString().isEmpty() && args[13].toString().isEmpty() && args[14].toString().isEmpty();
}
});
you can create UserModel object with constructor (pass all args to it)
in constructor map every args to field you want. now you have another UserModel.
you can compare them by overriding equal for UserModel or you can convert them with Gson and compare String! I prefer first solution.
Update
for empty lines that you add after edit you can check like this:
for(int i = 0; i < 15; i++){
if(!args[i].toString().isEmpty()) {
return false;
}
}
return true;

How to set text for password field via uiautomator

I can't set text for password field via uiautomator:
UiObject eaPassword = uiDevice.findObject(new UiSelector().textContains("Password"));
assertTrue(eaPassword.waitForExists(35_000));
eaPassword.click(); // optional
eaPassword.setText("1234"); // return true
It is able to find the object itself.
If I execute eaPassword.getText(); it returns "Password".
If you run eaPassword.click() , screen would be change(keyboard pop up),
so you cannot find eaPassword(Uiobject) again
setText() this function has two behavior
1. Long press EditView
2. Input text
UiObject eaPassword = uiDevice.findObject(new UiSelector().textContains("Password"));
assertTrue(eaPassword.waitForExists(35_000));
eaPassword.setText("1234");
or try other method
UiObject eaPassword = uiDevice.findObject(new UiSelector().textContains("Password"));
assertTrue(eaPassword.waitForExists(35_000));
eaPassword.click();
setStrings("test");
public void setStrings(String text) {
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c >= 48 && c <= 57) // 0~9
uiDevice.pressKeyCode(c - 41);
else if (c >= 65 && c <= 90) // A~Z
uiDevice.pressKeyCode(c - 36, 1);
else if (c >= 97 && c < 122) // a~z
uiDevice.pressKeyCode(c - 68);
else if (c == 42) // *
uiDevice.pressKeyCode(KEYCODE_STAR);
else if (c == 35) // #
uiDevice.pressKeyCode(KEYCODE_POUND);
else if (c == 46) // .
uiDevice.pressKeyCode(KEYCODE_PERIOD);
else if (c == 47) // /
uiDevice.pressKeyCode(KEYCODE_SLASH);
else if (c == 58) // :
uiDevice.pressKeyCode(KEYCODE_SEMICOLON);
}
}
It would be one by one to input word (not use setText())

how to fix divide by zero in android

it is not WORKING !!
I have used different methods to solve the case but did not work
Anyone who can help me?
..............................................................................
case '/':
pp = Double.parseDouble(text.getText().toString());
if (sss == '/') {
if (Double.parseDouble(text.getText().toString()) == 0.0 ||Integer.parseInt(text.getText().toString()) == 0) {
text.setText("");
text2.setText("");
Toast.makeText(getBaseContext(), "Cannot divide by zero", Toast.LENGTH_SHORT).show();
} else if (pp != 0 || pp != 0.0) {
vis = tt / pp;
temp = (int) vis;
if (vis == temp) {
text.setText(Integer.toString(temp));
} else {
text.setText(Double.toString(vis));
}
vis = 0;
ash = 0;
break;
}
}
Dividing a floating point value by zero is not an error, the result just becomes infinity. Check the result after the division:
case '/':
pp = Double.parseDouble(text.getText().toString());
if (sss == '/') {
vis = tt / pp;
if (Double.isInfinite(vis)) {
text.setText("");
text2.setText("");
Toast.makeText(getBaseContext(), "Cannot divide by zero", Toast.LENGTH_SHORT).show();
} else {
temp = (int) vis;
if (vis == temp) {
text.setText(Integer.toString(temp));
} else {
text.setText(Double.toString(vis));
}
vis = 0;
ash = 0;
break;
}
}
Don't make your code so complex. Use just Double variable as in division you need answer to certain precision.Also there is problem with division operation with double type variables as they don't throw Arithmetic exception.E.g.:
0/0 - generates ArithmeticException
1.0/0 - generates output NaN(infinite)
It seams that "pp" is of double type.
So write some thing like this:
double tt=Double.parseDouble(textView1.getText().toString().trim());
double pp=Double.parseDouble(textView2.getText().toString().trim());
if(pp!=0){
x=tt/pp;
System.out.println(" res :"+x);
}else{
//you logic if pp is 0
}
Avoid computation if denominator is zero by using simple check(denominator==0) or keep as it so that when denominator is zero it shows result NaN(infinite).

Encrypted text comes out wrong

Hi I have some code which encrypts a text and display it in a textView and send it as an SMS.
The algorithm is (letterInt * constant)%29 = new letterInt
so basically it is the leftovers of division of 29 on the letter value times the constant
The alphabet is like this
private List<Character> alfabet = new ArrayList<Character>();
alfabet.add('a');
alfabet.add('b');
alfabet.add('c');
alfabet.add('d');
alfabet.add('e');
alfabet.add('f');
alfabet.add('g');
alfabet.add('h');
alfabet.add('i');
alfabet.add('j');
alfabet.add('k');
alfabet.add('l');
alfabet.add('m');
alfabet.add('n');
alfabet.add('o');
alfabet.add('p');
alfabet.add('q');
alfabet.add('r');
alfabet.add('s');
alfabet.add('t');
alfabet.add('u');
alfabet.add('v');
alfabet.add('w');
alfabet.add('x');
alfabet.add('y');
alfabet.add('z');
alfabet.add('æ');
alfabet.add('ø');
alfabet.add('å');
The problem is, that whenever C becomes larger than 1 the text isnt encrypted corretly.
e.g. d = 4, but if i choose C = 4 then the output becomes h (8), not p (16).
The code part is like this:
char[] bogstaver = tekstString.toCharArray();
for (int i = 1; i <= bogstaver.length; i++) {
if (bogstaver[i-1] == ' ' || bogstaver[i-1] == '.' || bogstaver[i-1] == '?' || bogstaver[i-1] == '!' ||
bogstaver[i-1] == ',' || bogstaver[i-1] == ';' || bogstaver[i-1] == '+' || bogstaver[i-1] == '(' ||
bogstaver[i-1] == ')' || bogstaver[i-1] == '{' || bogstaver[i-1] == '}' || bogstaver[i-1] == ':'){
continue;
}
if( CType == 1){
C = Integer.valueOf(faktorA);
CType = 2;
}
else if (CType == 2){
C = Integer.valueOf(faktorB);
CType = 3;
}
else if (CType == 3){
C = Integer.valueOf(faktorE);
CType = 1;
}
bogstaver[i-1] = alfabet.get((alfabet.indexOf(bogstaver[i-1]) * C)%29);
}
String endeligeTekst = new String(bogstaver);
if (k == 1){
krypteredeTekst.setText(endeligeTekst);
}
else{
sendString(endeligeTekst, Nr);
}
This is why you're not getting the result you're expecting;
e is the 4th value in your List (it's 0 indexed, a=0, b=1 etc.
With C=3, the result is 4*3=12, and the 13'th character (at index 12) is m which is the output (I can't get n as your question states).

cannot compare if more or less than the current time Calendar.MONTH

I'm trying here check the date to put the appropriate separator, but the problem is that when comparing the Calendar.Months, and the other checks work fine
if (calendar.get(Calendar.DAY_OF_YEAR) > Calendar.getInstance().get(Calendar.DAY_OF_YEAR) && calendar.get(Calendar.YEAR) > Calendar.getInstance().get(Calendar.YEAR) ||
(calendar.get(Calendar.DAY_OF_YEAR) < Calendar.getInstance().get(Calendar.DAY_OF_YEAR) && calendar.get(Calendar.YEAR) > Calendar.getInstance().get(Calendar.YEAR)) ||
(calendar.get(Calendar.DAY_OF_YEAR) == Calendar.getInstance().get(Calendar.DAY_OF_YEAR) && calendar.get(Calendar.YEAR) > Calendar.getInstance().get(Calendar.YEAR))||
(calendar.get(Calendar.DAY_OF_YEAR) == Calendar.getInstance().get(Calendar.DAY_OF_YEAR) && calendar.get(Calendar.MONTH) > Calendar.getInstance().get(Calendar.MONTH)&&calendar.get(Calendar.YEAR) == Calendar.getInstance().get(Calendar.YEAR)))
{
newTask.setDateStatus(ModelSeparator.TYPE_FUTURE);
if (!adapter.containsSeparatorFuture) {
adapter.containsSeparatorFuture = true;
separator = new ModelSeparator(ModelSeparator.TYPE_FUTURE);
Toast.makeText(getActivity(),"Future",Toast.LENGTH_SHORT).show();
}

Categories

Resources