Skip to content

Commit

Permalink
Assigned Seating (#569)
Browse files Browse the repository at this point in the history
* Initial Seating for pure Single Elimination events

* Apply fixes from StyleCI

* Fix tests

---------

Co-authored-by: StyleCI Bot <bot@styleci.io>
  • Loading branch information
silasary and StyleCIBot authored Nov 2, 2023
1 parent 3571192 commit 11785d6
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 21 deletions.
4 changes: 4 additions & 0 deletions gatherling/admin/db-upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,10 @@ function redirect_deck_update($latest_id = 0)
ADD COLUMN `discord_channel_id` VARCHAR(20) NULL DEFAULT NULL AFTER `discord_guild_id`,
CHANGE COLUMN `discord_require_membership` `discord_require_membership` INT NULL DEFAULT NULL AFTER `discord_guild_invite`;');
});
upgrade_db(51, 'Add Initial Seed', function () {
do_query('ALTER TABLE `entries`
ADD COLUMN `initial_seed` INT NULL DEFAULT 127 AFTER `initial_byes`;');
});
$db->autocommit(true);

info('DB is up to date!');
54 changes: 49 additions & 5 deletions gatherling/event.php
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,12 @@ function playerList($event)
if ($format->tribal) {
echo '<th>Tribe</th>';
}
echo '<th>Byes</th>';
if ($event->mainstruct == 'Swiss')
echo '<th>Byes</th>';
elseif ($event->mainstruct == 'Single Elimination')
echo '<th>Seed</th>';
else
echo '<th></th>';
echo '<th>Delete</th></tr>';
} else {
echo '<tr><td align="center" colspan="5"><i>';
Expand Down Expand Up @@ -797,10 +802,21 @@ function playerList($event)
}
}
echo '<td align="center">';
if ($event->active == 1 || $event->finalized) {
echo $entry->initial_byes;
} else {
initialByeDropMenu('initial_byes[]', $entry->player->name, $entry->initial_byes);
if ($event->mainstruct == 'Swiss')
{
if ($event->active == 1 || $event->finalized) {
echo $entry->initial_byes;
} else {
initialByeDropMenu('initial_byes[]', $entry->player->name, $entry->initial_byes);
}
}
elseif ($event->mainstruct == 'Single Elimination')
{
if ($event->active == 1 || $event->finalized) {
echo $entry->initial_seed;
} else {
initialSeedDropMenu('initial_seed[]', $entry->player->name, $entry->initial_seed, $numentries);
}
}
echo '</td>';
echo '<td align="center">';
Expand Down Expand Up @@ -844,6 +860,8 @@ function playerList($event)
if ($event->active == 0 && $event->finalized == 0) {
echo '<table><tr><td colspan="2">';
echo '<font color= "red"><b><p class="squeeze">Warning: Players who have not entered deck lists will be dropped automatically!</p></b></font>';
if ($event->mainstruct == 'Single Elimination')
echo '<p>Note: When assigning initial seeds, players will be paired 1v2, 3v4, 5v6, etc.</p>';
echo '</td></tr></table>';
}

Expand Down Expand Up @@ -1529,6 +1547,16 @@ function initialByeDropMenu($name = 'initial_byes', $playername = '', $current_b
echo '</select>';
}

function initialSeedDropMenu($name = 'initial_seed', $playername = '', $current_seed = 127, $numentries = 8)
{
echo "<select class=\"inputbox\" name=\"{$name}\">";
echo "<option value=\"$playername 127\"".($current_seed == 127 ? ' selected' : '').'>None</option>';
for ($i = 1; $i <= $numentries; $i++) {
echo "<option value=\"$playername $i\"".($current_seed == $i ? ' selected' : '').">$i</option>";
}
echo '</select>';
}

function controlPanel($event, $cur = '')
{
$name = $event->name;
Expand Down Expand Up @@ -1587,6 +1615,22 @@ function updateReg()
}
}
}

if (isset($_POST['initial_seed'])) {
foreach ($_POST['initial_seed'] as $seeddata) {
if (!empty(trim($seeddata))) {
$array_data = explode(' ', $seeddata);
$seed = intval($array_data[count($array_data) - 1]);
unset($array_data[count($array_data) - 1]);
$playername = implode(' ', $array_data);
if (in_array($playername, $dropped)) {
continue;
}
$entry = new Entry($event->id, $playername);
$entry->setInitialSeed($seed);
}
}
}
}

function updateMatches()
Expand Down
2 changes: 1 addition & 1 deletion gatherling/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

include 'lib.php';
$version = Database::single_result('SELECT version FROM db_version LIMIT 1');
if ($version < 42) {
if ($version < 51) {
$gatherlingoutofservice = 1;
}

Expand Down
27 changes: 25 additions & 2 deletions gatherling/models/Entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Entry
public $medal;
public $drop_round;
public $initial_byes;
public $initial_seed;
public $ignored;

public static function findByEventAndPlayer($event_id, $playername)
Expand Down Expand Up @@ -84,12 +85,12 @@ public static function playerRegistered($eventid, $playername)
public function __construct($event_id, $playername)
{
$db = Database::getConnection();
$stmt = $db->prepare('SELECT deck, medal, ignored, drop_round, initial_byes FROM entries WHERE event_id = ? AND player = ?');
$stmt = $db->prepare('SELECT deck, medal, ignored, drop_round, initial_byes, initial_seed FROM entries WHERE event_id = ? AND player = ?');
$stmt or exit($db->error);
$stmt->bind_param('ds', $event_id, $playername);
$stmt->execute();
$this->ignored = 0;
$stmt->bind_result($deckid, $this->medal, $this->ignored, $this->drop_round, $this->initial_byes);
$stmt->bind_result($deckid, $this->medal, $this->ignored, $this->drop_round, $this->initial_byes, $this->initial_seed);

if ($stmt->fetch() == null) {
throw new Exception('Entry for '.$playername.' in '.$event_id.' not found');
Expand Down Expand Up @@ -207,6 +208,11 @@ public function createDeckLink()
}
}

/**
* @param int $byeqty
*
* @return void
*/
public function setInitialByes($byeqty)
{
$db = Database::getConnection();
Expand All @@ -223,4 +229,21 @@ public function setInitialByes($byeqty)
$db->commit();
$db->autocommit(true);
}

public function setInitialSeed($byeqty)
{
$db = Database::getConnection();
$db->autocommit(false);
$stmt = $db->prepare('UPDATE entries SET initial_seed = ? WHERE player = ? AND event_id = ?');
$stmt->bind_param('dsd', $byeqty, $this->player->name, $this->event->id);
$stmt->execute();
if ($stmt->affected_rows < 0) {
$db->rollback();
$db->autocommit(true);

throw new Exception('Entry for '.$this->player->name.' in '.$this->event->name.' not found');
}
$db->commit();
$db->autocommit(true);
}
}
27 changes: 20 additions & 7 deletions gatherling/models/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,9 @@ public function getEntriesByMedal()
);
}

/**
* @return Entry[]
*/
public function getEntries()
{
$players = $this->getPlayers();
Expand All @@ -672,7 +675,12 @@ public function getEntries()
return $entries;
}

public function getRegisteredEntries($deleteinvalid = false)
/**
* @param bool $deleteinvalid
*
* @return Entry[]
*/
public function getRegisteredEntries($deleteinvalid = false, $skip_invalid = false)
{
$players = $this->getPlayers();

Expand All @@ -682,8 +690,11 @@ public function getRegisteredEntries($deleteinvalid = false)
if (is_null($entry->deck) || !$entry->deck->isValid()) {
if ($deleteinvalid) {
$entry->removeEntry($player);
continue;
}
if ($skip_invalid) {
continue;
}
continue;
}
$entries[] = $entry;
}
Expand Down Expand Up @@ -1175,7 +1186,7 @@ public function isLeague()
// All this should probably go somewhere else
// Pairs the round which is currently running.
// This should probably be in Standings?
public function pairCurrentRound()
public function pairCurrentRound($skip_invalid = false)
{
//Check if all matches in the current round are finished
if (count($this->unfinishedMatches()) === 0) {
Expand All @@ -1202,7 +1213,7 @@ public function pairCurrentRound()
switch ($structure) {
case 'Swiss':
case 'Swiss (Blossom)':
$this->swissPairingBlossom($subevent_id);
$this->swissPairingBlossom($subevent_id, $skip_invalid);
break;
case 'Single Elimination':
$this->singleElimination($round);
Expand Down Expand Up @@ -1233,12 +1244,14 @@ public function pairCurrentRound()
}

// Pairs the current swiss round by using the Blossom method
public function swissPairingBlossom($subevent_id)
public function swissPairingBlossom($subevent_id, $skip_invalid)
{
Standings::resetMatched($this->name);
$active_entries = Entry::getActivePlayers($this->id);

$this->skipInvalidDecks($active_entries);
if ($skip_invalid) {
$this->skipInvalidDecks($active_entries);
}
$this->assignInitialByes($active_entries, $this->current_round + 1);

$db = Database::getConnection();
Expand Down Expand Up @@ -1832,7 +1845,7 @@ public function startEvent($precheck)
$entries = $this->getRegisteredEntries($precheck);
Standings::startEvent($entries, $this->name);
// $this->dropInvalidEntries();
$this->pairCurrentRound();
$this->pairCurrentRound($precheck);
$this->active = 1;
$this->save();
}
Expand Down
13 changes: 9 additions & 4 deletions gatherling/models/Standings.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Standings
public $matched;
public $new;

public function __construct($eventname, $playername)
public function __construct($eventname, $playername, $initial_seed = 127)
{
// Check to see if we are doing event standings of player standings
if ($playername == '0') {
Expand All @@ -31,7 +31,6 @@ public function __construct($eventname, $playername)

return;
} else {
//echo "past loop";
$db = Database::getConnection();
$stmt = $db->prepare('SELECT active, matches_played, games_won, games_played, byes, OP_Match, PL_Game, OP_Game, score, seed, matched, matches_won, draws FROM standings WHERE event = ? AND player = ? limit 1');
$stmt or exit($db->error);
Expand All @@ -42,6 +41,7 @@ public function __construct($eventname, $playername)
$this->event = $eventname;
if ($stmt->fetch() == null) { // No entry in standings table,
$this->new = true;
$this->seed = $initial_seed;
}
$stmt->close();
}
Expand All @@ -63,7 +63,6 @@ public function save()
$this->OP_Match = 0;
$this->PL_Game = 0;
$this->OP_Game = 0;
$this->seed = 127;
$this->matched = 0;
$this->draws = 0;

Expand Down Expand Up @@ -327,10 +326,16 @@ public function League_getAvailable_Opponents($subevent, $round)
return $opponent_names;
}

/**
* @param Entry[] $entries
* @param string $event_name
*
* @return void
*/
public static function startEvent($entries, $event_name)
{
foreach ($entries as $entry) {
$standing = new self($event_name, $entry->player->name);
$standing = new self($event_name, $entry->player->name, $entry->initial_seed);
$standing->save();
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/EventsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public function testRegistration($event)
// 8 players have expressed interest in the event.
$this->assertEquals(10, count($event->getEntries()));
// No players have filled out decklists.
$this->assertEquals(0, count($event->getRegisteredEntries()));
$this->assertEquals(0, count($event->getRegisteredEntries(false, true)));

$deck = insertDeck('testplayer0', $event, '60 Plains', '');
$this->assertEmpty($deck->errors, json_encode($deck->errors));
Expand All @@ -131,7 +131,7 @@ public function testRegistration($event)
$deck = insertDeck('testplayer7', $event, "55 Mountain\n5 Seven Dwarves", '5 Seven Dwarves');
$this->assertNotEmpty($deck->errors, json_encode($deck->errors), 'Too Many Dwarves');
// 5 Valid decks (0, 1, 2, and 4, 5), 3 invalid deck (3, 6, 7), and 3 not submitted decks.
$this->assertEquals(5, count($event->getRegisteredEntries()));
$this->assertEquals(5, count($event->getRegisteredEntries(false, true)));

return $event;
}
Expand Down

0 comments on commit 11785d6

Please sign in to comment.