Repository: skent259/crapssim (language: python)

Issue:
What are craps-test.py and run_simulations.py in the Python directory for?
It looks like craps-test.py might just be some pre unit testing smoke tests, so I would think that this could be removed or refactored and moved to the test directory. 

run_simulations.py looks like convenience methods to run simulations without having to set up the tables and players etc. I think that these would be good to have somewhere so maybe they can be refined and moved into crapssim?



Discussion / hints:
craps-test.py is exactly as you say.  It can be removed with the new testing

I'm not sure what to do with the helper functions in run_simulations.py.  I'm not sure if they add value to the package or confuse it.  Ideally it would be nice to have a place for specific run methods for certain simulations, but there's so many ways to do it that it might be counterproductive to add to crapssim.  Thoughts?
I like the idea of having some convenience methods for running the simulations, and maybe even some convenience methods for simplifying the data through displaying with charts or giving helpful aggregation data (I'm a gambler not a statistician but for me average ROI, risk of ruin, coin-in, etc. could be valuable.)

Might make sense to have that as a separate package or something within crapssim, but I think that as long as it's well documented it could just be available in crapssim itself.

I think that this would be useful on the users end for simplicity, and allow us to add more features for running those simulations. For example, one thing that I would like to see on that front would be using the tqdm package to allow us to show a progress bar of the simulation completion status. I would think most end users would find this helpful, but it would be burdensome to document how to set that up in the readme for a user who just wants to run a simulation on their strategy. Similarly, I haven't tested it yet but I think that there could be some significant speed increases if when running multi simulations we utilized the multiprocessing module.

In theory, I think that one way to do it might be a Simulation object where you could add the table(s) and player(s) and a run method that would then run and store the results. Maybe with classmethods or optional arguments to initialize it for table, player, strategy, etc. For example to run 1000 passline simulations:

```
sim = Simulation.from_strategy(strategy=passline, bankroll=10000, runout=True)
sim.run(count=1000)
```
then it would show a tqdm progress bar with x number of simulations over 1000 being completed. And then there would be methods or properties with data ex:

```
print(sim.win_loss_amounts)
>>> [100.4, -55.6, 4000, ...]
```


Fix patch:
diff --git a/Craps.Rproj b/Craps.Rproj
deleted file mode 100644
index 8e3c2ebc..00000000
--- a/Craps.Rproj
+++ /dev/null
@@ -1,13 +0,0 @@
-Version: 1.0
-
-RestoreWorkspace: Default
-SaveWorkspace: Default
-AlwaysSaveHistory: Default
-
-EnableCodeIndexing: Yes
-UseSpacesForTab: Yes
-NumSpacesForTab: 2
-Encoding: UTF-8
-
-RnwWeave: Sweave
-LaTeX: pdfLaTeX
diff --git a/Python/run_simulations.py b/Python/run_simulations.py
deleted file mode 100644
index 3158b635..00000000
--- a/Python/run_simulations.py
+++ /dev/null
@@ -1,126 +0,0 @@
-from crapssim import Table
-from crapssim import Player
-from crapssim import strategy
-import sys 
-import os 
-
-
-def run_printout(n_roll, n_shooter, bankroll, strategy, strategy_name, runout):
-    runout_str = "-runout" if runout else ""
-    # Run one simulation with verbose=True to check strategy
-    outfile_name = f"./output/printout/{strategy_name}_roll-{n_roll}_shooter-{n_shooter}_br-{bankroll}{runout_str}.txt"
-    # outfile_name = "./output/printout/{}_roll-{}_br-{}{}.txt".format(strategy_name, n_roll, bankroll, runout_str)
-    print("Running printout for " + os.path.basename(outfile_name))
-    # print("Running printout for {}_sim-{}_roll-{}_br-{}{}.txt".format(strategy_name, n_sim, n_roll, bankroll, runout_str))
-    with open(outfile_name, 'w') as f_out:
-        sys.stdout = f_out
-        table = Table()
-        table.add_player(Player(bankroll, strategy))
-        table.run(n_roll, n_shooter, verbose=True)
-    sys.stdout = sys.__stdout__ # reset stdout
-
-def run_simulation(n_sim, n_roll, bankroll, strategy, strategy_name, runout):
-    runout_str = "_runout" if runout else ""
-    # Run simulation of n_roll rolls (estimated rolls/hour with 5 players) 1000 times
-    outfile_name = "./output/simulations/{}_sim-{}_roll-{}_br-{}{}.txt".format(strategy_name, n_sim, n_roll, bankroll, runout_str)
-    print("Running simulations for {}_sim-{}_roll-{}_br-{}{}.txt".format(strategy_name, n_sim, n_roll, bankroll, runout_str))
-    with open(outfile_name, 'w') as f_out:
-        # Headers to match out
-        f_out.write("total_cash,bankroll,n_rolls") 
-        f_out.write(str('\n'))
-        for _ in range(n_sim):
-            table = Table()
-            table.add_player(Player(bankroll, strategy))
-            table.run(n_roll, verbose=False, runout=runout)
-            # write data to file
-            out = "{},{},{}".format(table.total_player_cash, bankroll, table.dice.n_rolls_)
-            f_out.write(str(out))
-            f_out.write(str('\n'))
-
-def run_simulation_burnin(n_sim, n_roll, bankroll, strategy, strategy_name, burn_in=20, runout=True):
-    runout_str = "_runout" if runout else ""
-    # Run simulation of n_roll rolls (estimated rolls/hour with 5 players) 1000 times
-    outfile_name = "./output/simulations/{}_sim-{}_roll-{}_br-{}_burnin{}.txt".format(strategy_name, n_sim, n_roll, bankroll, runout_str)
-    print("Running simulations for {}_sim-{}_roll-{}_br-{}_burnin{}.txt".format(strategy_name, n_sim, n_roll, bankroll, runout_str))
-    with open(outfile_name, 'w') as f_out:
-        # Headers to match out
-        f_out.write("total_cash,bankroll,n_rolls") 
-        f_out.write(str('\n'))
-        for _ in range(n_sim):
-            table = Table()
-            table.add_player(Player(bankroll, strategy))
-
-            table.run(burn_in, verbose=False, runout=False)
-            burn_in_bankroll = table.total_player_cash
-            table.run(n_roll, verbose=False, runout=runout)
-            # write data to file
-            out = "{},{},{}".format(table.total_player_cash, burn_in_bankroll, table.dice.n_rolls_)
-            f_out.write(str(out))
-            f_out.write(str('\n'))
-
-def run_multi_simulation(n_sim, n_roll, n_shooter, bankroll, strategy, name, runout=True):
-    runout_str = "_runout" if runout else ""
-    # Run simulation of n_roll rolls (estimated rolls/hour with 5 players) 1000 times
-    outfile_name = "./output/simulations/{}_sim-{}_roll-{}_br-{}_burnin{}.txt".format(name, n_sim, n_roll, bankroll, runout_str)
-    print("Running simulations for {}_sim-{}_roll-{}_br-{}_burnin{}.txt".format(name, n_sim, n_roll, bankroll, runout_str))
-    with open(outfile_name, 'w') as f_out:
-        # Headers to match out
-        f_out.write("simid,strategy,total_cash,bankroll,n_rolls") 
-        f_out.write(str('\n'))
-        for i in range(n_sim):
-            if i % 1000 == 0:
-                print(f"i: {i}")
-            table = Table() 
-            table.set_payouts("fielddouble", [2])
-            table.set_payouts("fieldtriple", [12])
-            for bank, s in zip(bankroll, strategy):
-                table.add_player(Player(bank, strategy[s], s))
-
-            # table.run(burn_in, verbose=False, runout=False)
-            # burn_in_bankroll = table.total_player_cash
-            table.run(n_roll, n_shooter, verbose=False, runout=runout)
-            # write data to file
-            # TODO: get actual player cash 
-            for bank, s in zip(bankroll, strategy):
-                out = f"{i},{s},{table.get_player(s).bankroll},{bank},{table.dice.n_rolls}"
-                # out = "{},{},{},{}".format(s, table.total_player_cash, bank, table.dice.n_rolls_)
-                f_out.write(str(out))
-                f_out.write(str('\n'))
-
-
-
-if __name__ == "__main__":
-    
-    sim = True 
-    printout = True
-
-    n_sim = 10
-    n_roll = float('inf')
-    n_shooter = 1
-    bankrolls= [10000]
-    strategies = {"passline": strategy.passline}
-    name = "testing"
-    # strategy = strat._strat_place68
-    # strategy_name = "place68" # don't include any "_" in this
-    runout = True
-    # runout_str = "-runout" if runout else ""
-
-    """ Run one strategy  """
-    if printout: 
-        for bank, s in zip(bankrolls, strategies):
-            run_printout(n_roll, n_shooter, bank, strategies[s], s, runout)    
-        # run_printout(n_roll, bankroll, strategy, strategy_name, runout)
-
-    if sim:
-        run_multi_simulation(n_sim, n_roll, n_shooter, bankrolls, strategies, name, runout)
-        # run_simulation_burnin(n_sim, n_roll, bankroll, strategy, strategy_name, burn_in=20, runout=runout)
-
-    
-
-    """ Run multiple strategies """
-    # strategies = [strat._strat_place68, strat._strat_place68_2come, strat._strat_pass2come, strat._strat_passline_odds2]
-    # strategy_names = ["place68", "place68-2come", "pass-2come", "passline-w-2odds"]
-
-    # for strategy, strategy_name in zip(strategies,strategy_names):
-    #     # run_simulation_burnin(n_sim, n_roll, bankroll, strategy, strategy_name, burn_in=20, runout=runout)
-    #     run_simulation(n_sim, n_roll, bankroll, strategy, strategy_name, runout=runout)


Test patch:
diff --git a/Python/craps-test.py b/Python/craps-test.py
deleted file mode 100644
index 21929f75..00000000
--- a/Python/craps-test.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import crapssim as craps
-
-if __name__ == "__main__":
-
-    # # Testing the rolling of dice
-    # d1 = Dice()
-
-    # d1.roll()
-    # d1.roll()
-    # d1.roll()
-
-    # print("Number of rolls: {}".format(d1.n_rolls_))
-    # print("Last Roll: {}".format(d1.result_))
-    # print("Last Roll Total: {}".format(d1.total_))
-
-    # Test making a player
-    # Sean = Player(500)
-    # print("Sean's bankroll: {}".format(Sean.bankroll))
-
-    # Test making a bet
-    # Sean.bet(passline(5))
-    # print("Sean's bankroll: {}".format(Sean.bankroll))
-    # print("Sean's current bets: {}".format(
-    #   {b.name: b.bet_amount for b in Sean.bets_on_table}
-    # ))
-    # print("Sean's total bet amount: {}".format(sum(
-    #  [b.bet_amount for b in Sean.bets_on_table]
-    # )))
-
-    table = craps.Table()
-
-    # place8 bet
-    Sean = craps.player.Player(100, "Sean")
-    d = craps.dice.Dice()
-    # Sean.bet(come(5))
-    # # d.fixed_roll([4,4])
-    # Sean.bet(come(6))
-    Sean.bet(craps.bet.Come(5))
-
-    d.fixed_roll([4, 4])
-    Sean.update_bet()
-    Sean.bet(craps.bet.Come(10))
-    print("Sean's current bets: {}".format(
-        {b.name: b.bet_amount for b in Sean.bets_on_table}
-    ))  # NTS: this will not show duplicate bets, but they still exist
-    print(Sean.bets_on_table)
-
-    print(Sean.get_bet("Come", "8"))