Esempio n. 1
0
    def create_game(srid=None,
                    status='scheduled',
                    away=None,
                    home=None,
                    site_sport=None,
                    round_start_times=False):
        # site_sport, created = SiteSport.objects.get_or_create(name=sport)

        ssm = SiteSportManager()
        season_model_class = ssm.get_season_class(site_sport)
        dum_srid = '%s' % site_sport
        dum_season_year = 2016
        dum_season_type = 'reg'
        dum_season, created = season_model_class.objects.get_or_create(
            srid=dum_srid,
            season_year=dum_season_year,
            season_type=dum_season_type,
        )

        if srid is None:
            srid = "srid-%s" % int(round(time.time() * 1000)),
        if away is None:
            away = Dummy.create_team(alias='AWAY', site_sport=site_sport)
        if home is None:
            home = Dummy.create_team(alias='HOME', site_sport=site_sport)

        dt_now = timezone.now()
        if round_start_times:
            # zero out the seconds and microseconds!
            dt_now = dt_now.replace(dt_now.year, dt_now.month, dt_now.day,
                                    dt_now.hour, dt_now.minute, 0, 0)

        if site_sport is None:
            game = GameChild()
        else:
            ssm = SiteSportManager()
            game_model = ssm.get_game_class(site_sport)
            game = game_model()

        game.season = dum_season  # cant be None
        game.srid = srid
        game.start = dt_now
        game.status = status

        game.away = away
        game.home = home

        game.save()
        return game
    def handle(self, *args, **options):

        values = []
        for x in options['values']:
            values.append(x)

        game_srid = values[0]
        duration = 500
        try:
            duration = int(values[1])  # defaults to
        except IndexError:
            pass  # there wasnt a duration specified, just use the default

        # find the Game -- check all sports
        ssm = SiteSportManager()
        game = None
        the_sport = None
        for sport in SiteSportManager.SPORTS:
            game_class = ssm.get_game_class(sport)
            try:
                game = game_class.objects.get(srid=game_srid)
                the_sport = sport
                break
            except game_class.DoesNotExist:
                pass
            self.stdout.write('checked %s for Game but it wasnt found' % sport)

        if game is None or the_sport is None:
            self.stdout.write('No game found for any sport '
                              '%s matching srid: %s\n' %
                              (SiteSportManager.SPORTS, game_srid))

        # get a prize structure that hopefully exists
        prize_structures = PrizeStructure.objects.all()
        count = prize_structures.count()
        r = Random()
        prize_structure = prize_structures[r.randint(0, count - 1)]
        self.stdout.write('randomly chosen prize structure: %s' %
                          str(prize_structure))

        #
        contest_pool_creator = ContestPoolCreator(the_sport, prize_structure,
                                                  game.start, duration)
        contest_pool_creator.get_or_create()
    def get_games(self, draft_group):
        """
        Return the sports.<sport>.Game objects of the DraftGroup instance.

        This method simply gets the distinct('game_srid') rows
        from the QuerySet returned by get_game_teams().

        :param draft_group:
        :return: QuerySet of sports.<sport>.Game objects
        """

        # get the distinct games from the gameteam model
        distinct_gameteam_games = self.get_game_teams(
            draft_group=draft_group).distinct('game_srid')
        game_srids = [x.game_srid for x in distinct_gameteam_games]

        # get the sports game_model (ie: sports.<sport>.Game)
        ssm = SiteSportManager()
        game_model = ssm.get_game_class(
            sport=draft_group.salary_pool.site_sport)
        return game_model.objects.filter(srid__in=game_srids)
Esempio n. 4
0
    def create_player_stats_model(self, game_srid, player_srid,
                                  my_player_stats_instance):
        """
        create a new PlayerStats model instance from the fields of the 'mongo_obj'
        :param mongo_obj:
        :return:
        """

        site_sport_manager = SiteSportManager()
        site_sport = site_sport_manager.get_site_sport('nfl')
        player_model_class = site_sport_manager.get_player_class(site_sport)
        game_model_class = site_sport_manager.get_game_class(site_sport)

        try:
            player = player_model_class.objects.get(srid=player_srid)
        except player_model_class.DoesNotExist:
            # if they were never in the database, they wont be in draft group and we should not
            # deal with that here! - Probably means they are defensive players.
            return

        player_stats_model_class = self.get_player_stats_model_class()

        # get new instance
        player_stats = player_stats_model_class()

        # set all properties with these fieldnames to 0
        player_stats.position = player.position  # use the position from their Player object
        player_stats.srid_game = game_srid
        player_stats.game = game_model_class.objects.get(srid=game_srid)
        player_stats.srid_player = player_srid
        player_stats.player = player

        for fieldname, var in my_player_stats_instance.get_vars().items():
            setattr(player_stats, fieldname, var)
            player_stats.save()

        logger.info(
            'Missing PlayerStats model created for player: %s | srid: %s' %
            (player, player_srid))
    def find_games_within_time_span(site_sport, start, end):
        #
        # we will use the SiteSportManager the model class for player, game
        ssm = SiteSportManager()
        game_model = ssm.get_game_class(site_sport)
        # get all games equal to or greater than start, and less than end.
        games = game_model.objects.filter(start__gte=start,
                                          start__lte=end).order_by('start')

        if len(games) == 0:
            err_msg = 'there are ZERO games in [%s until %s]' % (start, end)
            raise mysite.exceptions.NoGamesInRangeException(err_msg)
        elif len(games) < 2:
            raise NotEnoughGamesException()

        #
        # throw an exception if the specified start time does not coincide with any games
        if game_model.objects.filter(start=start).count() == 0:
            raise NoGamesAtStartTimeException()

        # Keep track of teams that are playing today.
        team_srids = []
        for game in games:
            # make sure we do not encounter the same team multiple times!
            for check_team in [game.away, game.home]:
                if check_team.srid in team_srids:
                    logger.warning("Excluding doubleheader game: %s" % game)
                    # If we find a game that has a team that is already playing today,
                    # exclude the second game.
                    games = games.exclude(pk=game.pk)

            # Add the teams to our list of srids.
            team_srids.append(game.away.srid)
            team_srids.append(game.home.srid)

        return games
Esempio n. 6
0
class BuyinTest(AbstractTest):
    """
    create a basic contest, and use the BuyinManager to buy into it.
    """

    def setUp(self):
        super().setUp()
        # ensure the default ticket
        TicketManager.create_default_ticket_amounts(verbose=False)
        # add funds to user
        self.user = self.get_basic_user()
        ct = CashTransaction(self.user)
        ct.deposit(100)

        # salary_generator = Dummy.generate_salaries()
        # self.salary_pool = salary_generator.pool
        # start
        #
        #
        self.verbose = True  # set to False to disable print statements

        #
        # The sport we are going to build fake stats for.
        # Lets use nfl, but it doesnt matter what sport we use
        self.sport = 'nfl'

        #
        # Ensure there are Games by using the Dummy to generate fake stats.
        # The ScheduleManager requires that Game objects exist
        # because when it creates scheduled Contest objects
        # it is required to create a draft group.
        self.dummy = Dummy(sport=self.sport)
        self.generator = self.dummy.generate()
        self.salary_pool = self.generator.pool
        self.site_sport = self.dummy.site_sport  # stash the site_sport for easy use

        self.site_sport_manager = SiteSportManager()
        self.game_model = self.site_sport_manager.get_game_class(
            self.site_sport)  # ie: sports.nfl.models.Game
        self.games = self.game_model.objects.all()  # there should be handful now, for today
        if self.games.count() <= 0:
            raise Exception(
                'buyin.tests.BuyinTest - we meant to create games.... but none were created!')
        # end

        # create a simple prize pool
        self.first = 100.0
        self.second = 50.0
        self.third = 25.0
        self.buyin = 10
        cps = CashPrizeStructureCreator(name='test')
        cps.add(1, self.first)
        cps.add(2, self.second)
        cps.add(3, self.third)
        cps.set_buyin(self.buyin)
        cps.save()
        cps.prize_structure.save()

        self.prize_structure = cps.prize_structure
        self.ranks = cps.ranks

        #
        # create the Contest
        # now = timezone.now()
        # start = DfsDateTimeUtil.create(now.date(), time(23,0))
        # end = DfsDateTimeUtil.create(now.date() + timedelta(days=1), time(0,0))
        start = self.games[0].start + timedelta(minutes=5)
        end = self.games[self.games.count() - 1].start  # set 'end' to start of last game
        cc = ContestCreator("test_contest", self.sport, self.prize_structure, start, end)
        self.draft_group2 = DraftGroup()
        self.draft_group2.salary_pool = self.salary_pool
        self.draft_group2.start = start
        self.draft_group2.end = end
        self.draft_group2.save()

        self.contest_pool, created = ContestPoolCreator(
            self.sport,
            self.prize_structure,
            start,
            (end - start).seconds * 60,
            self.draft_group2
        ).get_or_create()
        self.contest = cc.create()
        self.contest.status = Contest.RESERVABLE
        self.contest.save()

        self.draft_group = DraftGroup()
        self.draft_group.salary_pool = self.salary_pool
        self.draft_group.start = start
        self.draft_group.end = end
        self.draft_group.save()

    def test_incorrect_contest_type(self):
        bm = BuyinManager(self.user)
        self.assertRaises(mysite.exceptions.IncorrectVariableTypeException,
                          lambda: bm.buyin(0))

    def test_incorrect_lineup_type(self):
        bm = BuyinManager(self.user)
        self.assertRaises(mysite.exceptions.IncorrectVariableTypeException,
                          lambda: bm.buyin(self.contest, 0))

    def test_simple_buyin(self):
        bm = BuyinManager(self.user)
        bm.buyin(self.contest_pool)

    def test_simple_ticket_buyin(self):
        tm = TicketManager(self.user)
        try:
            tm.get_ticket_amount(self.buyin)

        except Exception:
            ta = TicketAmount()
            ta.amount = self.buyin
            ta.save()
        tm.deposit(amount=self.buyin)
        bm = BuyinManager(self.user)
        bm.buyin(self.contest_pool)
        tm.ticket.refresh_from_db()
        self.assertEqual((tm.ticket.consume_transaction is not None), True)

    def test_lineup_no_contest_draft_group(self):
        lineup = Lineup()
        lineup.draft_group = self.draft_group2
        lineup.user = self.user
        lineup.save()
        bm = BuyinManager(self.user)
        contest_pool = self.contest_pool
        contest_pool.draft_group = None
        contest_pool.save()
        self.assertRaises(exceptions.ContestIsNotAcceptingLineupsException,
                          lambda: bm.buyin(contest_pool, lineup))

    def test_lineup_share_draft_group(self):
        lineup = Lineup()
        lineup.draft_group = self.draft_group
        lineup.user = self.user

        bm = BuyinManager(self.user)
        self.assertRaises(exceptions.ContestLineupMismatchedDraftGroupsException,
                          lambda: bm.buyin(self.contest_pool, lineup))

    def test_contest_full(self):
        self.contest_pool.current_entries = 19
        self.contest_pool.entries = 1
        self.contest_pool.save()
        bm = BuyinManager(self.user)
        self.assertRaises(exceptions.ContestIsFullException,
                          lambda: bm.buyin(self.contest_pool))

    # def test_contest_is_in_progress(self):
    #     self.contest.status = self.contest.INPROGRESS
    #     self.contest.save()
    #     self.should_raise_contest_is_in_progress_or_closed_exception()
    #
    # def test_contest_is_cancelled(self):
    #     self.contest.status = self.contest.CANCELLED
    #     self.contest.save()
    #     self.should_raise_contest_is_in_progress_or_closed_exception()
    #
    # def test_contest_is_closed(self):
    #     self.contest.status = self.contest.CLOSED
    #     self.contest.save()
    #     self.should_raise_contest_is_in_progress_or_closed_exception()
    #
    # def test_contest_is_completed(self):
    #     self.contest.status = self.contest.COMPLETED
    #     self.contest.save()
    #     self.should_raise_contest_is_in_progress_or_closed_exception()
    #
    # def should_raise_contest_is_in_progress_or_closed_exception(self):
    #     bm = BuyinManager(self.user)
    #     self.assertRaises(exceptions.ContestIsInProgressOrClosedException,
    #               lambda: bm.buyin(self.contest))

    def test_user_owns_lineup(self):
        lineup = Lineup()
        lineup.draft_group = self.draft_group2
        lineup.user = self.get_admin_user()

        bm = BuyinManager(self.user)
        self.assertRaises(LineupDoesNotMatchUser,
                          lambda: bm.buyin(self.contest_pool, lineup))

    def test_user_submits_past_max_entries(self):
        self.contest_pool.max_entries = 1
        self.contest_pool.entries = 3
        self.contest_pool.save()

        bm = BuyinManager(self.user)
        bm.buyin(self.contest_pool)

        bm = BuyinManager(self.user)
        self.assertRaises(exceptions.ContestMaxEntriesReachedException,
                          lambda: bm.buyin(self.contest_pool))
class BlockManager(object):
    def __init__(self, block):
        self.block = block
        self.cutoff = self.block.get_utc_cutoff()
        self.block_prize_structures = BlockPrizeStructure.objects.filter(block=self.block)
        self.site_sport_manager = SiteSportManager()
        self.game_model_class = self.site_sport_manager.get_game_class(self.block.site_sport)

    def get_included_games(self):
        """
        Based on the block's cutoff and dfsday_end times, get all the sport's games that fall
        in between the 2 times.
        :return:
        """
        return self.game_model_class.objects.filter(
            start__gte=self.cutoff,
            start__lt=self.block.dfsday_end
        ).order_by('start')

    def create_contest_pools(self):
        """
        to determine the start of the earliest game in the block, we look for
        all games between the dfsday_start and dfsday_end of the block,
        and get the earliest start time of games after the cutoff.
        this ensures we capture all the games in the range, as opposed
        to relying on the BlockGame objects which have a very low chance
        of not including very recent scheduling changes!
        """

        # If we've already created pools for this block, don't attempt to create more,
        # that would cause us to have multiple slates of pools per day.
        if self.block.contest_pools_created:
            logger.info('Contests pools have already been created for this block, '
                        'not creating more. %s' % self.block)
            return

        # Don't make contest pools for should_create_contest_pools == False.
        if not self.block.should_create_contest_pools:
            raise Exception(
                'Not creating contest pools: Block.should_create_contest_pools is set to False.'
                ' - %s' % self.block)

        # default
        num_contest_pools_created = 0

        # determine the start time
        included_games = self.get_included_games()

        logger.info('% included games' % included_games.count())
        # we will not check if there are enough games here, and
        # ultimately let the draft group creator raise an exception
        # if it cant find enough games!
        if included_games.count() >= 1:

            earliest_start_time = included_games[0].start

            # duration is the # of minutes until the end of the Block (dfsday_end)
            td = self.block.dfsday_end - earliest_start_time
            duration = int(td.total_seconds() / 60)  # convert seconds to minutes

            # create all required ContestPools
            logger.info('%s formats based on default %s PrizeStructure(s)' % (
                len(self.block_prize_structures),
                self.block.site_sport)
                        )
            for block_prize_structure in self.block_prize_structures:
                # additional (optional) ContestPoolCreator arguments:
                #  draft_group=None, user_entry_limit=None, entry_cap=None
                contest_pool_creator = ContestPoolCreator(
                    self.block.site_sport.name, block_prize_structure.prize_structure,
                    earliest_start_time, duration, set_name=True)

                # because this method may attempt to create a DraftGroup,
                # we must be able to handle the DraftGroup exceptions that
                # could potentially be thrown.

                contest_pool = contest_pool_creator.get_or_create()
                num_contest_pools_created += 1
                logger.info('creating ContestPool: %s for Block: %s' % (contest_pool, self.block))

                #
                # we really want to let exceptions propagate up to the admin
                # so were not currently catching any in here...

        if num_contest_pools_created != 0:
            self.block.contest_pools_created = True
        self.block.save()

        logger.info(
            '%s ContestPool(s) created for Block: %s' % (num_contest_pools_created, self.block))
class ScheduleDay(object):
    """
    This is a factory that produces SportDays for each type of sport (MlbDay, NhlDay, etc). A SportDay is an object
    that has some properties that tell us when games for that sport usually start.

    With this info a Block is created. A block is a group of IRL games.
    """
    tzinfo_est = pytz_timezone('America/New_York')
    datetime_format_date = '%Y-%m-%d'
    datetime_format_time = '%I:%M %p'

    default_season_types = ['reg', 'pst']

    class SportDay(object):

        tzinfo_est = pytz_timezone('America/New_York')
        datetime_format_date = '%Y-%m-%d'
        datetime_format_time = '%I:%M %p'

        weekday = None
        saturday = None
        sunday = None

        weekday_values = [0, 1, 2, 3, 4]
        saturday_values = [5]
        sunday_values = [6]

        def __init__(self, site_sport, datetime_obj, games):
            self.site_sport = site_sport
            self.the_datetime = datetime_obj
            self.games = games

            # self.get_data()

            self.data = {
                'weekday': None,
                'type': None,
                'total': None,
                'include': None,
                'exclude': None,
                'include_times': None,
                'exclude_times': None,
                'include_pct': None,
            }

            self.get_data()

        def get_excluded_game_ids(self):
            return self.data['exclude']

        def get_excluded_games(self):
            return self.games.filter(pk__in=self.get_excluded_game_ids())

        def get_included_game_ids(self):
            return self.data['include']

        def get_included_games(self):
            return self.games.filter(pk__in=self.get_included_game_ids())

        def get_cutoff(self):
            """ get the 'cutoff_time' from the internal data """
            return self.data['cutoff_time']

        # def get_cutoff_datetime(self):
        #     return self.data['cutoff_datetime']

        def get_data(self):
            if self.games.count() == 0:
                return None

            weekday = None  # 0 - 6 day index.  its poorly named, but its NOT the self.weekday time() cutoff
            include = []
            exclude = []
            include_times = []
            exclude_times = []
            for game in self.games:

                if weekday is None:
                    # weekday = game.start.weekday()
                    #    ... i think its actually this:
                    weekday = self.get_local_datetime(game.start).weekday()

                datetime_start_est = self.get_local_datetime(game.start)
                if weekday in [0, 1, 2, 3, 4] and self.include_in_weekday_block(datetime_start_est):
                    include.append(game.pk)
                    include_times.append(self.get_str_local_time(game.start))
                elif weekday in [5] and self.include_in_saturday_block(datetime_start_est):
                    include.append(game.pk)
                    include_times.append(self.get_str_local_time(game.start))
                elif weekday in [6] and self.include_in_sunday_block(datetime_start_est):
                    include.append(game.pk)
                    include_times.append(self.get_str_local_time(game.start))
                else:
                    exclude.append(game.pk)
                    exclude_times.append(self.get_str_local_time(game.start))

            # self.data = {
            #     'weekday'       : weekday,
            #     'type'          : self.weekday_to_str(weekday),
            #     'total'         : self.games.count(),
            #     'include'       : include,
            #     'exclude'       : exclude,
            #     'include_times' : include_times,
            #     'exclude_times' : exclude_times,
            #     'include_pct'   : float(float(len(include)) / float(self.games.count()))
            # }
            self.save_internal_data(weekday, self.weekday_to_str(weekday), self.games.count(),
                                    include, exclude, include_times, exclude_times)

            return self.data

        def save_internal_data(self, weekday, type, total, include, exclude, include_times,
                               exclude_times):
            self.data = {
                'weekday': weekday,
                'type': type,
                'total': total,
                'include': include,
                'exclude': exclude,
                'include_times': include_times,
                'exclude_times': exclude_times,
                'include_pct': float(float(len(include)) / float(total)),
                'cutoff_time': self.get_weekday_cutoff_time(weekday),
            }

        def __str__(self):
            include_pct = self.data['include_pct']
            if include_pct is None:
                include_pct = 0.0
            else:
                include_pct = int(include_pct * 100.0)

            included = self.data['include']
            if included is None:
                included = 0
            else:
                included = len(included)

            return 'type: %s, weekday:%s, included games:%s pct   (%s of %s) >>> included times %s  ((excluded times %s))' \
                   '' % (self.data['type'], self.data['weekday'], include_pct,
                         included, str(self.data['total']), str(self.data['include_times']),
                         str(self.data['exclude_times']))

        def weekday_to_str(self, weekday):
            if weekday in self.weekday_values:
                return 'Weekday'
            elif weekday in self.saturday_values:
                return 'Saturday'
            elif weekday in self.sunday_values:
                return 'Sunday'

        def get_weekday_cutoff_time(self, weekday):
            """
            this is an internal method.

            use method get_cutoff() to retrieve the datetime.time()
            specifically related to the day of this instance
            after this sportday  has been updated
            """

            if weekday in self.weekday_values:
                return self.weekday
            elif weekday in self.saturday_values:
                return self.saturday
            elif weekday in self.sunday_values:
                return self.sunday

        def get_local_datetime(self, utc_datetime_obj):
            return utc_datetime_obj.astimezone(self.tzinfo_est)

        def get_str_local_time(self, datetime_obj):
            local_dt = datetime_obj.astimezone(self.tzinfo_est)
            return local_dt.strftime(self.datetime_format_time)

        def get_str_local_date(self, datetime_obj):
            local_dt = datetime_obj.astimezone(self.tzinfo_est)
            return local_dt.strftime(self.datetime_format_date)

        def include_in_weekday_block(self, datetime_obj):
            return datetime_obj.time() >= self.weekday

        def include_in_saturday_block(self, datetime_obj):
            return datetime_obj.time() >= self.saturday

        def include_in_sunday_block(self, datetime_obj):
            return datetime_obj.time() >= self.sunday

    class MlbDay(SportDay):

        weekday = time(19, 0)  # 7pm +
        saturday = time(16, 0)  # 4pm +
        sunday = time(13, 0)  # 1pm +

        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)

    class NhlDay(SportDay):

        weekday = time(19, 0)  # 7pm +
        saturday = time(19, 0)  # 7pm +
        sunday = time(15, 0)  # 3pm +

        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)

    class NbaDay(SportDay):

        weekday = time(19, 0)  # 7pm +
        saturday = time(19, 0)  # 7pm +
        sunday = time(18, 0)  # 6pm +

        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)

    class NflDay(SportDay):

        weekday = time(19, 0)  # 7pm +  (thursday night games)
        saturday = time(13, 0)  # 1pm +  (saturday games)
        sunday = time(13, 0)  # 1pm +  (sunday games)

        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)

    @staticmethod
    def factory(sport):
        if sport == 'nba':
            return ScheduleDay.NbaDay
        if sport == 'nhl':
            return ScheduleDay.NhlDay
        if sport == 'mlb':
            return ScheduleDay.MlbDay
        if sport == 'nfl':
            return ScheduleDay.NflDay

        else:
            raise Exception('ScheduleDay for sport: %s - UNIMPLEMENTED' % sport)
            # def get_data(self):
            #     if self.games.count() == 0:
            #         return None
            #
            #     weekday = None
            #     include = []
            #     exclude = []
            #     include_times = []
            #     exclude_times = []
            #     for game in self.games:
            #
            #         if weekday is None:
            #             weekday = game.start.weekday()
            #
            #         datetime_start_est = self.get_local_datetime(game.start)
            #         if weekday in [0,1,2,3,4] and self.include_in_weekday_block(datetime_start_est):
            #             include.append(game.pk)
            #             include_times.append(self.get_str_local_time(game.start))
            #         elif weekday in [5] and self.include_in_saturday_block(datetime_start_est):
            #             include.append(game.pk)
            #             include_times.append(self.get_str_local_time(game.start))
            #         elif weekday in [6] and self.include_in_sunday_block(datetime_start_est):
            #             include.append(game.pk)
            #             include_times.append(self.get_str_local_time(game.start))
            #         else:
            #             exclude.append(game.pk)
            #             exclude_times.append(self.get_str_local_time(game.start))
            #
            #     self.data = {
            #         'weekday'       : weekday,
            #         'type'          : self.weekday_to_str(weekday),
            #         'total'         : self.games.count(),
            #         'include'       : include,
            #         'exclude'       : exclude,
            #         'include_times' : include_times,
            #         'exclude_times' : exclude_times,
            #         'include_pct'   : float(float(len(include)) / float(self.games.count()))
            #     }
            #
            #     return self.data

    def __init__(self, sport, season=None, season_types=None):
        self.data = None
        self.sport = sport
        self.sport_day_class = ScheduleDay.factory(self.sport)
        self.site_sport_manager = SiteSportManager()
        self.site_sport = self.site_sport_manager.get_site_sport(self.sport)
        self.game_model_class = self.site_sport_manager.get_game_class(self.site_sport)
        self.season = season  # season is None, only get games for the season type after 'now'
        self.season_types = season_types
        if self.season_types is None:
            self.season_types = self.default_season_types

        # setup the datetime range with a start and end
        self.start = None
        self.end = None

    def get_data(self):
        return self.data

    def update_range(self, days_ago):
        """
        add timedelta(days=days) to the start and end datetime object

        :param days_ago:
        :return:
        """
        dfs_date_range = DfsDate.get_current_dfs_date_range()
        # set our dfsday range to start on the first day of the games we found
        self.start = dfs_date_range[0] - timedelta(days=days_ago)
        self.end = dfs_date_range[1] - timedelta(days=days_ago)

    def get_day_range(self):
        return self.start, self.end

    def get_days_since(self, datetime_obj):
        td = (timezone.now() - datetime_obj)
        return abs(td.days) + 1

    def increment_day_range(self):
        self.start = self.start + timedelta(days=1)
        self.end = self.end + timedelta(days=1)

    def update(self, verbose=False):
        """
        update the list of dfs days, with tuples of the start times
        and lists of all the games with their own unique start times
        """
        # if running for the first time, its very likely you wont want to add 1 day to start time
        # dfs_date_tomorrow = DfsDate.get_current_dfs_date_range()[0] + timedelta(days=1)
        dfs_date_tomorrow = DfsDate.get_current_dfs_date_range()[0]
        logger.info("Looking for games later than: %s" % dfs_date_tomorrow)

        games = []  # default
        self.data = []
        if self.season is None:
            # we are going to have to find the following dfs day... and check gte its start time
            games = self.game_model_class.objects.filter(
                start__gte=dfs_date_tomorrow,
                season__season_type__in=self.season_types).order_by('start')  # oldest first
        else:
            games = self.game_model_class.objects.filter(
                season__season_year=self.season,
                season__season_type__in=self.season_types).order_by('start')  # oldest first

        if games.count() <= 0:
            logger.info('0 games found. exiting...')
            return
        else:
            logger.info('%s games found, as old as %s' % (games.count(), games[0].start))

        #
        days_ago = self.get_days_since(games[0].start)
        self.update_range(days_ago)
        day_range = self.get_day_range()

        # logger.info('first day (dt range)', str(day_range))

        # Weekdays@7pm or later
        # Saturdays@7pm or later
        # Sundays@6pm or later

        # idx = 0
        while games.filter(start__gte=self.get_day_range()[0]).count() > 0:
            # get all the games for the dfs day
            daily_games = games.filter(start__range=self.get_day_range())

            if daily_games.count() >= 2:
                # there must be more than 2 games for DFS!
                dt = self.get_day_range()[0]
                date_str = self.get_str_local_date(dt)
                self.data.append((date_str, self.sport_day_class(self.site_sport, dt, daily_games)))

            #
            self.increment_day_range()

    def get_str_local_time(self, datetime_obj):
        local_dt = datetime_obj.astimezone(self.tzinfo_est)
        return local_dt.strftime(self.datetime_format_time)

    def get_str_local_date(self, datetime_obj):
        local_dt = datetime_obj.astimezone(self.tzinfo_est)
        return local_dt.strftime(self.datetime_format_date)

    def show_time_blocks(self):
        self.update()

        for date_str, sport_day in self.data:
            print(date_str, str(sport_day))
Esempio n. 9
0
 def __get_game_model(self):
     ssm = SiteSportManager()
     return ssm.get_game_class(self.site_sport)
    def handle(self, *args, **options):
        for name in settings.CACHES.keys():
            cache = caches[name]
            cache.clear()
            self.stdout.write('[%s] cache cleared!\n' % name)

        ssm = SiteSportManager()
        game_class = None
        sport = None
        pbp_list = []

        for sport_string in options['sport']:
            sport = sport_string
            game_class = ssm.get_game_class(sport_string)

        for game_srid in options['srid']:
            # Since we can't query by game_srid, we need to grab all events that are timestamped
            # after the game began, then loop though them trying to match game_srid in order
            # to determine if they are for the specified game or not.

            # Get the Game model.
            print('Getting Game for srid: %s' % game_srid)
            game = game_class.objects.get(srid=game_srid)

            print("Game found: %s" % game)

            # Find any dataden Updates that might be for that game, based on the timestamp.
            updates = Update.objects.filter(ts__gte=game.start)
            print(
                'Found %s potential PBP events. (not all of these are matches)'
                % updates.count())

            game_ids = set([])

            for update in updates:
                # The actual data is stored as a string'd python object. Eval it so we can check
                # it's game_srid.
                update_data = ast.literal_eval(update.o)
                game_id = update_data.get('game__id')
                game_ids.add(game_id)

                if not game_id:
                    game_id = update_data.get('id')

                if game_id and game_id == game_srid:
                    pbp_list.append(update_data)

                    # send it through parser!

                    # Ideally we'd take the output of the parser here and output it to a file,
                    # but the system isn't setup like that. Instead I made an optional setting
                    # that will pipe anything we'd normally send to Pusher and output it to
                    # a text file. You can see that in `push.classes`, look
                    # for: settings.PUSHER_OUTPUT_TO_FILE to see the logic.
                    parser = DataDenParser()
                    ns_parts = update.ns.split(
                        '.')  # split namespace on dot for db and coll
                    db = ns_parts[0]
                    collection = ns_parts[1]
                    parser.parse_obj(db,
                                     collection,
                                     ast.literal_eval(update.o),
                                     async=False)

            # If you want to dump out the objects we got from Dataden, before they were run
            # through the parsers, uncomment these lines.
            #
            # file_path = 'tmp/dataden_events--%s_game__%s.json' % (sport, game_srid)

            # print("Writing out %s Dataden PBP events for this game to `%s`" % (
            #     len(pbp_list), file_path))
            #
            # with open(file_path, 'w') as outfile:
            #     json.dump(pbp_list, outfile)
            print('Done!')

            print(
                "\nIf you didn't find any events with this id, maybe try one of these game ids:\n\n"
            )
            print(game_ids)
            print('\n\n')