- Add db_helpers.py with cross-database upsert functions for SQLite/PostgreSQL - Replace 12 on_conflict_replace() calls with PostgreSQL-compatible upserts - Add unique indexes: StratPlay(game, play_num), Decision(game, pitcher) - Add max_length to Team model fields (abbrev, sname, lname) - Fix boolean comparison in teams.py (== 0/1 to == False/True) - Create migrate_to_postgres.py with ID-preserving migration logic - Create audit_sqlite.py for pre-migration data integrity checks - Add PROJECT_PLAN.json for migration tracking - Add .secrets/ to .gitignore for credentials Audit results: 658,963 records across 29 tables, 2,390 orphaned stats (expected) Based on Major Domo migration lessons learned (33 issues resolved there)
1216 lines
34 KiB
Python
1216 lines
34 KiB
Python
import math
|
|
from datetime import datetime
|
|
from typing import List
|
|
import logging
|
|
import os
|
|
|
|
from pandas import DataFrame
|
|
from peewee import *
|
|
from peewee import ModelSelect
|
|
from playhouse.shortcuts import model_to_dict
|
|
|
|
# Database configuration - supports both SQLite and PostgreSQL
|
|
DATABASE_TYPE = os.environ.get("DATABASE_TYPE", "sqlite")
|
|
|
|
if DATABASE_TYPE.lower() == "postgresql":
|
|
from playhouse.pool import PooledPostgresqlDatabase
|
|
|
|
db = PooledPostgresqlDatabase(
|
|
os.environ.get("POSTGRES_DB", "pd_master"),
|
|
user=os.environ.get("POSTGRES_USER", "pd_admin"),
|
|
password=os.environ.get("POSTGRES_PASSWORD"),
|
|
host=os.environ.get("POSTGRES_HOST", "localhost"),
|
|
port=int(os.environ.get("POSTGRES_PORT", "5432")),
|
|
max_connections=20,
|
|
stale_timeout=300, # 5 minutes
|
|
timeout=0,
|
|
autoconnect=True,
|
|
autorollback=True, # Automatically rollback failed transactions
|
|
)
|
|
else:
|
|
# Default SQLite configuration for local development
|
|
db = SqliteDatabase(
|
|
"storage/pd_master.db",
|
|
pragmas={"journal_mode": "wal", "cache_size": -1 * 64000, "synchronous": 0},
|
|
)
|
|
|
|
date = f"{datetime.now().year}-{datetime.now().month}-{datetime.now().day}"
|
|
log_level = logging.INFO if os.environ.get("LOG_LEVEL") == "INFO" else "WARN"
|
|
logging.basicConfig(
|
|
filename=f"logs/database/{date}.log",
|
|
format="%(asctime)s - database - %(levelname)s - %(message)s",
|
|
level=log_level,
|
|
)
|
|
|
|
# 2025, 2005
|
|
ranked_cardsets = [24, 25, 26, 27, 28, 29]
|
|
LIVE_CARDSET_ID = 27
|
|
LIVE_PROMO_CARDSET_ID = 28
|
|
CARDSETS = {
|
|
"ranked": {"primary": ranked_cardsets, "human": ranked_cardsets},
|
|
"minor-league": {
|
|
"primary": [27, 8], # 2005, Mario
|
|
"secondary": [24], # 2025
|
|
"human": [x for x in range(1, 30)],
|
|
},
|
|
"major-league": {
|
|
"primary": [
|
|
27,
|
|
28,
|
|
24,
|
|
25,
|
|
13,
|
|
14,
|
|
6,
|
|
8,
|
|
], # 2005 + Promos, 2025 + Promos, 2018 + Promos, 2012, Mario
|
|
"secondary": [5, 3], # 2019, 2022
|
|
"human": ranked_cardsets,
|
|
},
|
|
"hall-of-fame": {"primary": [x for x in range(1, 30)], "human": ranked_cardsets},
|
|
"flashback": {
|
|
"primary": [13, 5, 1, 3, 8], # 2018, 2019, 2021, 2022, Mario
|
|
"secondary": [24], # 2025
|
|
"human": [13, 5, 1, 3, 8], # 2018, 2019, 2021, 2022
|
|
},
|
|
"gauntlet-3": {
|
|
"primary": [13], # 2018
|
|
"secondary": [5, 11, 9], # 2019, 2016, 2023
|
|
"human": [x for x in range(1, 30)],
|
|
},
|
|
"gauntlet-4": {
|
|
"primary": [3, 6, 16], # 2022, 2013, Backyard Baseball
|
|
"secondary": [4, 9], # 2022 Promos, 2023
|
|
"human": [3, 4, 6, 9, 15, 16],
|
|
},
|
|
"gauntlet-5": {
|
|
"primary": [17, 8], # 2024, Mario
|
|
"secondary": [13], # 2018
|
|
"human": [x for x in range(1, 30)],
|
|
},
|
|
"gauntlet-6": {
|
|
"primary": [20, 8], # 1998, Mario
|
|
"secondary": [12], # 2008
|
|
"human": [x for x in range(1, 30)],
|
|
},
|
|
"gauntlet-7": {
|
|
"primary": [5, 23], # 2019, Brilliant Stars
|
|
"secondary": [1], # 2021
|
|
"human": [x for x in range(1, 30)],
|
|
},
|
|
"gauntlet-8": {
|
|
"primary": [24], # 2025
|
|
"secondary": [17],
|
|
"human": [24, 25, 22, 23],
|
|
},
|
|
"gauntlet-9": {
|
|
"primary": [27], # 2005
|
|
"secondary": [24], # 2025
|
|
},
|
|
}
|
|
|
|
|
|
def model_csv_headers(this_obj, exclude=None) -> List:
|
|
data = model_to_dict(this_obj, recurse=False, exclude=exclude)
|
|
return [x for x in data.keys()]
|
|
|
|
|
|
def model_to_csv(this_obj, exclude=None) -> List:
|
|
data = model_to_dict(this_obj, recurse=False, exclude=exclude)
|
|
return [x for x in data.values()]
|
|
|
|
|
|
def query_to_csv(all_items: ModelSelect, exclude=None):
|
|
if all_items.count() == 0:
|
|
data_list = [["No data found"]]
|
|
else:
|
|
data_list = [model_csv_headers(all_items[0], exclude=exclude)]
|
|
for x in all_items:
|
|
data_list.append(model_to_csv(x, exclude=exclude))
|
|
|
|
return DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
|
|
def complex_data_to_csv(complex_data: List):
|
|
if len(complex_data) == 0:
|
|
data_list = [["No data found"]]
|
|
else:
|
|
data_list = [[x for x in complex_data[0].keys()]]
|
|
for line in complex_data:
|
|
logging.debug(f"line: {line}")
|
|
this_row = []
|
|
for key in line:
|
|
logging.debug(f"key: {key}")
|
|
if line[key] is None:
|
|
this_row.append("")
|
|
|
|
elif isinstance(line[key], dict):
|
|
if "name" in line[key]:
|
|
this_row.append(line[key]["name"])
|
|
elif "abbrev" in line[key]:
|
|
this_row.append(line[key]["abbrev"])
|
|
else:
|
|
this_row.append(line[key]["id"])
|
|
|
|
elif isinstance(line[key], int) and line[key] > 100000000:
|
|
this_row.append(f"'{line[key]}")
|
|
|
|
elif isinstance(line[key], str) and "," in line[key]:
|
|
this_row.append(line[key].replace(",", "-_-"))
|
|
|
|
else:
|
|
this_row.append(line[key])
|
|
|
|
data_list.append(this_row)
|
|
|
|
return DataFrame(data_list).to_csv(header=False, index=False)
|
|
|
|
|
|
class BaseModel(Model):
|
|
class Meta:
|
|
database = db
|
|
|
|
|
|
class Current(BaseModel):
|
|
season = IntegerField()
|
|
week = IntegerField(default=0)
|
|
gsheet_template = CharField()
|
|
gsheet_version = CharField()
|
|
live_scoreboard = IntegerField()
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "current"
|
|
|
|
@staticmethod
|
|
def latest():
|
|
latest_current = Current.select().order_by(-Current.id).get()
|
|
return latest_current
|
|
|
|
|
|
db.create_tables([Current])
|
|
|
|
|
|
class Rarity(BaseModel):
|
|
value = IntegerField()
|
|
name = CharField(unique=True)
|
|
color = CharField()
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "rarity"
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
|
|
db.create_tables([Rarity])
|
|
|
|
|
|
class Event(BaseModel):
|
|
name = CharField()
|
|
short_desc = CharField(null=True)
|
|
url = CharField(null=True)
|
|
long_desc = CharField(null=True)
|
|
thumbnail = CharField(null=True)
|
|
active = BooleanField(default=False)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "event"
|
|
|
|
|
|
db.create_tables([Event])
|
|
|
|
|
|
class Cardset(BaseModel):
|
|
name = CharField()
|
|
description = CharField()
|
|
event = ForeignKeyField(Event, null=True)
|
|
for_purchase = BooleanField(default=True) # for_purchase
|
|
total_cards = IntegerField()
|
|
in_packs = BooleanField(default=True)
|
|
ranked_legal = BooleanField(default=True)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "cardset"
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
|
|
db.create_tables([Cardset])
|
|
|
|
|
|
class MlbPlayer(BaseModel):
|
|
first_name = CharField()
|
|
last_name = CharField()
|
|
key_fangraphs = IntegerField(null=True)
|
|
key_bbref = CharField(null=True)
|
|
key_retro = CharField(null=True)
|
|
key_mlbam = IntegerField(null=True)
|
|
offense_col = IntegerField(default=1)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "mlbplayer"
|
|
|
|
|
|
db.create_tables([MlbPlayer])
|
|
|
|
|
|
class Player(BaseModel):
|
|
player_id = IntegerField(primary_key=True)
|
|
p_name = CharField()
|
|
cost = IntegerField(default=0)
|
|
image = CharField()
|
|
image2 = CharField(null=True)
|
|
mlbclub = CharField()
|
|
franchise = CharField()
|
|
cardset = ForeignKeyField(Cardset)
|
|
set_num = IntegerField()
|
|
rarity = ForeignKeyField(Rarity)
|
|
pos_1 = CharField()
|
|
pos_2 = CharField(null=True)
|
|
pos_3 = CharField(null=True)
|
|
pos_4 = CharField(null=True)
|
|
pos_5 = CharField(null=True)
|
|
pos_6 = CharField(null=True)
|
|
pos_7 = CharField(null=True)
|
|
pos_8 = CharField(null=True)
|
|
headshot = CharField(null=True)
|
|
vanity_card = CharField(null=True)
|
|
strat_code = CharField(null=True)
|
|
bbref_id = CharField(null=True)
|
|
fangr_id = CharField(null=True)
|
|
description = CharField()
|
|
quantity = IntegerField(default=999)
|
|
mlbplayer = ForeignKeyField(MlbPlayer, null=True)
|
|
|
|
def __str__(self):
|
|
return f"{self.cardset} {self.p_name} ({self.rarity.name})"
|
|
|
|
# def __eq__(self, other):
|
|
# if self.cardset.id == other.cardset.id and self.name == other.name:
|
|
# return True
|
|
# else:
|
|
# return False
|
|
|
|
def __lt__(self, other):
|
|
if self.wara < other.wara:
|
|
return True
|
|
elif self.wara > other.wara:
|
|
return False
|
|
elif self.name < other.name:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def get_all_pos(self):
|
|
all_pos = []
|
|
|
|
if self.pos_1 and self.pos_1 != "CP":
|
|
all_pos.append(self.pos_1)
|
|
if self.pos_2 and self.pos_2 != "CP":
|
|
all_pos.append(self.pos_2)
|
|
if self.pos_3 and self.pos_3 != "CP":
|
|
all_pos.append(self.pos_3)
|
|
if self.pos_4 and self.pos_4 != "CP":
|
|
all_pos.append(self.pos_4)
|
|
if self.pos_5 and self.pos_5 != "CP":
|
|
all_pos.append(self.pos_5)
|
|
if self.pos_6 and self.pos_6 != "CP":
|
|
all_pos.append(self.pos_6)
|
|
if self.pos_7 and self.pos_7 != "CP":
|
|
all_pos.append(self.pos_7)
|
|
if self.pos_8 and self.pos_8 != "CP":
|
|
all_pos.append(self.pos_8)
|
|
|
|
return all_pos
|
|
|
|
def change_on_sell(self):
|
|
# caps = {
|
|
# 'replacement': 15,
|
|
# 'reserve': 50,
|
|
# 'starter': 200,
|
|
# 'all-star': 750,
|
|
# 'mvp': 2500,
|
|
# 'hof': 999999999
|
|
# }
|
|
logging.info(f"{self.p_name} cost changing from: {self.cost}")
|
|
self.cost = max(math.floor(self.cost * 0.95), 1)
|
|
# if self.quantity != 999:
|
|
# self.quantity += 1
|
|
logging.info(f"{self.p_name} cost now: {self.cost}")
|
|
self.save()
|
|
|
|
def change_on_buy(self):
|
|
logging.info(f"{self.p_name} cost changing from: {self.cost}")
|
|
self.cost = math.ceil(self.cost * 1.1)
|
|
# if self.quantity != 999:
|
|
# self.quantity -= 1
|
|
logging.info(f"{self.p_name} cost now: {self.cost}")
|
|
self.save()
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "player"
|
|
|
|
|
|
db.create_tables([Player])
|
|
|
|
|
|
class Team(BaseModel):
|
|
abbrev = CharField(max_length=20) # Gauntlet teams use prefixes like "Gauntlet-NCB"
|
|
sname = CharField(max_length=100)
|
|
lname = CharField(max_length=255)
|
|
gmid = IntegerField()
|
|
gmname = CharField()
|
|
gsheet = CharField()
|
|
wallet = IntegerField()
|
|
team_value = IntegerField()
|
|
collection_value = IntegerField()
|
|
logo = CharField(null=True)
|
|
color = CharField(null=True)
|
|
season = IntegerField()
|
|
event = ForeignKeyField(Event, null=True)
|
|
career = IntegerField(default=0)
|
|
ranking = IntegerField(default=1000)
|
|
has_guide = BooleanField(default=False)
|
|
is_ai = IntegerField(null=True)
|
|
|
|
def __str__(self):
|
|
return f"S{self.season} {self.lname}"
|
|
|
|
@staticmethod
|
|
def get_by_owner(gmid, season=None):
|
|
if not season:
|
|
season = Current.get().season
|
|
team = Team.get_or_none((Team.gmid == gmid) & (Team.season == season))
|
|
|
|
if not team:
|
|
return None
|
|
|
|
return team
|
|
|
|
@staticmethod
|
|
def select_season(season=None):
|
|
if not season:
|
|
season = Current.get().season
|
|
return Team.select().where(Team.season == season)
|
|
|
|
@staticmethod
|
|
def get_season(abbrev, season=None):
|
|
if not season:
|
|
season = Current.get().season
|
|
return Team.get_or_none(Team.season == season, Team.abbrev == abbrev.upper())
|
|
|
|
def team_hash(self):
|
|
hash_string = f"{self.sname[-1]}{self.gmid / 6950123:.0f}{self.sname[-2]}{self.gmid / 42069123:.0f}"
|
|
logging.info(f"string: {hash_string}")
|
|
return hash_string
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "team"
|
|
|
|
|
|
db.create_tables([Team])
|
|
|
|
|
|
class PackType(BaseModel):
|
|
name = CharField()
|
|
card_count = IntegerField()
|
|
description = CharField()
|
|
cost = IntegerField()
|
|
available = BooleanField(default=True)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "packtype"
|
|
|
|
|
|
db.create_tables([PackType])
|
|
|
|
|
|
class Pack(BaseModel):
|
|
team = ForeignKeyField(Team)
|
|
pack_type = ForeignKeyField(PackType)
|
|
pack_team = ForeignKeyField(Team, null=True)
|
|
pack_cardset = ForeignKeyField(Cardset, null=True)
|
|
open_time = DateTimeField(null=True)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "pack"
|
|
|
|
|
|
db.create_tables([Pack])
|
|
|
|
|
|
class Card(BaseModel):
|
|
player = ForeignKeyField(Player, null=True)
|
|
team = ForeignKeyField(Team, null=True)
|
|
pack = ForeignKeyField(Pack, null=True)
|
|
value = IntegerField(default=0)
|
|
|
|
def __str__(self):
|
|
if self.player:
|
|
return f"{self.player} - {self.team.sname}"
|
|
else:
|
|
return f"Blank - {self.team.sname}"
|
|
|
|
@staticmethod
|
|
def select_season(season):
|
|
return Card.select().join(Team).where(Card.team.season == season)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "card"
|
|
|
|
|
|
db.create_tables([Card])
|
|
|
|
|
|
class Roster(BaseModel):
|
|
team = ForeignKeyField(Team)
|
|
name = CharField()
|
|
roster_num = IntegerField()
|
|
card_1 = ForeignKeyField(Card)
|
|
card_2 = ForeignKeyField(Card)
|
|
card_3 = ForeignKeyField(Card)
|
|
card_4 = ForeignKeyField(Card)
|
|
card_5 = ForeignKeyField(Card)
|
|
card_6 = ForeignKeyField(Card)
|
|
card_7 = ForeignKeyField(Card)
|
|
card_8 = ForeignKeyField(Card)
|
|
card_9 = ForeignKeyField(Card)
|
|
card_10 = ForeignKeyField(Card)
|
|
card_11 = ForeignKeyField(Card)
|
|
card_12 = ForeignKeyField(Card)
|
|
card_13 = ForeignKeyField(Card)
|
|
card_14 = ForeignKeyField(Card)
|
|
card_15 = ForeignKeyField(Card)
|
|
card_16 = ForeignKeyField(Card)
|
|
card_17 = ForeignKeyField(Card)
|
|
card_18 = ForeignKeyField(Card)
|
|
card_19 = ForeignKeyField(Card)
|
|
card_20 = ForeignKeyField(Card)
|
|
card_21 = ForeignKeyField(Card)
|
|
card_22 = ForeignKeyField(Card)
|
|
card_23 = ForeignKeyField(Card)
|
|
card_24 = ForeignKeyField(Card)
|
|
card_25 = ForeignKeyField(Card)
|
|
card_26 = ForeignKeyField(Card)
|
|
|
|
def __str__(self):
|
|
return f"{self.team} Roster"
|
|
|
|
# def get_cards(self, team):
|
|
# all_cards = Card.select().where(Card.roster == self)
|
|
# this_roster = []
|
|
# return [this_roster.card1, this_roster.card2, this_roster.card3, this_roster.card4, this_roster.card5,
|
|
# this_roster.card6, this_roster.card7, this_roster.card8, this_roster.card9, this_roster.card10,
|
|
# this_roster.card11, this_roster.card12, this_roster.card13, this_roster.card14, this_roster.card15,
|
|
# this_roster.card16, this_roster.card17, this_roster.card18, this_roster.card19, this_roster.card20,
|
|
# this_roster.card21, this_roster.card22, this_roster.card23, this_roster.card24, this_roster.card25,
|
|
# this_roster.card26]
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "roster"
|
|
|
|
|
|
class Result(BaseModel):
|
|
away_team = ForeignKeyField(Team)
|
|
home_team = ForeignKeyField(Team)
|
|
away_score = IntegerField()
|
|
home_score = IntegerField()
|
|
away_team_value = IntegerField(null=True)
|
|
home_team_value = IntegerField(null=True)
|
|
away_team_ranking = IntegerField(null=True)
|
|
home_team_ranking = IntegerField(null=True)
|
|
scorecard = CharField()
|
|
week = IntegerField()
|
|
season = IntegerField()
|
|
ranked = BooleanField()
|
|
short_game = BooleanField()
|
|
game_type = CharField(null=True)
|
|
|
|
@staticmethod
|
|
def select_season(season=None):
|
|
if not season:
|
|
season = Current.get().season
|
|
return Result.select().where(Result.season == season)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "result"
|
|
|
|
|
|
class BattingStat(BaseModel):
|
|
card = ForeignKeyField(Card)
|
|
team = ForeignKeyField(Team)
|
|
roster_num = IntegerField()
|
|
vs_team = ForeignKeyField(Team)
|
|
result = ForeignKeyField(Result, null=True)
|
|
pos = CharField()
|
|
pa = IntegerField()
|
|
ab = IntegerField()
|
|
run = IntegerField()
|
|
hit = IntegerField()
|
|
rbi = IntegerField()
|
|
double = IntegerField()
|
|
triple = IntegerField()
|
|
hr = IntegerField()
|
|
bb = IntegerField()
|
|
so = IntegerField()
|
|
hbp = IntegerField()
|
|
sac = IntegerField()
|
|
ibb = IntegerField()
|
|
gidp = IntegerField()
|
|
sb = IntegerField()
|
|
cs = IntegerField()
|
|
bphr = IntegerField()
|
|
bpfo = IntegerField()
|
|
bp1b = IntegerField()
|
|
bplo = IntegerField()
|
|
xch = IntegerField()
|
|
xhit = IntegerField()
|
|
error = IntegerField()
|
|
pb = IntegerField()
|
|
sbc = IntegerField()
|
|
csc = IntegerField()
|
|
week = IntegerField()
|
|
season = IntegerField()
|
|
created = DateTimeField()
|
|
game_id = IntegerField()
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "battingstat"
|
|
|
|
|
|
class PitchingStat(BaseModel):
|
|
card = ForeignKeyField(Card)
|
|
team = ForeignKeyField(Team)
|
|
roster_num = IntegerField()
|
|
vs_team = ForeignKeyField(Team)
|
|
result = ForeignKeyField(Result, null=True)
|
|
ip = FloatField()
|
|
hit = IntegerField()
|
|
run = IntegerField()
|
|
erun = IntegerField()
|
|
so = IntegerField()
|
|
bb = IntegerField()
|
|
hbp = IntegerField()
|
|
wp = IntegerField()
|
|
balk = IntegerField()
|
|
hr = IntegerField()
|
|
ir = IntegerField()
|
|
irs = IntegerField()
|
|
gs = IntegerField()
|
|
win = IntegerField()
|
|
loss = IntegerField()
|
|
hold = IntegerField()
|
|
sv = IntegerField()
|
|
bsv = IntegerField()
|
|
week = IntegerField()
|
|
season = IntegerField()
|
|
created = DateTimeField()
|
|
game_id = IntegerField()
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "pitchingstat"
|
|
|
|
|
|
class Award(BaseModel):
|
|
name = CharField()
|
|
season = IntegerField()
|
|
timing = CharField(default="In-Season")
|
|
card = ForeignKeyField(Card, null=True)
|
|
team = ForeignKeyField(Team, null=True)
|
|
image = CharField(null=True)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "award"
|
|
|
|
|
|
class Paperdex(BaseModel):
|
|
team = ForeignKeyField(Team)
|
|
player = ForeignKeyField(Player)
|
|
created = DateTimeField(default=int(datetime.timestamp(datetime.now()) * 1000))
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "paperdex"
|
|
|
|
# def add_to_paperdex(self, team, cards: list):
|
|
# for x in players:
|
|
# if not isinstance(x, Card):
|
|
# raise TypeError(f'The Pokedex can only take a list of Player or Card objects')
|
|
#
|
|
# Paperdex.get_or_create(team=team, player=player)
|
|
|
|
|
|
class Reward(BaseModel):
|
|
name = CharField(null=True)
|
|
season = IntegerField()
|
|
week = IntegerField()
|
|
team = ForeignKeyField(Team)
|
|
created = DateTimeField()
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "reward"
|
|
|
|
|
|
class GameRewards(BaseModel):
|
|
name = CharField()
|
|
pack_type = ForeignKeyField(PackType, null=True)
|
|
player = ForeignKeyField(Player, null=True)
|
|
money = IntegerField(null=True)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "gamerewards"
|
|
|
|
|
|
class Notification(BaseModel):
|
|
created = DateTimeField()
|
|
title = CharField()
|
|
desc = CharField(null=True)
|
|
field_name = CharField()
|
|
message = CharField()
|
|
about = CharField() # f'{Topic}-{Object ID}'
|
|
ack = BooleanField(default=False)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "notification"
|
|
|
|
|
|
class GauntletReward(BaseModel):
|
|
name = CharField()
|
|
gauntlet = ForeignKeyField(Event)
|
|
reward = ForeignKeyField(GameRewards)
|
|
win_num = IntegerField()
|
|
loss_max = IntegerField(default=1)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "gauntletreward"
|
|
|
|
|
|
class GauntletRun(BaseModel):
|
|
team = ForeignKeyField(Team)
|
|
gauntlet = ForeignKeyField(Event)
|
|
wins = IntegerField(default=0)
|
|
losses = IntegerField(default=0)
|
|
gsheet = CharField(null=True)
|
|
created = DateTimeField(default=int(datetime.timestamp(datetime.now()) * 1000))
|
|
ended = DateTimeField(default=0)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "gauntletrun"
|
|
|
|
|
|
db.create_tables(
|
|
[
|
|
Roster,
|
|
BattingStat,
|
|
PitchingStat,
|
|
Result,
|
|
Award,
|
|
Paperdex,
|
|
Reward,
|
|
GameRewards,
|
|
Notification,
|
|
GauntletReward,
|
|
GauntletRun,
|
|
]
|
|
)
|
|
|
|
|
|
class BattingCard(BaseModel):
|
|
player = ForeignKeyField(Player)
|
|
variant = IntegerField()
|
|
steal_low = IntegerField()
|
|
steal_high = IntegerField()
|
|
steal_auto = BooleanField()
|
|
steal_jump = FloatField()
|
|
bunting = CharField()
|
|
hit_and_run = CharField()
|
|
running = IntegerField()
|
|
offense_col = IntegerField()
|
|
hand = CharField(default="R")
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "battingcard"
|
|
|
|
|
|
bc_index = ModelIndex(
|
|
BattingCard, (BattingCard.player, BattingCard.variant), unique=True
|
|
)
|
|
BattingCard.add_index(bc_index)
|
|
|
|
|
|
class BattingCardRatings(BaseModel):
|
|
battingcard = ForeignKeyField(BattingCard)
|
|
vs_hand = CharField(default="R")
|
|
pull_rate = FloatField()
|
|
center_rate = FloatField()
|
|
slap_rate = FloatField()
|
|
homerun = FloatField()
|
|
bp_homerun = FloatField()
|
|
triple = FloatField()
|
|
double_three = FloatField()
|
|
double_two = FloatField()
|
|
double_pull = FloatField()
|
|
single_two = FloatField()
|
|
single_one = FloatField()
|
|
single_center = FloatField()
|
|
bp_single = FloatField()
|
|
hbp = FloatField()
|
|
walk = FloatField()
|
|
strikeout = FloatField()
|
|
lineout = FloatField()
|
|
popout = FloatField()
|
|
flyout_a = FloatField()
|
|
flyout_bq = FloatField()
|
|
flyout_lf_b = FloatField()
|
|
flyout_rf_b = FloatField()
|
|
groundout_a = FloatField()
|
|
groundout_b = FloatField()
|
|
groundout_c = FloatField()
|
|
avg = FloatField(null=True)
|
|
obp = FloatField(null=True)
|
|
slg = FloatField(null=True)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "battingcardratings"
|
|
|
|
|
|
bcr_index = ModelIndex(
|
|
BattingCardRatings,
|
|
(BattingCardRatings.battingcard, BattingCardRatings.vs_hand),
|
|
unique=True,
|
|
)
|
|
BattingCardRatings.add_index(bcr_index)
|
|
|
|
|
|
class PitchingCard(BaseModel):
|
|
player = ForeignKeyField(Player)
|
|
variant = IntegerField()
|
|
balk = IntegerField()
|
|
wild_pitch = IntegerField()
|
|
hold = IntegerField()
|
|
starter_rating = IntegerField()
|
|
relief_rating = IntegerField()
|
|
closer_rating = IntegerField(null=True)
|
|
batting = CharField(null=True)
|
|
offense_col = IntegerField()
|
|
hand = CharField(default="R")
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "pitchingcard"
|
|
|
|
|
|
pc_index = ModelIndex(
|
|
PitchingCard, (PitchingCard.player, PitchingCard.variant), unique=True
|
|
)
|
|
PitchingCard.add_index(pc_index)
|
|
|
|
|
|
class PitchingCardRatings(BaseModel):
|
|
pitchingcard = ForeignKeyField(PitchingCard)
|
|
vs_hand = CharField(default="R")
|
|
homerun = FloatField()
|
|
bp_homerun = FloatField()
|
|
triple = FloatField()
|
|
double_three = FloatField()
|
|
double_two = FloatField()
|
|
double_cf = FloatField()
|
|
single_two = FloatField()
|
|
single_one = FloatField()
|
|
single_center = FloatField()
|
|
bp_single = FloatField()
|
|
hbp = FloatField()
|
|
walk = FloatField()
|
|
strikeout = FloatField()
|
|
flyout_lf_b = FloatField()
|
|
flyout_cf_b = FloatField()
|
|
flyout_rf_b = FloatField()
|
|
groundout_a = FloatField()
|
|
groundout_b = FloatField()
|
|
xcheck_p = FloatField()
|
|
xcheck_c = FloatField()
|
|
xcheck_1b = FloatField()
|
|
xcheck_2b = FloatField()
|
|
xcheck_3b = FloatField()
|
|
xcheck_ss = FloatField()
|
|
xcheck_lf = FloatField()
|
|
xcheck_cf = FloatField()
|
|
xcheck_rf = FloatField()
|
|
avg = FloatField(null=True)
|
|
obp = FloatField(null=True)
|
|
slg = FloatField(null=True)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "pitchingcardratings"
|
|
|
|
|
|
pcr_index = ModelIndex(
|
|
PitchingCardRatings,
|
|
(PitchingCardRatings.pitchingcard, PitchingCardRatings.vs_hand),
|
|
unique=True,
|
|
)
|
|
PitchingCardRatings.add_index(pcr_index)
|
|
|
|
|
|
class CardPosition(BaseModel):
|
|
player = ForeignKeyField(Player)
|
|
variant = IntegerField()
|
|
position = CharField()
|
|
innings = IntegerField()
|
|
range = IntegerField()
|
|
error = IntegerField()
|
|
arm = IntegerField(null=True)
|
|
pb = IntegerField(null=True)
|
|
overthrow = IntegerField(null=True)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "cardposition"
|
|
|
|
|
|
pos_index = ModelIndex(
|
|
CardPosition,
|
|
(CardPosition.player, CardPosition.variant, CardPosition.position),
|
|
unique=True,
|
|
)
|
|
CardPosition.add_index(pos_index)
|
|
|
|
|
|
db.create_tables(
|
|
[BattingCard, BattingCardRatings, PitchingCard, PitchingCardRatings, CardPosition]
|
|
)
|
|
|
|
|
|
class StratGame(BaseModel):
|
|
season = IntegerField()
|
|
game_type = CharField()
|
|
away_team = ForeignKeyField(Team)
|
|
home_team = ForeignKeyField(Team)
|
|
week = IntegerField(default=1)
|
|
away_score = IntegerField(default=0)
|
|
home_score = IntegerField(default=0)
|
|
away_team_value = IntegerField(null=True)
|
|
home_team_value = IntegerField(null=True)
|
|
away_team_ranking = IntegerField(null=True)
|
|
home_team_ranking = IntegerField(null=True)
|
|
ranked = BooleanField(default=False)
|
|
short_game = BooleanField(default=False)
|
|
forfeit = BooleanField(default=False)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "stratgame"
|
|
|
|
|
|
class StratPlay(BaseModel):
|
|
game = ForeignKeyField(StratGame)
|
|
play_num = IntegerField()
|
|
batter = ForeignKeyField(Player, null=True)
|
|
batter_team = ForeignKeyField(Team, null=True)
|
|
pitcher = ForeignKeyField(Player)
|
|
pitcher_team = ForeignKeyField(Team)
|
|
on_base_code = CharField()
|
|
inning_half = CharField()
|
|
inning_num = IntegerField()
|
|
batting_order = IntegerField()
|
|
starting_outs = IntegerField()
|
|
away_score = IntegerField()
|
|
home_score = IntegerField()
|
|
batter_pos = CharField(null=True)
|
|
|
|
# These <base>_final fields track the base this runner advances to post-play (None) if out
|
|
on_first = ForeignKeyField(Player, null=True)
|
|
on_first_final = IntegerField(null=True)
|
|
on_second = ForeignKeyField(Player, null=True)
|
|
on_second_final = IntegerField(null=True)
|
|
on_third = ForeignKeyField(Player, null=True)
|
|
on_third_final = IntegerField(null=True)
|
|
batter_final = IntegerField(null=True)
|
|
|
|
pa = IntegerField(default=0)
|
|
ab = IntegerField(default=0)
|
|
e_run = IntegerField(default=0)
|
|
run = IntegerField(default=0)
|
|
hit = IntegerField(default=0)
|
|
rbi = IntegerField(default=0)
|
|
double = IntegerField(default=0)
|
|
triple = IntegerField(default=0)
|
|
homerun = IntegerField(default=0)
|
|
bb = IntegerField(default=0)
|
|
so = IntegerField(default=0)
|
|
hbp = IntegerField(default=0)
|
|
sac = IntegerField(default=0)
|
|
ibb = IntegerField(default=0)
|
|
gidp = IntegerField(default=0)
|
|
bphr = IntegerField(default=0)
|
|
bpfo = IntegerField(default=0)
|
|
bp1b = IntegerField(default=0)
|
|
bplo = IntegerField(default=0)
|
|
sb = IntegerField(default=0)
|
|
cs = IntegerField(default=0)
|
|
outs = IntegerField(default=0)
|
|
wpa = FloatField(default=0.0)
|
|
re24 = FloatField(default=0.0)
|
|
|
|
# These <position> fields are only required if the play is an x-check or baserunning play
|
|
catcher = ForeignKeyField(Player, null=True)
|
|
catcher_team = ForeignKeyField(Team, null=True)
|
|
defender = ForeignKeyField(Player, null=True)
|
|
defender_team = ForeignKeyField(Team, null=True)
|
|
runner = ForeignKeyField(Player, null=True)
|
|
runner_team = ForeignKeyField(Team, null=True)
|
|
|
|
check_pos = CharField(null=True)
|
|
error = IntegerField(default=0)
|
|
wild_pitch = IntegerField(default=0)
|
|
passed_ball = IntegerField(default=0)
|
|
pick_off = IntegerField(default=0)
|
|
balk = IntegerField(default=0)
|
|
is_go_ahead = BooleanField(default=False)
|
|
is_tied = BooleanField(default=False)
|
|
is_new_inning = BooleanField(default=False)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "stratplay"
|
|
|
|
|
|
# Unique index for StratPlay - a play number should be unique within a game
|
|
# Required for PostgreSQL on_conflict() upsert operations
|
|
stratplay_index = ModelIndex(
|
|
StratPlay, (StratPlay.game, StratPlay.play_num), unique=True
|
|
)
|
|
StratPlay.add_index(stratplay_index)
|
|
|
|
|
|
class Decision(BaseModel):
|
|
season = IntegerField()
|
|
game = ForeignKeyField(StratGame)
|
|
pitcher = ForeignKeyField(Player)
|
|
pitcher_team = ForeignKeyField(Team)
|
|
week = IntegerField(default=1)
|
|
win = IntegerField(default=0)
|
|
loss = IntegerField(default=0)
|
|
hold = IntegerField(default=0)
|
|
is_save = IntegerField(default=0)
|
|
b_save = IntegerField(default=0)
|
|
irunners = IntegerField(default=0)
|
|
irunners_scored = IntegerField(default=0)
|
|
rest_ip = FloatField(default=0.0)
|
|
rest_required = IntegerField(default=0)
|
|
is_start = BooleanField(default=False)
|
|
|
|
class Meta:
|
|
database = db
|
|
table_name = "decision"
|
|
|
|
|
|
# Unique index for Decision - one decision per pitcher per game
|
|
# Required for PostgreSQL on_conflict() upsert operations
|
|
decision_index = ModelIndex(Decision, (Decision.game, Decision.pitcher), unique=True)
|
|
Decision.add_index(decision_index)
|
|
|
|
|
|
db.create_tables([StratGame, StratPlay, Decision])
|
|
|
|
|
|
db.close()
|
|
|
|
# scout_db = SqliteDatabase(
|
|
# 'storage/card_creation.db',
|
|
# pragmas={
|
|
# 'journal_mode': 'wal',
|
|
# 'cache_size': -1 * 64000,
|
|
# 'synchronous': 0
|
|
# }
|
|
# )
|
|
#
|
|
#
|
|
# class BaseModelScout(Model):
|
|
# class Meta:
|
|
# database = scout_db
|
|
#
|
|
#
|
|
# class ScoutCardset(BaseModelScout):
|
|
# set_title = CharField()
|
|
# set_subtitle = CharField(null=True)
|
|
#
|
|
#
|
|
# class ScoutPlayer(BaseModelScout):
|
|
# sba_id = IntegerField(primary_key=True)
|
|
# name = CharField()
|
|
# fg_id = IntegerField()
|
|
# br_id = CharField()
|
|
# offense_col = IntegerField()
|
|
# hand = CharField(default='R')
|
|
#
|
|
#
|
|
# scout_db.create_tables([ScoutCardset, ScoutPlayer])
|
|
#
|
|
#
|
|
# class BatterRatings(BaseModelScout):
|
|
# id = CharField(unique=True, primary_key=True)
|
|
# player = ForeignKeyField(ScoutPlayer)
|
|
# cardset = ForeignKeyField(ScoutCardset)
|
|
# vs_hand = FloatField()
|
|
# is_prep = BooleanField()
|
|
# homerun = FloatField()
|
|
# bp_homerun = FloatField()
|
|
# triple = FloatField()
|
|
# double_three = FloatField()
|
|
# double_two = FloatField()
|
|
# double_pull = FloatField()
|
|
# single_two = FloatField()
|
|
# single_one = FloatField()
|
|
# single_center = FloatField()
|
|
# bp_single = FloatField()
|
|
# hbp = FloatField()
|
|
# walk = FloatField()
|
|
# strikeout = FloatField()
|
|
# lineout = FloatField()
|
|
# popout = FloatField()
|
|
# flyout_a = FloatField()
|
|
# flyout_bq = FloatField()
|
|
# flyout_lf_b = FloatField()
|
|
# flyout_rf_b = FloatField()
|
|
# groundout_a = FloatField()
|
|
# groundout_b = FloatField()
|
|
# groundout_c = FloatField()
|
|
# avg = FloatField(null=True)
|
|
# obp = FloatField(null=True)
|
|
# slg = FloatField(null=True)
|
|
#
|
|
#
|
|
# class PitcherRatings(BaseModelScout):
|
|
# id = CharField(unique=True, primary_key=True)
|
|
# player = ForeignKeyField(ScoutPlayer)
|
|
# cardset = ForeignKeyField(ScoutCardset)
|
|
# vs_hand = CharField()
|
|
# is_prep = BooleanField()
|
|
# homerun = FloatField()
|
|
# bp_homerun = FloatField()
|
|
# triple = FloatField()
|
|
# double_three = FloatField()
|
|
# double_two = FloatField()
|
|
# double_cf = FloatField()
|
|
# single_two = FloatField()
|
|
# single_one = FloatField()
|
|
# single_center = FloatField()
|
|
# bp_single = FloatField()
|
|
# hbp = FloatField()
|
|
# walk = FloatField()
|
|
# strikeout = FloatField()
|
|
# fo_slap = FloatField()
|
|
# fo_center = FloatField()
|
|
# groundout_a = FloatField()
|
|
# groundout_b = FloatField()
|
|
# xcheck_p = FloatField()
|
|
# xcheck_c = FloatField()
|
|
# xcheck_1b = FloatField()
|
|
# xcheck_2b = FloatField()
|
|
# xcheck_3b = FloatField()
|
|
# xcheck_ss = FloatField()
|
|
# xcheck_lf = FloatField()
|
|
# xcheck_cf = FloatField()
|
|
# xcheck_rf = FloatField()
|
|
# avg = FloatField(null=True)
|
|
# obp = FloatField(null=True)
|
|
# slg = FloatField(null=True)
|
|
#
|
|
#
|
|
# # scout_db.create_tables([BatterRatings, PitcherRatings])
|
|
#
|
|
#
|
|
# class CardColumns(BaseModelScout):
|
|
# id = CharField(unique=True, primary_key=True)
|
|
# player = ForeignKeyField(ScoutPlayer)
|
|
# hand = CharField()
|
|
# b_ratings = ForeignKeyField(BatterRatings, null=True)
|
|
# p_ratings = ForeignKeyField(PitcherRatings, null=True)
|
|
# one_dice = CharField()
|
|
# one_results = CharField()
|
|
# one_splits = CharField()
|
|
# two_dice = CharField()
|
|
# two_results = CharField()
|
|
# two_splits = CharField()
|
|
# three_dice = CharField()
|
|
# three_results = CharField()
|
|
# three_splits = CharField()
|
|
#
|
|
#
|
|
# class Position(BaseModelScout):
|
|
# player = ForeignKeyField(ScoutPlayer)
|
|
# cardset = ForeignKeyField(ScoutCardset)
|
|
# position = CharField()
|
|
# innings = IntegerField()
|
|
# range = IntegerField()
|
|
# error = IntegerField()
|
|
# arm = CharField(null=True)
|
|
# pb = IntegerField(null=True)
|
|
# overthrow = IntegerField(null=True)
|
|
#
|
|
#
|
|
# class BatterData(BaseModelScout):
|
|
# player = ForeignKeyField(ScoutPlayer)
|
|
# cardset = ForeignKeyField(ScoutCardset)
|
|
# stealing = CharField()
|
|
# st_low = IntegerField()
|
|
# st_high = IntegerField()
|
|
# st_auto = BooleanField()
|
|
# st_jump = FloatField()
|
|
# bunting = CharField(null=True)
|
|
# hit_and_run = CharField(null=True)
|
|
# running = CharField()
|
|
#
|
|
#
|
|
# class PitcherData(BaseModelScout):
|
|
# player = ForeignKeyField(ScoutPlayer)
|
|
# cardset = ForeignKeyField(ScoutCardset)
|
|
# balk = IntegerField(null=True)
|
|
# wild_pitch = IntegerField(null=True)
|
|
# hold = CharField()
|
|
# starter_rating = IntegerField()
|
|
# relief_rating = IntegerField()
|
|
# closer_rating = IntegerField(null=True)
|
|
# batting = CharField(null=True)
|
|
#
|
|
#
|
|
# scout_db.create_tables([CardColumns, Position, BatterData, PitcherData])
|
|
#
|
|
#
|
|
# class CardOutput(BaseModelScout):
|
|
# name = CharField()
|
|
# hand = CharField()
|
|
# positions = CharField()
|
|
# stealing = CharField()
|
|
# bunting = CharField()
|
|
# hitandrun = CharField()
|
|
# running = CharField()
|
|
#
|
|
#
|
|
# scout_db.close()
|