Merge pull request #262 from Sakimori/draft-pool-expansion
Draft pool expansion
This commit is contained in:
commit
bdc6841826
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -358,3 +358,4 @@ env
|
|||
/data/leagues
|
||||
/simmadome/build
|
||||
/simmadome/.eslintcache
|
||||
/matteo_env/Lib/site-packages
|
||||
|
|
28
games.py
28
games.py
|
@ -50,6 +50,8 @@ class player(object):
|
|||
"strikeouts_taken" : 0
|
||||
}
|
||||
self.stat_name = self.name
|
||||
if self.name == "Tim Locastro":
|
||||
self.randomize_stars()
|
||||
|
||||
def star_string(self, key):
|
||||
str_out = ""
|
||||
|
@ -68,6 +70,15 @@ class player(object):
|
|||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def randomize_stars(self):
|
||||
for key in ["batting_stars", "pitching_stars", "baserunning_stars", "defense_stars"]:
|
||||
#random star value between 0 and 6.5
|
||||
stars = random.randint(0,6)
|
||||
half_star = random.random() < 0.5 #half star addition
|
||||
if half_star:
|
||||
stars = half_star + 0.5
|
||||
self.stlats[key] = stars
|
||||
|
||||
|
||||
class team(object):
|
||||
def __init__(self):
|
||||
|
@ -208,6 +219,7 @@ class game(object):
|
|||
|
||||
def __init__(self, team1, team2, length=None):
|
||||
self.over = False
|
||||
self.random_weather_flag = False
|
||||
self.teams = {"away" : team1, "home" : team2}
|
||||
self.inning = 1
|
||||
self.outs = 0
|
||||
|
@ -682,6 +694,9 @@ class game(object):
|
|||
|
||||
self.top_of_inning = not self.top_of_inning
|
||||
|
||||
if self.random_weather_flag and self.top_of_inning:
|
||||
setattr(self, "weather", random.choice(list(weather.safe_weathers().values()))(self))
|
||||
|
||||
self.weather.on_flip_inning(self)
|
||||
|
||||
self.choose_next_batter()
|
||||
|
@ -690,6 +705,7 @@ class game(object):
|
|||
self.inning += 1
|
||||
if self.inning > self.max_innings and self.teams["home"].score != self.teams["away"].score: #game over
|
||||
self.over = True
|
||||
try: #if something goes wrong with OBL don't erase game
|
||||
if self.max_innings >= 9 or self.weather.name in ["Leaf Eddies", "Torrential Downpour"]:
|
||||
if self.teams["home"].score == 16:
|
||||
this_xvi_team = self.teams["home"]
|
||||
|
@ -698,6 +714,9 @@ class game(object):
|
|||
else:
|
||||
this_xvi_team = None
|
||||
db.save_obl_results(self.teams["home"] if self.teams["home"].score > self.teams["away"].score else self.teams["away"], self.teams["home"] if self.teams["home"].score < self.teams["away"].score else self.teams["away"], xvi_team=this_xvi_team)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def end_of_game_report(self):
|
||||
|
@ -798,6 +817,9 @@ def get_team(name):
|
|||
team_json.rotation.append(team_json.pitcher)
|
||||
team_json.pitcher = None
|
||||
update_team(team_json)
|
||||
for player in team_json.rotation + team_json.lineup:
|
||||
if player.name == "Tim Locastro":
|
||||
player.randomize_stars()
|
||||
return team_json
|
||||
return None
|
||||
except AttributeError:
|
||||
|
@ -818,6 +840,9 @@ def get_team_and_owner(name):
|
|||
team_json.rotation.append(team_json.pitcher)
|
||||
team_json.pitcher = None
|
||||
update_team(team_json)
|
||||
for player in team_json.rotation + team_json.lineup:
|
||||
if player.name == "Tim Locastro":
|
||||
player.randomize_stars()
|
||||
return (team_json, owner_id)
|
||||
return None
|
||||
except AttributeError:
|
||||
|
@ -864,6 +889,9 @@ def search_team(search_term):
|
|||
team_json.rotation.append(team_json.pitcher)
|
||||
team_json.pitcher = None
|
||||
update_team(team_json)
|
||||
for player in team_json.rotation + team_json.lineup:
|
||||
if player.name == "Tim Locastro":
|
||||
player.randomize_stars()
|
||||
except AttributeError:
|
||||
team_json.rotation = []
|
||||
team_json.rotation.append(team_json.pitcher)
|
||||
|
|
|
@ -45,7 +45,7 @@ class game_strings_base(object):
|
|||
|
||||
twoparts = []
|
||||
|
||||
diff_formats = {fielderschoice[0]: ("batter", "base_string"),
|
||||
diff_formats = {fielderschoice[0]: ("runner", "base_string"),
|
||||
steal_success[0]: ("runner", "base_string"),
|
||||
steal_caught[0]: ("runner", "base_string", "defender")}
|
||||
no_formats = strikeoutlooking + strikeoutswinging + doubleplay + walk + single + double + triple + homerun + grandslam
|
||||
|
|
|
@ -190,15 +190,19 @@ def update_loop():
|
|||
else:
|
||||
if this_game.top_of_inning:
|
||||
state["update_text"] = f"Top of {this_game.inning}. {this_game.teams['away'].name} batting!"
|
||||
this_game.weather.modify_top_of_inning_message(this_game, state)
|
||||
if this_game.random_weather_flag:
|
||||
this_game.weather.weather_report(this_game, state)
|
||||
else:
|
||||
if this_game.inning >= this_game.max_innings:
|
||||
if this_game.teams["home"].score > this_game.teams["away"].score:
|
||||
this_game.victory_lap = True
|
||||
state["update_text"] = f"Bottom of {this_game.inning}. {this_game.teams['home'].name} batting!"
|
||||
|
||||
this_game.weather.modify_top_of_inning_message(this_game, state)
|
||||
|
||||
|
||||
|
||||
|
||||
elif state["update_pause"] != 1 and this_game.play_has_begun:
|
||||
|
||||
if "twopart" in this_game.last_update[0].keys():
|
||||
|
@ -256,4 +260,4 @@ def update_loop():
|
|||
socket_thread = threading.Thread(target=socketio.emit, args=("states_update", game_states))
|
||||
socket_thread.start()
|
||||
#socketio.emit("states_update", game_states)
|
||||
time.sleep(8)
|
||||
time.sleep(3)
|
24
real_players.py
Normal file
24
real_players.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
from lxml import html
|
||||
import requests, json
|
||||
import onomancer as ono
|
||||
|
||||
|
||||
def random_real_player():
|
||||
name = []
|
||||
while name == []:
|
||||
page = requests.get("http://www.baseball-reference.com/rand.fcgi")
|
||||
tree = html.fromstring(page.content)
|
||||
name = tree.xpath("//h1[@itemprop='name']/span/text()")
|
||||
if len(name) > 0 and len(name[0]) == 4:
|
||||
name = [] #gets rid of years
|
||||
name = name[0]
|
||||
return name
|
||||
|
||||
def get_real_players(num):
|
||||
names = []
|
||||
for i in range(0, num):
|
||||
names.append(random_real_player())
|
||||
players = {}
|
||||
for name in names:
|
||||
players[name] = json.loads(ono.get_stats(name))
|
||||
return players
|
|
@ -46,6 +46,9 @@
|
|||
<Compile Include="games.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="real_players.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="roman.py" />
|
||||
<Compile Include="the_draft.py" />
|
||||
<Compile Include="the_prestige.py" />
|
||||
|
|
19
the_draft.py
19
the_draft.py
|
@ -2,7 +2,7 @@ from collections import namedtuple
|
|||
import games
|
||||
import json
|
||||
import uuid
|
||||
|
||||
import real_players
|
||||
import onomancer
|
||||
|
||||
Participant = namedtuple('Participant', ['handle', 'team'])
|
||||
|
@ -16,19 +16,22 @@ class Draft:
|
|||
"""
|
||||
|
||||
@classmethod
|
||||
def make_draft(cls, teamsize, draftsize, minsize, pitchers):
|
||||
draft = cls(teamsize, draftsize, minsize, pitchers)
|
||||
def make_draft(cls, teamsize, draftsize, minsize, pitchers, ono_ratio):
|
||||
draft = cls(teamsize, draftsize, minsize, pitchers, ono_ratio)
|
||||
return draft
|
||||
|
||||
def __init__(self, teamsize, draftsize, minsize, pitchers):
|
||||
self.DRAFT_SIZE = draftsize
|
||||
def __init__(self, teamsize, draftsize, minsize, pitchers, ono_ratio):
|
||||
self.DRAFT_SIZE = int(draftsize * ono_ratio)
|
||||
self.REAL_SIZE = draftsize - self.DRAFT_SIZE
|
||||
self.REFRESH_DRAFT_SIZE = minsize # fewer players remaining than this and the list refreshes
|
||||
self.DRAFT_ROUNDS = teamsize
|
||||
self.pitchers = pitchers
|
||||
self._id = str(uuid.uuid4())[:6]
|
||||
self._participants = []
|
||||
self._active_participant = BOOKMARK # draft mutex
|
||||
self._players = onomancer.get_names(limit=self.DRAFT_SIZE)
|
||||
nameslist = onomancer.get_names(limit=self.DRAFT_SIZE)
|
||||
nameslist.update(real_players.get_real_players(self.REAL_SIZE))
|
||||
self._players = nameslist
|
||||
self._round = 0
|
||||
|
||||
@property
|
||||
|
@ -68,7 +71,9 @@ class Draft:
|
|||
self.advance_draft()
|
||||
|
||||
def refresh_players(self):
|
||||
self._players = onomancer.get_names(limit=self.DRAFT_SIZE)
|
||||
nameslist = onomancer.get_names(limit=self.DRAFT_SIZE)
|
||||
nameslist.update(real_players.get_real_players(self.REAL_SIZE))
|
||||
self._players = nameslist
|
||||
|
||||
def advance_draft(self):
|
||||
"""
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import discord, json, math, os, roman, games, asyncio, random, main_controller, threading, time, urllib, leagues, datetime, gametext
|
||||
import discord, json, math, os, roman, games, asyncio, random, main_controller, threading, time, urllib, leagues, datetime, gametext, real_players
|
||||
import database as db
|
||||
import onomancer as ono
|
||||
from league_storage import league_exists, season_save, season_restart
|
||||
|
@ -646,6 +646,8 @@ class StartDraftCommand(Command):
|
|||
draftsize = 20
|
||||
minsize = 4
|
||||
pitchers = 3
|
||||
ono_ratio = 0.5
|
||||
timeout = 120
|
||||
|
||||
for flag in flags:
|
||||
try:
|
||||
|
@ -657,10 +659,16 @@ class StartDraftCommand(Command):
|
|||
minsize = int(flag[1])
|
||||
elif flag[0] == "p":
|
||||
pitchers = int(flag[1])
|
||||
elif flag[0] == "c":
|
||||
ono_ratio = float(flag[1])
|
||||
if ono_ratio > 1 or ono_ratio < 0:
|
||||
raise CommandError("The Chaos value needs to be between 0 and 1, chief. Probability has rules.")
|
||||
elif flag[0] == "w": #wait
|
||||
timeout = int(flag[1])
|
||||
else:
|
||||
raise CommandError(f"We don't recognize that {flag[0]} flag.")
|
||||
except ValueError:
|
||||
raise CommandError(f"Your {flag[0]} flag isn't a valid integer, boss.")
|
||||
raise CommandError(f"Your {flag[0]} flag isn't a valid nummber, boss.")
|
||||
|
||||
if teamsize-pitchers > 20 or pitchers > 8:
|
||||
raise CommandError("You can't fit that many players on a team, chief. Slow your roll.")
|
||||
|
@ -669,7 +677,13 @@ class StartDraftCommand(Command):
|
|||
if draftsize > 40:
|
||||
raise CommandError("40 players is the max. We're not too confident about pushing for more.")
|
||||
|
||||
draft = Draft.make_draft(teamsize, draftsize, minsize, pitchers)
|
||||
await msg.channel.send("Got it, boss. Give me a sec to find all the paperwork.")
|
||||
|
||||
try:
|
||||
draft = Draft.make_draft(teamsize, draftsize, minsize, pitchers, ono_ratio)
|
||||
except ConnectionError:
|
||||
await msg.channel.send("Baseball Reference isn't playing nice. Could you try again for us in a minute or so?")
|
||||
|
||||
mentions = {f'<@!{m.id}>' for m in msg.mentions}
|
||||
content = msg.content.split('\n')[1:] # drop command out of message
|
||||
if not content or len(content) % 3:
|
||||
|
@ -683,7 +697,7 @@ class StartDraftCommand(Command):
|
|||
handle = mention
|
||||
break
|
||||
else:
|
||||
await msg.channel.send(f"I don't recognize {handle_token}")
|
||||
await msg.channel.send(f"I don't recognize {handle_token}.")
|
||||
return
|
||||
team_name = content[i + 1].strip()
|
||||
if games.get_team(team_name):
|
||||
|
@ -727,7 +741,7 @@ class StartDraftCommand(Command):
|
|||
embed=build_draft_embed(draft.get_draftees(), footer=footer),
|
||||
)
|
||||
try:
|
||||
draft_message = await self.wait_draft(msg.channel, draft)
|
||||
draft_message = await self.wait_draft(msg.channel, draft, timeout)
|
||||
draft.draft_player(f'<@!{draft_message.author.id}>', draft_message.content.split(' ', 1)[1])
|
||||
except SlowDraftError:
|
||||
player = random.choice(draft.get_draftees())
|
||||
|
@ -777,7 +791,7 @@ class StartDraftCommand(Command):
|
|||
return False
|
||||
return False
|
||||
|
||||
async def wait_draft(self, channel, draft):
|
||||
async def wait_draft(self, channel, draft, timeout):
|
||||
|
||||
def check(m):
|
||||
if m.channel != channel:
|
||||
|
@ -790,16 +804,16 @@ class StartDraftCommand(Command):
|
|||
return False
|
||||
|
||||
try:
|
||||
draft_message = await client.wait_for('message', timeout=120.0, check=check)
|
||||
draft_message = await client.wait_for('message', timeout=timeout, check=check)
|
||||
except asyncio.TimeoutError:
|
||||
raise SlowDraftError('Too slow')
|
||||
raise SlowDraftError('Too slow, boss.')
|
||||
return draft_message
|
||||
|
||||
|
||||
class StartLeagueCommand(Command):
|
||||
name = "startleague"
|
||||
template = "m;startleague [league name]\n[games per hour]"
|
||||
description = """Optional flags for the first line: `--queue X` or `-q X` to play X number of series before stopping; `--noautopostseason` will pause the league before starting postseason.
|
||||
description = """Optional flags for the first line: `--queue X` or `-q X` to play X number of series before stopping; `--autopostseason` will automatically start postseason at the end of the season.
|
||||
Starts games from a league with a given name, provided that league has been saved on the website and has been claimed using claimleague. The games per hour sets how often the games will start (e.g. GPH 2 will start games at X:00 and X:30). By default it will play the entire season followed by the postseason and then stop but this can be customized using the flags.
|
||||
Not every team will play every series, due to how the scheduling algorithm is coded but it will all even out by the end."""
|
||||
|
||||
|
@ -2095,6 +2109,16 @@ def build_team_embed(team):
|
|||
def build_star_embed(player_json):
|
||||
starkeys = {"batting_stars" : "Batting", "pitching_stars" : "Pitching", "baserunning_stars" : "Baserunning", "defense_stars" : "Defense"}
|
||||
embed = discord.Embed(color=discord.Color.purple(), title=player_json["name"])
|
||||
|
||||
if player_json["name"] == "Tim Locastro": #the tim easter egg
|
||||
for key in ["batting_stars", "pitching_stars", "baserunning_stars", "defense_stars"]:
|
||||
#random star value between 0 and 6.5
|
||||
stars = random.randint(0,6)
|
||||
half_star = random.random() < 0.5 #half star addition
|
||||
if half_star:
|
||||
stars = half_star + 0.5
|
||||
player_json[key] = stars
|
||||
|
||||
for key in starkeys.keys():
|
||||
embedstring = ""
|
||||
starstring = str(player_json[key])
|
||||
|
|
38
weather.py
38
weather.py
|
@ -57,6 +57,11 @@ class Weather:
|
|||
def modify_game_end_message(self, game, state):
|
||||
pass
|
||||
|
||||
def weather_report(self, game, state):
|
||||
game.weather = random.choice(list(safe_weathers().values()))(game)
|
||||
state["update_emoji"] = "🚌"
|
||||
state["update_text"] += f" Weather report: {game.weather.name} {game.weather.emoji}"
|
||||
|
||||
|
||||
class Supernova(Weather):
|
||||
name = "Supernova"
|
||||
|
@ -545,6 +550,18 @@ class LeafEddies(Weather):
|
|||
if game.inning == 1:
|
||||
state["weather_text"] = self.name
|
||||
|
||||
class Smog(Weather):
|
||||
name = "Smog"
|
||||
emoji = "🚌"
|
||||
duration_range = [1,1]
|
||||
|
||||
def __init__(self, game):
|
||||
game.random_weather_flag = True
|
||||
setattr(game, "weather", random.choice(list(safe_weathers().values()))(game))
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def all_weathers():
|
||||
weathers_dic = {
|
||||
"Supernova" : Supernova,
|
||||
|
@ -562,7 +579,26 @@ def all_weathers():
|
|||
"Tornado" : Tornado,
|
||||
"Torrential Downpour" : Downpour,
|
||||
"Summer Mist" : SummerMist,
|
||||
"Leaf Eddies" : LeafEddies
|
||||
"Leaf Eddies" : LeafEddies,
|
||||
"Smog" : Smog
|
||||
}
|
||||
return weathers_dic
|
||||
|
||||
def safe_weathers():
|
||||
"""weathers safe to swap in mid-game"""
|
||||
weathers_dic = {
|
||||
"Supernova" : Supernova,
|
||||
"Midnight": Midnight,
|
||||
"Slight Tailwind": SlightTailwind,
|
||||
"Twilight" : Twilight,
|
||||
"Thinned Veil" : ThinnedVeil,
|
||||
"Drizzle" : Drizzle,
|
||||
"Breezy": Breezy,
|
||||
"Starlight" : Starlight,
|
||||
"Meteor Shower" : MeteorShower,
|
||||
"Hurricane" : Hurricane,
|
||||
"Tornado" : Tornado,
|
||||
"Summer Mist" : SummerMist
|
||||
}
|
||||
return weathers_dic
|
||||
|
||||
|
|
Loading…
Reference in a new issue