сравнение TLE

This commit is contained in:
emelianov
2026-05-27 12:00:52 +03:00
parent 29c06a4c9c
commit f4014a08a1
8 changed files with 247 additions and 52 deletions
@@ -9,6 +9,7 @@
bindEvents();
updateReference('first', null);
updateReference('second', null);
updateTimeLimits();
});
function bindEvents() {
@@ -16,6 +17,7 @@
const second = el('tle-second-text');
first?.addEventListener('input', () => scheduleParse('first'));
second?.addEventListener('input', () => scheduleParse('second'));
el('tle-comparison-time')?.addEventListener('change', validateCalculationTime);
el('tle-compare-submit')?.addEventListener('click', compareTle);
el('tle-compare-clear')?.addEventListener('click', clearPage);
}
@@ -26,6 +28,7 @@
if (!text.trim()) {
state[side] = null;
updateReference(side, null);
updateTimeLimits();
return;
}
setStatus(side, 'Разбор...', 'text-muted');
@@ -37,10 +40,12 @@
const parsed = await postJson('/api/tle-comparison/parse', { tle: getTleText(side) });
state[side] = parsed;
updateReference(side, parsed);
updateTimeLimits();
setStatus(side, 'Разобрано', 'tle-parse-ok');
} catch (error) {
state[side] = null;
updateReference(side, null);
updateTimeLimits();
setStatus(side, error.message || 'Ошибка разбора', 'tle-parse-error');
}
}
@@ -49,21 +54,25 @@
showAlert('');
const first = getTleText('first');
const second = getTleText('second');
const time = getCalculationTime();
if (!first.trim() || !second.trim()) {
showAlert('Введите оба TLE для сравнения.', 'warning');
return;
}
if (!time) {
showAlert('Задайте время расчета.', 'warning');
return;
}
const minTime = maxEpoch();
if (minTime && time < minTime) {
showAlert(`Время расчета должно быть не раньше максимальной эпохи TLE: ${formatDateTime(minTime)}.`, 'warning');
return;
}
setCompareLoading(true);
try {
const response = await postJson('/api/tle-comparison/compare', { first, second });
state.first = response.first;
state.second = response.second;
updateReference('first', response.first);
updateReference('second', response.second);
setStatus('first', 'Разобрано', 'tle-parse-ok');
setStatus('second', 'Разобрано', 'tle-parse-ok');
renderComparison(response.rows || []);
const response = await postJson('/api/tle-comparison/compare', { first, second, time });
renderComparison(response);
} catch (error) {
showAlert(error.message || 'Не удалось выполнить сравнение TLE.', 'danger');
} finally {
@@ -71,7 +80,8 @@
}
}
function renderComparison(rows) {
function renderComparison(response) {
const rows = response?.rows || [];
const body = el('tle-comparison-result-body');
const empty = el('tle-comparison-empty');
const wrap = el('tle-comparison-table-wrap');
@@ -98,9 +108,9 @@
empty.classList.add('d-none');
wrap.classList.remove('d-none');
if (meta) {
const firstEpoch = formatDateTime(state.first?.time);
const secondEpoch = formatDateTime(state.second?.time);
meta.textContent = `Эпохи: TLE 1 — ${firstEpoch || '—'}, TLE 2 — ${secondEpoch || '—'}`;
const deltaNorm = response.radiusVectorDelta?.norm;
const deltaText = Number.isFinite(deltaNorm) ? `${formatNumber(deltaNorm)} м` : '—';
meta.textContent = `Время расчета: ${formatDateTime(response.time)}. |Δr| = ${deltaText}. Эпохи: TLE 1 — ${formatDateTime(response.firstEpoch)}, TLE 2 — ${formatDateTime(response.secondEpoch)}.`;
}
}
@@ -114,16 +124,46 @@
}
}
function updateTimeLimits() {
const input = el('tle-comparison-time');
const helper = el('tle-comparison-time-helper');
const minTime = maxEpoch();
if (!input) return;
if (!minTime) {
input.removeAttribute('min');
if (helper) helper.textContent = 'Минимальное допустимое время появится после разбора двух TLE.';
return;
}
input.min = toDateTimeLocalValue(minTime);
if (!input.value || input.value < input.min) {
input.value = input.min;
}
if (helper) helper.textContent = `Минимальное допустимое время: ${formatDateTime(minTime)}.`;
}
function validateCalculationTime() {
const input = el('tle-comparison-time');
const minTime = maxEpoch();
if (!input || !minTime || !input.value) return;
const time = getCalculationTime();
if (time && time < minTime) {
showAlert(`Время расчета должно быть не раньше максимальной эпохи TLE: ${formatDateTime(minTime)}.`, 'warning');
}
}
function clearPage() {
el('tle-first-text').value = '';
el('tle-second-text').value = '';
const time = el('tle-comparison-time');
if (time) time.value = '';
state.first = null;
state.second = null;
updateReference('first', null);
updateReference('second', null);
updateTimeLimits();
showAlert('');
renderComparison([]);
setText('tle-comparison-result-meta', 'Нажмите “Сравнить” после ввода двух TLE.');
renderComparison({ rows: [] });
setText('tle-comparison-result-meta', 'Задайте время не раньше максимальной эпохи TLE и нажмите “Сравнить”.');
}
async function postJson(url, payload) {
@@ -145,6 +185,16 @@
return response.json();
}
function maxEpoch() {
if (!state.first?.time || !state.second?.time) return null;
return state.first.time >= state.second.time ? state.first.time : state.second.time;
}
function getCalculationTime() {
const value = el('tle-comparison-time')?.value;
return value ? value : null;
}
function getTleText(side) {
return el(`tle-${side}-text`)?.value || '';
}
@@ -160,7 +210,7 @@
const button = el('tle-compare-submit');
if (!button) return;
button.disabled = loading;
button.textContent = loading ? 'Сравнение...' : 'Сравнить';
button.textContent = loading ? 'Расчет...' : 'Рассчитать';
}
function showAlert(message, type = 'info') {
@@ -174,11 +224,20 @@
: '';
}
function toDateTimeLocalValue(value) {
if (!value) return '';
return String(value).slice(0, 19);
}
function formatDateTime(value) {
if (!value) return '';
return String(value).replace('T', ' ');
}
function formatNumber(value) {
return Number(value).toLocaleString('ru-RU', { maximumFractionDigits: 3 });
}
function emptyToDash(value) {
return value === null || value === undefined || value === '' ? '—' : value;
}