I am using multi-touch for a simple game. I have three buttons and if one button is pressed, the corresponding object is removed and if the correct two buttons are 'multitouched' then that corresponding object is removed. My problem is that the multitouch handler triggers two events, therefore removing two objects when it should only remove one. Here's a paraphrased version of my code:
function buttonHandler(event)
-- Store the users input
if (event.phase == "began") then
mt[event.target.id] == true
end
-- When the buttons are released, give the users input a value.
if (event.phase == "ended") then
if mt.One == true and mt.Two == true then number = 3
elseif mt.One == true and mt.Two == false then number = 1
elseif mt.One == false and mt.Two == true then number = 2
elseif mt.One == false and mt.Two == false then number = 0
end
-- Compare the user input with the object and remove it if there's a match.
if object.number == number then
object:removeSelf()
object = nil
end
-- Reset the user input.
mt.One = false
mt.Two = false
mt.Three = false
end
What is happening is that if the user selects the number 3 by pressing both the 1 and 2 buttons, the comparison code is being triggered twice, once for each 'ended' phase. So if the the two objects on the screen are a 3 and a 1, then the three will be removed and for the 1, it acts as if the user guessed wrong. On the other hand, if there are two '3' objects on the screen, both objects will be removed with one 'guess'.
I thought about moving the comparison code outside of the function, but I would be in the same situation. There will still be two events fired for one guess.
(If my actual code is needed, I'd be more than happy to provide it. This just saves a lot of space. Also, if this is a basic answer and I just don't see it, a link to reading material would be greatly appreciated. I don't mind work, just don't know where to start.)
Related
I am trying to collect the participants' responses (i.e., the first key they press on the keyboard) and their reaction time (i.e., the time elapsed since the presentation of a picture and the response). I am using the KbQueueXXX functions in Psychtoolbox, but I am not sure if I am using them properly.
Thanks for your help.
Dear Psychtoolbox users,
I wrote a script to run a 2AFC task where participants must respond within a fixed deadline of 2 seconds. If participants respond earlier, then they move to the subsequent trial straight away. To collect their responses (i.e., the first key they pressed and their RT), I coded a custom function that incorporates KbQueueCheck(). I am now reviewing and debugging my script but I have some doubts about the KbQueueXXX functions. I would be grateful if you could give me some feedback.
Task script
In a mixture of code and pseudocode, here is what I am doing.
KbQueueCreate(KEYBOARD, KEYS_OF_INTEREST);
KbQueueStart(KEYBOARD);
% TRIALS' LOOP STARTS
for iTrial = 1:nTrials
KbQueueFlush(KEYBOARD);
% show stimulus and record its onset and offset times
respDeadline = stimulusOffset + 2;
collectResponse(KEYBOARD, respDeadline, stimulusOnset); % <- KbQueueCheck() here!
end
% TRIALS' LOOP ENDS
KbQueueStop(KEYBOARD);
KbQueueRelease(KEYBOARD);
Custom function
Below is my custom function collectResponse() where I embedded KbQueueCheck().
function [choice, rt, choiceTime, firstPress, keyCodes, pressed] = collectResponse(deviceIndex, untilTime, targetOnset)
%% LOOK FOR KEYPRESSES
pressed = false;
while pressed == false && GetSecs <= untilTime
[pressed, firstPress] = KbQueueCheck(deviceIndex);
end
%% PROCESS KEYPRESSES
if pressed == false % NO KEYS WERE PRESSED
keyCodes = NaN;
firstPress = NaN;
choiceTime = NaN;
choice = NaN;
rt = NaN;
else % ONE OR MORE KEYS WERE PRESSED
keyCodes = find(firstPress > 0); % all keypresses
choiceTime = min(firstPress(keyCodes)); % ts of first keypress
choice = find(firstPress == choiceTime); % first keypress
if length(choice) > 1
% handle simultaneous keypresses
choice = -999;
end
rt = choiceTime - targetOnset; % reaction time
end
end
My questions
I am not sure whether I am calling KbQueueXXX functions correctly and whether they are in the expected position.
Shall I keep KbQueueCreate()/KbQueueStart() and KbQueueStop()/KbQueueRelease() respectively before and after the trials’ loop?
Shall I rather just KbQueueStart(), KbQueueCheck(), and KbQueueStop() at each trial iteratively?
Is it OK to KbQueueFlush() at the beginning of each trial, before the presentation of a new stimulus?
Is my custom function collectResponse() fit for the purpose I described at the top of this post?
Thank you very much for your time, I look forward to knowing your thoughts.
Kind regards,
Valerio
OS: Windows 10
MATLAB: 9.10.0.1851785 (R2021a) Update 6
PTB: 3.0.18 - Flavor: beta - Corresponds to SVN Revision 13009
The original post can be found in the Psychtoolbox forum.
KbQueueXXX functions: which to use and where do they go in relation to the trials' loop?
I need a data structure which has 3 operations: 1. push, 2. pop 3. has. It is like a stack with a set-like element lookup. The has operation should return true iff the stack contains the argument. I need the has operation to be fast, how do I implement it?
Examples:
push(1), push(2), push(1), pop(). // Expect has(1) to be true.
Well, you could make an argument that, if you need a has/contains method, it probably shouldn't be a stack. However, if I needed such functionality (and it was an object-oriented language), I would simply inherit from an actual stack and then intercept the push and pop calls to also maintain another alternate collection (e.g., a sorted resizable vector, or a sorted list, or counting set, other suitable one).
Every time something was pushed, I'd add it to the alternate collection as well. Upon popping, it would also be removed from the alternate collection.
Then your push and pop operations become (hopefully only) marginally slower and, your has method uses the alternate collection which is presumably a lot faster than a basic stack would be (using the method of examining every element in the stack to see if the item is in there).
And yes, you may have duplicate data but optimisation is often a space/time trade-off. In any case, you could mostly avoid any real impact by using pointers in (references to) the stack items within the alternate collection.
Since you haven't specified a language, and Python is the ultimate pseudo-code anyway :-), here's how I would approach it in that language. First a basic stack class with nothing other than push/pop:
class Stack:
def __init__(self):
self.stack = [] # Empty list to start.
def push(self, item):
self.stack.append(item) # Add to list end.
def pop(self):
item = self.stack[-1] # Get list end,
self.stack = self.stack[:-1] # shorten list by one,
return item # and return it.
The class that inherits from that calls the base class for each item but also maintains a dictionary (associative array) which maps item to a count (effectively a counting set).
class AltStack(Stack):
def __init__(self):
super().__init__() # Defer to base but
self.alternate = {} # also create alternate.
def push(self, item):
super().push(item) # Defer to base but
try: # also increment in
self.alternate[item] += 1 # alternate, creating if
except KeyError: # not yet set.
self.alternate[item] = 1
def pop(self):
item = super().pop() # Defer to base. Then
if self.alternate[item] == 1: # decrement in alternate,
del self.alternate[item] # deleting item from
else: # alternate when count
self.alternate[item] -= 1 # reaches zero.
return item
def has(self, item):
return item in self.alternate # Use alternate for "has".
Then all you need is the simplest of test harnesses:
my_stack = AltStack()
# Push 0, two each of 1-6, and 7.
for i in range(7):
my_stack.push(i)
my_stack.push(i+1)
# Pop each, displaying both it and whether stack has specific item.
for i in range(14):
print("Popping", my_stack.pop(), "has(4)? =", my_stack.has(4))
As you can see from the (annotated) output, this works as expected:
Popping 7 has(4)? = True <-- 4 was pushed twice, has(4) true.
Popping 6 has(4)? = True
Popping 6 has(4)? = True
Popping 5 has(4)? = True
Popping 5 has(4)? = True
Popping 4 has(4)? = True <-- first 4 popped, has(4) still true.
Popping 4 has(4)? = False <-- final 4 popped, has(4) now false.
Popping 3 has(4)? = False
Popping 3 has(4)? = False
Popping 2 has(4)? = False
Popping 2 has(4)? = False
Popping 1 has(4)? = False
Popping 1 has(4)? = False
Popping 0 has(4)? = False <-- and stay false forever.
Keep in mind this is an example showing how it could be done as a concept. I make no judgement call on whether dictionaries are more efficient than list though I suspect they are for medium to large structures. So try to remember this concept nature before you start to raise issues with the way I've done things.
Why not it is possible to extend the stack data structure class in java and add functionality so as to implement your specified has/contains method as required.
If you wish this idea works out I can write the necessary code for it.
I have a Ruby Discord (discordrb) bot written to manage D&D characters. I notice when multiple players submit the same command, at the same time, the results they each receive are not independent. The request of one player (assigning a weapon to their character) ends up being assigned to other characters who submitted the same request at the same time. I expected each request to be executed separately, in sequence. How do I prevent crossing requests?
bot.message(contains:"$Wset") do |event|
inputStr = event.content; # this should contain "$Wset#" where # is a single digit
check_user_or_nick(event); pIndex = nil; #fetch the value of #user & set pIndex
(0..(#player.length-1)).each do |y| #find the #player pIndex within the array using 5 char of #user
if (#player[y][0].index(#user.slice(0,5)) == 0) then pIndex = y; end; #finds player Index Value (integer or nil)
end;
weaponInt = Integer(inputStr.slice(5,1)) rescue false; #will detect integer or non integer input
if (pIndex != nil) && (weaponInt != false) then;
if weaponInt < 6 then;
#player[pIndex][1]=weaponInt;
say = #player[pIndex][0].to_s + " weapon damage has be set to " + #weapon[(#player[pIndex][1])].to_s;
else;
say = "Sorry, $Wset requires this format: $Wset? where ? is a single number ( 0 to 5 )";
end;
else
say = "Sorry, $Wset requires this format: $Wset? where ? is a single number ( 0 to 5 )";
end;
event.respond say;
end;
To avoid race conditions in multithreaded code like this, the main thing you want to look for are side effects.
Think about the bot.message(contains:"$Wset") do |event| block as a mini program or a thread. Everything in here should be self contained - there should be no way for it to effect any other threads.
Looking through your code initially, what I'm searching for are any shared variables. These produce a race condition if they are read/written by multiple threads at the same time.
In this case, there are 2 obvious offenders - #player and #user. These should be refactored to local variables rather than instance variables. Define them within the block so they don't affect any other scope, for example:
# Note, for this to work, you will have to change
# the method definition to return [player, user]
player, user = check_user_or_nick(event)
Sometimes, making side effects from threads is unavoidable (say you wanted to make a counter for how many times the thread was run). To prevent race conditions in these scenarios, a Mutex is generally the solution but also sometimes a distributed lock if the code is being run on multiple machines. However, from the code you've shown, it doesn't look like you need either of these things here.
In order to replicate this code, you will need these packages:
Tidyverse, Nycflights13
I am basically trying to understand why two pieces of code, which in my head should do the same thing, don't do the same thing.
I am currently learning R for data science from R for Data Science by Garrett Grolemund & Hadley Wickham, and I've gotten to a point which the code begins to confuse me quite a bit, which hopefully is normal! I will write down the two pieces of code which confuse me in why they don't do the same thing!
filter(flights, dest == c("HOU","IAH"))
#and
filter(flights, dest == "HOU" | dest == "IAH")
I expected both of these codes to show the same amount of rows but the first one shows 4658 rows (the wrong amount), where as the second one shows 9313 (the right amount).
What I wanted to do is to shorten the code by using (filter(flights, dest == c("HOU","IAH"))) instead of (filter(flights, dest == "HOU" | dest == "IAH"))
but it yields different results, which gravely confuses me!
Please give me your advice, I am a newbie!
Because filter(flights, dest == c("HOU","IAH")) is the same as
filter(flights, dest == c("HOU","IAH"))
flights$dest = c("HOU","IAH")
* # For demonstation purposes, I'm assuming the flights dataset has has 4 rows, as:
c("HOU","CPH","IAH","EDI") == c("HOU","IAH")
Now, a vector of 4 elements cannot possible be the same as a vector of 2 elements. And this performs an element-wise comparison, "HOU" == "HOU", "CPH" == "IAH", "IAH" == ???. So R "helps" us by repeating the shorter vector. The output is thus:
> c("HOU","CPH","IAH","EDI") == c("HOU","IAH")
[1] TRUE FALSE FALSE FALSE
Try extending with a 5th element:
> c("HOU","CPH","IAH","EDI", "LDN") == c("HOU","IAH")
[1] TRUE FALSE FALSE FALSE FALSE
Warning message:
In c("HOU", "CPH", "IAH", "EDI", "LDN") == c("HOU", "IAH") :
longer object length is not a multiple of shorter object length
and you broke it.
So the 1st line only makes sense if and only if flights has 2 rows, whereupon an element-wise comparison can be performed.
However, what you might be looking for is the %in% operator:
> c("HOU","CPH","IAH","EDI") %in% c("HOU","IAH")
[1] TRUE FALSE TRUE FALSE
> c("HOU","CPH","IAH","EDI","LDN") %in% c("HOU","IAH")
[1] TRUE FALSE TRUE FALSE FALSE
which can be expanded to filter(flights, dest %in% c("HOU","IAH")) and luckily works for vectors of any length.
You might already know the problem by the title.
I'm making a game, where i want the level number to change to 1 (from the first level 0). My code to change from level 0 to 1 is:
'Level 0 (Tutorial)
If levelNum.Text.Contains("0") Then
levelNum.Text = "1"
ButtonNext.Enabled = False
ButtonLeave.Enabled = True
ButtonBreak.Enabled = True
ButtonCoffee.Enabled = True
ButtonCoffeeForBoss.Enabled = True
End If
But it sets the label text to 2 instead of 1, wich was written (Line 3 of code above).
EXAMPLE:
http://cdn.makeagif.com/media/11-24-2013/9p4CcG.gif
Does anybody know how to fix that?
Maybe make a variable with "1" in it and then use that?
*TESTING THAT*
No, didn't work...
Could it be because it's starting on level 0?
I have no idea.
I'm using VB Express 2013.