From afa12da0d8addb325b4eb74777b2b52f91b519f1 Mon Sep 17 00:00:00 2001 From: Michael Pilosov Date: Sat, 26 Nov 2022 20:41:24 -0700 Subject: [PATCH] redefine Bet class, now allows adding of bets --- .gitignore | 160 ++++++++++++++++++++++++++ app.py | 5 +- pyroulette/__init__.py | 1 + roulette.py => pyroulette/roulette.py | 74 ++++++++---- setup.py | 22 ++++ strategy.py | 6 + 6 files changed, 244 insertions(+), 24 deletions(-) create mode 100644 .gitignore create mode 100644 pyroulette/__init__.py rename roulette.py => pyroulette/roulette.py (92%) create mode 100644 setup.py create mode 100644 strategy.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..68bc17f --- /dev/null +++ b/.gitignore @@ -0,0 +1,160 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/app.py b/app.py index c67d289..a1c9df7 100644 --- a/app.py +++ b/app.py @@ -1,8 +1,9 @@ from random import choice, randint, seed -from roulette import ( +from pyroulette import ( FEASIBLE_MOVES, Placement, + Bet, Player, Strategy, expected, @@ -15,7 +16,7 @@ from roulette import ( if __name__ == "__main__": - bet = init_bet() + bet = Bet() # bet = place_bet(bet, 21, 20) print(bet[21]) # bet = interpret_bet("red", 36, bet) diff --git a/pyroulette/__init__.py b/pyroulette/__init__.py new file mode 100644 index 0000000..eea53bb --- /dev/null +++ b/pyroulette/__init__.py @@ -0,0 +1 @@ +from .roulette import * # noqa: F401, F403 \ No newline at end of file diff --git a/roulette.py b/pyroulette/roulette.py similarity index 92% rename from roulette.py rename to pyroulette/roulette.py index f67d700..a7fa3f3 100644 --- a/roulette.py +++ b/pyroulette/roulette.py @@ -6,7 +6,50 @@ from random import choice, randint from statistics import mean, stdev from typing import Dict, List, Optional -Bet = Dict[int, float] + + +# define the class Bet which inherits from Dict[int, float] and define it's __add__ method as calling combine_bets +# Bet = Dict[int, float] + + +def init_bet() -> Bet: + """ + Initializes a bet with all individual placements set to 0. + + Returns + ------- + Bet + A dictionary representing the bet. + """ + D = {i: 0 for i in range(-1, 37)} + return D + + +@dataclass +class Bet: + """A class for representing a bet.""" + spread: Dict[int, float] = field(default_factory=init_bet) + + def __dict__(self) -> Dict[int, float]: + """Return the bet as a dictionary.""" + return self.spread + + def __add__(self, other: Bet) -> Bet: + """Combine two bets.""" + return combine_bets(self.spread, other.spread) + + def __setitem__(self, __name: int, __value: float) -> None: + """Set the value of a placement.""" + self.spread[__name] = __value + + def __getitem__(self, __name: int) -> float: + """Get the value of a placement.""" + return self.spread[__name] + + def copy(self) -> Bet: + """Return a copy of the bet.""" + return Bet(self.spread.copy()) + SINGLE_BETS = {str(i) for i in range(-1, 37)} @@ -38,7 +81,7 @@ ALIASES = { CHIP_VALUES = {0.25, 0.5, 1, 5, 10, 25, 50, 100} -def expected(bet) -> float: +def expected(bet: Bet) -> float: """ Returns the expected value of a bet. @@ -52,7 +95,7 @@ def expected(bet) -> float: float The expected value of the bet. """ - bets = list(bet.values()) + bets = list(bet.spread.values()) cond_bets = filter(lambda x: x > 0, bets) amt = sum(bets) payout = amt * 36 / 38 @@ -70,20 +113,7 @@ def expected(bet) -> float: # will use a function to distribute / interpret the bets, but it seems like we only need to track the numbers on the wheel. -def init_bet() -> Bet: - """ - Initializes a bet with all individual placements set to 0. - - Returns - ------- - Bet - A dictionary representing the bet. - """ - D = {i: 0 for i in range(-1, 37)} - return D - - -def place_bet(bet: Bet, on: int, amount: float): +def place_bet(bet: Bet, on: int, amount: float) -> Bet: """ Places a bet on a number. @@ -236,7 +266,7 @@ class Placement: """ return self.num * self.amt - def place_bet(self, bet=None) -> Bet: + def bet(self, bet=None) -> Bet: """ Places a bet on the wheel based on the bet type. """ @@ -340,7 +370,7 @@ class Strategy: def get_bet(self): return self.place_bets(self.placements) - + def get_placements(self): return self.placements @@ -360,12 +390,12 @@ class Strategy: A dictionary representing the bet. """ return reduce( - lambda bet, placement: combine_bets(bet, placement.place_bet()), placements, {} + lambda bet, placement: combine_bets(bet, placement.bet()), + placements, + {}, ) - - @dataclass class Player: """ diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..bbe78fe --- /dev/null +++ b/setup.py @@ -0,0 +1,22 @@ +from setuptools import setup +from pathlib import Path + +# Globals and constants variables. +BASEDIR = Path(__file__).parent.resolve() + +with open(BASEDIR.joinpath("README.md"), "r") as fp: + LONG_DESCRIPTION = fp.read() + +setup( + name="pyroulette", + version="0.0.1rc0", + description="A package for exploring roulette strategies.", + long_description=LONG_DESCRIPTION, + author="Mathematical Michael", + author_email="consistentbayes@gmail.com", + url="https://github.com/mathematicalmichael/pyroulette", + packages=["pyroulette"], + license="MIT", + install_requires=["dataclasses; python_version<'3.7'"], + python_requires=">=3.6, <4.0", +) diff --git a/strategy.py b/strategy.py new file mode 100644 index 0000000..14abc8b --- /dev/null +++ b/strategy.py @@ -0,0 +1,6 @@ +from pyroulette.roulette import Placement, Strategy, Bet + +if __name__ == "__main__": + + print(Bet({0: 1}) + Bet()) + print(Strategy(placements=[Placement(1, 10, "red"), Placement(2, 10, "black")]).get_bet()) \ No newline at end of file