コード例 #1
0
ファイル: update.py プロジェクト: HScarb/rankedftw
def countinously_update(regions=None,
                        check_stop=None,
                        update_manager=None,
                        switch_hour=10):

    update_manager = update_manager or UpdateManager()

    ranking = Ranking.objects.order_by('-id').first()

    if ranking.status != Ranking.COMPLETE_WITH_DATA:
        raise Exception("ranking %d is not in a good state, clean up" %
                        ranking.id)

    season = ranking.season

    cpp = sc2.RankingData(get_db_name(), Enums.INFO)

    while not check_stop(throw=False):

        # Check if we want to switch to new season.

        current_season = Season.get_current_season()
        if current_season.id != season.id:

            if current_season.id != season.get_next().id:
                raise Exception(
                    "something is really wrong, current season is not next")

            if Ladder.objects.filter(season=current_season,
                                     strangeness=Ladder.GOOD).count() > 8:
                season = current_season
                logger.info(
                    "switching to rank new season %d multiple new season ladders was detected"
                    % season.id)

        # Do we want to create new ranking? We want to switch around switch_hour UTC every day but not if ranking is
        # too young. If too old, switch anyway.
        now = utcnow()

        if season.id != ranking.season_id:
            # Create new ranking based on new season.
            ranking = Ranking.objects.create(season=season,
                                             created=now,
                                             data_time=season.start_time(),
                                             min_data_time=season.start_time(),
                                             max_data_time=season.start_time(),
                                             status=Ranking.CREATED)
            logger.info("created new ranking %d based on new season %d" %
                        (ranking.id, season.id))

            cpp.clear_team_ranks()
            cpp.reconnect_db()
            update_manager.save_ranking(cpp, ranking, 0)

        elif ((ranking.created + timedelta(hours=48) < now or
               (ranking.created + timedelta(hours=12) < now
                and now.hour == switch_hour))
              and not ranking.season.near_start(now, days=4)):
            # Create a new ranking within the season.

            cpp.clear_team_ranks()
            cpp.reconnect_db()

            with transaction.atomic():
                new_ranking = Ranking.objects.create(
                    season=season,
                    created=now,
                    data_time=ranking.data_time,
                    min_data_time=ranking.min_data_time,
                    max_data_time=ranking.max_data_time,
                    status=Ranking.CREATED)
                # Copy all caches of old ranking to new ranking. Also remake the full ranking while doing so to get
                # rid of leave leaguers.

                logger.info(
                    "created new ranking %d basing it on copy of ranking %d, seaons %d"
                    % (new_ranking.id, ranking.id, season.id))

                count = ranking.sources.count()
                logger.info(
                    "copying %d cached ladders from ranking %d to ranking %d and adding them to ranking"
                    % (count, ranking.id, new_ranking.id))

                for i, lc in enumerate(ranking.sources.all(), start=1):
                    lc.pk = None
                    lc.created = utcnow()
                    lc.ladder = None
                    lc.ranking = ranking
                    lc.save()

                    new_ranking.sources.add(lc)

                    ladder = Ladder.objects.get(region=lc.region, bid=lc.bid)
                    team_size = Mode.team_size(ladder.mode)
                    stats = cpp.update_with_ladder(
                        ladder.id, lc.id, ladder.region, ladder.mode,
                        ladder.league, ladder.tier, ladder.version,
                        ladder.season_id, to_unix(lc.updated), team_size,
                        ApiLadder(lc.data,
                                  lc.url).members_for_ranking(team_size))

                    if i % 100 == 0:
                        logger.info(
                            "copied and added cache %d/%d, player cache size %d, team cache size %d"
                            % (i, count, stats['player_cache_size'],
                               stats['team_cache_size']))

            ranking = new_ranking
            update_manager.save_ranking(cpp, ranking, 0)
        else:
            logger.info("continuing with ranking %d, season %d" %
                        (ranking.id, season.id))
            cpp.reconnect_db()
            cpp.load(ranking.id)

        now = utcnow()
        until = now.replace(hour=switch_hour, minute=0, second=0)
        if until < now:
            until += timedelta(hours=24)

        update_manager.update_until(ranking=ranking,
                                    cpp=cpp,
                                    regions=regions,
                                    until=until,
                                    check_stop=check_stop)
コード例 #2
0
ファイル: update.py プロジェクト: HScarb/rankedftw
    def update_until(self,
                     ranking=None,
                     cpp=None,
                     regions=None,
                     until=None,
                     check_stop=None,
                     fetch_manager=None,
                     bnet_client=None):
        """ Update until time until (utc) has passed and code outisde will decide if season and/or ranking switching
        should be done. """

        bnet_client = bnet_client or BnetClient()
        fetch_manager = fetch_manager or FetchManager(ranking, regions,
                                                      bnet_client)

        try:

            logger.info(
                "updating season %d, ranking %d, regions %s, until %s" %
                (ranking.season_id, ranking.id, regions, until))

            last_save = utcnow()
            last_season_check = utcnow()
            last_gm = utcnow(days=-20)
            last_plat = utcnow(days=-20)
            last_rest = utcnow(days=-20)

            while not check_stop(throw=False):

                now = utcnow()

                if now > until:
                    logger.info(
                        "we reached until time %s, pausing to switch season/ranking"
                        % until)
                    break

                if now - last_season_check > timedelta(minutes=30):
                    last_season_check = now
                    if ranking.season_id != Season.get_current_season().id:
                        logger.info(
                            "current season %d is closed, pausing to give chance for season switch"
                            % ranking.season_id)
                        break

                if now - last_save > timedelta(seconds=60):
                    self.save_ranking(cpp, ranking,
                                      len(fetch_manager.fetched_queue))
                    last_save = utcnow(
                    )  # This can take a long time, so get new now again.

                if now - last_gm > timedelta(seconds=60):
                    last_gm = now
                    fetch_manager.start_gm()

                if now - last_plat > timedelta(minutes=10):
                    last_plat = now
                    fetch_manager.start_plat()

                if now - last_rest > timedelta(minutes=60):
                    last_rest = now
                    fetch_manager.start_rest()

                try:
                    ladder, status, api_ladder, fetch_time = fetch_manager.pop(
                    )

                    with transaction.atomic():
                        stats = update_ladder_cache(cpp, ranking, ladder,
                                                    status, api_ladder,
                                                    fetch_time)
                        with LogContext(region=ladder.region):
                            logger.info(
                                "saved updated ladder %d and added data to ranking %d, "
                                "updated %d players %d teams, inserted %d players %d teams, "
                                "cache sizes %d players %d teams" % (
                                    ladder.id,
                                    ranking.id,
                                    stats["updated_player_count"],
                                    stats["updated_team_count"],
                                    stats["inserted_player_count"],
                                    stats["inserted_team_count"],
                                    stats["player_cache_size"],
                                    stats["team_cache_size"],
                                ))

                except IndexError:
                    sleep(0.04)

            logger.info("stopped fetching, saving")
            fetch_manager.stop()
            fetch_manager.join()
            self.save_ranking(cpp, ranking, len(fetch_manager.fetched_queue))
        except Exception:
            fetch_manager.stop()
            raise
        cpp.release()
コード例 #3
0
    def get(self, request, *args, tag=None, reverse=None, sort_key=None, **kwargs):
        
        if sort_key == 'ladder-rank':
            return redirect(self.redirect_mmr_url(request, 'clan', tag=tag, reverse=reverse))
        
        context = self.get_context_data()

        json_response = 'json' in request.GET

        if tag is None:
            raise Http404()

        region_id, race_id, league_id = self.extract_filters(request)
        is_reverse, sort_key_id = self.extract_common(reverse, sort_key)

        player = Player.objects.filter(tag=tag, mode=Mode.TEAM_1V1, season=Season.get_current_season()).first()
        if not player:
            raise Http404()

        context['tag'] = tag
        context['clan'] = player.clan

        try:
            data = self.fetch_data(tag, sort_key_id, is_reverse=is_reverse,
                                   league_id=league_id, region_id=region_id, race_id=race_id)
        except ClientError as e:
            logger.exception("Fetch from client error: %s" % str(e))
            context['error'] = 'The server is not feeling well, try again later.'
            return self.respond(context, json_response)

        LadderCommon.update_age(data)

        context['ladder'] = data
        context['team_size'] = 1

        paths = {
            'tag': tag,
            'sort_key': sort_key,
            'reverse': reverse,
        }

        args = {
            'region': Region.key_by_ids.get(region_id, Region.ALL_KEY),
            'league': League.key_by_ids.get(league_id),
            'race': Race.key_by_ids.get(race_id),
        }

        values = [('All', None)] + [(Race.name_by_ids[i], Race.key_by_ids[i])
                                    for i in Race.ids if i != Race.UNKNOWN]
        LadderCommon.set_nav(context, request, clan_url, paths, args, name='race', values=values)

        values = [('All', None)] + [(League.name_by_ids[i], League.key_by_ids[i])
                                    for i in League.ids if i not in (League.UNKNOWN, League.ALL)]
        LadderCommon.set_nav(context, request, clan_url, paths, args, name='league', values=values)

        values = [(Region.name_by_ids[i], Region.key_by_ids[i])
                  for i in Region.ids if i != Region.UNKNOWN]
        LadderCommon.set_nav(context, request, clan_url, paths, args, name='region', values=values)

        values = [('MMR', 'mmr'), ('League points', 'league-points'), ('Games played', 'played'), ('Wins', 'wins'),
                  ('Losses', 'losses'), ('Win rate', 'win-rate')]
        LadderCommon.set_nav(context, request, clan_url, paths, args, name='sort_key', values=values)

        context['reverse_visiting'] = 'visiting' if reverse else ''
        context['reverse_href'] = clan_url(request, paths, args, 'reverse', '' if reverse else '-')

        return self.respond(context, json_response)
コード例 #4
0
def get_top_clans():
    current_season = Season.get_current_season()
    return list(Player.objects
                .filter(season=current_season, mode=Mode.TEAM_1V1, tag__gt='')
                .values('clan', 'tag').annotate(count=Count('tag')).order_by('-count')[:32])
コード例 #5
0
def fetch_new(region=None, check_stop=lambda: None, bnet_client=None):

    with transaction.atomic():

        current_season = Season.get_current_season()

        for count in range(1, 6):
            check_stop()

            res = bnet_client.fetch_current_season(region)
            api_season = res.api_season

            if region == Region.SEA:
                if res.status != 200:
                    logger.info(
                        "could not get season info from %s, status %s, bailing"
                        % (api_season.url, res.status))
                    return
                else:
                    logger.warning("sea is alive")
                    break

            if res.status == 200:
                break

        else:
            level = INFO if region == Region.CN else WARNING
            logger.log(
                level,
                "could not get season info from %s after %d tries, status %s, bailing"
                % (api_season.url, count, res.status))
            return

        # Update or create the season cache, just for bookkeeping.
        try:
            cache = Cache.objects.get(region=region, type=Cache.SEASON, bid=1)
            cache.updated = res.fetch_time
            cache.data = api_season.to_text()
            cache.save()
        except Cache.DoesNotExist:
            Cache.objects.create(url=api_season.url,
                                 bid=1,
                                 type=Cache.SEASON,
                                 region=region,
                                 status=res.status,
                                 created=res.fetch_time,
                                 updated=res.fetch_time,
                                 data=api_season.to_text())

        # Check season.

        if current_season.id == api_season.season_id():
            # We already have latest season.
            pass

        elif current_season.id + 1 == api_season.season_id():
            # New season detected, create new season.
            create_new_season(current_season, api_season.start_date())
            return

        elif current_season.near_start(utcnow(), days=2):
            logger.info(
                "current season %d near start, blizzard says %d, probably cached or other region, bailing"
                % (current_season.id, api_season.season_id()))
            return
        else:
            raise Exception(
                "season mismatch blizzard says %d, current in db is %d" %
                (api_season.season_id(), current_season.id))

    fetch_new_in_region(check_stop, bnet_client, current_season, region)