Ejemplo n.º 1
0
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    steam_id = db.Column(db.String(40), unique=True)
    name = db.Column(db.String(40))
    admin = db.Column(db.Boolean, default=False)
    servers = db.relationship('GameServer', backref='user', lazy='dynamic')
    teams = db.relationship('Team', backref='user', lazy='dynamic')
    matches = db.relationship('Match', backref='user', lazy='dynamic')

    @staticmethod
    def get_or_create(steam_id):
        rv = User.query.filter_by(steam_id=steam_id).first()
        if rv is None:
            rv = User()
            rv.steam_id = steam_id
            db.session.add(rv)
            app.logger.info('Creating user for {}'.format(steam_id))

        rv.admin = ('ADMIN_IDS' in app.config) and (steam_id
                                                    in app.config['ADMIN_IDS'])
        return rv

    def get_url(self):
        return url_for('user', userid=self.id)

    def get_steam_url(self):
        return 'http://steamcommunity.com/profiles/{}'.format(self.steam_id)

    def get_recent_matches(self, limit=10):
        return self.matches.filter_by(cancelled=False).limit(limit)

    def __repr__(self):
        return 'User(id={}, steam_id={}, name={}, admin={})'.format(
            self.id, self.steam_id, self.name, self.admin)
Ejemplo n.º 2
0
class MapStats(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    match_id = db.Column(db.Integer, db.ForeignKey('match.id'))
    map_number = db.Column(db.Integer)
    map_name = db.Column(db.String(64))
    start_time = db.Column(db.DateTime)
    end_time = db.Column(db.DateTime)
    winner = db.Column(db.Integer, db.ForeignKey('team.id'))
    team1_score = db.Column(db.Integer, default=0)
    team2_score = db.Column(db.Integer, default=0)
    player_stats = db.relationship('PlayerStats',
                                   backref='mapstats',
                                   lazy='dynamic')

    @staticmethod
    def get_or_create(match_id, map_number, map_name=''):
        match = Match.query.get(match_id)
        if match is None or map_number >= match.max_maps:
            return None

        rv = MapStats.query.filter_by(match_id=match_id,
                                      map_number=map_number).first()
        if rv is None:
            rv = MapStats()
            rv.match_id = match_id
            rv.map_number = map_number
            rv.map_name = map_name
            rv.start_time = datetime.datetime.utcnow()
            rv.team1_score = 0
            rv.team2_score = 0
            db.session.add(rv)
        return rv

    def __repr__(self):
        return 'MapStats(' + str(self.id) + ',' + str(self.map_name) + ')'
Ejemplo n.º 3
0
class Season(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    name = db.Column(db.String(60), default='')
    start_date = db.Column(db.DateTime, default=datetime.datetime.utcnow())
    end_date = db.Column(db.DateTime)
    matches = db.relationship('Match', backref='season', lazy='dynamic')

    @staticmethod
    def create(user, name, start_date, end_date):
        rv = Season()
        rv.user_id = user.id
        rv.name = name
        rv.start_date = start_date
        rv.end_date = end_date
        db.session.add(rv)
        return rv

    def get_season_name(self):
        return self.name

    def set_data(self, user, name, start_date, end_date):
        self.user_id = user.id
        self.name = name
        self.start_date = start_date
        self.end_date = end_date

    def can_edit(self, user):
        if not user:
            return False
        if self.user_id == user.id:
            return True
        return False

    def can_delete(self, user):
        if not self.can_edit(user):
            return False
        return self.get_recent_matches().count() == 0

    def get_recent_matches(self, limit=10):
        season = Season.query.get_or_404(self.id)
        matches = season.matches

        recent_matches = matches.filter(
            (Match.season_id == self.id) & (Match.cancelled == False)
            & (Match.start_time != None)  # noqa: E712
        ).order_by(-Match.id).limit(5)

        if recent_matches is None:
            return []
        else:
            return recent_matches

    def __repr__(self):
        return 'Season(id={}, user_id={}, name={}, start_date={}, end_date={})'.format(
            self.id, self.user_id, self.name, self.start_date, self.end_date)
Ejemplo n.º 4
0
class Match(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    server_id = db.Column(db.Integer,
                          db.ForeignKey('game_server.id'),
                          index=True)
    team1_id = db.Column(db.Integer, db.ForeignKey('team.id'))
    team2_id = db.Column(db.Integer, db.ForeignKey('team.id'))
    season_id = db.Column(db.Integer, db.ForeignKey('season.id'))

    team1_string = db.Column(db.String(32), default='')
    team2_string = db.Column(db.String(32), default='')
    winner = db.Column(db.Integer, db.ForeignKey('team.id'))
    plugin_version = db.Column(db.String(32), default='unknown')

    forfeit = db.Column(db.Boolean, default=False)
    cancelled = db.Column(db.Boolean, default=False)
    start_time = db.Column(db.DateTime)
    end_time = db.Column(db.DateTime)
    max_maps = db.Column(db.Integer)
    title = db.Column(db.String(60), default='')
    skip_veto = db.Column(db.Boolean)
    api_key = db.Column(db.String(32))
    veto_first = db.Column(db.String(5))
    veto_mappool = db.Column(db.String(500))
    map_stats = db.relationship('MapStats', backref='match', lazy='dynamic')

    side_type = db.Column(db.String(32))
    team1_score = db.Column(db.Integer, default=0)
    team2_score = db.Column(db.Integer, default=0)
    team1_series_score = db.Column(db.Integer, default=0)
    team2_series_score = db.Column(db.Integer, default=0)
    spectator_auths = db.Column(db.PickleType)
    private_match = db.Column(db.Boolean)
    enforce_teams = db.Column(db.Boolean, default=True)

    @staticmethod
    def create(user,
               team1_id,
               team2_id,
               team1_string,
               team2_string,
               max_maps,
               skip_veto,
               title,
               veto_mappool,
               season_id,
               side_type,
               veto_first,
               server_id=None,
               team1_series_score=None,
               team2_series_score=None,
               spectator_auths=None,
               private_match=False,
               enforce_teams=True):
        rv = Match()
        rv.user_id = user.id
        rv.team1_id = team1_id
        rv.team2_id = team2_id
        rv.season_id = season_id
        rv.side_type = side_type
        rv.skip_veto = skip_veto
        rv.title = title
        rv.veto_mappool = ' '.join(veto_mappool)
        rv.server_id = server_id
        rv.max_maps = max_maps
        if veto_first == "CT":
            rv.veto_first = "team1"
        elif veto_first == "T":
            rv.veto_first = "team2"
        else:
            rv.veto_first = None
        rv.api_key = ''.join(
            random.SystemRandom().choice(string.ascii_uppercase +
                                         string.digits) for _ in range(24))
        rv.team1_series_score = team1_series_score
        rv.team2_series_score = team2_series_score
        rv.spectator_auths = spectator_auths
        rv.private_match = private_match
        rv.enforce_teams = enforce_teams
        db.session.add(rv)
        return rv

    def get_status_string(self, show_winner=True):
        if self.pending():
            return 'Pending'
        elif self.live():
            team1_score, team2_score = self.get_current_score()
            return 'Live, {}:{}'.format(team1_score, team2_score)
        elif self.finished():
            t1score, t2score = self.get_current_score()
            min_score = min(t1score, t2score)
            max_score = max(t1score, t2score)
            score_string = '{}:{}'.format(max_score, min_score)

            if not show_winner:
                return 'Finished'
            elif self.winner == self.team1_id:
                return 'Won {} by {}'.format(score_string,
                                             self.get_team1().name)
            elif self.winner == self.team2_id:
                return 'Won {} by {}'.format(score_string,
                                             self.get_team2().name)
            else:
                return 'Tied {}'.format(score_string)

        else:
            return 'Cancelled'

    def is_private_match(self):
        return self.private_match

    def get_vs_string(self):
        team1 = self.get_team1()
        team2 = self.get_team2()
        scores = self.get_current_score()

        str = '{} vs {} ({}:{})'.format(team1.get_name_url_html(),
                                        team2.get_name_url_html(), scores[0],
                                        scores[1])

        return Markup(str)

    def finalized(self):
        return self.cancelled or self.finished()

    def pending(self):
        return self.start_time is None and not self.cancelled

    def finished(self):
        return self.end_time is not None and not self.cancelled

    def live(self):
        return self.start_time is not None and self.end_time is None and not self.cancelled

    def get_server(self):
        return GameServer.query.filter_by(id=self.server_id).first()

    def get_start_time(self):
        return self.start_time if self.start_time is not None else ''

    def get_end_time(self):
        return self.end_time if self.end_time is not None else ''

    def get_season(self):
        if self.season_id:
            return Season.query.get(self.season_id)
        else:
            return None

    def get_season_id(self):
        return self.season_id

    def get_current_score(self):
        if self.max_maps == 1:
            mapstat = self.map_stats.first()
            if not mapstat:
                return (0, 0)
            else:
                return (mapstat.team1_score, mapstat.team2_score)

        else:
            return (self.team1_score, self.team2_score)

    def send_to_server(self):
        server = GameServer.query.get(self.server_id)
        if not server:
            return False

        url = url_for('match.match_config',
                      matchid=self.id,
                      _external=True,
                      _scheme='http')
        # Remove http protocal since the get5 plugin can't parse args with the
        # : in them.
        url = url.replace("http://", "")
        url = url.replace("https://", "")

        loadmatch_response = server.send_rcon_command('get5_loadmatch_url ' +
                                                      url)

        server.send_rcon_command('get5_web_api_key ' + self.api_key)

        # ***HACK FIX TO ENSURE CHECK_AUTHS WORKS AS INTENDED***
        server.send_rcon_command('map de_dust2')

        if loadmatch_response:  # There should be no response
            return False

        return True

    def get_team1(self):
        return Team.query.get(self.team1_id)

    def get_team2(self):
        return Team.query.get(self.team2_id)

    def get_user(self):
        return User.query.get(self.user_id)

    def get_winner(self):
        if self.team1_score > self.team2_score:
            return self.get_team1()
        elif self.team2_score > self.team1_score:
            return self.get_team2()
        else:
            return None

    def get_loser(self):
        if self.team1_score > self.team2_score:
            return self.get_team2()
        elif self.team2_score > self.team1_score:
            return self.get_team1()
        else:
            return None

    def build_match_dict(self):
        d = {}
        d['matchid'] = str(self.id)
        d['match_title'] = self.title
        d['side_type'] = self.side_type
        d['veto_first'] = self.veto_first

        d['skip_veto'] = self.skip_veto
        if self.max_maps == 2:
            d['bo2_series'] = True
        else:
            d['maps_to_win'] = self.max_maps / 2 + 1

        def add_team_data(teamkey, teamid, matchtext):
            team = Team.query.get(teamid)
            if not team:
                return
            d[teamkey] = {}

            # Add entries if they have values.
            def add_if(key, value):
                if value:
                    d[teamkey][key] = value

            add_if('name', team.name)
            add_if('name', team.name)
            add_if('tag', team.tag)
            add_if('flag', team.flag.upper())
            add_if('logo', team.logo)
            add_if('matchtext', matchtext)
            # Add new series score.
            if teamkey == 'team1':
                add_if('series_score', self.team1_series_score)
            else:
                add_if('series_score', self.team2_series_score)
            # Attempt to send in KV Pairs of preferred names.
            # If none, or error, send in the regular list.
            try:
                d[teamkey]['players'] = OrderedDict()
                for uid, name in zip(team.auths, team.preferred_names):
                    if uid:
                        d[teamkey]['players'][uid] = name
            except:
                d[teamkey]['players'] = filter(lambda x: x != '', team.auths)

        add_team_data('team1', self.team1_id, self.team1_string)
        add_team_data('team2', self.team2_id, self.team2_string)

        d['cvars'] = {}
        d['cvars']['get5_web_api_url'] = url_for('home',
                                                 _external=True,
                                                 _scheme='http')
        d['cvars']['get5_check_auths'] = "1" if self.enforce_teams else "0"
        # Add in for spectators modification.
        d['min_spectators_to_ready'] = 0

        # Perm spectators will go within config, then can add more from match
        # screen.
        d['spectators'] = {"players": app.config['SPECTATOR_IDS']}

        # If we don't have any perm spectators, create the new list.
        if not d['spectators']:
            d['spectators'] = {"players": []}
        # Append auths from match page if we have any.
        if self.spectator_auths:
            for spectator in self.spectator_auths:
                d['spectators']["players"].append(spectator)

        if not d['spectators']['players']:
            d['spectators'] = None

        if self.veto_mappool:
            d['maplist'] = []
            for map in self.veto_mappool.split():
                d['maplist'].append(map)

        return d

    def __repr__(self):
        return 'Match(id={})'.format(self.id)
Ejemplo n.º 5
0
class Match(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    server_id = db.Column(db.Integer,
                          db.ForeignKey('game_server.id'),
                          index=True)
    team1_id = db.Column(db.Integer, db.ForeignKey('team.id'))
    team2_id = db.Column(db.Integer, db.ForeignKey('team.id'))
    team1_string = db.Column(db.String(32), default='')
    team2_string = db.Column(db.String(32), default='')
    winner = db.Column(db.Integer, db.ForeignKey('team.id'))
    plugin_version = db.Column(db.String(32), default='unknown')

    forfeit = db.Column(db.Boolean, default=False)
    cancelled = db.Column(db.Boolean, default=False)
    start_time = db.Column(db.DateTime)
    end_time = db.Column(db.DateTime)
    max_maps = db.Column(db.Integer)
    title = db.Column(db.String(60), default='')
    skip_veto = db.Column(db.Boolean)
    api_key = db.Column(db.String(32))

    veto_mappool = db.Column(db.String(500))
    map_stats = db.relationship('MapStats', backref='match', lazy='dynamic')

    team1_score = db.Column(db.Integer, default=0)
    team2_score = db.Column(db.Integer, default=0)

    @staticmethod
    def create(user,
               team1_id,
               team2_id,
               team1_string,
               team2_string,
               max_maps,
               skip_veto,
               title,
               veto_mappool,
               server_id=None):
        rv = Match()
        rv.user_id = user.id
        rv.team1_id = team1_id
        rv.team2_id = team2_id
        rv.skip_veto = skip_veto
        rv.title = title
        rv.veto_mappool = ' '.join(veto_mappool)
        rv.server_id = server_id
        rv.max_maps = max_maps
        rv.api_key = ''.join(
            random.SystemRandom().choice(string.ascii_uppercase +
                                         string.digits) for _ in range(24))
        db.session.add(rv)
        return rv

    def get_status_string(self, show_winner=True):
        if self.pending():
            return 'Pending'
        elif self.live():
            team1_score, team2_score = self.get_current_score()
            return 'Live, {}:{}'.format(team1_score, team2_score)
        elif self.finished():
            t1score, t2score = self.get_current_score()
            min_score = min(t1score, t2score)
            max_score = max(t1score, t2score)
            score_string = '{}:{}'.format(max_score, min_score)

            if not show_winner:
                return 'Finished'
            elif self.winner == self.team1_id:
                return 'Won {} by {}'.format(score_string,
                                             self.get_team1().name)
            elif self.winner == self.team2_id:
                return 'Won {} by {}'.format(score_string,
                                             self.get_team2().name)
            else:
                return 'Tied {}'.format(score_string)

        else:
            return 'Cancelled'

    def get_vs_string(self):
        team1 = self.get_team1()
        team2 = self.get_team2()
        scores = self.get_current_score()

        str = '{} vs {} ({}:{})'.format(team1.get_name_url_html(),
                                        team2.get_name_url_html(), scores[0],
                                        scores[1])

        return Markup(str)

    def finalized(self):
        return self.cancelled or self.finished()

    def pending(self):
        return self.start_time is None and not self.cancelled

    def finished(self):
        return self.end_time is not None and not self.cancelled

    def live(self):
        return self.start_time is not None and self.end_time is None and not self.cancelled

    def get_server(self):
        return GameServer.query.filter_by(id=self.server_id).first()

    def get_current_score(self):
        if self.max_maps == 1:
            mapstat = self.map_stats.first()
            if not mapstat:
                return (0, 0)
            else:
                return (mapstat.team1_score, mapstat.team2_score)

        else:
            return (self.team1_score, self.team2_score)

    def send_to_server(self):
        server = GameServer.query.get(self.server_id)
        if not server:
            return False

        url = url_for('match.match_config',
                      matchid=self.id,
                      _external=True,
                      _scheme='http')
        # Remove http protocal since the get5 plugin can't parse args with the
        # : in them.
        url = url.replace("http://", "")
        url = url.replace("https://", "")

        loadmatch_response = server.send_rcon_command('get5_loadmatch_url ' +
                                                      url)

        server.send_rcon_command('get5_web_api_key ' + self.api_key)

        if loadmatch_response:  # There should be no response
            return False

        return True

    def get_team1(self):
        return Team.query.get(self.team1_id)

    def get_team2(self):
        return Team.query.get(self.team2_id)

    def get_user(self):
        return User.query.get(self.user_id)

    def get_winner(self):
        if self.team1_score > self.team2_score:
            return self.get_team1()
        elif self.team2_score > self.team1_score:
            return self.get_team2()
        else:
            return None

    def get_loser(self):
        if self.team1_score > self.team2_score:
            return self.get_team2()
        elif self.team2_score > self.team1_score:
            return self.get_team1()
        else:
            return None

    def build_match_dict(self):
        d = {}
        d['matchid'] = str(self.id)
        d['match_title'] = self.title

        d['skip_veto'] = self.skip_veto
        if self.max_maps == 2:
            d['bo2_series'] = True
        else:
            d['maps_to_win'] = self.max_maps / 2 + 1

        def add_team_data(teamkey, teamid, matchtext):
            team = Team.query.get(teamid)
            if not team:
                return
            d[teamkey] = {}

            # Add entries if they have values.
            def add_if(key, value):
                if value:
                    d[teamkey][key] = value

            add_if('name', team.name)
            add_if('name', team.name)
            add_if('tag', team.tag)
            add_if('flag', team.flag.upper())
            add_if('logo', team.logo)
            add_if('matchtext', matchtext)
            d[teamkey]['players'] = filter(lambda x: x != '', team.auths)

        add_team_data('team1', self.team1_id, self.team1_string)
        add_team_data('team2', self.team2_id, self.team2_string)

        d['cvars'] = {}

        d['cvars']['get5_web_api_url'] = url_for('home',
                                                 _external=True,
                                                 _scheme='http')

        if self.veto_mappool:
            d['maplist'] = []
            for map in self.veto_mappool.split():
                d['maplist'].append(map)

        if 'SPECTATOR_IDS' in app.config:
            d['spectators'] = {"players": app.config['SPECTATOR_IDS']}

        if 'MIN_SPECTATORS_TO_READY' in app.config:
            d['min_spectators_to_ready'] = app.config[
                'MIN_SPECTATORS_TO_READY']

        return d

    def __repr__(self):
        return 'Match(id={})'.format(self.id)
Ejemplo n.º 6
0
class Tournament(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    winner = db.Column(db.Integer, db.ForeignKey('team.id'))
    cancelled = db.Column(db.Boolean, default=False)
    finished = db.Column(db.Boolean, default=False)
    start_time = db.Column(db.DateTime)
    end_time = db.Column(db.DateTime)
    name = db.Column(db.String(60))
    url = db.Column(db.String(60))
    challonge_id = db.Column(db.Integer)
    challonge_data = db.Column(db.PickleType)
    participants = db.relationship('Team',
                                   secondary=TournamentTeam,
                                   backref='tournaments',
                                   lazy='dynamic')
    matches = db.relationship('Match', backref='tournament', lazy='dynamic')
    serverpool = db.relationship('GameServer',
                                 secondary=TournamentGameServer,
                                 backref='tournaments',
                                 lazy='dynamic')
    veto_mappool = db.Column(db.String(160))

    @staticmethod
    def create(user,
               name,
               url,
               veto_mappool,
               serverpool=None,
               challonge_id=None,
               challonge_data=None):
        rv = Tournament()
        rv.user_id = user.id
        rv.url = url
        rv.name = name
        rv.veto_mappool = ' '.join(veto_mappool)
        if serverpool:
            rv.serverpool.extend(serverpool)
        rv.challonge_id = challonge_id
        rv.challonge_data = challonge_data
        db.session.add(rv)
        return rv

    def finalized(self):
        return self.cancelled or self.finished()

    def pending(self):
        return self.start_time is None and not self.cancelled

    def finished(self):
        return self.end_time is not None and not self.cancelled

    def live(self):
        return self.start_time is not None and self.end_time is None and not self.cancelled

    def get_user(self):
        return User.query.get(self.user_id)

    def get_available_server(self):
        for server in self.serverpool.all():
            if not server.in_use:
                return server
        return None

    def __repr__(self):
        return 'Tournament(id={})'.format(self.id)