Esempio n. 1
0
    def setUp(self):
        # Create some saesons
        for year in range(1994, 2015):
            season = Season(season=year)
            season.save()

        self.seasons = Season.objects.all()
Esempio n. 2
0
def create_new_season(current_season, end_date):

    # New season.
    logger.info("detected season change")

    # New season date is not super important, ladders around break will end up in correct season, so
    # set it to today + 1 day.
    season = current_season

    season.end_date = end_date
    season.save()
    logger.info("set end date %s on season %d" % (season.end_date, season.id))

    next_season = season.get_next()
    next_season.start_date = end_date + timedelta(days=1)
    next_season.year = next_season.start_date.year
    next_season.number = 1 if next_season.year != season.year else season.number + 1
    next_season.name = "%d Season %d" % (next_season.year, next_season.number)
    next_season.save()
    logger.info("set start data %s, year, name and number on season %d" %
                (next_season.start_date, next_season.id))

    next_next_season = Season(id=next_season.id + 1,
                              start_date=None,
                              end_date=None,
                              year=0,
                              number=0,
                              name='',
                              version=Version.LOTV)
    next_next_season.save()
    logger.info("created empty season %d" % next_next_season.id)

    # Fixing rankings if they ended up with data time after season end.

    rankings = Ranking.objects.filter(
        season=season,
        status__in=(Ranking.COMPLETE_WITH_DATA, Ranking.COMPLETE_WITOUT_DATA),
        data_time__gte=season.end_time()).order_by('-id')

    for i, ranking in enumerate(rankings):
        ranking.data_time = season.end_time() - timedelta(seconds=i)
        ranking.save()
        logger.info(
            "changed data_time to %s for ranking %d since it was after season break"
            % (ranking.data_time, ranking.id))

    # Warn about the event to make monitoring send eamil.

    logger.warning(
        "season break detected, current is now season %d, start_date %s" %
        (next_season.id, next_season.start_date))
Esempio n. 3
0
def refetch_past_seasons(check_stop=lambda: None,
                         bnet_client=None,
                         now=None,
                         skip_fetch_new=False):

    bnet_client = bnet_client or BnetClient()
    now = now or utcnow()

    # Wait for this date before refetching season.
    season_end_limit = now - timedelta(
        days=Season.REFETCH_PAST_MIN_DAYS_AFTER_SEASON_END)

    # Fetch new for a while after season close to make sure we got all ladders. Since we don't save non 200 leagues
    # we can still miss ladders here, but unlikely. There is no point in continuing after need_refetch_limit since they
    # will not be picked up in the ranking anyway.
    prev_season = Season.get_current_season().get_prev()
    need_refetch_limit = prev_season.end_time() + timedelta(
        days=Season.REFETCH_PAST_UNTIL_DAYS_AFTER_SEASON_END)
    if not skip_fetch_new and prev_season.end_time(
    ) < now <= need_refetch_limit:
        for region in Region.ranking_ids:
            fetch_new_in_region(check_stop, bnet_client, prev_season, region)

    # Refetch all past seasons.
    for season in Season.objects.filter(
            id__gt=14, end_date__lt=season_end_limit).order_by('-id'):
        refetch_past_season(season, now, check_stop, bnet_client)
        check_stop()
Esempio n. 4
0
def get_season_based_on_fetch_time_and_match(fetch_time, match):
    """
    Mach is a really special snowflake, it can return curr when it is prev right after season switch but never prev
    instead of curr (since if a new ladder is referred the player_ladder is up to date). This code will trust that
    prev/curr is correct and let code outside make a sanity check and keep it as nyd if this fails.

    Returns the ladder's season based on fetch_time and match.
    """

    if match not in ('curr', 'prev'):
        raise Exception("match '%s' unexpected" % match)

    fetch_season = Season.get_active(fetch_time)

    if fetch_season.near_start(fetch_time):
        # May be season before if another region caused the season switch.
        fetch_valid = -1

    elif fetch_season.is_open() or fetch_season.near_end(fetch_time):
        # We may actually be in the next season.
        fetch_valid = 1
    else:

        # We are mid season so it is correct.
        fetch_valid = 0

    if match == 'prev':
        fetch_season = fetch_season.get_prev()

    return fetch_season, fetch_valid
Esempio n. 5
0
    def fetch_data(tag, sort_key_id, is_reverse=None, league_id=None, region_id=None, race_id=None):

        # Get ids from db.

        teams = {t.id: t for t in
                 Team.objects
                 .filter(member0__tag=tag, mode=Mode.TEAM_1V1, season=Season.get_current_season())
                 .all()
                 .select_related('member0')}

        # Fetch data from server.

        data = client.get_clan(team_ids=list(teams.keys()), key=sort_key_id, reverse=is_reverse,
                               region=region_id, race=race_id, league=league_id)

        # Fetch information about teams from database.

        team_ranks = data['teams']

        for tr in team_ranks:
            t = teams[tr["team_id"]]
            tr['rank'] += 1
            tr["m0_id"] = t.member0.id
            tr["m0_name"] = t.member0.name
            tr["m0_bnet_url"] = get_bnet_url(t.member0)

        return data
Esempio n. 6
0
    def get(self, request, *args, **kwargs):
        context = self.get_context_data()

        current_season = Season.get_current_season()

        clan = request.GET.get('clan', None)
        if clan is None:
            context['clans'] = cache_value("top_clans", 1200, get_top_clans)
        else:
            clan = clan.strip()
            context['search'] = True

            clans = list(Player.objects
                         .filter(season=current_season,
                                 mode=Mode.TEAM_1V1,
                                 tag__gt='')
                         .filter(Q(clan__istartswith=clan) | Q(tag__istartswith=clan))
                         .values('clan', 'tag').annotate(count=Count('tag')).order_by('-count')[:33])

            if len(clans) == 33:
                clans = clans[:32]
                context['left_out'] = True

            clans.sort(key=lambda c: c['clan'])

            if len(clans) == 1:
                return redirect('clan', tag=clans[0]['tag'], reverse='', sort_key=DEFAULT_SORT_KEY)

            context['clans'] = clans

        return self.render_to_response(context)
Esempio n. 7
0
 def create_season(self, **kwargs):
     kwargs = merge_args(
         {
             'id': 16,
             'start_date': '2013-11-11',
             'end_date': '2014-01-03',
             'name': '2013 Season 6',
             'year': 2013,
             'number': 6,
             'version': Version.HOTS
         }, **kwargs)
     try:
         self.get(Season, id=kwargs['id'])
         raise AssertionError("Season with id %d already exists." %
                              kwargs['id'])
     except Season.DoesNotExist:
         pass
     self.season = Season(**kwargs)
     self.season.save()
     return self.season
Esempio n. 8
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, 3):
            check_stop()

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

            if res.status == 200:
                update_season_cache(api_season, region, res)

                # Check season.
                if current_season.id == api_season.season_id():
                    # We already have latest season, continue with fetch.
                    break

                elif current_season.id + 1 == api_season.season_id():
                    # New season detected, create new season and wait for next fetch new.
                    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))

        else:
            # Is should be safe to continue after this since season id is in call to blizzard api. This is info logging
            # because it happens all the time due to some blizzard bug.
            logger.log(
                INFO,
                "could not get season info from %s after %d tries, status %s, skipping season check"
                % (api_season.url, count, res.status))

    fetch_new_in_region(check_stop, bnet_client, current_season, region)
Esempio n. 9
0
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)
Esempio n. 10
0
    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()
Esempio n. 11
0
class Db(object):
    """ Helper class to create test data in db. """
    def __init__(self):
        self.db_name = connection.settings_dict['NAME']
        print(self.db_name)
        self.team = None
        self.cache = None
        self.player = None
        self.season = None
        self.ladder = None
        self.ranking = None
        self.ranking_data = None
        self.default_ranking_data__data = {}
        self.clear_defaults()

    def clear_defaults(self):
        self.default_ranking_data__data = {}

    @staticmethod
    def filter(klass, *args, **kwargs):
        return klass.objects.filter(*args, **kwargs)

    @staticmethod
    def count(klass, *args, **kwargs):
        return klass.objects.filter(*args, **kwargs).count()

    @staticmethod
    def get(klass, *args, **kwargs):
        return klass.objects.get(*args, **kwargs)

    @staticmethod
    def objects(klass):
        return klass.objects

    @staticmethod
    def all(klass):
        return klass.objects.all()

    @staticmethod
    def execute(sql):
        cursor = connection.cursor()
        cursor.execute(sql)
        return cursor

    def delete_all(self, keep=None, delete=None):
        for d in (delete or [
                RankingData, RankingStats, Cache, Ranking, Team, Player,
                Ladder, Season
        ]):
            if d not in (keep or []):
                if d == Ranking:
                    cursor = connection.cursor()
                    cursor.execute("update cache set ranking_id = NULL")
                if d == Ladder:
                    cursor = connection.cursor()
                    cursor.execute("update cache set ladder_id = NULL")
                self.all(d).delete()

    def create_season(self, **kwargs):
        kwargs = merge_args(
            {
                'id': 16,
                'start_date': '2013-11-11',
                'end_date': '2014-01-03',
                'name': '2013 Season 6',
                'year': 2013,
                'number': 6,
                'version': Version.HOTS
            }, **kwargs)
        try:
            self.get(Season, id=kwargs['id'])
            raise AssertionError("Season with id %d already exists." %
                                 kwargs['id'])
        except Season.DoesNotExist:
            pass
        self.season = Season(**kwargs)
        self.season.save()
        return self.season

    def create_cache(self, type=Cache.LADDER, members=None, **kwargs):
        data = kwargs.pop('data', None)
        if data is None and members is not None:
            data = gen_ladder_data(members)

        kwargs = merge_args(
            {
                'bid': randint(1, 1e6),
                'url': 'http://bnet/' + uniqueid(10),
                'type': type,
                'region': Region.EU,
                'created': utcnow(),
                'updated': utcnow(),
                'status': 200,
                'retry_count': 0
            }, **kwargs)
        kwargs['data'] = json.dumps(data)

        self.cache = Cache(**kwargs)
        self.cache.save()
        return self.cache

    def create_ladder(self, **kwargs):
        kwargs = merge_args(
            {
                'bid': 1,
                'region': Region.EU,
                'strangeness': Ladder.GOOD,
                'league': League.GOLD,
                'tier': 0,
                'version': Version.HOTS,
                'mode': Mode.TEAM_1V1,
                'season': self.season,
                'first_join': utcnow(),
                'last_join': utcnow(),
                'created': utcnow(),
                'updated': utcnow(),
                'max_points': 20
            }, **kwargs)

        self.ladder = Ladder(**kwargs)
        self.ladder.save()
        return self.ladder

    def create_player(self, **kwargs):
        kwargs = merge_args(
            {
                'bid': randint(0, 1e9),
                'region': Region.EU,
                'realm': 1,
                'mode': Mode.TEAM_1V1,
                'season': self.season,
                'race': Race.ZERG,
                'name': uniqueid(12),
                'clan': uniqueid(32),
                'tag': uniqueid(6)
            }, **kwargs)
        self.player = Player(**kwargs)
        self.player.save()
        return self.player

    def create_team(self, **kwargs):
        kwargs = merge_args(
            dict(region=Region.EU,
                 mode=Mode.TEAM_1V1,
                 season=self.season,
                 version=Version.HOTS,
                 league=League.GOLD,
                 member0=self.player,
                 member1=None,
                 member2=None,
                 member3=None,
                 race0=Race.ZERG,
                 race1=Race.UNKNOWN,
                 race2=Race.UNKNOWN,
                 race3=Race.UNKNOWN), **kwargs)

        self.team = Team(**kwargs)
        self.team.save()
        return self.team

    def create_teams(self, count=1, **kwargs):
        teams = []
        for i in range(count):
            self.create_player(name="%s-%d" % (uniqueid(8), i))
            teams.append(self.create_team(**kwargs))
        return teams

    def get_teams_by_member0_bids(self, *bids, mode=Mode.TEAM_1V1):
        tids = []
        for bid in bids:
            p = self.get(Player, bid=bid)
            tids.append(self.get(Team, member0=p, mode=mode).id)
        return tids

    def create_ranking(self, **kwargs):
        kwargs = merge_args(
            dict(created=utcnow(),
                 data_time=utcnow(),
                 min_data_time=utcnow(),
                 max_data_time=utcnow(),
                 status=Ranking.COMPLETE_WITH_DATA,
                 season=self.season), **kwargs)

        self.ranking = Ranking.objects.create(**kwargs)
        return self.ranking

    def _default_team_rank(self, team_rank):
        """ Update a team_rank dict with defaults. """
        for k, v in self.default_ranking_data__data.items():
            team_rank.setdefault(k, v)
        team_rank.setdefault("team_id", self.team.id)
        team_rank.setdefault("data_time", to_unix(self.ranking.data_time))
        team_rank.setdefault("version", Version.HOTS)
        team_rank.setdefault("region", Region.EU)
        team_rank.setdefault("mode", Mode.TEAM_1V1)
        team_rank.setdefault("league", League.GOLD)
        team_rank.setdefault("tier", 0)
        team_rank.setdefault("ladder_id", self.ladder.id)
        team_rank.setdefault("join_time", to_unix(self.ranking.data_time))
        team_rank.setdefault("source_id", self.cache.id)
        team_rank.setdefault("mmr", 1000)
        team_rank.setdefault("points", 100.0)
        team_rank.setdefault("wins", 10)
        team_rank.setdefault("losses", 10)
        team_rank.setdefault("race0", Race.ZERG)
        team_rank.setdefault("race1", Race.UNKNOWN)
        team_rank.setdefault("race2", Race.UNKNOWN)
        team_rank.setdefault("race3", Race.UNKNOWN)
        team_rank.setdefault("ladder_rank", 1)
        team_rank.setdefault("ladder_count", 1)
        team_rank.setdefault("league_rank", 1)
        team_rank.setdefault("league_count", 1)
        team_rank.setdefault("region_rank", 1)
        team_rank.setdefault("region_count", 1)
        team_rank.setdefault("world_rank", 1)
        team_rank.setdefault("world_count", 1)

    def create_ranking_data(self, raw=True, **kwargs):
        kwargs = merge_args(dict(ranking=self.ranking, updated=utcnow()),
                            kwargs)
        data = kwargs.pop('data', [])
        ranking = kwargs['ranking']

        for team_rank in data:
            self._default_team_rank(team_rank)
            ranking.sources.add(self.get(Cache, pk=team_rank['source_id']))

        self.ranking_data = RankingData.objects.create(**kwargs)
        sc2.save_ranking_data_raw(self.db_name, ranking.id, 0, data, True)
        if not raw:
            cpp = sc2.RankingData(self.db_name, Enums.INFO)
            cpp.load(ranking.id)
            cpp.save_data(ranking.id, ranking.season_id, to_unix(utcnow()))
            cpp.release()

        return self.ranking_data

    def update_ranking_stats(self, ranking_id=None):
        """ Will build ranking stats based of the ranking by calling c++. """
        if ranking_id is None: ranking_id = self.ranking.id
        cpp = sc2.RankingData(self.db_name, Enums.INFO)
        cpp.load(ranking_id)
        cpp.save_stats(ranking_id, to_unix(utcnow()))
        cpp.release()
Esempio n. 12
0
def get_season_based_on_join_times(first_join, last_join):
    """
    Get season based off first and last join times only.

    Return <season, value>, valid will be 0 if sure, -1 if could be season before +1 if could be season after (if
    both joins are to close to boundary).

    Season boundaries will not be exact (also join time is in unknown time zone), since we switch autimatically they
    will be on the date after switch or event two days after because of different time zones. Also ladders have been
    created well before season start some time.

    If both times are near a boundary the last_join will be used against the stored value on the season (this will make
    it more likely to fall in the first season). If there is player ladder data it will sort this out, if there is not
    it may stay wrong.

    NOTE: Join times can be off by serveral days, like 3-4 days. If both joins are too close to the same season end
    valid will be -1 or +1 and join season could be off by one season.

    """

    context = "first_join %s, last_join %s" % (first_join, last_join)

    if last_join < first_join:
        raise Exception("%s, last_join is before first_join, this is strange" %
                        context)

    first_season = Season.get_active(first_join)
    last_season = Season.get_active(last_join)

    context += ", first_season %s, last_season %d" % (first_season.id,
                                                      last_season.id)

    if first_season.id == last_season.id:
        # Same season matched, this should be the most common case.

        if first_season.is_open() and not (first_season.near_start(first_join) or last_season.near_start(last_join))\
                or not first_season.is_open() and first_season.near_end(first_join):
            # Compact join period to the end of season, insecure, could be season after.
            return last_season, 1

        if last_season.near_start(last_join):
            # Compact join period to the start of season, insecure, could be season before.
            return last_season, -1

        # One/both join in the middle or first in beginning and last in end, secure.
        return last_season, 0

    if first_season.id + 1 == last_season.id:
        # End points in different seasons, prefer determine by last_join, but it depends on how valid it is.
        if last_season.near_start(last_join):
            # Last end is unsure.
            if first_season.near_end(first_join):
                # First end is also unsure, pick last_season, but may be season before.
                return last_season, -1

            # First end is sure, pick first season.
            return first_season, 0

        if first_season.near_end(first_join):
            # First end is unsure, pick last season.
            return last_season, 0

        # This means both are sure but in different seasons.
        raise CatError(
            "%s, can't determine season this ladder seems to span full seasons"
            % context)

    if first_season.id + 2 == last_season.id \
       and first_season.near_end(first_join) \
       and last_season.near_start(last_join):
        # Both ends are insecure, so it has to be season in the middle.
        return first_season.get_next(), 0

    raise CatError(
        "%s, this must be buggy, seasons wrong order or too far apart" %
        context)
Esempio n. 13
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])
Esempio n. 14
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)
Esempio n. 15
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)