def create_initial_default_prize_structures():

        site_sport_manager = SiteSportManager()
        for sport in SiteSportManager.SPORTS:
            created_default_prize_structures = 0
            site_sport = site_sport_manager.get_site_sport(sport)
            for buyin in DefaultPrizeStructureManager.default_buyin_amounts:
                for size, payout_spots in DefaultPrizeStructureManager.default_contest_sizes:
                    # get the prize structure based on the buyin and # of payout spots
                    prize_structures = PrizeStructure.objects.filter(
                        generator__buyin=buyin, generator__payout_spots=payout_spots)
                    prize_structure = None  # loop until we find it
                    for ps in prize_structures:
                        if size == ps.get_entries():
                            prize_structure = ps
                            break  # we found it
                    if prize_structure is None:
                        logger.warning(
                            ("No PrizeStructure for buyin: %s payout_spots: %s. You can add them "
                             "manually though!") % (buyin, payout_spots))
                        # raise Exception(err_msg)

                    else:
                        #
                        # create the default prize structures for the SiteSport
                        dps = DefaultPrizeStructure()
                        dps.site_sport = site_sport
                        dps.prize_structure = prize_structure
                        dps.save()
                        created_default_prize_structures += 1

            logger.info("%s created_default_prize_structures for %s" % (
                created_default_prize_structures, sport))
Example #2
0
 def get_player_stats_model_class(self):
     site_sport_manager = SiteSportManager()
     site_sport = site_sport_manager.get_site_sport(self.sport)
     player_stats_model_classes = site_sport_manager.get_player_stats_classes(
         site_sport)
     return player_stats_model_classes[
         0]  # return first element - nfl only has 1
    def __init__(self,
                 sport,
                 prize_structure,
                 start,
                 duration,
                 draft_group=None,
                 user_entry_limit=None,
                 entry_cap=None,
                 set_name=True):
        """
        :param sport: the name of the sport
        :param prize_structure: the prize.models.PrizeStructure
        :param start: datetime object, the scheduled start time
        :param duration: the integer number of minutes from the start until the end
                         that makes a range of datetime objects, between which to use
                         the sport's games.
        :param draft_group: if specified, the DraftGroup to use. otherwise get an existing one
                            using the DraftGroupManager class.
        """
        site_sport_manager = SSM()
        self.sport = sport
        self.site_sport = site_sport_manager.get_site_sport(self.sport)

        # validate and set the start datetime
        self.start = self.validate_start(start)

        # validate and set the duration (integer minutes)
        self.duration = self.validate_duration(duration)

        # validate and set the prize_structure model
        self.prize_structure = self.validate_prize_structure(prize_structure)

        # if a draft_group is specified, validate it
        self.draft_group = draft_group
        if self.draft_group is not None:
            self.draft_group = self.validate_draft_group(draft_group)

        # set the user entry limit (the max # of Entrys from one user for this ContestPool)
        self.user_entry_limit = self.USER_ENTRY_LIMIT
        if user_entry_limit is not None:
            self.user_entry_limit = user_entry_limit

        # set the entry cap (if there is one, typically there is not)
        self.entry_cap = self.ENTRY_CAP
        if entry_cap is not None:
            self.entry_cap = entry_cap

        # whether or not to set a name at creation time
        self.set_name = set_name

        # skill level
        slm = SkillLevelManager()
        self.skill_level = slm.get_for_amount(self.prize_structure.buyin)
Example #4
0
    def __init__(self, sport):
        self.sport = sport
        self.verbose = False
        self.debug_limit = 0
        self.pbp_parent_api = 'pbp'
        self.stats_parent_api = 'stats'
        self.delay_seconds = 5
        self.delay_seconds_behind = 0

        ssm = SiteSportManager()
        self.site_sport = ssm.get_site_sport(self.sport)
        self.player_class = ssm.get_player_class(self.site_sport)
Example #5
0
    def create_player_stats(sport=DEFAULT_SPORT):
        """
        return a newly created player who could fit in the default roster.

        if 'roster' is None, we will call Dummy.create_roster() and use that data

        :param sport:
        :param roster:
        :return:
        """

        # ('QB',1,0,True)     :['QB'],
        position = None
        for rs_tuple, pos_list in Dummy.DEFAULT_ROSTER_MAP.items():
            for pos_name in pos_list:
                site_sport, c = SiteSport.objects.get_or_create(name=sport)
                position, c = Position.objects.get_or_create(
                    name=pos_name, site_sport=site_sport)
                break
            break
        if position is None:
            raise Exception(
                '>>>>> Dummy.create_player_stats() couldnt find any positions in roster'
            )

        dt_now = timezone.now()
        unix_ts = dt_now.strftime('%s')  # unix timestamp as srid ... not bad

        ssm = SiteSportManager()
        site_sport = ssm.get_site_sport(sport)
        game = Dummy.create_game(srid='game' + unix_ts, site_sport=site_sport)

        player = Dummy.create_player(srid='player' + unix_ts,
                                     position=position,
                                     team=game.home,
                                     site_sport=site_sport)

        if sport == Dummy.DEFAULT_SPORT:
            site_sport = None  # hack for backwards compatability, to not break older code
        player_stats = Dummy.create_player_stats_model(game, player,
                                                       site_sport)

        return player_stats
    def handle(self, *args, **options):
        """
        calculate a single players salary (for debugging purposes) using
        the sports main salary algorithm.

        this command will infer the sport using SiteSportManager
        so all that needs to be specified is the player srid!
        """

        # collect the player srids passed as arguments
        player_srids = []
        for srid in options['player']:
            player_srids.append(srid)

        player_srid = player_srids[0] # get the first one
        print('looking for player:', str(player_srid))

        # find the sports.<sport>.models.Player object
        ssm = SiteSportManager()
        player = None
        site_sport = None # the sport (the string name) of the sport the player was found in
        for sport in SiteSportManager.SPORTS:
            site_sport = ssm.get_site_sport(sport)
            player_class = ssm.get_player_class(site_sport)
            try:
                player = player_class.objects.get(srid=player_srid)
                break
            except player_class.DoesNotExist:
                #self.stdout.write('checked %s for Player object but they werent found'%sport)
                pass

        # hopefully we found the player by now
        if player is None:
            self.stdout.write('player [%s] not found in any sport!' % player_srid)
            return
        # else:
        #     self.stdout.write('player:', str(player))

        # generate the salary for this player specifically, printing out all the player stats
        # objects used and the weighting involved in the calculations for debugging purposes.
        sg = SportSalaryGenerator(sport=site_sport.name, debug_srid=player_srid)
        sg.generate_salaries()
Example #7
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 get_player_model_class(self):
     if self.player_model_class is None:
         ssm = SiteSportManager()
         site_sport = ssm.get_site_sport(self.sport)
         self.player_model_class = ssm.get_player_class(site_sport)
     return self.player_model_class
 def get_player_model_class(self, sport):
     ssm = SiteSportManager()
     site_sport = ssm.get_site_sport(sport)
     sport_player_model_class = ssm.get_player_class(site_sport)
     return sport_player_model_class
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))
Example #11
0
class Dummy(object):
    DEFAULT_SPORT = 'test'

    DEFAULT_ROSTER_MAP = {
        ('QB', 1, 0, True): ['QB'],
        ('WR', 1, 1, True): ['WR'],
        ('FX', 1, 2, False): ['RB', 'WR', 'TE']
    }

    #
    # DEFAULT_SPORT_FIELD_FOR_FANTASY_POINTS = {
    #     'nfl' : ['pass_yds', 'rush_yds', 'rec_yds'],
    #     'nba' : ['assists', 'rebounds', 'blocks'],
    #
    # }

    # this class will iterate these to create dummy teams
    # if game or player objects need foreign keys to them
    DEFAULT_TEAMS = [('away', 'AWAY'), ('home', 'HOME')]

    def __init__(self, sport):
        """
        Create dummy objects. This could interfere with the live site,
        and is strictly meant for testing environments, and specifically
        the "./manage.py test" tool
        """
        self.ssm = SiteSportManager()
        self.site_sport = self.ssm.get_site_sport(sport)

    def generate(self):
        """
        essentially does what generate_salaries() does, but for the
        sport this class was instantiated with, whereas generate_salaries()
        is a static method which uses the default sport and
        GameChild / PlayerChild tables.

        Use to this to make more realistic instances in the database
        of players/games/playerstats/salaries/etc...
        """
        # clear out any existing rosters with the same sport, because theyll be recreated
        Dummy.remove_existing_rosters_for_sport(site_sport=self.site_sport)
        # prerequisite calls to create_roster(), create_player_stats_list()
        Dummy.create_roster(sport=self.site_sport.name)
        Dummy.create_player_stats_list(site_sport=self.site_sport,
                                       round_start_times=True)
        # players = Dummy.create_players(n=players, site_sport=site_sport)   #  -done
        # games   = Dummy.create_games(n=games, site_sport=site_sport)       #  -done
        # create_player_stats_model( players,games)                          #  -done

        salary_conf = Dummy.create_salary_config()  # -done no changes

        pool = Pool()  # -done no changes
        pool.site_sport = self.site_sport  # -done use member variable
        pool.salary_config = salary_conf  # -done no changes
        pool.active = True  # -done default True so its useable
        pool.save()

        Dummy.create_trailing_game_weight(salary_conf, 3, 3)  # -done
        Dummy.create_trailing_game_weight(salary_conf, 7, 2)  # -done
        Dummy.create_trailing_game_weight(salary_conf, 10, 1)  # -done

        #
        # the SiteSportManager.get_player_stats_class()
        # method actually returns a list of sport.<sport>.PlayerStats subclasses for the sport
        player_stats_classes = self.ssm.get_player_stats_class(
            self.site_sport)  # -done

        generator = SalaryGenerator(player_stats_classes, pool)  # -done
        generator.generate_salaries()  # -done
        return generator  # -done

    @staticmethod
    def remove_existing_rosters_for_sport(site_sport):
        """
        call this at the beginning of create_rosters() to ensure
        that if the rosters already exist when a Dummy instance
        gets used in a test, we break down, and recreate the proper rosters.
        without adding more (which it doesnt/shouldnt handle nicely)
        :return:
        """
        if site_sport == None:
            raise Exception(
                'Dummy.remove_existing_rosters_for_sport() - site_sport not set yet'
            )

        rsps = RosterSpotPosition.objects.filter(
            roster_spot__site_sport=site_sport)
        rsps.delete()
        rps = RosterSpot.objects.filter(site_sport=site_sport)
        rps.delete()

    # Shared setup methods for the test cases
    @staticmethod
    def create_roster(sport=DEFAULT_SPORT, roster=DEFAULT_ROSTER_MAP):
        """
        example usage: the top level keys are tuples, the lists contain positions,
        each tuple key has the form: ('roster spot name',amount,idx,is_primary_boolean)
            >>> roster = {
            ...     ('QB',1,0,True)     :['QB'],
            ...     ('WR',1,1,True)     :['WR'],
            ...     ('FX',1,1,False)    :['RB','WR','TE']
            ... }
            >>> site_sport = Dummy.create_roster(sport='mysport', roster=roster ) #example!

        :param sport:
        :param roster:
        :return:
        """

        ret_roster_spot_position_list = []

        # order the incoming roster dict by the idx
        ordered_roster = OrderedDict(
            sorted(roster.items(), key=lambda k: k[0][2]))

        site_sport, created = SiteSport.objects.get_or_create(name=sport)
        # print(site_sport, 'site_sport')

        # create the roster spot mappings
        for rs_tuple, pos_names_list in ordered_roster.items():
            roster_spot_name = rs_tuple[0]
            roster_spot_amount = rs_tuple[1]
            roster_spot_idx = rs_tuple[2]
            primary = rs_tuple[3]
            # print('roster spot: %s, amount:%s, idx:%s, is_primary:%s' % (roster_spot_name,
            #                         roster_spot_amount, roster_spot_idx, primary))
            for pos_name in pos_names_list:
                #
                # 'c' is a boolean indicating whether the object was created or not
                position, c = Position.objects.get_or_create(
                    name=pos_name, site_sport=site_sport)
                # print('    ', position)
                roster_spot, c = RosterSpot.objects.get_or_create(
                    name=roster_spot_name,
                    amount=roster_spot_amount,
                    idx=roster_spot_idx,
                    site_sport=site_sport)
                # print('    ', roster_spot)
                roster_spot_position, c = RosterSpotPosition.objects.get_or_create(
                    position=position,
                    roster_spot=roster_spot,
                    is_primary=primary)
                ret_roster_spot_position_list.append(roster_spot_position)
                # print('    ', roster_spot_position)
        # print('...created!')
        return ret_roster_spot_position_list

    @staticmethod
    def create_player_stats(sport=DEFAULT_SPORT):
        """
        return a newly created player who could fit in the default roster.

        if 'roster' is None, we will call Dummy.create_roster() and use that data

        :param sport:
        :param roster:
        :return:
        """

        # ('QB',1,0,True)     :['QB'],
        position = None
        for rs_tuple, pos_list in Dummy.DEFAULT_ROSTER_MAP.items():
            for pos_name in pos_list:
                site_sport, c = SiteSport.objects.get_or_create(name=sport)
                position, c = Position.objects.get_or_create(
                    name=pos_name, site_sport=site_sport)
                break
            break
        if position is None:
            raise Exception(
                '>>>>> Dummy.create_player_stats() couldnt find any positions in roster'
            )

        dt_now = timezone.now()
        unix_ts = dt_now.strftime('%s')  # unix timestamp as srid ... not bad

        ssm = SiteSportManager()
        site_sport = ssm.get_site_sport(sport)
        game = Dummy.create_game(srid='game' + unix_ts, site_sport=site_sport)

        player = Dummy.create_player(srid='player' + unix_ts,
                                     position=position,
                                     team=game.home,
                                     site_sport=site_sport)

        if sport == Dummy.DEFAULT_SPORT:
            site_sport = None  # hack for backwards compatability, to not break older code
        player_stats = Dummy.create_player_stats_model(game, player,
                                                       site_sport)

        return player_stats

    @staticmethod
    def create_team(srid=None, alias=None, site_sport=None):
        """
        Creates a team with a random srid - based on current milliseconds.
        """
        if not srid:
            srid = "srid-%s" % int(round(time.time() * 1000)),
        if not alias:
            alias = "alias-%s" % int(round(time.time() * 1000)),

        if site_sport is None:
            t, created = TeamChild.objects.get_or_create(srid=srid,
                                                         alias=alias)
        else:
            ssm = SiteSportManager()
            team_model = ssm.get_team_class(site_sport)
            t, created = team_model.objects.get_or_create(srid=srid,
                                                          alias=alias)
        return t

    @staticmethod
    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

    @staticmethod
    def create_player(srid, position, team, site_sport=None):

        player = PlayerChild()
        player.srid = srid
        player.first_name = "Jon"
        player.last_name = "Doe"
        player.position = position

        player.team = team

        player.save()
        return player

    @staticmethod
    def create_player_stats_model(game, player, site_sport=None):
        """
        If site_sport is not specified, defaults to use PlayerStatsChild model

        may not work to well for baseball since there
        are 2 PlayerStats types (hitter/pitcher)
        """
        player_stats = None
        if site_sport is None:
            player_stats = PlayerStatsChild()
        else:
            ssm = SiteSportManager()
            player_stats_model_list = ssm.get_player_stats_class(site_sport)
            player_stats_model = player_stats_model_list[0]
            player_stats = player_stats_model()

        player_stats.fantasy_points = randint(0, 100)

        player_stats.game = game
        player_stats.player = player
        player_stats.srid_game = game.srid
        player_stats.srid_player = player.srid
        player_stats.position = player.position
        player_stats.save(fantasy_points_override=player_stats.fantasy_points)
        return player_stats

    @staticmethod
    def create_games(n=20, site_sport=None, round_start_times=False):
        # site_sport, created = SiteSport.objects.get_or_create(name=sport)
        dt_now = timezone.now()
        unix_ts = int(
            dt_now.strftime('%s'))  # unix timestamp as srid ... not bad
        games = []
        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)

        for x in range(0, n):
            game = Dummy.create_game(srid='%s' % (unix_ts + x),
                                     site_sport=site_sport,
                                     round_start_times=round_start_times)
            # game.season = dum_season # cant be null
            game.start = game.start + timedelta(
                minutes=x)  # stagger each game by 1 minute
            game.save()
            games.append(game)

        return games

    @staticmethod
    def create_players(n=20, teams=DEFAULT_TEAMS, site_sport=None):
        """
        calls Dummy.create_roster() and then creates X players using the positions from the roster
        """
        team_list = []
        for t in teams:
            team, create = TeamChild.objects.get_or_create(srid=t[0],
                                                           alias=t[1])
            team_list.append(team)
        n_teams = len(team_list)

        dt_now = timezone.now()
        unix_ts = int(dt_now.strftime('%s'))
        if site_sport is None:
            Dummy.create_roster()

        Dummy.create_roster(sport=site_sport)
        positions = Position.objects.all()
        size = len(positions)
        players = []
        for x in range(0, n):
            pos_idx = x % (size)
            players.append(
                Dummy.create_player(srid='%s' % (unix_ts + x),
                                    position=positions[pos_idx],
                                    team=team_list[x % n_teams],
                                    site_sport=site_sport))
        return players

    @staticmethod
    def create_player_stats_list(players=20,
                                 games=20,
                                 site_sport=None,
                                 round_start_times=False):
        """
        calls Dummy.create_roster() as a preqrequisite

        'players' is the number of players we want to create
        'games' is the number of games for which we will generate player stats for each player for

        :param players:
        :param games:
        :return:
        """

        player_stats_list = []
        players = Dummy.create_players(
            n=players, site_sport=site_sport
        )  # n=20 is the default argument which creates 20 players
        games = Dummy.create_games(n=games,
                                   site_sport=site_sport,
                                   round_start_times=round_start_times
                                   )  # n=20 is default for game as well
        for game in games:
            for player in players:
                player_stats_list.append(
                    Dummy.create_player_stats_model(game, player, site_sport))
        # print(len(player_stats_list), 'player_stats objects created. here are the first 15...')
        # for ps in player_stats_list[:15]:
        #     print('    ', str(ps))
        return player_stats_list

    @staticmethod
    def create_salary_config():
        salary_conf = SalaryConfig()
        salary_conf.trailing_games = 10
        salary_conf.days_since_last_game_flag = 10
        salary_conf.min_games_flag = 7
        salary_conf.min_player_salary = 3000
        salary_conf.max_team_salary = 50000
        salary_conf.min_avg_fppg_allowed_for_avg_calc = 5
        salary_conf.save()
        return salary_conf

    @staticmethod
    def generate_salaries(sport=DEFAULT_SPORT, pool_active=True):
        """
        internally, in this order, calls:
            - create_roster()
            - create_player_stats_list()

        returns the SalaryGenerator which created the salaries.
        """

        # prerequisite calls to create_roster(), create_player_stats_list()
        Dummy.create_roster(sport=sport)
        site_sport, created = SiteSport.objects.get_or_create(name=sport)
        Dummy.create_player_stats_list(site_sport=site_sport)

        #
        # create the config and the pool
        site_sport, c = SiteSport.objects.get_or_create(name=sport)

        salary_conf = Dummy.create_salary_config()

        pool = Pool()
        pool.site_sport = site_sport
        pool.salary_config = salary_conf
        pool.active = pool_active
        pool.save()

        Dummy.create_trailing_game_weight(salary_conf, 3, 3)
        Dummy.create_trailing_game_weight(salary_conf, 7, 2)
        Dummy.create_trailing_game_weight(salary_conf, 10, 1)

        #
        # now use SalaryGenerator class on these objects
        player_stats_classes = [PlayerStatsChild]
        generator = SalaryGenerator(player_stats_classes, pool)
        generator.generate_salaries()
        return generator

    @staticmethod
    def create_trailing_game_weight(salary_config, through, weight):
        trailing_game_weight = TrailingGameWeight()
        trailing_game_weight.salary = salary_config
        trailing_game_weight.through = through
        trailing_game_weight.weight = weight
        trailing_game_weight.save()