Route all remaining fill paths through the shared atomic queue
Completes the overfill-race fix (item #1). New queue.php functions, all under the same GET_LOCK + transaction and self-healing numplayers: - pqs_add_player_to_mission (staff 'new' -> registration.php) - pqs_add_player_to_missions (staff 'add to N missions' -> registration.php) - pqs_enqueue_group (kiosk group leader -> callsign.php) - pqs_claim_group_slot (kiosk group member -> callsign.php) callsign.php and registration.php now call these instead of their own non-atomic read-check-insert blocks. Verified on the local stack: scenario test (leader/member/staff paths) and 120 mixed concurrent solo+group writers x3 -> zero overfill, zero drift; HTTP smoke of leader/member/new paths all seat correctly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+14
-54
@@ -111,16 +111,17 @@ if (isset($_GET['submit'])) {
|
|||||||
$lastCommitTime = $rs2[1];
|
$lastCommitTime = $rs2[1];
|
||||||
|
|
||||||
if($isMember){
|
if($isMember){
|
||||||
$replaceWho = $_GET['who'];
|
// Atomically claim an unclaimed slot reserved by the group leader.
|
||||||
$sql = "SELECT ID, MissionID FROM pqs_queue WHERE `CallSign` like '$replaceWho-%' LIMIT 1";
|
require_once("includes/queue.php");
|
||||||
$result = mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
|
$missionid = pqs_claim_group_slot($_GET['who'], $callsign, $mechname);
|
||||||
$line = mysqli_fetch_array($result);
|
if ($missionid === null) {
|
||||||
$replaceID = $line[0];
|
echo "<table width='1024' height='768' align='center' style='background: url(images/bsb.jpg);' border=1>";
|
||||||
$missionid = $line[1];
|
echo "<tr><td><br><br><table width='820' height='614' align='center' style='background: url(images/mr-block.gif);'>";
|
||||||
|
echo "<tr><td height='500' align='center' valign='middle'><div class='queued'><br>Sorry $_GET[callsign], there are no open slots left in that group.<br><br>Please register on your own or ask the group leader to reserve more slots.<br><br></div></td></tr>";
|
||||||
$sql = "UPDATE `pqs_queue` SET `CallSign`='$callsign',`Mech`='$mechname' WHERE `ID` = '$replaceID'";
|
echo "</table></td></tr></table>";
|
||||||
$result = mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
|
echo "<meta http-equiv='refresh' content='4;url=callsign.php'>";
|
||||||
mysqli_close($link);
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
$minToDeparture = $timePerGame*($missionid-$lastCommitedMissionID);
|
$minToDeparture = $timePerGame*($missionid-$lastCommitedMissionID);
|
||||||
$d=strtotime("+$minToDeparture Minutes",$lastCommitTime);
|
$d=strtotime("+$minToDeparture Minutes",$lastCommitTime);
|
||||||
@@ -136,50 +137,9 @@ if (isset($_GET['submit'])) {
|
|||||||
|
|
||||||
if($isLeader){
|
if($isLeader){
|
||||||
|
|
||||||
$sql = "SELECT MissionID, numplayers FROM pqs_mission WHERE Completed = 0 AND locked = 0 AND ($hm + numplayers) <= MissionSize ORDER BY MissionID ASC";
|
// Atomically reserve $hm seats (leader + placeholders) in one mission.
|
||||||
$getid = mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
|
require_once("includes/queue.php");
|
||||||
$rs = mysqli_fetch_array($getid);
|
$missionid = pqs_enqueue_group($callsign, $mechname, $hm);
|
||||||
$missionid = $rs[0];
|
|
||||||
$numplayers = $rs[1];
|
|
||||||
mysqli_close($link);
|
|
||||||
|
|
||||||
if ($missionid == "") {
|
|
||||||
$missionsize = $_SESSION['mechpods'];
|
|
||||||
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
|
|
||||||
mysqli_select_db($link, 'pqs') or die('Could not select database');
|
|
||||||
$sql = "INSERT INTO pqs_mission (MissionDate, MissionSize, numplayers, MissionTime) VALUES ($tdate, $missionsize, $hm, $ttime)";
|
|
||||||
mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
|
|
||||||
$sql = "SELECT MissionID, numplayers FROM pqs_mission WHERE Completed = 0 AND locked = 0 AND numplayers <= MissionSize ORDER BY MissionID DESC";
|
|
||||||
$getid = mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
|
|
||||||
$rs1 = mysqli_fetch_array($getid);
|
|
||||||
$missionid = $rs1[0];
|
|
||||||
$query = "INSERT INTO pqs_queue (callsign, mech, missionid) VALUES ('$callsign','$mechname',$missionid)";
|
|
||||||
$result = mysqli_query($link, $query) or die('Query failed: ' . mysqli_error($link));
|
|
||||||
$i = 2;
|
|
||||||
while ($i <= $hm){
|
|
||||||
$query = "INSERT INTO pqs_queue (callsign, mech, missionid) VALUES ('$callsign-$i','$mechname',$missionid)";
|
|
||||||
$result = mysqli_query($link, $query) or die('Query failed: ' . mysqli_error($link));
|
|
||||||
$i ++;
|
|
||||||
}
|
|
||||||
mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
|
|
||||||
mysqli_close($link);
|
|
||||||
} else {
|
|
||||||
$newplayers = $numplayers + $hm;
|
|
||||||
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
|
|
||||||
mysqli_select_db($link, 'pqs') or die('Could not select database');
|
|
||||||
$sql = "UPDATE pqs_mission SET numplayers = $newplayers WHERE MissionID = $missionid";
|
|
||||||
mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
|
|
||||||
$query = "INSERT INTO pqs_queue (callsign, mech, missionid) VALUES ('$callsign','$mechname',$missionid)";
|
|
||||||
$result = mysqli_query($link, $query) or die('Query failed: ' . mysqli_error($link));
|
|
||||||
$i = 2;
|
|
||||||
while ($i <= $hm){
|
|
||||||
$query = "INSERT INTO pqs_queue (callsign, mech, missionid) VALUES ('$callsign-$i','$mechname',$missionid)";
|
|
||||||
$result = mysqli_query($link, $query) or die('Query failed: ' . mysqli_error($link));
|
|
||||||
$i ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
mysqli_close($link);
|
|
||||||
}
|
|
||||||
|
|
||||||
$minToDeparture = $timePerGame*($missionid-$lastCommitedMissionID);
|
$minToDeparture = $timePerGame*($missionid-$lastCommitedMissionID);
|
||||||
$d=strtotime("+$minToDeparture Minutes",$lastCommitTime);
|
$d=strtotime("+$minToDeparture Minutes",$lastCommitTime);
|
||||||
|
|||||||
+249
-78
@@ -2,95 +2,266 @@
|
|||||||
/**
|
/**
|
||||||
* Queue domain logic for PQS.
|
* Queue domain logic for PQS.
|
||||||
*
|
*
|
||||||
* The core operation is "seat a player in the next open mission" — the thing
|
* Every path that adds players to a mission goes through here so they all share
|
||||||
* that races when the kiosk (callsign.php) and the staff console
|
* one advisory lock and can't race each other into overfilling a mission or
|
||||||
* (registration.php) add players at the same time. See docs/ARCHITECTURE.md §7.
|
* corrupting the numplayers counter. See docs/ARCHITECTURE.md §7.
|
||||||
|
*
|
||||||
|
* The kiosk (callsign.php) and the staff console (registration.php) are the
|
||||||
|
* concurrent writers; before this, each did its own read-check-insert.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once __DIR__ . '/db.php';
|
require_once __DIR__ . '/db.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomically seat a player in the lowest-numbered open mission, creating a new
|
* Run $fn while holding the global enqueue lock, guaranteeing release even if
|
||||||
* mission (sized to the current pod count) if none has room. Returns the
|
* $fn throws. Serializes all seat-taking across every request/connection.
|
||||||
* MissionID the player landed in.
|
|
||||||
*
|
|
||||||
* Concurrency safety comes from two layers:
|
|
||||||
* 1. GET_LOCK serializes the whole find-or-create-insert critical section, so
|
|
||||||
* no two registrations can interleave their capacity check and insert —
|
|
||||||
* this is what prevents overfilling a mission or racing to create
|
|
||||||
* duplicate missions.
|
|
||||||
* 2. An InnoDB transaction makes the mission update + queue insert commit (or
|
|
||||||
* roll back) as a unit, so a mid-way failure can't leave numplayers and
|
|
||||||
* the queue out of sync.
|
|
||||||
*
|
|
||||||
* Capacity is checked against the real COUNT(*) of queued rows, and numplayers
|
|
||||||
* is rewritten to that count after inserting, so the denormalized counter is
|
|
||||||
* self-healing and can't drift the mission into over/under-fill.
|
|
||||||
*/
|
*/
|
||||||
function pqs_enqueue_player(string $callsign, string $mech, int $merc = 0): int
|
function pqs_with_queue_lock(callable $fn)
|
||||||
{
|
{
|
||||||
$db = pqs_db();
|
|
||||||
|
|
||||||
if ((int) pqs_val("SELECT GET_LOCK('pqs_enqueue', 10)") !== 1) {
|
if ((int) pqs_val("SELECT GET_LOCK('pqs_enqueue', 10)") !== 1) {
|
||||||
throw new RuntimeException('Could not acquire enqueue lock (timeout)');
|
throw new RuntimeException('Could not acquire enqueue lock (timeout)');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$db->begin_transaction();
|
return $fn();
|
||||||
|
} finally {
|
||||||
// Lowest open mission that still has a free seat, judged by actual
|
|
||||||
// occupancy rather than the cached counter.
|
|
||||||
$mission = pqs_row(
|
|
||||||
"SELECT MissionID, MissionSize
|
|
||||||
FROM pqs_mission
|
|
||||||
WHERE Completed = 0
|
|
||||||
AND locked = 0
|
|
||||||
AND (SELECT COUNT(*) FROM pqs_queue WHERE MissionID = pqs_mission.MissionID) < MissionSize
|
|
||||||
ORDER BY MissionID ASC
|
|
||||||
LIMIT 1"
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($mission === null) {
|
|
||||||
// Nothing open: start a fresh mission sized to the current pods.
|
|
||||||
$size = (int) pqs_val("SELECT numpods FROM pqs_gameconfig WHERE gamechoiceid = 1");
|
|
||||||
if ($size < 1) {
|
|
||||||
$size = 1;
|
|
||||||
}
|
|
||||||
// nummercs is NOT NULL without a default; set it explicitly (a new
|
|
||||||
// mission has 0 mercs) so this works under strict SQL mode too.
|
|
||||||
pqs_exec(
|
|
||||||
"INSERT INTO pqs_mission (MissionDate, MissionSize, numplayers, nummercs, MissionTime)
|
|
||||||
VALUES (?, ?, 0, 0, ?)",
|
|
||||||
'iii',
|
|
||||||
[(int) date('Ymd'), $size, (int) date('Hi')]
|
|
||||||
);
|
|
||||||
$missionid = (int) $db->insert_id;
|
|
||||||
} else {
|
|
||||||
$missionid = (int) $mission['MissionID'];
|
|
||||||
}
|
|
||||||
|
|
||||||
pqs_exec(
|
|
||||||
"INSERT INTO pqs_queue (CallSign, Mech, MissionID, Merc) VALUES (?, ?, ?, ?)",
|
|
||||||
'ssii',
|
|
||||||
[$callsign, $mech, $missionid, $merc]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Rewrite the cached counter from the truth, so it can never drift.
|
|
||||||
pqs_exec(
|
|
||||||
"UPDATE pqs_mission
|
|
||||||
SET numplayers = (SELECT COUNT(*) FROM pqs_queue WHERE MissionID = ?)
|
|
||||||
WHERE MissionID = ?",
|
|
||||||
'ii',
|
|
||||||
[$missionid, $missionid]
|
|
||||||
);
|
|
||||||
|
|
||||||
$db->commit();
|
|
||||||
} catch (Throwable $e) {
|
|
||||||
$db->rollback();
|
|
||||||
pqs_val("SELECT RELEASE_LOCK('pqs_enqueue')");
|
pqs_val("SELECT RELEASE_LOCK('pqs_enqueue')");
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pqs_val("SELECT RELEASE_LOCK('pqs_enqueue')");
|
|
||||||
return $missionid;
|
/** Recompute a mission's numplayers from actual queue occupancy (self-healing). */
|
||||||
|
function pqs_sync_numplayers(int $missionid): void
|
||||||
|
{
|
||||||
|
pqs_exec(
|
||||||
|
"UPDATE pqs_mission
|
||||||
|
SET numplayers = (SELECT COUNT(*) FROM pqs_queue WHERE MissionID = ?)
|
||||||
|
WHERE MissionID = ?",
|
||||||
|
'ii',
|
||||||
|
[$missionid, $missionid]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a new mission sized to the current pod count; return its MissionID. */
|
||||||
|
function pqs_create_mission(): int
|
||||||
|
{
|
||||||
|
$size = (int) pqs_val("SELECT numpods FROM pqs_gameconfig WHERE gamechoiceid = 1");
|
||||||
|
if ($size < 1) {
|
||||||
|
$size = 1;
|
||||||
|
}
|
||||||
|
// nummercs is NOT NULL without a default; set it explicitly (0 for a new
|
||||||
|
// mission) so this works under strict SQL mode too.
|
||||||
|
pqs_exec(
|
||||||
|
"INSERT INTO pqs_mission (MissionDate, MissionSize, numplayers, nummercs, MissionTime)
|
||||||
|
VALUES (?, ?, 0, 0, ?)",
|
||||||
|
'iii',
|
||||||
|
[(int) date('Ymd'), $size, (int) date('Hi')]
|
||||||
|
);
|
||||||
|
return (int) pqs_db()->insert_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomically seat one player in the lowest-numbered open mission that has room
|
||||||
|
* (creating one if none does). Returns the MissionID. Used by the kiosk's
|
||||||
|
* normal registration.
|
||||||
|
*/
|
||||||
|
function pqs_enqueue_player(string $callsign, string $mech, int $merc = 0): int
|
||||||
|
{
|
||||||
|
return pqs_with_queue_lock(function () use ($callsign, $mech, $merc) {
|
||||||
|
$db = pqs_db();
|
||||||
|
$db->begin_transaction();
|
||||||
|
try {
|
||||||
|
$mission = pqs_row(
|
||||||
|
"SELECT MissionID
|
||||||
|
FROM pqs_mission
|
||||||
|
WHERE Completed = 0
|
||||||
|
AND locked = 0
|
||||||
|
AND (SELECT COUNT(*) FROM pqs_queue WHERE MissionID = pqs_mission.MissionID) < MissionSize
|
||||||
|
ORDER BY MissionID ASC
|
||||||
|
LIMIT 1"
|
||||||
|
);
|
||||||
|
$missionid = $mission === null ? pqs_create_mission() : (int) $mission['MissionID'];
|
||||||
|
|
||||||
|
pqs_exec(
|
||||||
|
"INSERT INTO pqs_queue (CallSign, Mech, MissionID, Merc) VALUES (?, ?, ?, ?)",
|
||||||
|
'ssii',
|
||||||
|
[$callsign, $mech, $missionid, $merc]
|
||||||
|
);
|
||||||
|
pqs_sync_numplayers($missionid);
|
||||||
|
|
||||||
|
$db->commit();
|
||||||
|
return $missionid;
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$db->rollback();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomically add a player to a SPECIFIC mission (staff "new" action). Does not
|
||||||
|
* pick a mission or enforce capacity — staff may intentionally overfill — but
|
||||||
|
* shares the lock so it can't race with kiosk registrations, and keeps
|
||||||
|
* numplayers accurate.
|
||||||
|
*/
|
||||||
|
function pqs_add_player_to_mission(int $missionid, string $callsign, string $mech, int $merc = 0): void
|
||||||
|
{
|
||||||
|
pqs_with_queue_lock(function () use ($missionid, $callsign, $mech, $merc) {
|
||||||
|
$db = pqs_db();
|
||||||
|
$db->begin_transaction();
|
||||||
|
try {
|
||||||
|
pqs_exec(
|
||||||
|
"INSERT INTO pqs_queue (CallSign, Mech, MissionID, Merc) VALUES (?, ?, ?, ?)",
|
||||||
|
'ssii',
|
||||||
|
[$callsign, $mech, $missionid, $merc]
|
||||||
|
);
|
||||||
|
pqs_sync_numplayers($missionid);
|
||||||
|
$db->commit();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$db->rollback();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Staff "add to multiple missions": place $callsign in the next $count missions
|
||||||
|
* after $startmission, filling existing missions that have room and creating
|
||||||
|
* new ones at the tail as needed. Runs as one atomic unit under the shared lock.
|
||||||
|
*/
|
||||||
|
function pqs_add_player_to_missions(int $startmission, int $count, string $callsign, string $mech, int $merc = 0): void
|
||||||
|
{
|
||||||
|
if ($count < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pqs_with_queue_lock(function () use ($startmission, $count, $callsign, $mech, $merc) {
|
||||||
|
$db = pqs_db();
|
||||||
|
$db->begin_transaction();
|
||||||
|
try {
|
||||||
|
$placed = 0;
|
||||||
|
$mid = $startmission + 1;
|
||||||
|
while ($placed < $count) {
|
||||||
|
$maxmission = (int) pqs_val("SELECT MAX(MissionID) FROM pqs_mission");
|
||||||
|
if ($mid <= $maxmission) {
|
||||||
|
$row = pqs_row(
|
||||||
|
"SELECT MissionSize,
|
||||||
|
(SELECT COUNT(*) FROM pqs_queue WHERE MissionID = ?) AS filled
|
||||||
|
FROM pqs_mission WHERE MissionID = ?",
|
||||||
|
'ii',
|
||||||
|
[$mid, $mid]
|
||||||
|
);
|
||||||
|
if ($row !== null && (int) $row['filled'] < (int) $row['MissionSize']) {
|
||||||
|
pqs_exec(
|
||||||
|
"INSERT INTO pqs_queue (CallSign, Mech, MissionID, Merc) VALUES (?, ?, ?, ?)",
|
||||||
|
'ssii',
|
||||||
|
[$callsign, $mech, $mid, $merc]
|
||||||
|
);
|
||||||
|
pqs_sync_numplayers($mid);
|
||||||
|
$placed++;
|
||||||
|
}
|
||||||
|
// full or missing: fall through and try the next mission
|
||||||
|
} else {
|
||||||
|
$mid = pqs_create_mission();
|
||||||
|
pqs_exec(
|
||||||
|
"INSERT INTO pqs_queue (CallSign, Mech, MissionID, Merc) VALUES (?, ?, ?, ?)",
|
||||||
|
'ssii',
|
||||||
|
[$callsign, $mech, $mid, $merc]
|
||||||
|
);
|
||||||
|
pqs_sync_numplayers($mid);
|
||||||
|
$placed++;
|
||||||
|
}
|
||||||
|
$mid++;
|
||||||
|
}
|
||||||
|
$db->commit();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$db->rollback();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomically reserve a group of $count seats in one mission for a leader:
|
||||||
|
* inserts the leader ($callsign) plus placeholder rows "$callsign-2" ..
|
||||||
|
* "$callsign-$count" that members later claim. Picks the lowest open mission
|
||||||
|
* that can fit the whole group, else creates one. Returns the MissionID.
|
||||||
|
*/
|
||||||
|
function pqs_enqueue_group(string $callsign, string $mech, int $count): int
|
||||||
|
{
|
||||||
|
if ($count < 1) {
|
||||||
|
$count = 1;
|
||||||
|
}
|
||||||
|
return pqs_with_queue_lock(function () use ($callsign, $mech, $count) {
|
||||||
|
$db = pqs_db();
|
||||||
|
$db->begin_transaction();
|
||||||
|
try {
|
||||||
|
$mission = pqs_row(
|
||||||
|
"SELECT MissionID
|
||||||
|
FROM pqs_mission
|
||||||
|
WHERE Completed = 0
|
||||||
|
AND locked = 0
|
||||||
|
AND (SELECT COUNT(*) FROM pqs_queue WHERE MissionID = pqs_mission.MissionID) + ? <= MissionSize
|
||||||
|
ORDER BY MissionID ASC
|
||||||
|
LIMIT 1",
|
||||||
|
'i',
|
||||||
|
[$count]
|
||||||
|
);
|
||||||
|
$missionid = $mission === null ? pqs_create_mission() : (int) $mission['MissionID'];
|
||||||
|
|
||||||
|
pqs_exec(
|
||||||
|
"INSERT INTO pqs_queue (CallSign, Mech, MissionID) VALUES (?, ?, ?)",
|
||||||
|
'ssi',
|
||||||
|
[$callsign, $mech, $missionid]
|
||||||
|
);
|
||||||
|
for ($i = 2; $i <= $count; $i++) {
|
||||||
|
pqs_exec(
|
||||||
|
"INSERT INTO pqs_queue (CallSign, Mech, MissionID) VALUES (?, ?, ?)",
|
||||||
|
'ssi',
|
||||||
|
["$callsign-$i", $mech, $missionid]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
pqs_sync_numplayers($missionid);
|
||||||
|
|
||||||
|
$db->commit();
|
||||||
|
return $missionid;
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$db->rollback();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomically claim one unclaimed placeholder slot reserved by leader $who,
|
||||||
|
* replacing it with this member's $callsign/$mech. Returns the MissionID the
|
||||||
|
* member landed in, or null if no free slot remained. Serialized so two members
|
||||||
|
* can't grab the same slot.
|
||||||
|
*/
|
||||||
|
function pqs_claim_group_slot(string $who, string $callsign, string $mech): ?int
|
||||||
|
{
|
||||||
|
return pqs_with_queue_lock(function () use ($who, $callsign, $mech) {
|
||||||
|
$db = pqs_db();
|
||||||
|
$db->begin_transaction();
|
||||||
|
try {
|
||||||
|
// Unclaimed placeholders still look like "who-<n>"; a claimed one has
|
||||||
|
// been renamed to the member's real callsign.
|
||||||
|
$slot = pqs_row(
|
||||||
|
"SELECT ID, MissionID FROM pqs_queue WHERE CallSign LIKE ? ORDER BY ID ASC LIMIT 1",
|
||||||
|
's',
|
||||||
|
["$who-%"]
|
||||||
|
);
|
||||||
|
if ($slot === null) {
|
||||||
|
$db->commit();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
pqs_exec(
|
||||||
|
"UPDATE pqs_queue SET CallSign = ?, Mech = ? WHERE ID = ?",
|
||||||
|
'ssi',
|
||||||
|
[$callsign, $mech, (int) $slot['ID']]
|
||||||
|
);
|
||||||
|
$db->commit();
|
||||||
|
return (int) $slot['MissionID'];
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$db->rollback();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-58
@@ -86,67 +86,24 @@ if (isset($_POST['edit'])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_POST['add'])) {
|
if (isset($_POST['add'])) {
|
||||||
if (isset($_POST['playerid'])) $playerid = $_POST['playerid'];
|
// Add one player to the next N missions after $missionid (atomic).
|
||||||
if (isset($_POST['callsign'])) $callsign = str_replace("'", "'", $_POST['callsign']);
|
require_once("includes/queue.php");
|
||||||
if (isset($_POST['missionid'])) $missionid = $_POST['missionid'];
|
$callsign = isset($_POST['callsign']) ? $_POST['callsign'] : '';
|
||||||
if (isset($_POST['merc'])) $merc = $_POST['merc'];
|
$mech = isset($_POST['mech']) ? $_POST['mech'] : '';
|
||||||
if (isset($_POST['mech'])) $mech = $_POST['mech'];
|
$merc = isset($_POST['merc']) ? (int)$_POST['merc'] : 0;
|
||||||
if (isset($_POST['nummissions'])) $nummissions = $_POST['nummissions'];
|
$startmission = isset($_POST['missionid']) ? (int)$_POST['missionid'] : 0;
|
||||||
|
$nummissions = isset($_POST['nummissions']) ? (int)$_POST['nummissions'] : 0;
|
||||||
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
|
pqs_add_player_to_missions($startmission, $nummissions, $callsign, $mech, $merc);
|
||||||
mysqli_select_db($link, 'pqs') or die('Could not select database');
|
|
||||||
|
|
||||||
$sql = "SELECT MAX(MissionID) FROM pqs_mission";
|
|
||||||
$result = mysqli_query($link, $sql) or die('Update player in Queue failed: ' . mysqli_error($link));
|
|
||||||
$rs = mysqli_fetch_array($result);
|
|
||||||
$maxmission = $rs[0];
|
|
||||||
$newmissionid = $missionid + 1;
|
|
||||||
|
|
||||||
for ($i = 1; $i <= $nummissions;) {
|
|
||||||
if ($newmissionid <= $maxmission) {
|
|
||||||
$sql = "SELECT numplayers FROM pqs_mission WHERE MissionID = $newmissionid";
|
|
||||||
$result = mysqli_query($link, $sql) or die('Update player in Queue failed: ' . mysqli_error($link));
|
|
||||||
$rs = mysqli_fetch_array($result);
|
|
||||||
if ($rs[0] < $missionsize) {
|
|
||||||
$sql = "UPDATE pqs_mission SET numplayers = numplayers + 1 WHERE MissionID = $newmissionid";
|
|
||||||
$result = mysqli_query($link, $sql) or die('Update player in Queue failed: ' . mysqli_error($link));
|
|
||||||
$sql = "INSERT INTO pqs_queue (CallSign, Mech, MissionID, Merc) VALUES ('$callsign', '$mech', $newmissionid, $merc)";
|
|
||||||
$result = mysqli_query($link, $sql) or die('Update player in Queue failed: ' . mysqli_error($link));
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$sql = "INSERT INTO pqs_mission (MissionDate, MissionSize, numplayers, nummercs, MissionTime) VALUES ($tdate, $missionsize, 1, $merc, $ttime)";
|
|
||||||
mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
|
|
||||||
$sql = "INSERT INTO pqs_queue (CallSign, Mech, MissionID, Merc) VALUES ('$callsign', '$mech', $newmissionid, $merc)";
|
|
||||||
$result = mysqli_query($link, $sql) or die('Update player in Queue failed: ' . mysqli_error($link));
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
$newmissionid++;
|
|
||||||
}
|
|
||||||
mysqli_close($link);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_POST['new'])) {
|
if (isset($_POST['new'])) {
|
||||||
if (isset($_POST['callsign'])) $callsign = str_replace("'", "''", $_POST['callsign']);
|
// Add one player to a specific mission (atomic).
|
||||||
if(is_null($callsign)){ $callsign = 'empty'; }
|
require_once("includes/queue.php");
|
||||||
if (isset($_POST['mech'])) $mech = $_POST['mech'];
|
$callsign = isset($_POST['callsign']) ? $_POST['callsign'] : '';
|
||||||
if (isset($_POST['missionid'])) $missionid = $_POST['missionid'];
|
if ($callsign === '') { $callsign = 'empty'; }
|
||||||
|
$mech = isset($_POST['mech']) ? $_POST['mech'] : '';
|
||||||
$link = mysqli_connect('localhost', 'pqs', 'pqs') or die('Could not connect: ' . mysqli_error($link));
|
$missionid = isset($_POST['missionid']) ? (int)$_POST['missionid'] : 0;
|
||||||
mysqli_select_db($link, 'pqs') or die('Could not select database');
|
pqs_add_player_to_mission($missionid, $callsign, $mech);
|
||||||
|
|
||||||
$sql = "SELECT numplayers FROM pqs_mission WHERE MissionID = '$missionid'";
|
|
||||||
$getid = mysqli_query($link, $sql) or die('Query failed: ' . mysqli_error($link));
|
|
||||||
$rs = mysqli_fetch_array($getid);
|
|
||||||
$numplayers = $rs[0];
|
|
||||||
$newplayers = $numplayers+1;
|
|
||||||
$sql = "UPDATE pqs_mission SET numplayers='$newplayers' WHERE MissionID=$missionid";
|
|
||||||
mysqli_query($link, $sql) or die('Update player in Queue failed: ' . mysqli_error($link));
|
|
||||||
|
|
||||||
$sql = "INSERT INTO pqs_queue (callsign, mech, missionid) VALUES ('$callsign','$mech',$missionid)";
|
|
||||||
mysqli_query($link, $sql) or die('Update player in Queue failed: ' . mysqli_error($link));
|
|
||||||
|
|
||||||
mysqli_close($link);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_POST['editgame'])) {
|
if (isset($_POST['editgame'])) {
|
||||||
|
|||||||
Reference in New Issue
Block a user