def get(self, id):
        ''' Returns tournament and pair number information this pair_id.

        Args: 
          id: Tournament ID for this tournament
        Returns: 
          a list of all unique ids in order. Length will necessarily equal
          to the number of pairs in this tournament.
    '''
        tourney = GetTourneyWithIdAndMaybeReturnStatus(self.response, id)
        if not tourney:
            return

        if not CheckUserOwnsTournamentAndMaybeReturnStatus(
                self.response, users.get_current_user(), tourney):
            return

        player_pairs = PlayerPair._query(ancestor=tourney.key).fetch(
            projection=[PlayerPair.id, PlayerPair.pair_no])
        player_pairs.sort(key=lambda p: p.pair_no)
        if not player_pairs:
            SetErrorStatus(
                self.response, 500, "Corrupted Data",
                "Could not find any players for this tournament. " +
                "Consider resetting tournament info.")

        self.response.headers['Content-Type'] = 'application/json'
        self.response.set_status(200)
        self.response.out.write(
            json.dumps({"pair_ids": [p.id for p in player_pairs]}, indent=2))
    def get(self, id, pair_no):
        ''' Returns the opaque pair ID for pair with pair nubmer pair_no in this
        Tournament.

        Args: 
          id: Tournament ID for this tournament.
          pair_no: The pair number whose ID has to be looked up.
    '''
        if not is_int(pair_no):
            SetErrorStatus(
                self.response, 404, "Invalid Pair Number",
                "Pair number must be an integer, was {}".format(pair_no))
            return

        tourney = GetTourneyWithIdAndMaybeReturnStatus(self.response, id)
        if not tourney:
            return

        if not CheckUserOwnsTournamentAndMaybeReturnStatus(
                self.response, users.get_current_user(), tourney):
            return
        player_pairs = PlayerPair._query(
            ndb.GenericProperty('pair_no') == int(pair_no),
            ancestor=tourney.key).fetch(1, projection=[PlayerPair.id])
        if not player_pairs:
            SetErrorStatus(
                self.response, 404, "Invalid Id",
                "Pair pair number {} does not exist in this " +
                "tournament".format(pair_no))
            return
        self.response.headers['Content-Type'] = 'application/json'
        self.response.set_status(200)
        self.response.out.write(
            json.dumps({'pair_id': player_pairs[0].id}, indent=2))
예제 #3
0
    def get(self, id):
        ''' Returns tournament metadata for tournament with id.

        Args: 
          id: tournament ID to look up. Tournament must already have been
              created.
    '''
        user = users.get_current_user()
        tourney = GetTourneyWithIdAndMaybeReturnStatus(self.response, id)
        if not tourney:
            return

        if not CheckUserOwnsTournamentAndMaybeReturnStatus(
                self.response, user, tourney):
            return

        combined_dict = {
            'no_pairs': tourney.no_pairs,
            'no_boards': tourney.no_boards,
            'name': tourney.name,
            'hands': tourney.GetScoredHandList()
        }
        player_pairs = PlayerPair.query(ancestor=tourney.key).fetch()
        player_pairs.sort(key=lambda p: p.pair_no)
        combined_dict['pair_ids'] = [p.id for p in player_pairs]
        for player_pair in player_pairs:
            if player_pair.players:
                for player in player_pair.player_list():
                    player['pair_no'] = player_pair.pair_no
                    combined_dict.setdefault('players', []).append(player)

        self.response.headers['Content-Type'] = 'application/json'
        self.response.set_status(200)
        self.response.out.write(json.dumps(combined_dict, indent=2))
예제 #4
0
  def get(self, id, pair_no):
    ''' Fetch movement for tournament with id and team pair_no. 

    Args:
      id: String. Tournament id. 
      pair_no: Integer. Pair number for the team whose movement we're getting.

    See api for request and response documentation.
    '''
    tourney = GetTourneyWithIdAndMaybeReturnStatus(self.response, id)
    if not tourney:
      return

    if not self._CheckValidPairMaybeSetStatus(tourney, pair_no):
      return

    player_pair = PlayerPair.GetByPairNo(tourney, int(pair_no))
    if not player_pair:
      SetErrorStatus(self.response, 404, "Invalid Request",
                     "Player pair {} not in tournament".format(pair_no))
      return

    if not self._CheckUserAllowedToSeeMovementMaybeSetStatus(
        tourney, player_pair):
      return

    no_hands_per_round, no_rounds = Movement.NumBoardsPerRoundFromTotal(
        tourney.no_pairs, tourney.no_boards)
    try:
      movement = Movement.CreateMovement(
          tourney.no_pairs, no_hands_per_round, no_rounds).GetMovement(
              int(pair_no))
    except ValueError:
      SetErrorStatus(self.response, 500, "Corrupted Data",
                     "No valid movement for this tourney's config")
      return

    movement_list = []
    for round in movement:
      movement_list.append(
          self._GetJsonRoundWithScore(round, tourney, int(pair_no)))

    combined_dict = {
      'name' : tourney.name,
      'players' : player_pair.player_list(),
      'movement': movement_list
    }

    self.response.headers['Content-Type'] = 'application/json'
    self.response.set_status(200)
    self.response.out.write(json.dumps(combined_dict, indent=2))
예제 #5
0
    def _CheckUserHasAccessMaybeSetStatus(self, tourney, hand_no):
        '''Tests if the current user has access to the results of this hand.

    Uses the pair id code, if any, set in the request header to see if the user
    is in one of the teams that is set to play this hand in this movement. 
    Directors always have access.

    Args:
      tourney: Tournament. Current tournament.
      hand_no: Integer. Number of the hand.

    Returns:
      A (Boolean, Integer, [(Integer, Integer)]) tuple. First member is True iff
      the user should have access to the hand provided they played it (or is a
      director). The second member is the pair number of the user (0 for director).
      Only set if first member is True. The last member is the list of 
      (nw_pair, ew_pair) tuples that correspond to the pairs that play hand_no in
      this movement.
    '''
        user = users.get_current_user()
        movement = tourney.GetMovement()
        all_matchups = movement.GetListOfPlayersForHand(hand_no)
        if user and tourney.owner_id == user.user_id():
            return (True, 0, all_matchups)
        if tourney.IsUnlocked():
            SetErrorStatus(
                self.response, 403, "Forbidden User",
                "The tournament is not set up to show hand " +
                "results to players.")
            return (False, None, None)

        error = "Forbidden User"
        pair_id = GetPairIdFromRequest(self.request)
        player_pairs = PlayerPair._query(
            ndb.GenericProperty('id') == pair_id).fetch(
                1, projection=[PlayerPair.pair_no])
        if not pair_id or not player_pairs:
            SetErrorStatus(
                self.response, 403, error,
                "User does not own tournament and is not authenticated " +
                "with a pair code to see the results of this hand.")
            return (False, None, None)
        pair_no = player_pairs[0].pair_no
        if not self._PlayerInMatchupList(pair_no, all_matchups):
            SetErrorStatus(self.response, 403, error,
                           "User does not play this hand.")
            return (False, None, None)
        return (True, pair_no, all_matchups)
예제 #6
0
 def _GetPlayerListForTourney(self, tourney):
   name_list = range(1, tourney.no_pairs + 1)
   for player_pair in PlayerPair.query(ancestor=tourney.key).fetch():
     if player_pair.players:
       player_list = player_pair.player_list()
       if not player_list:
         continue
       elif len(player_list) == 1:
         name_list[player_pair.pair_no - 1] = (player_list[0].get("name"),
                                               None)
       else:
         name_list[player_pair.pair_no - 1] = (player_list[0].get("name"),
                                               player_list[1].get("name"))
     else:
       name_list[player_pair.pair_no - 1] = (None, None)
   return name_list
예제 #7
0
  def _GetJsonRoundWithScore(self, round, tourney, pair_no):
    ''' Converts round information to a json interpretable string adding 
    scored hands if any exist.

    Args:
      round: MovementRound. Contains all player/hand information about a specific
        matchup from the point of view of Pair pair_no. 
      tourney: Tournament. Tournament in which this is happening.
      pair_no: Pair from whose point of view this movement is seen.

    Returns:
      Dict as expected by api. Includes any scores that have already been added.
    '''
    hands = round.hands
    round_str = round.to_dict()
    opp = round.opponent
    if opp:
      opp_pp = PlayerPair.GetByPairNo(tourney, opp)
      if opp_pp:
        round_str["opponent_names"] = [x.get("name") for x in
            opp_pp.player_list()]
    if hands:
      del round_str['hands']
    for h in hands:
      if round.is_north:
        hand_score = HandScore.GetByHandParams(tourney, h, pair_no, 
                                               round.opponent)
      else:
        hand_score = HandScore.GetByHandParams(tourney, h, round.opponent,
                                               pair_no)
      if hand_score:
        round_str.setdefault('hands', []).append({
          'hand_no' : h,
          'score': {
              'calls' : hand_score.calls_dict(),
              'ns_score' : hand_score.get_ns_score(),
              'ew_score' : hand_score.get_ew_score(),
              'notes' : hand_score.notes,
        }})
      else:
        round_str.setdefault('hands', []).append({ 'hand_no' : h })
    return round_str
예제 #8
0
    def _CheckUserHasAccessMaybeSetStatus(self, tourney, ns_pair, ew_pair):
        ''' Tests if the current user has access to a hand with given players.

    Uses the pair id code, if any, set in the request header to see if the user
    is in one of the teams playing the hand. Directors always have access.

    Args:
      tourney. Tournament. Current tournament.
      ns_pair: Integer. Pair number of team playing North/South.
      ew_pair: Integer. Pair number of team playing East/West.

    Returns:
      A (Boolean, Integer) pair. First member is True iff the user has access
      to the hand between ns_pair and ew_pair. Second member is the pair number
      of the user. Only set if first member is True.
    '''
        user = users.get_current_user()
        error = "Forbidden User"
        if user and tourney.owner_id == user.user_id():
            return (True, 0)
        pair_id = GetPairIdFromRequest(self.request)
        if not pair_id:
            SetErrorStatus(
                self.response, 403, error,
                "User does not own tournament and is not authenticated " +
                "with a pair code to overwrite this hand.")
            return (False, None)
        player_pairs = PlayerPair.query(ndb.OR(
            PlayerPair.pair_no == int(ns_pair),
            PlayerPair.pair_no == int(ew_pair)),
                                        ancestor=tourney.key).fetch()
        if (not player_pairs) or (pair_id not in [p.id for p in player_pairs]):
            SetErrorStatus(
                self.response, 403, error,
                "User does not own tournament and is authenticated with " +
                "the wrong code for involved pairs")
            return (False, None)
        return (True, next(p.pair_no for p in player_pairs if p.id == pair_id))
    def get(self, pair_id):
        ''' Returns tournament and pair number information this pair_id.

        Args: 
          pair_id: Opaque secret ID used to look up information for the user.
    '''
        player_pairs = PlayerPair._query(
            ndb.GenericProperty('id') == pair_id).fetch(
                projection=[PlayerPair.pair_no])
        if not player_pairs:
            SetErrorStatus(self.response, 404, "Invalid Id",
                           "Pair number with this ID does not exist")
            return
        info_dict = {
            'tournament_infos': [{
                'pair_no': p.pair_no,
                'tournament_id': str(p.key.parent().id())
            } for p in player_pairs]
        }

        self.response.headers['Content-Type'] = 'application/json'
        self.response.set_status(200)
        self.response.out.write(json.dumps(info_dict, indent=2))
    def _GetMovementHandsAsync(self, tourney, movement, pair_no):
        ''' Converts movement information to a json interpretable string adding 
    scored hands if any exist.

    Args:
      movement: Movement. Movement for this pair.
      tourney: Tournament. Tournament in which this is happening.
      pair_no: Pair from whose point of view this movement is seen.

    Returns:
      List as expected by api. Includes any scores that have already been added.
    '''
        # Dict from round number to list of futures
        hand_futures_dict = defaultdict(list)
        players_futures_dict = {}
        movement_list = []
        for round in movement:
            hands = round.hands
            if not hands:
                continue
            opp = round.opponent
            players_futures_dict[round.round] = PlayerPair.GetByPairNoAsync(
                tourney, opp)
            for h in hands:
                if round.is_north:
                    hand_futures_dict[round.round].append(
                        HandScore.GetByHandParamsAsync(tourney, h, pair_no,
                                                       round.opponent))
                else:
                    hand_futures_dict[round.round].append(
                        HandScore.GetByHandParamsAsync(tourney, h,
                                                       round.opponent,
                                                       pair_no))
        for round in movement:
            hands = round.hands
            round_str = round.to_dict()
            opp = round.opponent
            if opp:
                opp_pp = players_futures_dict[round.round].get_result()
                if opp_pp:
                    round_str["opponent_names"] = [
                        x.get("name") for x in opp_pp.player_list()
                    ]
            if hands:
                del round_str['hands']
            for i in xrange(len(hands)):
                hand_score = hand_futures_dict[round.round][i].get_result()
                if hand_score and not hand_score.deleted:
                    round_str.setdefault('hands', []).append({
                        'hand_no':
                        hands[i],
                        'score': {
                            'calls': hand_score.calls_dict(),
                            'ns_score': hand_score.get_ns_score(),
                            'ew_score': hand_score.get_ew_score(),
                            'notes': hand_score.notes,
                        }
                    })
                else:
                    round_str.setdefault('hands',
                                         []).append({'hand_no': hands[i]})
            movement_list.append(round_str)
        return movement_list