Page 2 of 2
Re: nback-task Array with fixed number of matches
Posted: Sun Aug 14, 2011 9:21 am
by bn
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:
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
Re: nback-task Array with fixed number of matches
Posted: Sun Aug 14, 2011 10:16 am
by JamesWebster
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
Re: nback-task Array with fixed number of matches
Posted: Sun Aug 14, 2011 10:29 am
by bn
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
Re: nback-task Array with fixed number of matches
Posted: Sun Aug 14, 2011 10:32 am
by bn
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
Re: nback-task Array with fixed number of matches
Posted: Sun Aug 14, 2011 10:51 am
by JamesWebster
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
Re: nback-task Array with fixed number of matches
Posted: Sun Aug 14, 2011 6:43 pm
by JamesWebster
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
Re: nback-task Array with fixed number of matches
Posted: Sun Aug 14, 2011 7:39 pm
by bn
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
Re: nback-task Array with fixed number of matches
Posted: Sun Aug 14, 2011 8:08 pm
by bn
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
Re: nback-task Array with fixed number of matches
Posted: Sun Aug 14, 2011 9:00 pm
by JamesWebster
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
Re: nback-task Array with fixed number of matches
Posted: Sun Aug 14, 2011 9:24 pm
by bn
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
Re: nback-task Array with fixed number of matches
Posted: Mon Aug 15, 2011 10:50 pm
by JamesWebster
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...