I am trying to compare items out of my DB to the value of an EditText (user input). The answer can have multiple answers, seperated by a ','. I first put them into a stringarray and then compare them to the answer. The LevenshteinDistance checks if the answer is more or les good (http://en.wikipedia.org/wiki/Levenshtein_distance#Computing_Levenshtein_distance).
userAnswer = etUserAnswer.getText().toString().toLowerCase();
String[] answers = qAnswer.split(",");
for (String answer : answers) {
if (answer.equals(userAnswer)) {
Toast.makeText(getApplicationContext(), ("Answer Correct"),
Toast.LENGTH_SHORT).show();
tvMessage.setText("You smartass!");
} else {
Toast.makeText(getApplicationContext(), ("Wrong"),
Toast.LENGTH_SHORT).show();
points = points - 4;
String answerGood = answer.toLowerCase();
LevenshteinDistance lDistance = new LevenshteinDistance();
int comparisonCheck = lDistance.computeLevenshteinDistance(
userAnswer, answerGood);
if (comparisonCheck == 1) {
tvMessage.setText("Almost there, but not quite yet!");
} else if (comparisonCheck > 1) {
tvMessage.setText("Are you serious, totally wrong?!");
}
}
}
Suppose I am having the answers for a question in the DB as follows: tree,test,radio
I am having two problems:
1. When I type "radi" it gives me 'Almost there...' which is good. It should also give me this if I enter "tes", but instead it gives me the 'Are you serious,...' line. I guess it keeps comparing to the last one.
2. Every time I type in something which is not correct, I get -12 instead of -4. I suppose this is due to the fact I am having three answers and it loops three times.. but I don't know how I can make it count only once..
Anyone can help me on the way? Thanks!
Assuming you don't need to know the word which gives the least Levenshtein distance, you could modify your loop to find smallest distance only;
userAnswer = etUserAnswer.getText().toString().toLowerCase();
String[] answers = qAnswer.split(",");
LevenshteinDistance lDistance = new LevenshteinDistance();
int minDistance = lDistance.computeLevenshteinDistance(
userAnswer, answers[0].toLowerCase());
for (int i = 1; i < answers.length; ++i) {
minDistance = Math.min(minDistance, lDistance.computeLevenshteinDistance(
userAnswer, answers[i].toLowerCase()));
}
if (minDistance == 0) {
// Correct answer...
} else {
// Wrong answer...
points -= 4;
// etc etc...
}
Related
So first of all sorry if this has already been asked and answered before, I couldn't find anything relating to my issue.
So I'm working on a project for college and I need to get int values from EditText widgets. I was told to use parseInt to do this however when running my program, that line of code causes the application to crash. I don't know what I'm doing wrong, I'm still very new to android development, thanks for the help :)
public void Calculate (View view)
{
int MilesTravelled;
int FuelUsed;
int MPG;
/* the two lines below are what cause the application to crash */
MilesTravelled = Integer.parseInt(txtMilesTravelled.getText().toString());
FuelUsed = Integer.parseInt(txtFuelUsed.getText().toString());
FuelUsed = (int) (FuelUsed / 4.55);
MPG = MilesTravelled / FuelUsed;
lblMPG.setText(FuelUsed);
}
Do you have this in the onCreate() function?
EditText txtMilesTravelled = (EditText) findViewById(R.id.YourEditText);
But I think you mixed Integer and int. They are not the same:
See this link!
First of all, don't capitalize the first letter of an variables or method names. Following the Java coding conventions, only do that for classes.
What is probably causing your app to crash is you trying to set the text of a label to an integer. The setText method for a TextView needs to take in a string.
So change:
lblMPG.setText(FuelUsed);
to:
lblMPG.setText(String.valueOf(FuelUsed));
Otherwise it might be that it's trying to parse a non-numerical string to an integer.
For exmaple, if the EditText is blank, it will cause your app to crash. To prevent that, try this:
int MilesTravelled = 0, FuelUsed = 0;
try {
MilesTravelled = Integer.parseInt(txtMilesTravelled.getText().toString());
FuelUsed = Integer.parseInt(txtFuelUsed.getText().toString());
} catch (NumberFormatException nfe) {
Toast.makeText(getApplicationContext(), "Error NFE!", 0).show();
nfe.printStackTrace();
}
This way, it will catch a NumberFormatException error (parsing a string to an integer that can't be represented as an integer, such as "hello"). If it catches the error, it will toast that an error has occurred and your integer variables will remain 0.
Or you could just test if the strings contain only digits using the following regex:
int MilesTravelled = 0, FuelUsed = 0;
if (txtMilesTravelled.getText().toString().matches("[0-9]+")) {
MilesTravelled = Integer.parseInt(txtMilesTravelled.getText().toString());
} else {
// contains characters that are not digits
}
if (txtFuelUsed.getText().toString().matches("[0-9]+")) {
FuelUsed = Integer.parseInt(txtFuelUsed.getText().toString());
} else {
// contains characters that are not digits
}
If that's not the problem, then make sure you define your variables properly.
txtMilesTravelled and txtFuelUsed should be EditText:
EditText txtMilesTravelled = (EditText)findViewById(R.id.txtMilesTravelled);
EditText txtFuelUsed = (EditText)findViewById(R.id.txtFuelUsed);
And make sure that your R.id.editText actually exists on your layout and that the IDs are the correct ones.
Last thing, make sure FuelUsed is not 0 before calculating MPG because then you are dividing by 0:
int MPG = 0;
if (FuelUsed != 0) {
MPG = MilesTravelled / FuelUsed;
}
I am assuming that you're entering perfect integers in the EditTexts. It might be a good idea to use the trim function txtMilesTravelled.getText().toString().trim() before using parseInt.
However, I think the major problem is here : lblMPG.setText(FuelUsed);
FuelUsed is an integral value, when you pass an integer to setText(), it looks for a string resource with that integral value. So you should be passing a String to the setText() method.
Use : lblMPG.setText(Integer.toString(FuelUsed));
I am 99% sure that this cannot be done, however I thought I would ask to be certain.
I am attempting to create an application that calculates the required dice roll for an action in a popular tabletop war game.
The following is this calculation in Java
int x = ((WSattacker * 2) - WSdefender);
int y = (WSattacker - WSdefender);
String result;
// Calculation for a +5
if (x <= -1) {
result = "5+";
}
// Calculation for a +4
else if (x >= 0 && y <= 0) {
result = "4+";
}
// Calculation for a +3
else if (y > 0) {
result = "3+";
} else {
result = "Error";
}
return result;
Now my issue is that to avoid copywriter infringement I cannot mention the name of the game in my application, and probably cannot hard code the above calculation in the app.
This means that it is difficult to tell a potential user what the app will do.
The only solution I can think of is to make the application generic and allow the user to input the calculation required in the form of an equation.
An equation that I can place anonymously on a public board or similar.
Therefore my questions are as follows.
Is there another way of going about this?
If no, is it possible to condense the above code into a single expression/ equationi.e. one that removes the if and else statements
To answer question 2:
result = test_condition_1 ? result2_if_true : (test_condition_2 ? result2_if_true : test3_or_result2);
You can then build up 'compound' test conditions this way, and it's based upon ternary operators.
EDIT
Ternary operators are a short-hand way of writing if..then..else statments, and more information can be found in the wiki-link above. An example of its use is below, which you can compile and run:
public class TernaryTest {
public static void main(String [] args){
int x = 14;
int y = 5;
String result = ( x <= 10 ) ? "Less than 10" : "More than 10";
System.out.println("Result is: " + result);
}
}
Try running it and see the result as you change the value of x to understand how it works. Then it's possible to extend it to include and else by replacing the "more than 10" string.
I have this code :
String[] whereyoufromarray = {"where", "you", "from"};
for (String whereyoufromstring : whereyoufromarray)
{
if (value.contains(whereyoufromstring)) {
//statement
}
}
But I want that if to only execute the statement if "value" has all of the words included in the array, something like "where are you from?". Currently if value has ONLY one of the words in the array the statement is executed.
I can do this with if (value.contains("where") && value.contains("you") && value.contains ("from")) but this just seems unnecessarily long. There has to be a workaround using arrays that I am missing.
Well, what is it?
p.s.: sorry for poor grammar. i'm suffering from sleep deprivation.
String[] whereyoufromarray = {"where", "you", "from"};
boolean valueContainsAllWordsInArray = true;
for (String whereyoufromstring : whereyoufromarray) {
// If one word wasn't found, the search is over, break the loop
if(!valueContainsAllWordsInArray) break;
valueContainsAllWordsInArray = valueContainsAllWordsInArray &&
value.contains(whereyoufromstring);
}
// valueContainsAllWordsInArray is now assigned to true only if value contains
// ALL strings in the array
For a case like this, I typically implement a function just to make the test. Let's call it containsAll()
public static boolean containsAll(String[] strings, String test)
{
for (String str : strings)
if (!test.contains(str))
return false;
return true;
}
And now you just do
if (containsAll(whereyoufromarray, value))
//statement
String[] whereyoufromarray = {"where", "you", "from"};
int arrayLength = whereyoufromarray.length;
int itemCount = 0;
for(String whereyoufromstring : whereyoufromarray)
{
if(value.contains(whereyoufromstring))
{
itemCount++;
}
}
if (itemCount == arrayLength){
//do your thing here
}
rough idea. I don't have my IDE up to proof this, but basically you can set a counter to = the length of your known array, then check each value in the array to see if it contains a match..if it does, increment another counter. At the end, test your counter to see if it matches the length of your array, so in your example, if itemCount= 3, then all values matched. if it was 2, then one would be missing and your method wouldn't execute.
I used the following code snippet to sort by phone number:
class Item { String addr; /* phone number */ }
private int compareByAddr(Item objA, Item objB) {
if (objA.addr==null && objB.addr==null) {
return 0;
} else if (objA.addr==null && objB.addr!=null) {
return -1;
} else if (objA.addr!=null && objB.addr==null) {
return 1;
} else {
if (PhoneNumberUtils.compare(objA.addr, objB.addr)) {
return 0;
} // end if
return objA.addr.compareTo(objB.addr);
} // end if
} // end compareByAddr()
However I got an Exception:
E/AndroidRuntime(12157): java.lang.IllegalArgumentException:
Comparison method violates its general contract!
I've searched about it, and found out that it means my sorting algorithm is not transitive...
Does anyone has a better algorithm for sorting by phone number?
Problem is you have 2 String's which represent phone numbers and you want to compare them and sort them from big to small like there were numbers...
but comparing 2 String to each-other (like in your code snippet):
objA.addr.compareTo(objB.addr);
wont work :(
you can do this by manipulating the String to a number (and discarding all non digit from it)
and then compare the 2 like they were regular numbers ...
String phone1Str
String phone2Str
int phone1
int phone2
phone1Str= phone1Str.replaceAll("\\D+",""); //using reg-ex to get only digits
phone1= Integer.valueOf(phone1Str); //convert to int to compare numbers
phone2Str= phone2Str.replaceAll("\\D+","");
phone2= Integer.valueOf(phone2Str);
if (PhoneNumberUtils.compare(phone1Str,phone2Str)
//they are equal
else if (phone1>phone2)
//phone1 is the larger number !
else
//phone2 is the larger number !
hope this helps
I am having a problem while looping through one of my loop constructions.
I get Question instances out of my database and one of the fields of the instance is Attempts. I pulled my database from my device and inspected it and all fields of the column attempts are filled with ints greater than 0.
int initialAttempts = 0;
initialAttempts = c.getInt(6);
q.setAttempts(initialAttempts);
and in my custom array adapter:
if (mView != null) {
int attempts = getItem(position).getAttempts();
int correctAnswer = getItem(position).getAnswerCorrect();
triangle.setVisibility(View.INVISIBLE);
if(correctAnswer == 1) {
triangle.setVisibility(View.VISIBLE);
}
else if (correctAnswer != 1 && attempts > 0) {
triangle.setVisibility(View.VISIBLE);
triangle.setImageResource(R.drawable.trianglered);
}
So the problem is it never shows trianglered. If I drop the && attempts > 0, it does show the trianglered, so I assume the error is in there. The strange thing is if I initialize attempts as 1 before the getItem(position).getAttempts, it still shows no trianglereds.
Any ideas where this goes wrong?
getItem(position).getAttempts() method returns 0. There are no other variants. Why it returns 0 is the question to you. Prefer debugging instead of asking such questions.
PS. No need to check for correctAnswer != 1 in else if statement. The opposite statement has already been checked in if and it was false.