Beispiel #1
0
    def validate(self, attrs):
        data = super().validate(attrs)

        refresh = self.get_token(self.user)

        data['refresh'] = str(refresh)
        data['access'] = str(refresh.access_token)

        #@Ole Add the logging 
        now = timezone.now()
        dt_string = now.strftime("%Y-%m-%d %H:%M:%S")

        # f = open("/apps/Klaverjassen/log/klaverjas_login.txt", "a")
        # log_text = "*** " + dt_string + ',   Username : '******'authentication').info(f'[{str(self.user)}] has logged in')
        # logger('debug').debug('This is a debug test')

        return data
Beispiel #2
0
    async def connect(self):
        #@ Currently there is no validation on user, so everybody can connect to a channel
        #@ Needs to add an authentication
        self.gameID = self.scope['url_route']['kwargs']['gameID']
        self.group_name = 'game_%s' % self.gameID

        # Join room group
        await self.channel_layer.group_add(
            self.group_name,
            self.channel_name
        )

        # can add here a validation before the accept
        await self.accept()

        # On connect send a confirmation with channelname to the client
        # the client can then send a back message with channel, gameid and position 
        # to be stored in the database
        message = { 
            'type': 'confirm_connected',
            'channel': self.channel_name
        }

        # Only send the the client (not to the group)
        await self.send(text_data=json.dumps(message))
        print('Connection created : ', self.channel_name)
        logger('debug').debug(f'Connection created : , {self.channel_name}')
Beispiel #3
0
    def post(self, request):
        """
        Based on token in the header get the user_id
        Put the user_id and token on the Blacklist, so that 
        this token is not allowed anymore.
        """

        try: 
            user_id = JWTAuthenticationBlacklist().authenticate(request)[0]
            access_token = JWTAuthenticationBlacklist().authenticate(request)[1]

            # Add user + token to the Blacklist
            user_obj = User.objects.get(username=user_id)
            item = BlackListedToken(
                        token   = access_token,
                        user    = user_obj
                   )
            item.save()

            #Log the logout
            logger('authentication').info(f'[{user_id}] has logged out')

            # see: https://www.django-rest-framework.org/api-guide/status-codes/
            content = {'logout': 'success'}
            return Response(content, status=status.HTTP_200_OK)
        
        except:
            logger('errors').error(f'User {user_id} failed to logout')
            content = {'logout': 'not succeeded'}
            return Response(content, status=status.HTTP_400_BAD_REQUEST)
Beispiel #4
0
    def is_not_on_blacklist(self, raw_token, validated_token):

        is_allowed = True
        user_id = self.get_user(validated_token)

        try:
            on_list = BlackListedToken.objects.get(user=user_id, token=validated_token)
            if on_list:
                logger('authentication').info(f'User {user_id} tried to login with token on Blacklist')
                is_allowed = False
        except BlackListedToken.DoesNotExist:
            is_allowed = True

        return is_allowed
Beispiel #5
0
def set_connected_status(gameID, position, channel):
    '''
    Update the status of a player at a position at the table at a game.
    Use this function when a player connects to the game.
    '''
    # first check that an entry for that game/position exists
    # if not, create an entry
    qs = WSConnectedStatus.objects.filter(gameID=gameID, position=position)
    if len(qs) > 0:
        obj = WSConnectedStatus.objects.get(gameID=gameID, position=position)
        obj.connected = True
        obj.channel = channel
        obj.save()
    else: 
        entry = WSConnectedStatus()
        entry.gameID = gameID
        entry.position = position
        entry.connected = True
        entry.channel = channel
        entry.save()
        # print('++ Entry created ', gameID, position, channel)
        logger('debug').debug(f'++ Entry created, {gameID}, {position}, {channel}')
Beispiel #6
0
    def get_raw_token(self, header):
        """
        Extracts an unvalidated JSON web token from the given "Authorization"
        header value.
        """
        parts = header.split()

        if len(parts) == 0:
            # Empty AUTHORIZATION header sent
            return None

        if parts[0] not in AUTH_HEADER_TYPE_BYTES:
            # Assume the header does not contain a JSON web token
            return None

        if len(parts) != 2:
            logger('errors').error(f'Authenticaion failed due to header {header}')
            raise AuthenticationFailed(
                _('Authorization header must contain two space-delimited values'),
                code='bad_authorization_header',
            )

        return parts[1]
Beispiel #7
0
    def save(self):
        # Define what needs to be saved
        # use validated_data as the input from the API

        # Create a User with the variable from validated data
        user = User(
            username    = self.validated_data['username'],
            first_name  = self.validated_data['first_name'],
            last_name   =  self.validated_data['last_name'],
            # It is possible to change the data. Then make sure to also update the validated_data
            # otherwise the old value will be shown in the API reponse
            # last_name   =  'XXX', 
            email       = self.validated_data['email']
        )

        # validate the password using the default password validators
        password = self.validated_data['password']
        # password = data.get('password')

        # When validating the password using the validate_password then 
        # the error must be catched, otherwise this whole serializer will result in an error

        errors = dict() 
        try:
            # validate the password and catch the exception
            validate_password(password=password)

        # the exception raised here is different than serializers.ValidationError
        except exceptions.ValidationError as e:
            errors['password'] = list(e.messages)

        if errors:
            raise serializers.ValidationError(errors)
        else:
            # Add the password to the user and save to the database
            user.set_password(password)
            user.save()

        # Log the registration of a new user
        now = timezone.now()
        dt_string = now.strftime("%Y-%m-%d %H:%M:%S")

        # f = open("/apps/Klaverjassen/log/klaverjas_registration.txt", "a")
        # log_text = '*** ' + dt_string + ', Username: '******'username'] \
        #             + ', Naam: ' + self.validated_data['first_name'] + ' ' + self.validated_data['last_name'] \
        #             + ', Email: ' + self.validated_data['email'] +  "\n"  
        # f.write(log_text)
        # f.close()

        # log the registration 
        logger_text = 'Username: '******'username'] \
                    + ', Naam: ' + self.validated_data['first_name'] + ' ' + self.validated_data['last_name'] \
                    + ', Email: ' + self.validated_data['email']  
        logger('registration').info(f'{logger_text}')

        try:
            # send a mail
            subject='New user registered'
            message_text = '*** ' + dt_string + ', Username: '******'username'] \
                        + ', Naam: ' + self.validated_data['first_name'] + ' ' + self.validated_data['last_name'] \
                        + ', Email: ' + self.validated_data['email'] 
            mailfrom='*****@*****.**'  
            mailto='*****@*****.**'
            send_mail(
                subject,
                message_text,
                mailfrom,
                [mailto],
                fail_silently=False,
            )
        except:
            logger('errors').exception('Mail could not be sent')
Beispiel #8
0
    def post(self, request):
        """
        Receive username, reset_code and password.
        These will be validated. When Ok then the new password will be set
        """

        try:
            username    = request.data['username']
            reset_code  = request.data['reset_code']
            password    = request.data['password']

            # Validate username
            # - exists, is unique, is active, 

            try:
                # Get the user, when this fails this will go to except
                user_obj = User.objects.get(username=username)

                # validate that user is active
                if user_obj.is_active == False:
                    content = {'message': 'Wachtwoord reset niet gelukt','username': ['Opgegeven gebruikersnaaam is niet meer actief.']}
                    logger('authentication').warning(f'Reset password failed. User [{username}] is not active anymore')
                    return Response(content, status=status.HTTP_404_NOT_FOUND)

            except:
                logger('authentication').warning(f'Reset password failed. Used incorrect username [{username}]')
                content = {'message': 'Wachtwoord reset niet gelukt','username': ['Incorrecte gebruikersnaam opgegeven.']}
                return Response(content, status=status.HTTP_404_NOT_FOUND)

            # When there is a correct user next validate the reset_code
            # - is not expired, belongs to given username
            # print('DUMMY1',user_obj.reset_code_valid_until.strftime('%Y-%m-%d %H:%M:%S'), timezone.now().strftime('%Y-%m-%d %H:%M:%S'))
            # print(user_obj.reset_code_valid_until.strftime('%Y-%m-%d %H:%M:%S') < timezone.now().strftime('%Y-%m-%d %H:%M:%S'))

            if reset_code != user_obj.reset_code:
                logger('authentication').warning(f'Reset password failed. User [{username}] used incorrect reset code')
                content = {'message': 'Wachtwoord reset niet gelukt','reset_code': ['Opgegeven resetcode is niet correct.']}
                return Response(content, status=status.HTTP_404_NOT_FOUND)
            else:
                # code is correct, now validate the expiration of code
                if user_obj.reset_code_valid_until.strftime('%Y-%m-%d %H:%M:%S') < timezone.now().strftime('%Y-%m-%d %H:%M:%S'):
                    logger('authentication').warning(f'Reset password failed. User [{username}] used expired reset code')
                    logger('authentication').warning(f"{user_obj.reset_code_valid_until.strftime('%Y-%m-%d %H:%M:%S')} versus {timezone.now().strftime('%Y-%m-%d %H:%M:%S')}")
                    content = {'message': 'Wachtwoord reset niet gelukt','reset_code': ['De reset_code is niet meer geldig']}
                    return Response(content, status=status.HTTP_404_NOT_FOUND)

            # Now the reset_code is valid, so the password can be set.
            # First validate the password
            try:
                # validate the password and catch the exception
                validate_password(password=password)

            # the exception raised here is different than serializers.ValidationError
            except exceptions.ValidationError as e:
                content = {'message': 'Wachtwoord reset niet gelukt','password': list(e.messages)}
                return Response(content, status=status.HTTP_400_BAD_REQUEST)

            user_obj.set_password(password)

            # Also set the reset_code to exipred
            user_obj.reset_code_valid_until = timezone.now() - timezone.timedelta(minutes=1)

            # Save the user object
            user_obj.save()

            logger('authentication').info(f'Reset password completed for user [{username}]')
            content = {'message': 'Wachtwoord van gebruiker is aangepast'}
            return Response(content, status=status.HTTP_201_CREATED)


        except:
            logger('authentication').error(f'Reset password for user [{username}] failed due to internal error.')
            content = {'message': 'Interne fout opgetreden bij het afhandelen van dit verzoek'}
            return Response(content, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
Beispiel #9
0
    def post(self, request):
        """
        Receive username and/or email address.
        When all validated, return a reset code
        """

        # Set the length to the reset code
        code_length = 8

        try:
            username    = request.data['username']
            email       = request.data['email']
            ip_address  = request.META.get("REMOTE_ADDR")

            if username != '':
                # When username is given, only use username to check the existence of this user
                qs = User.objects.filter(username=username)

                if len(qs) != 1:
                    # When there is not a single result, then create then error
                    content = {'message': 'Deze gebruikersnaam is niet in gebruik'}
                    logger('authentication').warning(f'Non existent user [{username}] requested password reset from IP [{ip_address}]')
                    return Response(content, status=status.HTTP_404_NOT_FOUND)

            else:
                # When no username is given check the email

                if email != '':
                    qs = User.objects.filter(email=email).order_by('username')

                    if len(qs) == 1:
                        # When there is a single account with this email address this can be used
                        # Do nothing, and create the code and email at the end
                        pass

                    elif len(qs) == 0:
                        # No  email adresses are using this email address,
                        # so so unique user can be determined
                        content = {'message': 'Geen gebruikersnamen gevonden die horen bij dit email adres.'}
                        logger('authentication').warning(f'Non existent mail address [{email}] requested password reset from IP [{ip_address}]')
                        return Response(content, status=status.HTTP_404_NOT_FOUND)

                    else:
                        # multiple accounts have been found for the email address

                        # Put the usernames in a list
                        list_names = list()
                        for item in qs:
                            list_names.append(item.username)

                        # send a mail with these usernames
                        mailVars = {
                            "users": list_names, 
                            "email": email
                        }
                        subject = 'Klaverjasfun.nl,  gebruikersnamen voor email adres'
                        from_email = '*****@*****.**'
                        to = [email]
                        bcc = ['*****@*****.**']
                        cc = []
                        html_message = render_to_string('mail_template_multiple_usernames.html', mailVars )
                        plain_message = strip_tags(html_message)
                        send_mail(subject, plain_message, from_email, to, html_message=html_message)

                        #Log sending the reset code
                        logger('authentication').info(f'Send reset code mail for multiple users for mail [{email}] from IP [{ip_address}]')


                        content = {'message': 'Meerdere gebruikersnamen horen bij dit email adres. Er is een mail verstuurd met de verschillende gebruikersnamen.'}
                        return Response(content, status=status.HTTP_404_NOT_FOUND)

                else:
                    # No username and no email
                    content = {'message': 'Gebruikersnaam of email adres moet worden gebruikt'}
                    return Response(content, status=status.HTTP_400_BAD_REQUEST)

            #############################################################################
            #  When a unique user has been found, create the reset_code 
            user_obj = User.objects.get(username=qs[0].username)
            reset_code = createResetCode(code_length)  
            user_obj.reset_code = reset_code

            # Set the Valid until to now + 15 minutes for the reset code
            user_obj.reset_code_valid_until = timezone.now() + timezone.timedelta(minutes=15)
            user_obj.save()

            # Send a mail to the user
            mailVars = {
                "username": user_obj.username, 
                "email": user_obj.email,
                "reset_code": reset_code
            }
            subject = 'Klaverjasfun.nl,  code voor reset wachtwoord'
            from_email = '*****@*****.**'
            to = [user_obj.email]
            bcc = ['*****@*****.**']
            cc = []
            html_message = render_to_string('mail_template_reset_code.html', mailVars )
            plain_message = strip_tags(html_message)
            send_mail(subject, plain_message, from_email, to, html_message=html_message)

            #Log sending the reset code
            logger('authentication').info(f'Send reset code mail for user [{user_obj.username}] and mail [{user_obj.email}] on IP [{ip_address}]')
 
            content = {'reset_code': reset_code}
            return Response(content, status=status.HTTP_200_OK)

        except:
            logger('authentication').exception(f'Error creating resetcode for user [{username}] and mail [{email}] from IP [{ip_address}]')
            content = {'reset_code': 'XXXXXXX'}
            return Response(content, status=status.HTTP_400_BAD_REQUEST)
Beispiel #10
0
    async def receive(self, text_data):
        message = json.loads(text_data)     # converts the data to Python


        ###### Functions to handle the different request types

        #####################################################################################################
        #### TYPE: connected_update
        ## register this player as connected and send all connection statusses of that game to all players
        if message['type'] == 'connected_update':
            # print('@@@ CONNECTED_UPDATE')
            await self.connected_update(message)

        #####################################################################################################
        #### TYPE: handle_verzaken
        ## Show to all players that a player has noted verzaakt
        if message['type'] == 'notify_verzaken':
            # print('@@@ HANDLE_VERZAKEN')
            await self.notify_verzaken(message)

        #####################################################################################################
        #### TYPE: process_verzaken
        ## Show to all players that a player has noted verzaakt
        # if message['type'] == 'process_verzaken':
        #     print('@@@ PROCESS_VERZAKEN')
        #     await self.process_verzaken(message)

        
        #####################################################################################################
        #### TYPE: get_players   !NOT USED ANYMORE !!!
        elif message['type'] == 'get_players':
            # Get the players for a gameID
            # print('@@@ GET_PLAYERS')
           
            message = json.loads(text_data)     # converts the data to Python
            # print('**', message)

            players = await get_players(message['gameID'])

            # send this info to all players in the group.
            message = {
                'type'      : 'send_players',
                'players'   : players
            }

            # Send message to room group
            await self.channel_layer.group_send(
                self.group_name, 
                {
                    'type': 'send_to_group',        ## Based on this name a function to handle is created
                    'message': message
                }
            )

            # print('GET_PLAYERS')


        #####################################################################################################
        #### TYPE: request_new_round
        ### Send to info to the player to play a new round
        ### Sends back 8 cards, but the cards that have been played in the previous rounds
        ### will be set to no card. This ensures that the cards will be shown on the same position as 
        ### in the previous round.
        ### Also a signal will be send to all other player to load the round.
        ### The troef is klaver for every first round. For the next rounds the troef will be the samen
        ### as the first round
        ###
        elif message['type'] == 'request_new_round':
            logger('debug').debug('REQUEST_NEW_ROUND')

            message = json.loads(text_data)     # converts the data to Python
            # print('**', message)

            # Set the variables to be used.
            matchID         = message['matchID']
            gameID          = message['gameID']
            position        = message['position']
            troef           = message['troef']              # Needs to be included when troef is changed in first round
            button_pressed  = message['button_pressed']

            # print('DUMMY20', matchID, gameID, position, troef )

            ### FIRST: get the information of the game
            game = await get_game(message['gameID'])
            current_leg     = game.legs_completed       # when 0 are completed get leg 0 for the new leg
            current_round   = game.rounds_completed

            ##@@@@@ Only do this when current_leg < n_leg (get from match)
            if current_leg < message['n_legs']:

                ### NEXT Determine the troef that needs to be send
                ### In the first round the default troef is clubs. This can be changed.
                ### In the next rounds in the leg the same troef will be used as in round 0
                troef_choices = ['clubs', 'hearts', 'spades', 'diamonds']
                if current_round != 0:
                    # get the troef from round = 0
                    slag = await get_slag(gameID, current_leg, 0 )
                    for i in range(len(troef_choices)):
                        if troef_choices[i] == slag.troef_id:
                            troef = i
                


                ### NEXT: get all cards of the leg and sort this for the troef
                cards_all = await get_player_cards(matchID, gameID, current_leg, position, troef)

                ### NEXT: get all played cards in the previous rounds of this leg for a position (player)
                played_cards = await get_played_cards_of_leg(gameID, current_leg, position)
                # print('played cards :', played_cards)

                ### NEXT: Remove the playeds cards from the hand, by setting the card to blank
                ### that is, set color and rank to 'no-card'

                cards = cards_all
                for i in range(len(cards)):
                    # check all cards in the hand to match a played card.
                    # When they match then the card will be set to no-card

                    # If played cards is empty the for loop will be skipped
                    # In that case assign all cards to the cards list
                    if len(played_cards) != 0:
                        for played in played_cards:
                            if cards[i] == played:
                                cards[i] = {'color': 'no-card', 'rank': 'no-card' }


                # print('position ', position, cards)

                ### NEXT: Determine which player has to start this round.
                if current_round == 0:
                    next_to_play = current_leg % 4
                else: 
                    # When cards in the round have been played,
                    # then the next person to start depends on the winner of the previous round
                    slag = await get_slag(gameID, current_leg, current_round - 1)
                    next_to_play = slag.player_won

                ## Determine the total roem thusfar in the leg for both parties 
                ## roem is a list of two values for team A and teamB
                ## Note: roem for teamA is : roem[0]['roem__sum']
                roem = await get_roem(gameID, current_leg)     # do not need current_round

                ### Send the information to only the player that requested this new round.
                # Only send to the client (not to the group)
                message = {
                    'type'          : 'send_new_round',
                    'cards'         : cards,
                    'next_to_play'  : next_to_play,
                    'current_leg'   : current_leg,
                    'current_round' : current_round,
                    'troef'         : troef,
                    'roem'          : roem          # is a list with the values of roemA and roemB
                    
                }

                # if not button pressed it only needs to be send to a single player
                if button_pressed == False:
                    await self.send(text_data=json.dumps(message))

                ### Send a message to the other players to if buttonpressed = true

                if button_pressed == True:
                    message = {
                    'type'          : 'signal_to_load_new_round'
                    }

                    # Send message to room group
                    await self.channel_layer.group_send(
                        self.group_name, 
                        {
                            'type': 'send_to_group',        ## Based on this name a function to handle is created
                            'message': message
                        }
                    )

            ### end if
                


        #####################################################################################################
        #### TYPE: request_player_cards
        ### This sends the cards to only the player that reqeusted the cards
        elif message['type'] == 'request_player_cards':
            # print('@@@ REQUEST_PLAYER_CARDS')

            message = json.loads(text_data)     # converts the data to Python
            # print('**', message)

            cards = await get_player_cards(message['matchID'], message['gameID'], message['leg'], message['position'], message['troef'])

            # Only send the the client (not to the group)
            message = {
                'type'      : 'send_player_cards',
                'cards'     : cards
            }
            await self.send(text_data=json.dumps(message))
            # print('Cards send : ', self.channel_name)


        #####################################################################################################
        #### When a player plays a card, this card needs to be communicated to the other players
        #### Django will also update who is next to play and the count on how many cards have been played in this round
        elif message['type'] == 'play_card':
            message = json.loads(text_data)     # converts the data to Python
            # print('@@@ PLAY_CARD')
            # print('Card played by :', message['position'], message['color'], message['rank'])

            # set the next player to throw a card
            message['next_to_play'] = ( message['next_to_play'] + 1 ) % 4 
            message['count_cards_played'] = ( message['count_cards_played'] + 1 )

            # Send message to room group
            await self.channel_layer.group_send(
                self.group_name, 
                {
                    'type': 'send_to_group',        ## Based on this name a function to handle is created
                    'message': message
                }
            )
        #####################################################################################################
        #### TYPE: check_round
        #### the played round is send from player with my_position = 0 to the websocket.
        #### The following needs to be done
        ####  - check who won the round and send this to the group
        #### receive : 'gameID', 'leg', 'round', 'cards', 'troef'
        elif message['type'] == 'check_round':
            message = json.loads(text_data)     # converts the data to Python
            print('@@@ CHECK_ROUND')
            # print(message)

            # FIRST: get the game information
            # We need the info from some fields 
            game = await get_game(message['gameID'])

            # NEXT:  determine the troef played
            troef_choices = ['clubs', 'hearts', 'spades', 'diamonds']
            troef = troef_choices[message['troef']]

            # NEXT: Determine which position started this round.
            # if the round = 0 then determine based on current leg
            # if round > 0 then look at the winner of the previous round
            if message['round'] == 0:
                position_start = (game.legs_completed ) % 4
                # print('Position that started this round: ', position_start)
            else:
                # Get the winner of the previous round (slag)
                slag = await get_slag(message['gameID'], message['leg'], message['round']-1  )
                position_start = slag.player_won
                

            # Determine which player and team won the round
            # print('AAAAA',troef, position_start,message['cards'])
            winner = evaluateSlag(message['cards'], troef, position_start)

            message = {
                'type'          : 'winner_round',
                'winner'        : winner
            }

            # Send message to room group
            await self.channel_layer.group_send(
                self.group_name, 
                {
                    'type': 'send_to_group',        ## Based on this name a function to handle is created
                    'message': message
                }
            )


        #####################################################################################################
        #### TYPE: log_round
        #### the played round is send from player with my_position = 0 to the websocket.
        #### Or verzaakt is reported by a player.
        ####
        #### The following needs to be done
        ####  - store the result of this round in the database
        ####  - Update this game with the correct leg and round numbers
        ####
        #### A variable is used to incidate that the game has ended
        ####
        #### when a slag already exists, then first remove it and then log the new slag
        ###
        ### This procedure needs to determine whether or not a new round needs to be played
        ### There are tree possibilies
        ###  - Play new round
        ###  - Signal end of leg
        ###  - Signal the end of game
        #### 
        #### receive : 'gameID', 'leg', 'round', 'cards', 'troef', 'roem'
        elif message['type'] == 'log_round':
            message = json.loads(text_data)     # converts the data to Python
            # print('@@@ LOG_ROUND')
            # print('***', message)
            await self.process_log_round(message)
           
                
        #####################################################################################################
        #### TYPE: request_scores
        #### For a game get all the leg scores and total score for the game
        elif message['type'] == 'request_scores':
            message = json.loads(text_data)     # converts the data to Python
            # print('@@@ REQUEST SCORES')
            # print(message)

            scores_per_leg , totalscores = await get_current_scores(message['gameID'])

            ### Create the message based on state
            message = {
                'type'                  : 'send_scores',
                'scores_per_leg'        : scores_per_leg,
                'totalscores'           : totalscores
            }

            # Only send the the client that did this request(not to the group)
            await self.send(text_data=json.dumps(message))

            # # Send message to room group
            # await self.channel_layer.group_send(
            #     self.group_name, 
            #     {
            #         'type': 'send_to_group',        ## Based on this name a function to handle is created
            #         'message': message
            #     }
            # )

        #####################################################################################################
        else:
            # Types that do not need to be processed can directly be forwarded to the group
            # like status updates
            # Send message to room group
            # print('@@@@ Other messages')
            await self.channel_layer.group_send(
                self.group_name, 
                {
                    'type': 'send_to_group',        ## Based on this name a function to handle is created
                    'message': message
                }
            )
Beispiel #11
0
def evaluate_leg(gameID, leg):
    '''
    Determine the winner and scores for a completed leg
    '''
    qs = Slag.objects.filter(gameID=gameID, leg=leg)
    

    if len(qs) != 8:
        # print('WARNING: Leg not properly completed')
        logger('debug').debug('WARNING: Leg not properly completed')
        return 'Leg not properly completed'
    else:
        # Determine who took om this leg. (heeft aangenomen)
        player_aangenomen = leg % 4  # In the game variant 'verplicht aannemen'
        
        total_score_A = 0
        total_score_B = 0
        total_roem_A = 0
        total_roem_B = 0
        # determine the total score and roem for both teams
        for slag in qs:
            if slag.teamA_won == True:
                total_score_A = total_score_A + slag.score
                total_roem_A = total_roem_A + slag.roem
            else:
                total_score_B = total_score_B + slag.score
                total_roem_B = total_roem_B + slag.roem

        # Check that the player of Team A succeeded in playing the leg (is 'door')
        if player_aangenomen == 0 or player_aangenomen == 2:
            team = 'team A'
            succeeded = (total_score_A + total_roem_A ) > (total_score_B + total_roem_B )
            if not succeeded:
                # als 'nat'
                total_score_A = 0
                total_roem_A = 0
                total_score_B = 162
                total_roem_B = (total_roem_A + total_roem_B)

            if succeeded and total_score_A == 162:
                total_roem_A = total_roem_A + 100
                pit = True 
            else:
                pit = False

        # Check that the player of Team B succeeded in playing the leg (is 'door')
        if player_aangenomen == 1 or player_aangenomen == 3:
            team = 'team B'
            succeeded = (total_score_B + total_roem_B ) > (total_score_A + total_roem_A )
            if not succeeded:
                # als 'nat'
                total_score_B = 0
                total_roem_B = 0
                total_score_A = 162
                total_roem_A = (total_roem_A + total_roem_B)

            if succeeded and total_score_B == 162:
                total_roem_B = total_roem_B + 100
                pit = True 
            else:
                pit = False

    return [player_aangenomen, succeeded, pit, team, total_score_A, total_roem_A, total_score_B, total_roem_B]