Расчет средних ЗРВ

This commit is contained in:
emelianov
2026-05-28 13:49:35 +03:00
parent 6e62a0bd19
commit 2c65f412cf
3 changed files with 87 additions and 9 deletions
@@ -57,4 +57,37 @@ class RvaRestController(
@PathVariable duration: Long, @PathVariable duration: Long,
@RequestBody stations: List<StationDTO> @RequestBody stations: List<StationDTO>
) = slotService.rvaMergeOnRev(satelliteId, duration, stations) ) = slotService.rvaMergeOnRev(satelliteId, duration, stations)
@PostMapping("/average/{satelliteId}/{duration}")
@ResponseBody
fun rvaAverage(
@PathVariable satelliteId: Long,
@PathVariable duration: Long,
@RequestBody stations: List<StationDTO>
): List<RvaAverageDTO> {
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
)
@@ -30,6 +30,17 @@
return date.toLocaleString('ru-RU'); 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() { function selectedMode() {
return document.querySelector('input[name="rva-mode"]:checked')?.value || 'common'; return document.querySelector('input[name="rva-mode"]:checked')?.value || 'common';
} }
@@ -113,7 +124,7 @@
<td>${row.durationSec}</td> <td>${row.durationSec}</td>
</tr> </tr>
`).join(''); `).join('');
} else { } else if (resultState.mode === 'merge-on-rev') {
head.innerHTML = ` head.innerHTML = `
<tr> <tr>
<th>Виток</th> <th>Виток</th>
@@ -123,7 +134,24 @@
body.innerHTML = resultState.rows.map(row => ` body.innerHTML = resultState.rows.map(row => `
<tr> <tr>
<td>${row.revolution}</td> <td>${row.revolution}</td>
<td>${row.durationSec}</td> <td>${formatNumber(row.durationSec, 1)}</td>
</tr>
`).join('');
} else if (resultState.mode === 'average') {
head.innerHTML = `
<tr>
<th>№ППИ</th>
<th>Широта ППИ</th>
<th>Сред.кол-во</th>
<th>Сред.длит., с</th>
</tr>
`;
body.innerHTML = resultState.rows.map(row => `
<tr>
<td>${row.ppiNumber}</td>
<td>${formatNumber(row.ppiLatitude, 6)}</td>
<td>${formatNumber(row.averageCount, 3)}</td>
<td>${formatNumber(row.averageDurationSec, 1)}</td>
</tr> </tr>
`).join(''); `).join('');
} }
@@ -145,8 +173,9 @@
return; return;
} }
const lines = resultState.mode === 'common' let lines;
? [ if (resultState.mode === 'common') {
lines = [
['stationId', 'revolution', 'onStart', 'onMaximum', 'onStop', 'duration'], ['stationId', 'revolution', 'onStart', 'onMaximum', 'onStop', 'duration'],
...resultState.rows.map(row => [ ...resultState.rows.map(row => [
row.stationId, row.stationId,
@@ -156,23 +185,35 @@
row.onStop.time, row.onStop.time,
row.duration row.duration
]) ])
] ];
: resultState.mode === 'merge' } else if (resultState.mode === 'merge') {
? [ lines = [
['begin', 'end', 'durationSec'], ['begin', 'end', 'durationSec'],
...resultState.rows.map(row => [ ...resultState.rows.map(row => [
row.begin, row.begin,
row.end, row.end,
row.durationSec row.durationSec
]) ])
] ];
: [ } else if (resultState.mode === 'merge-on-rev') {
lines = [
['revolution', 'durationSec'], ['revolution', 'durationSec'],
...resultState.rows.map(row => [ ...resultState.rows.map(row => [
row.revolution, row.revolution,
row.durationSec 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 csv = lines.map(line => line.map(csvEscape).join(';')).join('\n');
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
@@ -56,6 +56,10 @@
<input class="form-check-input" type="radio" name="rva-mode" id="rva-mode-merge-on-rev" value="merge-on-rev"> <input class="form-check-input" type="radio" name="rva-mode" id="rva-mode-merge-on-rev" value="merge-on-rev">
<label class="form-check-label" for="rva-mode-merge-on-rev">Суммарная длительность на витке</label> <label class="form-check-label" for="rva-mode-merge-on-rev">Суммарная длительность на витке</label>
</div> </div>
<div class="form-check">
<input class="form-check-input" type="radio" name="rva-mode" id="rva-mode-average" value="average">
<label class="form-check-label" for="rva-mode-average">Средняя длительность</label>
</div>
</div> </div>
</div> </div>