linting problems, rename functions
This commit is contained in:
parent
24a197f760
commit
fb66902f59
13
Makefile
13
Makefile
@ -1,8 +1,15 @@
|
||||
build:
|
||||
rm -rf build/ dist/ *.egg-info/
|
||||
build: clean
|
||||
python -m build --sdist --wheel -n
|
||||
|
||||
clean:
|
||||
rm -rf build/ dist/ *.egg-info/ .eggs/ .pytest_cache/ .mypy_cache/ .coverage */__pycache__/ __pycache__/
|
||||
|
||||
publish: build
|
||||
twine upload dist/*
|
||||
|
||||
.PHONY: build publish
|
||||
lint:
|
||||
black .
|
||||
isort .
|
||||
flake8 --max-line-length=88 --extend-ignore=E203,W503 pyroulette/
|
||||
|
||||
.PHONY: build publish clean lint
|
@ -28,13 +28,15 @@ players = generate_players(
|
||||
budget=100,
|
||||
)
|
||||
|
||||
for player in results:
|
||||
print(player)
|
||||
|
||||
results = play_roulette(
|
||||
players=players,
|
||||
number_of_games=1000,
|
||||
)
|
||||
|
||||
for player in results:
|
||||
print(player)
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
18
app.py
18
app.py
@ -1,18 +1,8 @@
|
||||
from random import choice, randint, seed
|
||||
|
||||
from pyroulette import (
|
||||
FEASIBLE_MOVES,
|
||||
Placement,
|
||||
Bet,
|
||||
Player,
|
||||
Strategy,
|
||||
expected,
|
||||
generate_players,
|
||||
init_spread,
|
||||
interpret_bet,
|
||||
place_bet,
|
||||
simulate_games,
|
||||
)
|
||||
from pyroulette import (FEASIBLE_MOVES, Bet, Placement, Player, Strategy,
|
||||
expected, generate_players, init_spread, interpret_bet,
|
||||
place_bet, play_roulette)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@ -108,7 +98,7 @@ if __name__ == "__main__":
|
||||
print("SIMULATING GAMES")
|
||||
# simulate 10 games
|
||||
# seed(59)
|
||||
players = simulate_games(players, num_games=100000)
|
||||
players = play_roulette(players, games=100000)
|
||||
|
||||
for p in sorted(players):
|
||||
print(p, "\n")
|
||||
|
@ -1,14 +1,11 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from dataclasses import dataclass, field
|
||||
from functools import reduce
|
||||
from random import choice, randint
|
||||
from statistics import mean, stdev
|
||||
from typing import Dict, List, Optional
|
||||
import json
|
||||
|
||||
# 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_spread() -> Dict[int, float]:
|
||||
@ -24,7 +21,6 @@ def init_spread() -> Dict[int, float]:
|
||||
return D
|
||||
|
||||
|
||||
# for two bets of structure Dict[int, float], iterate through all the keys and add up the values, returning a new dict.
|
||||
def combine_bets(bet_1: Bet, bet_2: Bet) -> Bet:
|
||||
"""
|
||||
Combines two bets into a single bet.
|
||||
@ -143,19 +139,13 @@ def expected(bet: Bet) -> float:
|
||||
amt = sum(bets)
|
||||
payout = amt * 36 / 38
|
||||
print(
|
||||
f"bet: {amt:.2f}, expected: {payout:.2f}: {payout/amt:2.4f} with std {stdev(bets*36)} mean win of {36*mean(cond_bets)} {sum(filter(lambda x: x > 0, bets))}/38 times."
|
||||
f"bet: {amt:.2f}, expected: {payout:.2f}: {payout/amt:2.4f}"
|
||||
+ f"with std {stdev(bets*36)} mean win of"
|
||||
+ f"{36*mean(cond_bets)} {sum(filter(lambda x: x > 0, bets))}/38 times."
|
||||
)
|
||||
return payout
|
||||
|
||||
|
||||
# 38 numbers, 6 street bets, 2 half-bets,
|
||||
|
||||
|
||||
# payout grid based on bets placed.
|
||||
# a street bet is the same as splitting the bet across all the numbers in the group.
|
||||
# will use a function to distribute / interpret the bets, but it seems like we only need to track the numbers on the wheel.
|
||||
|
||||
|
||||
def place_bet(bet: Bet, on: int, amount: float) -> Bet:
|
||||
"""
|
||||
Places a bet on a number.
|
||||
@ -258,7 +248,8 @@ def interpret_bet(on="red", amount=0, bet=Optional[Bet]) -> Bet:
|
||||
div = 1
|
||||
except ValueError as e:
|
||||
raise e(
|
||||
f"Bet `{on}` not understood. Choose from feasible moves:\n {set(range(-1, 37))}"
|
||||
f"Bet `{on}` not understood."
|
||||
+ f"Choose from feasible moves:\n {set(range(-1, 37))}"
|
||||
)
|
||||
|
||||
bet = reduce(lambda bet, num: place_bet(bet, num, amount / div), NUMS, bet)
|
||||
@ -287,9 +278,10 @@ class Placement:
|
||||
on: str
|
||||
|
||||
def __post_init__(self):
|
||||
assert (self.on in FEASIBLE_MOVES) or (
|
||||
self.on in ALIASES
|
||||
), f"Bet `{self.on}` not understood. Choose from feasible moves:\n {FEASIBLE_MOVES}"
|
||||
assert (self.on in FEASIBLE_MOVES) or (self.on in ALIASES), (
|
||||
f"Bet `{self.on}` not understood."
|
||||
+ f"Choose from feasible moves:\n {FEASIBLE_MOVES}"
|
||||
)
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.amt > other.amt
|
||||
@ -316,20 +308,18 @@ class Placement:
|
||||
return interpret_bet(self.on, self.num * self.amt, bet)
|
||||
|
||||
|
||||
# for a list of Placements, call the place_bet method on each one and combine the results using reduce and combine_bets, starting with an empty dictionary as the initial argument
|
||||
|
||||
|
||||
@dataclass
|
||||
class Strategy:
|
||||
"""
|
||||
A strategy is a list of placements, each of which is a bet on a particular number or group of numbers.
|
||||
A strategy is a list of placements, each of which is a bet on a
|
||||
particular number or group of numbers.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
budget : float
|
||||
The amount of money to spend on the strategy.
|
||||
placements : List[Placement]
|
||||
A list of placements, each of which is a bet on a particular number or group of numbers.
|
||||
A list of placements the player will make.
|
||||
|
||||
"""
|
||||
|
||||
@ -337,7 +327,10 @@ class Strategy:
|
||||
placements: List[Placement] = field(default_factory=list)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Strategy(budget={self.budget}, value={self.value}, placements={self.placements})"
|
||||
return (
|
||||
f"Strategy(budget={self.budget},"
|
||||
+ f"value={self.value}, placements={self.placements})"
|
||||
)
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
@ -369,10 +362,11 @@ class Strategy:
|
||||
while (budget > 0) and (num_placements < max_placements):
|
||||
amt = choice([v for v in CHIP_VALUES if v <= budget])
|
||||
# guarantees the max bet cannot exceed budget:
|
||||
# 4 is the max number of chips because after that you might as well use a higher chip value.
|
||||
# 4 is the max number of chips bc you might as well use a higher chip value.
|
||||
num = randint(1, min(budget // amt, 4))
|
||||
# select random bet type
|
||||
# TODO: consider if this is the logic you want... really let's define a player's profile / psychological disposition.
|
||||
# TODO: consider if this is the logic you want...
|
||||
# really let's define a player's profile / psychological disposition.
|
||||
# if randint(0, 1) == 0:
|
||||
# on = choice(list(FEASIBLE_MOVES))
|
||||
# else:
|
||||
@ -446,7 +440,13 @@ class Player:
|
||||
self.wallet: float = self.budget
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Player(id={self.id}, budget={self.budget}, wallet={self.wallet}, strategy={sorted(self.strategy.placements)}, strategy_cost={self.strategy.value}, strategy_budget={self.strategy.budget}, num_placements={len(self.strategy.placements)}"
|
||||
return (
|
||||
f"Player(id={self.id}, budget={self.budget}, wallet={self.wallet},"
|
||||
+ f"strategy={sorted(self.strategy.placements)},"
|
||||
+ f"strategy_cost={self.strategy.value},"
|
||||
+ f"strategy_budget={self.strategy.budget},"
|
||||
+ f"num_placements={len(self.strategy.placements)}"
|
||||
)
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.id < other.id
|
||||
@ -474,7 +474,6 @@ def simulate_random_strategy(min_num_games=1, total_budget=200) -> Strategy:
|
||||
return Strategy.generate_random(strategy_budget)
|
||||
|
||||
|
||||
# given BUDGET, generate a bunch of random players, each with a random strategy, and return a list of players
|
||||
def generate_players(num_players=10, min_num_games=1, total_budget=200) -> List[Player]:
|
||||
"""
|
||||
Generates a list of players with random strategies.
|
||||
@ -484,7 +483,8 @@ def generate_players(num_players=10, min_num_games=1, total_budget=200) -> List[
|
||||
num_players : int
|
||||
The number of players to generate.
|
||||
min_num_games : int
|
||||
The minimum number of games each player will play using their strategy and budget.
|
||||
The minimum number of games each player wants to play
|
||||
given their strategy and budget.
|
||||
total_budget : float
|
||||
The total budget for each player.
|
||||
|
||||
@ -502,7 +502,8 @@ def generate_players(num_players=10, min_num_games=1, total_budget=200) -> List[
|
||||
for i in range(num_players)
|
||||
]
|
||||
|
||||
# if a player has placements with identical amt and on values, combine them into a single placement
|
||||
# if a player has placements with identical `amt` and `on` values,
|
||||
# combine them into a single placement
|
||||
for player in players:
|
||||
placements = []
|
||||
for placement in player.strategy.placements:
|
||||
@ -514,8 +515,7 @@ def generate_players(num_players=10, min_num_games=1, total_budget=200) -> List[
|
||||
return players
|
||||
|
||||
|
||||
# simulate a game of roulette, picking a random integer from -1 to 37, taking the players as inputs and returning their expected winnings
|
||||
def simulate_game(players, verbose=False) -> List[float]:
|
||||
def play_round(players, verbose=False) -> List[float]:
|
||||
"""
|
||||
Simulates a single game of roulette.
|
||||
|
||||
@ -538,31 +538,45 @@ def simulate_game(players, verbose=False) -> List[float]:
|
||||
# for each player, place their bets on the wheel
|
||||
bets = [p.strategy.get_bet() for p in players]
|
||||
# for each player, calculate their winnings
|
||||
winnings = [36 * bet.get(num, 0) for bet in bets]
|
||||
winnings = [36 * bet.get(num) for bet in bets]
|
||||
# for each player, calculate their expected winnings
|
||||
return winnings
|
||||
|
||||
|
||||
# simulate multiple games, reducing each player's budget by the amount of their bet and adding the amount of their winnings
|
||||
def simulate_games(players, num_games=10):
|
||||
def play_roulette(players: List[Player], games: int = 10) -> List[Player]:
|
||||
"""
|
||||
Simulates playing multiple games of roulette.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
players : List[Player]
|
||||
The players in the game.
|
||||
games : int
|
||||
The number of games to play.
|
||||
|
||||
Returns
|
||||
-------
|
||||
List[Player]
|
||||
The players after playing the games.
|
||||
"""
|
||||
losers = []
|
||||
for g in range(num_games):
|
||||
for g in range(games):
|
||||
if not players:
|
||||
break
|
||||
# print(f"GAME {g}")
|
||||
winnings = simulate_game(players)
|
||||
winnings = play_round(players)
|
||||
new_losers = []
|
||||
for i, p in enumerate(players):
|
||||
p.wallet -= p.strategy.value
|
||||
p.wallet += winnings[
|
||||
i
|
||||
] # TODO: reinvestment logic goes here. maybe add "reinvest" as a player attribute?
|
||||
p.wallet += winnings[i]
|
||||
# TODO: reinvestment logic goes here.
|
||||
# maybe add "reinvest" as a player attribute?
|
||||
# if a player runs out of money to keep using their strategy,
|
||||
# remove them from the list of players and add them to the list of losers
|
||||
# remove them from the list of players and add them to losers.
|
||||
if p.wallet < p.strategy.value:
|
||||
new_losers.append(p)
|
||||
for l in new_losers:
|
||||
players.remove(l)
|
||||
for losing_player in new_losers:
|
||||
players.remove(losing_player)
|
||||
losers.extend(new_losers)
|
||||
|
||||
return players + losers
|
||||
|
7
setup.py
7
setup.py
@ -1,6 +1,7 @@
|
||||
from setuptools import setup
|
||||
from pathlib import Path
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
# Globals and constants variables.
|
||||
BASEDIR = Path(__file__).parent.resolve()
|
||||
|
||||
@ -9,10 +10,10 @@ with open(BASEDIR.joinpath("README.md"), "r") as fp:
|
||||
|
||||
setup(
|
||||
name="pyroulette",
|
||||
version="0.0.1rc1",
|
||||
version="0.0.1rc2",
|
||||
description="A package for exploring roulette strategies.",
|
||||
long_description=LONG_DESCRIPTION,
|
||||
long_description_content_type='text/markdown',
|
||||
long_description_content_type="text/markdown",
|
||||
author="Mathematical Michael",
|
||||
author_email="consistentbayes@gmail.com",
|
||||
url="https://github.com/mathematicalmichael/pyroulette",
|
||||
|
@ -1,4 +1,4 @@
|
||||
from pyroulette.roulette import Placement, Strategy, Bet
|
||||
from pyroulette.roulette import Bet, Placement, Strategy
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(Bet({-1: 1}).__repr__()) # this should print with 00
|
||||
|
Loading…
Reference in New Issue
Block a user