This might be of interest to some, which is why I am quickly posting about it.
I used a Pavlovia shelf integer to assign a participant number to each participant. After assigning the number, the shelf variable is incremented. However despite not collecting a crazy number of participants (20-ish at a time), I have three cases where the same participant number was assigned more than once.
time |
|
participant_number |
2024-10-22 |
08:00:35 AM |
99 |
2024-10-22 |
07:58:46 AM |
99 |
2024-10-22 |
07:59:59 AM |
102 |
2024-10-22 |
07:57:58 AM |
102 |
2024-10-22 |
08:00:19 AM |
105 |
2024-10-22 |
07:58:13 AM |
105 |
This happened because the participants seemed to have completed the relevant part close (but sometimes not super close) in time to each other. Luckily, I caught this and none of my routines rely on this number alone (e.g. there is always another unique ID like the prolific ID) but I can easily see how this could create a more serious issue, which is why I want to warn people using this approach.
One additional procedure, I luckily implemented, is that I tell my participant to create a unique ID by adding two letters to the number like the first letter of two people they know.
You haven’t show the code you are using or said where it appears in your experiment.
However, in principle if you get the current number of participants and then save the new number you could have someone else getting the current number before the new number has been saved.
The get a unique number with the shelf you might be able to append a tag to a list and then retrieve the list and check the position of the tag (so it wouldn’t matter if another participant has also appended a tag by the time the first participant retrieves the list to look for their own tag).
I have two tools for unique participant numbers.
https://moryscarter.com/vespr/pavlovia.php
and
https://moryscarter.com/vespr/portal/admin/
I don’t believe that either of these can produce duplicates (except the VESPR Study Portal allows you to restart your participant numbering so session is unique).
Good point here is the code I used:
participant_number = await psychoJS.shelf.getIntegerValue({key: ['participant_number'], defaultVlaue: 0})
participant_number = participant_number + 1
// https://www.psychopy.org/online/shelf.html#interacting-with-integer-records
expInfo['participant_number'] = participant_number
// increase the value on the shelf by 1
psychoJS.shelf.addIntegerValue({key: ['participant_number'], delta: 1})
The problem probably is that time between the first and last line of the code is large enough for participants to get the same number (as you say) but I was surprised how often this happened given the small number of participants I collected at the same time. I now also suspect that the counterbalance routine has similar issues.
A better solution probably would be to run the routines on a server that has access to these variables instead of having the participants’ computer communicate with the Pavlovia server, which introduces delay. That is what VESPR is doing right?
Looking at my code, pavlovia.php also does it in two database calls.
$query = "INSERT INTO pavlovia (folder,experiment,participant) VALUES ('$folder','$experiment','$participant')";
$ResultA = mysqli_query($link,$query);
$query = "SELECT id from pavlovia WHERE folder='$folder' AND experiment = '$experiment' AND participant = '$participant'";
$ResultB = mysqli_query($link,$query);
$numRows = mysqli_num_rows($ResultB);
It may be that MySQL is better at locking the database for the duration of the consecutive calls, because I haven’t had any reports of duplicate numbers.
However, I’ve just updated the code so that any rows added after the first database call are ignored:
$query = "INSERT INTO pavlovia (folder,experiment,participant) VALUES ('$folder','$experiment','$participant')";
$ResultA = mysqli_query($link,$query);
$new_id=mysqli_insert_id($link);
$query = "SELECT id from pavlovia WHERE folder='$folder' AND experiment = '$experiment' AND participant = '$participant' AND id <= $new_id";
$ResultB = mysqli_query($link,$query);
$numRows = mysqli_num_rows($ResultB);
1 Like