The following code reads the spreadsheet cell values with the JXL plugin and then compares these values with the values on the page and chooses the matching value from the combo box.
The code I have works but it is case sensitive, the value must be identical.
I want to improve this code to search the combo box faster and select the closest value without being identical. Currently it runs through all values slowly.
String valDesejado = tipopromocao;
String valorComboBox = "";
Select verificaOpt = new Select(driver.findElement(By.name("tipoDePromocaoPromocao")));
int tamanhoBox = verificaOpt.getOptions().size();
int variavelVerificadora1 = 0;
System.out.println("Tamanho: " + tamanhoBox);
for (int i = 0; i < tamanhoBox; i++)
{
verificaOpt.selectByIndex(i);
valorComboBox = verificaOpt.getFirstSelectedOption().getText().toString();
if (valDesejado.equalsIgnoreCase(valorComboBox))
{
i = tamanhoBox;
variavelVerificadora1 = 1;
}
}
if (variavelVerificadora1 == 0)
{
System.out.println("ALERTA: The Option + valDesejado + " no comboBox \"tipoDePromocaoPromocao\" not found.");
}
I put some comments in the code that explains what I'm doing and makes corrections on a few things.
Instead of using an int and setting it to 0/1, use a boolean and set it to true/false.
This loop should be faster because I'm not selecting each option as I loop. You can examine the text of each option without selecting it... then once you find a match, select the match.
Use break to exit a loop instead of setting the counter to max value.
Give this code a try.
String valDesejado = tipopromocao;
boolean variavelVerificadora1 = false; // use boolean instead of int set to 0/1
Select verificaOpt = new Select(driver.findElement(By.name("tipoDePromocaoPromocao")));
System.out.println("Tamanho: " + verificaOpt.getOptions().size());
// as this loops, the variable 'option' contains the current loops' OPTION element
// you don't need to select the option to get its text so this loop should be much faster
// it selects the OPTION once the correct one is found
for (WebElement option : verificaOpt.getOptions())
{
if (valDesejado.equalsIgnoreCase(option.getText()))
{
verificaOpt.selectByVisibleText(option.getText()); // select the OPTION match
variavelVerificadora1 = true; // set the boolean to true to indicate we found a match
break; // exits the for loop
}
}
if (!variavelVerificadora1) // this is the equivalent of variavelVerificadora1 == false, it's basically saying if not true
{
System.out.println("ALERTA: The Option" + valDesejado + " no comboBox \"tipoDePromocaoPromocao\" not found.");
}
Related
I am getting ~20'000 rows out of a database with JDBC in Java, Eclipse IDE.
I go through the result set step by step (ordered by id). Every row contains information about its previous and succeeding "identifier" (unique string of a row). So for every row I check if the chain is broken or not, b/c of whatever reason.
My approach beneath works, and don't quote me on that, but it seems it works better for the first 10'000 than for the following. Error quota is 335 for 19'999 entries. I checked with my own eyes if the reported errors are in accordance with reality, but they are definitely not, at least for 1 error.
Do I miss something important? Why does this happen? It almost looks like it is the result of parallelization, multithreading, etc.?
int i = 0;
String actualprevious = "", previous = "", next = "";
boolean first = true; // we can't check if the first is in line because it is the first
int errors = 0;
while (rs.next())
{
if (i%10000==0) { System.out.println("Checked "+(i/10000)+" myriads."); } // inform
String current = rs.getString("identifier");
if (!current.equals(next)) { System.out.println("Current is: "+current); System.out.println("Expected "+next+" to be next, but "+current+" is."); errors++; } // inform
// ignore: Document doc = Jsoup.parse(rs.getString("source"));
next = rs.getString("next");
if (next==null) { System.out.println("There is no next listed in row "+current+"."); errors++; } // inform
previous = rs.getString("previous");
if (!first && !actualprevious.equals(previous)) { System.out.println("Expected "+actualprevious+" to be listed as previous, but "+previous+" was in document "+current+"."); errors++; } // inform
actualprevious = current;
i++;
first = false;
}
I need to create a method which checks each element in my array to see if it is true or false, each element holds several values such as mass, formula, area etc for one compound, and in total there are 30 compounds (so the array has 30 elements). I need an algorithm to ask if mass < 50 and area > 5 = true .
My properties class looks like:
public void addProperty (Properties pro )
{
if (listSize >=listlength)
{
listlength = 2 * listlength;
TheProperties [] newList = new TheProperties [listlength];
System.arraycopy (proList, 0, newList, 0, proList.length);
proList = newList;
}
//add new property object in the next position
proList[listSize] = pro;
listSize++;
}
public int getSize()
{
return listSize;
}
//returns properties at a paticular position in list numbered from 0
public TheProperties getProperties (int pos)
{
return proList[pos];
}
}
and after using my getters/setters from TheProperties I put all the information in the array using the following;
TheProperties tp = new properties();
string i = tp.getMass();
String y = tp.getArea();
//etc
theList.addProperty(tp);
I then used the following to save an output of the file;
StringBuilder builder = new StringBuilder();
for (int i=0; i<theList.getSize(); i++)
{
if(theList.getProperties(i).getFormatted() != null)
{
builder.append(theList.getProperties(i).getFormatted());
builder.append("\n");
}
}
SaveFile sf = new SaveFile(this, builder.toString());
I just cant work out how to interrogate each compound individually for whether they reach the value or not, reading a file in and having a value for each one which then gets saved has worked, and I can write an if statement for the requirements to check against, but how to actually check the elements for each compound match the requirements? I am trying to word this best I can, I am still working on my fairly poor java skills.
Not entirely sure what you are after, I found your description quite hard to understand, but if you want to see if the mass is less than 50 and the area is greater than 5, a simple if statement, like so, will do.
if (tp.getMass() < 50 && tp.getArea() > 5) {}
Although, you will again, have to instantiate tp and ensure it has been given its attributes through some sort of constructor.
Lots of ways to do this, which makes it hard to answer.
You could check at creation time, and just not even add the invalid ones to the list. That would mean you only have to loop once.
If you just want to save the output to the file, and not do anything else, I suggest you combine the reading and writing into one function.
Open up the read and the write file
while(read from file){
check value is ok
write to file
}
close both files
The advantage of doing it this way are:
You only loop through once, not three times, so it is faster
You never have to store the whole list in memory, so you can handle really large files, with thousands of elements.
In case the requirements changes, you can write method that uses Predicate<T>, which is a FunctionalInterface designed for such cases (functionalInterfaces was introduced in Java 8):
// check each element of the list by custom condition (predicate)
public static void checkProperties(TheList list, Predicate<TheProperties> criteria) {
for (int i=0; i < list.getSize(); i++) {
TheProperties tp = list.get(i);
if (!criteria.apply(tp)) {
throw new IllegalArgumentException(
"TheProperty at index " + i + " does not meet the specified criteria");
}
}
}
If you want to check if mass < 50 and area > 5, you would write:
checkProperties(theList, new Predicate<TheProperties> () {
#Override
public boolean apply(TheProperties tp) {
return tp.getMass() < 50 && tp.getArea() > 5;
}
}
This can be shortened by using lambda expression:
checkProperties(theList, (TheProperties tp) -> {
return tp.getMass() < 50 && tp.getArea() > 5;
});
I am making a simple app where you have to toggle buttons/booleans trying to guess the correct combination. I was wondering the simplest way to compare the toggles booleans against the "right" combination. For example if user has:
boolean 1: true
boolean 2: false
Boolean 3: true
but the correct combination is:
boolean 1: true
boolean 2: true
Boolean 3: true
I want the user to see a message that says you have 2 out of 3 correct. I have
public void go(View view){
if (bool1 == true && boo12 == true && bool3 == true) {
// do this
} else {
// display the correct amount of booleans the user has correct.
}
}
Create a BitSet for the correct combination (set the bits that correspond to "true", clear the bits that correspond to "false").
When you want to check the user's input, create a BitSet from the buttons that are pressed (set "true", clear "false").
Correctness can be checked with correctValue.equals(usersAttempt).
A count can be obtained by doing usersAttempt.xor(correctValue) then usersAttempt.cardinality() will return the number of incorrect values.
This requires a bare minimal amount of coding. For your example:
// Correct: [true,true,true]
BitSet correct = new BitSet(3);
correct.set(0); // <= true
correct.set(1); // <= true
correct.set(2); // <= true
// User's attempt (buttonN.isChecked() is just placeholder, drop in whatever
// code you actually use to get the state of your buttons):
BitSet attempt = new BitSet(3);
attempt.set(0, button0.isChecked()); // <= true in your example
attempt.set(1, button1.isChecked()); // <= false in your example
attempt.set(2, button2.isChecked()); // <= true in your example
// Check answer (produces false in your example):
boolean matchIsPerfect = attempt.equals(correct);
// Get the count (produces 1 in your example):
attempt.xor(correct);
int incorrectCount = attempt.cardinality();
// To get the correct count just subtract 'incorrectCount' from total.
// Another way to check if attempt is correct is 'if (incorrectCount == 0)'.
// Note that the remaining bits set in 'attempt' after the above xor()
// will correspond to the individual inputs that weren't correct.
This will let you support any size, the code is clear and you don't need to do any of the logic on your own. Note that you can simplify the button -> user's attempt setup if you have an array of buttons or can access user input given an index.
If the conditions are not always to be true, say bool3 needs to be false, you can use something like this maybe. Otherwise, as the other answers mentioned, an array would work best probably.
int correctCount = 0;
if (bool1) correctCount++;
if (bool2) correctCount++;
if (!bool3) correctCount++;
if (correctCount == 3) {
// do this
} else {
Toast.makeText(context, String.valueOf(correctCount) + " out of 3 correct", Toast.LENGTH_LONG).show();
}
Assuming that your "right" combination will include both true and false values, the following method will return the number of matches, or -1 if the array lengths don't match:
private int getMatches(boolean[] toggleValues, boolean[] matchPattern)
{
if(toggleValues.length != matchPattern.length)
return -1;
int matches = 0;
for (int j = 0; j < toggleValues.length; j++)
{
if(toggleValues[j] == matchPattern[j])
{
matches++;
}
}
return matches;
}
As an example, if you have 3 ToggleButtons, tb1, tb2, and tb3, the following will return 2:
tb1.setChecked(true);
tb2.setChecked(false);
tb3.setChecked(false);
final boolean[] matchPattern = {true, false, true};
final boolean[] toggleValues = {tb1.isChecked(), tb2.isChecked(), tb3.isChecked()};
int matches = getMatches(toggleValues, matchPattern);
This method will allow you to easily change the matching pattern without changing code, e.g by reading stored values into the matchPattern array from a file or SharedPreferences.
you can do it, as the number of boolean values can be more than 3. you may want to use for loop (easy way) and iterate it for the end of the value and return the number of counts to the value k. here k-> number of true boolean values and b is an array containing the array of boolean values.
public void go(View view){
boolean b[]={bool1,bool2,bool3,bool4,bool5,bool6,bool7,bool8,bool9,bool10};
int k=0;
for(int i=0;i<b.length;i++)
{
if(b[i]==true)
{
k++;
}
}
if(k==b.length)
{
do task
}
else
{
Toast.makeText(getApplicationContext(), k+ "out of "+b.length+ "correct",Toast.LENGTH_LONG).show();
}
}
I'm attempting to use DOCX4J to parse and insert content into a template. As part of this template I have loops which I need to copy everything inbetween two markers, and repeat all that content X times.
The relavant code is as follows:
public List<Object> getBetweenLoop(String name){
String startTag = this.tag_start + name + "_LOOP" + this.tag_end;
String endTag = this.tag_start + name + this.tag_end;
P begin_loop = this.getTagParagraph(startTag);
P end_loop = this.getTagParagraph(endTag);
ContentAccessor parent = (ContentAccessor) this.getCommonParent(begin_loop, end_loop);
List<Object> loop = new ArrayList<Object>();
boolean save = false;
//Cycle through the content for the parent and copy all the objects that
//are between and including the start and end-tags
for(Object item : parent.getContent()){
if(item.equals(begin_loop) || item.equals(end_loop))
save = (save) ? false : true;
if(save || item.equals(end_loop)){
loop.add(XmlUtils.deepCopy(item));
}
if(item.equals(end_loop)){
//Here I want to insert everything copied X times after the current item and then exit the for loop.
//This is the part I'm not sure how to do since I don't see any methods "Insert Child", etc.
}
}
return loop;
}
getTagParagraph successfully returns the object representing the paragraph for the tag sent. This works beautifully.
getCommonParent returns the shared parent between the two supplied tags. This works beautifully.
My problem is, as commented, how to insert the newly copied items into the appropriate place.
If you're looking to insert all the objects you have stored in your loop collection, you simply need to do something like this (in the conditional you've commented):
item.getContent().addAll(loop);
item represents the end_loop object (a paragraph or whatever), and inserts all the objects you've collected into the loop collection. (addAll may require an int argument too, I can't recall, but if it does that's just the desired index within the overall MainDocumentPart.getContent() JAXB document representation).
#Ben, thank-you!
If you know of any instances where below wouldn't work, please let me know.
I had actually just figured out something very similar, but ended up changing a lot more code. Below is what I put together.
public void repeatLoop(String startTag, String endTag, Integer iterations){
P begin_loop = this.getTagParagraph(startTag);
P end_loop = this.getTagParagraph(endTag);
ContentAccessor parent = (ContentAccessor) this.getCommonParent(begin_loop, end_loop);
List<Object> content = parent.getContent();
Integer begin_pointer = content.indexOf(begin_loop);
Integer end_pointer = content.indexOf(end_loop);
List<Object> loop = new ArrayList<Object>();
for(int x=begin_pointer; x <= end_pointer; x = x + 1){
loop.add(XmlUtils.deepCopy(content.get(x)));
}
Integer insert = end_pointer + 1;
for(int z = 1; z < iterations; z = z + 1){
content.addAll(insert, loop);
insert = insert + loop.size();
}
}
I'm trying to find an appropriate ExpectedConditions method for this situation. I have a chart and I want to check the text in each row after re-sorting the chart. Problem is, when the chart is refreshing, the text still exists, it's just greyed out. So when I click a button to get the chart to be re-sorted, then look for the text that I'm looking for right away, the test fails because the text hasn't changed yet. I can't use visibilityOfElementLocated because the element is still visible when the chart is refreshing, I'm just waiting for the element to change.
Not sure if any of that makes sense!! It is a really difficult issue to explain.
A little background: I'm using Selenium Java and testing using Chrome. Here is my method thus far. It works fine, I just need to figure out how to make the program wait long enough for the chart to refresh WITHOUT using a sleep statement.
Thanks a bunch everyone! I know that wasn't as clear as it could be, but please let me know if you need any clarification.
public void Check_for_text_in_column(String text, String row, String column)
{
By by = By.xpath("//*[#id=\"table_Table_table_ktg\"]/tbody/tr[" + row + "]/td[" + column + "]/div/div/span");
WebDriverWait wait = new WebDriverWait(getWebDriver(), WAIT_TIME);
//This is the line that I need to change:
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));
if(!element.getText().equals(text))
{
fail("\nDid not find text: " + text + "\nFound text: " + element.getText() + "\n");
}
}
Cheers!
You can replace
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));
with
WebElement element = wait.until(ExpectedConditions.textToBePresentInElement(by, text));
EDIT:
Your WAIT_TIME is the timeout for your wait.
If the expected condition hasn't returned true before timing out according to your WAIT_TIME, then element will be null.
So, your check could look something like this:
if(element == null)
{
fail("\nDid not find text: " + text + "\nFound text: " + element.getText() + "\n");
}
EDIT:
Perhaps another option could be something like this:
public void Check_for_text_in_column(String text, String row, String column)
{
By by = By.xpath("//*[#id=\"table_Table_table_ktg\"]/tbody/tr[" + row + "]/td[" + column + "]/div/div/span");
WebDriverWait wait = new WebDriverWait(getWebDriver(), WAIT_TIME);
// your original find
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));
// flag to set when text is found, for exiting loop
boolean hasText = false;
// counter for # of times to loop, finally timing out
int tries = 0;
// until text is found or loop has executed however many times...
while (hasText == false && tries < 20) {
// get the element
element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));
// if text is not present, wait 250 millis before trying again
if(!element.getText().equals(text){
Thread.sleep(250);
tries++;
}
else{
// text found, so set flag to exit loop
hasText = true;
}
}
if(!element.getText().equals(text))
{
fail("\nDid not find text: " + text + "\nFound text: " + element.getText() + "\n");
}
}
I know you said you don't want sleep statements, but I assume you meant that you just don't want a single unnecessarily long one. Even ExpectedConditions are using sleep internally. They sleep for a few milliseconds between polling for changes - and that's exactly what this does, just without the ExpectedCondition type wrapper.