Page 1 of 1

Repeat a handler until time limit expires

Posted: Mon Oct 01, 2012 7:21 am
by PoLyGLoT
Hi all,

What is the best way to repeatedly summon a specific handler until a given length of time expires? I'm creating a program wherein I want a specific card to remain open for *up to* 8 seconds OR until they click a button to proceed. In other words, the card opens and remains fully open for up to 8 seconds, but if participants want to selectively advance they can press a button.

One of the major problems I'm having is that I need the handler to repeatedly check the elapsed time. If the time has not expired, then I need the exact same handler to run again. In this manner, the handler will once again check the time. If the time has still not expired, then I need the exact same handler to run again, etc. until the time has elapsed. If, during the course of the handler repeatedly running, I need the button which is clicked to tell the handler to STOP running.

The major issue is that repeatedly running a handler gives me a recursion limit reached error.

Here is some code to facilitate discussion:

Code: Select all

on keeptrack6
   global matlist1,testtemp,howlong,whichitem,timeoutRT,session,recall,numtrials,tempanswer,data,stopkeeptrack6,matlist2,matlist3,matlist4,matlist5,matlist6,subID,testtemp,matlist,dropstatus,matlists,stopkeeptrack7,firstkey,writetime,lagcond,checktime
   if stopkeeptrack6 is false then  --K
      put (the ticks - timeoutRT) into checktime
      if session = 1 then --a
         put 480 into howlong
      else
         put 3600 into howlong
      end if  --a
      if checktime > howlong then -- 8 seconds --A
         if firstkey is true then  --b
            put ((the ticks - writetime)/60) & "," after data
            put "no" & "," after data 
         end if  --b
         put cd fld "recall"  & "," after data
         put cd fld "recall"  into tempanswer
         put empty into cd fld "recall" 
         show cd fld "hide recall" 
         hide cd fld "hide definition" 
         hide cd fld "recall instructions"  
         hide cd fld "study instructions" 
         put item 2 of line 1 of testtemp into whichitem # item num
         if (char 1 to 4 of item 1 of line 1 of tempanswer) = (char 1 to 4 of item 4 of line 1 of testtemp) then --Y  ---> Answer Correct
            add 1 to line whichitem of cd fld "dropstatus" of cd "main task materials"
            if line whichitem of cd fld "dropstatus" of cd "main task materials" < item 5 of line 1 of testtemp then  --X  --> Answer correct, not reached criterion yet
               put return & line 1 of testtemp after matlist1
               opencard
            else  --X   --> Answer correct and reached criterion
               go to cd "confidence"
            end if --X
         else  --if answer is incorrect Y
            put return & line 1 of testtemp after matlist1
            show cd fld "hide recall" 
            hide cd fld "hide definition" 
            hide cd fld "recall instructions" 
            hide cd fld "study instructions" 
            hide button "done with recall" 
            hide cd fld "recall instructions2" 
            wait 30 ticks
            opencard
         end if  --Y
      else #time limit not reached on test trial  --A
         keeptrack6
      end if  --A
   end if  --K
end keeptrack6
I very much hope you can help me!

Thanks in advance.

Re: Repeat a handler until time limit expires

Posted: Mon Oct 01, 2012 10:02 am
by Mark
Hi,

Here's a simple example:

Code: Select all

constant kMilliSecs = 20000 // 20 seconds
constant kDelay = 200 // millisecs
local lAbsTimeLimit

on doUntilTimeLimit
  if lAbsTimeLimit is empty then put the millisecs + kMilliSecs into lAbsTimeLimit
  if the millisecs > lAbsTimeLimit then
    beep
    answer "Finished!"
  else
    put (lAbsTimeLimit - the millisecs)/1000 && "seconds to go" // into msg box
    send "doUntilTimeLimit" to me in kDelay millisecs
  end if
end doUntilTimeLimit
You can change the constants to keep the script running for a longer time or to abort it earlier and to run it less or more frequently during the given time.

Kind regards,

Mark

Re: Repeat a handler until time limit expires

Posted: Mon Oct 01, 2012 7:33 pm
by PoLyGLoT
Thanks for the advice. I have an additional question: Let's say I'm on handler A. The last bit of code executes handler B. Handler B will keep repeating itself until 8 seconds has elapsed. However, handler C can be activated via a mouse click. I want to make it so that handler C *automatically terminates* the running of handler B.

Functionally, handler C = handler B. They both do similar things. The kicker is that I only need the script in both handlers to execute 1 time (either handler B or handler C; but not both).

Is there a command which will automatically stop handler B once handler C is activated?

Thanks,

PoLy

Re: Repeat a handler until time limit expires

Posted: Tue Oct 02, 2012 2:47 am
by dunbarx
Hi.

I made a button named "doStuff", and another named "terminate". I put this in the "dostuff" script:

Code: Select all

on mouseUp
--doYourStuff
   put the seconds + 8 into tSecs
   set the doRun of this card to "run"
   callHandlerB tSecs
end mouseUp
This in the "terminate" script:

Code: Select all

on mouseUp
  set the doRun of this card to ""
end mouseUp
in the card acript:

Code: Select all

on callHandlerB tSecs
   put random(99)
   if the doRun of me <> "run" then  exit to top
   if tSecs > the seconds then send "callHandlerB" && tSecs to me in 0 millisecs
end callHandlerB
Interestingly, I tried to do this purely by passing parameters instead of setting a custom property. I am having trouble with that. The code works fine if I step through it,but will not work if I just run it. Watch this space.

Craig Newman

Re: Repeat a handler until time limit expires

Posted: Tue Oct 02, 2012 2:26 pm
by Mark
Hi Poly,

Here's an example, which does what you ask. Create a new button and enter the script below.

Code: Select all

constant kDelay = 200
local lStartStopFlag

on mouseUp
     handlerA
end mouseUp

on handlerA
     if the optionKey is down then
          // full stop
          put the pendingMessages into myMessages
          if "handlerB" is in myMessages  or "handlerC" is in myMessages then
               repeat for each line myMsg in myMessages
                    if myMsg contains "handlerB" or myMsg contains "handlerC" then cancel item 1 of myMsg
               end repeat
               put empty into lStartStopFlag
               put empty
          end if
     else
          if lStartStopFlag is not false then
               put false into lStartStopFlag
               handlerB
          else
               put true into lStartStopFlag
               handlerC
          end if
     end if
end handlerA

on handlerB
     // stop handlerC after the user clicks on this button
     put the pendingMessages into myMessages
     if "handlerC" is in myMessages then
          repeat for each line myMsg in myMessages
               if myMsg contains "handlerC" then cancel item 1 of myMsg
          end repeat
     end if
     if lStartStopFlag is false then
          // do something here, e.g. put the seconds
          put the seconds & cr & lStartStopFlag & cr & "HandlerB"
          send "handlerB" to me in kDelay millisecs
     end if
end handlerB

on handlerC
     // stop handlerB
     // stop handlerB after the user clicks on this button
     put the pendingMessages into myMessages
     if "handlerB" is in myMessages then
          repeat for each line myMsg in myMessages
               if myMsg contains "handlerB" then cancel item 1 of myMsg
          end repeat
     end if
     if lStartStopFlag is true then
          // do something here, e.g. put the seconds
          put the seconds & cr & lStartStopFlag & cr & "HandlerC"
          send "handlerC" to me in kDelay millisecs
     end if
end handlerC
Kind regards,

Mark