From fea8b677f94fb566c069b02eec1d3e04fae4f1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Fri, 3 Apr 2026 18:56:02 +0200 Subject: [PATCH] meteorshower eingebaut --- .codex-temp/php-server.err.log | 63 +++++++++++++ public/monatsvorhersage_old.php | 160 ++++++++++++++++++++++++++++++++ 2 files changed, 223 insertions(+) diff --git a/.codex-temp/php-server.err.log b/.codex-temp/php-server.err.log index 51bd979..e3a9de6 100644 --- a/.codex-temp/php-server.err.log +++ b/.codex-temp/php-server.err.log @@ -134,3 +134,66 @@ [Fri Apr 3 18:36:49 2026] [::1]:53631 Accepted [Fri Apr 3 18:36:49 2026] [::1]:53631 [200]: GET /favicon.ico [Fri Apr 3 18:36:49 2026] [::1]:53631 Closing +[Fri Apr 3 18:44:31 2026] [::1]:59929 Accepted +[Fri Apr 3 18:44:36 2026] [::1]:59929 [200]: GET /monatsvorhersage_old.php?year=2026&month=8 +[Fri Apr 3 18:44:36 2026] [::1]:59929 Closing +[Fri Apr 3 18:45:03 2026] [::1]:63306 Accepted +[Fri Apr 3 18:45:09 2026] [::1]:63306 [200]: GET /monatsvorhersage_old.php?year=2026&month=8 +[Fri Apr 3 18:45:09 2026] [::1]:63306 Closing +[Fri Apr 3 18:48:05 2026] [::1]:62679 Accepted +[Fri Apr 3 18:48:10 2026] [::1]:62679 [200]: GET /monatsvorhersage_old.php?year=2026&month=4 +[Fri Apr 3 18:48:10 2026] [::1]:62679 Closing +[Fri Apr 3 18:48:10 2026] [::1]:49184 Accepted +[Fri Apr 3 18:48:10 2026] [::1]:49184 [200]: GET /css/style.css +[Fri Apr 3 18:48:10 2026] [::1]:49184 Closing +[Fri Apr 3 18:48:10 2026] [::1]:52798 Accepted +[Fri Apr 3 18:48:10 2026] [::1]:52798 [200]: GET /js/astronomy.browser.min.js +[Fri Apr 3 18:48:10 2026] [::1]:52798 Closing +[Fri Apr 3 18:48:10 2026] [::1]:55547 Accepted +[Fri Apr 3 18:48:10 2026] [::1]:55547 [200]: GET /images/star16x16.png +[Fri Apr 3 18:48:10 2026] [::1]:55238 Accepted +[Fri Apr 3 18:48:10 2026] [::1]:55238 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 18:48:10 2026] [::1]:55547 Closing +[Fri Apr 3 18:48:10 2026] [::1]:55238 Closing +[Fri Apr 3 18:48:10 2026] [::1]:56364 Accepted +[Fri Apr 3 18:48:11 2026] [::1]:56364 [200]: GET /favicon.ico +[Fri Apr 3 18:48:11 2026] [::1]:56364 Closing +[Fri Apr 3 18:49:14 2026] [::1]:56788 Accepted +[Fri Apr 3 18:49:19 2026] [::1]:56788 [200]: GET /monatsvorhersage_old.php?year=2026&month=8 +[Fri Apr 3 18:49:19 2026] [::1]:56788 Closing +[Fri Apr 3 18:49:19 2026] [::1]:50541 Accepted +[Fri Apr 3 18:49:19 2026] [::1]:50541 [200]: GET /css/style.css +[Fri Apr 3 18:49:19 2026] [::1]:64984 Accepted +[Fri Apr 3 18:49:19 2026] [::1]:50541 Closing +[Fri Apr 3 18:49:19 2026] [::1]:64984 [200]: GET /js/astronomy.browser.min.js +[Fri Apr 3 18:49:19 2026] [::1]:64984 Closing +[Fri Apr 3 18:49:19 2026] [::1]:59992 Accepted +[Fri Apr 3 18:49:19 2026] [::1]:59556 Accepted +[Fri Apr 3 18:49:19 2026] [::1]:59992 [200]: GET /images/star16x16.png +[Fri Apr 3 18:49:19 2026] [::1]:59556 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 18:49:19 2026] [::1]:59992 Closing +[Fri Apr 3 18:49:19 2026] [::1]:59556 Closing +[Fri Apr 3 18:49:19 2026] [::1]:50294 Accepted +[Fri Apr 3 18:49:20 2026] [::1]:50294 [200]: GET /favicon.ico +[Fri Apr 3 18:49:20 2026] [::1]:50294 Closing +[Fri Apr 3 18:51:40 2026] [::1]:63754 Accepted +[Fri Apr 3 18:51:46 2026] [::1]:63754 [200]: GET /monatsvorhersage_old.php?year=2026&month=8 +[Fri Apr 3 18:51:46 2026] [::1]:63754 Closing +[Fri Apr 3 18:53:18 2026] [::1]:57294 Accepted +[Fri Apr 3 18:53:24 2026] [::1]:57294 [200]: GET /monatsvorhersage_old.php?year=2026&month=8 +[Fri Apr 3 18:53:24 2026] [::1]:57294 Closing +[Fri Apr 3 18:53:24 2026] [::1]:55563 Accepted +[Fri Apr 3 18:53:24 2026] [::1]:55563 [200]: GET /css/style.css +[Fri Apr 3 18:53:24 2026] [::1]:58259 Accepted +[Fri Apr 3 18:53:24 2026] [::1]:55563 Closing +[Fri Apr 3 18:53:24 2026] [::1]:58259 [200]: GET /js/astronomy.browser.min.js +[Fri Apr 3 18:53:24 2026] [::1]:58259 Closing +[Fri Apr 3 18:53:24 2026] [::1]:59141 Accepted +[Fri Apr 3 18:53:24 2026] [::1]:59141 [200]: GET /images/star16x16.png +[Fri Apr 3 18:53:24 2026] [::1]:56253 Accepted +[Fri Apr 3 18:53:24 2026] [::1]:56253 [200]: GET /images/star16x16_rays.png +[Fri Apr 3 18:53:24 2026] [::1]:59141 Closing +[Fri Apr 3 18:53:24 2026] [::1]:56253 Closing +[Fri Apr 3 18:53:24 2026] [::1]:53603 Accepted +[Fri Apr 3 18:53:24 2026] [::1]:53603 [200]: GET /favicon.ico +[Fri Apr 3 18:53:24 2026] [::1]:53603 Closing diff --git a/public/monatsvorhersage_old.php b/public/monatsvorhersage_old.php index 568e2ef..6117904 100644 --- a/public/monatsvorhersage_old.php +++ b/public/monatsvorhersage_old.php @@ -68,6 +68,7 @@ $venusPeakMagnitudeEvents = []; $outerPlanetEvents = []; $outerPlanetStationEvents = []; $moonOccultations = []; +$meteorShowerPeaks = []; $seasonChanges = []; $timeChanges = []; $monthEventList = []; @@ -92,6 +93,91 @@ if (!function_exists('buildMonthOccultationStarLabel')) { } } +if (!function_exists('normalizeMonthForecastDegree')) { + function normalizeMonthForecastDegree(float $value): float + { + $normalized = fmod($value, 360.0); + if ($normalized < 0.0) { + $normalized += 360.0; + } + + return $normalized; + } +} + +if (!function_exists('monthForecastSolarLongitude')) { + function monthForecastSolarLongitude(DateTimeImmutable $dateTime): float + { + $julianDay = ((float) $dateTime->format('U')) / 86400.0 + 2440587.5; + $daysSinceJ2000 = $julianDay - 2451545.0; + $meanLongitude = normalizeMonthForecastDegree(280.46 + 0.9856474 * $daysSinceJ2000); + $meanAnomalyRad = deg2rad(normalizeMonthForecastDegree(357.528 + 0.9856003 * $daysSinceJ2000)); + + return normalizeMonthForecastDegree( + $meanLongitude + + 1.915 * sin($meanAnomalyRad) + + 0.020 * sin(2.0 * $meanAnomalyRad) + ); + } +} + +if (!function_exists('monthForecastForwardDegreeDistance')) { + function monthForecastForwardDegreeDistance(float $from, float $to): float + { + return normalizeMonthForecastDegree($to - $from); + } +} + +if (!function_exists('monthForecastRadiantIsVisible')) { + function monthForecastRadiantIsVisible(float $latitudeDeg, ?float $declinationDeg): bool + { + if ($declinationDeg === null) { + return false; + } + + return abs($latitudeDeg - $declinationDeg) < 90.0; + } +} + +if (!function_exists('findMonthForecastSolarLongitudeCrossing')) { + function findMonthForecastSolarLongitudeCrossing( + DateTimeImmutable $rangeStartLocal, + DateTimeImmutable $rangeEndLocal, + float $targetLongitude, + DateTimeZone $displayTimezone + ): ?DateTimeImmutable { + $utc = new DateTimeZone('UTC'); + $rangeStartUtc = $rangeStartLocal->setTimezone($utc); + $rangeEndUtc = $rangeEndLocal->setTimezone($utc); + + $startLongitude = monthForecastSolarLongitude($rangeStartUtc); + $endLongitude = monthForecastSolarLongitude($rangeEndUtc); + $targetDelta = monthForecastForwardDegreeDistance($startLongitude, $targetLongitude); + $rangeDelta = monthForecastForwardDegreeDistance($startLongitude, $endLongitude); + + if ($targetDelta > $rangeDelta + 0.0001) { + return null; + } + + $low = (int) $rangeStartUtc->format('U'); + $high = (int) $rangeEndUtc->format('U'); + + for ($i = 0; $i < 40; $i++) { + $mid = (int) floor(($low + $high) / 2); + $midLongitude = monthForecastSolarLongitude(new DateTimeImmutable('@' . $mid)); + $midDelta = monthForecastForwardDegreeDistance($startLongitude, $midLongitude); + + if ($midDelta < $targetDelta) { + $low = $mid; + } else { + $high = $mid; + } + } + + return (new DateTimeImmutable('@' . $high))->setTimezone($displayTimezone); + } +} + try { $dbConfig = require __DIR__ . '/../config/database.php'; $dsn = sprintf( @@ -250,6 +336,24 @@ try { 'size' => $row['major_axis'] !== null ? (float) $row['major_axis'] : 8.0, ]; } + + $meteorStmt = $pdo->query( + "SELECT designation, shower_code, radiant_delta_deg, peak_sol, zhr, zhr_variable + FROM meteorshowers + WHERE peak_sol IS NOT NULL + ORDER BY peak_sol ASC, designation ASC" + ); + + while ($row = $meteorStmt->fetch()) { + $meteorShowerPeaks[] = [ + 'designation' => trim((string) ($row['designation'] ?? '')), + 'shower_code' => trim((string) ($row['shower_code'] ?? '')), + 'radiant_delta_deg' => $row['radiant_delta_deg'] !== null ? (float) $row['radiant_delta_deg'] : null, + 'peak_sol' => (float) $row['peak_sol'], + 'zhr' => $row['zhr'] !== null ? (int) $row['zhr'] : null, + 'zhr_variable' => trim((string) ($row['zhr_variable'] ?? '')), + ]; + } } catch (Throwable $e) { $starDataError = $e->getMessage(); } @@ -884,6 +988,62 @@ foreach ($moonOccultations as $occultationEvent) { ]; } +$monthStartLocal = new DateTimeImmutable( + sprintf('%04d-%02d-01 00:00:00', $selectedYear, $selectedMonth), + new DateTimeZone($chartTimezone) +); +$monthEndLocal = $monthStartLocal->modify('first day of next month'); + +foreach ($meteorShowerPeaks as $meteorShowerPeak) { + if (!monthForecastRadiantIsVisible($chartLatitude, $meteorShowerPeak['radiant_delta_deg'] ?? null)) { + continue; + } + + $peakSol = isset($meteorShowerPeak['peak_sol']) ? (float) $meteorShowerPeak['peak_sol'] : null; + if ($peakSol === null) { + continue; + } + + $peakDateTime = findMonthForecastSolarLongitudeCrossing( + $monthStartLocal, + $monthEndLocal, + $peakSol, + new DateTimeZone($chartTimezone) + ); + if (!$peakDateTime instanceof DateTimeImmutable) { + continue; + } + + $designation = trim((string) ($meteorShowerPeak['designation'] ?? '')); + $showerCode = trim((string) ($meteorShowerPeak['shower_code'] ?? '')); + $zhr = $meteorShowerPeak['zhr'] ?? null; + $zhrVariable = trim((string) ($meteorShowerPeak['zhr_variable'] ?? '')); + $rateText = ''; + + if (is_int($zhr) && $zhr >= 0) { + $rateText = 'ZHR ca. ' . $zhr; + } elseif ($zhrVariable !== '') { + $rateText = 'ZHR ca. ' . $zhrVariable; + } + + $labelParts = []; + $labelParts[] = 'Maximum ' . ($designation !== '' ? $designation : 'Meteorstrom'); + if ($showerCode !== '') { + $labelParts[] = $showerCode; + } + if ($rateText !== '') { + $labelParts[] = $rateText; + } + + $monthEventList[] = [ + 'event' => implode(' - ', $labelParts), + 'date' => $peakDateTime->format('d.m.Y'), + 'time' => $peakDateTime->format('H:i'), + 'local_iso' => $peakDateTime->format(DateTimeInterface::ATOM), + 'type' => 'meteor_shower_peak', + ]; +} + usort( $monthEventList, static fn (array $a, array $b): int => strcmp((string) ($a['local_iso'] ?? ''), (string) ($b['local_iso'] ?? ''))