Exemplo n.º 1
0
    def __init__(self,
                 update_season_frequence=604800,
                 query_match_data_frequence=28800,
                 scraper_requests_frequence=43200,
                 **dbparams):
        self.logger = logging.getLogger('ComunioScore')
        self.logger.info('Create class SofascoreDB')

        # init base classes
        DBHandler.__init__(self, **dbparams)
        Thread.__init__(self)

        # attributes for the update frequence
        self.update_season_frequence = update_season_frequence  # 604800 seconds (once in a week)
        self.query_match_data_frequence = query_match_data_frequence  # 28800 seconds (8h)
        self.scraper_requests_frequence = scraper_requests_frequence  # 43200 seconds (12h)

        self.running = True

        # event handler
        self.matchscheduler_event_handler = None
        self.comunio_user_data_event_handler = None

        # counters set to zero
        self.update_season_counter = 0
        self.query_match_data_counter = 0
        self.scraper_requests_counter = 0

        # create BundesligaScore instance
        self.bundesliga = BundesligaScore()

        self.season_data = None
Exemplo n.º 2
0
    def __init__(self, **dbparams):
        self.logger = logging.getLogger('ComunioScore')
        self.logger.info('Create class LiveData')

        # init base class
        super().__init__(**dbparams)

        # set attributes
        self.running = True
        self.is_notify = True
        self.msg_rate = 10 * 60  # 10 min as default
        self.msg_rate_timer = 0

        # bundesligascore instance
        self.bundesliga = BundesligaScore()

        # create PointCalculator instance
        self.pointcalculator = PointCalculator()

        # sql
        self.user_sql = "select userid, username from {}.{}".format(self.comunioscore_schema, self.comunioscore_table_user)
        self.squad_sql = "select playername, playerposition, club  from {}.{} where userid = %s and linedup = 'true' ".format(self.comunioscore_schema, self.comunioscore_table_squad)
        self.comunio_users = self.dbfetcher.all(sql=self.user_sql)

        # event handler
        self.update_squad_event_handler = None
        self.telegram_send_event_handler = None

        # init current match day to None
        self.current_match_day = None

        # create lock object
        self.telegram_lock = Lock()
Exemplo n.º 3
0
    def setUp(self) -> None:

        # load local config file
        self.config = configparser.ConfigParser()
        self.config.read(ROOT_DIR + '/config/cfg.ini')

        # ScraperAPI config
        try:
            self.apikey = self.config.get('ScraperAPI', 'apikey')
        except (KeyError, configparser.NoSectionError) as e:
            self.apikey = os.environ['ScraperAPI']

        SofaScore.init_scraper(api_key=self.apikey)

        self.bundesliga = BundesligaScore()
        self.bundesliga.init_season_data(season_date="2020-05-15")

        self.match_id = "8272345"
Exemplo n.º 4
0
class TestBundesligaScore(unittest.TestCase):
    def setUp(self) -> None:

        # load local config file
        self.config = configparser.ConfigParser()
        self.config.read(ROOT_DIR + '/config/cfg.ini')

        # ScraperAPI config
        try:
            self.apikey = self.config.get('ScraperAPI', 'apikey')
        except (KeyError, configparser.NoSectionError) as e:
            self.apikey = os.environ['ScraperAPI']

        SofaScore.init_scraper(api_key=self.apikey)

        self.bundesliga = BundesligaScore()
        self.bundesliga.init_season_data(season_date="2020-05-15")

        self.match_id = "8272345"

    def test_ids_for_matchday(self):

        matchday_ids = self.bundesliga.ids_for_matchday(date="2019-10-05")
        self.assertIsInstance(matchday_ids,
                              list,
                              msg="matchday ids must be type of list")
        for match in matchday_ids:
            self.assertIsInstance(match,
                                  dict,
                                  msg="match must be type of dict")
            self.assertIn('id', match, msg="match dict has no key id")
            self.assertIn('match', match, msg="match dict has no key match")
            self.assertIn('homeTeam',
                          match,
                          msg="match dict has no key homeTeam")
            self.assertIn('awayTeam',
                          match,
                          msg="match dict has no key awayTeam")

    def test_lineup_from_match_id(self):

        lineup = self.bundesliga.lineup_from_match_id(match_id=self.match_id)

        self.assertIsInstance(lineup, dict, msg="lineup must be type of dict")
        self.assertIn('homeTeam',
                      lineup,
                      msg="lineup dict has no key homeTeam")
        self.assertIn('awayTeam',
                      lineup,
                      msg="lineup dict has no key awayTeam")
        self.assertIn('homeTeamIncidents',
                      lineup,
                      msg="lineup dict has no key homeTeamIncidents")
        self.assertIn('awayTeamIncidents',
                      lineup,
                      msg="lineup dict has no key awayTeamIncidents")
        self.assertIsInstance(lineup['homeTeam'],
                              list,
                              msg="lineup['homeTeam'] must be type of list")
        self.assertIsInstance(lineup['awayTeam'],
                              list,
                              msg="lineup['awayTeam'] must be type of list")
        self.assertIsInstance(
            lineup['homeTeamIncidents'],
            list,
            msg="lineup['homeTeamIncidents'] must be type of list")
        self.assertIsInstance(
            lineup['awayTeamIncidents'],
            list,
            msg="lineup['awayTeamIncidents'] must be type of list")
        for (homeplayer, awayplayer) in zip(lineup['homeTeam'],
                                            lineup['awayTeam']):
            self.assertIsInstance(homeplayer,
                                  dict,
                                  msg="homeplayer must be type of list")
            self.assertIsInstance(awayplayer,
                                  dict,
                                  msg="awayplayer must be type of list")

    def test_season_data(self):

        season_data = self.bundesliga.season_data()
        self.assertIsInstance(season_data,
                              list,
                              msg="season data must be type of list")
        for matchday in season_data:
            self.assertIsInstance(matchday,
                                  dict,
                                  msg="matchday data must be type of dict")

    def test_is_finished(self):

        is_finished = self.bundesliga.is_finished(matchid=self.match_id)
        self.assertTrue(is_finished, msg="is_finished must be True!")

    def tearDown(self) -> None:

        self.bundesliga.close()
Exemplo n.º 5
0
class SofascoreDB(DBHandler, Thread):
    """ class SofascoreDB to insert sofascore data into database

    USAGE:
            sofascoredb = SofascoreDB(update_frequence=21600, **dbparams)
            sofascoredb.start()

    """
    def __init__(self,
                 update_season_frequence=604800,
                 query_match_data_frequence=28800,
                 scraper_requests_frequence=43200,
                 **dbparams):
        self.logger = logging.getLogger('ComunioScore')
        self.logger.info('Create class SofascoreDB')

        # init base classes
        DBHandler.__init__(self, **dbparams)
        Thread.__init__(self)

        # attributes for the update frequence
        self.update_season_frequence = update_season_frequence  # 604800 seconds (once in a week)
        self.query_match_data_frequence = query_match_data_frequence  # 28800 seconds (8h)
        self.scraper_requests_frequence = scraper_requests_frequence  # 43200 seconds (12h)

        self.running = True

        # event handler
        self.matchscheduler_event_handler = None
        self.comunio_user_data_event_handler = None

        # counters set to zero
        self.update_season_counter = 0
        self.query_match_data_counter = 0
        self.scraper_requests_counter = 0

        # create BundesligaScore instance
        self.bundesliga = BundesligaScore()

        self.season_data = None

    def run(self) -> None:
        """ run thread for class SofascoreDB

        """
        self.delete_season()
        sleep(1)
        self.delete_points()
        sleep(1)
        self.insert_season()
        sleep(1)
        self.insert_points()
        sleep(1)
        self.query_match_data()
        self.scraper_account_requests()
        self.logger.info("Start Sofascoredb run thread!")

        while self.running:
            sleep(1)
            self.update_season_counter += 1
            self.query_match_data_counter += 1
            self.scraper_requests_counter += 1

            if self.query_match_data_counter > self.query_match_data_frequence:
                self.query_match_data()
                self.query_match_data_counter = 0
            if self.update_season_counter > self.update_season_frequence:
                self.update_season()
                self.update_season_counter = 0
            if self.scraper_requests_counter > self.scraper_requests_frequence:
                self.scraper_account_requests()
                self.scraper_requests_counter = 0

    def register_matchscheduler_event_handler(self, func):
        """ register the matchscheduler event handler function

        :param func: event handler function
        """

        self.matchscheduler_event_handler = func

    def register_comunio_user_data(self, func):
        """ register the comunio user data event handler function

        :param func: event handler function
        """
        self.comunio_user_data_event_handler = func

    def insert_season(self):
        """ insert season data into database

        """
        self.logger.info("Sofascoredb insert season data into database")

        sql = "insert into {}.{} (match_day, match_type, match_id, start_timestamp, start_datetime, homeTeam, " \
              "awayTeam, homeScore, awayScore, season, scheduled) values(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)".format(
               self.comunioscore_schema, self.comunioscore_table_season)

        self.season_data = self.bundesliga.season_data()
        season_list = list()

        for matchday in self.season_data:
            start_dt = datetime.datetime.fromtimestamp(
                matchday['startTimestamp'])
            season_list.append(
                (matchday['matchDay'], matchday['type'], matchday['matchId'],
                 matchday['startTimestamp'], start_dt, matchday['homeTeam'],
                 matchday['awayTeam'], matchday['homeScore'],
                 matchday['awayScore'], self.bundesliga.season_year, False))

        try:
            self.dbinserter.many_rows(sql=sql, datas=season_list)
        except DBInserterError as ex:
            self.logger.error(ex)

    def update_season(self):
        """ updates season data into database

        """
        self.logger.info("Sofascoredb updating season data in database")

        self.season_data = self.bundesliga.season_data()

        sql = "update {}.{} set match_type = %s, homeScore = %s, awayScore = %s where match_id = %s".format(
            self.comunioscore_schema, self.comunioscore_table_season)

        try:
            for matchday in self.season_data:
                self.dbinserter.row(
                    sql=sql,
                    data=(matchday['type'], matchday['homeScore'],
                          matchday['awayScore'], matchday['matchId']))
        except DBInserterError as ex:
            self.logger.error(ex)

    def delete_season(self):
        """ deletes season data from database

        """
        self.logger.info("Sofascoredb deleting season data from database")

        sql = "delete from {}.{}".format(self.comunioscore_schema,
                                         self.comunioscore_table_season)

        try:
            self.dbinserter.sql(sql=sql, autocommit=True)
        except DBInserterError as ex:
            self.logger.error(ex)

    def get_last_match_day(self):
        """ get last match day from database

        :return: None if first match day, else last match day
        """
        last_match_day_sql = "select match_day from {}.{} where match_type='finished' order by match_day desc limit 1"\
                             .format(self.comunioscore_schema, self.comunioscore_table_season)

        last_match_day = self.dbfetcher.one(sql=last_match_day_sql)

        if last_match_day is None:
            return None
        else:
            # check if 9 matches are already finished
            finished_sql = "select match_day from {}.{} where match_type='finished' and match_day=%s".format(
                self.comunioscore_schema, self.comunioscore_table_season)

            last_match_day = last_match_day[0]
            matches_finished_list = self.dbfetcher.all(sql=finished_sql,
                                                       data=(last_match_day, ))

            if len(matches_finished_list) == 9:
                return last_match_day
            else:
                return last_match_day - 1

    def query_match_data(self):
        """ queries the match day data from season table and registers new match events

        """
        self.logger.info("Sofascoredb queries match data from database")

        last_match_day = self.get_last_match_day()

        if last_match_day is None:
            next_match_day = 1
        elif last_match_day == 34:
            self.logger.info(
                "Last match day {} reached!".format(last_match_day))
            return
        else:
            next_match_day = last_match_day + 1

        self.logger.info("Set next_match_day to {}".format(next_match_day))

        match_sql = "select * from {}.{} where match_day=%s and scheduled='false'".format(
            self.comunioscore_schema, self.comunioscore_table_season)
        postponed_matches_sql = "select * from {}.{} where match_day<%s and match_type='notstarted' and scheduled='false'".format(
            self.comunioscore_schema, self.comunioscore_table_season)
        #next_match_day = 34
        match_day_data = self.dbfetcher.all(sql=match_sql,
                                            data=(next_match_day, ))
        postponed_matches_data = self.dbfetcher.all(sql=postponed_matches_sql,
                                                    data=(next_match_day, ))

        if self.matchscheduler_event_handler:
            # register weekly matchday data
            self.logger.info(
                "Start registering {} matches for match day {}".format(
                    len(match_day_data), next_match_day))
            for (i, match) in enumerate(match_day_data):

                if match[1] in (
                        'postponed',
                        'canceled'):  # log postponed or canceled match types
                    self.logger.error(
                        "Not registering match day {}: {} vs. {} because match is {}"
                        .format(match[0], match[5], match[6], match[1]))

                elif match[1] in (
                        'notstarted', 'inprogress'
                ):  # notstarted, inprogress are the normal match types for new events
                    self.update_scheduled_match(match_day=match[0],
                                                match_id=match[2])
                    self.matchscheduler_event_handler(event_ts=match[3],
                                                      match_day=match[0],
                                                      match_id=match[2],
                                                      home_team=match[5],
                                                      away_team=match[6])
                else:
                    self.logger.error(
                        "Could not register new event for match day {} ({}): {} vs. {}"
                        .format(match[0], match[1], match[5], match[6]))

            self.logger.info(
                "Finished registering matches for match day {}".format(
                    next_match_day))

            # register postponed matches data
            for (i, match) in enumerate(postponed_matches_data):
                self.update_scheduled_match(match_day=match[0],
                                            match_id=match[2])
                self.matchscheduler_event_handler(event_ts=match[3],
                                                  match_day=match[0],
                                                  match_id=match[2],
                                                  home_team=match[5],
                                                  away_team=match[6],
                                                  postponed=True)
        else:
            self.logger.error("No matchscheduler event handler registered!!")

    def update_scheduled_match(self, match_day, match_id):
        """ updates the scheduled attribute in the season table

        """
        update_scheduled_sql = "update {}.{} set scheduled=%s where match_day=%s and match_id=%s".format(
            self.comunioscore_schema, self.comunioscore_table_season)

        try:
            self.dbinserter.row(sql=update_scheduled_sql,
                                data=(True, match_day, match_id))
        except DBInserterError as ex:
            self.logger.error(ex)

    def insert_points(self):
        """ inserts all data into points table

        """
        self.logger.info("Sofascoredb insert points data into database")

        points_sql = "insert into {}.{} (userid, username, match_id, match_day, hometeam, awayteam) " \
                     "values (%s, %s, %s, %s, %s, %s)".format(self.comunioscore_schema, self.comunioscore_table_points)

        points_table_list = list()
        if self.comunio_user_data_event_handler:
            user_data = self.comunio_user_data_event_handler()

            if user_data is not None:

                for user in user_data:
                    userid = user['id']
                    username = user['name']
                    for matchday in self.season_data:
                        points_table_list.append(
                            (userid, username, matchday['matchId'],
                             matchday['matchDay'], matchday['homeTeam'],
                             matchday['awayTeam']))

                try:
                    self.dbinserter.many_rows(sql=points_sql,
                                              datas=points_table_list)
                except DBInserterError as ex:
                    self.logger.error(ex)
            else:
                self.logger.error(
                    "Could not insert points data into database because user_data is None. Retry in 5 seconds"
                )
                sleep(5)
                self.insert_points()
        else:
            self.logger.error("Event Handler for comunio user data is None!")

    def delete_points(self):
        """ deletes all data from points table

        """
        self.logger.info("Sofascoredb deleting points data from database")

        sql = "delete from {}.{}".format(self.comunioscore_schema,
                                         self.comunioscore_table_points)

        try:
            self.dbinserter.sql(sql=sql, autocommit=True)
        except DBInserterError as ex:
            self.logger.error(ex)

    def scraper_account_requests(self):
        """ logs the scraper account requests

        """

        scraper_requests = self.bundesliga.get_scraper_requests()
        if ('requestCount' and 'requestLimit') in scraper_requests.keys():
            request_count = scraper_requests['requestCount']
            request_limit = scraper_requests['requestLimit']
            self.logger.info("Scraper request {} from Limit of {}".format(
                request_count, request_limit))
        else:
            self.logger.error(
                "Could not request the ScraperAPIClient account info!")
Exemplo n.º 6
0
class LiveData(DBHandler):
    """ class LiveData to fetch live data from given match id

    USAGE:
            livedata = LiveData()
            livedata.fetch()

    """
    is_squad_updated = False

    def __init__(self, **dbparams):
        self.logger = logging.getLogger('ComunioScore')
        self.logger.info('Create class LiveData')

        # init base class
        super().__init__(**dbparams)

        # set attributes
        self.running = True
        self.is_notify = True
        self.msg_rate = 10 * 60  # 10 min as default
        self.msg_rate_timer = 0

        # bundesligascore instance
        self.bundesliga = BundesligaScore()

        # create PointCalculator instance
        self.pointcalculator = PointCalculator()

        # sql
        self.user_sql = "select userid, username from {}.{}".format(self.comunioscore_schema, self.comunioscore_table_user)
        self.squad_sql = "select playername, playerposition, club  from {}.{} where userid = %s and linedup = 'true' ".format(self.comunioscore_schema, self.comunioscore_table_squad)
        self.comunio_users = self.dbfetcher.all(sql=self.user_sql)

        # event handler
        self.update_squad_event_handler = None
        self.telegram_send_event_handler = None

        # init current match day to None
        self.current_match_day = None

        # create lock object
        self.telegram_lock = Lock()

    def register_update_squad_event_handler(self, func):
        """ register the update squad event handler

        :param func: event handler
        """
        self.update_squad_event_handler = func

    def register_telegram_send_event_handler(self, func):
        """ register the telegram send event handler

        :param func: event handler
        """
        self.telegram_send_event_handler = func

    def fetch(self, match_day, match_id, home_team, away_team):
        """ fetches live data from given match id for comunio players of interest

        :param match_day: current match day
        :param match_id: match id for sofascore
        :param home_team: home team
        :param away_team: away team
        """

        live_data_start_msg = "Start fetching live data from match day {}: *{}* vs. *{}*".format(match_day, home_team, away_team)
        self.logger.info(live_data_start_msg)

        # send start msg
        if self.is_notify:
            self.telegram_lock.acquire()
            self.telegram_send_event_handler(live_data_start_msg)
            self.telegram_lock.release()

        # set current match_day
        self.current_match_day = match_day

        # update linedup comunio players in database before sending livedata
        self.update_linedup_squad()

        def update_livedata(send=False):

            # get all comunio players of interest for sofascore rating
            players_of_interest_for_match = self.set_comunio_players_of_interest_for_match(home_team=home_team, away_team=away_team)

            # get match lineup from match id
            match_lineup = self.bundesliga.lineup_from_match_id(match_id=match_id)

            # create livedata with mapping of comunio players and sofascore lineup players
            self.logger.info("Map livedata for match day {}: {} vs. {}".format(match_day, home_team, away_team))
            livedata = self.map_players_of_interest_with_match_lineup(players_of_interest=players_of_interest_for_match,
                                                                      match_lineup=match_lineup)

            # calculate the points for current match day
            self.logger.info("Calculate points for match day {}: {} vs. {}".format(match_day, home_team, away_team))
            self.calculate_points_per_match(livedata=livedata, match_id=match_id, match_day=match_day)

            if self.is_notify and send:
                # prepare the telegram message
                self.logger.info("Prepare telegram message for match day {}: {} vs. {}".format(match_day, home_team, away_team))
                livedata_msg = self.prepare_telegram_message(livedata=livedata, home_team=home_team, away_team=away_team,
                                                             match_day=match_day, match_id=match_id)

                self.telegram_lock.acquire()
                self.telegram_send_event_handler(text=livedata_msg)
                self.telegram_lock.release()
                self.msg_rate_timer = 0

        # collect livedata as long as match is not finished
        #while self.running:
        while not self.bundesliga.is_finished(matchid=match_id):
            if self.msg_rate_timer > self.msg_rate:
                update_livedata(send=True)
            else:
                update_livedata(send=False)
            sleep(480)  # update data every 8 minutes
            self.msg_rate_timer += 480

        # after match is finished send msg
        live_data_end_msg = "Finished fetching live data from match *{}* vs *{}*".format(home_team, away_team)
        self.logger.info(live_data_end_msg)

        if self.is_notify:
            # send finish msg
            self.telegram_lock.acquire()
            self.telegram_send_event_handler(text=live_data_end_msg)
            self.telegram_lock.release()

        # update livedata for the last time
        if self.bundesliga.is_finished(matchid=match_id):
            sleep(600)  # sleep 10 minutes and update last time
            self.logger.info("Match {} vs {} finished, updating live data the last time after 10 min".format(home_team, away_team))
            update_livedata(send=True)

        # set linedup squad to false
        LiveData.is_squad_updated = False

    def update_linedup_squad(self):
        """ update linedup squad to fetch livedata only from linedup players

        """
        if not LiveData.is_squad_updated:
            if self.update_squad_event_handler:
                LiveData.is_squad_updated = True
                self.update_squad_event_handler()
            else:
                self.logger.error("No update_squad_event_handler registered!")
        else:
            self.logger.error("Squad already updated in LiveData class")

    def set_comunio_players_of_interest_for_match(self, home_team, away_team):
        """ sets all comunio players of interest for current match

        :return: list with all comunio players of interest
        [{'user': '******', 'squad': [('Jorge Meré', '1. FC Köln'), ('Bornauw', '1. FC Köln')]}, ...]
        """
        # complete player list of interest for rest query to sofascore
        all_players_of_interest_for_rating_query = list()

        # iterate over all comunio users
        for user in self.comunio_users:
            user_id = user[0]
            user_name = user[1]

            # get current squad (player,club) with userid from database
            squad = self.dbfetcher.all(sql=self.squad_sql, data=(user_id,))

            if len(squad) < 11:
                self.logger.error("Length of linedup comunio squad from {} is less as 11".format(user_name))

            # player list of interest for one comunio user
            player_list_per_user = list()

            # check if comunio player in home or away team
            for player in squad:
                team = player[2]
                if (team == home_team) or (team == away_team):
                    player_list_per_user.append(player)
                else:
                    hometeam_ratio = SequenceMatcher(None, team, home_team).ratio()
                    awayteam_ratio = SequenceMatcher(None, team, away_team).ratio()
                    if (hometeam_ratio > 0.6) or (awayteam_ratio > 0.6):
                        player_list_per_user.append(player)

            user_query = dict()
            user_query['user'] = user_name
            user_query['userid'] = user_id
            user_query['squad'] = player_list_per_user
            all_players_of_interest_for_rating_query.append(user_query)

        return all_players_of_interest_for_rating_query

    def map_players_of_interest_with_match_lineup(self, players_of_interest, match_lineup):
        """ maps player of interest with match line up and creates a new data structure for livedata

        :param players_of_interest: players of interest
        :param match_lineup: match lineup

        :return: list with live data
        [{'user': '******', 'userid': 13065521, 'squad': [{'name': 'Jorge Mere', 'rating': '7.6', 'position': 'defender', 'points': 6, 'incidents': [{'type': 'goal', 'class': 'regulargoal', 'player': 'Jorge Mere'}]}]}, ...]
        """

        # data with all comunio user and related players
        livedata = list()
        #print(match_lineup)
        # iterate over all comunio users
        for comuniouser in players_of_interest:
            user_name = comuniouser['user']
            user_id = comuniouser['userid']
            comuniosquad = comuniouser['squad']

            # dict with comunio user and related players for livedata
            user_squad_dict = dict()
            user_squad_dict['user'] = user_name
            user_squad_dict['userid'] = user_id
            user_squad_dict['squad'] = list()

            # iterate over squad of comunio user
            for comunioplayerdata in comuniosquad:
                comunioplayername = comunioplayerdata[0]
                comunioplayerposition = comunioplayerdata[1]
                comunioplayername_forename, comunioplayername_surename = self.seperate_playername(playername=comunioplayername)

                # iterate over all homeplayer of home team
                for homeplayer in match_lineup['homeTeam']:
                    homeplayer_name = homeplayer['player_name']
                    homeplayer_forename, homeplayer_surename = self.seperate_playername(playername=homeplayer_name)

                    #print("compare {} with {}".format(comunioplayername_surename, homeplayer_surename))

                    # compare comunio player name with sofascore player name
                    if ((comunioplayername_surename == homeplayer_surename) or
                            (SequenceMatcher(None, comunioplayername_surename, homeplayer_surename,).ratio() > 0.74)):
                        if comunioplayername_forename:
                            if comunioplayername_forename == homeplayer_forename[:len(comunioplayername_forename)]:
                                user_squad_dict['squad'].append(self.get_player_data(playername=homeplayer_name,
                                                                                     playerrating=homeplayer['player_rating'],
                                                                                     playerposition=comunioplayerposition,
                                                                                     incidents=match_lineup['homeTeamIncidents']))
                                break
                        else:
                            user_squad_dict['squad'].append(self.get_player_data(playername=homeplayer_name,
                                                                                 playerrating=homeplayer['player_rating'],
                                                                                 playerposition=comunioplayerposition,
                                                                                 incidents=match_lineup['homeTeamIncidents']))
                            break

                # iterate over all awayplayer of away team
                for awayplayer in match_lineup['awayTeam']:
                    awayplayer_name = awayplayer['player_name']
                    awayplayer_forename, awayplayer_surename = self.seperate_playername(playername=awayplayer_name)

                    #print("compare {} with {}".format(comunioplayername_surename, awayplayer_surename))

                    # compare comunio player name with sofascore player name
                    if ((comunioplayername_surename == awayplayer_surename) or
                            (SequenceMatcher(None, comunioplayername_surename, awayplayer_surename).ratio() > 0.77)):
                        if comunioplayername_forename:
                            if (comunioplayername_forename == awayplayer_forename[:len(comunioplayername_forename)]):
                                user_squad_dict['squad'].append(self.get_player_data(playername=awayplayer_name,
                                                                                     playerrating=awayplayer['player_rating'],
                                                                                     playerposition=comunioplayerposition,
                                                                                     incidents=match_lineup['awayTeamIncidents']))
                                break
                        else:
                            user_squad_dict['squad'].append(self.get_player_data(playername=awayplayer_name,
                                                                                 playerrating=awayplayer['player_rating'],
                                                                                 playerposition=comunioplayerposition,
                                                                                 incidents=match_lineup['awayTeamIncidents']))
                            break

            # add user data to list
            livedata.append(user_squad_dict)
        #print(livedata)
        return livedata

    def get_player_data(self, playername, playerrating, playerposition, incidents):
        """ get player data dict for livedata

        :param playername: player name
        :param playerrating: player rating
        :param playerposition: player position

        :return: dict of player data
        """
        player_data = dict()

        player_data['name'] = playername # from sofascore
        player_data['rating'] = playerrating
        if playerrating == "–":
            player_data['points'] = playerrating
        else:
            player_data['points'] = self.pointcalculator.get_points_from_rating(rating=float(playerrating))
        player_data['position'] = playerposition

        # check active incidents
        incidents_list = list()
        for incident in incidents:
            # check if given player has an active incident
            if incident['player'] == playername:
                # TODO remove player name incident.pop('player')
                incidents_list.append(incident)
        player_data['incidents'] = incidents_list

        return player_data

    def seperate_playername(self, playername):
        """ seperates the playername into forename and surename

        :return: forename and surename of player
        """
        playername_list = playername.split()

        if len(playername_list) == 0:
            playername_forename = ''
            playername_surename = ''
        elif len(playername_list) == 1:
            playername_forename = ''
            playername_surename = playername_list[0]
        elif len(playername_list) == 2:
            playername_forename = playername_list[0].replace('.', '')
            playername_surename = playername_list[1]
        elif len(playername_list) == 3:
            playername_forename = playername_list[0]
            playername_surename = playername_list[2]
        else:
            playername_forename = ''
            playername_surename = ''

        # remove accents
        nfkd_form = unicodedata.normalize('NFKD', playername_surename)
        playername_surename_accents = u"".join([c for c in nfkd_form if not unicodedata.name(c).endswith('ACCENT')])

        return playername_forename, playername_surename_accents

    def prepare_telegram_message(self, livedata, home_team, away_team, match_day, match_id):
        """ prepares the livedata for a new telegram message

        :param livedata: livedata data structure

        :return: telegram message
        """

        telegram_str = ""
        match_str = "Points rating for *{}* vs. *{}* \n\n".format(home_team, away_team)
        telegram_str += match_str

        for user in livedata:
            username = user['user']
            userid = user['userid']
            squad = user['squad']

            telegram_str += "\n*{}*:\n".format(username)
            if len(squad) == 0:
                telegram_str += "no player in lineup!\n"
            else:
                points_data = self.query_rating_goal_off_points(userid=userid, match_day=match_day, match_id=match_id)

                points_rating = points_data[0][0]
                points_goal = points_data[0][1]
                points_off = points_data[0][2]
                points = points_rating + points_goal + points_off
                for player in squad:
                    player_str = ''.join("{} (*{}*)=>*{}*\n".format(player['name'], player['rating'], player['points']))
                    telegram_str += player_str
                rating_str = "*P: {} + G: {} + O: {} => {}*\n".format(points_rating, points_goal, points_off, points)
                telegram_str += rating_str

        return telegram_str

    def calculate_points_per_match(self, livedata, match_id, match_day):
        """ calculates the points for each user with the linedup players

        :param livedata: live data with player points
        :param match_id: match id
        :param match_day: match day

        """
        # points for rating, goals (regulargoal, penalty) and offs (YellowRed, Red)
        for user in livedata:
            userid = user['userid']
            squad = user['squad']
            points_rating = 0
            points_goals = 0
            points_offs = 0
            for player in squad:
                for incident in player['incidents']:
                    # goal points regular
                    if (incident['type'] == 'goal') and (incident['class'] == 'regulargoal'):
                        points = self.pointcalculator.get_points_for_goal(position=player['position'])
                        if points is not None:
                            points_goals += points
                    # goal points penalty
                    elif (incident['type'] == 'goal') and (incident['class'] == 'penalty'):
                        points_goals += self.pointcalculator.get_penalty()
                    # yellow red off points
                    elif (incident['type'] == 'card') and (incident['class'] == 'YellowRed'):
                        points_offs += self.pointcalculator.get_points_for_offs(off_type='yellow_red')
                    # red off points
                    elif (incident['type'] == 'card') and (incident['class'] == 'Red'):
                        points_offs += self.pointcalculator.get_points_for_offs(off_type='red')
                # rating points
                if player['points'] != '–':
                    points_rating += player['points']

            self.update_points_in_database(userid=userid, match_id=match_id, match_day=match_day,
                                           points_rating=points_rating, points_goal=points_goals, points_off=points_offs)

    def points_summery(self):
        """ sums up the current points for each comunio player

        :return: dict with sorted players and points
        """

        sum_points = dict()

        for user in self.comunio_users:
            userid = user[0]
            username = user[1]
            points_data = self.query_rating_goal_off_points(userid=userid, match_day=self.current_match_day)
            # iterate over 9 matches
            points_all = 0
            for match in points_data:
                # check if not all elements are none
                if all(el is not None for el in match):
                    points_rating = match[0]
                    points_goal = match[1]
                    points_offs = match[2]
                    points_match = points_rating + points_goal + points_offs
                    points_all += points_match
                else:
                    #self.logger.error("Invalid None points: {}".format(match))
                    pass

            sum_points[username] = points_all

        # sort dict by key
        sum_points_sorted = {k: v for k, v in sorted(sum_points.items(), key=lambda item: item[1], reverse=True)}

        return self.current_match_day, sum_points_sorted

    def set_msg_rate(self, rate):
        """ set the msg notification rate

        :param rate: rate
        """
        try:
            self.msg_rate = int(rate) * 60
        except ValueError as ex:
            self.logger.error(ex)

    def set_notify_flag(self, notify):
        """ sets the notify flag

        :param notify: notify flag
        """
        self.is_notify = notify

    def get_linedup_squad(self):
        """ get the linedup squad

        :return: linedup squad
        """
        pass
Exemplo n.º 7
0
    def __init__(self, name, comunio_user, comunio_pass, token, chatid,
                 season_date, api_key, **dbparams):
        self.logger = logging.getLogger('ComunioScore')
        self.logger.info('Create class ComunioScore')

        self.name = name
        self.comunio_user = comunio_user
        self.comunio_pass = comunio_pass
        self.token = token
        self.chatid = chatid
        self.season_date = season_date
        self.api_key = api_key

        # create the APIHandler instance
        self.api = APIHandler()

        # init SofaScore scraper client and Bundesliga season data
        SofaScore.init_scraper(api_key=self.api_key)
        BundesligaScore().init_season_data(season_date=self.season_date)

        # router instance for specific endpoints
        self.router = Router(name=self.name)
        self.router.add_endpoint('/',
                                 'index',
                                 method="GET",
                                 handler=self.api.index)

        # create ComunioScoreTelegram instance
        self.telegram = ComunioScoreTelegram(token=self.token,
                                             chat_id=self.chatid)

        # create ComunioDB instance
        self.comuniodb = ComunioDB(comunio_user=self.comunio_user,
                                   comunio_pass=self.comunio_pass,
                                   **dbparams)

        # create LiveData instance
        self.livedata = LiveData(**dbparams)
        self.livedata.register_update_squad_event_handler(
            func=self.comuniodb.update_linedup_squad)
        self.livedata.register_telegram_send_event_handler(
            func=self.telegram.new_msg)

        # register summery points, rate and notify event handler
        self.telegram.register_points_summery_event_handler(
            func=self.livedata.points_summery)
        self.telegram.register_rate_event_handler(
            func=self.livedata.set_msg_rate)
        self.telegram.register_notify_event_handler(
            func=self.livedata.set_notify_flag)

        # create MatchScheduler instance
        self.matchscheduler = MatchScheduler()
        self.matchscheduler.register_livedata_event_handler(
            func=self.livedata.fetch)

        # create SofascoreDB instance
        self.sofascoredb = SofascoreDB(**dbparams)
        self.sofascoredb.register_matchscheduler_event_handler(
            func=self.matchscheduler.new_event)
        self.sofascoredb.register_comunio_user_data(
            func=self.comuniodb.get_comunio_user_data)