I have a task where I am trying to check an array list of "jobs" against an array list of "machines" (all different types) and if the first three letters off the job match the first three letters off the machine (e.g. a PRT job code could only be assigned to a machine with code PRT). I want it to accept the job but if not I would like it to print out a message saying that there is no available machine. I have only been learning Java for a couple of weeks so this might not be the best way:
public void assignJob() {
for(Job j : jobs) {
String jobCode = j.getCode().substring(0, 3);
for(Machine m : machines) {
String machineCode = m.getCode().substring(0,3);
if (jobCode.equals(machineCode)){
m.acceptJob(j);
System.out.println("The job " + j.getCode() + " has been
assigned to a machine.");
break;
}
else {
System.out.println("Sorry there is no machine available to accept the type of job: " + j.getCode() );
}
}
}
}
The issue I am getting is that it is printing out the message every time it goes around the loop so it will say there is no machine available 3 times before it finds the correct machine the fourth time and then says the job has been accepted. I only really want the message one time and only after it has searched and not found anything.
Any help would be appreciated.
Use a boolean found = false; above the outer for loop, move else part of if statement below the outer for loop and make it an if statement. If you've found your match then set found = true; and break loops. Then check if it is found, display message if not found...
Related
I'm using tdbc::odbc to connect to a Pervasive (btrieve type) database, and am unable to pass variables to the driver. A short test snippet:
set customer "100000"
set st [pvdb prepare {
INSERT INTO CUSTOMER_TEMP_EMPTY
SELECT * FROM CUSTOMER_MASTER
WHERE CUSTOMER = :customer
}]
$st execute
This returns:
[Pervasive][ODBC Client Interface]Parameter number out of range.
(binding the 'customer' parameter)
Works fine if I replace :customer with "100000", and I have tried using a variable with $, #, wrapping in apostrophes, quotes, braces. I believe that tdbc::tokenize is the answer I'm looking for, but the man page gives no useful information on its use. I've experimented with tokenize with no progress at all. Can anyone comment on this?
The tdbc::tokenize command is a helper for writing TDBC drivers. It's used for working out what bound variables are inside an SQL string so the binding map can be supplied to the low level driver or, in the case of particularly stupid drivers, string substitutions performed (I hope there's no drivers that need to do this; it'd be annoyingly difficult to get right). The parser knows enough to handle weird cases like things that look like bound variables in strings and comments (those aren't bound variables).
If we feed it (it's calling syntax is trivial) the example SQL you've got, we get this result:
{
INSERT INTO CUSTOMER_TEMP_EMPTY
SELECT * FROM CUSTOMER_MASTER
WHERE CUSTOMER = } :customer {
}
That's a list of three items (the last element just has a newline in it) that simplifies processing a lot; each item is either trivially a bound variable or trivially not.
Other examples (bear in mind in the second case that bound variables may also start with $ or #):
% tdbc::tokenize {':abc' = :abc = ":abc" -- :abc}
{':abc' = } :abc { = ":abc" -- :abc}
% tdbc::tokenize {foo + $bar - #grill}
{foo + } {$bar} { - } #grill
% tdbc::tokenize {foo + :bar + [:grill]}
{foo + } :bar { + [:grill]}
Note that the tokenizer does not fully understand SQL! It makes no attempt to parse the other bits; it's just looking for what is a bound variable.
I've no idea what use the tokenizer could be to you if you're not writing a DB driver.
Still could not get the driver to accept the variable, but looking at your first example of the tokenized return, I came up with:
set customer "100000"
set v [tdbc::tokenize "$customer"]
set query "INSERT INTO CUSTOMER_TEMP_EMPTY SELECT * FROM CUSTOMER_MASTER WHERE CUSTOMER = $v"
set st [pvdb prepare $query]
$st execute
as a test command, and it did indeed successfully pass the command through the driver
I've been researching hours without success
I just need the syntax for Autohotkey to get the size of a table rows/column
I am following this guide https://www.guru99.com/handling-dynamic-selenium-webdriver.html
In other languages they suggest this:
WebElement tbody = driver.findElement(By.xpath("//div[#class='z-listbox-body']/table/tbody"));
List<WebElement> rows = tbody.findElements(By.xpath("tr"));
totalrows = rows.size();
Note that they use the "List" to convert into a List type the variable, the problem is, that in AHK there is no variable type definition, it should be automatically, but apparently not in this case
This is the page I am doing test on, but can't get it to work
http://demo.guru99.com/test/web-table-element.php#
I just need to know how many rows and/or columns it has, it should be as simple as this:
MsgBox % "" oChrome.findElementByXpath("//*[#id='leftcontainer']/table/thead/tr/th").size()
(Gives no error but doesnt show any value)
Or even this, like there they suggested (How to get the total number of elements in a HTML with Selenium WebDriver and Autohotkey?)
MsgBox % "" oChrome.findElementByXpath("//*[#id='leftcontainer']/table/thead/tr/th").Count()
(Error: Unknown Name, Specifically: Count)
The goals is to have the number of columns (in this case 5) and Rows (26), this, in order to further fo a For Each and loop through the values of each row
I would appreciate any kinds of suggestions, thanks!
Full Code
oChrome := ChromeGet() ; Object for Chrome
MsgBox % "" oChrome.findElementByXpath("//*[#id='leftcontainer']/table/thead/tr/th").Size() ; FAIL
MsgBox % "Finish"
return
ChromeGet(IP_Port := "127.0.0.1:9222") {
oChrome := ComObjCreate("Selenium.ChromeDriver")
oChrome.SetCapability("debuggerAddress", IP_Port)
oChrome.Start()
return oChrome
}
Ahh, so, after days of research, I noted a a little bigger thing, I needed to use:
.findElementsByXpath()
Instead of:
.findElementByXpath()
I noticed tht when looking in this Selenium documentarion for Python:
https://selenium-python.readthedocs.io/locating-elements.html
Which made me thing on that extra "s" on it, and so, it was that! and also I used Count().
And it falls in a simple logic (and common sense now I realize), findElementsByXpath(), as the docs said, search for multiple element values, not just one, that way you are allowed to use the ".Count()" to search for the total of children in a node for example
So, the end code working for me is the following:
oChrome := ChromeGet() ; Object for Chrome
MsgBox % "" oChrome.findElementsByXpath("//*[#id='leftcontainer']/table/thead/tr/th").Count()
MsgBox % "Finish"
return
ChromeGet(IP_Port := "127.0.0.1:9222") {
oChrome := ComObjCreate("Selenium.ChromeDriver")
oChrome.SetCapability("debuggerAddress", IP_Port)
oChrome.Start()
return oChrome
}
I'm using late acceptance as local search algorithm and here is how it actually picks moves:
If my forager is 5, it'll pick 5 moves and then get 1 random move to be applied for every step.
At every step it only picks moves that are increasing scores ie greedy picking across steps.
Forager.pickMove()
public LocalSearchMoveScope pickMove(LocalSearchStepScope stepScope) {
stepScope.setSelectedMoveCount(selectedMoveCount);
stepScope.setAcceptedMoveCount(acceptedMoveCount);
if (earlyPickedMoveScope != null) {
return earlyPickedMoveScope;
}
List<LocalSearchMoveScope> finalistList = finalistPodium.getFinalistList();
if (finalistList.isEmpty()) {
return null;
}
if (finalistList.size() == 1 || !breakTieRandomly) {
return finalistList.get(0);
}
int randomIndex = stepScope.getWorkingRandom().nextInt(finalistList.size());// should have checked for best here
return finalistList.get(randomIndex);
}
I have two questions:
In first, can we make forager to pick the best of 5 instead of pick 1 randomly.
Can we allow move to pick that degrades score but can increase score later(no way to know it)?
Look for acceptedCountLimit and selectedCountLimit in the docs. Those do exactly that.
That's already the case (especially with Late Acceptance and Simulated Annealing). In the DEBUG log, just look at the step score vs the best score. Or ask for the step score statistic in optaplanner-benchmark.
Trying to wrap my head around zoho creator, its not as simple as they make it out to be for building apps… I have an inventory database, and i have four fields that I call to fill a field called Inventory Number (Inv_Num1) –
First Name (First_Name)
Last Name (Last_Name)
Year (Year)
Number (Number)
I have a Custom Function script that I call through a Custom Action in the form report. What I am trying to do is upload a CSV file with 900 entries. Of course, not all of those have those values (first/last/number) so I need to bulk edit all of them. However when I do the bulk edit, the Inv_Num1 field is not updated with the new values. I use the custom action to populate the Inv_Num1 field with the values of the other 4 fields.
Heres is my script:
void onetime.UpdateInv()
{
for each Inventory_Record in Management
{
FN = Inventory_Record.First_Name.subString(0,1);
LN = Inventory_Record.Last_Name.subString(0,1);
YR = Inventory_Record.Year.subString(2,4);
NO = Inventory_Record.Number;
outputstr = FN + LN + YR + NO;
Inventory_Record.Inv_Num1 = outputstr;
}
}
I get this error back when I try to run this function
Error.
Error in executing UpdateInv workflow.
Error in executing For Each Record task.
Error in executing Set Variable task. Unable to update template variable FN.
Error evaluating STRING expression :
Even though there is a First Name for example, it still thinks there is none. This only happens on the fields I changed with Bulk Edit. If I do each one by hand, then the custom action works—but of course then the Inv_Num1 is already updated through my edit on success functions and makes the whole thing moot.
this may be one year late, you might have found the solution but just to highlight, the error u were facing was just due to the null value in first name.
you just have put a null check on each field and u r good to go.
you can generate the inv_number on the time of bulk uploading also by adding null check in the same code on and placing the code on Add> On Submt.( just the part inside the loop )
the Better option would be using a formula field, you just have to put this formula in that formula field and you'll get your inventory_number autogenerated , you can rename the formula_field to Inv Number or whaterver u want.
Since you are using substring directly in year Field, I am assuming the
year field as string.else you would have to user Year.tostring().substring(2,4) & instead of if(Year=="","",...) you have to put if(Year==null , null,...);
so here's the formula
if(First_Name=="","",First_Name.subString(0,1))+if(Last_Name =="","",Last_Name.subString(0,1)) + if(Year=="","",Year.subString(2,4)+Number
Let me know ur response if u implement this.
Without knowing the datatype its difficult to fix, but making the assumption that your Inventory_Record.number is a numeric data item you are adding a string to a number:
The "+" is used for string Concatenation - Joiner but it also adds two numbers together so think "a" + "b" = "ab" for strings but for numbers 1 + 2 = 3.
All good, but when you do "a" + 2 the system doesn't know whether to add or concatenate so gives an error.
So, I've figured out how to be able to get more than 100 tweets, thanks to How to retrieve more than 100 results using Twitter4j
However, when do I make the script stop and print stop when maximum results have been reached? For example, I set
int numberOfTweets = 512;
And, it finds just 82 tweets matching my query.
However, because of:
while (tweets.size () < numberOfTweets)
it still continues to keep on querying over and over until I max out my rate limit of 180 requests per 15 seconds.
I'm really a novice at java, so I would really appreciate if you could show me how to resolve this by modifying the first answer script at How to retrieve more than 100 results using Twitter4j
Thanks in advance!
You only need to modify things in the try{} block. One solution is to check whether the ID of the last tweet you found on the previous loop(previousLastID) in the while is the same as the ID of the last tweet (lastID) in the new batch collected (newTweets). If it is, it means the new batch's elements already exist in the previous array, and that that we have reached the end of possible tweets for this hastag.
try {
QueryResult result = twitter.search(query);
List<Status> newTweets = result.getTweets();
long previousLastID = lastID;
for (Status t: newTweets)
if (t.getId() < lastID) lastID = t.getId();
if (previousLastID == lastID) {
println("Last batch (" + tweets.size() + " tweets) was the same as first. Stopping the Gathering process");
break;
}