diff --git a/.gitignore b/.gitignore
index 473c2b0..ce115fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -358,3 +358,4 @@ env
/data/leagues
/simmadome/build
/simmadome/.eslintcache
+/matteo_env/Lib/site-packages
diff --git a/games.py b/games.py
index a4f2a08..8371337 100644
--- a/games.py
+++ b/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,14 +705,18 @@ 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
- 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"]
- elif self.teams["away"].score == 16:
- this_xvi_team = self.teams["away"]
- 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)
+ 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"]
+ elif self.teams["away"].score == 16:
+ this_xvi_team = self.teams["away"]
+ 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)
diff --git a/gametext.py b/gametext.py
index 7e8146a..9958581 100644
--- a/gametext.py
+++ b/gametext.py
@@ -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
diff --git a/main_controller.py b/main_controller.py
index 95d4f82..2cf6db1 100644
--- a/main_controller.py
+++ b/main_controller.py
@@ -190,13 +190,17 @@ 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)
- this_game.weather.modify_top_of_inning_message(this_game, state)
+
elif state["update_pause"] != 1 and this_game.play_has_begun:
@@ -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)
\ No newline at end of file
+ time.sleep(3)
\ No newline at end of file
diff --git a/real_players.py b/real_players.py
new file mode 100644
index 0000000..c118231
--- /dev/null
+++ b/real_players.py
@@ -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
\ No newline at end of file
diff --git a/the-prestige.pyproj b/the-prestige.pyproj
index e9f0b7a..ce3561e 100644
--- a/the-prestige.pyproj
+++ b/the-prestige.pyproj
@@ -46,6 +46,9 @@
Code
+
+ Code
+
diff --git a/the_draft.py b/the_draft.py
index 15504c9..13771d2 100644
--- a/the_draft.py
+++ b/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):
"""
diff --git a/the_prestige.py b/the_prestige.py
index 9728df8..265fe2f 100644
--- a/the_prestige.py
+++ b/the_prestige.py
@@ -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,10 +646,12 @@ class StartDraftCommand(Command):
draftsize = 20
minsize = 4
pitchers = 3
+ ono_ratio = 0.5
+ timeout = 120
for flag in flags:
try:
- if flag[0] == "t":
+ if flag[0] == "t":
teamsize = int(flag[1])
elif flag[0] == "d":
draftsize = int(flag[1])
@@ -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])
diff --git a/weather.py b/weather.py
index b4cf74e..1049cd7 100644
--- a/weather.py
+++ b/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