From 2c65f412cf13c08f99778b14f7f45086d4eddf98 Mon Sep 17 00:00:00 2001 From: emelianov Date: Thu, 28 May 2026 13:49:35 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B0=D1=81=D1=87=D0=B5=D1=82=20=D1=81?= =?UTF-8?q?=D1=80=D0=B5=D0=B4=D0=BD=D0=B8=D1=85=20=D0=97=D0=A0=D0=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../slots_service/controller/RvaController.kt | 33 +++++++++++ .../src/main/resources/static/rva_scripts.js | 59 ++++++++++++++++--- .../src/main/resources/templates/rva.html | 4 ++ 3 files changed, 87 insertions(+), 9 deletions(-) diff --git a/services/pcp-ui-service/src/main/kotlin/space/nstart/pcp/slots_service/controller/RvaController.kt b/services/pcp-ui-service/src/main/kotlin/space/nstart/pcp/slots_service/controller/RvaController.kt index 44a2c0f..7c3cf93 100644 --- a/services/pcp-ui-service/src/main/kotlin/space/nstart/pcp/slots_service/controller/RvaController.kt +++ b/services/pcp-ui-service/src/main/kotlin/space/nstart/pcp/slots_service/controller/RvaController.kt @@ -57,4 +57,37 @@ class RvaRestController( @PathVariable duration: Long, @RequestBody stations: List ) = slotService.rvaMergeOnRev(satelliteId, duration, stations) + + @PostMapping("/average/{satelliteId}/{duration}") + @ResponseBody + fun rvaAverage( + @PathVariable satelliteId: Long, + @PathVariable duration: Long, + @RequestBody stations: List + ): List { + val days = duration.coerceAtLeast(1).toDouble() + val zonesByStation = slotService.rvaCommon(satelliteId, duration, stations) + .groupBy { it.stationId } + + return stations + .sortedBy { it.number } + .map { station -> + val zones = zonesByStation[station.number.toLong()].orEmpty() + val zoneCount = zones.size + val totalDurationSec = zones.sumOf { it.duration } + RvaAverageDTO( + ppiNumber = station.number.toLong(), + ppiLatitude = station.position.lat, + averageCount = zoneCount / days, + averageDurationSec = if (zoneCount == 0) 0.0 else totalDurationSec / zoneCount + ) + } + } } + +data class RvaAverageDTO( + val ppiNumber: Long, + val ppiLatitude: Double, + val averageCount: Double, + val averageDurationSec: Double +) diff --git a/services/pcp-ui-service/src/main/resources/static/rva_scripts.js b/services/pcp-ui-service/src/main/resources/static/rva_scripts.js index a78a545..21ea05c 100644 --- a/services/pcp-ui-service/src/main/resources/static/rva_scripts.js +++ b/services/pcp-ui-service/src/main/resources/static/rva_scripts.js @@ -30,6 +30,17 @@ return date.toLocaleString('ru-RU'); } + function formatNumber(value, digits = 3) { + const number = Number(value); + if (!Number.isFinite(number)) { + return ''; + } + return number.toLocaleString('ru-RU', { + minimumFractionDigits: 0, + maximumFractionDigits: digits + }); + } + function selectedMode() { return document.querySelector('input[name="rva-mode"]:checked')?.value || 'common'; } @@ -113,7 +124,7 @@ ${row.durationSec} `).join(''); - } else { + } else if (resultState.mode === 'merge-on-rev') { head.innerHTML = ` Виток @@ -123,7 +134,24 @@ body.innerHTML = resultState.rows.map(row => ` ${row.revolution} - ${row.durationSec} + ${formatNumber(row.durationSec, 1)} + + `).join(''); + } else if (resultState.mode === 'average') { + head.innerHTML = ` + + №ППИ + Широта ППИ + Сред.кол-во + Сред.длит., с + + `; + body.innerHTML = resultState.rows.map(row => ` + + ${row.ppiNumber} + ${formatNumber(row.ppiLatitude, 6)} + ${formatNumber(row.averageCount, 3)} + ${formatNumber(row.averageDurationSec, 1)} `).join(''); } @@ -145,8 +173,9 @@ return; } - const lines = resultState.mode === 'common' - ? [ + let lines; + if (resultState.mode === 'common') { + lines = [ ['stationId', 'revolution', 'onStart', 'onMaximum', 'onStop', 'duration'], ...resultState.rows.map(row => [ row.stationId, @@ -156,23 +185,35 @@ row.onStop.time, row.duration ]) - ] - : resultState.mode === 'merge' - ? [ + ]; + } else if (resultState.mode === 'merge') { + lines = [ ['begin', 'end', 'durationSec'], ...resultState.rows.map(row => [ row.begin, row.end, row.durationSec ]) - ] - : [ + ]; + } else if (resultState.mode === 'merge-on-rev') { + lines = [ ['revolution', 'durationSec'], ...resultState.rows.map(row => [ row.revolution, row.durationSec ]) ]; + } else { + lines = [ + ['ppiNumber', 'ppiLatitude', 'averageCount', 'averageDurationSec'], + ...resultState.rows.map(row => [ + row.ppiNumber, + row.ppiLatitude, + row.averageCount, + row.averageDurationSec + ]) + ]; + } const csv = lines.map(line => line.map(csvEscape).join(';')).join('\n'); const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); diff --git a/services/pcp-ui-service/src/main/resources/templates/rva.html b/services/pcp-ui-service/src/main/resources/templates/rva.html index f5fc046..45709fd 100644 --- a/services/pcp-ui-service/src/main/resources/templates/rva.html +++ b/services/pcp-ui-service/src/main/resources/templates/rva.html @@ -56,6 +56,10 @@ +
+ + +