Initial commit

This commit is contained in:
Cal Corum 2023-02-19 21:34:38 -06:00 committed by GitHub
parent 16a6618549
commit 0c638ae6a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 14456 additions and 1379 deletions

469
ai_manager.py Normal file
View File

@ -0,0 +1,469 @@
import copy
import logging
import random
import pydantic
from db_calls_gameplay import StratPlay, get_team_lineups
from db_calls import db_get, db_post
import db_calls_card_creation as scouting
from peewee import *
from typing import Optional, Literal
db = SqliteDatabase(
'storage/ai-database.db',
pragmas={
'journal_mode': 'wal',
'cache_size': -1 * 64000,
'synchronous': 0
}
)
class BaseModel(Model):
class Meta:
database = db
class Lineup(BaseModel):
team_id = IntegerField()
game_level = CharField() # 'minor', 'major', 'hof'
vs_hand = CharField() # 'left', 'right'
bat_one_card = IntegerField()
bat_one_pos = CharField()
bat_two_card = IntegerField()
bat_two_pos = CharField()
bat_three_card = IntegerField()
bat_three_pos = CharField()
bat_four_card = IntegerField()
bat_four_pos = CharField()
bat_five_card = IntegerField()
bat_five_pos = CharField()
bat_six_card = IntegerField()
bat_six_pos = CharField()
bat_seven_card = IntegerField()
bat_seven_pos = CharField()
bat_eight_card = IntegerField()
bat_eight_pos = CharField()
bat_nine_card = IntegerField()
bat_nine_pos = CharField()
class Rotation(BaseModel):
team_id = IntegerField()
game_level = CharField()
sp_one_card = IntegerField()
sp_two_card = IntegerField()
sp_three_card = IntegerField()
sp_four_card = IntegerField()
sp_five_card = IntegerField()
class Bullpen(BaseModel):
team_id = IntegerField()
game_level = CharField() # 'minor', 'major', 'hof'
vs_hand = CharField() # 'left', 'right'
# def grade_player()
def batter_grading(vs_hand, rg_data):
raw_bat = (rg_data[f'contact-{vs_hand}'] + rg_data[f'power-{vs_hand}'] +
min(rg_data[f'contact-{vs_hand}'], rg_data[f'power-{vs_hand}'])) / 3
other_metrics = [
rg_data['vision'], rg_data['speed'], rg_data['stealing'], rg_data['reaction'], rg_data['arm'],
rg_data['fielding']
]
blended_rating = sum(sorted(other_metrics, reverse=True)[:4], raw_bat * 4) / 8
return {
'overall': rg_data['overall'],
'raw-bat': raw_bat,
'blended': blended_rating
}
def get_or_create_card(player: dict, team: dict) -> int:
# get player card; create one if none found
z = 0
card_id = None
while z < 2 and card_id is None:
z += 1
c_query = db_get('cards',
params=[('team_id', team['id']), ('player_id', player['player_id'])])
if c_query['count'] > 0:
card_id = c_query['cards'][0]['id']
else:
db_post(
'cards',
payload={'cards': [
{'player_id': player['player_id'], 'team_id': team['id'], 'pack_id': 1}
]}
)
if card_id is None:
logging.error(f'Could not create card for {player["p_name"]} on the {team["lname"]}')
return card_id
# First attempt - pulls ratings guide info
def build_lineup_graded(team_object: dict, vs_hand: str, league_name: str, num_innings: int, batter_rg):
in_lineup = [] # player ids for quick checking
players = {
'c': [],
'1b': [],
'2b': [],
'3b': [],
'ss': [],
'lf': [],
'cf': [],
'rf': [],
'dh': []
}
# Get all eligible players
try:
all_players = db_get(
endpoint='players',
params=[('mlbclub', team_object['lname']), ('pos_exclude', 'RP'), ('inc_dex', False)],
timeout=10
)['players']
except ConnectionError as e:
raise ConnectionError(f'Error pulling players for the {team_object["lname"]}. Cal help plz.')
# Grade players and add to position lists
for x in all_players:
if x['pos_1'] not in ['SP', 'RP']:
this_guy = copy.deepcopy(x)
rg_data = next(x for x in batter_rg if x['player_id'] == this_guy['player_id'])
grading = batter_grading(vs_hand, rg_data)
logging.info(f'player: {this_guy} / grading: {grading}')
this_guy['overall'] = grading['overall']
this_guy['raw-bat'] = grading['raw-bat']
this_guy['blended'] = grading['blended']
players['dh'].append(this_guy)
if 'C' in [this_guy['pos_1'], this_guy['pos_2'], this_guy['pos_3'], this_guy['pos_4'], this_guy['pos_5'],
this_guy['pos_6'], this_guy['pos_7'], this_guy['pos_8']]:
players['c'].append(this_guy)
if '1B' in [this_guy['pos_1'], this_guy['pos_2'], this_guy['pos_3'], this_guy['pos_4'], this_guy['pos_5'],
this_guy['pos_6'], this_guy['pos_7'], this_guy['pos_8']]:
players['1b'].append(this_guy)
if '2B' in [this_guy['pos_1'], this_guy['pos_2'], this_guy['pos_3'], this_guy['pos_4'], this_guy['pos_5'],
this_guy['pos_6'], this_guy['pos_7'], this_guy['pos_8']]:
players['2b'].append(this_guy)
if '3B' in [this_guy['pos_1'], this_guy['pos_2'], this_guy['pos_3'], this_guy['pos_4'], this_guy['pos_5'],
this_guy['pos_6'], this_guy['pos_7'], this_guy['pos_8']]:
players['3b'].append(this_guy)
if 'SS' in [this_guy['pos_1'], this_guy['pos_2'], this_guy['pos_3'], this_guy['pos_4'], this_guy['pos_5'],
this_guy['pos_6'], this_guy['pos_7'], this_guy['pos_8']]:
players['ss'].append(this_guy)
if 'LF' in [this_guy['pos_1'], this_guy['pos_2'], this_guy['pos_3'], this_guy['pos_4'], this_guy['pos_5'],
this_guy['pos_6'], this_guy['pos_7'], this_guy['pos_8']]:
players['lf'].append(this_guy)
if 'CF' in [this_guy['pos_1'], this_guy['pos_2'], this_guy['pos_3'], this_guy['pos_4'], this_guy['pos_5'],
this_guy['pos_6'], this_guy['pos_7'], this_guy['pos_8']]:
players['cf'].append(this_guy)
if 'RF' in [this_guy['pos_1'], this_guy['pos_2'], this_guy['pos_3'], this_guy['pos_4'], this_guy['pos_5'],
this_guy['pos_6'], this_guy['pos_7'], this_guy['pos_8']]:
players['rf'].append(this_guy)
# Select players for lineup
while len(players) > 0:
# Sort players dict by position with fewest eligible players
this_pass_data = sorted(players.items(), key=lambda item: len(item[1]))
logging.info(f'this_pass_data: {this_pass_data}')
# Pull one tuple ('<position>', [<player objects>])
this_pos_data = this_pass_data[0]
logging.info(f'this_pos_data: {this_pos_data}')
# Sort players at this position by blended rating (raw-bat for DH)
if this_pos_data[0] == 'dh':
this_pos = sorted(this_pos_data[1], key=lambda item: item['raw-bat'], reverse=True)
else:
this_pos = sorted(this_pos_data[1], key=lambda item: item['blended'], reverse=True)
logging.info(f'this_pos: {this_pos}')
# Add top player to the lineup
in_lineup.append({'position': copy.deepcopy(this_pos_data[0].upper()), 'player': copy.deepcopy(this_pos[0])})
logging.info(f'adding player: {this_pos[0]}')
logging.info(f'deleting position: {this_pos_data[0]}')
# Remove this position from consideration
del players[this_pos_data[0]]
for key in players:
for x in players[key]:
# Remove duplicate players (even across cardsets) once in lineup
if x['strat_code'] == this_pos[0]['strat_code']:
players[key].remove(x)
# Set batting order as list of lists: [ ['<pos>', <player_id>], ... ]
batting_order = []
return batting_order
def build_lineup(team_object: dict, game_id: int, league_name: str, vs_hand: str = 'r') -> list:
players = {
'C': None,
'1B': None,
'2B': None,
'3B': None,
'SS': None,
'LF': None,
'CF': None,
'RF': None,
'DH': None
}
p_names = []
# Pull players sorted by current cost
try:
all_players = db_get(
endpoint='players',
params=[
('mlbclub', team_object['lname']), ('pos_include', 'C'), ('pos_include', '1B'), ('pos_include', '2B'),
('pos_include', '3B'), ('pos_include', 'SS'), ('pos_include', 'LF'), ('pos_include', 'CF'),
('pos_include', 'RF'), ('pos_include', 'DH'), ('cardset_id_exclude', 2), ('cardset_id_exclude', 4),
('inc_dex', False), ('sort_by', 'cost-desc')
],
timeout=10
)['players']
except ConnectionError as e:
raise ConnectionError(f'Error pulling batters for the {team_object["lname"]}. Cal help plz.')
logging.info(f'build_lineup - eligible batter count: {len(all_players)}')
# Choose starting nine & position
# In order of cost:
# Try to add to pos_1; if unavailable, try remaining pos; if unavailable, add to DH
# If all pos unavailable; note player's pos_1 and check if incumbent can move; if so, check for new incumbent
# and recurse
# If not possible, pass player and continue
for guy in all_players:
placed = False
if guy['p_name'] not in p_names:
for pos in [
guy['pos_1'], guy['pos_2'], guy['pos_3'], guy['pos_4'], guy['pos_5'], guy['pos_6'], guy['pos_7'],
guy['pos_8']
]:
if pos is None or pos in ['SP', 'RP', 'CP']:
break
elif players[pos] is None:
players[pos] = guy
p_names.append(guy["p_name"])
placed = True
break
if not placed:
if players['DH'] is None:
players['DH'] = guy
p_names.append(guy["p_name"])
else:
logging.info(f'build_lineup - could not place {guy["p_name"]} in {team_object["sname"]} lineup')
else:
logging.info(f'build_lineup - {guy["p_name"]} already in lineup')
if None in players.values():
bad_pos = {x for x in players if players[x] is None}
raise ValueError(f'Could not find a {bad_pos} for the {team_object["sname"]}')
logging.info(f'build_lineup - {players}')
# Sort players into lineup
# Pseudo-random? Patterns? Something to mix up lineups
# 421356789 or [123 (rand)][456 (rand)][789 (rand)] (optional: chance to flip 3/4 and 6/7)
lineups = []
# [ (<pos>, <player_obj>), (<pos>, <player_obj>), etc. ]
sorted_players = sorted(players.items(), key=lambda x: x[1]['cost'], reverse=True)
grp_1 = sorted_players[:3]
grp_2 = sorted_players[3:6]
grp_3 = sorted_players[6:]
random.shuffle(grp_1)
random.shuffle(grp_2)
random.shuffle(grp_3)
i = 1
for x in [grp_1, grp_2, grp_3]:
for y in x:
# get player card; create one if none found
z = 0
card_id = None
while z < 2 and card_id is None:
z += 1
c_query = db_get('cards', params=[('team_id', team_object['id']), ('player_id', y[1]['player_id'])])
if c_query['count'] > 0:
card_id = c_query['cards'][0]['id']
else:
db_post(
'cards',
payload={'cards': [
{'player_id': y[1]['player_id'], 'team_id': team_object['id'], 'pack_id': 1}
]}
)
if card_id is None:
logging.error(f'Could not create card for {y[1]["p_name"]} on the {team_object["lname"]}')
lineups.append({
'game_id': game_id,
'team_id': team_object['id'],
'player_id': y[1]['player_id'],
'card_id': card_id,
'position': y[0],
'batting_order': i,
'after_play': 0
})
i += 1
logging.info(f'build_lineup - final lineup: {lineups}')
return lineups
def get_starting_pitcher(team_object: dict, game_id: int, is_home: bool, league_name: str = None) -> dict:
# Pull starters sorted by current cost
try:
pitchers = db_get(
endpoint='players',
params=[
('mlbclub', team_object['lname']), ('pos_include', 'SP'), ('pos_exclude', 'RP'),
('cardset_id_exclude', 2), ('cardset_id_exclude', 4), ('inc_dex', False), ('sort_by', 'cost-desc'),
('limit', 5)
],
timeout=10
)
except ConnectionError as e:
logging.error(f'Could not get pitchers for {team_object["lname"]}: {e}')
raise ConnectionError(f'Error pulling starting pitchers for the {team_object["lname"]}. Cal help plz.')
logging.info(f'build_lineup - eligible starting pitcher count: {len(pitchers)}')
if pitchers['count'] == 0:
raise DatabaseError(f'Could not find any SP for {team_object["abbrev"]}. Seems like a Cal issue.')
d_100 = random.randint(1, 100)
starter = None
if is_home:
if d_100 <= 30:
starter = pitchers['players'][0]
elif d_100 <= 55 and pitchers['count'] > 1:
starter = pitchers['players'][1]
elif d_100 <= 75 and pitchers['count'] > 2:
starter = pitchers['players'][2]
elif d_100 <= 90 and pitchers['count'] > 3:
starter = pitchers['players'][3]
elif pitchers['count'] == 5:
starter = pitchers['players'][4]
else:
starter = pitchers['players'][0]
else:
if d_100 <= 50:
starter = pitchers['players'][0]
elif d_100 <= 75 and pitchers['count'] > 1:
starter = pitchers['players'][1]
elif d_100 <= 85 and pitchers['count'] > 2:
starter = pitchers['players'][2]
elif d_100 <= 95 and pitchers['count'] > 3:
starter = pitchers['players'][3]
elif pitchers['count'] == 5:
starter = pitchers['players'][4]
else:
starter = pitchers['players'][0]
# get player card; create one if none found
z = 0
card_id = None
while z < 2 and card_id is None:
z += 1
c_query = db_get('cards', params=[('team_id', team_object['id']), ('player_id', starter['player_id'])])
if c_query['count'] > 0:
card_id = c_query['cards'][0]['id']
else:
db_post(
'cards',
payload={'cards': [
{'player_id': starter['player_id'], 'team_id': team_object['id'], 'pack_id': 1}
]}
)
if card_id is None:
logging.error(f'Could not create card for {starter["p_name"]} on the {team_object["lname"]}')
return {
'game_id': game_id,
'team_id': team_object['id'],
'player_id': starter['player_id'],
'card_id': card_id,
'position': 'P',
'batting_order': 10,
'after_play': 0
}
def get_relief_pitcher(this_play: StratPlay, ai_team: dict, used_pitchers: list, league_name: str = None) -> dict:
used_codes = [db_get('cards', object_id=x.card_id)["player"]["strat_code"] for x in used_pitchers]
logging.info(f'get_rp - used_pitchers: {used_codes}')
reliever = None
attempts = 0
while reliever is None:
attempts += 1
if attempts > 3:
raise ValueError(f'Could not find a reliever for the {ai_team["sname"]}. Cal plz.')
# Pull relievers sorted by current cost
params = [
('mlbclub', ai_team['lname']), ('pos_include', 'RP'), ('cardset_id_exclude', 2), ('cardset_id_exclude', 4),
('inc_dex', False), ('sort_by', 'cost-desc')
]
alt_flag = False
if attempts == 1:
# Try to get long man
if this_play.inning_num < 6:
logging.info(f'get_rp - game {this_play.game.id} try for long man')
params.append(('pos_include', 'SP'))
alt_flag = True
# Try to get closer
elif this_play.inning_num > 8:
if (this_play.inning_half == 'top' and this_play.home_score >= this_play.away_score) or \
(this_play.inning_half == 'bot' and this_play.away_score >= this_play.home_score):
logging.info(f'get_rp - game {this_play.game.id} try for closer')
params.append(('pos_include', 'CP'))
alt_flag = True
else:
params.append(('pos_exclude', 'CP'))
# Try to exclude long men
elif attempts == 1:
logging.info(f'get_rp - game {this_play.game.id} try to exclude long men')
params.append(('pos_exclude', 'SP'))
try:
pitchers = db_get(
endpoint='players',
params=params,
timeout=10
)
except ConnectionError as e:
logging.error(f'Could not get pitchers for {ai_team["lname"]}: {e}')
raise ConnectionError(f'Error pulling starting pitchers for the {ai_team["lname"]}. Cal help plz.')
if pitchers['count'] > 0:
if alt_flag or this_play.inning_num > 9 or attempts > 2:
start = 0
else:
start = 9 - this_play.inning_num
for count, guy in enumerate(pitchers['players']):
if count >= start and guy['strat_code'] not in used_codes:
card_id = get_or_create_card(guy, ai_team)
return {
'game_id': this_play.game.id,
'team_id': ai_team['id'],
'player_id': guy['player_id'],
'card_id': card_id,
'position': 'P',
'batting_order': 10,
'after_play': this_play.play_num - 1
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3488
cogs/gameplay.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,19 @@
import datetime
import logging
import os
import discord import discord
from discord import Object
from discord.ext import commands from discord.ext import commands
from discord.ext.commands import Greedy, Context
from typing import Optional, Literal
date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}'
logging.basicConfig(
filename=f'logs/{date}.log',
format='%(asctime)s - %(levelname)s - %(message)s',
level=logging.WARNING
)
class Owner(commands.Cog): class Owner(commands.Cog):
@ -10,9 +24,8 @@ class Owner(commands.Cog):
@commands.is_owner() @commands.is_owner()
async def load(self, ctx, *, cog: str): async def load(self, ctx, *, cog: str):
try: try:
self.bot.load_extension(f'cogs.{cog}') await self.bot.load_extension(f'cogs.{cog}')
print(f'Loaded {cog}') logging.warning(f'Loaded {cog}')
print('------')
except Exception as e: except Exception as e:
await ctx.send(f'**ERROR:** {type(e).__name__} - {e}') await ctx.send(f'**ERROR:** {type(e).__name__} - {e}')
else: else:
@ -22,9 +35,8 @@ class Owner(commands.Cog):
@commands.is_owner() @commands.is_owner()
async def unload(self, ctx, *, cog: str): async def unload(self, ctx, *, cog: str):
try: try:
self.bot.unload_extension(f'cogs.{cog}') await self.bot.unload_extension(f'cogs.{cog}')
print(f'Unloaded {cog}') logging.warning(f'Unloaded {cog}')
print('------')
except Exception as e: except Exception as e:
await ctx.send(f'**ERROR:** {type(e).__name__} - {e}') await ctx.send(f'**ERROR:** {type(e).__name__} - {e}')
else: else:
@ -34,16 +46,86 @@ class Owner(commands.Cog):
@commands.is_owner() @commands.is_owner()
async def reload(self, ctx, *, cog: str): async def reload(self, ctx, *, cog: str):
try: try:
self.bot.unload_extension(f'cogs.{cog}') await self.bot.unload_extension(f'cogs.{cog}')
print(f'Unloaded {cog}') logging.warning(f'Unloaded {cog}')
self.bot.load_extension(f'cogs.{cog}') await self.bot.load_extension(f'cogs.{cog}')
print(f'Reloaded {cog}') logging.warning(f'Reloaded {cog}')
print('------')
except Exception as e: except Exception as e:
await ctx.send(f'**ERROR:** {type(e).__name__} - {e}') await ctx.send(f'**ERROR:** {type(e).__name__} - {e}')
else: else:
await ctx.send('**SUCCESS**') await ctx.send('**SUCCESS**')
@commands.command(hidden=True)
@commands.is_owner()
async def fullreset(self, ctx):
cogs = ['helpers', 'admins', 'economy', 'players']
def setup(bot): for x in cogs:
bot.add_cog(Owner(bot)) try:
await self.bot.unload_extension(f'cogs.{x}')
logging.warning(f'Unloaded {x}')
except Exception as e:
await ctx.send(f'Failed to unload **{x}**')
for x in cogs:
try:
await self.bot.load_extension(f'cogs.{x}')
logging.warning(f'Loaded {x}')
except Exception as e:
await ctx.send(f'Failed to load **{x}**')
await ctx.send('**SUCCESS**')
# @commands.command(name='sync', hidden=True)
# @commands.is_owner()
# async def sync_command(self, ctx, sync_type: str = 'local'):
# sync = None
# await ctx.send('I will try to sync slash commands...')
# try:
# if sync_type == 'global':
# sync = await self.bot.tree.sync()
# else:
# sync = await self.bot.tree.sync(guild=discord.Object(os.environ.get('GUILD_ID')))
# logging.warning(f'sync: {sync}')
# except Exception as e:
# logging.error(f'failed to sync: {e}')
#
# await ctx.send(f'Just ran the sync. Here is the output:\n{sync}')
@commands.command()
@commands.is_owner()
async def sync(self, ctx: Context, guilds: Greedy[Object], spec: Optional[Literal['~', "*"]] = None) -> None:
"""
!sync -> global sync
!sync ~ -> sync current guild
!sync * -> copies all global app commands to current guild and syncs
!sync id_1 id_2 -> syncs guilds with id 1 and 2
"""
if not guilds:
if spec == "~":
fmt = await ctx.bot.tree.sync(guild=ctx.guild)
elif spec == "*":
ctx.bot.tree.copy_global_to(guild=ctx.guild)
fmt = await ctx.bot.tree.sync(guild=ctx.guild)
else:
fmt = await ctx.bot.tree.sync()
await ctx.send(
f"Synced {len(fmt)} commands {'globally' if spec is None else 'to the current guild.'}"
)
return
fmt = 0
for guild in guilds:
try:
await ctx.bot.tree.sync(guild=guild)
except discord.HTTPException:
pass
else:
fmt += 1
await ctx.send(f"Synced the tree to {fmt}/{len(guilds)} guilds.")
async def setup(bot):
await bot.add_cog(Owner(bot))

File diff suppressed because it is too large Load Diff

161
db_calls.py Normal file
View File

@ -0,0 +1,161 @@
import requests
import logging
import json
import os
AUTH_TOKEN = {'Authorization': f'Bearer {os.environ.get("API_TOKEN")}'}
DB_URL = 'http://pd-database/api'
master_debug = True
alt_database = None
if alt_database == 'prod':
DB_URL = 'https://sombaseball.ddns.net/pd/api'
elif alt_database == 'local':
DB_URL = 'https://manticorum.ddns.net/pd/api'
def param_char(other_params):
if other_params:
return '&'
else:
return '?'
def get_req_url(endpoint: str, api_ver: int = 1, object_id: int = None, params: list = None):
req_url = f'{DB_URL}/v{api_ver}/{endpoint}{"/" if object_id is not None else ""}{object_id if object_id is not None else ""}'
if params:
other_params = False
for x in params:
req_url += f'{param_char(other_params)}{x[0]}={x[1]}'
other_params = True
return req_url
def db_get(endpoint: str, api_ver: int = 1, object_id: int = None, params: list = None, none_okay: bool = True,
timeout: int = 3):
req_url = get_req_url(endpoint, api_ver=api_ver, object_id=object_id, params=params)
log_string = f'get:\n{endpoint} id: {object_id} params: {params}'
logging.info(log_string) if master_debug else logging.debug(log_string)
try:
resp = requests.get(req_url, timeout=timeout)
except requests.ReadTimeout as e:
logging.error(f'Read Timeout: {e}')
raise ConnectionError(f'DB: The internet was a bit too slow for me to grab the data I needed. Please '
f'hang on a few extra seconds and try again.')
if resp.status_code == 200:
data = resp.json()
log_string = f'{data}'
if master_debug:
logging.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}')
else:
logging.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}')
return data
elif none_okay:
data = resp.json()
log_string = f'{data}'
if master_debug:
logging.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}')
else:
logging.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}')
return None
else:
logging.warning(resp.text)
raise ValueError(f'DB: {resp.text}')
def db_patch(endpoint: str, object_id: int, params: list, api_ver: int = 1, timeout: int = 3):
req_url = get_req_url(endpoint, api_ver=api_ver, object_id=object_id, params=params)
log_string = f'patch:\n{endpoint} {params}'
logging.info(log_string) if master_debug else logging.debug(log_string)
try:
resp = requests.patch(req_url, headers=AUTH_TOKEN, timeout=timeout)
except requests.ReadTimeout as e:
logging.error(f'Read Timeout: {e}')
raise ConnectionError(f'DB: The internet was a bit too slow for me to grab the data I needed. Please '
f'hang on a few extra seconds and try again.')
if resp.status_code == 200:
data = resp.json()
log_string = f'{data}'
if master_debug:
logging.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}')
else:
logging.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}')
return data
else:
logging.warning(resp.text)
raise ValueError(f'DB: {resp.text}')
def db_post(endpoint: str, api_ver: int = 1, payload: dict = None, timeout: int = 3):
req_url = get_req_url(endpoint, api_ver=api_ver)
log_string = f'post:\n{endpoint} payload: {payload}\ntype: {type(payload)}'
logging.info(log_string) if master_debug else logging.debug(log_string)
try:
resp = requests.post(req_url, json=payload, headers=AUTH_TOKEN, timeout=timeout)
except requests.ReadTimeout as e:
logging.error(f'Read Timeout: {e}')
raise ConnectionError(f'DB: The internet was a bit too slow for me to grab the data I needed. Please '
f'hang on a few extra seconds and try again.')
if resp.status_code == 200:
data = resp.json()
log_string = f'{data}'
if master_debug:
logging.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}')
else:
logging.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}')
return data
else:
logging.warning(resp.text)
raise ValueError(f'DB: {resp.text}')
def db_delete(endpoint: str, object_id: int, api_ver: int = 3):
req_url = get_req_url(endpoint, api_ver=api_ver, object_id=object_id)
log_string = f'delete:\n{endpoint} {object_id}'
logging.info(log_string) if master_debug else logging.debug(log_string)
try:
resp = requests.delete(req_url, headers=AUTH_TOKEN, timeout=3)
except requests.ReadTimeout as e:
logging.error(f'Read Timeout: {e}')
raise ConnectionError(f'DB: The internet was a bit too slow for me to grab the data I needed. Please '
f'hang on a few extra seconds and try again.')
if resp.status_code == 200:
data = resp.json()
log_string = f'{data}'
if master_debug:
logging.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}')
else:
logging.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}')
return True
else:
logging.warning(resp.text)
raise ValueError(f'DB: {resp.text}')
def get_team_by_abbrev(abbrev: str):
all_teams = db_get('teams', params=[('abbrev', abbrev)])
if not all_teams or not all_teams['count']:
return None
return all_teams['teams'][0]
def post_to_dex(player, team):
return db_post('paperdex', payload={'team_id': team['id'], 'player_id': player['id']})
def team_hash(team):
hash_string = f'{team["abbrev"]}{team["gmid"] / 123:.0f}'
return hash(hash_string)

2128
db_calls_gameplay.py Normal file

File diff suppressed because it is too large Load Diff

917
dice.py Normal file
View File

@ -0,0 +1,917 @@
import discord
import random
from helpers import INFIELD_X_CHART, OUTFIELD_X_CHART
def get_dice_embed(team: dict = None, embed_title: str = None):
if team:
embed = discord.Embed(
color=int(team["dice_color"], 16) if 'dice_color' in team else int(team["color"], 16)
)
else:
embed = discord.Embed(
color=int('0x000000', 16)
)
if embed_title:
embed.title = embed_title
return embed
def sa_fielding_roll(pos_code: str, team: dict) -> [discord.Embed]:
"""
Make a Super Advanced fielding check.
"""
d_twenty = random.randint(1, 20)
d_six_one = random.randint(1, 6)
d_six_two = random.randint(1, 6)
d_six_three = random.randint(1, 6)
error_dice = d_six_one + d_six_two + d_six_three
x_chart = None
error_chart = 'https://sombaseball.ddns.net/static/images/season04/error-'
symbol_link = None
range_note = None
error_note = None
error_note1 = None
error_note2 = None
if pos_code in ['1B', '2B', '3B', 'SS']:
x_chart = 'https://sombaseball.ddns.net/static/images/season04/range-infield.png'
symbol_link = 'https://docs.google.com/document/d/1p8Y2On0301C1yq4ktyPxE4lXxrIALYaF1vbW6RkRpII/edit' \
'#heading=h.qgqyxe5xb77m'
# Build range note
if d_twenty == 1:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'G3# SI1 ----SI2----\n' \
'```\n\n'
elif d_twenty == 2:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'G2# SI1 ----SI2----\n' \
'```\n\n'
elif d_twenty <= 4:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'G2# G3# SI1 --SI2--\n' \
'```\n\n'
elif d_twenty == 5:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'G1 --G3#-- SI1 SI2\n' \
'```\n\n'
elif d_twenty == 6:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'G1 G2# G3# SI1 SI2\n' \
'```\n\n'
elif d_twenty <= 8:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'G1 G2 --G3#-- SI1\n' \
'```\n\n'
elif d_twenty == 9:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'G1 G2 G3 --G3#--\n' \
'```\n\n'
elif d_twenty == 10:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G1--- G2 --G3#--\n' \
'```\n\n'
elif d_twenty <= 12:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G1--- G2 G3 G3#\n' \
'```\n\n'
elif d_twenty == 13:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G1--- G2 --G3---\n' \
'```\n\n'
elif d_twenty == 14:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G1--- --G2--- G3\n' \
'```\n\n'
elif d_twenty <= 16:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'----G1----- G2 G3\n' \
'```\n\n'
elif d_twenty == 17:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'------G1------- G3\n' \
'```\n\n'
elif d_twenty <= 19:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'------G1------- G2\n' \
'```\n\n'
elif d_twenty == 20:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--------G1---------\n' \
'```\n\n'
if pos_code == '1B':
error_chart += 'first-base.png'
if error_dice == 18:
error_note = '2-base error for e3 -> e12, e19 -> e28\n' \
'1-base error for e1, e2, e30'
elif error_dice == 17:
error_note = '2-base error for e13 -> e28\n' \
'1-base error for e1, e5, e8, e9, e29'
elif error_dice == 16:
error_note = '2-base error for e29, e30\n' \
'1-base error for e2, e8, e16, e19, e23'
elif error_dice == 15:
error_note = '1-base error for e3, e8, e10 -> e12, e20, e26, e30'
elif error_dice == 14:
error_note = '1-base error for e4, e5, e9, e15, e18, e22, e24 -> e28'
elif error_dice == 13:
error_note = '1-base error for e6, e13, e24, e26 -> e28, e30'
elif error_dice == 12:
error_note = '1-base error for e14 -> e18, e21 -> e26, e28 -> e30'
elif error_dice == 11:
error_note = '1-base error for e10, e13, e16 -> e20, e23 -> e25, e27 -> e30'
elif error_dice == 10:
error_note = '1-base error for e19 -> e21, e23, e29'
elif error_dice == 9:
error_note = '1-base error for e7, e12, e14, e21, e25, e26, e29'
elif error_dice == 8:
error_note = '1-base error for e11, e27'
elif error_dice == 7:
error_note = '1-base error for e9, e15, e22, e27, e28'
elif error_dice == 6:
error_note = '1-base error for e8, e11, e12, e17, e20'
elif error_dice == 5:
error_note = f'Rare play!\n\n' \
f'**G3**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**G2**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**G1**: {INFIELD_X_CHART["g1"]["rp"]}\n' \
f'**SI1**: {INFIELD_X_CHART["si1"]["rp"]}\n' \
f'**SI2**: {OUTFIELD_X_CHART["si2"]["rp"]}\n'
elif error_dice == 4:
error_note = 'No error'
elif error_dice == 3:
error_note = '2-base error for e8 -> e12, e24 -> e28\n' \
'1-base error for e2, e3, e6, e7, e14, e16, e17, e21'
if pos_code == '2B':
error_chart += 'second-base.png'
if error_dice == 18:
error_note = '2-base error for e4 -> e19, e28 -> e41, e53 -> e65\n' \
'1-base error for e22, e24, e25, e27, e44, e50'
elif error_dice == 17:
error_note = '2-base error for e20 -> e41, e68, e71\n' \
'1-base error for e3, e4, e8 -> e12, e15, e16, e19'
elif error_dice == 16:
error_note = '2-base error for e53 -> 71\n' \
'1-base error for e5 -> 10, e14, e16, e29, e37'
elif error_dice == 15:
error_note = '1-base error for e11, e12, e14, e16, e17, e19, e26 -> e28, e30, e32, e37, ' \
'e50 -> e62, e71'
elif error_dice == 14:
error_note = '1-base error for e13, e15, e34, e47, e65'
elif error_dice == 13:
error_note = '1-base error for e18, e20, e21, e26 -> e28, e39, e41, e50, e56, e59, e65, e71'
elif error_dice == 12:
error_note = '1-base error for e22, e30, e34, e39, e44, e47, e53, e56, e62, e68, e71'
elif error_dice == 11:
error_note = '1-base error for e23 -> e25, e29, e32, e37, e41, e50, e53, e59, e62, e68'
elif error_dice == 10:
error_note = '1-base error for e68'
elif error_dice == 9:
error_note = '1-base error for e44'
elif error_dice == 8:
error_note = 'No error'
elif error_dice == 7:
error_note = '1-base error for e47, e65'
elif error_dice == 6:
error_note = '1-base error for e17, e19, e56 -> 62'
elif error_dice == 5:
error_note = f'Rare play!\n\n' \
f'**G3**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**G2**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**G1**: {INFIELD_X_CHART["g1"]["rp"]}\n' \
f'**SI1**: {INFIELD_X_CHART["si1"]["rp"]}\n' \
f'**SI2**: {OUTFIELD_X_CHART["si2"]["rp"]}\n'
elif error_dice == 4:
error_note = '1-base error for e10, e21'
elif error_dice == 3:
error_note = '2-base error for e12 -> e19, e37 -> e41, e59 -> e65\n' \
'1-base error for e2 -> e4, e6, e20, e25, e28, e29'
if pos_code == '3B':
error_chart += 'third-base.png'
if error_dice == 18:
error_note = '2-base error for e1, e2, e8, e10, e13 -> e16, e21 -> e24, e27, e30 -> e33, e50, ' \
'e56, e62, e65\n' \
'1-base error for e39'
elif error_dice == 17:
error_note = '2-base error for e3 -> e10, e17, e18, e25 -> e27, e34 -> e37, e44, e47\n' \
'1-base error for e11, e19, e32, e56'
elif error_dice == 16:
error_note = '2-base error for e11 -> e18, e32, e33, e37, e53, e62, e65\n' \
'1-base error for e4, e8, e19, e21, e22, e27, e41'
elif error_dice == 15:
error_note = '2-base error for e19 -> 27, e32, e33, e37, e39, e44, e50, e59\n' \
'1-base error for e5 -> e8, e11, e14, e15, e17, e18, e28 -> e31, e34'
elif error_dice == 14:
error_note = '2-base error for e28 -> e31, e34, e35, e50\n' \
'1-base error for e14, e16, e19, e20, e22, e32, e39, e44, e56, e62'
elif error_dice == 13:
error_note = '2-base error for e41, e47, e53, e59\n' \
'1-base error for e10, e15, e23, e25, e28, e30, e32, e33, e35, e44, e65'
elif error_dice == 12:
error_note = '2-base error for e62\n' \
'1-base error for e12, e17, e22, e24, e27, e29, e34 -> e50, e56 -> e59, e65'
elif error_dice == 11:
error_note = '2-base error for e56, e65\n' \
'1-base error for e13, e18, e20, e21, e23, e26, e28, e31 -> e33, e35, e37, ' \
'e41 -> e53, e59, e65'
elif error_dice == 10:
error_note = '1-base error for e26, e31, e41, e53 -> 65'
elif error_dice == 9:
error_note = '1-base error for e24, e27, e29, e34, e37, e39, e47 -> e65'
elif error_dice == 8:
error_note = '1-base error for e25, e30, e33, e47, e53, e56, e62, e65'
elif error_dice == 7:
error_note = '1-base error for e16, e19, e39, e59 -> e65'
elif error_dice == 6:
error_note = '1-base error for e21, e25, e30, e34, e53'
elif error_dice == 5:
error_note = f'Rare play!\n\n' \
f'**G3**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**G2**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**G1**: {INFIELD_X_CHART["g1"]["rp"]}\n' \
f'**SI1**: {INFIELD_X_CHART["si1"]["rp"]}\n' \
f'**SI2**: {OUTFIELD_X_CHART["si2"]["rp"]}\n'
elif error_dice == 4:
error_note = '1-base error for e2, e3, e6, e14, e16, e44'
elif error_dice == 3:
error_note = '2-base error for e10, e15, e16, e23, e24, e56\n' \
'1-base error for e1 -> e4, e8, e14'
if pos_code == 'SS':
error_chart += 'shortstop.png'
if error_dice == 18:
error_note = '2-base error for e4 -> e12, e22 -> e32, e40 -> e48, e64, e68\n' \
'1-base error for e1, e18, e34, e52, e56'
elif error_dice == 17:
error_note = '2-base error for e14 -> 32, e52, e56, e72 -> e84\n' \
'1-base error for e3 -> e5, e8 ,e10, e36'
elif error_dice == 16:
error_note = '2-base error for e33 -> 56, e72\n' \
'1-base error for e6 -> e10, e17, e18, e20, e28, e31, e88'
elif error_dice == 15:
error_note = '2-base error for e60 -> e68, e76 -> 84\n' \
'1-base error for e12, e14, e17, e18, e20 -> e22, e24, e28, e31 -> 36, e40, ' \
'e48, e72'
elif error_dice == 14:
error_note = '1-base error for e16, e19, e38, e42, e60, e68'
elif error_dice == 13:
error_note = '1-base error for e23, e25, e32 -> 38, e44, e52, e72 -> 84'
elif error_dice == 12:
error_note = '1-base error for e26, e27, e30, e42, e48, e56, e64, e68, e76 -> e88'
elif error_dice == 11:
error_note = '1-base error for e29, e40, e52 -> e60, e72, e80 -> e88'
elif error_dice == 10:
error_note = '1-base error for e84'
elif error_dice == 9:
error_note = '1-base error for e64, e68, e76, e88'
elif error_dice == 8:
error_note = '1-base error for e44'
elif error_dice == 7:
error_note = '1-base error for e60'
elif error_dice == 6:
error_note = '1-base error for e21, e22, e24, e28, e31, e48, e64, e72'
elif error_dice == 5:
error_note = f'Rare play!\n\n' \
f'**G3**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**G2**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**G1**: {INFIELD_X_CHART["g1"]["rp"]}\n' \
f'**SI1**: {INFIELD_X_CHART["si1"]["rp"]}\n' \
f'**SI2**: {OUTFIELD_X_CHART["si2"]["rp"]}\n'
elif error_dice == 4:
error_note = '2-base error for e72\n' \
'1-base error for e14, e19, e20, e24, e25, e31, e80'
elif error_dice == 3:
error_note = '2-base error for e10, e12, e28 -> e32, e48, e84\n' \
'1-base error for e2, e5, e7, e23, e27'
elif pos_code in ['LF', 'CF', 'RF']:
x_chart = 'https://sombaseball.ddns.net/static/images/season04/range-outfield.png'
symbol_link = 'https://docs.google.com/document/d/1p8Y2On0301C1yq4ktyPxE4lXxrIALYaF1vbW6RkRpII/edit' \
'#heading=h.drrzdsvu0ij0'
# Build range note
if d_twenty == 1:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'F1 DO2 DO3 --TR3--\n' \
'```\n\n'
elif d_twenty == 2:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'F2 SI2 DO2 DO3 TR3\n' \
'```\n\n'
elif d_twenty == 3:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'F2 SI2 --DO2-- DO3\n' \
'```\n\n'
elif d_twenty == 4:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'F2 F1 SI2 DO2 DO3\n' \
'```\n\n'
elif d_twenty <= 6:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--F2--- --SI2-- DO2\n' \
'```\n\n'
elif d_twenty == 7:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--F2--- F1 SI2 DO2\n' \
'```\n\n'
elif d_twenty == 8:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--F2--- F1 --SI2--\n' \
'```\n\n'
elif d_twenty <= 11:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'----F2----- --SI2--\n' \
'```\n\n'
elif d_twenty <= 13:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'----F2----- F1 SI2\n' \
'```\n\n'
elif d_twenty <= 15:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'F3 ----F2----- SI2\n' \
'```\n\n'
elif d_twenty == 16:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--F3--- --F2--- F1\n' \
'```\n\n'
elif d_twenty <= 18:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'----F3----- F2 F1\n' \
'```\n\n'
elif d_twenty == 19:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'------F3------- F2\n' \
'```\n\n'
elif d_twenty == 20:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--------F3---------\n' \
'```\n\n'
if pos_code in ['LF', 'RF']:
error_chart += 'corner-outfield.png'
if error_dice == 18:
error_note = '3-base error for e4 -> e12, e19 -> e25\n' \
'2-base error for e18\n' \
'1-base error for e2, e3, e15'
elif error_dice == 17:
error_note = '3-base error for e13 -> e25\n' \
'2-base error for e1, e6, e8, e10'
elif error_dice == 16:
error_note = '2-base error for e2\n' \
'1-base error for e7 -> 12, e22, e24, e25'
elif error_dice == 15:
error_note = '2-base error for e3, e4, e7, e8, e10, e11, e13, e20, e21'
elif error_dice == 14:
error_note = '2-base error for e5, e6, e10, e12, e14, e15, e22, e23'
elif error_dice == 13:
error_note = '2-base error for e11, e12, e16, e20, e24, e25'
elif error_dice == 12:
error_note = '2-base error for e13 -> e18, e21 -> e23, e25'
elif error_dice == 11:
error_note = '2-base error for e9, e18 -> e21, e23 -> e25'
elif error_dice == 10:
error_note = '2-base error for e19'
elif error_dice == 9:
error_note = '2-base error for e22'
elif error_dice == 8:
error_note = '2-base error for e24'
elif error_dice == 7:
error_note = '1-base error for e19 -> e21, e23'
elif error_dice == 6:
error_note = '2-base error for e7, e8\n' \
'1-base error for e13 -> e18, e22, e24, e25'
elif error_dice == 5:
error_note = f'Rare play!'
error_note1 = f'**F1**: {OUTFIELD_X_CHART["f1"]["rp"]}\n' \
f'**F2**: {OUTFIELD_X_CHART["f2"]["rp"]}\n' \
f'**F3**: {OUTFIELD_X_CHART["f3"]["rp"]}\n'
error_note2 = f'**SI2**: {OUTFIELD_X_CHART["si2"]["rp"]}\n' \
f'**DO2**: {OUTFIELD_X_CHART["do2"]["rp"]}\n' \
f'**DO3**: {OUTFIELD_X_CHART["do3"]["rp"]}\n' \
f'**TR3**: {OUTFIELD_X_CHART["tr3"]["rp"]}\n'
elif error_dice == 4:
error_note = '2-base error for e13, e16, e20, e23 -> e25\n' \
'1-base error for e4 -> e6, e10 -> 12, e16 -> e18'
elif error_dice == 3:
error_note = '3-base error for e8 -> e12, e24, e25\n' \
'2-base error for e19\n' \
'1-base error for e1 -> e3, e6, e14, e15, e18, e20 -> e22'
else:
error_chart += 'center-field.png'
if error_dice == 18:
error_note = '3-base error for e4 -> 19\n' \
'2-base error for e2, e25\n' \
'1-base error for e3, e23'
elif error_dice == 17:
error_note = '3-base error for e20 -> e25\n' \
'2-base error for e1, e2, e5, e7, e9, e13 -> e15, e17'
elif error_dice == 16:
error_note = '2-base error for e3 -> e5, e8, e23\n' \
'1-base error for e10 -> e18'
elif error_dice == 15:
error_note = '2-base error for e6 -> e8, e12, e13, e19'
elif error_dice == 14:
error_note = '2-base error for e9, e10, e16 -> e18, e20 -> e23'
elif error_dice == 13:
error_note = '2-base error for e11, e18, e20, e23 -> e25'
elif error_dice == 12:
error_note = '2-base error for e14, e15, e21, e22, e24'
elif error_dice == 11:
error_note = '2-base error for e19, e25'
elif error_dice >= 8:
error_note = 'No error'
elif error_dice == 7:
error_note = '2-base error for e16, e17'
elif error_dice == 6:
error_note = '2-base error for e12, e13\n' \
'1-base error for e19 -> e25'
elif error_dice == 5:
error_note = f'Rare play!'
error_note1 = f'**F1**: {OUTFIELD_X_CHART["f1"]["rp"]}\n' \
f'**F2**: {OUTFIELD_X_CHART["f2"]["rp"]}\n' \
f'**F3**: {OUTFIELD_X_CHART["f3"]["rp"]}\n'
error_note2 = f'**SI2**: {OUTFIELD_X_CHART["si2"]["rp"]}\n' \
f'**DO2**: {OUTFIELD_X_CHART["do2"]["rp"]}\n' \
f'**DO3**: {OUTFIELD_X_CHART["do3"]["rp"]}\n' \
f'**TR3**: {OUTFIELD_X_CHART["tr3"]["rp"]}\n'
elif error_dice == 4:
error_note = '2-base error for e10, e12, e13, e20, e22, e23\n' \
'1-base error for e3 -> e9, e15 -> e18'
elif error_dice == 3:
error_note = '3-base error for e12 -> e19\n' \
'2-base error for e10, e11\n' \
'1-base error for e2, e3, e7 -> e9, e21 -> e23'
elif pos_code == 'C':
x_chart = 'https://sombaseball.ddns.net/static/images/season04/range-catcher.png'
error_chart += 'catcher.png'
symbol_link = 'https://docs.google.com/document/d/1a_g6apg74ixcwJapNrbOJZAx7gVxGjeNm79c5XLjSF0/' \
'edit#heading=h.mcf1vrt5gzr9'
# Build range note
range_note = '__If Bases Empty__\n'
if d_twenty == 1:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'G3 ------SI1------\n' \
'```\n'
elif d_twenty == 2:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G3--- ----SI1----\n' \
'```\n'
elif d_twenty == 3:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'PO --G3--- --SI1--\n' \
'```\n'
elif d_twenty == 4:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--PO--- --G3--- SI1\n' \
'```\n'
elif d_twenty == 5:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'----PO----- --G3---\n' \
'```\n'
elif d_twenty == 6:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'------PO------- G3\n' \
'```\n'
elif d_twenty <= 10:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--------PO---------\n' \
'```\n'
elif d_twenty == 11:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'FO -------PO------\n' \
'```\n'
elif d_twenty == 12:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--FO--- -----PO----\n' \
'```\n'
elif d_twenty == 13:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'----FO----- --PO---\n' \
'```\n'
elif d_twenty == 14:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'------FO------- PO\n' \
'```\n'
elif d_twenty <= 16:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--------FO---------\n' \
'```\n'
elif d_twenty == 17:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G2--- G3 --FO---\n' \
'```\n'
elif d_twenty == 18:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G2--- --G3--- FO\n' \
'```\n'
elif d_twenty == 19:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G1--- G2 --G3---\n' \
'```\n'
elif d_twenty == 20:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G1--- --G2--- G3\n' \
'```\n'
range_note += '__If Runners on Base__\n'
if d_twenty <= 2:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--------WP---------\n' \
'```\n'
elif d_twenty == 3:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
' X -------WP------\n' \
'```\n'
elif d_twenty == 4:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'---X--- -----WP----\n' \
'```\n'
elif d_twenty == 5:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'-----X----- --WP---\n' \
'```\n'
elif d_twenty == 6:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'-------X------- WP\n' \
'```\n'
elif d_twenty <= 9:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'PO -------X-------\n' \
'```\n'
elif d_twenty <= 12:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--PO--- -----X-----\n' \
'```\n'
elif d_twenty == 13:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'FO PO -----X-----\n' \
'```\n'
elif d_twenty == 14:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--FO--- PO ---X---\n' \
'```\n'
elif d_twenty <= 16:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'----FO----- ---X---\n' \
'```\n'
elif d_twenty == 17:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G2--- G3 PO X\n' \
'```\n'
elif d_twenty == 18:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G2--- --G3--- X\n' \
'```\n'
elif d_twenty == 19:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'G1 --G2--- --G3---\n' \
'```\n'
elif d_twenty == 20:
range_note += '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G1--- --G2--- G3\n' \
'```\n'
# Build error note
# error_dice = 5
if error_dice == 18:
error_note = '2-base error for e4 -> 16\n1-base error for e2, e3'
elif error_dice == 17:
error_note = '1-base error for e1, e2, e4, e5, e12 -> e14, e16'
elif error_dice == 16:
error_note = '1-base error for e3 -> e5, e7, e12 -> e14, e16'
elif error_dice == 15:
error_note = '1-base error for e7, e8, e12, e13, e15'
elif error_dice == 14:
error_note = '1-base error for e6'
elif error_dice == 13:
error_note = '1-base error for e9'
elif error_dice == 12:
error_note = '1-base error for e10, e14'
elif error_dice == 11:
error_note = '1-base error for e11, e15'
elif 8 <= error_dice <= 10:
error_note = 'No error'
elif error_dice == 7:
error_note = '1-base error for e16'
elif error_dice == 6:
error_note = '1-base error for e8, e12, e13'
elif error_dice == 5:
error_note = 'Rare play! Ignore range chart above and consult ranges below\n\n'
error_note1 = '__If Bases Empty__\n'
if d_twenty == 1:
error_note1 += f'**c-1**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**c-2 -> 5**: {INFIELD_X_CHART["si1"]["rp"]}\n\n'
elif d_twenty == 2:
error_note1 += f'**c-1 -> 2**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**c-3 -> 5**: {INFIELD_X_CHART["si1"]["rp"]}\n\n'
elif d_twenty == 3:
error_note1 += f'**c-1**: {INFIELD_X_CHART["po"]["rp"]}\n' \
f'**c-2 -> 3**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**c-4 -> 5**: {INFIELD_X_CHART["si1"]["rp"]}\n\n'
elif d_twenty == 4:
error_note1 += f'**c-1 -> 2**: {INFIELD_X_CHART["po"]["rp"]}\n' \
f'**c-3 -> 4**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**c-5**: {INFIELD_X_CHART["si1"]["rp"]}\n\n'
elif d_twenty == 5:
error_note1 += f'**c-1 -> 3**: {INFIELD_X_CHART["po"]["rp"]}\n' \
f'**c-4 -> 5**: {INFIELD_X_CHART["g3"]["rp"]}\n\n'
elif d_twenty == 6:
error_note1 += f'**c-1 -> 4**: {INFIELD_X_CHART["po"]["rp"]}\n' \
f'**c-5**: {INFIELD_X_CHART["g3"]["rp"]}\n\n'
elif d_twenty <= 10:
error_note1 += f'**c-1 -> 5**: {INFIELD_X_CHART["po"]["rp"]}\n\n'
elif d_twenty == 11:
error_note1 += f'**c-1**: {INFIELD_X_CHART["fo"]["rp"]}\n' \
f'**c-2 -> 5**: {INFIELD_X_CHART["po"]["rp"]}\n\n'
elif d_twenty == 12:
error_note1 += f'**c-1 -> 2**: {INFIELD_X_CHART["fo"]["rp"]}\n' \
f'**c-3 -> 5**: {INFIELD_X_CHART["po"]["rp"]}\n\n'
elif d_twenty == 13:
error_note1 += f'**c-1 -> 3**: {INFIELD_X_CHART["fo"]["rp"]}\n' \
f'**c-4 -> 5**: {INFIELD_X_CHART["po"]["rp"]}\n\n'
elif d_twenty == 14:
error_note1 += f'**c-1 -> 4**: {INFIELD_X_CHART["fo"]["rp"]}\n' \
f'**c-5**: {INFIELD_X_CHART["po"]["rp"]}\n\n'
elif d_twenty <= 16:
error_note1 += f'**c-1 -> 5**: {INFIELD_X_CHART["fo"]["rp"]}\n\n'
elif d_twenty == 17:
error_note1 += f'**c-1 -> 2**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**c-3**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**c-4 -> 5**: {INFIELD_X_CHART["fo"]["rp"]}\n\n'
elif d_twenty == 18:
error_note1 += f'**c-1 -> 2**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**c-3 -> 4**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**c-5**: {INFIELD_X_CHART["fo"]["rp"]}\n\n'
elif d_twenty == 19:
error_note1 += f'**c-1 -> 2**: {INFIELD_X_CHART["g1"]["rp"]}\n' \
f'**c-3**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**c-4 -> 5**: {INFIELD_X_CHART["g3"]["rp"]}\n\n'
elif d_twenty == 20:
error_note1 += f'**c-1 -> 2**: {INFIELD_X_CHART["g1"]["rp"]}\n' \
f'**c-3 -> 4**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**c-5**: {INFIELD_X_CHART["g3"]["rp"]}\n\n'
error_note2 = '__If Runners on Base__\n'
if d_twenty <= 2:
error_note2 += f'**c-1 -> 5**: {INFIELD_X_CHART["wp"]["rp"]}\n\n'
elif d_twenty == 3:
error_note2 += f'**c-1**: {INFIELD_X_CHART["x"]["rp"]}\n' \
f'**c-2 -> 5**: {INFIELD_X_CHART["wp"]["rp"]}\n\n'
elif d_twenty == 4:
error_note2 += f'**c-1 -> 2**: {INFIELD_X_CHART["x"]["rp"]}\n' \
f'**c-3 -> 5**: {INFIELD_X_CHART["wp"]["rp"]}\n\n'
elif d_twenty == 5:
error_note2 += f'**c-1 -> 3**: {INFIELD_X_CHART["x"]["rp"]}\n' \
f'**c-4 -> 5**: {INFIELD_X_CHART["wp"]["rp"]}\n\n'
elif d_twenty == 6:
error_note2 += f'**c-1 -> 4**: {INFIELD_X_CHART["x"]["rp"]}\n' \
f'**c-5**: {INFIELD_X_CHART["wp"]["rp"]}\n\n'
elif d_twenty <= 9:
error_note2 += f'**c-1**: {INFIELD_X_CHART["po"]["rp"]}\n' \
f'**c-2 -> 5**: {INFIELD_X_CHART["x"]["rp"]}\n\n'
elif d_twenty <= 12:
error_note2 += f'**c-1 -> 2**: {INFIELD_X_CHART["po"]["rp"]}\n' \
f'**c-3 -> 5**: {INFIELD_X_CHART["x"]["rp"]}\n\n'
elif d_twenty == 13:
error_note2 += f'**c-1**: {INFIELD_X_CHART["fo"]["rp"]}\n' \
f'**c-2**: {INFIELD_X_CHART["po"]["rp"]}\n' \
f'**c-3 -> 5**: {INFIELD_X_CHART["x"]["rp"]}\n\n'
elif d_twenty == 14:
error_note2 += f'**c-1 -> 2**: {INFIELD_X_CHART["fo"]["rp"]}\n' \
f'**c-3**: {INFIELD_X_CHART["po"]["rp"]}\n' \
f'**c-4 -> 5**: {INFIELD_X_CHART["x"]["rp"]}\n\n'
elif d_twenty <= 16:
error_note2 += f'**c-1 -> 3**: {INFIELD_X_CHART["fo"]["rp"]}\n' \
f'**c-4 -> 5**: {INFIELD_X_CHART["x"]["rp"]}\n\n'
elif d_twenty == 17:
error_note2 += f'**c-1 -> 2**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**c-3**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**c-4**: {INFIELD_X_CHART["po"]["rp"]}\n' \
f'**c-5**: {INFIELD_X_CHART["x"]["rp"]}\n\n'
elif d_twenty == 18:
error_note2 += f'**c-1 -> 2**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**c-3 -> 4**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**c-5**: {INFIELD_X_CHART["x"]["rp"]}\n\n'
elif d_twenty == 19:
error_note2 += f'**c-1**: {INFIELD_X_CHART["g1"]["rp"]}\n' \
f'**c-2 -> 3**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**c-4 -> 5**: {INFIELD_X_CHART["g3"]["rp"]}\n\n'
elif d_twenty == 20:
error_note2 += f'**c-1 -> 2**: {INFIELD_X_CHART["g1"]["rp"]}\n' \
f'**c-3 -> 4**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**c-5**: {INFIELD_X_CHART["g3"]["rp"]}\n\n'
elif error_dice == 4:
error_note = '1-base error for e5, e13'
else:
error_note = '2-base error for e12 -> e16\n1-base error for e2, e3, e7, e11'
elif pos_code == 'P':
x_chart = 'https://sombaseball.ddns.net/static/images/season04/range-pitcher.png'
error_chart += 'pitcher.png'
symbol_link = 'https://docs.google.com/document/d/1a_g6apg74ixcwJapNrbOJZAx7gVxGjeNm79c5XLjSF0/edit' \
'#heading=h.fpjqmiv10r8l'
# Build range note
if d_twenty <= 2:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'G3 ------SI1------\n' \
'```\n'
elif d_twenty == 3:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G3--- ----SI1----\n' \
'```\n'
elif d_twenty == 4:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'----G3----- --SI1--\n' \
'```\n'
elif d_twenty <= 6:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'------G3------- SI1\n' \
'```\n'
elif d_twenty == 7:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--------G3---------\n' \
'```\n'
elif d_twenty <= 9:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'G2 ------G3-------\n' \
'```\n'
elif d_twenty <= 12:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'G1 G2 ----G3-----\n' \
'```\n'
elif d_twenty == 13:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G1--- G2 --G3---\n' \
'```\n'
elif d_twenty == 14:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G1--- --G2--- G3\n' \
'```\n'
elif d_twenty <= 16:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--G1--- ----G2-----\n' \
'```\n'
elif d_twenty <= 18:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'----G1----- --G2---\n' \
'```\n'
elif d_twenty == 19:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'------G1------- G2\n' \
'```\n'
elif d_twenty == 20:
range_note = '```\n' \
' 1 | 2 | 3 | 4 | 5\n' \
'--------G1---------\n' \
'```\n'
# Build error note
if error_dice == 18:
error_note = '2-base error for e4 -> e12, e19 -> e28, e34 -> e43, e46 -> e48'
elif error_dice == 17:
error_note = '2-base error for e13 -> e28, e44 -> e50'
elif error_dice == 16:
error_note = '2-base error for e34 -> e48, e50, e51\n' \
'1-base error for e8, e11, e16, e23'
elif error_dice == 15:
error_note = '2-base error for e50, e51\n' \
'1-base error for e10 -> e12, e19, e20, e24, e26, e30, e35, e38, e40, e46, e47'
elif error_dice == 14:
error_note = '1-base error for e4, e14, e18, e21, e22, e26, e31, e35, e42, e43, e48 -> e51'
elif error_dice == 13:
error_note = '1-base error for e6, e13, e14, e21, e22, e26, e27, e30 -> 34, e38 -> e51'
elif error_dice == 12:
error_note = '1-base error for e7, e11, e12, e15 -> e19, e22 -> e51'
elif error_dice == 11:
error_note = '1-base error for e10, e13, e15, e17, e18, e20, e21, e23, e24, e27 -> 38, e40, e42, ' \
'e44 -> e51'
elif error_dice == 10:
error_note = '1-base error for e20, e23, e24, e27 -> e51'
elif error_dice == 9:
error_note = '1-base error for e16, e19, e26, e28, e34 -> e36, e39 -> e51'
elif error_dice == 8:
error_note = '1-base error for e22, e33, e38, e39, e43 -> e51'
elif error_dice == 7:
error_note = '1-base error for e14, e21, e36, e39, e42 -> e44, e47 -> e51'
elif error_dice == 6:
error_note = '1-base error for e8, e22, e38, e39, e43 -> e51'
elif error_dice == 5:
error_note = f'Rare play!\n\n' \
f'**G3**: {INFIELD_X_CHART["g3"]["rp"]}\n' \
f'**G2**: {INFIELD_X_CHART["g2"]["rp"]}\n' \
f'**G1**: {INFIELD_X_CHART["g1"]["rp"]}\n' \
f'**SI1**: {INFIELD_X_CHART["si1"]["rp"]}\n'
elif error_dice == 4:
error_note = '1-base error for e15, e16, e40'
elif error_dice == 3:
error_note = '2-base error for e8 -> e12, e26 -> e28, e39 -> e43\n' \
'1-base error for e6, e7, e17, e30, e33, e44'
roll_message = f'```md\n' \
f'# {str(d_twenty)},{str(d_six_one + d_six_two + d_six_three)}\n' \
f'Details:[1d20;3d6 ({d_twenty} - {d_six_one} {d_six_two} {d_six_three})]```'
roll_embed = get_dice_embed(team)
roll_embed.add_field(name=f'SA Fielding roll for {team["gmname"]}', value=roll_message)
chart_embed = get_dice_embed(team, f'{pos_code} Fielding Check Summary')
chart_embed.add_field(name='Range Result', value=range_note, inline=False)
chart_embed.add_field(name='Error Result', value=error_note, inline=False)
chart_embed.add_field(name='Help Commands',
value=f'Run !<result> for full chart readout (e.g. `!g1` or `!do3`)')
chart_embed.add_field(name='Range Chart', value=x_chart, inline=False)
chart_embed.add_field(name='Error Chart', value=error_chart, inline=False)
chart_embed.add_field(name='Result Reference', value=symbol_link, inline=False)
error1_embed, error2_embed = None, None
if error_note1:
error1_embed = get_dice_embed(team)
error1_embed.add_field(name='Error Results', value=error_note1)
if error_note2:
error2_embed = get_dice_embed(team)
error2_embed.add_field(name='Error Results', value=error_note2)
return [roll_embed, chart_embed, error1_embed, error2_embed]

157
gameplay_helpers.py Normal file
View File

@ -0,0 +1,157 @@
import logging
import random
from db_calls_gameplay import StratGame, StratPlay, StratLineup, StratManagerAi, patch_play, advance_runners, \
complete_play, get_team_lineups, get_or_create_bullpen, get_player, get_sheets, make_sub
from db_calls import db_get
def single_onestar(this_play: StratPlay, comp_play: bool = True):
patch_play(this_play.id, locked=True)
advance_runners(this_play.id, num_bases=1)
patch_play(this_play.id, pa=1, ab=1, hit=1)
if comp_play:
complete_play(this_play.id, batter_to_base=1)
def single_wellhit(this_play: StratPlay, comp_play: bool = True):
patch_play(this_play.id, locked=True)
advance_runners(this_play.id, num_bases=2)
patch_play(this_play.id, pa=1, ab=1, hit=1)
if comp_play:
complete_play(this_play.id, batter_to_base=1)
def double_twostar(this_play: StratPlay, comp_play: bool = True):
patch_play(this_play.id, locked=True)
advance_runners(this_play.id, num_bases=2)
patch_play(this_play.id, pa=1, ab=1, hit=1, double=1)
if comp_play:
complete_play(this_play.id, batter_to_base=2)
def double_threestar(this_play: StratPlay, comp_play: bool = True):
patch_play(this_play.id, locked=True)
advance_runners(this_play.id, num_bases=3)
patch_play(this_play.id, pa=1, ab=1, hit=1, double=1)
if comp_play:
complete_play(this_play.id, batter_to_base=2)
def triple(this_play: StratPlay, comp_play: bool = True):
patch_play(this_play.id, locked=True)
advance_runners(this_play.id, num_bases=3)
patch_play(this_play.id, pa=1, ab=1, hit=1, triple=1)
if comp_play:
complete_play(this_play.id, batter_to_base=3)
async def next_pitcher(this_play: StratPlay, ai_team, bot):
used_pitchers = await get_team_lineups(
game_id=this_play.game.id, team_id=ai_team['id'], inc_inactive=True, pitchers_only=True, as_string=False
)
logging.debug(f'\n\nused_pitchers: {used_pitchers}')
used_ids = [x.card_id for x in used_pitchers]
logging.debug(f'used_ids: {used_ids}')
bullpen = get_or_create_bullpen(ai_team, bot)
logging.debug(f'bullpen: {bullpen}')
if this_play.game.short_game:
if this_play.inning_num == 1:
relievers = [bullpen.middle_two_id, bullpen.middle_one_id, bullpen.middle_three_id]
elif this_play.inning_num == 2:
relievers = [bullpen.setup_id, bullpen.middle_one_id, bullpen.middle_two_id, bullpen.middle_three_id]
elif this_play.inning_num == 3:
relievers = [
bullpen.closer_id, bullpen.setup_id, bullpen.middle_one_id, bullpen.middle_two_id,
bullpen.middle_three_id
]
else:
relievers = [
bullpen.long_one_id, bullpen.long_two_id, bullpen.long_three_id, bullpen.long_four_id,
bullpen.middle_three_id, bullpen.middle_two_id, bullpen.middle_one_id, bullpen.setup_id,
bullpen.closer_id
]
else:
if this_play.inning_num < 6:
relievers = [bullpen.long_one_id, bullpen.long_two_id, bullpen.long_three_id, bullpen.long_four_id]
elif this_play.inning_num == 6:
relievers = [bullpen.middle_two_id, bullpen.middle_one_id, bullpen.middle_three_id]
elif this_play.inning_num == 7:
relievers = [bullpen.middle_one_id, bullpen.middle_two_id, bullpen.middle_three_id]
elif this_play.inning_num == 8:
relievers = [bullpen.setup_id, bullpen.middle_one_id, bullpen.middle_two_id, bullpen.middle_three_id]
elif this_play.inning_num == 9:
relievers = [
bullpen.closer_id, bullpen.setup_id, bullpen.middle_one_id, bullpen.middle_two_id, bullpen.middle_three_id
]
else:
relievers = [
bullpen.long_one_id, bullpen.long_two_id, bullpen.long_three_id, bullpen.long_four_id,
bullpen.middle_three_id, bullpen.middle_two_id, bullpen.middle_one_id, bullpen.setup_id, bullpen.closer_id
]
for arm in relievers:
if arm and arm not in used_ids:
return {'player': await get_player(this_play.game, {'card_id': arm}), 'card_id': arm}
relievers = [
bullpen.closer_id, bullpen.setup_id, bullpen.middle_one_id, bullpen.middle_two_id, bullpen.middle_three_id,
bullpen.long_one_id, bullpen.long_two_id, bullpen.long_three_id, bullpen.long_four_id
]
for arm in relievers:
if arm and arm not in used_ids:
return {'player': await get_player(this_play.game, {'card_id': arm}), 'card_id': arm}
return {"p_name": "Backup Infielder"}
def starting_pitcher(ai_team, bot, is_home):
sheets = get_sheets(bot)
this_sheet = sheets.open_by_key(ai_team['gsheet'])
r_sheet = this_sheet.worksheet_by_title('My Rosters')
rotation_range = f'I4:I8'
raw_cells = r_sheet.range(rotation_range)
d_100 = random.randint(1, 100)
logging.info(f'raw_cells: {raw_cells} / d_100: {d_100}')
if is_home:
if d_100 <= 30:
return raw_cells[0][0].value
elif d_100 <= 55:
return raw_cells[1][0].value
elif d_100 <= 75:
return raw_cells[2][0].value
elif d_100 <= 90:
return raw_cells[3][0].value
else:
return raw_cells[4][0].value
else:
if d_100 <= 50:
return raw_cells[0][0].value
elif d_100 <= 75:
return raw_cells[1][0].value
elif d_100 <= 85:
return raw_cells[2][0].value
elif d_100 <= 95:
return raw_cells[3][0].value
else:
return raw_cells[4][0].value
def replace_pitcher(ai_team, this_play, pitcher_card_id):
this_card = db_get(f'cards', object_id=int(pitcher_card_id))
new_lineup = {
'game_id': this_play.game.id,
'team_id': ai_team['id'],
'player_id': this_card['player']['player_id'],
'card_id': pitcher_card_id,
'position': 'P',
'batting_order': 10,
'after_play': this_play.play_num - 1
}
make_sub(new_lineup)

146
help_text.py Normal file
View File

@ -0,0 +1,146 @@
SHEET_SHARE_STEPS = (
f'We have a very easy-to-use Google Sheet for you to manage your team. It has a script attached that '
f'powers most of the advanced functionality. Google requires you to manually copy a sheet if it '
f'has scripts so I need you to follow three quick steps to get it shared:\n'
f'1) Make a copy of the embedded sheet below\n'
f'2) Share the sheet with Paper Domo with this email address: `pd-service-account@paper-dynasty.iam.'
f'gserviceaccount.com`\n'
f'3) Run `/newsheet <google_sheet_URL>` and I will assign it to your team!\n\n'
f'__Do not__ share this sheet with anyone else. Access to the sheet grants buying and selling rights over your '
f'collection.'
)
HELP_SHEET_SCRIPTS = (
f'The first time that you use the Paper Dynasty menu, Google Sheets will require that you authorize the script '
f'the first time you access the Paper Dynasty menu following these steps:\n\n'
f'1. Click **Continue** and select your account\n'
f'2. Google has not verified this app, so click **Advanced** in the lower left corner and scroll down to '
f'**Go to Paper Dynasty Marketplace (unsafe)**\n'
f'3. When told that the Paper Dynasty Marketplace wants to access your Google Account, scroll down and select '
f'**Allow**\n\n'
f'The Paper Dynasty menu will now work on your Team Sheet!'
)
HELP_GAMEMODES = (
f'- Ranked Play: Play against another PD manager with your ranked roster. The top teams will make '
f'the playoffs at the end of the season and fight for the Paper Cup.\n'
f'- Unlimited Play: Play against another PD manager or an AI with either of your un-ranked rosters. Great for '
f'casual play, playtesting rosters, and event games.\n'
f'- Gauntlets: Coming soon'
)
HELP_NEWGAME = (
f'- Run `/newgame` and add the prompted info\n'
f'- Set starting lineups with `/read-lineup` for each team\n'
f'- Set your starting pitcher with `/starting-pitcher`\n\n'
f'From here, the game scorebug will be posted and you are ready to start rolling dice!'
)
HELP_PLAYGAME = (
f'- Run `!help Dice` to see all roll commands available; `!ab` is the one you will roll for every at bat\n'
f'- Log results with `/log <play-data>`; all results on the card should be represented, some have '
f'nested commands (e.g. `/log flyball b`)\n'
f'- When you mess up a result, run `/log undo-play` and it will roll back one play\n'
f'- Run `/gamestate` to see the scorebug with both lineups\n'
f'- Run `/substitution` to make lineup changes (for you and the AI in single player)\n'
f'- Run `/show-card` to see upcoming batters or the current defenders'
)
HELP_ENDGAME = (
f'- Run `/endgame`\n'
f'- ???\n'
f'- Profit\n'
)
HELP_TS_DASH = (
f'Your dashboard is split into three main columns:\n\n'
f'- The left column has your depth chart and lineups at the top, your roster list in the middle, and '
f'the bulk marketplace category at the bottom.\n'
f'- The center column is the Paper Dynasty Marketplace. You can search and filter cards in Paper '
f'Dynasty to purchase, sell, or just view them.\n'
f'- The right column is the player overview. This will display the most recently selected player '
f'from the Marketplace column.'
)
HELP_TS_ROSTER = (
f'Top left of the My Team tab\n\n'
f'You have three rosters available for use: Primary, Secondary, and Ranked. The roster highlighted '
f'green is the active roster; to swich the active roster, click on its name in the gray cell.\n\n'
f'You can set your rotation and two default lineups in the Lineups section. These are imported '
f'by Paper Domo when you play a game so it sets your lineup automatically.\n\n'
f'If you don\'t have any players showing up in the Depth Chart, scroll down and add players to your '
f'roster in the Roster Management section'
)
HELP_TS_MARKET = (
f'By default, this column will display all player cards in the Paper Dynasty universe. You can set '
f'filters at the very top; you can also search for a first or last name in the search bar.\n\n'
f'By checking the box beside a player\'s name, it sets them as the active player. This will display '
f'their overview on the right of the dashboard and select them for any "Quick" actions.'
)
HELP_TS_MENU = (
f'In the top bar (to the far right of File / Edit) is a Paper Dynasty tab. When that is selected, '
f'you have access to the automations built into your team sheet.\n\n'
f'Data Refresh - resync all data imports across your sheet and is a good first step '
f'if things arent\'t loading on your sheet\n'
f'Rosters - save or clear your saved rosters and lineups\n'
f'Marketplace - buy it now, add to card, and quick sell cards\n'
f'Shopping Cart - manage your cart and purchase multiple cards at once\n'
f'Sale Barn - bulk sell cards in the bottom-left corner of your team sheet'
)
HELP_REWARDS_PREMIUM = (
'- Win a 9-inning game\n'
'- Finish in top half of weekly standings\n'
'- Purchasable for 200₼\n'
'- Purchasable for $3 on the ko-fi shop'
)
HELP_REWARDS_STANDARD = (
'- Win a 3-inning game\n'
'- Play at least one game per week\n'
'- Purchasable for 100₼\n'
'- Every fifth check-in (`/comeonmanineedthis`)\n'
'- Purchasable for $2 on the ko-fi shop'
)
HELP_REWARDS_MONEY = (
'- 75₼ for playing a 9-inning game\n'
'- 25₼ for playing a 3-inning game\n'
'- Variable per cardset collections (`/paperdex`)'
)
HELP_REWARDS_SHOP = (
'The Ko-fi shop can be [viewed here](https://ko-fi.com/manticorum/shop). In addition to card packs, '
'the full ratings guide is available for purchase.'
)
HELP_START_WHAT = (
f'Well, whipper snapper, have a seat and I\'ll tell you. We\'re running a diamond dynasty / '
f'perfect team style game with electronic card and dice baseball!\n\nGet a starter pack, play '
f'games at your leisure either solo or against another player, and collect cards from the '
f'custom 2021 player set.'
)
HELP_START_HOW = (
f'Run the `.in` command - that\'s a period followed by the word "in". That\'ll get you the '
f'Paper Dynasty Players role so you can run all of the other PD commands!\n\nOnce you get your '
f'role, run `/newteam` and follow the prompts to get your starter team.'
)
HELP_START_PLAY = (
'A step-by-step of how to play was written by Riles [starting here](https://discord.com/channels'
'/613880856032968834/633456305830625303/985968300272001054). '
'In addition, you can find the Rules Reference [right here](https://docs.google.com/document/d/'
'1yGZcHy9zN2MUi4hnce12dAzlFpIApbn7zR24vCkPl1o).\n\nThere are three key differences from league '
'play:\n1) Injuries: there are no injuries in Paper Dynasty!\n2) sWAR: there is no sWAR "salary '
'cap" for your team like in league play. Some events will have roster construction rules to '
'follow, though!\n3) The Universal DH is in effect; teams may forfeit the DH at their '
'discretion.'
)
HELP_START_ASK = (
f'Feel free to ask any questions down in '
)

1898
helpers.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,36 +1,68 @@
import discord
import datetime
import logging
import asyncio
import os
from discord.ext import commands from discord.ext import commands
raw_log_level = os.getenv('LOG_LEVEL')
if raw_log_level == 'DEBUG':
log_level = logging.DEBUG
elif raw_log_level == 'INFO':
log_level = logging.INFO
elif raw_log_level == 'WARN':
log_level = logging.WARNING
else:
log_level = logging.ERROR
date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}'
logging.basicConfig(
filename=f'logs/{date}.log',
format='%(asctime)s - %(levelname)s - %(message)s',
level=log_level
)
COGS = [ COGS = [
'cogs.owner', 'cogs.owner',
'cogs.helpers',
'cogs.admins', 'cogs.admins',
'cogs.economy', 'cogs.economy',
'cogs.players', 'cogs.players',
'cogs.gameplay',
] ]
intents = discord.Intents.default()
intents.members = True
intents.message_content = True
bot = commands.Bot(command_prefix='.', bot = commands.Bot(command_prefix='.',
intents=intents,
# help_command=None,
description='The Paper Dynasty Bot\nIf you have questions, feel free to contact Cal.', description='The Paper Dynasty Bot\nIf you have questions, feel free to contact Cal.',
case_insensitive=True, case_insensitive=True,
owner_id=000) owner_id=258104532423147520)
@bot.event @bot.event
async def on_ready(): async def on_ready():
print('Logged in as:') logging.info('Logged in as:')
print(bot.user.name) logging.info(bot.user.name)
print(bot.user.id) logging.info(bot.user.id)
print('------')
for c in COGS: # @bot.tree.error
try: # async def on_error(interaction, error):
bot.load_extension(c) # await interaction.channel.send(f'{error}')
print(f'Loaded cog: {c}')
except Exception as e:
print(f'******\nFailed to load cog: {c}')
print(f'{type(e).__name__} - {e}')
print('******')
print('------')
bot.run("TOKEN") async def main():
for c in COGS:
try:
await bot.load_extension(c)
logging.info(f'Loaded cog: {c}')
except Exception as e:
logging.error(f'Failed to load cog: {c}')
logging.error(f'{e}')
async with bot:
await bot.start(os.environ.get('BOT_TOKEN'))
asyncio.run(main())

6
requirements.txt Normal file
View File

@ -0,0 +1,6 @@
discord.py @ git+https://github.com/Rapptz/discord.py
peewee
pygsheets
pydantic
gsheets
bs4