0) { return 'HIP ' . $hip; } return 'Unbenannter Stern'; } function runPythonApi(string $scriptPath, string $action, array $arguments): array { $pythonCandidates = ['/usr/bin/python', '/usr/bin/python3', 'python3', 'python']; $escapedArguments = [escapeshellarg($scriptPath), escapeshellarg($action)]; foreach ($arguments as $argument) { $escapedArguments[] = escapeshellarg((string)$argument); } $lastError = 'Python konnte nicht ausgeführt werden.'; $debugOutput = []; foreach ($pythonCandidates as $pythonBinary) { $command = $pythonBinary . ' ' . implode(' ', $escapedArguments) . ' 2>&1'; $output = []; $resultCode = 0; exec($command, $output, $resultCode); $joined = trim(implode("\n", $output)); $debugOutput = $output; if ($resultCode !== 0) { $lastError = $joined !== '' ? $joined : ('Fehlercode ' . $resultCode . ' bei ' . $pythonBinary); continue; } $decoded = json_decode($joined, true); if (!is_array($decoded)) { $lastError = $joined !== '' ? 'Python-Ausgabe war kein gültiges JSON.' : 'Python lieferte keine Ausgabe zurück.'; continue; } if (!($decoded['ok'] ?? false)) { return [ 'ok' => false, 'error' => (string)($decoded['error'] ?? 'Unbekannter Python-Fehler'), 'debug' => $joined, ]; } return ['ok' => true, 'data' => $decoded]; } return [ 'ok' => false, 'error' => $lastError, 'debug' => implode("\n", $debugOutput), ]; } $defaultLocation = null; $pdo = null; $pageError = null; $pageLocation = null; $detailMapStars = []; $constellationLines = []; $detailMapCatalogLimit = 8.0; $isAjax = isset($_POST['ajax']) && (string)$_POST['ajax'] === '1'; try { $config = require __DIR__ . '/../config/database.php'; $dsn = sprintf( 'mysql:host=%s;dbname=%s;charset=%s', $config['host'], $config['dbname'], $config['charset'] ?? 'utf8mb4' ); $pdo = new PDO( $dsn, $config['user'], $config['pass'], [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ] ); if ($loggedIn && isset($_SESSION['user_id'])) { $stmtLocation = $pdo->prepare( 'SELECT id, name, latitude, longitude, elevation, timezone FROM app_user_locations WHERE user_id = ? AND is_default = 1 LIMIT 1' ); $stmtLocation->execute([(int)$_SESSION['user_id']]); $defaultLocation = $stmtLocation->fetch() ?: null; } } catch (Throwable $exception) { $pageError = $exception->getMessage(); } if (!empty($defaultLocation) && is_array($defaultLocation)) { $pageLocation = [ 'name' => (string)($defaultLocation['name'] ?? ''), 'latitude' => isset($defaultLocation['latitude']) ? (float)$defaultLocation['latitude'] : null, 'longitude' => isset($defaultLocation['longitude']) ? (float)$defaultLocation['longitude'] : null, 'elevation' => isset($defaultLocation['elevation']) && $defaultLocation['elevation'] !== null ? (float)$defaultLocation['elevation'] : 0.0, 'timezone' => (string)($defaultLocation['timezone'] ?? 'Europe/Berlin'), ]; } $timezoneName = $pageLocation['timezone'] ?? 'Europe/Berlin'; try { $timezone = new DateTimeZone($timezoneName); } catch (Throwable $exception) { $timezoneName = 'Europe/Berlin'; $timezone = new DateTimeZone($timezoneName); } $todayLocal = (new DateTimeImmutable('now', $timezone))->format('Y-m-d'); $selectedDate = isset($_POST['date']) && preg_match('/^\d{4}-\d{2}-\d{2}$/', (string)$_POST['date']) ? (string)$_POST['date'] : $todayLocal; $selectedMag = isset($_POST['mag']) ? (float)$_POST['mag'] : 3.0; $selectedMag = max(1.0, min(6.0, $selectedMag)); $selectedMag = round($selectedMag, 1); if (!$isAjax && $pageError === null && $pdo instanceof PDO && $pageLocation !== null && $pageLocation['latitude'] !== null && $pageLocation['longitude'] !== null) { try { $stmtDetailMap = $pdo->query( "SELECT `hip`, `proper`, `bf`, `con`, `mag`, `ra`, `dec`, `dist` FROM `star_hipparcos` WHERE `mag` IS NOT NULL AND `ra` IS NOT NULL AND `dec` IS NOT NULL AND `mag` <= 8.0 ORDER BY `mag` ASC, `proper` ASC, `bf` ASC, `hip` ASC" ); foreach ($stmtDetailMap->fetchAll() as $row) { $detailMapStars[] = [ 'hip' => isset($row['hip']) ? (int)$row['hip'] : 0, 'label' => buildStarLabel($row), 'constellation' => trim((string)($row['con'] ?? '')), 'mag' => isset($row['mag']) ? (float)$row['mag'] : null, 'ra' => isset($row['ra']) ? (float)$row['ra'] : null, 'dec' => isset($row['dec']) ? (float)$row['dec'] : null, 'distLy' => isset($row['dist']) && $row['dist'] !== null && (float)$row['dist'] > 0.0 ? (float)$row['dist'] * 3.26156 : 1000.0, ]; } $stmtLines = $pdo->query( "SELECT cl.`id` AS line_id, clp.`point_index`, sh.`ra` AS ra_hours, sh.`dec` AS dec_deg FROM `constellation_lines` cl INNER JOIN `constellation_line_points` clp ON clp.`line_id` = cl.`id` INNER JOIN `star_hipparcos` sh ON sh.`hip` = clp.`hip_number` WHERE sh.`ra` IS NOT NULL AND sh.`dec` IS NOT NULL ORDER BY cl.`id`, clp.`point_index`" ); foreach ($stmtLines->fetchAll() as $row) { $lineId = (int)$row['line_id']; $constellationLines[$lineId][] = [ 'ra' => isset($row['ra_hours']) ? (float)$row['ra_hours'] : null, 'dec' => isset($row['dec_deg']) ? (float)$row['dec_deg'] : null, ]; } } catch (Throwable $exception) { $pageError = $exception->getMessage(); $detailMapStars = []; $constellationLines = []; } } if ($isAjax) { header('Content-Type: application/json; charset=utf-8'); if ($pageLocation === null || $pageLocation['latitude'] === null || $pageLocation['longitude'] === null) { echo json_encode([ 'ok' => false, 'error' => 'Kein Standard-Standort gesetzt. Bitte zuerst in den Einstellungen einen Standard-Standort hinterlegen.', ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } if ($pageError !== null || !($pdo instanceof PDO)) { echo json_encode([ 'ok' => false, 'error' => $pageError ?? 'Die Datenbank ist nicht verfuegbar.', ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } try { $stmtStars = $pdo->prepare( "SELECT `hip`, `proper`, `bf`, `con`, `mag`, `ra`, `dec`, `dist` FROM `star_hipparcos` WHERE `mag` IS NOT NULL AND `ra` IS NOT NULL AND `dec` IS NOT NULL AND `mag` <= :max_mag ORDER BY `mag` ASC, `proper` ASC, `bf` ASC, `hip` ASC" ); $stmtStars->execute([':max_mag' => $selectedMag]); $stars = []; foreach ($stmtStars->fetchAll() as $row) { $stars[] = [ 'hip' => isset($row['hip']) ? (int)$row['hip'] : 0, 'label' => buildStarLabel($row), 'constellation' => trim((string)($row['con'] ?? '')), 'mag' => isset($row['mag']) ? (float)$row['mag'] : 99.0, 'ra' => isset($row['ra']) ? (float)$row['ra'] : 0.0, 'dec' => isset($row['dec']) ? (float)$row['dec'] : 0.0, 'distLy' => isset($row['dist']) && $row['dist'] !== null && (float)$row['dist'] > 0.0 ? (float)$row['dist'] * 3.26156 : 1000.0, ]; } $starCount = count($stars); $tempFile = tempnam(sys_get_temp_dir(), 'occult_stars_'); if ($tempFile === false) { throw new RuntimeException('Temporäre Sterndatei konnte nicht angelegt werden.'); } try { file_put_contents($tempFile, json_encode($stars, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR)); $pythonResult = runPythonApi( __DIR__ . '/py/api.py', 'moon_star_occultations', [ (string)$pageLocation['latitude'], (string)$pageLocation['longitude'], (string)$pageLocation['elevation'], $selectedDate, $timezoneName, $tempFile, ] ); if (!$pythonResult['ok']) { echo json_encode([ 'ok' => false, 'error' => $pythonResult['error'] ?? 'Unbekannter Python-Fehler', 'debug' => $pythonResult['debug'] ?? null, ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } echo json_encode([ 'ok' => true, 'star_count' => $starCount, 'results' => $pythonResult['data']['results'] ?? [], 'selected_date' => $selectedDate, 'selected_mag' => $selectedMag, ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } finally { if (is_file($tempFile)) { @unlink($tempFile); } } } catch (Throwable $exception) { echo json_encode([ 'ok' => false, 'error' => $exception->getMessage(), ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; } } require __DIR__ . '/header.php'; if (!empty($currentLocation) && is_array($currentLocation)) { $pageLocation = [ 'name' => (string)($currentLocation['name'] ?? ''), 'latitude' => isset($currentLocation['latitude']) ? (float)$currentLocation['latitude'] : null, 'longitude' => isset($currentLocation['longitude']) ? (float)$currentLocation['longitude'] : null, 'elevation' => isset($currentLocation['elevation']) && $currentLocation['elevation'] !== null ? (float)$currentLocation['elevation'] : 0.0, 'timezone' => (string)($currentLocation['timezone'] ?? 'Europe/Berlin'), ]; } ?>
Fuer die Berechnung wird der Standard-Standort aus der Datenbank verwendet. Bitte wähle in den Einstellungen einen Standard-Standort aus.
Die Sterndaten konnten nicht geladen werden.
Technischer Hinweis: = h($pageError) ?>
Wähle Datum und Grenzgröße und starte die Auswertung mit dem Button.