diff --git a/games.py b/games.py index 5cbc3a4..0395646 100644 --- a/games.py +++ b/games.py @@ -285,18 +285,18 @@ class game(object): outcome["ishit"] = False fc_flag = False if roll["hitnum"] < -1.5: - outcome["text"] = random.choice([appearance_outcomes.strikeoutlooking, appearance_outcomes.strikeoutswinging]) + outcome["outcome"] = random.choice([appearance_outcomes.strikeoutlooking, appearance_outcomes.strikeoutswinging]) elif roll["hitnum"] < 1: - outcome["text"] = appearance_outcomes.groundout + outcome["outcome"] = appearance_outcomes.groundout outcome["defender"] = defender elif roll["hitnum"] < 4: - outcome["text"] = appearance_outcomes.flyout + outcome["outcome"] = appearance_outcomes.flyout outcome["defender"] = defender else: - outcome["text"] = appearance_outcomes.walk + outcome["outcome"] = appearance_outcomes.walk if self.bases[1] is not None and roll["hitnum"] < -2 and self.outs != 2: - outcome["text"] = appearance_outcomes.doubleplay + outcome["outcome"] = appearance_outcomes.doubleplay outcome["defender"] = "" #for base in self.bases.values(): @@ -313,7 +313,7 @@ class game(object): if self.outs < 2 and len(runners) > 1: #fielder's choice replaces not great groundouts if any forceouts are present def_stat = random_star_gen("defense_stars", defender) if -1.5 <= roll["hitnum"] and roll["hitnum"] < -0.5: #poorly hit groundouts - outcome["text"] = appearance_outcomes.fielderschoice + outcome["outcome"] = appearance_outcomes.fielderschoice outcome["defender"] = "" if 2.5 <= roll["hitnum"] and self.outs < 2: #well hit flyouts can lead to sacrifice flies/advanced runners @@ -322,16 +322,16 @@ class game(object): else: outcome["ishit"] = True if roll["hitnum"] < 1: - outcome["text"] = appearance_outcomes.single + outcome["outcome"] = appearance_outcomes.single elif roll["hitnum"] < 2.85 or "error" in outcome.keys(): - outcome["text"] = appearance_outcomes.double + outcome["outcome"] = appearance_outcomes.double elif roll["hitnum"] < 3.1: - outcome["text"] = appearance_outcomes.triple + outcome["outcome"] = appearance_outcomes.triple else: if self.bases[1] is not None and self.bases[2] is not None and self.bases[3] is not None: - outcome["text"] = appearance_outcomes.grandslam + outcome["outcome"] = appearance_outcomes.grandslam else: - outcome["text"] = appearance_outcomes.homerun + outcome["outcome"] = appearance_outcomes.homerun return outcome def thievery_attempts(self): #returns either false or "at-bat" outcome @@ -391,7 +391,7 @@ class game(object): def baserunner_check(self, defender, outcome): def_stat = random_star_gen("defense_stars", defender) - if outcome["text"] == appearance_outcomes.homerun or outcome["text"] == appearance_outcomes.grandslam: + if outcome["outcome"] == appearance_outcomes.homerun or outcome["outcome"] == appearance_outcomes.grandslam: runs = 1 for base in self.bases.values(): if base is not None: @@ -407,7 +407,7 @@ class game(object): elif "advance" in outcome.keys(): runs = 0 if self.bases[3] is not None: - outcome["text"] = appearance_outcomes.sacrifice + outcome["outcome"] = appearance_outcomes.sacrifice self.get_batter().game_stats["sacrifices"] += 1 self.bases[3] = None runs = 1 @@ -418,10 +418,11 @@ class game(object): self.bases[2] = None return runs - elif outcome["text"] == appearance_outcomes.fielderschoice: + elif outcome["outcome"] == appearance_outcomes.fielderschoice: furthest_base, runner = outcome["runners"].pop() #get furthest baserunner self.bases[furthest_base] = None outcome["fc_out"] = (runner.name, base_string(furthest_base+1)) #runner thrown out + outcome["base"] = furthest_base+1 for index in range(0,len(outcome["runners"])): base, this_runner = outcome["runners"].pop() self.bases[base+1] = this_runner #includes batter, at base 0 @@ -430,20 +431,20 @@ class game(object): return 1 return 0 - elif outcome["text"] == appearance_outcomes.groundout or outcome["text"] == appearance_outcomes.doubleplay: + elif outcome["outcome"] == appearance_outcomes.groundout or outcome["outcome"] == appearance_outcomes.doubleplay: runs = 0 if self.bases[3] is not None: runs += 1 self.bases[3] = None if self.bases[2] is not None: run_roll = random.gauss(2*math.erf((random_star_gen("baserunning_stars", self.bases[2])-def_stat)/4)-1,3) - if run_roll > 1.5 or outcome["text"] == appearance_outcomes.doubleplay: #double play gives them time to run, guaranteed + if run_roll > 1.5 or outcome["outcome"] == appearance_outcomes.doubleplay: #double play gives them time to run, guaranteed self.bases[3] = self.bases[2] self.bases[2] = None if self.bases[1] is not None: #double plays set this to None before this call run_roll = random.gauss(2*math.erf((random_star_gen("baserunning_stars", self.bases[1])-def_stat)/4)-1,3) if run_roll < 2 or self.bases[2] is not None: #if runner can't make it or if baserunner blocking on second, convert to fielder's choice - outcome["text"] == appearance_outcomes.fielderschoice + outcome["outcome"] == appearance_outcomes.fielderschoice runners = [(0,self.get_batter())] for base in range(1,4): if self.bases[base] == None: @@ -458,7 +459,7 @@ class game(object): elif outcome["ishit"]: runs = 0 - if outcome["text"] == appearance_outcomes.single: + if outcome["outcome"] == appearance_outcomes.single: if self.bases[3] is not None: runs += 1 self.bases[3] = None @@ -483,7 +484,7 @@ class game(object): self.bases[1] = self.get_batter() return runs - elif outcome["text"] == appearance_outcomes.double: + elif outcome["outcome"] == appearance_outcomes.double: runs = 0 if self.bases[3] is not None: runs += 1 @@ -503,7 +504,7 @@ class game(object): return runs - elif outcome["text"] == appearance_outcomes.triple: + elif outcome["outcome"] == appearance_outcomes.triple: runs = 0 for basenum in self.bases.keys(): if self.bases[basenum] is not None: @@ -516,50 +517,60 @@ class game(object): def batterup(self): scores_to_add = 0 - result = self.at_bat() + if "twopart" not in self.last_update[0]: + result = self.at_bat() + self.weather.activate(self, result) # possibly modify result in-place - self.weather.activate(self, result) # possibly modify result in-place - self.voice.activate(self.last_update[0], result) - - if "text_only" in result or "twopart" in result: - return (result, 0) + if "text_only" in result: + return (result, 0) - if self.top_of_inning: - offense_team = self.teams["away"] - defense_team = self.teams["home"] + if self.top_of_inning: + offense_team = self.teams["away"] + defense_team = self.teams["home"] + else: + offense_team = self.teams["home"] + defense_team = self.teams["away"] + + + defenders = defense_team.lineup.copy() + defenders.append(defense_team.pitcher) + defender = random.choice(defenders) #pitcher can field outs now :3 + result["defender"] = defender + result["defense_team"] = defense_team + result["offense_team"] = offense_team + + text_list = getattr(self.voice, result["outcome"].name) + voice_index = random.randrange(0, len(text_list)) + result["voiceindex"] = voice_index else: - offense_team = self.teams["home"] - defense_team = self.teams["away"] + result = {} + self.voice.activate(self.last_update[0], result, self) - defenders = defense_team.lineup.copy() - defenders.append(defense_team.pitcher) - defender = random.choice(defenders) #pitcher can field outs now :3 - result["defender"] = defender - result["defense_team"] = defense_team - result["offense_team"] = offense_team + if "twopart" in result: + return (result, 0) if result["ishit"]: #if batter gets a hit: self.get_batter().game_stats["hits"] += 1 self.get_pitcher().game_stats["hits_allowed"] += 1 - if result["text"] == appearance_outcomes.single: + if result["outcome"] == appearance_outcomes.single: self.get_batter().game_stats["total_bases"] += 1 - elif result["text"] == appearance_outcomes.double: + elif result["outcome"] == appearance_outcomes.double: self.get_batter().game_stats["total_bases"] += 2 - elif result["text"] == appearance_outcomes.triple: + elif result["outcome"] == appearance_outcomes.triple: self.get_batter().game_stats["total_bases"] += 3 - elif result["text"] == appearance_outcomes.homerun or result["text"] == appearance_outcomes.grandslam: + elif result["outcome"] == appearance_outcomes.homerun or result["outcome"] == appearance_outcomes.grandslam: self.get_batter().game_stats["total_bases"] += 4 self.get_batter().game_stats["home_runs"] += 1 - scores_to_add += self.baserunner_check(defender, result) + scores_to_add += self.baserunner_check(result["defender"], result) else: #batter did not get a hit - if result["text"] == appearance_outcomes.walk: + if result["outcome"] == appearance_outcomes.walk: walkers = [(0,self.get_batter())] for base in range(1,4): if self.bases[base] == None: @@ -576,7 +587,7 @@ class game(object): self.get_batter().game_stats["walks_taken"] += 1 self.get_pitcher().game_stats["walks_allowed"] += 1 - elif result["text"] == appearance_outcomes.doubleplay: + elif result["outcome"] == appearance_outcomes.doubleplay: self.get_pitcher().game_stats["outs_pitched"] += 2 self.outs += 2 self.bases[1] = None @@ -584,11 +595,11 @@ class game(object): scores_to_add += self.baserunner_check(defender, result) self.get_batter().game_stats["rbis"] -= scores_to_add #remove the fake rbi from the player in advance - elif result["text"] == appearance_outcomes.fielderschoice or result["text"] == appearance_outcomes.groundout: + elif result["outcome"] == appearance_outcomes.fielderschoice or result["outcome"] == appearance_outcomes.groundout: self.get_pitcher().game_stats["outs_pitched"] += 1 self.outs += 1 if self.outs < 3: - scores_to_add += self.baserunner_check(defender, result) + scores_to_add += self.baserunner_check(result["defender"], result) elif "advance" in result.keys(): self.get_pitcher().game_stats["outs_pitched"] += 1 @@ -598,7 +609,7 @@ class game(object): self.get_batter().game_stats["sacrifices"] += 1 scores_to_add += self.baserunner_check(defender, result) - elif result["text"] == appearance_outcomes.strikeoutlooking or result["text"] == appearance_outcomes.strikeoutswinging: + elif result["outcome"] == appearance_outcomes.strikeoutlooking or result["outcome"] == appearance_outcomes.strikeoutswinging: self.get_pitcher().game_stats["outs_pitched"] += 1 self.outs += 1 self.get_batter().game_stats["strikeouts_taken"] += 1 @@ -609,14 +620,17 @@ class game(object): self.outs += 1 self.get_batter().game_stats["plate_appearances"] += 1 + + if "add_base" in result: + result["update_text"] = result["update_text"] % base_string(result["base"]) if self.outs < 3: - offense_team.score += scores_to_add #only add points if inning isn't over + result["offense_team"].score += scores_to_add #only add points if inning isn't over else: scores_to_add = 0 self.get_batter().game_stats["rbis"] += scores_to_add self.get_pitcher().game_stats["runs_allowed"] += scores_to_add - offense_team.lineup_position += 1 #put next batter up + result["offense_team"].lineup_position += 1 #put next batter up self.choose_next_batter() if self.outs >= 3: self.flip_inning() diff --git a/gametext.py b/gametext.py index 4d2101f..c5c4347 100644 --- a/gametext.py +++ b/gametext.py @@ -43,33 +43,34 @@ class game_strings_base(object): diff_formats = {fielderschoice: ("defender", "base_string")} no_formats = [strikeoutlooking, strikeoutswinging, doubleplay, walk, single, double, triple, homerun, grandslam] - def activate(self, lastupdate, currentupdate): + def activate(self, lastupdate, currentupdate, game): #try: - if "text" in lastupdate and self.check_for_twopart(getattr(self, lastupdate["text"].name)[lastupdate["voiceindex"]]): - currentupdate.clear() - currentupdate.update({ - "text": getattr(self, lastupdate["text"].name)[lastupdate["text_index"][1]], - "twopart": True, - 'defender': lastupdate['defender'], - 'base': lastupdate['base'], - 'batter': lastupdate['batter'], - 'runner': lastupdate['runner'], - 'defense_team': lastupdate['defense_team'], - 'offense_team': lastupdate['offense_team'] - }) - #except: + if "twopart" in lastupdate: + for key, value in lastupdate.items(): + if key != "twopart": + currentupdate[key] = value + currentupdate["displaytext"] = self.format_gamestring(getattr(self, currentupdate["outcome"].name)[currentupdate["voiceindex"]][1], currentupdate) + + elif "outcome" in currentupdate: + if self.check_for_twopart(getattr(self, currentupdate["outcome"].name)[currentupdate["voiceindex"]]): + currentupdate.update({ + "twopart": True, + "displaytext": f"{currentupdate['batter']} {self.format_gamestring(getattr(self, currentupdate['outcome'].name)[currentupdate['voiceindex']][0], currentupdate)}" + }) + else: + currentupdate["displaytext"] = f"{currentupdate['batter']} {self.format_gamestring(getattr(self, currentupdate['outcome'].name)[currentupdate['voiceindex']], currentupdate)}" #pass def check_for_twopart(self, gamestring): return gamestring in self.twoparts - def format_gamestring(self, gamestring, game): + def format_gamestring(self, gamestring, update): if gamestring in self.no_formats: return gamestring elif gamestring in self.diff_formats: - return gamestring.format(*parse_formats(self.diff_formats[gamestring], game)) + return gamestring.format(*parse_formats(self.diff_formats[gamestring], update)) else: - return gamestring.format(*parse_formats(self.default_format, game)) + return gamestring.format(*parse_formats(self.default_format, update)) class TheGoddesses(game_strings_base): @@ -117,10 +118,10 @@ class TheGoddesses(game_strings_base): "hits a soft line drive over the infield, and makes it to first as it lands in the grass for a single.", "shoots a comebacker right over second base and pulls into first safely, racking up a base hit."] - double = "hits a double!" - triple = "hits a triple!" - homerun = "hits a dinger!" - grandslam = "hits a grand slam!" + double = ["hits a double!"] + triple = ["hits a triple!"] + homerun = ["hits a dinger!"] + grandslam = ["hits a grand slam!"] diff_formats = {groundout[3][1] : ("batter",), flyout[0][1]: ("batter",), flyout[2][1]: ("defender", "batter"), @@ -132,21 +133,22 @@ class TheGoddesses(game_strings_base): twoparts = [groundout[1], groundout[3], flyout[0], flyout[2], flyout[4], walk[2], single[0], sacrifice[0]] -def parse_formats(format_tuple, game): +def parse_formats(format_tuple, update): out_list = [] for string in format_tuple: if string == "defender": - out_list.append(game.last_update[0]['defender'].name) + out_list.append(update['defender'].name) elif string == "base_string": - out_list.append(base_string(game.last_update[0]['base'])) + update["add_base"] = True + out_list.append("%s") elif string == "batter": - out_list.append(game.last_update[0]['batter'].name) + out_list.append(update['batter'].name) elif string == "fc_out" or string == "runner": - out_list.append(game.last_update[0]['runner'].name) + out_list.append(update['runner'].name) elif string == "defense_team": - out_list.append(game.last_update[0]['defense_team'].name) + out_list.append(update['defense_team'].name) elif string == "offense_team": - out_list.append(game.last_update[0]['offense_team'].name) + out_list.append(update['offense_team'].name) return tuple(out_list) def base_string(base): diff --git a/main_controller.py b/main_controller.py index f2e59ca..8885288 100644 --- a/main_controller.py +++ b/main_controller.py @@ -3,7 +3,6 @@ from leagues import league_structure from league_storage import league_exists from flask import Flask, url_for, Response, render_template, request, jsonify, send_from_directory, abort from flask_socketio import SocketIO, emit -from random import randrange import database as db app = Flask("the-prestige", static_folder='simmadome/build/', subdomain_matching=True) @@ -199,8 +198,10 @@ def update_loop(): state["update_emoji"] = this_game.weather.emoji elif "ishit" in this_game.last_update[0].keys() and this_game.last_update[0]["ishit"]: state["update_emoji"] = "🏏" - elif "text" in this_game.last_update[0].keys() and this_game.last_update[0]["text"] == gametext.appearance_outcomes.walk: + elif "outcome" in this_game.last_update[0].keys() and this_game.last_update[0]["outcome"] == gametext.appearance_outcomes.walk: state["update_emoji"] = "👟" + elif "twopart" in this_game.last_update[0].keys(): + state["update_emoji"] = "💬" else: state["update_emoji"] = "🗞" @@ -215,29 +216,13 @@ def update_loop(): elif "text_only" in this_game.last_update[0].keys(): #this handles many weather messages state["update_text"] = this_game.last_update[0]["text"] else: - updatestring = "" - punc = "" - if this_game.last_update[0]["defender"] != "": - punc = ". " - - if "fc_out" in this_game.last_update[0].keys(): - name, out_at_base_string = this_game.last_update[0]['fc_out'] - updatestring = f"{this_game.last_update[0]['batter']} {this_game.last_update[0]['text'].value.format(name, out_at_base_string)} {this_game.last_update[0]['defender']}{punc}" - else: - text_list = getattr(this_game.voice, this_game.last_update[0]["text"].name) - voice_index = randrange(0, len(text_list)) - updatestring = text_list[voice_index] - this_game.last_update[0]["voiceindex"] = voice_index - if this_game.voice.check_for_twopart(updatestring): - updatestring = updatestring[0] - this_game.last_update[0]["twopart"] = True - updatestring = this_game.voice.format_gamestring(updatestring, this_game) + updatestring = this_game.last_update[0]["displaytext"] if this_game.last_update[1] > 0: - updatestring += f"{this_game.last_update[1]} runs scored!" + updatestring += f" {this_game.last_update[1]} runs scored!" - state["update_text"] = f"{this_game.last_update[0]['batter']} {updatestring}" + state["update_text"] = f"{updatestring}" this_game.weather.modify_atbat_message(this_game, state) diff --git a/weather.py b/weather.py index 7c28fbb..0656e0f 100644 --- a/weather.py +++ b/weather.py @@ -72,7 +72,7 @@ class SlightTailwind(Weather): def activate(self, game, result): - if "mulligan" not in game.last_update[0].keys() and not result["ishit"] and result["text"] != appearance_outcomes.walk: + if "mulligan" not in game.last_update[0].keys() and not result["ishit"] and result["outcome"] != appearance_outcomes.walk: mulligan_roll_target = -((((game.get_batter().stlats["batting_stars"])-5)/6)**2)+1 if random.random() > mulligan_roll_target and game.get_batter().stlats["batting_stars"] <= 5: result.clear() @@ -90,7 +90,7 @@ class Starlight(Weather): def activate(self, game, result): - if (result["text"] == appearance_outcomes.homerun or result["text"] == appearance_outcomes.grandslam): + if (result["outcome"] == appearance_outcomes.homerun or result["outcome"] == appearance_outcomes.grandslam): result["weather_message"] = True dinger_roll = random.random() if "dragon" in game.get_batter().name.lower(): @@ -190,7 +190,7 @@ class ThinnedVeil(Weather): def activate(self, game, result): if result["ishit"]: - if result["text"] == appearance_outcomes.homerun or result["text"] == appearance_outcomes.grandslam: + if result["outcome"] == appearance_outcomes.homerun or result["outcome"] == appearance_outcomes.grandslam: result["veil"] = True def modify_atbat_message(self, game, state):