backend overhaul
This commit is contained in:
18 files changed
+1824
-1747
No files matched your search
@@ -0,0 +1,366 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class SessionEntry:
|
||||
session_id: str
|
||||
session_date: str
|
||||
player_name: str
|
||||
buy_in_cents: int = 0
|
||||
front_cents: int = 0
|
||||
front_collected_cents: int = 0
|
||||
front_writeoff_cents: int = 0
|
||||
cash_out_cents: int = 0
|
||||
paid_cents: int = 0
|
||||
rollover_in_cents: int = 0
|
||||
payout_carry_in_cents: int = 0
|
||||
rollover_out_cents: int = 0
|
||||
notes: list[str] = field(default_factory=list)
|
||||
|
||||
@property
|
||||
def invested_cents(self) -> int:
|
||||
# Poker performance: money/chips that entered play. This is intentionally
|
||||
# broader than real cash because fronts and rollover-ins affect results.
|
||||
return self.buy_in_cents + self.front_cents + self.rollover_in_cents
|
||||
|
||||
@property
|
||||
def net_cents(self) -> int:
|
||||
return self.cash_out_cents - self.invested_cents
|
||||
|
||||
@property
|
||||
def paid_out_cents(self) -> int:
|
||||
return self.paid_cents
|
||||
|
||||
@property
|
||||
def debt_repayment_cents(self) -> int:
|
||||
return self.front_collected_cents
|
||||
|
||||
@property
|
||||
def writeoff_cents(self) -> int:
|
||||
return self.front_writeoff_cents
|
||||
|
||||
@property
|
||||
def gross_payout_cents(self) -> int:
|
||||
# Settlement: cashout is a gross chip count/result, not proof that cash
|
||||
# was paid. Fronts are recovered from the cashout before the player has
|
||||
# a claim against the house.
|
||||
return max(self.cash_out_cents - self.front_cents, 0)
|
||||
|
||||
@property
|
||||
def player_owes_gross_cents(self) -> int:
|
||||
return max(self.front_cents - self.cash_out_cents, 0)
|
||||
|
||||
@property
|
||||
def gross_due_to_house_cents(self) -> int:
|
||||
return self.player_owes_gross_cents
|
||||
|
||||
@property
|
||||
def settled_to_player_cents(self) -> int:
|
||||
# Rollover-out resolves the source session's payable even though it is
|
||||
# not real cash out. The destination session records it as rollover-in.
|
||||
return self.paid_out_cents + self.rollover_out_cents
|
||||
|
||||
@property
|
||||
def current_due_to_player_cents(self) -> int:
|
||||
return max(
|
||||
self.gross_payout_cents
|
||||
+ self.payout_carry_in_cents
|
||||
- self.settled_to_player_cents,
|
||||
0,
|
||||
)
|
||||
|
||||
@property
|
||||
def settled_to_house_cents(self) -> int:
|
||||
# Front collections are real cash in. Writeoffs are not cash, but they
|
||||
# do resolve the receivable.
|
||||
return self.debt_repayment_cents + self.writeoff_cents
|
||||
|
||||
@property
|
||||
def current_due_to_house_cents(self) -> int:
|
||||
return max(self.gross_due_to_house_cents - self.settled_to_house_cents, 0)
|
||||
|
||||
@property
|
||||
def real_cash_in_cents(self) -> int:
|
||||
return self.buy_in_cents + self.debt_repayment_cents
|
||||
|
||||
@property
|
||||
def real_cash_out_cents(self) -> int:
|
||||
return self.paid_out_cents
|
||||
|
||||
@property
|
||||
def payout_due_cents(self) -> int:
|
||||
return self.gross_payout_cents
|
||||
|
||||
@property
|
||||
def payout_remaining_cents(self) -> int:
|
||||
return self.current_due_to_player_cents
|
||||
|
||||
@property
|
||||
def settled_cents(self) -> int:
|
||||
return self.settled_to_player_cents
|
||||
|
||||
@property
|
||||
def current_due_cents(self) -> int:
|
||||
return self.current_due_to_player_cents
|
||||
|
||||
@property
|
||||
def player_owes_cents(self) -> int:
|
||||
return self.current_due_to_house_cents
|
||||
|
||||
@property
|
||||
def raw_player_owes_cents(self) -> int:
|
||||
return self.gross_due_to_house_cents
|
||||
|
||||
@property
|
||||
def front_shortfall_cents(self) -> int:
|
||||
return self.gross_due_to_house_cents
|
||||
|
||||
@property
|
||||
def overpaid_front_cents(self) -> int:
|
||||
return 0
|
||||
|
||||
@property
|
||||
def front_writeoff_applied_cents(self) -> int:
|
||||
return min(
|
||||
self.writeoff_cents,
|
||||
max(self.gross_due_to_house_cents - self.front_collected_applied_cents, 0),
|
||||
)
|
||||
|
||||
@property
|
||||
def front_collected_applied_cents(self) -> int:
|
||||
return min(self.debt_repayment_cents, self.gross_due_to_house_cents)
|
||||
|
||||
@property
|
||||
def front_resolved_cents(self) -> int:
|
||||
return min(self.settled_to_house_cents, self.gross_due_to_house_cents)
|
||||
|
||||
@property
|
||||
def payout_status(self) -> str:
|
||||
if self.current_due_to_house_cents > 0:
|
||||
return "owes"
|
||||
if self.writeoff_cents > 0:
|
||||
return "written_off"
|
||||
if self.debt_repayment_cents > 0:
|
||||
return "collected"
|
||||
if self.gross_payout_cents <= 0:
|
||||
return "none"
|
||||
if self.current_due_to_player_cents <= 0:
|
||||
if self.paid_out_cents < self.gross_payout_cents:
|
||||
return "settled"
|
||||
return "paid"
|
||||
if self.settled_to_player_cents <= 0:
|
||||
return "unpaid"
|
||||
return "partial"
|
||||
|
||||
|
||||
@dataclass
|
||||
class SessionSummary:
|
||||
session_id: str
|
||||
session_date: str
|
||||
entries: list[SessionEntry]
|
||||
status: str = "closed"
|
||||
opened_at: str = ""
|
||||
|
||||
@property
|
||||
def is_open(self) -> bool:
|
||||
return self.status == "open"
|
||||
|
||||
@property
|
||||
def total_buy_in_cents(self) -> int:
|
||||
return sum(entry.buy_in_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_front_cents(self) -> int:
|
||||
return sum(entry.front_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_rollover_in_cents(self) -> int:
|
||||
return sum(entry.rollover_in_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_payout_carry_in_cents(self) -> int:
|
||||
return sum(entry.payout_carry_in_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_invested_cents(self) -> int:
|
||||
return sum(entry.invested_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_cash_out_cents(self) -> int:
|
||||
return sum(entry.cash_out_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_payout_due_cents(self) -> int:
|
||||
return self.total_gross_payout_cents
|
||||
|
||||
@property
|
||||
def total_remaining_cents(self) -> int:
|
||||
return self.total_current_due_to_player_cents
|
||||
|
||||
@property
|
||||
def total_net_cents(self) -> int:
|
||||
return sum(entry.net_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_gross_payout_cents(self) -> int:
|
||||
return sum(entry.gross_payout_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_paid_cents(self) -> int:
|
||||
return self.total_paid_out_cents
|
||||
|
||||
@property
|
||||
def total_paid_out_cents(self) -> int:
|
||||
return sum(entry.paid_out_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_rollover_out_cents(self) -> int:
|
||||
return sum(entry.rollover_out_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_settled_to_player_cents(self) -> int:
|
||||
return sum(entry.settled_to_player_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_current_due_to_player_cents(self) -> int:
|
||||
return sum(entry.current_due_to_player_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_player_owes_gross_cents(self) -> int:
|
||||
return sum(entry.gross_due_to_house_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_gross_due_to_house_cents(self) -> int:
|
||||
return self.total_player_owes_gross_cents
|
||||
|
||||
@property
|
||||
def total_settled_to_house_cents(self) -> int:
|
||||
return sum(entry.settled_to_house_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_current_due_to_house_cents(self) -> int:
|
||||
return sum(entry.current_due_to_house_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_front_writeoff_cents(self) -> int:
|
||||
return self.total_writeoff_cents
|
||||
|
||||
@property
|
||||
def total_front_collected_cents(self) -> int:
|
||||
return self.total_debt_repayment_cents
|
||||
|
||||
@property
|
||||
def total_debt_repayment_cents(self) -> int:
|
||||
return sum(entry.debt_repayment_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_writeoff_cents(self) -> int:
|
||||
return sum(entry.writeoff_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_cash_in_cents(self) -> int:
|
||||
return sum(entry.real_cash_in_cents for entry in self.entries)
|
||||
|
||||
@property
|
||||
def total_real_cash_in_cents(self) -> int:
|
||||
return self.total_cash_in_cents
|
||||
|
||||
@property
|
||||
def total_real_cash_out_cents(self) -> int:
|
||||
return self.total_paid_out_cents
|
||||
|
||||
@property
|
||||
def total_banker_cash_in_cents(self) -> int:
|
||||
return self.total_real_cash_in_cents
|
||||
|
||||
@property
|
||||
def total_banker_cash_out_cents(self) -> int:
|
||||
return self.total_real_cash_out_cents
|
||||
|
||||
@property
|
||||
def total_current_due_cents(self) -> int:
|
||||
return self.total_current_due_to_player_cents
|
||||
|
||||
@property
|
||||
def total_player_owes_cents(self) -> int:
|
||||
return self.total_current_due_to_house_cents
|
||||
|
||||
@property
|
||||
def total_open_balance_cents(self) -> int:
|
||||
return self.total_current_due_to_player_cents - self.total_current_due_to_house_cents
|
||||
|
||||
@property
|
||||
def total_net_book_position_cents(self) -> int:
|
||||
# Banker view: cash currently held, plus collectible receivables, minus
|
||||
# unpaid player claims. Rollover-outs reduce payables but are not cash.
|
||||
return (
|
||||
self.total_cash_in_cents
|
||||
- self.total_paid_out_cents
|
||||
+ self.total_current_due_to_house_cents
|
||||
- self.total_current_due_to_player_cents
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class PlayerStats:
|
||||
player_name: str
|
||||
sessions_played: int
|
||||
winning_sessions: int
|
||||
losing_sessions: int
|
||||
break_even_sessions: int
|
||||
win_pct: float
|
||||
avg_win_cents: int
|
||||
avg_loss_cents: int
|
||||
biggest_win_cents: int
|
||||
biggest_loss_cents: int
|
||||
total_buy_in_cents: int
|
||||
total_front_cents: int
|
||||
total_front_collected_cents: int
|
||||
total_front_writeoff_cents: int
|
||||
current_player_owes_cents: int
|
||||
total_rollover_in_cents: int
|
||||
total_payout_carry_in_cents: int
|
||||
total_invested_cents: int
|
||||
total_cash_out_cents: int
|
||||
total_gross_payout_cents: int
|
||||
total_paid_cents: int
|
||||
total_rollover_out_cents: int
|
||||
current_due_to_player_cents: int
|
||||
total_net_cents: int
|
||||
roi_pct: float
|
||||
current_win_streak: int
|
||||
current_loss_streak: int
|
||||
longest_win_streak: int
|
||||
longest_loss_streak: int
|
||||
best_session_date: str | None
|
||||
best_session_net_cents: int
|
||||
worst_session_date: str | None
|
||||
worst_session_net_cents: int
|
||||
rank_change: int = 0
|
||||
|
||||
@property
|
||||
def total_debt_repayment_cents(self) -> int:
|
||||
return self.total_front_collected_cents
|
||||
|
||||
@property
|
||||
def total_writeoff_cents(self) -> int:
|
||||
return self.total_front_writeoff_cents
|
||||
|
||||
@property
|
||||
def current_due_to_house_cents(self) -> int:
|
||||
return self.current_player_owes_cents
|
||||
|
||||
@property
|
||||
def total_paid_out_cents(self) -> int:
|
||||
return self.total_paid_cents
|
||||
|
||||
@property
|
||||
def total_real_cash_out_cents(self) -> int:
|
||||
return self.total_paid_out_cents
|
||||
|
||||
@property
|
||||
def total_real_cash_in_cents(self) -> int:
|
||||
return self.total_buy_in_cents + self.total_debt_repayment_cents
|
||||
Reference in new issue
Block a user