Skip to content

Commit

Permalink
Merge pull request #853 from PennyDreadfulMTG/deck-nullables
Browse files Browse the repository at this point in the history
Nicer display of Host Control Panel, internal fixes
  • Loading branch information
bakert authored Nov 21, 2024
2 parents 7913103 + c884981 commit 24730d5
Show file tree
Hide file tree
Showing 29 changed files with 558 additions and 545 deletions.
6 changes: 3 additions & 3 deletions gatherling/Data/Db.php
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ private function bindParams(PDOStatement $stmt, array $params): void

/**
* @param array<string, mixed> $params
* @return array{0: string, 1: array<string, mixed>}
* @return array{sql: string, params: array<string, mixed>}
*/
private function expandArrayParams(string $sql, array $params): array
{
Expand All @@ -520,7 +520,7 @@ private function expandArrayParams(string $sql, array $params): array
$expandedParams[$key] = $value;
}
}
return [$sql, $expandedParams];
return ['sql' => $sql, 'params' => $expandedParams];
}

/** @param array<string, mixed> $params */
Expand All @@ -539,7 +539,7 @@ private function executeInternal(string $sql, array $params, callable $operation
logger()->warning('[DB] DDL statement issued within transaction, this may cause issues.');
}

[$sql, $params] = $this->expandArrayParams($sql, $params);
['sql' => $sql, 'params' => $params] = $this->expandArrayParams($sql, $params);

try {
$startTime = microtime(true);
Expand Down
1 change: 0 additions & 1 deletion gatherling/Helpers/ErrorHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public function handle(Throwable $e): never
$requestId = Request::getRequestId();

if ($e instanceof NotFoundInDatabaseException) {
// BAKERT this is weak but it's a start
$e = new NotFoundException($e->getMessage(), $e->getCode(), $e, $e->type, $e->ids);
}

Expand Down
96 changes: 45 additions & 51 deletions gatherling/Models/Deck.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

class Deck
{
public ?int $id;
public int $id;
public ?string $name = null;
public ?string $archetype = null;
public ?string $notes = null;
Expand All @@ -25,8 +25,8 @@ class Deck
/** @var array<string> */
public array $errors = [];
public ?string $playername = null; // Belongs to player through entries, now held in decks table
public ?string $eventname; // Belongs to event through entries
public ?int $event_id; // Belongs to event through entries
public ?string $eventname = null; // Belongs to event through entries
public ?int $event_id = null; // Belongs to event through entries
public ?int $subeventid; // Belongs to event
public ?string $format = null; // Belongs to event.. now held in decks table
public ?string $tribe = null; // used only for tribal events
Expand All @@ -36,12 +36,12 @@ class Deck
public ?string $sideboard_hash;
public ?string $whole_hash;
/** @var array<string, int> */
public array $unparsed_cards;
public array $unparsed_cards = [];
/** @var array<string, int> */
public array $unparsed_side;
public ?string $deck_contents_cache;
public array $unparsed_side = [];
public ?string $deck_contents_cache = null;
/** @var ?list<self> */
public ?array $identical_decks;
public ?array $identical_decks = null;
public ?string $medal = null; // has a medal
public bool $new; // is new

Expand All @@ -53,32 +53,35 @@ public function __construct(int $id)
return;
}
$sql = '
SELECT
id, name, playername, archetype, format, tribe, notes, deck_hash,
sideboard_hash, whole_hash, created_date, deck_colors AS deck_color_str
FROM
decks d
WHERE
id = :id';
SELECT id, name, playername, archetype, format, tribe, notes, deck_hash,
sideboard_hash, whole_hash, created_date, deck_colors AS deck_color_str
FROM decks d
WHERE id = :id';
$deck = db()->selectOnlyOrNull($sql, DeckDto::class, ['id' => $id]);
if (!$deck) {
if ($deck === null) {
$this->id = 0;
$this->new = true;
return;
}
foreach (get_object_vars($deck) as $key => $value) {
$this->{$key} = $value;
}
$this->id = $deck->id;
$this->name = $deck->name;
$this->playername = $deck->playername;
$this->archetype = $deck->archetype;
$this->format = $deck->format;
$this->tribe = $deck->tribe;
$this->notes = $deck->notes;
$this->deck_hash = $deck->deck_hash;
$this->sideboard_hash = $deck->sideboard_hash;
$this->whole_hash = $deck->whole_hash;
$this->created_date = $deck->created_date;
$this->deck_color_str = $deck->deck_color_str;
$this->new = false;

if (empty($this->playername)) {
$sql = '
SELECT
p.name
FROM
players p, entries e, decks d
WHERE
p.name = e.player AND d.id = e.deck AND d.id = :id';
SELECT p.name
FROM players p, entries e, decks d
WHERE p.name = e.player AND d.id = e.deck AND d.id = :id';
$this->playername = db()->optionalString($sql, ['id' => $id]);
}

Expand All @@ -90,16 +93,10 @@ public function __construct(int $id)

// Retrieve cards.
$sql = '
SELECT
c.name, dc.qty, dc.issideboard
FROM
cards c, deckcontents dc, decks d
WHERE
d.id = dc.deck
AND c.id = dc.card
AND d.id = :id
ORDER BY
c.name';
SELECT c.name, dc.qty, dc.issideboard
FROM cards c, deckcontents dc, decks d
WHERE d.id = dc.deck AND c.id = dc.card AND d.id = :id
ORDER BY c.name';
$cards = db()->select($sql, DeckCardDto::class, ['id' => $id]);

$this->maindeck_cardcount = 0;
Expand All @@ -116,16 +113,11 @@ public function __construct(int $id)

// Retrieve event
$sql = '
SELECT
e.name, e.id
FROM
events e, entries n, decks d
WHERE
d.id = :id
AND d.id = n.deck
AND n.event_id = e.id';
SELECT e.name, e.id
FROM events e, entries n, decks d
WHERE d.id = :id AND d.id = n.deck AND n.event_id = e.id';
$event = db()->selectOnlyOrNull($sql, DeckEventDto::class, ['id' => $id]);
if ($event) {
if ($event !== null) {
$this->eventname = $event->name;
$this->event_id = $event->id;
}
Expand All @@ -137,14 +129,10 @@ public function __construct(int $id)
// Find subevent id - ignores sub-subevents like finals, which have the same name but different subevent id
if (!is_null($this->eventname)) {
$sql = '
SELECT
events.format
FROM
entries
INNER JOIN
events ON entries.event_id = events.id
WHERE
entries.deck = :id';
SELECT events.format
FROM entries
INNER JOIN events ON entries.event_id = events.id
WHERE entries.deck = :id';
$this->format = db()->optionalString($sql, ['id' => $id]);
$sql = 'SELECT MIN(id) FROM subevents WHERE parent = :eventname';
$this->subeventid = db()->optionalInt($sql, ['eventname' => $this->eventname]);
Expand Down Expand Up @@ -176,6 +164,9 @@ public static function getArchetypes(): array

public function getEntry(): Entry
{
if ($this->event_id === null || $this->playername === null) {
throw new InvalidArgumentException('Cannot get entry for deck without event ID and playername');
}
return new Entry($this->event_id, $this->playername);
}

Expand Down Expand Up @@ -251,6 +242,9 @@ public function getCastingCosts(): array

public function getEvent(): Event
{
if ($this->event_id === null) {
throw new InvalidArgumentException('Cannot get event for deck without event ID');
}
return new Event($this->event_id);
}

Expand Down
61 changes: 27 additions & 34 deletions gatherling/Models/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -467,8 +467,8 @@ public function getFinalists(): array
}

/**
* @param array{0?: ?string, 1?: ?string} $t4
* @param array{0?: ?string, 1?: ?string, 2?: ?string, 3?: ?string} $t8
* @param list<string> $t4
* @param list<string> $t8
*/
public function setFinalists(string $win, ?string $sec, array $t4, array $t8): void
{
Expand Down Expand Up @@ -890,32 +890,34 @@ public function assignTrophiesFromMatches(): void

$finalRounds = $this->finalrounds;
$totalRounds = $this->mainrounds + $finalRounds;
// If this event only has main rounds then those are effectively the "final rounds".
if ($finalRounds === 0) {
$finalRounds = $this->mainrounds;
}

if ($finalRounds > 0) {
$finalMatches = $this->getRoundMatches($totalRounds);
if (!empty($finalMatches)) {
$finalMatch = $finalMatches[0];
$win = $finalMatch->getWinner();
$sec = $finalMatch->getLoser();
}
$finalMatches = $this->getRoundMatches($totalRounds);
if (!empty($finalMatches)) {
$finalMatch = $finalMatches[0];
$win = $finalMatch->getWinner();
$sec = $finalMatch->getLoser();
}

if ($finalRounds >= 2) {
$semiMatches = $this->getRoundMatches($totalRounds - 1);
foreach ($semiMatches as $match) {
$loser = $match->getLoser();
if ($loser !== null) {
$t4[] = $loser;
}
if ($finalRounds >= 2) {
$semiMatches = $this->getRoundMatches($totalRounds - 1);
foreach ($semiMatches as $match) {
$loser = $match->getLoser();
if ($loser !== null) {
$t4[] = $loser;
}
}
}

if ($finalRounds >= 3) {
$quarterMatches = $this->getRoundMatches($totalRounds - 2);
foreach ($quarterMatches as $match) {
$loser = $match->getLoser();
if ($loser !== null) {
$t8[] = $loser;
}
if ($finalRounds >= 3) {
$quarterMatches = $this->getRoundMatches($totalRounds - 2);
foreach ($quarterMatches as $match) {
$loser = $match->getLoser();
if ($loser !== null) {
$t8[] = $loser;
}
}
}
Expand Down Expand Up @@ -997,15 +999,6 @@ public function findNext(): ?self
return null;
}

/** @return array{link: string, text: string} */
public function makeLinkArgs(string $text): array
{
return [
'link' => 'event.php?name=' . rawurlencode($this->name),
'text' => $text,
];
}

public static function count(): int
{
return db()->int('SELECT COUNT(name) FROM events');
Expand Down Expand Up @@ -1645,10 +1638,10 @@ public function assignMedalsByStandings(): void

$t8 = $t4 = [];
if ($medalCount >= 8) {
$t8 = array_map(fn($i) => $players[$i]->player, [4, 5, 6, 7]);
$t8 = array_values(array_filter(array_map(fn($i) => $players[$i]->player ?? null, [4, 5, 6, 7])));
}
if ($medalCount >= 4) {
$t4 = array_map(fn($i) => $players[$i]->player, [2, 3]);
$t4 = array_values(array_filter(array_map(fn($i) => $players[$i]->player ?? null, [2, 3])));
}
$sec = $players[1]->player ?? null;
$win = $players[0]->player;
Expand Down
79 changes: 79 additions & 0 deletions gatherling/Views/Components/EntryListItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

declare(strict_types=1);

namespace Gatherling\Views\Components;

use Gatherling\Models\Entry;
use Gatherling\Models\Standings;

class EntryListItem
{
public int $dropRound;
public string $eventName;
public ?string $emailAddress;
public bool $canDrop = false;
public bool $canUndrop = false;
public string $undropLink = '';
public string $medalSrc = '';
public GameName $gameName;
public ?DeckLink $deckLink = null;
public ?CreateDeckLink $createDeckLink = null;
public bool $invalidRegistration = false;
public string $tribe = '';
public ?InitialByesDropMenu $initialByeDropMenu = null;
public ?InitialSeedDropMenu $initialSeedDropMenu = null;
public bool $canDelete = false;
public ?NotAllowed $notAllowed = null;
public bool $isSwiss = false;
public bool $hasStarted = false;
public int $initialByes = 0;
public bool $isSingleElim = false;
public int $initialSeed = 0;

public function __construct(Entry $entry, int $numEntries, public bool $isTribal)
{
$this->dropRound = $entry->drop_round;
$this->eventName = $entry->event->name;
$this->emailAddress = $entry->player->emailAddress;
if ($entry->event->active == 1) {
$playerActive = Standings::playerActive($entry->event->name, $entry->player->name);
$this->canDrop = $playerActive;
$this->canUndrop = !$playerActive;
$undropParams = [
'view' => 'reg',
'player' => $entry->player->name,
'event' => $entry->event->id,
'action' => 'undrop',
'event_id' => $entry->event->id,
];
$this->undropLink = 'event.php?' . http_build_query($undropParams, '', '&', PHP_QUERY_RFC3986);
}
if ($entry->event->isFinished() && $entry->medal !== '') {
$this->medalSrc = "styles/images/{$entry->medal}.png";
}
$this->gameName = new GameName($entry->player, $entry->event->client);
if ($entry->deck) {
$this->deckLink = new DeckLink($entry->deck);
} else {
$this->createDeckLink = new CreateDeckLink($entry);
}
$this->invalidRegistration = $entry->deck != null && !$entry->deck->isValid();
$this->tribe = $isTribal && $entry->deck !== null && $entry->deck->tribe !== null ? $entry->deck->tribe : '';
$this->isSwiss = $entry->event->isSwiss();
$this->hasStarted = $entry->event->hasStarted();
$this->initialByes = $entry->initial_byes;
$this->isSingleElim = $entry->event->isSingleElim();
$this->initialSeed = $entry->initial_seed;
if ($this->isSwiss && !$this->hasStarted) {
$this->initialByeDropMenu = new InitialByesDropMenu('initial_byes[]', $entry->player->name, $entry->initial_byes);
} elseif ($entry->event->isSingleElim() && !$entry->event->hasStarted()) {
$this->initialSeedDropMenu = new InitialSeedDropMenu('initial_seed[]', $entry->player->name, $entry->initial_seed, $numEntries);
}
if ($entry->canDelete()) {
$this->canDelete = true;
} else {
$this->notAllowed = new NotAllowed("Can't delete player, they have matches recorded.");
}
}
}
Loading

0 comments on commit 24730d5

Please sign in to comment.