dialed in the simsim levers to accurately simulate baseball

This commit is contained in:
Sakimori 2020-12-21 04:46:12 -05:00
parent c7ec53375a
commit 844450c142
4 changed files with 115 additions and 9 deletions

98
debug storage.py Normal file
View File

@ -0,0 +1,98 @@
def large_scale_debug(): #massive debug, goes in games.py
average_player = player('{"id" : "average", "name" : "average", "batting_stars" : 2.5, "pitching_stars" : 2.5, "defense_stars" : 2.5, "baserunning_stars" : 2.5}')
max_player = player('{"id" : "max", "name" : "max", "batting_stars" : 5, "pitching_stars" : 5, "defense_stars" : 5, "baserunning_stars" : 5}')
min_player = player('{"id" : "min", "name" : "min", "batting_stars" : 1, "pitching_stars" : 1, "defense_stars" : 1, "baserunning_stars" : 1}')
team_avg = team()
team_avg.add_lineup(average_player)
team_avg.set_pitcher(average_player)
team_avg.finalize()
team_max = team()
team_max.add_lineup(max_player)
team_max.set_pitcher(max_player)
team_max.finalize()
team_min = team()
team_min.add_lineup(min_player)
team_min.set_pitcher(min_player)
team_min.finalize()
average_game = game(team_avg, team_avg)
slugging_game = game(team_max, team_min)
shutout_game = game(team_min, team_max)
hit_count_avg = 0
walk_count_avg = 0
home_run_avg = 0
so_avg = 0
fo_avg = 0
go_avg = 0
for i in range(0,10000):
ab = average_game.at_bat()
if ab["ishit"]:
hit_count_avg += 1
if ab["text"] == appearance_outcomes.homerun:
home_run_avg += 1
elif ab["text"] == appearance_outcomes.walk:
walk_count_avg += 1
elif ab["text"] == appearance_outcomes.strikeoutlooking or ab["text"] == appearance_outcomes.strikeoutswinging:
so_avg += 1
elif ab["text"] == appearance_outcomes.groundout:
go_avg += 1
elif ab["text"] == appearance_outcomes.flyout:
fo_avg += 1
hit_count_slg = 0
walk_count_slg = 0
home_run_slg = 0
fo_slg = 0
go_slg = 0
so_slg = 0
for i in range(0,10000):
ab = slugging_game.at_bat()
if ab["ishit"]:
hit_count_slg += 1
if ab["text"] == appearance_outcomes.homerun:
home_run_slg += 1
elif ab["text"] == appearance_outcomes.walk:
walk_count_slg += 1
elif ab["text"] == appearance_outcomes.strikeoutlooking or ab["text"] == appearance_outcomes.strikeoutswinging:
so_slg += 1
elif ab["text"] == appearance_outcomes.groundout:
go_slg += 1
elif ab["text"] == appearance_outcomes.flyout:
fo_slg += 1
hit_count_sht = 0
walk_count_sht = 0
home_run_sht = 0
go_sht = 0
fo_sht = 0
so_sht = 0
for i in range(0,10000):
ab = shutout_game.at_bat()
if ab["ishit"]:
hit_count_sht += 1
if ab["text"] == appearance_outcomes.homerun:
home_run_sht += 1
elif ab["text"] == appearance_outcomes.walk:
walk_count_sht += 1
elif ab["text"] == appearance_outcomes.strikeoutlooking or ab["text"] == appearance_outcomes.strikeoutswinging:
so_sht += 1
elif ab["text"] == appearance_outcomes.groundout:
go_sht += 1
elif ab["text"] == appearance_outcomes.flyout:
fo_sht += 1
return (hit_count_avg, walk_count_avg, hit_count_slg, walk_count_slg, hit_count_sht, walk_count_sht, home_run_avg, home_run_slg, home_run_sht, so_avg, so_slg, so_sht, go_avg, go_slg, go_sht, fo_avg, fo_slg, fo_sht)
# massive debug function, companion to above. goes in the_prestige
# elif command == "testabs":
# result = games.large_scale_debug()
# await msg.channel.send(f"over 10000 atbats, average player vs average pitcher achieved avg {(result[0]/(10000-result[1]))} and walk rate {result[1]/10000}.")
# await msg.channel.send(f"over 10000 atbats, max player vs min pitcher achieved avg {(result[2]/(10000-result[3]))} and walk rate {result[3]/10000}.")
# await msg.channel.send(f"over 10000 atbats, min player vs max pitcher achieved avg {(result[4]/(10000-result[5]))} and walk rate {result[5]/10000}.")
# await msg.channel.send(f"""there were {result[6]}, {result[7]}, and {result[8]} home runs, respectively.
# there were {result[9]}, {result[10]}, and {result[11]} strikeouts, respectively.
# there were {result[12]}, {result[13]}, and {result[14]} groundouts, respectively.
# there were {result[15]}, {result[16]}, and {result[17]} flyouts, respectively.""")

View File

@ -28,7 +28,7 @@ class appearance_outcomes(Enum):
flyout = "flies out to" flyout = "flies out to"
fielderschoice = "reaches on fielder's choice." fielderschoice = "reaches on fielder's choice."
doubleplay = "grounds into a double play!" doubleplay = "grounds into a double play!"
walks = "draws a walk." walk = "draws a walk."
single = "hits a single!" single = "hits a single!"
double = "hits a double!" double = "hits a double!"
triple = "hits a triple!" triple = "hits a triple!"
@ -110,22 +110,24 @@ class game(object):
bat_stat = random_star_gen("batting_stars", batter) bat_stat = random_star_gen("batting_stars", batter)
pitch_stat = random_star_gen("pitching_stars", pitcher) pitch_stat = random_star_gen("pitching_stars", pitcher)
def_stat = random_star_gen("defense_stars", defender) def_stat = random_star_gen("defense_stars", defender)
pb_system_stat = (random.gauss(1.5*math.erf((bat_stat - pitch_stat)/2)-1.5,3)) pb_system_stat = (random.gauss(1*math.erf((bat_stat - pitch_stat)*1.5)-1.8,2.2))
hitnum = random.gauss(2*math.erf(bat_stat)-0.5,3) hitnum = random.gauss(2*math.erf(bat_stat/4)-1,3)
outcome = {} outcome = {}
if pb_system_stat <= 0: if pb_system_stat <= 0:
outcome["ishit"] = False outcome["ishit"] = False
fc_flag = False fc_flag = False
if hitnum < 1: if hitnum < -1.5:
outcome["text"] = random.choice([appearance_outcomes.strikeoutlooking, appearance_outcomes.strikeoutswinging]) outcome["text"] = random.choice([appearance_outcomes.strikeoutlooking, appearance_outcomes.strikeoutswinging])
elif hitnum < 2: elif hitnum < 1:
outcome["text"] = appearance_outcomes.groundout outcome["text"] = appearance_outcomes.groundout
outcome["defender"] = defender outcome["defender"] = defender
else: elif hitnum < 4:
outcome["text"] = appearance_outcomes.flyout outcome["text"] = appearance_outcomes.flyout
outcome["defender"] = defender outcome["defender"] = defender
else:
outcome["text"] = appearance_outcomes.walk
if self.bases[1] is not None and hitnum < 1: if self.bases[1] is not None and hitnum < 1:
outcome["text"] = appearance_outcomes.doubleplay outcome["text"] = appearance_outcomes.doubleplay
@ -135,11 +137,12 @@ class game(object):
if fc_flag and 1 <= hitnum and hitnum < 2: if fc_flag and 1 <= hitnum and hitnum < 2:
outcome["text"] = appearance_outcomes.fielderschoice outcome["text"] = appearance_outcomes.fielderschoice
else: else:
outcome["ishit"] = True
if hitnum < 1: if hitnum < 1:
outcome["text"] = appearance_outcomes.single outcome["text"] = appearance_outcomes.single
elif hitnum < 2: elif hitnum < 2.85:
outcome["text"] = appearance_outcomes.double outcome["text"] = appearance_outcomes.double
elif hitnum < 3: elif hitnum < 3.1:
outcome["text"] = appearance_outcomes.triple outcome["text"] = appearance_outcomes.triple
else: else:
if self.bases[1] is not None and self.bases[2] is not None and self.bases[3] is not None: if self.bases[1] is not None and self.bases[2] is not None and self.bases[3] is not None:
@ -153,7 +156,7 @@ class game(object):
self.teams["home"].lineup_position += 1 self.teams["home"].lineup_position += 1
return outcome return outcome
def random_star_gen(key, player): def random_star_gen(key, player):
return random.gauss(config()["stlat_weights"][key] * player.stlats[key],1) return random.gauss(config()["stlat_weights"][key] * player.stlats[key],1)

View File

@ -25,6 +25,9 @@
<Compile Include="database.py"> <Compile Include="database.py">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="debug storage.py">
<SubType>Code</SubType>
</Compile>
<Compile Include="onomancer.py"> <Compile Include="onomancer.py">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>

View File

@ -100,6 +100,8 @@ async def on_message(msg):
except KeyError: except KeyError:
await msg.channel.send(f"{batter.name} {atbat['text'].value}") await msg.channel.send(f"{batter.name} {atbat['text'].value}")
elif command == "credit": elif command == "credit":
await msg.channel.send("Our avatar was graciously provided to us, with permission, by @HetreaSky on Twitter.") await msg.channel.send("Our avatar was graciously provided to us, with permission, by @HetreaSky on Twitter.")