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
from discord import Object
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):
@ -10,9 +24,8 @@ class Owner(commands.Cog):
@commands.is_owner()
async def load(self, ctx, *, cog: str):
try:
self.bot.load_extension(f'cogs.{cog}')
print(f'Loaded {cog}')
print('------')
await self.bot.load_extension(f'cogs.{cog}')
logging.warning(f'Loaded {cog}')
except Exception as e:
await ctx.send(f'**ERROR:** {type(e).__name__} - {e}')
else:
@ -22,9 +35,8 @@ class Owner(commands.Cog):
@commands.is_owner()
async def unload(self, ctx, *, cog: str):
try:
self.bot.unload_extension(f'cogs.{cog}')
print(f'Unloaded {cog}')
print('------')
await self.bot.unload_extension(f'cogs.{cog}')
logging.warning(f'Unloaded {cog}')
except Exception as e:
await ctx.send(f'**ERROR:** {type(e).__name__} - {e}')
else:
@ -34,16 +46,86 @@ class Owner(commands.Cog):
@commands.is_owner()
async def reload(self, ctx, *, cog: str):
try:
self.bot.unload_extension(f'cogs.{cog}')
print(f'Unloaded {cog}')
self.bot.load_extension(f'cogs.{cog}')
print(f'Reloaded {cog}')
print('------')
await self.bot.unload_extension(f'cogs.{cog}')
logging.warning(f'Unloaded {cog}')
await self.bot.load_extension(f'cogs.{cog}')
logging.warning(f'Reloaded {cog}')
except Exception as e:
await ctx.send(f'**ERROR:** {type(e).__name__} - {e}')
else:
await ctx.send('**SUCCESS**')
@commands.command(hidden=True)
@commands.is_owner()
async def fullreset(self, ctx):
cogs = ['helpers', 'admins', 'economy', 'players']
def setup(bot):
bot.add_cog(Owner(bot))
for x in cogs:
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
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.owner',
'cogs.helpers',
'cogs.admins',
'cogs.economy',
'cogs.players',
'cogs.gameplay',
]
intents = discord.Intents.default()
intents.members = True
intents.message_content = True
bot = commands.Bot(command_prefix='.',
intents=intents,
# help_command=None,
description='The Paper Dynasty Bot\nIf you have questions, feel free to contact Cal.',
case_insensitive=True,
owner_id=000)
owner_id=258104532423147520)
@bot.event
async def on_ready():
print('Logged in as:')
print(bot.user.name)
print(bot.user.id)
print('------')
logging.info('Logged in as:')
logging.info(bot.user.name)
logging.info(bot.user.id)
for c in COGS:
try:
bot.load_extension(c)
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.tree.error
# async def on_error(interaction, error):
# await interaction.channel.send(f'{error}')
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