nback-task Array with fixed number of matches

Got a LiveCode personal license? Are you a beginner, hobbyist or educator that's new to LiveCode? This forum is the place to go for help getting started. Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4171
Joined: Sun Jan 07, 2007 9:12 pm

Re: nback-task Array with fixed number of matches

Post by bn » Sun Aug 14, 2011 9:21 am

Hi James,

I am not shure what is going on since I don't see the complete script.

Some things come to mind. In the preopencard handler you say:

Code: Select all

.....
nbacktiming
end Preopencard
this means in the preopencard handler you branch into the nbacktiming handler and the preopencard handler waits until nbacktiming is finished and then the preopencard handler finishes and the opencard message can take place. If you say instead:

Code: Select all

...
send nbacktiming to me in 10 milliseconds
end Preopencard
the preopencard handler can finish and then the nback handler is called. In the nback handler you wait 500 milliseconds. Maybe this is the 500 milliseconds you are talking about.

In the nback handler you use a lot of variables (Fehleranzahl, tOutput, xback, Antwort etc) I don't see how you initialized them since they are not local variables. Did you declare them as script local variables or global variables at the top of the script? My guess is that some of the problems stem from not initializing variables for nback.

The send nback to me in 2500 milliseconds should work. You just have to watch out that when you leave the card there might be a "nback" message pending which will probably not find the handler when you are at the next card. Look at pendingmessages.You would have to cancel that message. Example

Code: Select all

on closeCard
repeat for each line aLine in the pendingMessages
if aLine contains "nback" then cancel item 1 of aLine
end repeat
end closeCard
Did you convert my code to arrays or did you use it as is with arrays later on? BTW, I like arrays very much but in this case it felt more natural to use chunks since you work on letters. Easier to read and debug in this case.

Kind regards

Bernd

JamesWebster
Posts: 25
Joined: Sun Aug 07, 2011 11:36 am

Re: nback-task Array with fixed number of matches

Post by JamesWebster » Sun Aug 14, 2011 10:16 am

Hi Bernd
The whole code is:

Code: Select all

local tOutput
local aktuell
local totallaenge
global Fehleranzahl
local xback
local Antwort
On Preopencard
   local tAChar
   local abc
   local matches
   local tCollect
   local gematched
      put "BCDFGHJKMNPQRSTVXZ" into abc #start Values
   put 2 into xback
   put 3 into matches 
   put 9 into totallaenge
   put "" into tCollect
   put 0 into gematched
   
   -- just a little error checking, more is probably needed
   -- matches should not be more than half the length
   if matches > totalLaenge/2 then 
      answer "can not fit matches into length"
      exit Preopencard
   end if
   
   repeat until gematched = matches  -- just let the routine run until it has found a combination of matches that  matches
      
      repeat with i = 1 to totalLaenge
         -- just grab a random letter
         put char random(18) of abc after tCollect
         
         -- only test for xback if enough letters are in tCollect to compare
         if the number of chars of tCollect >xback then
            
            -- test for xback here
            if (char (length (tCollect)- xback) of tCollect = (last char of tCollect))  then
               
               -- only if matches are not yet reached mark last character as lowercase
               if  (gematched < matches) then
                  put last char of tCollect into last char of tCollect
                  add 1 to gematched
                  
               else
                  -- we don't want more xback occurences and get a new random letter that is not the one used before
                  repeat 
                     put char random(18) of abc into tAChar
                     if tAChar <> last char of tCollect then
                        put tAChar into last char of tCollect
                        -- we found a new random letter, get out of repeat loop
                        exit repeat
                     end if
                  end repeat
               end if
            end if
         end if
      end repeat
      
      if gematched < matches then -- not enough matches repeat the whole thing
         put 0 into gematched
         put "" into tCollect
      end if
      
      wait 0 milliseconds with messages -- in case the repeat loop can not finish we can interrupt it with command + period or escape
      
   end repeat
   
   -- lets put spaces between the letters
   repeat for each char aChar in tCollect
   put aChar & space after tOutPut
   end repeat
   delete last char of tOutPut -- a space
   
   put tOutPut into field id 2155
   --put gematched into field 2 -- if you want to monitor how many matches make a field
   --put xback into field 3
put 0 into aktuell
put 0 into Fehleranzahl
split tOutput with space
   nbacktiming
end Preopencard

On MouseUp
   put "match" into Antwort
end MouseUp
On MouseDoubleUp
   put "mismatch" into Antwort
end MouseDoubleUp
local x
On nbacktiming
   local durchgang
   put 1 into durchgang
   put (aktuell & "- Fehlerzahl: " & Fehleranzahl[durchgang]) into field id 2151
   If aktuell <= totallaenge then
      If Random(8) is 1 then
         put ToLower(tOutput[aktuell]) into field id 2143
      Else
         put tOutput[aktuell] into field id 2143
      end if
      #If aktuell > xback then
      #Userinput and counting of mistakes
      If aktuell > xback then
         If (tOutput[aktuell] is tOutput[aktuell-xback]) then
            If (Antwort is "mismatch") then
               Mouseup
               MouseDoubleup
               add 1 to Fehleranzahl[durchgang]
            End if
         Else
            If (Antwort is "match") then
               Mouseup
               MouseDoubleup
               add 1 to Fehleranzahl[durchgang]
            End if
         End if
         If (Antwort is "missed") then
            add 1 to Fehleranzahl[durchgang]
         End if
         put "missed" into Antwort
         
      End if

   #show the letter for 500 ms - I changed it from wait to this because I noticed/remembered there's no Userinput possible if it's wait
      put 500 into x
      bumpCounter
      If x = 0 then
      add 1 to aktuell
      put "" into field id 2143 # hide the letter
         send "nbacktiming" to me in 2500 millisec #supposed to wait for 2500 ms before going again and showing the next letter
         end if
   Else
      delete local aktuell
      go to next card
   End if
end nbacktiming
On bumpCounter
if x >= 0 then
       put x into fld id 2158
       subtract 1 from x
       send "bumpCounter" to me in 1 millisec
Else
   put "" into fld id 2158
   End if
   end bumpCounter
What I think should happen is that:
1) it branches from Preopencard to nbacktiming.
1.1) it shows a letter
1.2) nbacktiming branches to bumpCounter - which ensures that the letter is shown for 500 ms
1.2) It goes back to nbacktiming and hides the letter (= puts "" into the field")
1.3) It waits for 2500 ms
1.4) it goes back to nbacktiming and does everything from 1.1 to 1.4 again till there are no more letters left to show
The send nback to me in 2500 milliseconds should work. You just have to watch out that when you leave the card there might be a "nback" message pending which will probably not find the handler when you are at the next card. Look at pendingmessages.You would have to cancel that message. Example

Code: Select all

on closeCard
repeat for each line aLine in the pendingMessages
if aLine contains "nback" then cancel item 1 of aLine
end repeat
end closeCard
I don't understand this part. What exactly should I think of as a "nback" message, which the handler can't find?

with kind regards
James

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4171
Joined: Sun Jan 07, 2007 9:12 pm

Re: nback-task Array with fixed number of matches

Post by bn » Sun Aug 14, 2011 10:29 am

Hi James
I don't understand this part. What exactly should I think of as a "nback" message, which the handler can't find?
this was a typo/neglicence on my part, should have been nbacktiming
If you send a message in time it gets queued in the pendingmessages and is executed at the predetermined time. To clear it from the pendingMessages you would use something like this

Code: Select all

on closeCard
repeat for each line aLine in the pendingMessages
if aLine contains "nbacktiming" then cancel item 1 of aLine
end repeat
end closeCard
Kind regards

Bernd

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4171
Joined: Sun Jan 07, 2007 9:12 pm

Re: nback-task Array with fixed number of matches

Post by bn » Sun Aug 14, 2011 10:32 am

Hi James,

could you zip the stack and upload it? It gets tedious to reconstruct it especially since you use field ids.

Kind regards

Bernd

JamesWebster
Posts: 25
Joined: Sun Aug 07, 2011 11:36 am

Re: nback-task Array with fixed number of matches

Post by JamesWebster » Sun Aug 14, 2011 10:51 am

Hi Bernd,

I attached the files. And I'm working with field ids since sometimes it gives me an error for working with field names.

with kind regards
James
Attachments
nback.livecode.zip
(2.86 KiB) Downloaded 231 times

JamesWebster
Posts: 25
Joined: Sun Aug 07, 2011 11:36 am

Re: nback-task Array with fixed number of matches

Post by JamesWebster » Sun Aug 14, 2011 6:43 pm

Ok, I've put the problem into a short code, which is working except for me using wait, which would hinder the User to answer while the letter is shown.
It's supposed to show the letter for 500 ms, put empty into the field and wait for another 2,5 seconds.

Code: Select all

local asd
local aktuell
local x
On Preopencard
   put "A" into asd
   put 0 into aktuell
   put 5 into x
   nbacktiming
end Preopencard

On nbacktiming
   put asd && aktuell into field id 2151
   add 1 to aktuell
Wait 500 millisec
         put "" into fld id 2151
   put 25 into x
   bumpCounter
   send "nbacktiming" to me in 1 millisec
end nbacktiming

On bumpCounter
if x >= 0 then
       put x into fld id 2158
       subtract 1 from x
       send "bumpCounter" to me in 100 millisec
   End if
   end bumpCounter
with kind regards
James
Attachments
nback.livecode.zip
(1.7 KiB) Downloaded 232 times

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4171
Joined: Sun Jan 07, 2007 9:12 pm

Re: nback-task Array with fixed number of matches

Post by bn » Sun Aug 14, 2011 7:39 pm

Hi James,

here is a working version based on the first upload you did. It waits 500 milliseconds with messages, then the wait is not blocking. There were a couple of problems. Not Initializing an array properly, var aktuell was 0 and asked for the content of tOutPut array [0] which did not exists etc. I commented my changes with bn and a comment. Search for bn and you will find my changes.
I dont know exactly how n-back is played since I never did it, so you would have to check that.
I will have a look at your new version.

Code: Select all

local tOutput
local aktuell
local totallaenge
global Fehleranzahl
local xback
local Antwort

On Preopencard
   local tAChar
   local abc
   local matches
   local tCollect
   local gematched
      put "BCDFGHJKMNPQRSTVXZ" into abc #start Values
      put 2 into xback
      put 3 into matches 
      put 9 into totallaenge
      put "" into tCollect
      put 0 into gematched
      
      -- just a little error checking, more is probably needed
      -- matches should not be more than half the length
      if matches > totalLaenge/2 then 
            answer "can not fit matches into length"
            exit Preopencard
      end if
      
      repeat until gematched = matches  -- just let the routine run until it has found a combination of matches that  matches
            
            repeat with i = 1 to totalLaenge
                  -- just grab a random letter
                  put char random(18) of abc after tCollect
                  
                  -- only test for xback if enough letters are in tCollect to compare
                  if the number of chars of tCollect >xback then
                        
                        -- test for xback here
                        if (char (length (tCollect)- xback) of tCollect = (last char of tCollect))  then
                              
                              -- only if matches are not yet reached mark last character as lowercase
                              if  (gematched < matches) then
                                    put last char of tCollect into last char of tCollect
                                    add 1 to gematched
                                    
                              else
                                    -- we don't want more xback occurences and get a new random letter that is not the one used before
                                    repeat 
                                          put char random(18) of abc into tAChar
                                          if tAChar <> last char of tCollect then
                                                put tAChar into last char of tCollect
                                                -- we found a new random letter, get out of repeat loop
                                                exit repeat
                                          end if
                                    end repeat
                              end if
                        end if
                  end if
            end repeat
            
            if gematched < matches then -- not enough matches repeat the whole thing
                  put 0 into gematched
                  put "" into tCollect
            end if
            
            wait 0 milliseconds with messages -- in case the repeat loop can not finish we can interrupt it with command + period or escape
            
      end repeat
      
      -- lets put spaces between the letters
      repeat for each char aChar in tCollect
         put aChar & space after tOutPut
      end repeat
      delete last char of tOutPut -- a space
      
      put tOutPut into field id 2155
      --put gematched into field 2 -- if you want to monitor how many matches make a field
      --put xback into field 3
   put 0 into aktuell
   --  put 0 into Fehleranzahl -- bn blocked  was not an array
   put 0 into Fehleranzahl[1] -- bn made it into an array -- bn
   split tOutput with space
   send "nbacktiming" to me in 10 milliseconds
end Preopencard

On MouseUp
   put "match" into Antwort
end MouseUp
On MouseDoubleUp
   put "mismatch" into Antwort
end MouseDoubleUp

local x
On nbacktiming
   local durchgang
   put 1 into durchgang
   put (aktuell & "- Fehlerzahl: " & Fehleranzahl[durchgang]) into field id 2151
   
   add 1 to aktuell -- bn added, aktuell was 0, no key 0 in tOutPut ---  bn
   
   If aktuell <= totallaenge then
      If Random(8) is 1 then
         put ToLower(tOutput[aktuell]) into field id 2143
      Else
         put tOutput[aktuell] into field id 2143
      end if
      #If aktuell > xback then
      #Usereingabe bzw. keine Usereingabe und Fehlerzählen
      If aktuell > xback then
         If (tOutput[aktuell] is tOutput[aktuell-xback]) then
            If (Antwort is "mismatch") then
               Mouseup
               MouseDoubleup
               add 1 to Fehleranzahl[durchgang]
            End if
         Else
            If (Antwort is "match") then
               Mouseup
               MouseDoubleup
               add 1 to Fehleranzahl[durchgang]
            End if
         End if
         If (Antwort is "missed") then
            add 1 to Fehleranzahl[durchgang]
         End if
         put "missed" into Antwort
         
      End if
      
      #Wait for 500 millisec
      
      wait 500 milliseconds with messages -- bn added to wait 500 milliseconds, why do you want to wait at all? Do you want the bump counter?
      
      
      
      -- bn blocked the conditional, see below
      -- put 500 into x
      -- bumpCounter -- bn the bumpCounter takes a lot more than 500 milliseconds since the graphical field update is not fast enough
      
      --      -- bn x will never be 0 since bumCounter starts with 500 make one round and calls itelf
      --      -- bn when the flow of the program getshere x is 499 and nbackTiming is never send
      --      If x = 0 then 
      --         add 1 to aktuell
      --         put "" into field id 2143
      --         send "nbacktiming" to me in 2500 millisec
      --      End if
      send "nbacktiming" to me in 2500 millisec -- bn took this out of the conditional
   Else
      delete local aktuell
      go to next card
   End if
end nbacktiming

On bumpCounter
   if x >0 then -- changed from >= to > since you subtract 1 and go down to 0 = - 1 later you test for x = 0
          put x into fld id 2158
          subtract 1 from x
          send "bumpCounter" to me in 1 millisec
   Else
      put "" into fld id 2158
   End if
end bumpCounter
Kind regards

Bernd

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4171
Joined: Sun Jan 07, 2007 9:12 pm

Re: nback-task Array with fixed number of matches

Post by bn » Sun Aug 14, 2011 8:08 pm

Hi James,

what you can do to avoid blocking is:

Code: Select all

  -- instead of wait 500
  send "clearField" to me in 500 milliseconds
  ...

on clearField
   put empty into field id 2151
end clearField
or you could "wait 500 milliseconds with messages" instead of "wait 500 milliseconds", if you don't say with messages a wait is blocking, with messages it is non-blocking.

I never had problems with addressing field by name provided you put the names in quotes in the code. Always quote literals, as opposed to variables in Livecode. You can get away without but difficult to debug if you accidentally call a variable the same as an object. I avoid reserved words as a name for an object. I tend to prepend the names of fields with an f, like, fAddress, this tells me that it is a field name and gets out of the problem of confusing Livecode. Naming objects with meaningful names makes code a lot easier to read and debug.
I strongly recommend to use the debugger if something does not work as expected. It shows you what is really in the variables, it might not be what you think should be... :)

Kind regards

Bernd

JamesWebster
Posts: 25
Joined: Sun Aug 07, 2011 11:36 am

Re: nback-task Array with fixed number of matches

Post by JamesWebster » Sun Aug 14, 2011 9:00 pm

Hi Bernd,

thank you very much. Actually I noticed some of those mistakes myself, e.g. not properly initializing the Fehleranzahl array - I even found the Wait with messages command before I've tried to take another look into the forum. The script works, but it's still supposed to wait for 2500 seconds with messages after the field is empty. Show letter for 500 ms, put empty into field, wait for 2500ms - repeat the process.
Using another Wait with messages function after I've emptied the field produces a failure in showing all the letters - it's skipping some cause of a reason I don't quite understand. Any idea on how to fix this?

About addressing the field names: I'm using the same field names a lot within a stack, cause the function is always similar. For the first fields with a certain name it functions, for the rest it sometimes, not always, returns an error

kind regards
James

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4171
Joined: Sun Jan 07, 2007 9:12 pm

Re: nback-task Array with fixed number of matches

Post by bn » Sun Aug 14, 2011 9:24 pm

Hi James,

I would use the clearfield approach and increase the send in time for nbackTiming to 3000 (500 for the visibility of the letter and 2500 before the next letter
note I added a closeCard handler to stop sending nbacktiming when going to the next card.

Code: Select all

...
send "clearField" to me in 500 milliseconds
send "nbacktiming" to me in 3000 millisec
.....

on clearField
   put "" into field id 2143
end clearField

-- in my last script there is no way to stop nbacktiming go on forever, this stops it
on closeCard
   repeat for each line aLine in the pendingMessages
      if aLine contains "nbacktiming" then cancel item 1 of aLine
   end repeat
end closeCard

about the field by name: if properly addressed I never had problems???
kind regards

Bernd

JamesWebster
Posts: 25
Joined: Sun Aug 07, 2011 11:36 am

Re: nback-task Array with fixed number of matches

Post by JamesWebster » Mon Aug 15, 2011 10:50 pm

Hi Bernd,

again thank you very much - for other cards in the stack I've found another way, which enables me to show the user the time that's passing and not use to much resources with the "send" command. A simple repeat loop does the trick. Something like:
On Counter
repeat with a=1 to p
put a into field "Counter"
Wait for 1 sec with messages
end repeat
end Counter

with kind regards
James

Edit: There seems to be a problem with execution the program setting totallaenge to 45 and matches to 14, is there any way to resolve this?, cause those are the settings it should be able to work with. And while there is the close card command you wrote, I think it's still executing parts of this card after going to the next, cause live code is slowing down...

Post Reply