Auswahl der Kalenderwoche möglich in GUI

This commit is contained in:
Eskimue
2026-04-24 13:15:05 +02:00
parent 645ee8aeb9
commit 09dc007b0c
+161 -4
View File
@@ -11,6 +11,8 @@ $publicBasePath = './';
$currentYear = (int) date('Y');
$selectedYear = isset($_GET['year']) ? (int) $_GET['year'] : $currentYear;
$selectedMonth = isset($_GET['month']) ? max(1, min(12, (int) $_GET['month'])) : (int) date('n');
$selectedWeek = isset($_GET['week']) ? max(1, min(53, (int) $_GET['week'])) : (int) date('W');
$selectedWeekYear = isset($_GET['week_year']) ? (int) $_GET['week_year'] : $currentYear;
$shouldRunForecast = isset($_GET['run']) && $_GET['run'] === '1';
// -------------------------------------------------------------------------
@@ -178,7 +180,16 @@ $favoriteCometVisibilityMaxMagnitude = 10.0;
// Einzelne Zufallstreffer sollen nicht als eigenes Monatsereignis erscheinen.
$favoriteCometVisibilityMinConsecutiveDays = 2;
if (!function_exists('getIsoWeekCountForYear')) {
function getIsoWeekCountForYear(int $year): int
{
return (int) (new DateTimeImmutable(sprintf('%04d-12-28', $year)))->format('W');
}
}
$years = range($currentYear - 2, $currentYear + 5);
$selectedWeek = max(1, min($selectedWeek, getIsoWeekCountForYear($selectedWeekYear)));
$weekNumbers = range(1, getIsoWeekCountForYear($selectedWeekYear));
$months = [
1 => 'Januar',
2 => 'Februar',
@@ -2399,7 +2410,13 @@ $observationTipCalendarFilenameJson = json_encode(sprintf('astrotools-monatserei
<p>Die Sternkarte wird für den 15. des gewählten Monats mit der festen Monatsuhrzeit erzeugt.</p>
</div>
<input type="hidden" name="run" value="1">
<section class="monatsvorhersage-mode">
<div class="monatsvorhersage-mode-header">
<h4>Monat</h4>
<p>Bestehende Monatsansicht mit Berechnung per Button.</p>
</div>
<input type="hidden" name="run" value="1">
<label class="monatsvorhersage-field">
<span>Jahr</span>
@@ -2423,9 +2440,44 @@ $observationTipCalendarFilenameJson = json_encode(sprintf('astrotools-monatserei
</select>
</label>
<div class="monatsvorhersage-actions">
<button type="submit">Monatsvorhersage berechnen</button>
</div>
<div class="monatsvorhersage-actions">
<button type="submit">Monatsvorhersage berechnen</button>
</div>
</section>
<section class="monatsvorhersage-mode monatsvorhersage-mode-disabled" aria-labelledby="wochenauswahl-heading">
<div class="monatsvorhersage-mode-header">
<h4 id="wochenauswahl-heading">Woche</h4>
<p>Nur vorbereitete GUI. Die Wochenberechnung ist noch nicht angeschlossen.</p>
</div>
<label class="monatsvorhersage-field">
<span>Jahr</span>
<select name="week_year" id="weekYearSelect">
<?php foreach ($years as $year): ?>
<option value="<?= htmlspecialchars((string) $year, ENT_QUOTES, 'UTF-8') ?>" <?= $year === $selectedWeekYear ? 'selected' : '' ?>>
<?= htmlspecialchars((string) $year, ENT_QUOTES, 'UTF-8') ?>
</option>
<?php endforeach; ?>
</select>
</label>
<label class="monatsvorhersage-field">
<span>Woche</span>
<select name="week" id="weekSelect">
<?php foreach ($weekNumbers as $weekNumber): ?>
<?php $weekStartLabel = (new DateTimeImmutable('now'))->setISODate($selectedWeekYear, $weekNumber, 1)->format('d.m.Y'); ?>
<option value="<?= htmlspecialchars((string) $weekNumber, ENT_QUOTES, 'UTF-8') ?>" <?= $weekNumber === $selectedWeek ? 'selected' : '' ?>>
<?= htmlspecialchars('KW ' . str_pad((string) $weekNumber, 2, '0', STR_PAD_LEFT) . ' (' . $weekStartLabel . ')', ENT_QUOTES, 'UTF-8') ?>
</option>
<?php endforeach; ?>
</select>
</label>
<div class="monatsvorhersage-actions">
<button type="button" disabled>Wochenansicht folgt spaeter</button>
</div>
</section>
</form>
<?php if ($shouldRunForecast): ?>
@@ -2590,6 +2642,37 @@ $observationTipCalendarFilenameJson = json_encode(sprintf('astrotools-monatserei
padding: 22px 20px;
}
.monatsvorhersage-mode {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px;
align-content: start;
padding: 18px;
border: 1px solid rgba(108, 145, 220, 0.2);
border-radius: 16px;
background: rgba(6, 12, 24, 0.38);
}
.monatsvorhersage-mode-disabled {
border-color: rgba(201, 168, 76, 0.18);
background: rgba(18, 18, 22, 0.34);
}
.monatsvorhersage-mode-header {
grid-column: 1 / -1;
}
.monatsvorhersage-mode-header h4 {
margin: 0 0 6px;
font-size: 1.05rem;
}
.monatsvorhersage-mode-header p {
margin: 0;
color: rgba(222, 232, 255, 0.78);
line-height: 1.6;
}
.monatsvorhersage-form-header,
.monatskarte-header,
.monatskarte-footer {
@@ -2650,6 +2733,13 @@ $observationTipCalendarFilenameJson = json_encode(sprintf('astrotools-monatserei
cursor: pointer;
}
.monatsvorhersage-mode-disabled .monatsvorhersage-actions button {
border-color: rgba(180, 186, 205, 0.38);
background: rgba(48, 54, 70, 0.7);
color: rgba(226, 232, 244, 0.76);
cursor: not-allowed;
}
.monatskarte-header {
display: flex;
justify-content: space-between;
@@ -2761,6 +2851,10 @@ $observationTipCalendarFilenameJson = json_encode(sprintf('astrotools-monatserei
grid-template-columns: 1fr;
}
.monatsvorhersage-mode {
grid-template-columns: 1fr;
}
.monatskarte-header {
flex-direction: column;
}
@@ -2785,6 +2879,69 @@ const OBSERVATION_TIP_ICAL_FILENAME = <?= $observationTipCalendarFilenameJson ?:
const MONTH_CHART_COMET_K = 0.01720209895;
const MONTH_CHART_COMET_OBLIQ = 23.439279444444445 * Math.PI / 180;
function isoWeekCount(year) {
const dec28 = new Date(Date.UTC(year, 11, 28));
const day = dec28.getUTCDay() || 7;
dec28.setUTCDate(dec28.getUTCDate() + 4 - day);
const yearStart = new Date(Date.UTC(dec28.getUTCFullYear(), 0, 1));
return Math.ceil((((dec28 - yearStart) / 86400000) + 1) / 7);
}
function isoWeekMonday(year, week) {
const jan4 = new Date(Date.UTC(year, 0, 4));
const jan4Day = jan4.getUTCDay() || 7;
const monday = new Date(jan4);
monday.setUTCDate(jan4.getUTCDate() - jan4Day + 1 + ((week - 1) * 7));
return monday;
}
function formatGermanDate(date) {
const day = String(date.getUTCDate()).padStart(2, '0');
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
const year = String(date.getUTCFullYear());
return day + '.' + month + '.' + year;
}
function rebuildWeekOptions() {
const weekYearSelect = document.getElementById('weekYearSelect');
const weekSelect = document.getElementById('weekSelect');
if (!weekYearSelect || !weekSelect) {
return;
}
const selectedYear = Number(weekYearSelect.value);
if (!Number.isInteger(selectedYear) || selectedYear < 1) {
return;
}
const previousWeek = Number(weekSelect.value) || 1;
const totalWeeks = isoWeekCount(selectedYear);
const nextWeek = Math.min(Math.max(previousWeek, 1), totalWeeks);
weekSelect.innerHTML = '';
for (let week = 1; week <= totalWeeks; week++) {
const option = document.createElement('option');
option.value = String(week);
option.textContent = 'KW ' + String(week).padStart(2, '0') + ' (' + formatGermanDate(isoWeekMonday(selectedYear, week)) + ')';
if (week === nextWeek) {
option.selected = true;
}
weekSelect.appendChild(option);
}
}
document.addEventListener('DOMContentLoaded', function () {
const weekYearSelect = document.getElementById('weekYearSelect');
if (!weekYearSelect) {
return;
}
rebuildWeekOptions();
weekYearSelect.addEventListener('change', rebuildWeekOptions);
});
function monthChartCometSolveElliptic(M, e) {
let E = e < 0.8 ? M : (M >= 0 ? Math.PI : -Math.PI);
for (let i = 0; i < 30; i++) {