示例#1
0
    def test_insert(self):
        # Disable Foreign Keys checks for this test
        TestRating.db.disableForeignKeys()

        with TestRating.db.transaction() as t:
            TestRating.db.upsert(
                Rating('rating match_date TD INS', 'league mnemonic TD INS',
                       'team name TD INS', 'team name TD INS', 100, 100))
            objs = TestRating.db.select(Rating())

            self.assertEqual(len(objs), 3)

            d = eval(
                "{'match_date': 'rating match_date TD INS', 'league': 'league mnemonic TD INS', 'home_team': 'team name TD INS', 'away_team': 'team name TD INS', 'algo_id': 100}"
            )
            for k, v in d.items():
                self.assertEqual(objs[2].__getattribute__('get' + k.title())(),
                                 v)

            d = eval("{'mark': 100}")
            for k, v in d.items():
                self.assertEqual(objs[2].__getattribute__('get' + k.title())(),
                                 v)

            # force a rollback
            t.fail()
示例#2
0
    def test_update(self):
        # Disable Foreign Keys checks for this test
        TestRating.db.disableForeignKeys()

        with TestRating.db.transaction() as t:
            TestRating.db.upsert(
                Rating('rating match_date TD', 'league mnemonic TD',
                       'team name TD', 'team name TD', 98, 100))
            objs = TestRating.db.select(
                Rating('rating match_date TD', 'league mnemonic TD',
                       'team name TD', 'team name TD', 98))

            self.assertEqual(len(objs), 1)
            self.assertEqual(objs[0].getMatch_Date(), 'rating match_date TD')
            self.assertEqual(objs[0].getLeague(), 'league mnemonic TD')
            self.assertEqual(objs[0].getHome_Team(), 'team name TD')
            self.assertEqual(objs[0].getAway_Team(), 'team name TD')
            self.assertEqual(objs[0].getAlgo_Id(), 98)

            d = eval("{'mark': 100}")
            for k, v in d.items():
                self.assertEqual(objs[0].__getattribute__('get' + k.title())(),
                                 v)

            # force a rollback
            t.fail()

        with TestRating.db.transaction() as t:
            rating = TestRating.db.select(
                Rating('rating match_date TD', 'league mnemonic TD',
                       'team name TD', 'team name TD', 98))[0]
            for k, v in d.items():
                rating.__getattribute__('set' + k.title())(v)

            TestRating.db.upsert(rating)

            objs = TestRating.db.select(
                Rating('rating match_date TD', 'league mnemonic TD',
                       'team name TD', 'team name TD', 98))
            self.assertEqual(len(objs), 1)
            self.assertEqual(objs[0].getMatch_Date(), 'rating match_date TD')
            self.assertEqual(objs[0].getLeague(), 'league mnemonic TD')
            self.assertEqual(objs[0].getHome_Team(), 'team name TD')
            self.assertEqual(objs[0].getAway_Team(), 'team name TD')
            self.assertEqual(objs[0].getAlgo_Id(), 98)

            for k, v in d.items():
                self.assertEqual(objs[0].__getattribute__('get' + k.title())(),
                                 v)

            # force a rollback
            t.fail()
示例#3
0
    def test_delete(self):
        # Disable Foreign Keys checks for this test
        TestRating.db.disableForeignKeys()

        with TestRating.db.transaction() as t:
            TestRating.db.delete(
                Rating('rating match_date TD', 'league mnemonic TD',
                       'team name TD', 'team name TD', 98))

            objs = TestRating.db.select(Rating())
            self.assertEqual(len(objs), 1)

            # force a rollback
            t.fail()
示例#4
0
 def test_repr(self):
     obj = Rating('rating match_date TD', 'league mnemonic TD',
                  'team name TD', 'team name TD', 98, 98)
     self.assertEqual(
         str(obj),
         "rating : Keys {'match_date': 'rating match_date TD', 'league': 'league mnemonic TD', 'home_team': 'team name TD', 'away_team': 'team name TD', 'algo_id': 98} : Values {'mark': 98}"
     )
示例#5
0
    def test_create(self):
        obj = Rating.create(('rating match_date TD', 'league mnemonic TD',
                             'team name TD', 'team name TD', 98, 98))

        self.assertEqual(obj.getMatch_Date(), 'rating match_date TD')
        self.assertEqual(obj.getLeague(), 'league mnemonic TD')
        self.assertEqual(obj.getHome_Team(), 'team name TD')
        self.assertEqual(obj.getAway_Team(), 'team name TD')
        self.assertEqual(obj.getAlgo_Id(), 98)

        self.assertEqual(obj.getMark(), 98)
示例#6
0
    def test_select(self):
        objs = TestRating.db.select(Rating())
        self.assertEqual(len(objs), 2)
        self.assertEqual(objs[0].getMatch_Date(), 'rating match_date TD')
        self.assertEqual(objs[0].getLeague(), 'league mnemonic TD')
        self.assertEqual(objs[0].getHome_Team(), 'team name TD')
        self.assertEqual(objs[0].getAway_Team(), 'team name TD')
        self.assertEqual(objs[0].getAlgo_Id(), 98)

        self.assertEqual(objs[0].getMark(), 98)

        self.assertEqual(objs[1].getMatch_Date(), 'rating match_date TD2')
        self.assertEqual(objs[1].getLeague(), 'league mnemonic TD2')
        self.assertEqual(objs[1].getHome_Team(), 'team name TD2')
        self.assertEqual(objs[1].getAway_Team(), 'team name TD2')
        self.assertEqual(objs[1].getAlgo_Id(), 99)

        self.assertEqual(objs[1].getMark(), 99)

        objs = TestRating.db.select(
            Rating('rating match_date TD', 'league mnemonic TD',
                   'team name TD', 'team name TD', 98))
        self.assertEqual(len(objs), 1)
        self.assertEqual(objs[0].getMatch_Date(), 'rating match_date TD')
        self.assertEqual(objs[0].getLeague(), 'league mnemonic TD')
        self.assertEqual(objs[0].getHome_Team(), 'team name TD')
        self.assertEqual(objs[0].getAway_Team(), 'team name TD')
        self.assertEqual(objs[0].getAlgo_Id(), 98)

        self.assertEqual(objs[0].getMark(), 98)

        objs = TestRating.db.select(Rating.createAdhoc({'mark': 98}))
        self.assertEqual(len(objs), 1)
        self.assertEqual(objs[0].getMatch_Date(), 'rating match_date TD')
        self.assertEqual(objs[0].getLeague(), 'league mnemonic TD')
        self.assertEqual(objs[0].getHome_Team(), 'team name TD')
        self.assertEqual(objs[0].getAway_Team(), 'team name TD')
        self.assertEqual(objs[0].getAlgo_Id(), 98)

        self.assertEqual(objs[0].getMark(), 98)
示例#7
0
 def getStatisticsForResult(result, setfn, getfn):
     keys = {'league': league.getMnemonic(), 'result': result}
     order = ['>date']
     for m in db.select(Match.createAdhoc(keys, order)):
         rating = db.select(
             Rating(m.getDate(), m.getLeague(), m.getHome_Team(),
                    m.getAway_Team(), algoId))
         if rating:
             mark = rating[0].getMark()
             s = stats.get(mark, Statistics(str( \
                     datetime.now().date()), algoId, \
                     league.getMnemonic(), mark, 0, 0, 0, 0))
             s.setMark_Freq(s.getMark_Freq() + 1)
             setfn(s, getfn(s) + 1)
             stats[mark] = s
示例#8
0
    def test_analyseMatches(self):
        analyseMatches(self.mock_Logger, 1, 'league mnemonic TD')

        calls = (
                    call.info('Analysing matches for league <league ' \
                            'mnemonic TD> with algo <1>'),
                    call.debug('Opening database: ./db/test.db'),
                    call.debug('Last rating for match 99'),
                    call.debug('7 matches found to mark'),
                )
        self.mock_Logger.assert_has_calls(calls)

        with Database(self.dbName, SQLite3Impl()) as db:
            stats = db.select(Statistics())
            ratings = db.select(Rating())

            self.assertEquals(len(stats), 2)
            self.assertEquals(stats[0].getGeneration_Date(), \
                    str(datetime.now().date()))
            self.assertEquals(stats[0].getAlgo_Id(), 1)
            self.assertEquals(stats[0].getLeague(), 'league mnemonic TD')
            self.assertEquals(stats[0].getMark(), -3)
            self.assertEquals(stats[0].getMark_Freq(), 50.0)
            self.assertEquals(stats[0].getHome_Freq(), 100.0)
            self.assertEquals(stats[0].getAway_Freq(), 0.0)
            self.assertEquals(stats[0].getDraw_Freq(), 0.0)

            self.assertEquals(stats[1].getGeneration_Date(), \
                    str(datetime.now().date()))
            self.assertEquals(stats[1].getAlgo_Id(), 1)
            self.assertEquals(stats[1].getLeague(), 'league mnemonic TD')
            self.assertEquals(stats[1].getMark(), -2)
            self.assertEquals(stats[1].getMark_Freq(), 50.0)
            self.assertEquals(stats[1].getHome_Freq(), 100.0)
            self.assertEquals(stats[1].getAway_Freq(), 0.0)
            self.assertEquals(stats[1].getDraw_Freq(), 0.0)

            self.assertEquals(len(ratings), 2)
            self.assertEquals(ratings[0].getMatch_Oid(), 6)
            self.assertEquals(ratings[0].getAlgo_Id(), 1)
            self.assertEquals(ratings[0].getMark(), -3)

            self.assertEquals(ratings[1].getMatch_Oid(), 7)
            self.assertEquals(ratings[1].getAlgo_Id(), 1)
            self.assertEquals(ratings[1].getMark(), -2)
示例#9
0
def presentFixtures(log:Logger, algoId:int, league:str=None, show:bool=False, \
        mail:bool=False, backtest:bool=False, season:str=None):
    '''
    Present the latest set of fixtures with all the appropriate ratings.

    :param log: a logging object
    :param league: the subject league, None signifies all available leagues 
    :param show: displays any tables as HTML when True
    :param mail: send as email
    :param backtest: run in backtest mode
    :param season: season to run backtest for
    '''
    log.info('Presenting fixtures for algo <{}>, league <{}> and backtest ' \
            '<{}> for season <{}>'.format(algoId, league if league else 'ALL', \
            backtest, season))

    config = getSweeperConfig()
    dbName = config['dbName']
    log.debug('Opening database: {}'.format(dbName))

    with Database(dbName, SQLite3Impl()) as db, db.transaction() as t:
        date = (datetime.today() - timedelta(days=1)).strftime('%Y-%m-%d')
        try:
            algo = db.select(Algo(algoId))[0]
            algo = AlgoFactory.create(algo.getName())
        except Exception as e:
            log.critical('No algo matching the provided id exists')
            log.critical('Because...%s' % e)
            sys.exit(2)

        if backtest:
            # In backtest mode use the inverse algoId to retrieve config,
            # ratings and stats and process all matches irrespective of
            # existing results
            algoId = -algoId
            if season:
                try:
                    season = db.select(Season(season))[0]
                except Exception as e:
                    log.critical( \
                            'No season matching the provided season exists')
                    sys.exit(3)
            else:
                log.critical('Must specify season with backtest')
                sys.exit(4)
            keys = {'>date' : season.getL_Bnd_Date(), \
                    '<date' : season.getU_Bnd_Date()}
        else:
            keys = {'>date': date, 'result': ''}

        try:
            if league: keys.update({'league': league})
            order = ['<league', '<date']
            fixtures = db.select(Match.createAdhoc(keys, order))
            if not fixtures: raise Exception('No fixtures')
        except Exception as e:
            log.critical("Couldn't find fixtures for league and date " \
                    "provided, run sourcedata?")
            log.critical('Because...{}'.format(e))
            sys.exit(5)

        try:
            if 'result' in keys: del keys['result']
            if '<date' in keys: keys.update({'<match_date': keys.pop('<date')})
            del keys['>date']
            dt = datetime.strptime(min(f.getDate() for f in fixtures), \
                    '%Y-%m-%d') - timedelta(days=1)
            keys.update({'>match_date': dt.strftime('%Y-%m-%d')})
            keys.update({'algo_id': algoId})
            order = ['<league', '<match_date']
            ratings = db.select(Rating.createAdhoc(keys, order))
            log.debug('Num fixtures {}, ratings {}'.format(len(fixtures), \
                    len(ratings)))
            if len(fixtures) != len(ratings):
                raise Exception('Mismatched ratings')
        except Exception as e:
            log.critical("Couldn't find algo ratings for all fixtures, " \
                    "run analysematches?")
            log.critical('Because...{}'.format(e))
            sys.exit(6)

        try:
            del keys['>match_date']
            if '<match_date' in keys: del keys['<match_date']
            keys.update({'>generation_date': date})
            order = ['>generation_date']
            stats = db.select(Statistics.createAdhoc(keys, order))
            if not stats: raise Exception('No statistics')
            lastGenDate = stats[0].getGeneration_Date()
            stats = [s for s in stats if s.getGeneration_Date() == lastGenDate]
        except Exception as e:
            log.critical("Couldn't find algo statistics for league and date, " \
                    "run genstats?")
            log.critical('Because...{}'.format(e))
            sys.exit(7)

        def statsSummary(s: Statistics):
            if s.getMark() == 99:
                return 0, 0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0.0
            markF = s.getMark_Freq()
            homeF = s.getHome_Freq()
            homeP = (homeF / markF) * 100.0 if markF else 0.0
            homeO = 100.0 / homeP if homeP else 99.99
            drawF = s.getDraw_Freq()
            drawP = (drawF / markF) * 100.0 if markF else 0.0
            drawO = 100.0 / drawP if drawP else 99.99
            awayF = s.getAway_Freq()
            awayP = (awayF / markF) * 100.0 if markF else 0.0
            awayO = 100.0 / awayP if awayP else 99.99
            return markF, homeF, homeP, homeO, drawF, drawP, drawO, awayF, \
                    awayP, awayO

        for r in itertools.filterfalse(lambda r : r.getMark() in \
                [s.getMark() for s in stats if r.getLeague() == s.getLeague()],\
                ratings):
            stats.append(Statistics(r.getMatch_Date(), r.getAlgo_Id(), \
                    r.getLeague(), r.getMark(), 0, 0, 0, 0))
        analytics = map(lambda r : [(r, statsSummary(s)) for s in stats \
                if r.getMark() == s.getMark() \
                and r.getLeague() == s.getLeague()], ratings)
        presentation = zip(fixtures, analytics)

        tables = {}
        mailText = 'Visit the website for more details - http://www.sweeperfootball.com<br/><br/>'
        for i, (league, group) in enumerate(itertools.groupby(presentation, \
                lambda x : x[0].getLeague())):
            try:
                leagueDesc = db.select(League(league))[0].getDesc()
            except Exception as e:
                log.critical("Couldn't find league")
                log.critical('Because..{}'.format(e))
                sys.exit(5)
            try:
                keys = {'league': league, 'algo_id': algoId}
                order = ['>config_date']
                algoCfg = db.select(Algo_Config.createAdhoc(keys, order))[0]
            except Exception as e:
                log.critical("Couldn't find algo config for league")
                log.critical('Because...{}'.format(e))
                sys.exit(6)

            presGrp = list(group)
            headers = ['Date', 'Match', 'Mark', 'M#', \
                    'H#', 'H%', 'HO', 'D#', 'D%', 'DO', 'A#', 'A%', 'AO']
            schema = ['{:<12}', '{:<40}', '{:>4}', '{:>4}', \
                    '{:>4}', '{:>5.2f}', '{:>5.2f}', '{:>4}', '{:>5.2f}', \
                    '{:>5.2f}', '{:>4}', '{:>5.2f}', '{:>5.2f}']
            t = Table(headers=headers, schema=schema, \
                    title='{} Fixtures'.format(leagueDesc))

            if backtest:
                # if we are backtesting then only return the predictions
                t.append([[f.getDate(), '{} (vs) {}'.format(f.getHome_Team(), \
                        f.getAway_Team()), r.getMark(), *a] \
                        for f, [(r, a)] in presGrp \
                        if r.getMark() > algoCfg.getL_Bnd_Mark() \
                        and r.getMark() < algoCfg.getU_Bnd_Mark()])
                return t

            t.append([[f.getDate(), '{} (vs) {}'.format(f.getHome_Team(), \
                    f.getAway_Team()), r.getMark(), *a] \
                    for f, [(r, a)] in presGrp])
            t.setHighlights([['Match', '{} (vs) {}'.format(f.getHome_Team(), \
                    f.getAway_Team()), False, False] \
                    for f, [(r, a)] in presGrp \
                    if r.getMark() > algoCfg.getL_Bnd_Mark() \
                    and r.getMark() < algoCfg.getU_Bnd_Mark()])
            t.htmlReplacements([['(vs)', '<br/>']])

            try:
                keys = {'>u_bnd_date': date, '<l_bnd_date': date}
                season = db.select(Season.createAdhoc(keys))[0].getName()
            except Exception as e:
                log.critical("Couldn't find season for date")
                log.critical('Because...{}'.format(e))
                sys.exit(6)

            mask = log.getMask()
            log.setMask(mask & ~Logger.INFO)
            leagueTable, formTable = genFormTable(log, league, season, date)
            log.setMask(mask)
            log.info(t)
            log.info(formTable)

            tables[leagueDesc] = (t, leagueTable, formTable)

            if show:
                t.asHTML(show)
                formTable.asHTML(show)

            if mail:
                if not i:
                    mailText += t.asHTML().replace('</body>', '') + '<br/>'
                else:
                    mailText += t.asHTML(fullyFormed=False) + '<br/>'
                mailText += formTable.asHTML(fullyFormed=False) + '<br/>'

        if mail:
            mailText = 'MIME-Version: 1.0\nContent-type: text/html\nSubject: Sweeper Football Predictions\n\n{}</body>'.format(
                mailText)
            #mailText = 'MIME-Version: 1.0\nContent-type: text/html\nSubject: Sweeper Football Predictions - PREDICTIONS AVAILABLE FROM THIS WEEK!\n\n{}</body>'.format(mailText)
            mailCfg = getSweeperConfig('mail.cfg')
            fromAddr = mailCfg['fromAddr']
            subs = db.select(Subscriber.createAdhoc({'include': 1}))
            toAddrs = [s.getEmail() for s in subs]
            server = smtplib.SMTP(mailCfg['svr'], int(mailCfg['port']))
            server.ehlo()
            server.starttls()
            server.ehlo()
            server.login(fromAddr, mailCfg['pwd'])
            server.sendmail(fromAddr, toAddrs, mailText)
            server.quit()
            log.info('email sent to: {!s}'.format(toAddrs))

        return tables
示例#10
0
def analyseMatches(log:Logger, algoId:int, league:str=None, season:str=None, \
        backtest:bool=False):
    '''
    Mark all unmarked matches

    :param log: a logging object
    :param algoId: the algo to apply
    :param league: the league to apply the algo over, None means ALL
    :param season: the season to apply the algo over, None means ALL
    :param backtest: run in backtest mode
    '''
    log.info('Analysing matches for league <{}>, season <{}> with algo <{}> ' \
            'and backtest <{}>'.format(league if league else 'ALL', \
            season if season else 'ALL', algoId, backtest))

    config = getSweeperConfig()
    dbName = config['dbName']
    log.debug('Opening database: {}'.format(dbName))

    with Database(dbName, SQLite3Impl()) as db, db.transaction() as t:
        try:
            algo = db.select(Algo(algoId))[0]
            algo = AlgoFactory.create(algo.getName())
            # In backtest mode use the inverse algoId to retrieve config,
            # ratings and stats
            if backtest: algoId = -algoId
        except:
            log.critical('No algo matching the provided id exists')
            sys.exit(2)
        try:
            if league:
                leagues = db.select(League(league))
            else:
                leagues = db.select(League())
        except:
            log.critical('No league matching the provided mnemonic exists')
            sys.exit(3)
        try:
            if season: season = db.select(Season(season))[0]
        except:
            log.critical('No season matching the provided season exists')
            sys.exit(4)

        keys = {'algo_id': algoId, '<mark': 99}
        ratings = db.select(Rating.createAdhoc(keys))
        ratedMatchKeys = [MatchKeys(r.getMatch_Date(), r.getLeague(), \
                r.getHome_Team(), r.getAway_Team()) for r in ratings]
        log.info('Found {} ratings for algo {}'.format(len(ratedMatchKeys), \
                algoId))

        for league in leagues:
            if season:
                keys = {'league' : league.getMnemonic(), \
                        '>date' : season.getL_Bnd_Date(), \
                        '<date' : season.getU_Bnd_Date()}
            else:
                keys = {'league': league.getMnemonic()}
            order = ['>league', '>date']
            matches = db.select(Match.createAdhoc(keys, order))
            unmarked = list(filter(lambda x : x._keys not in ratedMatchKeys, \
                    matches))
            results = list(filter(lambda x: x.getResult() != '', matches))
            log.info('{} {} matches found unmarked'.format(len(unmarked), \
                    league.getMnemonic()))
            for m in unmarked:
                hTeamMatches = list(filter(lambda x : m.getHome_Team() in \
                        (x.getHome_Team(), x.getAway_Team()) and x.getDate() \
                        < m.getDate(), results))
                aTeamMatches = list(filter(lambda x : m.getAway_Team() in \
                        (x.getHome_Team(), x.getAway_Team()) and x.getDate() \
                        < m.getDate(), results))
                mark = algo.markMatch(m, hTeamMatches, aTeamMatches)
                if mark is not None:
                    db.upsert(Rating(m.getDate(), m.getLeague(), \
                            m.getHome_Team(), m.getAway_Team(), algoId, mark))
示例#11
0
 def test_keys_adhoc(self):
     l = Rating.createAdhoc(None)
     self.assertEqual(l.getTable(), 'rating')
     self.assertTrue(l._keys.getFields() is None)
示例#12
0
 def test_isNullable(self):
     obj = Rating()
     self.assertTrue(True)