[HowTo] Wait for images in 2 regions at same time

Asked by Randy

Sorry if this question seemed dumb and have been answered before. When it comes to scripts i have little to no knowledge. My english is poor so if my question is unclear i'd try to clearify. Many thanks for helping

Say i have 2 programs running simultaneously in 2 regions A&B and would like to write a script that would run on whichever region the image appears on FIRST. For eg, If image appears on A FIRST ignore B and run script etc.

Thank you

Question information

Language:
English Edit question
Status:
Solved
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Solved by:
RaiMan
Solved:
Last query:
Last reply:
Revision history for this message
RaiMan (raimund-hocke) said :
#1

regA = Region(x,y,w,h) # to be specified or evaluated somehow
regB = Region(x,y,w,h) # to be specified or evaluated somehow
img = "the image you are waiting for.png"

isRegA = False
while True:
    if regA.exists(img, 0):
        isRegA = True
        break # appeared in region A
    if regB.exists(img, 0):
        break # appeared in region B
    wait(1) # wait 1 second and try again
if isRegA:
    print "running script for A"
else:
    print "running script for B"

Since each find with exists(img,0) in a region should cost max 0.5 seconds, with this construct, search in regA starts about every 2 seconds. If img appears within search time in region B before image appears in region A, region A will win.

Alternatively you might use the observe() feature, but it is more complex (look docs: http://sikuli.org/docx/region.html#observing-visual-events-in-a-region)

Revision history for this message
Randy (rchok2) said :
#2

Is it correct? because it just pops right out after a few seconds without any error. I'm still lost

regA = False
while True:
    if regA.exists(img A):
        regA = True
        break
    if regB.exists(img B):
        break
    wait(5)
if regA:
    sleep
else:
    if regC.exists(img B):
         click(img B)
    else:
         click(img C)
         .waitVanish( )

Revision history for this message
RaiMan (raimund-hocke) said :
#3

this should work (made some corrections):

regA = False
while True:
    if regA.exists("imgA.png"):
        regA = True
        break
    if regB.exists("imgB.png"):
        break
    wait(5)
if regA:
    wait(10) # sleep is deprecated and needs a time in seconds
else:
    if regC.exists("imgB.png"):
         click(regC.getLastMatch()) # to avoid another find operation
    else:
         click("imgC.png")
         waitVanish("someImg.png", a_time_in_seconds )

I used "imgX.png", because this is how it is shown in the Python code. In the IDE these strings are represented by the image thumbnails.

I suppose, that regA, regB and Regc are defined properly.

Revision history for this message
Randy (rchok2) said :
#4

Thanks RaiMan for your time

I still encounter some problem, apparently the script only run regA and not regB even when imgB appears on regB. Wonder if i miss something here. Because i meant to get

[if regB.exists("imgB.png"):] part to run [if regC.exists("imgB.png")....]

Also how do i get this whole script to loop because it just pops right out after running regA a single time.

Thank you

Revision history for this message
RaiMan (raimund-hocke) said :
#5

Sorry, but this script now is complete rubbish.

regA, regB, imgA, imgB, isRegA, isRegB are variables, that have to be taken as is!
I am taking my first version and add the option, that we check for both images always and loop

regA = Region(x,y,w,h) # to be specified or evaluated somehow
regB = Region(x,y,w,h) # to be specified or evaluated somehow
imgA = "the captured image A you are waiting for.png" # here you should see the thumbnail!
imgB = "the captured image B you are waiting for.png"

while True: # now it loops for ever
    isRegA = False
    isRegB = False
    while True:
        if regA.exists(imgA, 0): isRegA = True
        if regB.exists(imgB, 0): isRegB = True
        if isRegA or isRegB: break # one or both images appeared
        wait(5)

    if isRegA:
        print "running script for A"
    elif isRegB:
        print "running script for B"
    else:
        print "should never happen"
# this is the end of the main loop

To stop the loop, you have to either kill the IDE, or have somewhere in the loop a statement like

if some_condition == True: break

Revision history for this message
Randy (rchok2) said :
#6

Sorry again i think my problem is much simpler than it looks, sorry for the trouble i think i got it to work by this

while True:
   if regA.exists(imgA ):
      print "script for regA"
   if not regA.exists(imgA):
      print "script for regB"
      wait(5)

It seems like the "exists" command on scans it every few seconds i need it to continually "observe" so as long as the imgA exists script for regB doesnt run but unsure how to use to observe command when i replace exists with observe it gives an error "TypeError: observe(): 1st arg can't be coerced to double"

Revision history for this message
Best RaiMan (raimund-hocke) said :
#7

Excuse me, if I am wrong, but it seems, that you do not really understand, what is happening here.
... and you do not really use my suggestions :-(

You need some understanding of scripting generally and Python basics.

I explain your snippet, hoping you understand that it is not really doing something of value and hoping you try to understand, what my suggested script from comment #5.

- a line beginning with a # is a comment in Python
- on a line containing a statement, text after # is comment
- I put comments in your code and refer to them in the following comments

The most basic thing in Python is to understand indenting, which is Pythons feature to form a block of statements: all consecutive statements with the exactly the same indentation form a block. blocks can be nested.

while True: # loop
   # loop block start
   # if
   if regA.exists(imgA): # exists 1
      # if block start
      print "script for regA"
      # if block end
   if not regA.exists(imgA): #exists 2
      # if block start
      print "script for regB"
      wait(5) # wait
      # if block end
   # loop block end

the comments:

-- # loop
while True: is the simplest construct, to say, that the following block (the statements between # loop block start and # loop block start) should be repeated forever.
You can replace True by any expression that evaluates to False or True. In this case the loop will run as long the condition evaluates to True.

-- # if
generally

if condition:
    pass # processed if condition evaluates to True
else:
    pass # processed if condition evaluates to False

pass is Python and means "do nothing", but it assures indentation for correct syntax.

since Python does not have a case statement, you can use intermediate elif's:

if condition:
    pass # processed if condition evaluates to True
elif condition1:
    pass # processed if condition1 evaluates to True
elif condition2:
    pass # processed if condition2 evaluates to True
# more elif's possible
else:
    pass # processed if all of the above conditions evaluate to False

-- # exists 1
regA.exists(imgA) repeatedly searches for image imgA in region regA until found or the standard waiting time of 3 seconds elapses. returns True if found, otherwise False.
That it makes sense, to use exists() in decisions like yours, it makes sense to use the option, that exists returns after the first try to find the image (usually earlier than 0.5 seconds).
So I recommend to use:
if regA.exists(imgA, 0):

-- #exists 2
here you start a subsequent search for thee same thing as before with # exists 1. But now you state, that if the imgA is not found within 3 seconds, then we have a situation "script for regB". I doubt that this makes any sense, since you do not know here the situation in regB.

If it would make sense, it should read:

  if regA.exists(imgA): # exists 1
      # if block start
      print "script for regA"
      # if block end
  else:
      # else block start
      print "script for regB"
      wait(5) # wait
      # else block end

# wait
the position of the wait(5) leads to that it is only processed, when imgA is not found. If imgA is found, the loop instantly starts all over again.

--- So I hope with this you might have a chance to understand my suggestion

regA = Region(x,y,w,h) # to be specified or evaluated somehow
regB = Region(x,y,w,h) # to be specified or evaluated somehow
imgA = "the captured image A you are waiting for.png" # here you should see the thumbnail!
imgB = "the captured image B you are waiting for.png"

while True: # this loops for ever
    # loop 1
    isRegA = False
    isRegB = False
    while True:
        # loop 1
        # look for imgA, set isRegA to True if found
        if regA.exists(imgA, 0): isRegA = True
        # look for imgB, set isRegB to True if found
        if regB.exists(imgB, 0): isRegB = True
        # check isRegA and isRegB
        # if one of it is True, leave the loop
        if isRegA or isRegB: break # one or both images appeared
        wait(5) # wait 5 seconds and start over again at # loop 2

    # loop 1 has ended, we check the result
    if isRegA: # imgA was found if isRegA is True
        print "running script for A"
    elif isRegB: # imgB was found if isRegB is True
        print "running script for B"
    else:
        # this should never be printed, since loop 2 is only left,
        # if either imgA or imgB is found
        print "should never happen"
    # we start over at # loop 1

# this is the end of the main loop (# loop 1)
print "this will not be printed, since we never come here - loop 1 is forever"

Revision history for this message
Randy (rchok2) said :
#8

Thanks Raiman for the input and most detailed explaination. I perfectly understood now. Appreciate the time uve put in to explain this to me. Sorry for being a dummy in the first place

Revision history for this message
Randy (rchok2) said :
#9

Thanks RaiMan, that solved my question.