First pass of real card gen

This commit is contained in:
Cal Corum 2023-10-11 00:58:30 -05:00
parent 1776df7173
commit 485a046855
5 changed files with 812 additions and 65 deletions

File diff suppressed because one or more lines are too long

View File

@ -577,6 +577,9 @@ BattingCard.add_index(bc_index)
class BattingCardRatings(BaseModel): class BattingCardRatings(BaseModel):
battingcard = ForeignKeyField(BattingCard) battingcard = ForeignKeyField(BattingCard)
vs_hand = CharField(default='R') vs_hand = CharField(default='R')
pull_rate: FloatField()
center_rate: FloatField()
slap_rate: FloatField()
homerun = FloatField() homerun = FloatField()
bp_homerun = FloatField() bp_homerun = FloatField()
triple = FloatField() triple = FloatField()

View File

@ -1,7 +1,8 @@
import os import os
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.templating import Jinja2Templates # from fastapi.staticfiles import StaticFiles
# from fastapi.templating import Jinja2Templates
from .routers_v2 import ( from .routers_v2 import (
current, teams, rarity, cardsets, players, packtypes, packs, cards, events, results, rewards, current, teams, rarity, cardsets, players, packtypes, packs, cards, events, results, rewards,
@ -12,6 +13,7 @@ app = FastAPI(
responses={404: {'description': 'Not found'}} responses={404: {'description': 'Not found'}}
) )
# app.mount("/static", StaticFiles(directory="storage/static"), name="static")
# templates = Jinja2Templates(directory=os.path.dirname(os.path.abspath(__file__))) # templates = Jinja2Templates(directory=os.path.dirname(os.path.abspath(__file__)))
app.include_router(current.router) app.include_router(current.router)

View File

@ -4,7 +4,7 @@ import logging
import pydantic import pydantic
from pydantic import root_validator from pydantic import root_validator
from ..db_engine import db, CardPosition, model_to_dict, chunked, Player from ..db_engine import db, CardPosition, model_to_dict, chunked, Player, fn
from ..dependencies import oauth2_scheme, valid_token, LOG_DATA from ..dependencies import oauth2_scheme, valid_token, LOG_DATA
logging.basicConfig( logging.basicConfig(
@ -22,7 +22,7 @@ router = APIRouter(
class CardPositionModel(pydantic.BaseModel): class CardPositionModel(pydantic.BaseModel):
player_id: int player_id: int
variant: int = 0 variant: int = 0
position: Literal['P', 'C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF'] position: Literal['P', 'C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF', 'DH']
innings: int = 1 innings: int = 1
range: int = 5 range: int = 5
error: int = 0 error: int = 0
@ -45,10 +45,10 @@ class PositionList(pydantic.BaseModel):
@router.get('') @router.get('')
async def get_card_positions( async def get_card_positions(
player_id: Optional[int] = None, position: list = Query(default=None), min_innings: Optional[int] = 1, player_id: list = Query(default=None), position: list = Query(default=None), min_innings: Optional[int] = 1,
r: list = Query(default=None), e: list = Query(default=None), arm: list = Query(default=None), r: list = Query(default=None), e: list = Query(default=None), arm: list = Query(default=None),
pb: list = Query(default=None), overthrow: list = Query(default=None), cardset_id: list = Query(default=None), pb: list = Query(default=None), overthrow: list = Query(default=None), cardset_id: list = Query(default=None),
short_output: Optional[bool] = False): short_output: Optional[bool] = False, sort: Optional[str] = 'innings-desc'):
all_pos = CardPosition.select().where(CardPosition.innings >= min_innings).order_by( all_pos = CardPosition.select().where(CardPosition.innings >= min_innings).order_by(
CardPosition.player, CardPosition.position, CardPosition.variant CardPosition.player, CardPosition.position, CardPosition.variant
) )
@ -56,7 +56,8 @@ async def get_card_positions(
if player_id is not None: if player_id is not None:
all_pos = all_pos.where(CardPosition.player_id << player_id) all_pos = all_pos.where(CardPosition.player_id << player_id)
if position is not None: if position is not None:
all_pos = all_pos.where(CardPosition.position << position) p_list = [x.lower() for x in position]
all_pos = all_pos.where(fn.Lower(CardPosition.position) << p_list)
if r is not None: if r is not None:
all_pos = all_pos.where(CardPosition.range << r) all_pos = all_pos.where(CardPosition.range << r)
if e is not None: if e is not None:
@ -67,10 +68,19 @@ async def get_card_positions(
all_pos = all_pos.where(CardPosition.pb << pb) all_pos = all_pos.where(CardPosition.pb << pb)
if overthrow is not None: if overthrow is not None:
all_pos = all_pos.where(CardPosition.overthrow << overthrow) all_pos = all_pos.where(CardPosition.overthrow << overthrow)
if position is not None: if cardset_id is not None:
all_players = Player.select().where(Player.cardset_id << cardset_id) all_players = Player.select().where(Player.cardset_id << cardset_id)
all_pos = all_pos.where(CardPosition.player << all_players) all_pos = all_pos.where(CardPosition.player << all_players)
if sort == 'innings-desc':
all_pos = all_pos.order_by(CardPosition.innings.desc())
elif sort == 'innings-asc':
all_pos = all_pos.order_by(CardPosition.innings)
elif sort == 'range-desc':
all_pos = all_pos.order_by(CardPosition.range.desc())
elif sort == 'range-asc':
all_pos = all_pos.order_by(CardPosition.range)
return_val = {'count': all_pos.count(), 'positions': [ return_val = {'count': all_pos.count(), 'positions': [
model_to_dict(x, recurse=not short_output) for x in all_pos model_to_dict(x, recurse=not short_output) for x in all_pos
]} ]}

View File

@ -1,17 +1,18 @@
import os.path import os.path
import base64
from fastapi import APIRouter, Depends, HTTPException, Request, Response, Query from fastapi import APIRouter, Depends, HTTPException, Request, Response, Query
from fastapi.responses import FileResponse from fastapi.responses import FileResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from html2image import Html2Image from html2image import Html2Image
from typing import Optional, List from typing import Optional, List, Literal
import logging import logging
import pydantic import pydantic
from pandas import DataFrame from pandas import DataFrame
from ..card_creation import get_batter_card_html, get_batter_card_data from ..card_creation import get_batter_card_data, get_pitcher_card_data
from ..db_engine import db, Player, model_to_dict, fn, chunked, Paperdex, Cardset, Rarity, BattingCard, \ from ..db_engine import db, Player, model_to_dict, fn, chunked, Paperdex, Cardset, Rarity, BattingCard, \
BattingCardRatings BattingCardRatings, PitchingCard, PitchingCardRatings, CardPosition
from ..dependencies import oauth2_scheme, valid_token, LOG_DATA from ..dependencies import oauth2_scheme, valid_token, LOG_DATA
logging.basicConfig( logging.basicConfig(
@ -329,57 +330,70 @@ async def get_one_player(player_id, csv: Optional[bool] = False):
return return_val return return_val
@router.get('/{player_id}/battingcard') @router.get('/{player_id}/{card_type}card')
async def get_player_card( async def get_batter_card(
request: Request, player_id: int, variant: int = 0, d: str = None, html: Optional[bool] = False): request: Request, player_id: int, card_type: Literal['batting', 'pitching'], variant: int = 0, d: str = None,
if os.path.isfile(f'storage/cards/{player_id}-{d}-v{variant}.png') and html is False: html: Optional[bool] = False):
db.close()
return FileResponse(
path=f'storage/cards/{player_id}-{d}-v{variant}.png',
media_type='image/png'
)
try: try:
this_player = Player.get_by_id(player_id) this_player = Player.get_by_id(player_id)
except Exception: except Exception:
db.close() db.close()
raise HTTPException(status_code=404, detail=f'No player found with id {player_id}') raise HTTPException(status_code=404, detail=f'No player found with id {player_id}')
this_bc = BattingCard.get_or_none(BattingCard.player == this_player, BattingCard.variant == variant) if os.path.isfile(f'storage/cards/cardset-{this_player.cardset.id}/{player_id}-{d}-v{variant}.png') and html is False:
if this_bc is None: db.close()
raise HTTPException(status_code=404, detail=f'Batting card not found for id {player_id}, variant {variant}') return FileResponse(
path=f'storage/cards/cardset-{this_player.cardset.id}/{player_id}-{d}-v{variant}.png',
media_type='image/png'
)
rating_vl = BattingCardRatings.get_or_none( all_pos = CardPosition.select().where(CardPosition.player == this_player).order_by(CardPosition.innings.desc())
BattingCardRatings.battingcard == this_bc, BattingCardRatings.vs_hand == 'L')
rating_vr = BattingCardRatings.get_or_none(
BattingCardRatings.battingcard == this_bc, BattingCardRatings.vs_hand == 'R')
if None in [rating_vr, rating_vl]:
raise HTTPException(status_code=404, detail=f'Ratings not found for batting card {this_bc.id}')
hti = Html2Image( if card_type == 'batting':
browser='chromium', this_bc = BattingCard.get_or_none(BattingCard.player == this_player, BattingCard.variant == variant)
size=(1200, 600), if this_bc is None:
output_path=f'storage/cards', raise HTTPException(status_code=404, detail=f'Batting card not found for id {player_id}, variant {variant}')
custom_flags=['--no-sandbox', '--disable-remote-debugging', '--headless', '--disable-gpu',
'--disable-software-rasterizer', '--disable-dev-shm-usage'] rating_vl = BattingCardRatings.get_or_none(
) BattingCardRatings.battingcard == this_bc, BattingCardRatings.vs_hand == 'L')
card_data = { rating_vr = BattingCardRatings.get_or_none(
'player': this_player, BattingCardRatings.battingcard == this_bc, BattingCardRatings.vs_hand == 'R')
'card_type': 'batter', if None in [rating_vr, rating_vl]:
'results_vl_one': 'Big Dongs', raise HTTPException(status_code=404, detail=f'Ratings not found for batting card {this_bc.id}')
'results_vl_two': 'Lesser Dongs',
'results_vl_three': 'Sad Dongs', card_data = get_batter_card_data(this_player, this_bc, rating_vl, rating_vr, all_pos)
'results_vr_one': 'Light Dongs', card_data['request'] = request
'results_vr_two': 'Hefty Dongs', html_response = templates.TemplateResponse("player_card.html", card_data)
'results_vr_three': 'Obese Dongs',
'request': request else:
} this_pc = PitchingCard.get_or_none(PitchingCard.player == this_player, PitchingCard.variant == variant)
html_response = templates.TemplateResponse("player_card.html", card_data) if this_pc is None:
raise HTTPException(
status_code=404, detail=f'Pitching card not found for id {player_id}, variant {variant}')
rating_vl = PitchingCardRatings.get_or_none(
PitchingCardRatings.pitchingcard == this_pc, PitchingCardRatings.vs_hand == 'L')
rating_vr = PitchingCardRatings.get_or_none(
PitchingCardRatings.pitchingcard == this_pc, PitchingCardRatings.vs_hand == 'R')
if None in [rating_vr, rating_vl]:
raise HTTPException(status_code=404, detail=f'Ratings not found for pitching card {this_pc.id}')
card_data = get_pitcher_card_data(this_player, this_pc, rating_vl, rating_vr, all_pos)
card_data['request'] = request
html_response = templates.TemplateResponse("player_card.html", card_data)
if html: if html:
db.close() db.close()
return html_response return html_response
hti = Html2Image(
browser='chromium',
size=(1200, 600),
output_path=f'storage/cards/cardset-{this_player.cardset.id}/',
custom_flags=['--no-sandbox', '--disable-remote-debugging', '--headless', '--disable-gpu',
'--disable-software-rasterizer', '--disable-dev-shm-usage']
)
logging.debug(f'body:\n{html_response.body.decode("UTF-8")}') logging.debug(f'body:\n{html_response.body.decode("UTF-8")}')
x = hti.screenshot( x = hti.screenshot(
html_str=str(html_response.body.decode("UTF-8")), html_str=str(html_response.body.decode("UTF-8")),
@ -390,6 +404,11 @@ async def get_player_card(
return FileResponse(path=x[0], media_type='image/png') return FileResponse(path=x[0], media_type='image/png')
# @router.get('/{player_id}/pitchingcard')
# async def get_pitcher_card(
# request: Request, player_id: int, variant: int = 0, d: str = None, html: Optional[bool] = False)
@router.patch('/{player_id}') @router.patch('/{player_id}')
async def v1_players_patch( async def v1_players_patch(
player_id, name: Optional[str] = None, image: Optional[str] = None, image2: Optional[str] = None, player_id, name: Optional[str] = None, image: Optional[str] = None, image2: Optional[str] = None,
@ -444,42 +463,42 @@ async def v1_players_patch(
raise HTTPException(status_code=404, detail=f'No rarity found with id {rarity_id}') raise HTTPException(status_code=404, detail=f'No rarity found with id {rarity_id}')
this_player.rarity = this_rarity this_player.rarity = this_rarity
if pos_1 is not None: if pos_1 is not None:
if pos_1 == 'False': if pos_1 in ['None', 'False', '']:
this_player.pos_1 = None this_player.pos_1 = None
else: else:
this_player.pos_1 = pos_1 this_player.pos_1 = pos_1
if pos_2 is not None: if pos_2 is not None:
if pos_2 == 'False': if pos_2 in ['None', 'False', '']:
this_player.pos_2 = None this_player.pos_2 = None
else: else:
this_player.pos_2 = pos_2 this_player.pos_2 = pos_2
if pos_3 is not None: if pos_3 is not None:
if pos_3 == 'False': if pos_3 in ['None', 'False', '']:
this_player.pos_3 = None this_player.pos_3 = None
else: else:
this_player.pos_3 = pos_3 this_player.pos_3 = pos_3
if pos_4 is not None: if pos_4 is not None:
if pos_4 == 'False': if pos_4 in ['None', 'False', '']:
this_player.pos_4 = None this_player.pos_4 = None
else: else:
this_player.pos_4 = pos_4 this_player.pos_4 = pos_4
if pos_5 is not None: if pos_5 is not None:
if pos_5 == 'False': if pos_5 in ['None', 'False', '']:
this_player.pos_5 = None this_player.pos_5 = None
else: else:
this_player.pos_5 = pos_5 this_player.pos_5 = pos_5
if pos_6 is not None: if pos_6 is not None:
if pos_6 == 'False': if pos_6 in ['None', 'False', '']:
this_player.pos_6 = None this_player.pos_6 = None
else: else:
this_player.pos_6 = pos_6 this_player.pos_6 = pos_6
if pos_7 is not None: if pos_7 is not None:
if pos_7 == 'False': if pos_7 in ['None', 'False', '']:
this_player.pos_7 = None this_player.pos_7 = None
else: else:
this_player.pos_7 = pos_7 this_player.pos_7 = pos_7
if pos_8 is not None: if pos_8 is not None:
if pos_8 == 'False': if pos_8 in ['None', 'False', '']:
this_player.pos_8 = None this_player.pos_8 = None
else: else:
this_player.pos_8 = pos_8 this_player.pos_8 = pos_8