Skip to content

Commit

Permalink
Merge pull request #4 from schwalle/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
schwalle authored Oct 21, 2020
2 parents 69daa6c + f57ecd0 commit 9fd86f8
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 258 deletions.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/datetime_test.py → helper/datetime_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pytest
from src import deadline
from helper import deadline
from datetime import datetime
from datetime import timedelta

Expand Down
File renamed without changes.
File renamed without changes.
23 changes: 10 additions & 13 deletions kicktippbb.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@
from docopt import docopt
from robobrowser import RoboBrowser

import src.prediction
from src.deadline import is_before_dealine, timedelta_tostring
from src.match import Match
import predictors.base
from helper.deadline import is_before_dealine, timedelta_tostring
from helper.match import Match

URL_BASE = 'http://www.kicktipp.de'
URL_LOGIN = URL_BASE + '/info/profil/login'
Expand Down Expand Up @@ -177,8 +177,8 @@ def place_bets(browser: RoboBrowser, communities: list, predictor, override=Fals

homebet,roadbet = predictor.predict(match)
print("{0} - betting {1}:{2}".format(match, homebet, roadbet))
submitform[field_hometeam.attrs['name']] = homebet
submitform[field_roadteam.attrs['name']] = roadbet
submitform[field_hometeam.attrs['name']] = str(homebet)
submitform[field_roadteam.attrs['name']] = str(roadbet)
if not dryrun:
browser.submit_form(submitform, submit='submitbutton')
else:
Expand All @@ -201,20 +201,17 @@ def choose_predictor(predictor_param, predictors):
else:
exit('Unknown predictor: {}'.format(predictor_param))
else:
predictor = predictors['SimplePredictor']()
# Just get the first predictor in the dict and instanciate it
predictor = next(iter(predictors.values()))()
print("Using predictor: "+type(predictor).__name__)
return predictor


def get_predictors():
return dict((name, obj) for name, obj in inspect.getmembers(sys.modules['prediction'], predicate=inspect.isclass) if 'predict' in [x for x, y in inspect.getmembers(obj, predicate=inspect.isfunction) if x == 'predict'])


def main(arguments):
browser = RoboBrowser(parser="html.parser")

validate_arguments(arguments)
predictors = get_predictors()
predictors_ = predictors.base.get_predictors()

# Log in to kicktipp and print out the login cookie value
if arguments['--get-login-token']:
Expand All @@ -224,7 +221,7 @@ def main(arguments):

# Just list the predictors at hand and exit
if arguments['--list-predictors']:
[print(key) for key in predictors.keys()]
[print(key) for key in predictors_.keys()]
exit(0)

# Use login token pass by argument or let the caller log in right here
Expand All @@ -244,7 +241,7 @@ def main(arguments):

# Which prediction method is used
predictor_param = arguments['--predictor'] if '--predictor' in arguments else None
predictor = choose_predictor(predictor_param, predictors)
predictor = choose_predictor(predictor_param, predictors_)

# Place bets
place_bets(browser, communities, predictor,
Expand Down
Empty file added predictors/__init__.py
Empty file.
27 changes: 27 additions & 0 deletions predictors/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from helper.match import Match
import pkgutil
import importlib
import os.path

class PredictorBase():
"""
Predictor base class
all actual predictors shall derive from this class and implement the predict method
"""
def predict(self, match: Match):
"""
predict a match by returning the number of goals as tuple (home_goals, road_goals)
"""
raise NotImplementedError

def explore_package():
return [sub_module_name for _, sub_module_name, _ in pkgutil.iter_modules([os.path.dirname(__file__)])]

def get_predictors():
"""
Get all predictors from all modules in this folder
return: dict{name:str, cls:class}
"""
for mod in explore_package():
importlib.import_module('.'+mod, __package__)
return {cls.__name__: cls for cls in PredictorBase.__subclasses__()}
31 changes: 4 additions & 27 deletions src/prediction.py → predictors/calculationpredictor.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,12 @@
"""
This module holds all preditors used by kicktipp bet bot.
A generator is a class that defines a method 'predict' with one argument.
Simple preditor for kicktipp bet bot.
"""
from src.match import Match
from helper.match import Match
from .base import PredictorBase
import random
import math


class SimplePredictor(object):
DOMINATION_THRESHOLD = 6
DRAW_THRESHOLD = 1.2

def predict(self, match: Match):

diff = math.fabs(match.rate_home - match.rate_road)
home_wins = match.rate_home < match.rate_road

if diff < self.DRAW_THRESHOLD:
return (1, 1)

if diff >= self.DOMINATION_THRESHOLD:
result = (3, 1)
elif diff >= self.DOMINATION_THRESHOLD / 2:
result = (2, 1)
else:
result = (1, 0)

return result if home_wins else tuple(reversed(result))


class CalculationPredictor(object):
class CalculationPredictor(PredictorBase):
MAX_GOALS = 5
DOMINATION_THRESHOLD = 9
DRAW_THRESHOLD = 1.3
Expand Down
14 changes: 14 additions & 0 deletions predictors/predictors_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import pytest
from . import base

def test_scanpreditors():
subpackages = base.explore_package()
assert len(subpackages) > 0
pass

def test_instanciatepreditors():
predictors = base.get_predictors()
assert 'SimplePredictor' in predictors.keys()
predictorobj = predictors['SimplePredictor']()
assert issubclass(type(predictorobj), base.PredictorBase)
pass
29 changes: 29 additions & 0 deletions predictors/simplepredictor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
Simple preditor for kicktipp bet bot.
"""
from helper.match import Match
from .base import PredictorBase
import random
import math


class SimplePredictor(PredictorBase):
DOMINATION_THRESHOLD = 6
DRAW_THRESHOLD = 1.2

def predict(self, match: Match):

diff = math.fabs(match.rate_home - match.rate_road)
home_wins = match.rate_home < match.rate_road

if diff < self.DRAW_THRESHOLD:
return (1, 1)

if diff >= self.DOMINATION_THRESHOLD:
result = (3, 1)
elif diff >= self.DOMINATION_THRESHOLD / 2:
result = (2, 1)
else:
result = (1, 0)

return result if home_wins else tuple(reversed(result))
Loading

0 comments on commit 9fd86f8

Please sign in to comment.