Exemple #1
0
def replay():
    match_id = request.args.get('match_id')
    profile_id = request.args.get('profile_id')

    url = 'https://aoe.ms/replay/?gameId={}&profileId={}'.format(match_id, profile_id)

    try:
        filename = aoeapi.download_rec(url, 'recs')
    except aoeapi.AoeApiError:
        print('could not download valid rec: ', match_id, ' - ', profile_id)
        abort(404)
        return
    except RuntimeError:
        print('could not download valid rec: ', match_id, ' - ', profile_id)
        abort(404)
        return

    print('recs/' + filename)

    start = time.time()
    with open('recs/' + filename, 'rb') as handle:
        data = handle.read()

    handle = io.BytesIO(data)
    summary = mgz.summary.Summary(handle, None)

    end = time.time()
    print('process', end - start, 's')

    os.remove('recs/' + filename)

    map = summary.get_map()
    del map['tiles']

    return json.dumps({
        "players": summary.get_players(),
        "completed": summary.get_completed(),
        "chat": summary.get_chat(),
        "dataset": summary.get_dataset(),
        "diplomacy": summary.get_diplomacy(),
        "duration": summary.get_duration(),
        "encoding": summary.get_encoding(),
        "file_hash": summary.get_file_hash(),
        "language": summary.get_language(),
        "mirror": summary.get_mirror(),
        "owner": summary.get_owner(),
        "platform": summary.get_platform(),
        "postgame": summary.get_postgame(), # null
        "teams": summary.get_teams(),
        "start_time": summary.get_start_time(), # 0
        "restored": summary.get_restored(),
        "ratings": summary.get_ratings(), # empty
        "profile_ids": summary.get_profile_ids(),
        "map": map,
    }, default=str)
Exemple #2
0
# print('recs/' + filename)
# start = time.time()

with open('recs/' + filename, 'rb') as handle:
    data = handle.read()

handle = io.BytesIO(data)
summary = mgz.summary.Summary(handle, None)

# end = time.time()
# print('process', end - start, 's')

os.remove('recs/' + filename)

map = summary.get_map()
del map['tiles']

sys.stdout = old_stdout
print(
    json.dumps(
        {
            "players": summary.get_players(),
            "completed": summary.get_completed(),
            "chat": summary.get_chat(),
            "dataset": summary.get_dataset(),
            "diplomacy": summary.get_diplomacy(),
            "duration": summary.get_duration(),
            "encoding": summary.get_encoding(),
            "file_hash": summary.get_file_hash(),
            "language": summary.get_language(),
Exemple #3
0
    def _add_match(  # pylint: disable=too-many-branches, too-many-return-statements
            self,
            summary,
            played,
            match_hash,
            user_data,
            series_name=None,
            series_id=None,
            platform_id=None,
            platform_match_id=None,
            platform_metadata=None,
            ladder=None,
            build=None):
        """Add a match."""
        try:
            duration = summary.get_duration()
        except RuntimeError:
            LOGGER.error("[m] failed to get duration")
            return False, 'Failed to get duration'

        log_id = match_hash[:LOG_ID_LENGTH]
        platform_data = summary.get_platform()
        rated, ladder_id, platform_id, platform_match_id = merge_platform_attributes(
            ladder, platform_id, platform_match_id, platform_data,
            self.platforms)

        settings = summary.get_settings()
        try:
            map_data = summary.get_map()
        except ValueError:
            LOGGER.error("[m:%s] has an invalid map", log_id)
            return False, 'Invalid map'
        completed = summary.get_completed()
        restored, _ = summary.get_restored()
        has_postgame = summary.has_achievements()
        version_id, game_version, save_version, log_version = summary.get_version(
        )
        try:
            dataset_data = summary.get_dataset()
        except ValueError:
            LOGGER.error("[m:%s] dataset inconclusive", log_id)
            return False, 'Inconclusive dataset'

        teams = summary.get_teams()
        diplomacy = summary.get_diplomacy()
        players = list(summary.get_players())
        mirror = summary.get_mirror()
        if platform_match_id:
            log_id += ':{}'.format(platform_match_id)

        if restored:
            LOGGER.error("[m:%s] is restored game", log_id)
            return False, 'Restored matches not supported'

        if not completed:
            LOGGER.error("[m:%s] was not completed", log_id)
            return False, 'Incomplete matches not supported'

        if user_data and len(players) != len(user_data):
            LOGGER.error("[m:%s] has mismatched user data", log_id)
            return False, 'Mismatched user data'

        if has_transposition(user_data, players):
            LOGGER.error("[m:%s] has mismatched user data (transposition)",
                         log_id)
            return False, 'Transposed user data'

        try:
            dataset = self.session.query(Dataset).filter_by(
                id=dataset_data['id']).one()
        except NoResultFound:
            LOGGER.error("[m:%s] dataset not supported: userpatch id: %s (%s)",
                         log_id, dataset_data['id'], dataset_data['name'])
            return False, 'Dataset not supported'

        series, tournament, event, event_map_id = self._handle_series(
            series_id, series_name, map_data, log_id)

        objects = summary.get_objects()
        try:
            compressed_objects = compress_objects(objects['objects'])
        except struct.error:
            return False, "bad object parsing"

        match = get_unique(
            self.session,
            Match, ['hash', 'platform_match_id'],
            platform_match_id=platform_match_id,
            platform_id=platform_id,
            platform_metadata=platform_metadata,
            played=played,
            hash=match_hash,
            series=series,
            tournament=tournament,
            event=event,
            version_id=version_id.value,
            game_version=game_version,
            save_version=round(save_version, 2),
            log_version=log_version,
            build=build,
            dataset=dataset,
            dataset_version=dataset_data['version'],
            ladder_id=ladder_id,
            rated=rated,
            lobby_name=platform_data['lobby_name'],
            objects=compressed_objects,
            builtin_map_id=map_data['id'],
            event_map_id=event_map_id,
            map_size_id=map_data['dimension'],
            map_name=map_data['name'],
            map_tiles=compress_tiles(map_data['tiles']),
            rms_seed=map_data['seed'],
            rms_zr=map_data['zr'],
            rms_custom=map_data['custom'],
            guard_state=map_data['modes']['guard_state'],
            direct_placement=map_data['modes']['direct_placement'],
            effect_quantity=map_data['modes']['effect_quantity'],
            fixed_positions=map_data['modes']['fixed_positions'],
            water_percent=map_data['water'],
            duration=timedelta(milliseconds=duration),
            completed=completed,
            restored=restored,
            postgame=has_postgame,
            type_id=settings['type'][0],
            difficulty_id=settings['difficulty'][0],
            population_limit=settings['population_limit'],
            map_reveal_choice_id=settings['map_reveal_choice'][0],
            speed_id=settings['speed'][0],
            cheats=settings['cheats'],
            lock_teams=settings['lock_teams'],
            treaty_length=settings['treaty_length'],
            starting_resources_id=settings['starting_resources'][0],
            starting_age_id=settings['starting_age'][0],
            victory_condition_id=settings['victory_condition'][0],
            team_together=settings['team_together'],
            all_technologies=settings['all_technologies'],
            lock_speed=settings['lock_speed'],
            multiqueue=settings['multiqueue'],
            diplomacy_type=diplomacy['type'],
            team_size=diplomacy.get('team_size'),
            mirror=mirror,
            starting_town_centers=objects.get('tcs'),
            starting_walls=objects.get('stone_walls'),
            starting_palisades=objects.get('palisade_walls'))

        winning_team_id = None
        for data in players:
            team_id = None
            for i, team in enumerate(teams):
                if data['number'] in team:
                    team_id = i
            if data['winner']:
                winning_team_id = team_id
            feudal_time = data['achievements']['technology']['feudal_time']
            castle_time = data['achievements']['technology']['castle_time']
            imperial_time = data['achievements']['technology']['imperial_time']
            try:
                get_unique(self.session,
                           Team, ['match', 'team_id'],
                           winner=(team_id == winning_team_id),
                           match=match,
                           team_id=team_id)
                if data['user_id']:
                    get_unique(self.session,
                               User, ['id', 'platform_id'],
                               id=str(data['user_id']),
                               platform_id=platform_id)
                player = get_unique(
                    self.session,
                    Player, ['match_id', 'number'],
                    civilization_id=int(data['civilization']),
                    team_id=team_id,
                    match_id=match.id,
                    dataset=dataset,
                    platform_id=platform_id,
                    user_id=data['user_id'],
                    user_name=data['name'] if data['user_id'] else None,
                    human=data['human'],
                    name=data['name'],
                    number=data['number'],
                    color_id=data['color_id'],
                    start_x=data['position'][0],
                    start_y=data['position'][1],
                    winner=data['winner'],
                    mvp=data['mvp'],
                    cheater=data['cheater'],
                    score=data['score'],
                    rate_snapshot=data['rate_snapshot'],
                    military_score=data['achievements']['military']['score'],
                    units_killed=data['achievements']['military']
                    ['units_killed'],
                    hit_points_killed=data['achievements']['military']
                    ['hit_points_killed'],
                    units_lost=data['achievements']['military']['units_lost'],
                    buildings_razed=data['achievements']['military']
                    ['buildings_razed'],
                    hit_points_razed=data['achievements']['military']
                    ['hit_points_razed'],
                    buildings_lost=data['achievements']['military']
                    ['buildings_lost'],
                    units_converted=data['achievements']['military']
                    ['units_converted'],
                    economy_score=data['achievements']['economy']['score'],
                    food_collected=data['achievements']['economy']
                    ['food_collected'],
                    wood_collected=data['achievements']['economy']
                    ['wood_collected'],
                    stone_collected=data['achievements']['economy']
                    ['stone_collected'],
                    gold_collected=data['achievements']['economy']
                    ['gold_collected'],
                    tribute_sent=data['achievements']['economy']
                    ['tribute_sent'],
                    tribute_received=data['achievements']['economy']
                    ['tribute_received'],
                    trade_gold=data['achievements']['economy']['trade_gold'],
                    relic_gold=data['achievements']['economy']['relic_gold'],
                    technology_score=data['achievements']['technology']
                    ['score'],
                    feudal_time=timedelta(
                        seconds=feudal_time) if feudal_time else None,
                    castle_time=timedelta(
                        seconds=castle_time) if castle_time else None,
                    imperial_time=timedelta(
                        seconds=imperial_time) if imperial_time else None,
                    explored_percent=data['achievements']['technology']
                    ['explored_percent'],
                    research_count=data['achievements']['technology']
                    ['research_count'],
                    research_percent=data['achievements']['technology']
                    ['research_percent'],
                    society_score=data['achievements']['society']['score'],
                    total_wonders=data['achievements']['society']
                    ['total_wonders'],
                    total_castles=data['achievements']['society']
                    ['total_castles'],
                    total_relics=data['achievements']['society']
                    ['total_relics'],
                    villager_high=data['achievements']['society']
                    ['villager_high'])
            except RuntimeError:
                LOGGER.warning(
                    "[m:%s] failed to insert players (probably bad civ id: %d)",
                    log_id, data['civilization'])
                return False, 'Failed to load players'

            if match.platform_id in [PLATFORM_VOOBLY, PLATFORM_IGZ
                                     ] and not user_data and player.human:
                self._guess_match_user(player, data['name'], match.platform_id)

        match.winning_team_id = winning_team_id
        success, attrs = save_extraction(self.session, summary, ladder_id,
                                         match.id, dataset_data['id'], log_id)
        if success:
            match.has_playback = True
            match.state_reader_version = attrs['version']
            match.state_reader_interval = attrs['interval']
            match.state_reader_runtime = attrs['runtime']

        save_chat(self.session, summary.get_chat(), match.id)
        return match, None
Exemple #4
0
    def _add_match( # pylint: disable=too-many-branches
            self, summary, played, match_hash, user_data,
            series_name=None, series_id=None, platform_id=None,
            platform_match_id=None, ladder=None
    ):
        """Add a match."""
        try:
            postgame = summary.get_postgame()
            duration = summary.get_duration()
        except RuntimeError:
            LOGGER.error("[m] failed to get duration")
            return False

        rated = False
        from_voobly, ladder_name, rated, _ = summary.get_ladder()
        if ladder:
            rated = True
        if not ladder:
            ladder = ladder_name
        if from_voobly and not platform_id:
            platform_id = PLATFORM_VOOBLY
        settings = summary.get_settings()
        map_data = summary.get_map()
        completed = summary.get_completed()
        restored, _ = summary.get_restored()
        has_postgame = bool(postgame)
        major_version, minor_version = summary.get_version()
        dataset_data = summary.get_dataset()
        teams = summary.get_teams()
        diplomacy = summary.get_diplomacy()
        players = list(summary.get_players())
        mirror = summary.get_mirror()
        log_id = match_hash[:LOG_ID_LENGTH]
        if platform_match_id:
            log_id += ':{}'.format(platform_match_id)

        if restored:
            LOGGER.error("[m:%s] is restored game", log_id)
            return False

        if not completed:
            LOGGER.error("[m:%s] was not completed", log_id)
            return False

        if user_data and len(players) != len(user_data):
            LOGGER.error("[m:%s] has mismatched user data", log_id)
            return False

        if platform_id:
            try:
                if platform_id in VOOBLY_PLATFORMS:
                    ladder_id = voobly.lookup_ladder_id(ladder)
                else:
                    ladder_id = 1 # fix..
                ladder = self._get_unique(
                    Ladder, keys=['id', 'platform_id'], id=ladder_id,
                    platform_id=platform_id, name=ladder
                )
            except ValueError:
                ladder_id = None
        else:
            ladder_id = None

        try:
            dataset = self.session.query(Dataset).filter_by(id=dataset_data['id']).one()
        except NoResultFound:
            LOGGER.error("[m:%s] dataset not supported: userpatch id: %s (%s)",
                         log_id, dataset_data['id'], dataset_data['name'])
            return False

        series, tournament, event, event_map_id = self._handle_series(series_id, series_name, map_data, log_id)
        if series:
            played = series.played

        match = self._get_unique(
            Match, ['hash', 'platform_match_id'],
            platform_match_id=platform_match_id,
            platform_id=platform_id,
            played=played,
            hash=match_hash,
            series=series,
            tournament=tournament,
            event=event,
            version=major_version,
            minor_version=minor_version,
            dataset=dataset,
            dataset_version=dataset_data['version'],
            ladder_id=ladder_id,
            rated=rated,
            builtin_map_id=map_data['id'],
            event_map_id=event_map_id,
            map_size_id=map_data['dimension'],
            map_name=map_data['name'],
            rms_seed=map_data['seed'],
            rms_zr=map_data['zr'],
            rms_custom=map_data['custom'],
            guard_state=map_data['modes']['guard_state'],
            direct_placement=map_data['modes']['direct_placement'],
            effect_quantity=map_data['modes']['effect_quantity'],
            fixed_positions=map_data['modes']['fixed_positions'],
            duration=timedelta(milliseconds=duration),
            completed=completed,
            restored=restored,
            postgame=has_postgame,
            type_id=settings['type'][0],
            difficulty_id=settings['difficulty'][0],
            population_limit=settings['population_limit'],
            map_reveal_choice_id=settings['map_reveal_choice'][0],
            speed_id=settings['speed'][0],
            cheats=settings['cheats'],
            lock_teams=settings['lock_teams'],
            starting_resources_id=settings['starting_resources'][0],
            starting_age_id=settings['starting_age'][0],
            victory_condition_id=settings['victory_condition'][0],
            team_together=settings['team_together'],
            all_technologies=settings['all_technologies'],
            lock_speed=settings['lock_speed'],
            multiqueue=settings['multiqueue'],
            diplomacy_type=diplomacy['type'],
            team_size=diplomacy.get('team_size'),
            mirror=mirror
        )

        winning_team_id = None
        for data in players:
            team_id = None
            for i, team in enumerate(teams):
                if data['number'] in team:
                    team_id = i
            if data['winner']:
                winning_team_id = team_id
            feudal_time = data['achievements']['technology']['feudal_time']
            castle_time = data['achievements']['technology']['castle_time']
            imperial_time = data['achievements']['technology']['imperial_time']
            self._get_unique(
                Team,
                ['match', 'team_id'],
                winner=(team_id == winning_team_id),
                match=match,
                team_id=team_id
            )
            player = self._get_unique(
                Player,
                ['match_id', 'number'],
                civilization_id=int(data['civilization']),
                team_id=team_id,
                match_id=match.id,
                dataset=dataset,
                platform_id=platform_id,
                human=data['human'],
                name=data['name'],
                number=data['number'],
                color_id=data['color_id'],
                start_x=data['position'][0],
                start_y=data['position'][1],
                winner=data['winner'],
                mvp=data['mvp'],
                score=data['score'],
                rate_snapshot=data['rate_snapshot'],
                military_score=data['achievements']['military']['score'],
                units_killed=data['achievements']['military']['units_killed'],
                hit_points_killed=data['achievements']['military']['hit_points_killed'],
                units_lost=data['achievements']['military']['units_lost'],
                buildings_razed=data['achievements']['military']['buildings_razed'],
                hit_points_razed=data['achievements']['military']['hit_points_razed'],
                buildings_lost=data['achievements']['military']['buildings_lost'],
                units_converted=data['achievements']['military']['units_converted'],
                economy_score=data['achievements']['economy']['score'],
                food_collected=data['achievements']['economy']['food_collected'],
                wood_collected=data['achievements']['economy']['wood_collected'],
                stone_collected=data['achievements']['economy']['stone_collected'],
                gold_collected=data['achievements']['economy']['gold_collected'],
                tribute_sent=data['achievements']['economy']['tribute_sent'],
                tribute_received=data['achievements']['economy']['tribute_received'],
                trade_gold=data['achievements']['economy']['trade_gold'],
                relic_gold=data['achievements']['economy']['relic_gold'],
                technology_score=data['achievements']['technology']['score'],
                feudal_time=timedelta(seconds=feudal_time) if feudal_time else None,
                castle_time=timedelta(seconds=castle_time) if castle_time else None,
                imperial_time=timedelta(seconds=imperial_time) if imperial_time else None,
                explored_percent=data['achievements']['technology']['explored_percent'],
                research_count=data['achievements']['technology']['research_count'],
                research_percent=data['achievements']['technology']['research_percent'],
                society_score=data['achievements']['society']['score'],
                total_wonders=data['achievements']['society']['total_wonders'],
                total_castles=data['achievements']['society']['total_castles'],
                total_relics=data['achievements']['society']['total_relics'],
                villager_high=data['achievements']['society']['villager_high']
            )
            if match.platform_id == PLATFORM_VOOBLY and not user_data:
                self._guess_match_user(player, data['name'])

        match.winning_team_id = winning_team_id
        return match