Ephemeriden Karte verbessert

This commit is contained in:
Eskimue
2026-04-28 13:42:51 +02:00
parent 7990c9f321
commit dd0a390344
2 changed files with 126 additions and 48 deletions
+110 -43
View File
@@ -327,6 +327,8 @@ $intervalOptions = [
'360' => '6 Stunden', '360' => '6 Stunden',
'720' => '12 Stunden', '720' => '12 Stunden',
'1440' => '1 Tag', '1440' => '1 Tag',
'2880' => '2 Tage',
'4320' => '3 Tage',
'10080' => '7 Tage', '10080' => '7 Tage',
'20160' => '14 Tage', '20160' => '14 Tage',
'43200' => '30 Tage', '43200' => '30 Tage',
@@ -361,6 +363,12 @@ if ($rangeValueInput === '') {
$rangeValueInput = '7'; $rangeValueInput = '7';
} }
$startDtInput = trim((string) ($_POST['start_dt'] ?? ''));
// Validierung: muss leer sein (= jetzt) oder dem Format YYYY-MM-DDTHH:MM entsprechen
if ($startDtInput !== '' && !preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/', $startDtInput)) {
$startDtInput = '';
}
function ephemeriden_h(mixed $value): string function ephemeriden_h(mixed $value): string
{ {
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8'); return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
@@ -441,8 +449,6 @@ $exportFormat = (string) ($_POST['export_format'] ?? '');
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($pageLocation === null || $pageLocation['latitude'] === null || $pageLocation['longitude'] === null) { if ($pageLocation === null || $pageLocation['latitude'] === null || $pageLocation['longitude'] === null) {
$errorMessage = 'Kein gültiger Standard-Standort verfügbar. Bitte zuerst in den Einstellungen einen Standard-Standort setzen.'; $errorMessage = 'Kein gültiger Standard-Standort verfügbar. Bitte zuerst in den Einstellungen einen Standard-Standort setzen.';
} elseif (false && (str_starts_with($selectedBody, 'comet:') || str_starts_with($selectedBody, 'minorplanet:'))) {
$errorMessage = 'Favoriten-Kometen und Favoriten-Kleinplaneten sind jetzt in der Auswahl sichtbar. Die eigentliche Ephemeriden-Berechnung dafür binden wir als Nächstes an.';
} elseif (!ctype_digit($rangeValueInput) || (int) $rangeValueInput < 1 || (int) $rangeValueInput > 100) { } elseif (!ctype_digit($rangeValueInput) || (int) $rangeValueInput < 1 || (int) $rangeValueInput > 100) {
$errorMessage = 'Der Zeitraum muss als ganze Zahl zwischen 1 und 100 angegeben werden.'; $errorMessage = 'Der Zeitraum muss als ganze Zahl zwischen 1 und 100 angegeben werden.';
} else { } else {
@@ -456,6 +462,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$selectedInterval, $selectedInterval,
$rangeValueInput, $rangeValueInput,
$selectedRangeUnit, $selectedRangeUnit,
$startDtInput,
]; ];
if (isset($minorplanetPayloads[$selectedBody])) { if (isset($minorplanetPayloads[$selectedBody])) {
@@ -470,6 +477,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$selectedInterval, $selectedInterval,
$rangeValueInput, $rangeValueInput,
$selectedRangeUnit, $selectedRangeUnit,
$startDtInput,
]; ];
} elseif (isset($cometPayloads[$selectedBody])) { } elseif (isset($cometPayloads[$selectedBody])) {
$pythonAction = 'small_body_ephemeris'; $pythonAction = 'small_body_ephemeris';
@@ -483,6 +491,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$selectedInterval, $selectedInterval,
$rangeValueInput, $rangeValueInput,
$selectedRangeUnit, $selectedRangeUnit,
$startDtInput,
]; ];
} }
@@ -767,7 +776,17 @@ require __DIR__ . '/header.php';
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="ephemeridenRangeValue">Zeitraum ab heute</label> <label for="ephemeridenStartDt">Startdatum &amp; Uhrzeit</label>
<input
type="datetime-local"
id="ephemeridenStartDt"
name="start_dt"
value="<?= ephemeriden_h($startDtInput) ?>"
>
</div>
<div class="form-group">
<label for="ephemeridenRangeValue">Zeitraum</label>
<input <input
type="number" type="number"
id="ephemeridenRangeValue" id="ephemeridenRangeValue"
@@ -813,6 +832,7 @@ require __DIR__ . '/header.php';
<input type="hidden" name="interval_minutes" value="<?= ephemeriden_h($selectedInterval) ?>"> <input type="hidden" name="interval_minutes" value="<?= ephemeriden_h($selectedInterval) ?>">
<input type="hidden" name="range_value" value="<?= ephemeriden_h($rangeValueInput) ?>"> <input type="hidden" name="range_value" value="<?= ephemeriden_h($rangeValueInput) ?>">
<input type="hidden" name="range_unit" value="<?= ephemeriden_h($selectedRangeUnit) ?>"> <input type="hidden" name="range_unit" value="<?= ephemeriden_h($selectedRangeUnit) ?>">
<input type="hidden" name="start_dt" value="<?= ephemeriden_h($startDtInput) ?>">
<input type="hidden" name="export_format" value="csv"> <input type="hidden" name="export_format" value="csv">
<button type="submit" class="btn btn-secondary">Export CSV</button> <button type="submit" class="btn btn-secondary">Export CSV</button>
</form> </form>
@@ -894,8 +914,17 @@ require __DIR__ . '/header.php';
<?php endforeach; ?> <?php endforeach; ?>
</select> </select>
</div> </div>
<div class="form-group">
<label for="ephemeridenChartLabelRotation">Textausrichtung</label>
<select id="ephemeridenChartLabelRotation">
<?php foreach (range(-165, 165, 15) as $deg): ?>
<option value="<?= ephemeriden_h((string) $deg) ?>"<?= $deg === -45 ? ' selected' : '' ?>><?= ephemeriden_h($deg > 0 ? "+$deg" : (string) $deg) ?>°</option>
<?php endforeach; ?>
</select>
</div>
<div class="ephemeriden-submit-group"> <div class="ephemeriden-submit-group">
<button type="button" class="btn btn-secondary" id="ephemeridenChartApply">Karte neu berechnen</button> <button type="button" class="btn btn-secondary" id="ephemeridenChartApply">Karte neu berechnen</button>
<button type="button" class="btn btn-secondary" id="ephemeridenChartExport">Als PNG exportieren</button>
</div> </div>
</div> </div>
</div> </div>
@@ -924,9 +953,14 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
const pointSelect = document.getElementById('ephemeridenChartPoint'); const pointSelect = document.getElementById('ephemeridenChartPoint');
const timeInput = document.getElementById('ephemeridenChartTime'); const timeInput = document.getElementById('ephemeridenChartTime');
const labelStepSelect = document.getElementById('ephemeridenChartLabelStep'); const labelStepSelect = document.getElementById('ephemeridenChartLabelStep');
const labelRotationSelect = document.getElementById('ephemeridenChartLabelRotation');
const applyButton = document.getElementById('ephemeridenChartApply'); const applyButton = document.getElementById('ephemeridenChartApply');
if (!toggleButton || !chartCard || !canvas || !pointSelect || !timeInput || !labelStepSelect || !applyButton || !Array.isArray(EPHEMERIDEN_CHART_ROWS) || EPHEMERIDEN_CHART_ROWS.length === 0) { const logoImage = new Image();
logoImage.src = 'images/logoAM.png';
logoImage.onload = () => { if (!chartCard.hidden) { drawChart(); } };
if (!toggleButton || !chartCard || !canvas || !pointSelect || !timeInput || !labelStepSelect || !labelRotationSelect || !applyButton || !Array.isArray(EPHEMERIDEN_CHART_ROWS) || EPHEMERIDEN_CHART_ROWS.length === 0) {
return; return;
} }
@@ -1039,6 +1073,11 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
return Number.isInteger(value) && value >= 1 ? value : 4; return Number.isInteger(value) && value >= 1 ? value : 4;
} }
function getLabelRotationValue() {
const value = Number(labelRotationSelect.value);
return Number.isFinite(value) ? value : 45;
}
function syncChartTimeFromSelectedRow() { function syncChartTimeFromSelectedRow() {
const selectedRow = getSelectedRow(); const selectedRow = getSelectedRow();
if (!selectedRow || !selectedRow.time_local) { if (!selectedRow || !selectedRow.time_local) {
@@ -1210,7 +1249,7 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
return ''; return '';
} }
function drawStars(centerX, centerY, radius) { function drawStars(centerX, centerY, radius, scale) {
if (!window.Astronomy || !observer || !getChartDate() || !Array.isArray(EPHEMERIDEN_CHART_STARS)) { if (!window.Astronomy || !observer || !getChartDate() || !Array.isArray(EPHEMERIDEN_CHART_STARS)) {
return; return;
} }
@@ -1238,7 +1277,7 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
? Math.min(Number(star.mag), Number(EPHEMERIDEN_CHART_CONFIG.starLimit || 4.4) + 0.35) ? Math.min(Number(star.mag), Number(EPHEMERIDEN_CHART_CONFIG.starLimit || 4.4) + 0.35)
: Number(star.mag); : Number(star.mag);
const brightness = clamp01((Number(EPHEMERIDEN_CHART_CONFIG.starLimit || 4.4) - effectiveMagnitude + 1.6) / magRange); const brightness = clamp01((Number(EPHEMERIDEN_CHART_CONFIG.starLimit || 4.4) - effectiveMagnitude + 1.6) / magRange);
const starRadius = (isConstellationStar ? 0.85 : 0.65) + Math.pow(brightness, 1.9) * 5.2; const starRadius = ((isConstellationStar ? 0.85 : 0.65) + Math.pow(brightness, 1.9) * 5.2) * scale;
const glowRadius = starRadius * (effectiveMagnitude <= 1 ? 2.8 : 1.9); const glowRadius = starRadius * (effectiveMagnitude <= 1 ? 2.8 : 1.9);
const color = starColor(star); const color = starColor(star);
@@ -1258,7 +1297,7 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
if (Number(star.mag) <= 0.8) { if (Number(star.mag) <= 0.8) {
ctx.strokeStyle = color + '44'; ctx.strokeStyle = color + '44';
ctx.lineWidth = 1; ctx.lineWidth = scale;
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(pt.x - starRadius * 1.35, pt.y); ctx.moveTo(pt.x - starRadius * 1.35, pt.y);
ctx.lineTo(pt.x + starRadius * 1.35, pt.y); ctx.lineTo(pt.x + starRadius * 1.35, pt.y);
@@ -1270,19 +1309,19 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
if (Number(star.mag) <= Number(EPHEMERIDEN_CHART_CONFIG.starLabelLimit || 2.0)) { if (Number(star.mag) <= Number(EPHEMERIDEN_CHART_CONFIG.starLabelLimit || 2.0)) {
const label = getStarLabel(star); const label = getStarLabel(star);
if (label !== '') { if (label !== '') {
drawLabel(label, pt.x + starRadius + 5, pt.y - 1, { drawLabel(label, pt.x + starRadius + 5 * scale, pt.y - 1, {
font: '600 11px Rajdhani, sans-serif', font: `600 ${Math.round(11 * scale)}px Rajdhani, sans-serif`,
color: 'rgba(232, 239, 255, 0.82)', color: 'rgba(232, 239, 255, 0.82)',
align: 'left', align: 'left',
baseline: 'middle', baseline: 'middle',
padding: 2, padding: 2 * scale,
}); });
} }
} }
} }
} }
function drawConstellationLines(centerX, centerY, radius) { function drawConstellationLines(centerX, centerY, radius, scale) {
if (!window.Astronomy || !observer || !getChartDate() || !Array.isArray(EPHEMERIDEN_CHART_CONSTELLATIONS)) { if (!window.Astronomy || !observer || !getChartDate() || !Array.isArray(EPHEMERIDEN_CHART_CONSTELLATIONS)) {
return; return;
} }
@@ -1327,7 +1366,7 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
ctx.lineJoin = 'round'; ctx.lineJoin = 'round';
ctx.strokeStyle = 'rgba(210, 214, 224, 0.16)'; ctx.strokeStyle = 'rgba(210, 214, 224, 0.16)';
ctx.lineWidth = 2.1; ctx.lineWidth = 2.1 * scale;
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y); ctx.moveTo(points[0].x, points[0].y);
for (let index = 1; index < points.length; index += 1) { for (let index = 1; index < points.length; index += 1) {
@@ -1336,7 +1375,7 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
ctx.stroke(); ctx.stroke();
ctx.strokeStyle = 'rgba(36, 40, 48, 0.34)'; ctx.strokeStyle = 'rgba(36, 40, 48, 0.34)';
ctx.lineWidth = 0.95; ctx.lineWidth = 0.95 * scale;
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(points[0].x + 0.18, points[0].y - 0.12); ctx.moveTo(points[0].x + 0.18, points[0].y - 0.12);
for (let index = 1; index < points.length; index += 1) { for (let index = 1; index < points.length; index += 1) {
@@ -1363,9 +1402,9 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
drawChart(); drawChart();
} }
function drawCircleLabel(text, x, y) { function drawCircleLabel(text, x, y, scale) {
ctx.save(); ctx.save();
ctx.font = '12px Space Mono, monospace'; ctx.font = `${Math.round(12 * scale)}px Space Mono, monospace`;
ctx.fillStyle = 'rgba(232, 239, 255, 0.76)'; ctx.fillStyle = 'rgba(232, 239, 255, 0.76)';
ctx.textAlign = 'center'; ctx.textAlign = 'center';
ctx.textBaseline = 'middle'; ctx.textBaseline = 'middle';
@@ -1373,9 +1412,10 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
ctx.restore(); ctx.restore();
} }
function drawChart() { function drawChart(overrideSize) {
const width = canvas.clientWidth; const width = overrideSize ?? canvas.clientWidth;
const height = canvas.clientHeight; const height = overrideSize ?? canvas.clientHeight;
const scale = width / (canvas.clientWidth || width);
const centerX = width / 2; const centerX = width / 2;
const centerY = height / 2; const centerY = height / 2;
const radius = Math.min(width, height) * 0.43; const radius = Math.min(width, height) * 0.43;
@@ -1383,6 +1423,8 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
resetLabelBoxes(); resetLabelBoxes();
ctx.clearRect(0, 0, width, height); ctx.clearRect(0, 0, width, height);
ctx.fillStyle = '#06080f';
ctx.fillRect(0, 0, width, height);
const background = ctx.createRadialGradient(centerX, centerY, radius * 0.05, centerX, centerY, radius); const background = ctx.createRadialGradient(centerX, centerY, radius * 0.05, centerX, centerY, radius);
background.addColorStop(0, 'rgba(8, 12, 22, 0.98)'); background.addColorStop(0, 'rgba(8, 12, 22, 0.98)');
@@ -1394,13 +1436,13 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
ctx.fill(); ctx.fill();
ctx.strokeStyle = 'rgba(130, 170, 255, 0.18)'; ctx.strokeStyle = 'rgba(130, 170, 255, 0.18)';
ctx.lineWidth = 1; ctx.lineWidth = scale;
[0, 30, 60].forEach((altitude) => { [0, 30, 60].forEach((altitude) => {
const ringRadius = radius * ((90 - altitude) / 90); const ringRadius = radius * ((90 - altitude) / 90);
ctx.beginPath(); ctx.beginPath();
ctx.arc(centerX, centerY, ringRadius, 0, Math.PI * 2); ctx.arc(centerX, centerY, ringRadius, 0, Math.PI * 2);
ctx.stroke(); ctx.stroke();
drawCircleLabel(`${altitude}°`, centerX, centerY - ringRadius - 12); drawCircleLabel(`${altitude}°`, centerX, centerY - ringRadius - 12 * scale, scale);
}); });
ctx.beginPath(); ctx.beginPath();
@@ -1411,13 +1453,13 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
ctx.strokeStyle = 'rgba(130, 170, 255, 0.14)'; ctx.strokeStyle = 'rgba(130, 170, 255, 0.14)';
ctx.stroke(); ctx.stroke();
drawCircleLabel('N', centerX, centerY - radius - 20); drawCircleLabel('N', centerX, centerY - radius - 20 * scale, scale);
drawCircleLabel('O', centerX + radius + 20, centerY); drawCircleLabel('W', centerX + radius + 20 * scale, centerY, scale);
drawCircleLabel('S', centerX, centerY + radius + 20); drawCircleLabel('S', centerX, centerY + radius + 20 * scale, scale);
drawCircleLabel('W', centerX - radius - 20, centerY); drawCircleLabel('O', centerX - radius - 20 * scale, centerY, scale);
drawCircleLabel('Zenit', centerX, centerY); drawCircleLabel('Zenit', centerX, centerY, scale);
drawConstellationLines(centerX, centerY, radius); drawConstellationLines(centerX, centerY, radius, scale);
drawStars(centerX, centerY, radius); drawStars(centerX, centerY, radius, scale);
const visiblePoints = EPHEMERIDEN_CHART_ROWS const visiblePoints = EPHEMERIDEN_CHART_ROWS
.map((row, rowIndex) => { .map((row, rowIndex) => {
@@ -1455,46 +1497,45 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
} }
}); });
ctx.strokeStyle = 'rgba(246, 206, 97, 0.92)'; ctx.strokeStyle = 'rgba(246, 206, 97, 0.92)';
ctx.lineWidth = 2.6; ctx.lineWidth = 2.6 * scale;
ctx.shadowColor = 'rgba(246, 206, 97, 0.32)'; ctx.shadowColor = 'rgba(246, 206, 97, 0.32)';
ctx.shadowBlur = 10; ctx.shadowBlur = 10 * scale;
ctx.stroke(); ctx.stroke();
ctx.shadowBlur = 0; ctx.shadowBlur = 0;
const labelStep = getLabelStepValue(); const labelStep = getLabelStepValue();
const labelRotation = getLabelRotationValue();
resetLabelBoxes(); resetLabelBoxes();
visiblePoints.forEach((entry, index) => { visiblePoints.forEach((entry, index) => {
const isFirst = index === 0; const isFirst = index === 0;
const isLast = index === visiblePoints.length - 1; const isLast = index === visiblePoints.length - 1;
const markerRadius = isFirst || isLast ? 5 : 3.5;
ctx.beginPath(); ctx.beginPath();
ctx.arc(entry.point.x, entry.point.y, markerRadius, 0, Math.PI * 2); ctx.arc(entry.point.x, entry.point.y, 3.5 * scale, 0, Math.PI * 2);
ctx.fillStyle = isFirst ? '#7fd8ff' : (isLast ? '#ffb36b' : 'rgba(255, 236, 190, 0.96)'); ctx.fillStyle = 'rgba(255, 236, 190, 0.96)';
ctx.fill(); ctx.fill();
if (isFirst || isLast || (index % labelStep === 0)) { if (isFirst || isLast || (index % labelStep === 0)) {
drawLabel(entry.label, entry.point.x + 10, entry.point.y - 8, { drawLabel(entry.label, entry.point.x + 10 * scale, entry.point.y - 8 * scale, {
font: '11px Space Mono, monospace', font: `${Math.round(11 * scale)}px Space Mono, monospace`,
color: 'rgba(232, 239, 255, 0.88)', color: 'rgba(232, 239, 255, 0.88)',
align: 'left', align: 'left',
baseline: 'bottom', baseline: 'bottom',
padding: 4, padding: 4 * scale,
rotationDeg: -45, rotationDeg: labelRotation,
backgroundColor: 'rgba(7, 10, 18, 0.82)', backgroundColor: 'rgba(7, 10, 18, 0.82)',
force: true, force: true,
}); });
} }
}); });
if (selectedRow) {
if (logoImage.complete && logoImage.naturalWidth > 0) {
const logoH = Math.round(width * 0.07);
const logoW = Math.round(logoH * logoImage.naturalWidth / logoImage.naturalHeight);
ctx.save(); ctx.save();
ctx.font = '600 12px Rajdhani, sans-serif'; ctx.globalAlpha = 0.82;
ctx.fillStyle = 'rgba(232, 239, 255, 0.78)'; ctx.drawImage(logoImage, width - logoW - 14, height - logoH - 14, logoW, logoH);
ctx.textAlign = 'right';
ctx.textBaseline = 'top';
const chartTimeValue = getChartTimeValue() || String(selectedRow.time_local || '').slice(0, 5);
ctx.fillText(`Sternhimmel für ${selectedRow.date_local} ${chartTimeValue}`, width - 18, 16);
ctx.restore(); ctx.restore();
} }
} }
@@ -1527,6 +1568,32 @@ const EPHEMERIDEN_CHART_CONSTELLATIONS = <?= $ephemerisConstellationLinesJson ?>
} }
}); });
const exportButton = document.getElementById('ephemeridenChartExport');
if (exportButton) {
exportButton.addEventListener('click', () => {
const exportSize = 2000;
const sw = canvas.width;
const sh = canvas.height;
canvas.width = exportSize;
canvas.height = exportSize;
ctx.setTransform(1, 0, 0, 1, 0, 0);
drawChart(exportSize);
const link = document.createElement('a');
link.download = 'ephemeriden.png';
link.href = canvas.toDataURL('image/png');
link.click();
canvas.width = sw;
canvas.height = sh;
ctx.setTransform(1, 0, 0, 1, 0, 0);
const ratio = Math.min(window.devicePixelRatio || 1, 2);
ctx.scale(ratio, ratio);
drawChart();
});
}
syncChartTimeFromSelectedRow(); syncChartTimeFromSelectedRow();
})(); })();
</script> </script>
+15 -4
View File
@@ -419,12 +419,19 @@ def build_rows_response(
row_builder, row_builder,
rise_set_builder, rise_set_builder,
action_name: str, action_name: str,
start_dt_str: str = "",
) -> dict: ) -> dict:
try: try:
tz = ZoneInfo(timezone_name) tz = ZoneInfo(timezone_name)
except Exception as exc: except Exception as exc:
fail("Zeitzone ist ungueltig.", extra={"details": str(exc)}) fail("Zeitzone ist ungueltig.", extra={"details": str(exc)})
if start_dt_str:
try:
local_start = datetime.strptime(start_dt_str, "%Y-%m-%dT%H:%M").replace(tzinfo=tz)
except ValueError as exc:
fail("Startdatum ist ungueltig.", extra={"details": str(exc), "start_dt_str": start_dt_str})
else:
local_start = datetime.now(tz).replace(second=0, microsecond=0) local_start = datetime.now(tz).replace(second=0, microsecond=0)
local_end = add_calendar_unit(local_start, range_value, range_unit) local_end = add_calendar_unit(local_start, range_value, range_unit)
@@ -483,9 +490,9 @@ def build_rows_response(
def action_planet_ephemeris(args: list[str]) -> dict: def action_planet_ephemeris(args: list[str]) -> dict:
if len(args) != 8: if len(args) not in {8, 9}:
fail( fail(
"Aktion planet_ephemeris erwartet 8 Argumente: latitude longitude elevation timezone body intervalMinutes rangeValue rangeUnit", "Aktion planet_ephemeris erwartet 8 oder 9 Argumente: latitude longitude elevation timezone body intervalMinutes rangeValue rangeUnit [startDt]",
extra={"argv": args}, extra={"argv": args},
) )
@@ -502,6 +509,7 @@ def action_planet_ephemeris(args: list[str]) -> dict:
fail("Intervall oder Zeitraum ist ungueltig.", extra={"details": str(exc), "argv": args}) fail("Intervall oder Zeitraum ist ungueltig.", extra={"details": str(exc), "argv": args})
range_unit = str(args[7]).strip() range_unit = str(args[7]).strip()
start_dt_str = str(args[8]).strip() if len(args) == 9 else ""
if interval_minutes <= 0: if interval_minutes <= 0:
fail("Intervall muss groesser als 0 sein.", extra={"interval_minutes": interval_minutes}) fail("Intervall muss groesser als 0 sein.", extra={"interval_minutes": interval_minutes})
@@ -559,13 +567,14 @@ def action_planet_ephemeris(args: list[str]) -> dict:
row_builder=row_builder, row_builder=row_builder,
rise_set_builder=rise_set_builder, rise_set_builder=rise_set_builder,
action_name="planet_ephemeris", action_name="planet_ephemeris",
start_dt_str=start_dt_str,
) )
def action_small_body_ephemeris(args: list[str]) -> dict: def action_small_body_ephemeris(args: list[str]) -> dict:
if len(args) != 9: if len(args) not in {9, 10}:
fail( fail(
"Aktion small_body_ephemeris erwartet 9 Argumente: latitude longitude elevation timezone bodyType payload intervalMinutes rangeValue rangeUnit", "Aktion small_body_ephemeris erwartet 9 oder 10 Argumente: latitude longitude elevation timezone bodyType payload intervalMinutes rangeValue rangeUnit [startDt]",
extra={"argv": args}, extra={"argv": args},
) )
@@ -588,6 +597,7 @@ def action_small_body_ephemeris(args: list[str]) -> dict:
fail("Intervall oder Zeitraum ist ungueltig.", extra={"details": str(exc), "argv": args}) fail("Intervall oder Zeitraum ist ungueltig.", extra={"details": str(exc), "argv": args})
range_unit = str(args[8]).strip() range_unit = str(args[8]).strip()
start_dt_str = str(args[9]).strip() if len(args) == 10 else ""
if body_type not in {"minorplanet", "comet"}: if body_type not in {"minorplanet", "comet"}:
fail("Objekttyp ist ungueltig.", extra={"body_type": body_type}) fail("Objekttyp ist ungueltig.", extra={"body_type": body_type})
@@ -649,6 +659,7 @@ def action_small_body_ephemeris(args: list[str]) -> dict:
row_builder=row_builder, row_builder=row_builder,
rise_set_builder=rise_set_builder, rise_set_builder=rise_set_builder,
action_name="small_body_ephemeris", action_name="small_body_ephemeris",
start_dt_str=start_dt_str,
) )