psychopy.org | Reference | Downloads | Github

Saving multiple drag and drop data in output

WIN 10, PsychoPy3 2020.2.5 (but I use version 2020.2.4, because version 5 creates errors with the coloring of the background and stimuli in pavlovia)

Dear PsychoPy community, I need your help with some code elements. In my experiment I created a drag and drop game where participants can drag and drop green and red pieces (circles) over various polygon stimuli. At the end participants will have drawn and dragged 42 pieces over 42 different polygons. I need to save the final position of every piece so that I know, which color piece was dragged over which polygon. I am struggeling with that part because what I tried so far does not do what I need.
What I need is basically this:
#if polygon contains a piece --> save piece.name and the polygon name in two columns (cvs/excel file etc.)

I am able to save the data while participants drag and drop the pieces, but that does not tell me what the final positions are with certain. As soon as another piece touches a polygon, this will be saved in the excel file, even if it was not dropped on the polygon.
I have also tried to use the “checkAnswer” function from @dvbridges code but I couldn’t figure out how to adapt it to my needs succesfully…

I’ll post my current code below (Python part, but I will need a JS version too…). If you have a solution or tip I would be very happy!

#Begin Experiemnt:
def createPiece(piece, pos, name):
    return visual.ImageStim(win, image=piece.image, name=piece.name, size=piece.size, pos=pos, opacity=0.5, interpolate=True)

def drawPicked(picked):
    for each in picked:
        each.draw()

def movePicked(picked, mouseMulti, grabbed):
    #move piece if it is already being moved 
    if grabbed is not None and mouseMulti.isPressedIn(grabbed): #JS 'undefined'
        grabbed.pos = mouseMulti.getPos()
        return grabbed
    else: #move newly clicked piece
        for piece in picked:
            if mouseMulti.isPressedIn(piece) and grabbed is None: #JS 'undefined'
                return piece
------------------------------
#Begin Routine:
polygons = [polygon1_7, polygon2_12,  polygon3_1, polygon4_37, polygon5_18, polygon6_2, polygon7_31, polygon8_4, polygon9_10, polygon10_27, polygon11_11, polygon12_19, polygon13_13, polygon14_34, polygon15_21, polygon16_42, polygon17_15, polygon18_29, polygon19_20,  polygon20_8, polygon21_22,  polygon22_38, polygon23_36, polygon24_14, polygon25_33, polygon26_25, polygon27_40, polygon28_32, polygon29_6, polygon30_28, polygon31_23, polygon32_41, polygon33_24, polygon34_9, polygon35_35, polygon36_16, polygon37_5, polygon38_39, polygon39_3, polygon40_26, polygon41_17, polygon42_30]

for polygon in polygons:
    polygon.setFillColor(None) #JS 'undefined'
    polygon.setLineColor(None) #JS 'undefined'

pieces = [redPieceM, greenPieceM]
picked = []
newPiece = None #JS 'undefined'
movingPiece = None  #JS 'undefined'

ClickCountNewPiece = 0
CountPolygons = False

polygonNameList = ['polygon1_7', 'polygon2_12', 'polygon3_1', 'polygon4_37', 'polygon5_18', 'polygon6_2', 'polygon7_31', 'polygon8_4', 'polygon9_10', 'polygon10_27', 'polygon11_11', 'polygon12_19', 'polygon13_13', 'polygon14_34', 'polygon15_21', 'polygon16_42', 'polygon17_15', 'polygon18_29', 'polygon19_20', 'polygon20_8', 'polygon21_22', 'polygon22_38', 'polygon23_36', 'polygon24_14', 'polygon25_33', 'polygon26_25', 'polygon27_40', 'polygon28_32', 'polygon29_6', 'polygon30_28', 'polygon31_23', 'polygon32_41', 'polygon33_24', 'polygon34_9', 'polygon35_35', 'polygon36_16', 'polygon37_5', 'polygon38_39', 'polygon39_3', 'polygon40_26', 'polygon41_17', 'polygon42_30']
polygonsList = [] #empty list for storing polygons names
      
multipleAnswered = False

polygonWeiterMultiOn = False
polygonWeiterMultiSelected = False
polygonWeiterMulti.setAutoDraw(False)
polygonWeiterMulti.setFillColor(None) #JS 'undefined'
polygonWeiterMulti.setLineColor(None) #JS 'undefined'

-------------------------------------
#Each frame:
for piece in pieces:
    if mouseMulti.isPressedIn(piece) and movingPiece is None:
        newPiece = createPiece(piece, mouseMulti.getPos(), piece.name)
        ClickCountNewPiece = ClickCountNewPiece + 1
        if ClickCountNewPiece >= 42:
            CountPolygons = True
        
        picked.append(newPiece) #to create and enable to drag multiple new created pieces
        clicked_piece = newPiece
        
#reset the newPiece to none, if one was just picked to be able to pick up another one again:
    if newPiece is not None and mouseMulti.getPressed()[0] == 0:
        newPiece = None
    
    movingPiece = movePicked(picked, mouseMulti, movingPiece)
    drawPicked(picked)

#store the name of piece and polygons :
    for polygon in polygons:
       if polygon.contains(mouseMulti): #and mouseMulti.isPressedIn(piece): #I want this part to be added but psychopy always ignores this and won't run the following code correcty 
        #check if polygonslist empty, put polygon name in list
            if len(polygonsList) == 0:
                polygonsList.append(polygon.name)
                thisExp.addData('MultiAnsPolyName', polygon.name)
                thisExp.addData('MultiAnsClickedPiece', clicked_piece.name)
                thisExp.nextEntry()
            #for following responses, only store if they aren't a repetition of the immeadiate prior one (entry [-1]):
            elif polygonsList[-1] != polygon.name:
                polygonsList.append(polygon.name)
                thisExp.addData('MultiAnsPolyName', polygon.name)
                thisExp.addData('MultiAnsClickedPiece', clicked_piece.name)
                thisExp.nextEntry()

#check if all polygons added to the list match the original polygon name list:
    if len(polygonsList):
        allMatch = True
        for item in polygonNameList:
            if item not in polygonsList:
                allMatch = False
        if allMatch:
            multipleAnswered = True
            
               
#draw and enable button once multipleAnswered is complete
    if multipleAnswered and CountPolygons and not polygonWeiterMultiOn:
        polygonWeiterMulti.setFillColor([-1.000,0.004,0.506],'rgb')
        polygonWeiterMulti.setLineColor([-1.000,0.004,0.506],'rgb')
        polygonWeiterMulti.setAutoDraw(True) 
        polygonWeiterMultiOn = True
    
        #check for click in button when it is on:
    if  polygonWeiterMultiOn and mouseMulti.isPressedIn(polygonWeiterMulti): #and not ContinueButtonSelected:
        polygonWeiterMultiSelected = True
                        
    #if activated button is pressed, store data and proceed:
    if polygonWeiterMultiSelected:
        for polygon in polygons:
        #for piece in pieces: #tried to add this to the loop and indent the following accordingly but to no avail
            #if redPieceM.overlaps(polygon): #first try= throws: typeError: only size-1 arrays can be converted to Python scalars
            #if redPieceM.contains(polygon): #second try= throws: typeError: only size-1 arrays can be converted to Python scalars
            if polygon.contains(redPieceM): #third try= throws: typeError: only size-1 arrays can be converted to Python scalars
                #print('in polygon redpiece loop')
                thisExp.addData('MultiAnswersPolygonName', polygon.name)
                thisExp.addData('MultiAnswersPieceColor', piece.name)
                thisExp.nextEntry()
            #elif greenPieceM.overlaps(polygon):
            #if greenPieceM.contains(polygon): #typeError: only size-1 arrays...
            if polygon.contains(greenPieceM):
                #print('in polygon greenpiece loop')
                thisExp.addData('MultiAnswersPolygonName', polygon.name)
                thisExp.addData('MultiAnswersPieceColor', piece.name)
                thisExp.nextEntry()
        continueRoutine = False

---------------------
#End Routine:
polygonWeiterMultiOn = False
polygonWeiterMultiSelected = False
polygonWeiterMulti.setFillColor(None) #JS 'undefined'
polygonWeiterMulti.setLineColor(None) #JS 'undefined'
polygonWeiterMulti.setAutoDraw(False)