Example #1
0
    def match_start(self, payload: typing.Dict[str, typing.Any],
                    user: DiscordUser):
        """
        We will scaffold a basic match into the database and give it a status of
        'initial'. This status changes when the replay parser successfully runs
        in which case the status will change to 'final'. We will have a background
        cron job that will destroy any match that is 'initial' when it has elapsed
        4 hours from its creation time to account for "abandoned" matches.

        Parameters
        ----------
        payload
        user

        Returns
        -------

        """
        log.debug('In match start')
        game_id = str(payload['game_id'])
        observers = payload['observers']
        players = payload['players']

        match, match_created = TempMatch.objects.get_or_create(id=game_id,
                                                               defaults={
                                                                   'status':
                                                                   'initial',
                                                               })
        for o in observers:
            if o['handle'] == '':
                continue

            log.debug(f'creating {o}')
            obs = utils.fetch_or_create_profile(o['handle'])
            match.observers.add(obs)
        match.save()

        for p in players:
            profile = utils.fetch_or_create_profile(p['handle'])
            TempRoster.objects.get_or_create(match=match,
                                             sc2_profile=profile,
                                             defaults={
                                                 'team_number': p['team'],
                                                 'position_number': p['slot'],
                                                 'color': p['color'],
                                             })
            # Look for current connected clients
            for user in profile.discord_users.all():
                heartbeat = user.client_heartbeat
                now = datetime.now(timezone.utc)
                if now - heartbeat < timedelta(minutes=10):
                    match.clients.add(user)

        print('done!')
        new_match.send(sender=self.__class__, instance=match)
Example #2
0
    def _update(self, pb: PlayerBank):
        profile_cache = {}
        profile = utils.fetch_or_create_profile(pb.id, profile_cache)
        for mode in pb.modes:
            print(f'updating self for mode {mode}')
            obj = pb.modes[mode]
            Leaderboard.objects.get_or_create(profile=profile,
                                              mode=mode,
                                              defaults={
                                                  'wins':
                                                  int(obj.get('wins', 0)),
                                                  'games':
                                                  int(obj.get('games', 0)),
                                                  'losses':
                                                  int(obj.get('losses', 0)),
                                                  'elo':
                                                  float(obj.get('elo', 0)),
                                              })
        # Update records where the 'time' field is greater than last update.
        mode = pb.last_game.get('mode')
        if mode is None:
            return
        time = int(pb.last_game.get('time'), 0)
        players = pb.last_game.get('players', {})
        for id, stats in players.items():
            profile = utils.fetch_or_create_profile(id, profile_cache)
            print(f'getting ready to update {mode} for {profile.name}')
            wins = int(stats.get('wins', 0))
            games = int(stats.get('games', 0))
            losses = int(stats.get('losses', 0))
            elo = float(stats.get('elo', 0))
            lb, created = Leaderboard.objects.get_or_create(profile=profile,
                                                            mode=mode,
                                                            defaults={
                                                                'wins': wins,
                                                                'games': games,
                                                                'losses':
                                                                losses,
                                                                'elo': elo
                                                            })
            if created:
                continue
            # updated_iso = lb.updated.timestamp()
            # Can't use time. Epoch is not UTC based.
            if lb.games > games:
                continue

            lb.wins = wins
            lb.losses = losses
            lb.games = games
            lb.elo = elo
            lb.save()
Example #3
0
def import_leaderboards(cache=None):
    cache = cache if cache is not None else {}
    for l in leaderboards:

        toon = fetch_or_create_profile(l.get('player_handle'), cache)

        print(f'Importing {toon.name}')
        wins = l.get('wins', 0)
        games = l.get('games', 0)
        losses = games - wins
        models.Leaderboard.objects.update_or_create(
            profile=toon,
            mode='2v2v2v2',
            defaults={
                'created': l.get('created'),
                'wins': wins,
                'games': games,
                'losses':  losses,
                'elo': l.get('elo'),

            }
        )
Example #4
0
def import_matches(match_set=matches):
    cache = {}
    handle_map = {h['id']:h['handle'] for h in handles}
    arcade_map = models.Game.objects.all().first()
    guild = import_guild()
    game = import_game()
    for m in match_set:

        try:
            guild, season, league = None, None, None
            print(f"Importing Match{m.get('id')}")
            related_rosters = [r for r in rosters if r['match_id'] == m['id']]
            related_events = [me for me in match_events if me['match_id'] == m['id']]


            season = None
            league = None
            if m['league_id'] is not None:
                league = get_league(m['league_id'])

            if m['season_id'] is not None and league is not None:
                season = get_season(m['season_id'], league)

            if m['game_id'] is None:
                # No game Id. This match will never be able to get imported.
                # Make a very long fake one.
                m['game_id'] = ''.join(str(random.randint(0, 9)) for _ in range(30))
                print(f"Using Game ID {m['game_id']}")
            match, created = models.Match.objects.get_or_create(
                id=m['game_id'],
                defaults={
                    'created': m['created'],
                    'guild': guild,
                    'arcade_map': arcade_map,
                    'league': league,
                    'season': season,
                    'legacy': True,
                    'ranked': True,
                }
            )
            team_map = {0: {'players': []}, 1: {'players': []}, 2: {'players': []}, 3: {'players': []}}
            for r in related_rosters:
                roster_handle_string = None
                roster_handle_string = handle_map[r['handle_id']]
                #for h in handles:
                #    if h['id'] == r['handle_id']:
                #        roster_handle_string = h['handle']
                print(f"Importing Roster Match {match.id}")
                print(f"Handle {roster_handle_string}")

                handle = fetch_or_create_profile(roster_handle_string, cache)

                team_map[r['team_number']]['players'].append(handle)
                team_map[r['team_number']]['position'] = get_team_position(r['position_number'])
                lane = get_lane(r['position_number'], related_rosters)
                if lane is not None:
                    lane = get_profile(lane, handle_map, cache)
                roster, _ = models.Roster.objects.get_or_create(
                    match=match,
                    sc2_profile=handle,
                    team_number=r['team_number'],
                    position_number=r['position_number'],
                    defaults={
                        'created': r['created'],
                        'color': r['color'],
                        'lane': lane,
                    }
                )



            for me in [r for r in related_events]:

                # Need to get the original handle profile string
                handle_string = None
                opposing_handle_string = None
                for h in handles:
                    if h['id'] == me['opposing_handle_id']:
                        opposing_handle_string = h['handle']
                    if h['id'] == me['handle_id']:
                        handle_string = h['handle']
                sc2handle, opposing_handle = None, None
                if handle_string is not None:
                    sc2handle = fetch_or_create_profile(handle_string, cache)
                if opposing_handle_string is not None:
                    opposing_handle = fetch_or_create_profile(opposing_handle_string, cache)
                print(f"Importing Match {match.id} Event {me['key']}")

                if me['key'] == 'WIN':
                    models.MatchWinner.objects.update_or_create(
                        match=match,
                        profile=sc2handle
                    )
                    update_team_outcome(team_map, sc2handle, 'win')

                elif me['key'] == 'LOSS':
                    models.MatchLoser.objects.update_or_create(
                        match=match,
                        profile=sc2handle,
                        defaults={
                            'killer': None,
                            'left_game': False,
                            'game_time': me.get('game_time', 0) or 0,
                            'victim_number': 0,
                        }
                    )
                    update_team_outcome(team_map, sc2handle, 'loss')
                elif me['key'] == 'DRAW':
                    match.draw = True
                    match.save()
                    update_team_outcome(team_map, sc2handle, 'draw')
                else:
                    game_event_name, created = models.GameEventName.objects.get_or_create(
                        id=me['key'],
                        defaults={'title': f"New Game Event {me['key']}"}
                    )
                    obj, _ = models.GameEvent.objects.get_or_create(
                        key=game_event_name,
                        match=match,
                        profile=sc2handle,
                        opposing_profile=opposing_handle,
                        game_time=me['game_time'],
                        defaults= {
                            'value': me['value'],
                            'description': me['description'],
                            'total_score': 0,
                            'minerals_on_hand': 0,
                        }
                    )
                    print(obj.key)
            updated_rosters = models.Roster.objects.filter(match=match)
            for team_num, team_details in team_map.items():
                team_obj = get_or_create_team(team_details['players'])
                print(f"Mapping {team_details}")
                print(team_obj)
                match_team, created = models.MatchTeam.objects.get_or_create(
                    match=match,
                    team=team_obj,
                    defaults={
                        'position': team_details.get('position', -1),
                        'outcome': team_details.get('outcome', "unknown"),
                    }

                )
                for ros in updated_rosters:
                    if ros.sc2_profile in team_details['players']:
                        ros.team = match_team
                        ros.save()

        except models.SC2Profile.DoesNotExist:
            continue
    return cache
Example #5
0
def get_profile(handle, handle_map, cache={}) -> typing.Optional[models.SC2Profile]:
    handle_string = handle_map[handle['handle_id']]
    return fetch_or_create_profile(handle_string, cache)