✨feature: Add contract features to dashboard page
This commit is contained in:
332
index.php
332
index.php
@@ -40,6 +40,10 @@ $systemWaypoints = array();
|
||||
$paginatedWaypoints = array();
|
||||
$marketDetails = array();
|
||||
$shipyardDetails = array();
|
||||
$activeContracts = array();
|
||||
$pendingContracts = array();
|
||||
$deliveryReadyByTradeSymbol = array();
|
||||
$contractNegotiationShipSymbol = '';
|
||||
$selectedShipSymbol = '';
|
||||
$selectedWaypointSymbol = '';
|
||||
$waypointPageSize = 15;
|
||||
@@ -103,6 +107,161 @@ try {
|
||||
$ships = $shipsResponse['data'] ?? $shipsResponse;
|
||||
$contracts = $contractsResponse['data'] ?? $contractsResponse;
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset( $_POST['contract_action'] ) ) {
|
||||
$contractAction = (string) $_POST['contract_action'];
|
||||
|
||||
if ($contractAction === 'fulfill_contract' ) {
|
||||
$contractId = trim( (string) ( $_POST['contract_id'] ?? '' ) );
|
||||
if ($contractId !== '' ) {
|
||||
$client->fulfillContract( $contractId );
|
||||
$storage->clearAllCache();
|
||||
$statusMessage = 'Contract ' . $contractId . ' fulfilled.';
|
||||
}
|
||||
} elseif ($contractAction === 'deliver_contract' ) {
|
||||
$contractId = trim( (string) ( $_POST['contract_id'] ?? '' ) );
|
||||
if ($contractId !== '' ) {
|
||||
$contractToDeliver = null;
|
||||
foreach ( (array) $contracts as $contract ) {
|
||||
if ((string) ( $contract['id'] ?? '' ) === $contractId ) {
|
||||
$contractToDeliver = $contract;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_array( $contractToDeliver ) ) {
|
||||
throw new SpacetradersApiException( 'Contract not found.' );
|
||||
}
|
||||
|
||||
$deliveries = (array) ( $contractToDeliver['terms']['deliver'] ?? array() );
|
||||
$deliveryAttempts = 0;
|
||||
|
||||
foreach ( $deliveries as $delivery ) {
|
||||
$tradeSymbol = (string) ( $delivery['tradeSymbol'] ?? '' );
|
||||
$destinationSymbol = (string) ( $delivery['destinationSymbol'] ?? '' );
|
||||
$unitsRequired = (int) ( $delivery['unitsRequired'] ?? 0 );
|
||||
$unitsFulfilled = (int) ( $delivery['unitsFulfilled'] ?? 0 );
|
||||
$unitsRemaining = max( 0, $unitsRequired - $unitsFulfilled );
|
||||
|
||||
if ($tradeSymbol === '' || $destinationSymbol === '' || $unitsRemaining <= 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( $ships as $ship ) {
|
||||
if ($unitsRemaining <= 0 ) {
|
||||
break;
|
||||
}
|
||||
|
||||
$shipSymbol = (string) ( $ship['symbol'] ?? '' );
|
||||
$shipStatus = (string) ( $ship['nav']['status'] ?? '' );
|
||||
$shipWaypoint = (string) ( $ship['nav']['waypointSymbol'] ?? '' );
|
||||
|
||||
if ($shipSymbol === '' || $shipStatus === 'IN_TRANSIT' || $shipWaypoint !== $destinationSymbol ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$shipResponse = $client->getShip( $shipSymbol );
|
||||
$shipData = $shipResponse['data'] ?? array();
|
||||
|
||||
$currentStatus = (string) ( $shipData['nav']['status'] ?? '' );
|
||||
if ($currentStatus === 'IN_TRANSIT' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($currentStatus !== 'DOCKED' ) {
|
||||
$client->dockShip( $shipSymbol );
|
||||
}
|
||||
|
||||
$availableUnits = 0;
|
||||
$inventory = (array) ( $shipData['cargo']['inventory'] ?? array() );
|
||||
foreach ( $inventory as $item ) {
|
||||
if ((string) ( $item['symbol'] ?? '' ) === $tradeSymbol ) {
|
||||
$availableUnits = (int) ( $item['units'] ?? 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($availableUnits <= 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$deliverUnits = min( $availableUnits, $unitsRemaining );
|
||||
if ($deliverUnits <= 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$client->deliverContractCargo( $contractId, $shipSymbol, $tradeSymbol, $deliverUnits );
|
||||
$unitsRemaining -= $deliverUnits;
|
||||
$deliveryAttempts++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($deliveryAttempts > 0 ) {
|
||||
$storage->clearAllCache();
|
||||
$statusMessage = 'Delivered contract cargo using ' . $deliveryAttempts . ' shipment(s) for contract ' . $contractId . '.';
|
||||
} else {
|
||||
$errorMessage = 'No eligible cargo/ships available to deliver for contract ' . $contractId . '.';
|
||||
}
|
||||
}
|
||||
} elseif ($contractAction === 'negotiate_contract' ) {
|
||||
$negotiateShipSymbol = trim( (string) ( $_POST['negotiate_ship_symbol'] ?? '' ) );
|
||||
if ($negotiateShipSymbol === '' ) {
|
||||
$negotiateShipSymbol = (string) ( $ships[0]['symbol'] ?? '' );
|
||||
}
|
||||
|
||||
if ($negotiateShipSymbol === '' ) {
|
||||
throw new SpacetradersApiException( 'No available ship found to negotiate a contract.' );
|
||||
}
|
||||
|
||||
$client->negotiateContract( $negotiateShipSymbol );
|
||||
$storage->clearAllCache();
|
||||
$statusMessage = 'Negotiated a new contract using ' . $negotiateShipSymbol . '.';
|
||||
}
|
||||
|
||||
if ($statusMessage !== '' || $errorMessage !== '' ) {
|
||||
$shipsResponse = $client->listMyShips();
|
||||
$contractsResponse = $client->listMyContracts();
|
||||
$ships = $shipsResponse['data'] ?? $shipsResponse;
|
||||
$contracts = $contractsResponse['data'] ?? $contractsResponse;
|
||||
}
|
||||
}
|
||||
|
||||
$activeContracts = array_values(
|
||||
array_filter(
|
||||
(array) $contracts,
|
||||
static function ( array $contract ): bool {
|
||||
return (bool) ( $contract['accepted'] ?? false ) && ! (bool) ( $contract['fulfilled'] ?? false );
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
$pendingContracts = array_values(
|
||||
array_filter(
|
||||
(array) $contracts,
|
||||
static function ( array $contract ): bool {
|
||||
return ! (bool) ( $contract['accepted'] ?? false ) && ! (bool) ( $contract['fulfilled'] ?? false );
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $ships as $ship ) {
|
||||
$inventory = (array) ( $ship['cargo']['inventory'] ?? array() );
|
||||
foreach ( $inventory as $item ) {
|
||||
$tradeSymbol = (string) ( $item['symbol'] ?? '' );
|
||||
$units = (int) ( $item['units'] ?? 0 );
|
||||
if ($tradeSymbol === '' || $units <= 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! isset( $deliveryReadyByTradeSymbol[ $tradeSymbol ] ) ) {
|
||||
$deliveryReadyByTradeSymbol[ $tradeSymbol ] = 0;
|
||||
}
|
||||
|
||||
$deliveryReadyByTradeSymbol[ $tradeSymbol ] += $units;
|
||||
}
|
||||
}
|
||||
|
||||
$contractNegotiationShipSymbol = (string) ( $ships[0]['symbol'] ?? '' );
|
||||
|
||||
$currentSystemSymbol = '';
|
||||
|
||||
if (isset( $ships[0]['nav']['systemSymbol'] ) && is_string( $ships[0]['nav']['systemSymbol'] ) ) {
|
||||
@@ -468,7 +627,7 @@ try {
|
||||
</td>
|
||||
<td class="border border-gray-300 px-4 py-2"><?php echo htmlspecialchars( ucfirst( strtolower( $ship['registration']['role'] ) ) ); ?></td>
|
||||
<td class="border border-gray-300 px-4 py-2"><?php echo htmlspecialchars( $ship['frame']['name'] ); ?></td>
|
||||
<td class="border border-gray-300 px-4 py-2"><?php echo htmlspecialchars( ucfirst( strtolower( $shipStatus ) ) ); ?></td>
|
||||
<td class="border border-gray-300 px-4 py-2"><?php echo htmlspecialchars( formatString( $shipStatus ) ); ?></td>
|
||||
<td class="border border-gray-300 px-4 py-2">
|
||||
<span
|
||||
class="ship-nav-timer"
|
||||
@@ -488,65 +647,126 @@ try {
|
||||
</table>
|
||||
|
||||
<h2 class="text-2xl font-bold my-4">Contracts</h2>
|
||||
<div class="flex flex-col lg:flex-row gap-4">
|
||||
<?php
|
||||
$i = 1;
|
||||
|
||||
foreach ( $contracts as $contract ) :
|
||||
$type = ucfirst( strtolower( str_replace( '_', ' ', $contract['type'] ) ) ) ?? null;
|
||||
$delivery = ucfirst( strtolower( str_replace( '_', ' ', $contract['terms']['deliver'][0]['tradeSymbol'] ) ) ) ?? null;
|
||||
$accepted = $contract['accepted'] ? 'Accepted' : false;
|
||||
$fulfilled = $contract['fulfilled'] ? 'Fulfilled' : false;
|
||||
|
||||
if ($fulfilled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $accepted && ! $fulfilled) {
|
||||
$status = 'Not Accepted';
|
||||
} elseif ($accepted && ! $fulfilled) {
|
||||
$status = 'Accepted';
|
||||
} elseif ($accepted && $fulfilled) {
|
||||
$status = 'Fulfilled';
|
||||
} else {
|
||||
$status = 'Unknown';
|
||||
}
|
||||
?>
|
||||
<div class="mb-4 border border-gray-300 p-4 rounded">
|
||||
<h3 class="text-xl font-bold mb-2 w-full underline decoration-gray-300">Contract <?php echo $i; ?>: <?php echo htmlspecialchars( $type ); ?> - <?php echo htmlspecialchars( $delivery ); ?></h3>
|
||||
|
||||
<p class="mb-0 font-bold">
|
||||
Delivery Details: <span class="font-normal"><?php echo number_format( $contract['terms']['deliver'][0]['unitsRequired'] ); ?> units delivered to <?php echo htmlspecialchars( $contract['terms']['deliver'][0]['destinationSymbol'] ); ?></span>
|
||||
</p>
|
||||
|
||||
<p class="mb-2 font-bold">
|
||||
Payment: <span class="font-normal"><?php echo number_format( $contract['terms']['payment']['onAccepted'] ); ?> on Accept, <?php echo number_format( $contract['terms']['payment']['onFulfilled'] ); ?> on Fulfill</span>
|
||||
</p>
|
||||
|
||||
<p class="mb-0 font-bold">Deadline To Accept: <span class="font-normal"><?php echo htmlspecialchars( date( 'Y-m-d H:i:s', strtotime( $contract['deadlineToAccept'] ) ) ); ?></span></p>
|
||||
<p class="mb-2 font-bold">Deadline: <span class="font-normal"><?php echo htmlspecialchars( date( 'Y-m-d H:i:s', strtotime( $contract['terms']['deadline'] ) ) ); ?></span></p>
|
||||
|
||||
<p class="mb-0 font-bold">
|
||||
Status: <span class="font-normal"><?php echo htmlspecialchars( $status ); ?></span>
|
||||
<?php if ($status === 'Not Accepted' ) : ?>
|
||||
<span class="ml-2">
|
||||
<a
|
||||
href="index.php?accept_contract=<?php echo urlencode( $contract['id'] ); ?>"
|
||||
class="font-normal text-blue-400 hover:underline"
|
||||
>
|
||||
Accept?
|
||||
</a>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<div class="mb-6 border border-gray-600 rounded p-4">
|
||||
<h3 class="text-xl font-bold mb-3">Active Contracts</h3>
|
||||
<?php if (empty( $activeContracts ) ) : ?>
|
||||
<p class="text-gray-300 mb-3">No active contracts.</p>
|
||||
<?php if ($contractNegotiationShipSymbol !== '' ) : ?>
|
||||
<form method="post">
|
||||
<input type="hidden" name="contract_action" value="negotiate_contract">
|
||||
<input type="hidden" name="negotiate_ship_symbol" value="<?php echo htmlspecialchars( $contractNegotiationShipSymbol ); ?>">
|
||||
<button type="submit" class="px-3 py-2 bg-emerald-700 rounded hover:bg-emerald-600">
|
||||
Negotiate New Contract
|
||||
</button>
|
||||
</form>
|
||||
<p class="text-sm text-gray-400 mt-2">
|
||||
Uses ship: <?php echo htmlspecialchars( $contractNegotiationShipSymbol ); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
<?php foreach ( $activeContracts as $contract ) : ?>
|
||||
<?php
|
||||
$contractType = (string) ( $contract['type'] ?? '' );
|
||||
$deliveries = (array) ( $contract['terms']['deliver'] ?? array() );
|
||||
?>
|
||||
<div class="border border-gray-500 rounded p-3">
|
||||
<p><span class="font-bold">Contract:</span> <?php echo htmlspecialchars( (string) ( $contract['id'] ?? '' ) ); ?></p>
|
||||
<p><span class="font-bold">Type:</span> <?php echo htmlspecialchars( ucfirst( strtolower( str_replace( '_', ' ', $contractType ) ) ) ); ?></p>
|
||||
<p>
|
||||
<span class="font-bold">Deadline:</span>
|
||||
<?php echo htmlspecialchars( (string) date( 'Y-m-d H:i:s', strtotime( (string) ( $contract['terms']['deadline'] ?? '' ) ) ) ); ?>
|
||||
</p>
|
||||
<p>
|
||||
<span class="font-bold">Payment:</span>
|
||||
<?php echo number_format( (int) ( $contract['terms']['payment']['onAccepted'] ?? 0 ) ); ?>
|
||||
+
|
||||
<?php echo number_format( (int) ( $contract['terms']['payment']['onFulfilled'] ?? 0 ) ); ?>
|
||||
</p>
|
||||
<form method="post" class="mt-3">
|
||||
<input type="hidden" name="contract_action" value="deliver_contract">
|
||||
<input type="hidden" name="contract_id" value="<?php echo htmlspecialchars( (string) ( $contract['id'] ?? '' ) ); ?>">
|
||||
<button type="submit" class="px-3 py-1 bg-violet-700 rounded hover:bg-violet-600">
|
||||
Deliver Contract Goods
|
||||
</button>
|
||||
</form>
|
||||
<form method="post" class="mt-2">
|
||||
<input type="hidden" name="contract_action" value="fulfill_contract">
|
||||
<input type="hidden" name="contract_id" value="<?php echo htmlspecialchars( (string) ( $contract['id'] ?? '' ) ); ?>">
|
||||
<button type="submit" class="px-3 py-1 bg-emerald-700 rounded hover:bg-emerald-600">
|
||||
Fulfill Contract
|
||||
</button>
|
||||
</form>
|
||||
<?php if (! empty( $deliveries ) ) : ?>
|
||||
<p class="mt-2 font-bold">Deliveries:</p>
|
||||
<ul class="list-disc list-inside text-sm text-gray-300">
|
||||
<?php foreach ( $deliveries as $delivery ) : ?>
|
||||
<?php
|
||||
$tradeSymbol = (string) ( $delivery['tradeSymbol'] ?? '' );
|
||||
$unitsRequired = (int) ( $delivery['unitsRequired'] ?? 0 );
|
||||
$unitsFulfilled = (int) ( $delivery['unitsFulfilled'] ?? 0 );
|
||||
$remainingUnits = max( 0, $unitsRequired - $unitsFulfilled );
|
||||
$readyUnits = (int) ( $deliveryReadyByTradeSymbol[ $tradeSymbol ] ?? 0 );
|
||||
$deliverableNow = min( $readyUnits, $remainingUnits );
|
||||
?>
|
||||
<li>
|
||||
<?php echo htmlspecialchars( $tradeSymbol ); ?>:
|
||||
<?php echo number_format( $unitsFulfilled ); ?>/<?php echo number_format( $unitsRequired ); ?>
|
||||
to <?php echo htmlspecialchars( (string) ( $delivery['destinationSymbol'] ?? '' ) ); ?>
|
||||
| Ready: <?php echo number_format( $deliverableNow ); ?>
|
||||
<?php if ($readyUnits > $deliverableNow ) : ?>
|
||||
(<?php echo number_format( $readyUnits ); ?> in cargo)
|
||||
<?php endif; ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$i++;
|
||||
endforeach;
|
||||
?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (! empty( $pendingContracts ) ) : ?>
|
||||
<div class="mb-6 border border-gray-600 rounded p-4">
|
||||
<h3 class="text-xl font-bold mb-3">Pending Contracts</h3>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
<?php foreach ( $pendingContracts as $contract ) : ?>
|
||||
<div class="border border-gray-500 rounded p-3">
|
||||
<?php $deliveries = (array) ( $contract['terms']['deliver'] ?? array() ); ?>
|
||||
<p><span class="font-bold">Contract:</span> <?php echo htmlspecialchars( (string) ( $contract['id'] ?? '' ) ); ?></p>
|
||||
<p><span class="font-bold">Type:</span> <?php echo htmlspecialchars( ucfirst( strtolower( str_replace( '_', ' ', (string) ( $contract['type'] ?? '' ) ) ) ) ); ?></p>
|
||||
<p><span class="font-bold">Deadline To Accept:</span> <?php echo htmlspecialchars( date( 'Y-m-d H:i:s', strtotime( (string) ( $contract['deadlineToAccept'] ?? '' ) ) ) ); ?></p>
|
||||
<?php if (! empty( $deliveries ) ) : ?>
|
||||
<p class="mt-2 font-bold">Requirements:</p>
|
||||
<ul class="list-disc list-inside text-sm text-gray-300">
|
||||
<?php foreach ( $deliveries as $delivery ) : ?>
|
||||
<?php
|
||||
$tradeSymbol = (string) ( $delivery['tradeSymbol'] ?? '' );
|
||||
$unitsRequired = (int) ( $delivery['unitsRequired'] ?? 0 );
|
||||
$unitsFulfilled = (int) ( $delivery['unitsFulfilled'] ?? 0 );
|
||||
$destinationSymbol = (string) ( $delivery['destinationSymbol'] ?? '' );
|
||||
?>
|
||||
<li>
|
||||
<?php echo htmlspecialchars( $tradeSymbol ); ?>:
|
||||
<?php echo number_format( $unitsFulfilled ); ?>/<?php echo number_format( $unitsRequired ); ?>
|
||||
to <?php echo htmlspecialchars( $destinationSymbol ); ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
<a
|
||||
href="index.php?accept_contract=<?php echo urlencode( (string) ( $contract['id'] ?? '' ) ); ?>"
|
||||
class="mt-2 inline-block px-3 py-1 bg-blue-700 rounded hover:bg-blue-600"
|
||||
>
|
||||
Accept Contract
|
||||
</a>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const tabs = document.querySelectorAll('.system-tab');
|
||||
|
||||
20
lib/functions.php
Normal file
20
lib/functions.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Spacetraders utility functions.
|
||||
*
|
||||
* @package SpacetradersAPI
|
||||
* @author Keith Solomon <keith@keithsolomon.net>
|
||||
* @license MIT License
|
||||
* @version GIT: <git_id>
|
||||
* @link https://git.keithsolomon.net/keith/Spacetraders
|
||||
*/
|
||||
|
||||
/**
|
||||
* Formats a string by replacing underscores with spaces and capitalizing the first letter.
|
||||
*
|
||||
* @param string $str The string to format.
|
||||
* @return string The formatted string.
|
||||
*/
|
||||
function formatString( $str ) {
|
||||
return ucfirst( strtolower( str_replace( '_', ' ', $str ) ) );
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
require_once __DIR__ . '/spacetraders-api-exception.php';
|
||||
require_once __DIR__ . '/spacetraders-storage.php';
|
||||
require_once __DIR__ . '/functions.php';
|
||||
|
||||
/**
|
||||
* Spacetraders API Client
|
||||
|
||||
11
market.php
11
market.php
@@ -136,6 +136,9 @@ try {
|
||||
<?php require __DIR__ . '/main-menu.php'; ?>
|
||||
|
||||
<h1 class="text-3xl font-bold mb-6 underline decoration-gray-300 w-full"><a href="market.php">Spacetraders - Markets</a></h1>
|
||||
<p class="mb-4">
|
||||
<a href="shop.php" class="px-3 py-2 bg-emerald-700 rounded hover:bg-emerald-600 inline-block">Open Shop</a>
|
||||
</p>
|
||||
|
||||
<?php if (isset( $tokenError ) ) : ?>
|
||||
<div class="mb-6 border border-red-500 p-4 rounded text-red-300">
|
||||
@@ -182,6 +185,14 @@ try {
|
||||
<?php if ((string) ( $record['error'] ?? '' ) !== '' ) : ?>
|
||||
<p class="text-red-300"><?php echo htmlspecialchars( (string) $record['error'] ); ?></p>
|
||||
<?php else : ?>
|
||||
<p class="mb-3">
|
||||
<a
|
||||
href="shop.php?waypoint=<?php echo urlencode( (string) ( $record['waypointSymbol'] ?? '' ) ); ?>"
|
||||
class="text-blue-300 hover:underline"
|
||||
>
|
||||
Shop At This Waypoint
|
||||
</a>
|
||||
</p>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div>
|
||||
<h3 class="font-bold mb-2">Imports</h3>
|
||||
|
||||
@@ -667,16 +667,6 @@ try {
|
||||
$errorMessage = $e->getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a string by replacing underscores with spaces and capitalizing the first letter.
|
||||
*
|
||||
* @param string $value The string to format.
|
||||
* @return string The formatted string.
|
||||
*/
|
||||
function formatString( $value ): string {
|
||||
return ucfirst( strtolower( str_replace( '_', ' ', $value ) ) );
|
||||
}
|
||||
|
||||
$deliveryReadyByTradeSymbol = array();
|
||||
foreach ( $miningShips as $miningShip ) {
|
||||
$inventory = (array) ( $miningShip['cargo']['inventory'] ?? array() );
|
||||
|
||||
@@ -196,16 +196,6 @@ try {
|
||||
} catch (SpacetradersApiException $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a string by replacing underscores with spaces and capitalizing the first letter.
|
||||
*
|
||||
* @param string $str The string to format.
|
||||
* @return string The formatted string.
|
||||
*/
|
||||
function formatString( $str ) {
|
||||
return ucfirst( strtolower( str_replace( '_', ' ', $str ) ) );
|
||||
}
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
279
shop.php
Normal file
279
shop.php
Normal file
@@ -0,0 +1,279 @@
|
||||
<?php
|
||||
/**
|
||||
* Spacetraders cargo shop page.
|
||||
*
|
||||
* @package SpacetradersAPI
|
||||
* @author Keith Solomon <keith@keithsolomon.net>
|
||||
* @license MIT License
|
||||
* @version GIT: <git_id>
|
||||
* @link https://git.keithsolomon.net/keith/Spacetraders
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/lib/spacetraders-api.php';
|
||||
require_once __DIR__ . '/lib/spacetraders-storage.php';
|
||||
|
||||
$config = require __DIR__ . '/lib/project-config.php';
|
||||
|
||||
$storage = new SpacetradersStorage( $config['db_path'] );
|
||||
$token = $storage->getAgentToken();
|
||||
|
||||
$statusMessage = '';
|
||||
$errorMessage = '';
|
||||
$agent = array();
|
||||
$ships = array();
|
||||
$stationedShips = array();
|
||||
$selectedShipSymbol = '';
|
||||
$selectedShip = array();
|
||||
$selectedMarketData = array();
|
||||
$selectedMarketError = '';
|
||||
$selectedSystemSymbol = '';
|
||||
$selectedWaypointSymbol = '';
|
||||
$preferredWaypoint = trim( (string) ( $_GET['waypoint'] ?? '' ) );
|
||||
|
||||
if (! is_string( $token ) || trim( $token ) === '' ) {
|
||||
$envToken = getenv( 'SPACETRADERS_TOKEN' );
|
||||
|
||||
if (is_string( $envToken ) && trim( $envToken ) !== '' ) {
|
||||
$token = trim( $envToken );
|
||||
$storage->setAgentToken( $token );
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_string( $token ) || trim( $token ) === '' ) {
|
||||
$tokenError = 'No token found. Set one in config.php or SPACETRADERS_TOKEN.';
|
||||
}
|
||||
|
||||
if (! isset( $tokenError ) ) {
|
||||
$client = new SpacetradersApi(
|
||||
trim( $token ),
|
||||
$config['api_base_url'],
|
||||
(int) $config['api_timeout'],
|
||||
$storage,
|
||||
(int) $config['cache_ttl']
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
if (! isset( $tokenError ) ) {
|
||||
$agentResponse = $client->getMyAgent();
|
||||
$shipsResponse = $client->listMyShips();
|
||||
|
||||
$agent = $agentResponse['data'] ?? $agentResponse;
|
||||
$ships = $shipsResponse['data'] ?? $shipsResponse;
|
||||
|
||||
foreach ( $ships as $ship ) {
|
||||
$status = (string) ( $ship['nav']['status'] ?? '' );
|
||||
if ($status === 'IN_TRANSIT' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$stationedShips[] = $ship;
|
||||
}
|
||||
|
||||
$selectedShipSymbol = trim( (string) ( $_POST['ship_symbol'] ?? '' ) );
|
||||
if ($selectedShipSymbol === '' ) {
|
||||
$selectedShipSymbol = trim( (string) ( $_GET['ship'] ?? '' ) );
|
||||
}
|
||||
|
||||
if ($selectedShipSymbol === '' && $preferredWaypoint !== '' ) {
|
||||
foreach ( $stationedShips as $stationedShip ) {
|
||||
$waypointSymbol = (string) ( $stationedShip['nav']['waypointSymbol'] ?? '' );
|
||||
if ($waypointSymbol === $preferredWaypoint ) {
|
||||
$selectedShipSymbol = (string) ( $stationedShip['symbol'] ?? '' );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($selectedShipSymbol === '' && ! empty( $stationedShips ) ) {
|
||||
$selectedShipSymbol = (string) ( $stationedShips[0]['symbol'] ?? '' );
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset( $_POST['buy_cargo'] ) ) {
|
||||
$selectedShipSymbol = trim( (string) ( $_POST['ship_symbol'] ?? '' ) );
|
||||
$tradeSymbol = trim( (string) ( $_POST['trade_symbol'] ?? '' ) );
|
||||
$units = (int) ( $_POST['units'] ?? 0 );
|
||||
|
||||
if ($selectedShipSymbol === '' || $tradeSymbol === '' || $units <= 0 ) {
|
||||
throw new SpacetradersApiException( 'Ship, trade symbol, and units are required.' );
|
||||
}
|
||||
|
||||
$selectedShipResponse = $client->getShip( $selectedShipSymbol );
|
||||
$selectedShipData = $selectedShipResponse['data'] ?? array();
|
||||
$shipStatus = (string) ( $selectedShipData['nav']['status'] ?? '' );
|
||||
|
||||
if ($shipStatus === 'IN_TRANSIT' ) {
|
||||
throw new SpacetradersApiException( 'Selected ship is currently in transit.' );
|
||||
}
|
||||
|
||||
if ($shipStatus !== 'DOCKED' ) {
|
||||
$client->dockShip( $selectedShipSymbol );
|
||||
}
|
||||
|
||||
$client->purchaseCargo( $selectedShipSymbol, $tradeSymbol, $units );
|
||||
$storage->clearAllCache();
|
||||
$statusMessage = 'Purchased ' . number_format( $units ) . ' units of ' . $tradeSymbol . '.';
|
||||
|
||||
$shipsResponse = $client->listMyShips();
|
||||
$ships = $shipsResponse['data'] ?? $shipsResponse;
|
||||
$stationedShips = array();
|
||||
foreach ( $ships as $ship ) {
|
||||
$status = (string) ( $ship['nav']['status'] ?? '' );
|
||||
if ($status === 'IN_TRANSIT' ) {
|
||||
continue;
|
||||
}
|
||||
$stationedShips[] = $ship;
|
||||
}
|
||||
}
|
||||
|
||||
if ($selectedShipSymbol !== '' ) {
|
||||
$selectedShipResponse = $client->getShip( $selectedShipSymbol );
|
||||
$selectedShip = $selectedShipResponse['data'] ?? array();
|
||||
$selectedSystemSymbol = (string) ( $selectedShip['nav']['systemSymbol'] ?? '' );
|
||||
$selectedWaypointSymbol = (string) ( $selectedShip['nav']['waypointSymbol'] ?? '' );
|
||||
|
||||
if ($selectedSystemSymbol !== '' && $selectedWaypointSymbol !== '' ) {
|
||||
try {
|
||||
$marketResponse = $client->getWaypointMarket( $selectedSystemSymbol, $selectedWaypointSymbol );
|
||||
$selectedMarketData = (array) ( $marketResponse['data'] ?? array() );
|
||||
} catch (SpacetradersApiException $e) {
|
||||
$selectedMarketError = $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SpacetradersApiException $e) {
|
||||
$errorMessage = $e->getMessage();
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Spacetraders - Shop</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
</head>
|
||||
<body class="container mx-auto px-4 py-8 bg-stone-800 text-gray-200">
|
||||
<?php require __DIR__ . '/main-menu.php'; ?>
|
||||
|
||||
<h1 class="text-3xl font-bold mb-6 underline decoration-gray-300 w-full"><a href="shop.php">Spacetraders - Shop</a></h1>
|
||||
|
||||
<?php if (isset( $tokenError ) ) : ?>
|
||||
<div class="mb-6 border border-red-500 p-4 rounded text-red-300">
|
||||
<?php echo htmlspecialchars( $tokenError ); ?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<?php exit; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($statusMessage !== '' ) : ?>
|
||||
<div class="mb-6 border border-green-500 p-4 rounded text-green-300">
|
||||
<?php echo htmlspecialchars( $statusMessage ); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($errorMessage !== '' ) : ?>
|
||||
<div class="mb-6 border border-red-500 p-4 rounded text-red-300">
|
||||
<?php echo htmlspecialchars( $errorMessage ); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<p class="mb-4">
|
||||
Credits: <span class="font-semibold"><?php echo number_format( (int) ( $agent['credits'] ?? 0 ) ); ?></span>
|
||||
| Stationed Ships: <span class="font-semibold"><?php echo number_format( count( $stationedShips ) ); ?></span>
|
||||
</p>
|
||||
|
||||
<form method="post" class="mb-6 border border-gray-600 rounded p-4 flex flex-wrap items-end gap-3">
|
||||
<div>
|
||||
<label for="ship_symbol" class="block text-sm mb-1">Ship</label>
|
||||
<select id="ship_symbol" name="ship_symbol" class="px-3 py-2 rounded text-black min-w-64">
|
||||
<?php foreach ( $stationedShips as $ship ) : ?>
|
||||
<?php
|
||||
$shipSymbol = (string) ( $ship['symbol'] ?? '' );
|
||||
$shipWaypoint = (string) ( $ship['nav']['waypointSymbol'] ?? '' );
|
||||
?>
|
||||
<option value="<?php echo htmlspecialchars( $shipSymbol ); ?>" <?php echo $shipSymbol === $selectedShipSymbol ? 'selected' : ''; ?>>
|
||||
<?php echo htmlspecialchars( $shipSymbol . ' @ ' . $shipWaypoint ); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="px-4 py-2 bg-blue-700 rounded hover:bg-blue-600">Load Market</button>
|
||||
</form>
|
||||
|
||||
<?php if ($selectedShipSymbol === '' ) : ?>
|
||||
<div class="border border-gray-600 rounded p-4">
|
||||
No stationed ships are available for shopping.
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="mb-6 border border-gray-600 rounded p-4">
|
||||
<p>
|
||||
<span class="font-bold">Selected Ship:</span>
|
||||
<?php echo htmlspecialchars( $selectedShipSymbol ); ?>
|
||||
</p>
|
||||
<p>
|
||||
<span class="font-bold">Location:</span>
|
||||
<?php echo htmlspecialchars( $selectedWaypointSymbol ); ?>
|
||||
</p>
|
||||
<p>
|
||||
<span class="font-bold">Cargo:</span>
|
||||
<?php echo number_format( (int) ( $selectedShip['cargo']['units'] ?? 0 ) ); ?>
|
||||
/
|
||||
<?php echo number_format( (int) ( $selectedShip['cargo']['capacity'] ?? 0 ) ); ?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php if ($selectedMarketError !== '' ) : ?>
|
||||
<div class="border border-red-500 rounded p-4 text-red-300">
|
||||
<?php echo htmlspecialchars( $selectedMarketError ); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<?php $tradeGoods = (array) ( $selectedMarketData['tradeGoods'] ?? array() ); ?>
|
||||
<?php if (empty( $tradeGoods ) ) : ?>
|
||||
<div class="border border-gray-600 rounded p-4">
|
||||
No trade goods available for this market yet.
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table-auto border-collapse border border-gray-300 w-full">
|
||||
<tr>
|
||||
<th class="border border-gray-300 px-3 py-2">Symbol</th>
|
||||
<th class="border border-gray-300 px-3 py-2">Type</th>
|
||||
<th class="border border-gray-300 px-3 py-2">Supply</th>
|
||||
<th class="border border-gray-300 px-3 py-2">Purchase Price</th>
|
||||
<th class="border border-gray-300 px-3 py-2">Sell Price</th>
|
||||
<th class="border border-gray-300 px-3 py-2">Buy</th>
|
||||
</tr>
|
||||
<?php foreach ( $tradeGoods as $tradeGood ) : ?>
|
||||
<?php
|
||||
$tradeSymbol = (string) ( $tradeGood['symbol'] ?? '' );
|
||||
$purchasePrice = (int) ( $tradeGood['purchasePrice'] ?? 0 );
|
||||
?>
|
||||
<tr>
|
||||
<td class="border border-gray-300 px-3 py-2"><?php echo htmlspecialchars( $tradeSymbol ); ?></td>
|
||||
<td class="border border-gray-300 px-3 py-2"><?php echo htmlspecialchars( (string) ( $tradeGood['type'] ?? '' ) ); ?></td>
|
||||
<td class="border border-gray-300 px-3 py-2"><?php echo htmlspecialchars( (string) ( $tradeGood['supply'] ?? '' ) ); ?></td>
|
||||
<td class="border border-gray-300 px-3 py-2"><?php echo number_format( $purchasePrice ); ?></td>
|
||||
<td class="border border-gray-300 px-3 py-2"><?php echo number_format( (int) ( $tradeGood['sellPrice'] ?? 0 ) ); ?></td>
|
||||
<td class="border border-gray-300 px-3 py-2">
|
||||
<?php if ($tradeSymbol !== '' && $purchasePrice > 0 ) : ?>
|
||||
<form method="post" class="flex items-center gap-2">
|
||||
<input type="hidden" name="buy_cargo" value="1">
|
||||
<input type="hidden" name="ship_symbol" value="<?php echo htmlspecialchars( $selectedShipSymbol ); ?>">
|
||||
<input type="hidden" name="trade_symbol" value="<?php echo htmlspecialchars( $tradeSymbol ); ?>">
|
||||
<input type="number" name="units" min="1" value="1" class="w-20 px-2 py-1 rounded text-black">
|
||||
<button type="submit" class="px-3 py-1 bg-emerald-700 rounded hover:bg-emerald-600">Buy</button>
|
||||
</form>
|
||||
<?php else : ?>
|
||||
<span class="text-gray-400 text-sm">N/A</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user