feat(phase1): complete base structure - landing page, auth, dashboard, airports, API, DB schema, 60 airports CSV
This commit is contained in:
331
www/public/api/game.php
Normal file
331
www/public/api/game.php
Normal file
@@ -0,0 +1,331 @@
|
||||
<?php
|
||||
/**
|
||||
* Airline Tycoon - Game API
|
||||
* Hauptspiel-API für Flüge, Routen, Flugzeuge, etc.
|
||||
*/
|
||||
|
||||
require_once dirname(__DIR__) . '/src/bootstrap.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// Auth Check für alle Aktionen außer 'status'
|
||||
$action = $_GET['action'] ?? $_POST['action'] ?? '';
|
||||
|
||||
$publicActions = ['status', 'info'];
|
||||
if (!in_array($action, $publicActions) && !Session::isLoggedIn()) {
|
||||
jsonResponse(['error' => 'Nicht angemeldet'], 401);
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'status':
|
||||
handleStatus();
|
||||
break;
|
||||
|
||||
case 'info':
|
||||
handleInfo();
|
||||
break;
|
||||
|
||||
case 'purchase':
|
||||
handlePurchase();
|
||||
break;
|
||||
|
||||
case 'flight':
|
||||
handleFlight();
|
||||
break;
|
||||
|
||||
case 'routes':
|
||||
handleRoutes();
|
||||
break;
|
||||
|
||||
case 'create_route':
|
||||
handleCreateRoute();
|
||||
break;
|
||||
|
||||
case 'stats':
|
||||
handleStats();
|
||||
break;
|
||||
|
||||
case 'leaderboard':
|
||||
handleLeaderboard();
|
||||
break;
|
||||
|
||||
default:
|
||||
jsonResponse(['error' => 'Unbekannte Aktion'], 400);
|
||||
}
|
||||
|
||||
function handleStatus() {
|
||||
global $db, $config;
|
||||
|
||||
$response = [
|
||||
'success' => true,
|
||||
'authenticated' => Session::isLoggedIn(),
|
||||
'timestamp' => time(),
|
||||
'config' => [
|
||||
'start_balance' => $config['game']['start_balance'],
|
||||
'fuel_cost_per_km' => $config['game']['fuel_cost_per_km']
|
||||
]
|
||||
];
|
||||
|
||||
if (Session::isLoggedIn()) {
|
||||
$userId = Session::getUserId();
|
||||
$user = $db->getUserById($userId);
|
||||
|
||||
if ($user) {
|
||||
$response['user'] = [
|
||||
'id' => $user['id'],
|
||||
'username' => $user['username'],
|
||||
'airline_name' => $user['airline_name'],
|
||||
'balance' => $user['balance'],
|
||||
'level' => $user['level'],
|
||||
'experience' => $user['experience']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
jsonResponse($response);
|
||||
}
|
||||
|
||||
function handleInfo() {
|
||||
global $config;
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'app' => $config['app'],
|
||||
'game' => $config['game'],
|
||||
'aircraft_types' => $config['aircraft_types']
|
||||
]);
|
||||
}
|
||||
|
||||
function handlePurchase() {
|
||||
global $db, $config;
|
||||
|
||||
$userId = Session::getUserId();
|
||||
$user = $db->getUserById($userId);
|
||||
|
||||
$type = $_POST['aircraft_type'] ?? '';
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
|
||||
if (empty($type) || !isset($config['aircraft_types'][$type])) {
|
||||
jsonResponse(['error' => 'Ungültiger Flugzeugtyp'], 400);
|
||||
}
|
||||
|
||||
$specs = $config['aircraft_types'][$type];
|
||||
$price = $specs['purchase_price'];
|
||||
|
||||
if ($user['balance'] < $price) {
|
||||
jsonResponse([
|
||||
'error' => 'Nicht genug Geld!',
|
||||
'required' => $price,
|
||||
'available' => $user['balance']
|
||||
], 400);
|
||||
}
|
||||
|
||||
// Balance abziehen
|
||||
$newBalance = $user['balance'] - $price;
|
||||
$db->update('users', ['balance' => $newBalance], 'id = ?', [$userId]);
|
||||
|
||||
// Aircraft erstellen
|
||||
$aircraftId = $db->purchaseAircraft($userId, $type, $name, $price);
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'message' => "{$type} \"{$name}\" wurde gekauft!",
|
||||
'aircraft_id' => $aircraftId,
|
||||
'price' => $price,
|
||||
'new_balance' => $newBalance
|
||||
]);
|
||||
}
|
||||
|
||||
function handleFlight() {
|
||||
global $db;
|
||||
|
||||
$userId = Session::getUserId();
|
||||
$user = $db->getUserById($userId);
|
||||
|
||||
$routeId = (int) ($_POST['route_id'] ?? 0);
|
||||
$aircraftId = (int) ($_POST['aircraft_id'] ?? 0);
|
||||
|
||||
if ($routeId <= 0 || $aircraftId <= 0) {
|
||||
jsonResponse(['error' => 'Route und Flugzeug erforderlich'], 400);
|
||||
}
|
||||
|
||||
// Route prüfen
|
||||
$route = $db->selectOne(
|
||||
"SELECT r.*, a1.name as from_name, a2.name as to_name
|
||||
FROM routes r
|
||||
JOIN airports a1 ON r.from_airport_id = a1.id
|
||||
JOIN airports a2 ON r.to_airport_id = a2.id
|
||||
WHERE r.id = ? AND r.user_id = ? AND r.is_active = 1",
|
||||
[$routeId, $userId]
|
||||
);
|
||||
|
||||
if (!$route) {
|
||||
jsonResponse(['error' => 'Route nicht gefunden'], 404);
|
||||
}
|
||||
|
||||
// Aircraft prüfen
|
||||
$aircraft = $db->selectOne(
|
||||
"SELECT * FROM aircraft WHERE id = ? AND user_id = ?",
|
||||
[$aircraftId, $userId]
|
||||
);
|
||||
|
||||
if (!$aircraft) {
|
||||
jsonResponse(['error' => 'Flugzeug nicht gefunden'], 404);
|
||||
}
|
||||
|
||||
if ($aircraft['condition'] <= 0) {
|
||||
jsonResponse(['error' => 'Flugzeug ist zu beschädigt!'], 400);
|
||||
}
|
||||
|
||||
if ($aircraft['range_km'] < $route['distance_km']) {
|
||||
jsonResponse([
|
||||
'error' => 'Flugzeug hat nicht genug Reichweite!',
|
||||
'required' => $route['distance_km'],
|
||||
'available' => $aircraft['range_km']
|
||||
], 400);
|
||||
}
|
||||
|
||||
try {
|
||||
$result = $db->executeFlight($userId, $routeId, $aircraftId);
|
||||
|
||||
// User-Daten aktualisieren
|
||||
$updatedUser = $db->getUserById($userId);
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'message' => 'Flug erfolgreich!',
|
||||
'flight' => [
|
||||
'from' => $route['from_name'],
|
||||
'to' => $route['to_name'],
|
||||
'passengers' => $result['passengers'],
|
||||
'revenue' => $result['revenue'],
|
||||
'fuel_cost' => $result['fuel_cost'],
|
||||
'profit' => $result['profit']
|
||||
],
|
||||
'user' => [
|
||||
'balance' => $updatedUser['balance'],
|
||||
'experience' => $updatedUser['experience'],
|
||||
'level' => $updatedUser['level']
|
||||
]
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
jsonResponse(['error' => 'Flug fehlgeschlagen: ' . $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
function handleRoutes() {
|
||||
global $db;
|
||||
|
||||
$userId = Session::getUserId();
|
||||
$routes = $db->getUserRoutes($userId);
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'routes' => $routes,
|
||||
'count' => count($routes)
|
||||
]);
|
||||
}
|
||||
|
||||
function handleCreateRoute() {
|
||||
global $db;
|
||||
|
||||
$userId = Session::getUserId();
|
||||
|
||||
$fromId = (int) ($_POST['from_airport'] ?? 0);
|
||||
$toId = (int) ($_POST['to_airport'] ?? 0);
|
||||
|
||||
if ($fromId <= 0 || $toId <= 0) {
|
||||
jsonResponse(['error' => 'Gültige Flughäfen erforderlich'], 400);
|
||||
}
|
||||
|
||||
if ($fromId === $toId) {
|
||||
jsonResponse(['error' => 'Von und Nach müssen unterschiedlich sein'], 400);
|
||||
}
|
||||
|
||||
// Flughäfen prüfen
|
||||
$fromAirport = $db->selectOne("SELECT * FROM airports WHERE id = ?", [$fromId]);
|
||||
$toAirport = $db->selectOne("SELECT * FROM airports WHERE id = ?", [$toId]);
|
||||
|
||||
if (!$fromAirport || !$toAirport) {
|
||||
jsonResponse(['error' => 'Ein oder beide Flughäfen nicht gefunden'], 404);
|
||||
}
|
||||
|
||||
// Prüfen ob Route bereits existiert
|
||||
$existing = $db->selectOne(
|
||||
"SELECT id FROM routes WHERE user_id = ? AND from_airport_id = ? AND to_airport_id = ?",
|
||||
[$userId, $fromId, $toId]
|
||||
);
|
||||
|
||||
if ($existing) {
|
||||
jsonResponse(['error' => 'Diese Route existiert bereits'], 409);
|
||||
}
|
||||
|
||||
// Distance berechnen
|
||||
$distance = $db->calculateDistance(
|
||||
$fromAirport['latitude'], $fromAirport['longitude'],
|
||||
$toAirport['latitude'], $toAirport['longitude']
|
||||
);
|
||||
|
||||
// Route erstellen
|
||||
$routeId = $db->createRoute($userId, $fromId, $toId, $distance);
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'message' => "Route {$fromAirport['iata_code']} → {$toAirport['iata_code']} erstellt!",
|
||||
'route_id' => $routeId,
|
||||
'distance' => $distance
|
||||
]);
|
||||
}
|
||||
|
||||
function handleStats() {
|
||||
global $db;
|
||||
|
||||
$userId = Session::getUserId();
|
||||
$user = $db->getUserById($userId);
|
||||
|
||||
$stats = $db->getUserStats($userId);
|
||||
$todayStats = $db->getTodayStats($userId);
|
||||
$aircraft = $db->getUserAircraft($userId);
|
||||
$routes = $db->getUserRoutes($userId);
|
||||
|
||||
// Level-Berechnung
|
||||
$config = require dirname(__DIR__) . '/src/config.php';
|
||||
$expForNextLevel = $config['game']['level_up_threshold'] * pow($config['game']['level_multiplier'], $user['level'] - 1);
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'user' => [
|
||||
'balance' => $user['balance'],
|
||||
'level' => $user['level'],
|
||||
'experience' => $user['experience'],
|
||||
'exp_for_next' => $expForNextLevel
|
||||
],
|
||||
'stats' => $stats,
|
||||
'today' => $todayStats,
|
||||
'fleet_count' => count($aircraft),
|
||||
'routes_count' => count($routes)
|
||||
]);
|
||||
}
|
||||
|
||||
function handleLeaderboard() {
|
||||
global $db;
|
||||
|
||||
$limit = min(50, (int) ($_GET['limit'] ?? 10));
|
||||
|
||||
$leaders = $db->select(
|
||||
"SELECT id, username, airline_name, balance, level, experience,
|
||||
(SELECT COUNT(*) FROM routes WHERE user_id = users.id AND is_active = 1) as routes_count,
|
||||
(SELECT COUNT(*) FROM flights WHERE user_id = users.id) as total_flights
|
||||
FROM users
|
||||
WHERE is_active = 1
|
||||
ORDER BY balance DESC, level DESC, experience DESC
|
||||
LIMIT ?",
|
||||
[$limit]
|
||||
);
|
||||
|
||||
jsonResponse([
|
||||
'success' => true,
|
||||
'leaderboard' => $leaders,
|
||||
'count' => count($leaders)
|
||||
]);
|
||||
}
|
||||
Reference in New Issue
Block a user