Задание НУ из ui
This commit is contained in:
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package space.nstart.pcp.pcp_types_lib.dto.ballistics
|
||||||
|
|
||||||
|
enum class MovementModel {
|
||||||
|
FOTO,
|
||||||
|
KONDOR,
|
||||||
|
METEORM1,
|
||||||
|
METEORM2,
|
||||||
|
BARS,
|
||||||
|
KONDOR_PROGNOZ
|
||||||
|
}
|
||||||
+4
-2
@@ -2,6 +2,8 @@ package space.nstart.pcp.pcp_types_lib.dto.ballistics
|
|||||||
|
|
||||||
class SatelliteICDTO(
|
class SatelliteICDTO(
|
||||||
val satelliteId: Long = -1,
|
val satelliteId: Long = -1,
|
||||||
val ic : InitialConditionsDTO = InitialConditionsDTO()
|
val ic : InitialConditionsDTO = InitialConditionsDTO(),
|
||||||
|
movementModel: MovementModel? = MovementModel.FOTO
|
||||||
) {
|
) {
|
||||||
}
|
val movementModel: MovementModel = movementModel ?: MovementModel.FOTO
|
||||||
|
}
|
||||||
|
|||||||
+12
@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.Operation
|
|||||||
import io.swagger.v3.oas.annotations.Parameter
|
import io.swagger.v3.oas.annotations.Parameter
|
||||||
import jakarta.validation.Valid
|
import jakarta.validation.Valid
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
|
import org.springframework.http.ResponseEntity
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
import org.springframework.web.bind.annotation.PathVariable
|
import org.springframework.web.bind.annotation.PathVariable
|
||||||
import org.springframework.web.bind.annotation.PostMapping
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
@@ -11,9 +12,11 @@ import org.springframework.web.bind.annotation.RequestBody
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
import org.springframework.web.bind.annotation.RequestParam
|
import org.springframework.web.bind.annotation.RequestParam
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
import space.nstart.pcp.pcp_request_service.service.SatelliteIcEventService
|
||||||
import space.nstart.pcp.pcp_request_service.service.SatelliteService
|
import space.nstart.pcp.pcp_request_service.service.SatelliteService
|
||||||
import space.nstart.pcp.pcp_types_lib.configuration.CustomValidationException
|
import space.nstart.pcp.pcp_types_lib.configuration.CustomValidationException
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.ExactTimePositionRequestDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.ExactTimePositionRequestDTO
|
||||||
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteICDTO
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
|
||||||
@@ -23,6 +26,9 @@ class SatelliteController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private lateinit var satelliteService: SatelliteService
|
private lateinit var satelliteService: SatelliteService
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private lateinit var satelliteIcEventService: SatelliteIcEventService
|
||||||
|
|
||||||
@PostMapping("/{satellite_id}/extract-time")
|
@PostMapping("/{satellite_id}/extract-time")
|
||||||
fun extractTime(
|
fun extractTime(
|
||||||
@PathVariable("satellite_id") satelliteId : Long,
|
@PathVariable("satellite_id") satelliteId : Long,
|
||||||
@@ -30,6 +36,12 @@ class SatelliteController {
|
|||||||
) =
|
) =
|
||||||
satelliteService.exactTime(satelliteId, body)
|
satelliteService.exactTime(satelliteId, body)
|
||||||
|
|
||||||
|
@PostMapping("/receive-rv")
|
||||||
|
fun receiveRv(@RequestBody body: SatelliteICDTO): ResponseEntity<Void> {
|
||||||
|
satelliteIcEventService.handlePlacedIcRv(body)
|
||||||
|
return ResponseEntity.accepted().build()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Operation(
|
@Operation(
|
||||||
|
|||||||
+7
@@ -6,6 +6,7 @@ import org.springframework.kafka.annotation.KafkaListener
|
|||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
import space.nstart.pcp.pcp_request_service.service.SatelliteIcEventService
|
import space.nstart.pcp.pcp_request_service.service.SatelliteIcEventService
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.InitialConditionsDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.InitialConditionsDTO
|
||||||
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.MovementModel
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteICDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteICDTO
|
||||||
import tools.jackson.databind.ObjectMapper
|
import tools.jackson.databind.ObjectMapper
|
||||||
import tools.jackson.databind.node.ObjectNode
|
import tools.jackson.databind.node.ObjectNode
|
||||||
@@ -52,6 +53,11 @@ class SatelliteIcRvKafkaListener(
|
|||||||
*/
|
*/
|
||||||
private fun normalizePayload(payloadNode: tools.jackson.databind.JsonNode): tools.jackson.databind.JsonNode {
|
private fun normalizePayload(payloadNode: tools.jackson.databind.JsonNode): tools.jackson.databind.JsonNode {
|
||||||
val normalizedPayload = payloadNode.deepCopy()
|
val normalizedPayload = payloadNode.deepCopy()
|
||||||
|
if (normalizedPayload is ObjectNode &&
|
||||||
|
(normalizedPayload["movementModel"] == null || normalizedPayload["movementModel"].isNull)
|
||||||
|
) {
|
||||||
|
normalizedPayload.put("movementModel", DEFAULT_MOVEMENT_MODEL.name)
|
||||||
|
}
|
||||||
val initialConditionsNode = normalizedPayload["ic"]
|
val initialConditionsNode = normalizedPayload["ic"]
|
||||||
if (initialConditionsNode is ObjectNode) {
|
if (initialConditionsNode is ObjectNode) {
|
||||||
if (initialConditionsNode["sBall"] == null || initialConditionsNode["sBall"].isNull) {
|
if (initialConditionsNode["sBall"] == null || initialConditionsNode["sBall"].isNull) {
|
||||||
@@ -66,5 +72,6 @@ class SatelliteIcRvKafkaListener(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val DEFAULT_INITIAL_CONDITIONS = InitialConditionsDTO()
|
private val DEFAULT_INITIAL_CONDITIONS = InitialConditionsDTO()
|
||||||
|
private val DEFAULT_MOVEMENT_MODEL = MovementModel.FOTO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-1
@@ -7,6 +7,7 @@ import ballistics.types.EarthType
|
|||||||
import ballistics.types.FleghtLineSector
|
import ballistics.types.FleghtLineSector
|
||||||
import ballistics.types.InitialConditions
|
import ballistics.types.InitialConditions
|
||||||
import ballistics.types.KeplerParams
|
import ballistics.types.KeplerParams
|
||||||
|
import ballistics.types.ModDVType
|
||||||
import ballistics.types.OPKatObj
|
import ballistics.types.OPKatObj
|
||||||
import ballistics.types.OrbitalPoint
|
import ballistics.types.OrbitalPoint
|
||||||
import ballistics.types.PPI
|
import ballistics.types.PPI
|
||||||
@@ -46,6 +47,7 @@ import space.nstart.pcp.pcp_request_service.utils.ContourClipService
|
|||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.AscNodeDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.AscNodeDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.ExactTimePositionRequestDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.ExactTimePositionRequestDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.InitialConditionsDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.InitialConditionsDTO
|
||||||
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.MovementModel
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.ObjDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.ObjDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.OrbPointDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.OrbPointDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.PointViewParamDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.PointViewParamDTO
|
||||||
@@ -184,8 +186,9 @@ class SatelliteService {
|
|||||||
|
|
||||||
suspend fun resieveRV(rv: SatelliteICDTO) {
|
suspend fun resieveRV(rv: SatelliteICDTO) {
|
||||||
val bal = Ballistics()
|
val bal = Ballistics()
|
||||||
|
bal.modDVType = rv.movementModel.toModDVType()
|
||||||
|
|
||||||
logger.info("Начало расчета баллистики по RV id = ${rv.satelliteId}")
|
logger.info("Начало расчета баллистики по RV id = ${rv.satelliteId}, model = ${rv.movementModel}")
|
||||||
|
|
||||||
bal.rollMax = (45.0 * PI / 180.0)
|
bal.rollMax = (45.0 * PI / 180.0)
|
||||||
bal.rollMin = (20.0 * PI / 180.0)
|
bal.rollMin = (20.0 * PI / 180.0)
|
||||||
@@ -231,6 +234,16 @@ class SatelliteService {
|
|||||||
logger.info("Расчет для КА ${rv.satelliteId} завершился успешно")
|
logger.info("Расчет для КА ${rv.satelliteId} завершился успешно")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun MovementModel.toModDVType(): ModDVType =
|
||||||
|
when (this) {
|
||||||
|
MovementModel.FOTO -> ModDVType.FOTO
|
||||||
|
MovementModel.KONDOR -> ModDVType.KONDOR
|
||||||
|
MovementModel.METEORM1 -> ModDVType.METEORM1
|
||||||
|
MovementModel.METEORM2 -> ModDVType.METEORM2
|
||||||
|
MovementModel.BARS -> ModDVType.BARS
|
||||||
|
MovementModel.KONDOR_PROGNOZ -> ModDVType.KONDOR_PROGNOZ
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun mergeSectors(sectors: List<FleghtLineSector>): List<FleghtLineSector> {
|
fun mergeSectors(sectors: List<FleghtLineSector>): List<FleghtLineSector> {
|
||||||
if (sectors.isEmpty()) return emptyList()
|
if (sectors.isEmpty()) return emptyList()
|
||||||
|
|||||||
+5
-1
@@ -4,6 +4,7 @@ import org.junit.jupiter.api.Assertions.assertEquals
|
|||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.springframework.beans.factory.ObjectProvider
|
import org.springframework.beans.factory.ObjectProvider
|
||||||
import space.nstart.pcp.pcp_request_service.service.SatelliteIcEventService
|
import space.nstart.pcp.pcp_request_service.service.SatelliteIcEventService
|
||||||
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.MovementModel
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteICDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteICDTO
|
||||||
import tools.jackson.databind.ObjectMapper
|
import tools.jackson.databind.ObjectMapper
|
||||||
|
|
||||||
@@ -46,6 +47,7 @@ class SatelliteIcRvKafkaListenerTest {
|
|||||||
assertEquals(56756L, satelliteIcEventService.lastMessage?.satelliteId)
|
assertEquals(56756L, satelliteIcEventService.lastMessage?.satelliteId)
|
||||||
assertEquals(42L, satelliteIcEventService.lastMessage?.ic?.orbPoint?.revolution)
|
assertEquals(42L, satelliteIcEventService.lastMessage?.ic?.orbPoint?.revolution)
|
||||||
assertEquals(140.0, satelliteIcEventService.lastMessage?.ic?.f81)
|
assertEquals(140.0, satelliteIcEventService.lastMessage?.ic?.f81)
|
||||||
|
assertEquals(MovementModel.FOTO, satelliteIcEventService.lastMessage?.movementModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -54,8 +56,9 @@ class SatelliteIcRvKafkaListenerTest {
|
|||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
"type": "ICRVPlacedEvent",
|
"type": "ICRVPlacedEvent",
|
||||||
"data": {
|
"data": {
|
||||||
"satelliteId": 56756,
|
"satelliteId": 56756,
|
||||||
|
"movementModel": null,
|
||||||
"ic": {
|
"ic": {
|
||||||
"orbPoint": {
|
"orbPoint": {
|
||||||
"time": "2026-04-16T12:00:00",
|
"time": "2026-04-16T12:00:00",
|
||||||
@@ -77,6 +80,7 @@ class SatelliteIcRvKafkaListenerTest {
|
|||||||
|
|
||||||
assertEquals(0.0, satelliteIcEventService.lastMessage?.ic?.sBall)
|
assertEquals(0.0, satelliteIcEventService.lastMessage?.ic?.sBall)
|
||||||
assertEquals(147.8, satelliteIcEventService.lastMessage?.ic?.f81)
|
assertEquals(147.8, satelliteIcEventService.lastMessage?.ic?.f81)
|
||||||
|
assertEquals(MovementModel.FOTO, satelliteIcEventService.lastMessage?.movementModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RecordingSatelliteIcEventService : SatelliteIcEventService() {
|
private class RecordingSatelliteIcEventService : SatelliteIcEventService() {
|
||||||
|
|||||||
+19
-1
@@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestParam
|
|||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
import org.springframework.web.server.ResponseStatusException
|
import org.springframework.web.server.ResponseStatusException
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.InitialConditionsDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.InitialConditionsDTO
|
||||||
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteICDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.requests.slots.SlotCalculationSummaryDTO
|
import space.nstart.pcp.pcp_types_lib.dto.requests.slots.SlotCalculationSummaryDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteCreateDTO
|
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteCreateDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteGroupCreateDTO
|
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteGroupCreateDTO
|
||||||
@@ -22,6 +23,7 @@ import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteObservationProfileD
|
|||||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteSlotProfileDTO
|
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteSlotProfileDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteUpdateDTO
|
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteUpdateDTO
|
||||||
import space.nstart.pcp.slots_service.service.GroupStateService
|
import space.nstart.pcp.slots_service.service.GroupStateService
|
||||||
|
import space.nstart.pcp.slots_service.service.BallisticsService
|
||||||
import space.nstart.pcp.slots_service.service.SatelliteCatalogService
|
import space.nstart.pcp.slots_service.service.SatelliteCatalogService
|
||||||
import space.nstart.pcp.slots_service.service.SatellitePdcmService
|
import space.nstart.pcp.slots_service.service.SatellitePdcmService
|
||||||
import space.nstart.pcp.slots_service.service.SlotService
|
import space.nstart.pcp.slots_service.service.SlotService
|
||||||
@@ -36,7 +38,8 @@ class CatalogRestController(
|
|||||||
private val satelliteCatalogService: SatelliteCatalogService,
|
private val satelliteCatalogService: SatelliteCatalogService,
|
||||||
private val slotService: SlotService,
|
private val slotService: SlotService,
|
||||||
private val groupStateService: GroupStateService,
|
private val groupStateService: GroupStateService,
|
||||||
private val satellitePdcmService: SatellitePdcmService
|
private val satellitePdcmService: SatellitePdcmService,
|
||||||
|
private val ballisticsService: BallisticsService
|
||||||
) {
|
) {
|
||||||
private val sendInitialConditionsTimeFormatter =
|
private val sendInitialConditionsTimeFormatter =
|
||||||
DateTimeFormatter.ofPattern("dd.MM.uuuu HH:mm:ss.SSS").withResolverStyle(ResolverStyle.STRICT)
|
DateTimeFormatter.ofPattern("dd.MM.uuuu HH:mm:ss.SSS").withResolverStyle(ResolverStyle.STRICT)
|
||||||
@@ -73,6 +76,21 @@ class CatalogRestController(
|
|||||||
return ResponseEntity.accepted().build()
|
return ResponseEntity.accepted().build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/satellites/pdcm/{satelliteId}/initial-conditions")
|
||||||
|
fun setSatelliteInitialConditions(
|
||||||
|
@PathVariable satelliteId: Long,
|
||||||
|
@RequestBody request: SatelliteICDTO
|
||||||
|
): ResponseEntity<Void> {
|
||||||
|
ballisticsService.receiveRv(
|
||||||
|
SatelliteICDTO(
|
||||||
|
satelliteId = satelliteId,
|
||||||
|
ic = request.ic,
|
||||||
|
movementModel = request.movementModel
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return ResponseEntity.accepted().build()
|
||||||
|
}
|
||||||
|
|
||||||
private fun parseSendInitialConditionsTime(time: String?): LocalDateTime {
|
private fun parseSendInitialConditionsTime(time: String?): LocalDateTime {
|
||||||
val normalizedTime = time?.trim()?.takeIf { it.isNotEmpty() }
|
val normalizedTime = time?.trim()?.takeIf { it.isNotEmpty() }
|
||||||
?: return LocalDateTime.now()
|
?: return LocalDateTime.now()
|
||||||
|
|||||||
+11
@@ -9,6 +9,7 @@ import space.nstart.pcp.pcp_types_lib.dto.ballistics.ExactTimePositionRequestDTO
|
|||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.AscNodeDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.AscNodeDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.FlightLineDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.FlightLineDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.OrbPointDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.OrbPointDTO
|
||||||
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteICDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteOrbitAvailabilityDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteOrbitAvailabilityDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TLEDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TLEDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TlePointRequestDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TlePointRequestDTO
|
||||||
@@ -71,6 +72,16 @@ class BallisticsService (webClientBuilderProvider: ObjectProvider<WebClient.Buil
|
|||||||
?.firstOrNull()
|
?.firstOrNull()
|
||||||
?: throw CustomErrorException("Не удалось получить положение спутника $id на время $time")
|
?: throw CustomErrorException("Не удалось получить положение спутника $id на время $time")
|
||||||
|
|
||||||
|
fun receiveRv(request: SatelliteICDTO) {
|
||||||
|
webClientBuilder.build()
|
||||||
|
.post()
|
||||||
|
.uri("$url/api/satellites/receive-rv")
|
||||||
|
.bodyValue(request)
|
||||||
|
.retrieve()
|
||||||
|
.toBodilessEntity()
|
||||||
|
.block()
|
||||||
|
}
|
||||||
|
|
||||||
fun parseTle(tle: TLEDTO): TleParsedDTO =
|
fun parseTle(tle: TLEDTO): TleParsedDTO =
|
||||||
webClientBuilder.build()
|
webClientBuilder.build()
|
||||||
.post()
|
.post()
|
||||||
|
|||||||
@@ -15,6 +15,12 @@
|
|||||||
width: 15rem;
|
width: 15rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.satellite-pdcm-ic-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.satellite-pdcm-status {
|
.satellite-pdcm-status {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
width: 0.75rem;
|
width: 0.75rem;
|
||||||
|
|||||||
@@ -110,6 +110,55 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseDateTimeForPayload(value, fieldName) {
|
||||||
|
const text = value?.trim() || '';
|
||||||
|
const match = text.match(sendInitialConditionsDateTimePattern);
|
||||||
|
if (!match) {
|
||||||
|
throw new Error(`${fieldName}: укажите время в формате dd.mm.yyyy hh:MM:ss.zzz`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [, day, month, year, hour, minute, second, millisecond] = match;
|
||||||
|
const parsed = new Date(
|
||||||
|
Number(year),
|
||||||
|
Number(month) - 1,
|
||||||
|
Number(day),
|
||||||
|
Number(hour),
|
||||||
|
Number(minute),
|
||||||
|
Number(second),
|
||||||
|
Number(millisecond)
|
||||||
|
);
|
||||||
|
const validDate = parsed.getFullYear() === Number(year)
|
||||||
|
&& parsed.getMonth() === Number(month) - 1
|
||||||
|
&& parsed.getDate() === Number(day)
|
||||||
|
&& parsed.getHours() === Number(hour)
|
||||||
|
&& parsed.getMinutes() === Number(minute)
|
||||||
|
&& parsed.getSeconds() === Number(second)
|
||||||
|
&& parsed.getMilliseconds() === Number(millisecond);
|
||||||
|
|
||||||
|
if (!validDate) {
|
||||||
|
throw new Error(`${fieldName}: некорректная дата или время`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${year}-${month}-${day}T${hour}:${minute}:${second}.${millisecond}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseRequiredNumber(inputId, fieldName) {
|
||||||
|
const value = document.getElementById(inputId)?.value;
|
||||||
|
const number = Number(value);
|
||||||
|
if (value === '' || !Number.isFinite(number)) {
|
||||||
|
throw new Error(`${fieldName}: укажите число`);
|
||||||
|
}
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseRequiredInteger(inputId, fieldName) {
|
||||||
|
const number = parseRequiredNumber(inputId, fieldName);
|
||||||
|
if (!Number.isInteger(number)) {
|
||||||
|
throw new Error(`${fieldName}: укажите целое число`);
|
||||||
|
}
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
function formatNumber(value) {
|
function formatNumber(value) {
|
||||||
return Number(value ?? 0).toFixed(3);
|
return Number(value ?? 0).toFixed(3);
|
||||||
}
|
}
|
||||||
@@ -142,6 +191,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderSetInitialConditionsState(details, loading = false) {
|
||||||
|
const openButton = document.getElementById('satellite-pdcm-open-set-ic');
|
||||||
|
const submitButton = document.getElementById('satellite-pdcm-set-ic-submit');
|
||||||
|
if (openButton) {
|
||||||
|
openButton.disabled = !details || loading;
|
||||||
|
openButton.title = details ? '' : 'Выберите спутник';
|
||||||
|
}
|
||||||
|
if (submitButton) {
|
||||||
|
submitButton.disabled = loading;
|
||||||
|
submitButton.textContent = loading ? 'Запуск...' : 'Запустить расчет';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function renderList() {
|
function renderList() {
|
||||||
const tableBody = document.getElementById('satellite-pdcm-list');
|
const tableBody = document.getElementById('satellite-pdcm-list');
|
||||||
tableBody.innerHTML = '';
|
tableBody.innerHTML = '';
|
||||||
@@ -182,6 +244,7 @@
|
|||||||
summary.innerHTML = '<div class="catalog-helper">Выберите спутник слева.</div>';
|
summary.innerHTML = '<div class="catalog-helper">Выберите спутник слева.</div>';
|
||||||
renderExportState(null);
|
renderExportState(null);
|
||||||
renderSendInitialConditionsState(null);
|
renderSendInitialConditionsState(null);
|
||||||
|
renderSetInitialConditionsState(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,6 +276,7 @@
|
|||||||
`;
|
`;
|
||||||
renderExportState(details);
|
renderExportState(details);
|
||||||
renderSendInitialConditionsState(details);
|
renderSendInitialConditionsState(details);
|
||||||
|
renderSetInitialConditionsState(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderTable(details) {
|
function renderTable(details) {
|
||||||
@@ -365,10 +429,89 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openSetInitialConditionsModal() {
|
||||||
|
if (!state.selectedSatelliteId || !state.details) {
|
||||||
|
showAlert('Выберите спутник для задания начальных условий');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('satellite-pdcm-set-ic-target').textContent =
|
||||||
|
`${state.details.name} · ID ${state.details.satelliteId}`;
|
||||||
|
document.getElementById('satellite-pdcm-ic-time').value = currentDateTimeInputValue();
|
||||||
|
document.getElementById('satellite-pdcm-ic-revolution').value = '';
|
||||||
|
document.getElementById('satellite-pdcm-ic-movement-model').value = 'FOTO';
|
||||||
|
document.getElementById('satellite-pdcm-ic-s-ball').value = '0';
|
||||||
|
document.getElementById('satellite-pdcm-ic-f81').value = '147.8';
|
||||||
|
['x', 'y', 'z', 'vx', 'vy', 'vz'].forEach(field => {
|
||||||
|
document.getElementById(`satellite-pdcm-ic-${field}`).value = '';
|
||||||
|
});
|
||||||
|
|
||||||
|
if (window.bootstrap) {
|
||||||
|
window.bootstrap.Modal.getOrCreateInstance(document.getElementById('satellite-pdcm-set-ic-modal')).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildInitialConditionsPayload() {
|
||||||
|
const movementModel = document.getElementById('satellite-pdcm-ic-movement-model').value || 'FOTO';
|
||||||
|
return {
|
||||||
|
satelliteId: state.selectedSatelliteId,
|
||||||
|
movementModel,
|
||||||
|
ic: {
|
||||||
|
orbPoint: {
|
||||||
|
time: parseDateTimeForPayload(document.getElementById('satellite-pdcm-ic-time').value, 'Time'),
|
||||||
|
revolution: parseRequiredInteger('satellite-pdcm-ic-revolution', 'Revolution'),
|
||||||
|
vx: parseRequiredNumber('satellite-pdcm-ic-vx', 'Vx'),
|
||||||
|
vy: parseRequiredNumber('satellite-pdcm-ic-vy', 'Vy'),
|
||||||
|
vz: parseRequiredNumber('satellite-pdcm-ic-vz', 'Vz'),
|
||||||
|
x: parseRequiredNumber('satellite-pdcm-ic-x', 'X'),
|
||||||
|
y: parseRequiredNumber('satellite-pdcm-ic-y', 'Y'),
|
||||||
|
z: parseRequiredNumber('satellite-pdcm-ic-z', 'Z')
|
||||||
|
},
|
||||||
|
sBall: parseRequiredNumber('satellite-pdcm-ic-s-ball', 'S-ball'),
|
||||||
|
f81: parseRequiredNumber('satellite-pdcm-ic-f81', 'F81')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitInitialConditions(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!state.selectedSatelliteId || !state.details) {
|
||||||
|
showAlert('Выберите спутник для задания начальных условий');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let payload;
|
||||||
|
try {
|
||||||
|
payload = buildInitialConditionsPayload();
|
||||||
|
} catch (error) {
|
||||||
|
showAlert(error.message || 'Проверьте параметры начальных условий');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSetInitialConditionsState(state.details, true);
|
||||||
|
showAlert('');
|
||||||
|
try {
|
||||||
|
await requestJson(`${apiBase}/${state.selectedSatelliteId}/initial-conditions`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
});
|
||||||
|
const modalElement = document.getElementById('satellite-pdcm-set-ic-modal');
|
||||||
|
if (window.bootstrap && modalElement) {
|
||||||
|
window.bootstrap.Modal.getOrCreateInstance(modalElement).hide();
|
||||||
|
}
|
||||||
|
showAlert('Расчет ПДЦМ по начальным условиям запущен', 'success');
|
||||||
|
} catch (error) {
|
||||||
|
showAlert(error.message || 'Не удалось запустить расчет ПДЦМ по начальным условиям');
|
||||||
|
} finally {
|
||||||
|
renderSetInitialConditionsState(state.details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function selectSatellite(satelliteId) {
|
async function selectSatellite(satelliteId) {
|
||||||
state.selectedSatelliteId = satelliteId;
|
state.selectedSatelliteId = satelliteId;
|
||||||
renderList();
|
renderList();
|
||||||
renderSendInitialConditionsState(null);
|
renderSendInitialConditionsState(null);
|
||||||
|
renderSetInitialConditionsState(null);
|
||||||
showAlert('');
|
showAlert('');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -414,6 +557,8 @@
|
|||||||
});
|
});
|
||||||
document.getElementById('satellite-pdcm-export').addEventListener('click', exportCurrentCsv);
|
document.getElementById('satellite-pdcm-export').addEventListener('click', exportCurrentCsv);
|
||||||
document.getElementById('satellite-pdcm-send-ic').addEventListener('click', sendInitialConditions);
|
document.getElementById('satellite-pdcm-send-ic').addEventListener('click', sendInitialConditions);
|
||||||
|
document.getElementById('satellite-pdcm-open-set-ic').addEventListener('click', openSetInitialConditionsModal);
|
||||||
|
document.getElementById('satellite-pdcm-set-ic-form').addEventListener('submit', submitInitialConditions);
|
||||||
const sendInitialConditionsTimeInput = document.getElementById('satellite-pdcm-send-ic-time');
|
const sendInitialConditionsTimeInput = document.getElementById('satellite-pdcm-send-ic-time');
|
||||||
sendInitialConditionsTimeInput.value = currentDateTimeInputValue();
|
sendInitialConditionsTimeInput.value = currentDateTimeInputValue();
|
||||||
sendInitialConditionsTimeInput.addEventListener('input', () => renderSendInitialConditionsState(state.details));
|
sendInitialConditionsTimeInput.addEventListener('input', () => renderSendInitialConditionsState(state.details));
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button id="satellite-pdcm-send-ic" type="button" class="btn btn-outline-primary" disabled>Передать НУ в slot-service</button>
|
<button id="satellite-pdcm-send-ic" type="button" class="btn btn-outline-primary" disabled>Передать НУ в slot-service</button>
|
||||||
|
<button id="satellite-pdcm-open-set-ic" type="button" class="btn btn-primary" disabled>Задать НУ</button>
|
||||||
<button id="satellite-pdcm-refresh" type="button" class="btn btn-outline-secondary">Обновить</button>
|
<button id="satellite-pdcm-refresh" type="button" class="btn btn-outline-secondary">Обновить</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -80,6 +81,84 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="satellite-pdcm-set-ic-modal" tabindex="-1" aria-labelledby="satellite-pdcm-set-ic-title" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||||
|
<form id="satellite-pdcm-set-ic-form" class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="satellite-pdcm-set-ic-title">Задать начальные условия</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div id="satellite-pdcm-set-ic-target" class="catalog-helper mb-3">Выберите спутник слева.</div>
|
||||||
|
|
||||||
|
<div class="satellite-pdcm-ic-grid">
|
||||||
|
<div>
|
||||||
|
<label for="satellite-pdcm-ic-time" class="form-label">Time</label>
|
||||||
|
<input id="satellite-pdcm-ic-time" type="text" class="form-control" placeholder="dd.mm.yyyy hh:mm:ss.zzz" required/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="satellite-pdcm-ic-revolution" class="form-label">Revolution</label>
|
||||||
|
<input id="satellite-pdcm-ic-revolution" type="number" class="form-control" required/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="satellite-pdcm-ic-movement-model" class="form-label">Модель движения</label>
|
||||||
|
<select id="satellite-pdcm-ic-movement-model" class="form-select" required>
|
||||||
|
<option value="FOTO" selected>FOTO</option>
|
||||||
|
<option value="KONDOR">KONDOR</option>
|
||||||
|
<option value="METEORM1">METEORM1</option>
|
||||||
|
<option value="METEORM2">METEORM2</option>
|
||||||
|
<option value="BARS">BARS</option>
|
||||||
|
<option value="KONDOR_PROGNOZ">KONDOR_PROGNOZ</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="satellite-pdcm-ic-s-ball" class="form-label">S-ball</label>
|
||||||
|
<input id="satellite-pdcm-ic-s-ball" type="number" step="any" class="form-control" value="0" required/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="satellite-pdcm-ic-f81" class="form-label">F81</label>
|
||||||
|
<input id="satellite-pdcm-ic-f81" type="number" step="any" class="form-control" value="147.8" required/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="satellite-pdcm-ic-grid mt-3">
|
||||||
|
<div>
|
||||||
|
<label for="satellite-pdcm-ic-x" class="form-label">X</label>
|
||||||
|
<input id="satellite-pdcm-ic-x" type="number" step="any" class="form-control" required/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="satellite-pdcm-ic-y" class="form-label">Y</label>
|
||||||
|
<input id="satellite-pdcm-ic-y" type="number" step="any" class="form-control" required/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="satellite-pdcm-ic-z" class="form-label">Z</label>
|
||||||
|
<input id="satellite-pdcm-ic-z" type="number" step="any" class="form-control" required/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="satellite-pdcm-ic-grid mt-3">
|
||||||
|
<div>
|
||||||
|
<label for="satellite-pdcm-ic-vx" class="form-label">Vx</label>
|
||||||
|
<input id="satellite-pdcm-ic-vx" type="number" step="any" class="form-control" required/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="satellite-pdcm-ic-vy" class="form-label">Vy</label>
|
||||||
|
<input id="satellite-pdcm-ic-vy" type="number" step="any" class="form-control" required/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="satellite-pdcm-ic-vz" class="form-label">Vz</label>
|
||||||
|
<input id="satellite-pdcm-ic-vz" type="number" step="any" class="form-control" required/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Отмена</button>
|
||||||
|
<button id="satellite-pdcm-set-ic-submit" type="submit" class="btn btn-primary">Запустить расчет</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/satellite_pdcm_scripts.js"></script>
|
<script src="/satellite_pdcm_scripts.js"></script>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
|||||||
+48
@@ -1,6 +1,7 @@
|
|||||||
package space.nstart.pcp.slots_service.controller
|
package space.nstart.pcp.slots_service.controller
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.mockito.ArgumentCaptor
|
||||||
import org.mockito.ArgumentMatchers.any
|
import org.mockito.ArgumentMatchers.any
|
||||||
import org.mockito.ArgumentMatchers.eq
|
import org.mockito.ArgumentMatchers.eq
|
||||||
import org.mockito.Mockito.doReturn
|
import org.mockito.Mockito.doReturn
|
||||||
@@ -15,6 +16,7 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean
|
|||||||
import org.springframework.web.reactive.function.client.WebClient
|
import org.springframework.web.reactive.function.client.WebClient
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.InitialConditionsDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.InitialConditionsDTO
|
||||||
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.MovementModel
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.OrbPointDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.OrbPointDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteICDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteICDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.PositionDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.PositionDTO
|
||||||
@@ -34,6 +36,7 @@ import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteGroupCreateDTO
|
|||||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteGroupDTO
|
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteGroupDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteSlotProfileDTO
|
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteSlotProfileDTO
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteVisualizationDTO
|
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteVisualizationDTO
|
||||||
|
import space.nstart.pcp.slots_service.service.BallisticsService
|
||||||
import space.nstart.pcp.slots_service.service.GroupStateService
|
import space.nstart.pcp.slots_service.service.GroupStateService
|
||||||
import space.nstart.pcp.slots_service.service.SatelliteCatalogService
|
import space.nstart.pcp.slots_service.service.SatelliteCatalogService
|
||||||
import space.nstart.pcp.slots_service.service.SatellitePdcmService
|
import space.nstart.pcp.slots_service.service.SatellitePdcmService
|
||||||
@@ -73,6 +76,9 @@ class CatalogControllerTest {
|
|||||||
@MockitoBean
|
@MockitoBean
|
||||||
private lateinit var satellitePdcmService: SatellitePdcmService
|
private lateinit var satellitePdcmService: SatellitePdcmService
|
||||||
|
|
||||||
|
@MockitoBean
|
||||||
|
private lateinit var ballisticsService: BallisticsService
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `groups page is rendered`() {
|
fun `groups page is rendered`() {
|
||||||
val body = WebClient.create("http://localhost:$port")
|
val body = WebClient.create("http://localhost:$port")
|
||||||
@@ -136,6 +142,9 @@ class CatalogControllerTest {
|
|||||||
assertTrue(body.contains("Спутники"))
|
assertTrue(body.contains("Спутники"))
|
||||||
assertTrue(body.contains("Скачать CSV"))
|
assertTrue(body.contains("Скачать CSV"))
|
||||||
assertTrue(body.contains("satellite-pdcm-send-ic-time"))
|
assertTrue(body.contains("satellite-pdcm-send-ic-time"))
|
||||||
|
assertTrue(body.contains("Задать НУ"))
|
||||||
|
assertTrue(body.contains("satellite-pdcm-set-ic-modal"))
|
||||||
|
assertTrue(body.contains("value=\"FOTO\" selected"))
|
||||||
assertTrue(body.contains("dd.mm.yyyy hh:MM:ss.zzz"))
|
assertTrue(body.contains("dd.mm.yyyy hh:MM:ss.zzz"))
|
||||||
assertTrue(body.contains("/webjars/bootstrap/5.3.0/css/bootstrap.min.css"))
|
assertTrue(body.contains("/webjars/bootstrap/5.3.0/css/bootstrap.min.css"))
|
||||||
}
|
}
|
||||||
@@ -343,6 +352,43 @@ class CatalogControllerTest {
|
|||||||
verify(slotService, never()).sendSatelliteInitialConditions(eq(501L), anyLocalDateTime())
|
verify(slotService, never()).sendSatelliteInitialConditions(eq(501L), anyLocalDateTime())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `satellite pdcm set initial conditions endpoint proxies request to ballistics`() {
|
||||||
|
val request = SatelliteICDTO(
|
||||||
|
satelliteId = 999L,
|
||||||
|
movementModel = MovementModel.KONDOR,
|
||||||
|
ic = InitialConditionsDTO(
|
||||||
|
orbPoint = OrbPointDTO(
|
||||||
|
time = LocalDateTime.of(2026, 4, 24, 10, 15, 30, 123_000_000),
|
||||||
|
revolution = 42L,
|
||||||
|
vx = 1.0,
|
||||||
|
vy = 2.0,
|
||||||
|
vz = 3.0,
|
||||||
|
x = 4.0,
|
||||||
|
y = 5.0,
|
||||||
|
z = 6.0
|
||||||
|
),
|
||||||
|
sBall = 0.07,
|
||||||
|
f81 = 145.2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val status = WebClient.create("http://localhost:$port")
|
||||||
|
.post()
|
||||||
|
.uri("/api/catalog/satellites/pdcm/501/initial-conditions")
|
||||||
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
|
.bodyValue(request)
|
||||||
|
.exchangeToMono { response -> Mono.just(response.statusCode()) }
|
||||||
|
.block()!!
|
||||||
|
|
||||||
|
val requestCaptor = ArgumentCaptor.forClass(SatelliteICDTO::class.java)
|
||||||
|
assertEquals(HttpStatus.ACCEPTED, status)
|
||||||
|
verify(ballisticsService).receiveRv(captureSatelliteIc(requestCaptor))
|
||||||
|
assertEquals(501L, requestCaptor.value.satelliteId)
|
||||||
|
assertEquals(MovementModel.KONDOR, requestCaptor.value.movementModel)
|
||||||
|
assertEquals(42L, requestCaptor.value.ic.orbPoint.revolution)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `satellite create endpoint proxies request`() {
|
fun `satellite create endpoint proxies request`() {
|
||||||
val request = SatelliteCreateDTO(
|
val request = SatelliteCreateDTO(
|
||||||
@@ -578,4 +624,6 @@ class CatalogControllerTest {
|
|||||||
private fun anyInitialConditions(): InitialConditionsDTO = any(InitialConditionsDTO::class.java) ?: InitialConditionsDTO()
|
private fun anyInitialConditions(): InitialConditionsDTO = any(InitialConditionsDTO::class.java) ?: InitialConditionsDTO()
|
||||||
private fun anySlotProfile(): SatelliteSlotProfileDTO = any(SatelliteSlotProfileDTO::class.java) ?: SatelliteSlotProfileDTO()
|
private fun anySlotProfile(): SatelliteSlotProfileDTO = any(SatelliteSlotProfileDTO::class.java) ?: SatelliteSlotProfileDTO()
|
||||||
private fun anyLocalDateTime(): LocalDateTime = any(LocalDateTime::class.java) ?: LocalDateTime.MIN
|
private fun anyLocalDateTime(): LocalDateTime = any(LocalDateTime::class.java) ?: LocalDateTime.MIN
|
||||||
|
private fun captureSatelliteIc(captor: ArgumentCaptor<SatelliteICDTO>): SatelliteICDTO =
|
||||||
|
captor.capture() ?: SatelliteICDTO()
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-3
@@ -7,7 +7,10 @@ import org.junit.jupiter.api.Test
|
|||||||
import org.springframework.beans.factory.ObjectProvider
|
import org.springframework.beans.factory.ObjectProvider
|
||||||
import org.springframework.test.util.ReflectionTestUtils
|
import org.springframework.test.util.ReflectionTestUtils
|
||||||
import org.springframework.web.reactive.function.client.WebClient
|
import org.springframework.web.reactive.function.client.WebClient
|
||||||
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.InitialConditionsDTO
|
||||||
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.MovementModel
|
||||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.OrbPointDTO
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.OrbPointDTO
|
||||||
|
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteICDTO
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
@@ -27,7 +30,8 @@ class BallisticsServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `sat data methods forward time interval to ballistics service`() {
|
fun `sat data methods forward time interval to ballistics service`() {
|
||||||
val requests = CopyOnWriteArrayList<URI>()
|
val requests = CopyOnWriteArrayList<URI>()
|
||||||
val serverUrl = startServer(requests)
|
val requestBodies = CopyOnWriteArrayList<String>()
|
||||||
|
val serverUrl = startServer(requests, requestBodies)
|
||||||
val service = createService(serverUrl)
|
val service = createService(serverUrl)
|
||||||
val timeStart = LocalDateTime.of(2026, 4, 21, 10, 0)
|
val timeStart = LocalDateTime.of(2026, 4, 21, 10, 0)
|
||||||
val timeStop = LocalDateTime.of(2026, 4, 21, 12, 0)
|
val timeStop = LocalDateTime.of(2026, 4, 21, 12, 0)
|
||||||
@@ -37,6 +41,24 @@ class BallisticsServiceTest {
|
|||||||
service.points(101L, timeStart, timeStop).collectList().block()
|
service.points(101L, timeStart, timeStop).collectList().block()
|
||||||
val availability = service.orbitAvailability()
|
val availability = service.orbitAvailability()
|
||||||
val exactPoint = service.exactTimePoint(101L, timeStart)
|
val exactPoint = service.exactTimePoint(101L, timeStart)
|
||||||
|
service.receiveRv(
|
||||||
|
SatelliteICDTO(
|
||||||
|
satelliteId = 101L,
|
||||||
|
movementModel = MovementModel.KONDOR,
|
||||||
|
ic = InitialConditionsDTO(
|
||||||
|
orbPoint = OrbPointDTO(
|
||||||
|
time = timeStart,
|
||||||
|
revolution = 7L,
|
||||||
|
vx = 1.0,
|
||||||
|
vy = 2.0,
|
||||||
|
vz = 3.0,
|
||||||
|
x = 4.0,
|
||||||
|
y = 5.0,
|
||||||
|
z = 6.0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
listOf(
|
listOf(
|
||||||
@@ -44,7 +66,8 @@ class BallisticsServiceTest {
|
|||||||
"/api/satellites/101/flight-line",
|
"/api/satellites/101/flight-line",
|
||||||
"/api/satellites/101/orbit",
|
"/api/satellites/101/orbit",
|
||||||
"/api/satellites/orbit/availability",
|
"/api/satellites/orbit/availability",
|
||||||
"/api/satellites/101/extract-time"
|
"/api/satellites/101/extract-time",
|
||||||
|
"/api/satellites/receive-rv"
|
||||||
),
|
),
|
||||||
requests.map { it.path }
|
requests.map { it.path }
|
||||||
)
|
)
|
||||||
@@ -54,6 +77,7 @@ class BallisticsServiceTest {
|
|||||||
"time_start=2026-04-21T10:00&time_stop=2026-04-21T12:00",
|
"time_start=2026-04-21T10:00&time_stop=2026-04-21T12:00",
|
||||||
"time_start=2026-04-21T10:00&time_stop=2026-04-21T12:00",
|
"time_start=2026-04-21T10:00&time_stop=2026-04-21T12:00",
|
||||||
null,
|
null,
|
||||||
|
null,
|
||||||
null
|
null
|
||||||
),
|
),
|
||||||
requests.map { it.query }
|
requests.map { it.query }
|
||||||
@@ -62,6 +86,7 @@ class BallisticsServiceTest {
|
|||||||
assertEquals(101L, availability.single().satelliteId)
|
assertEquals(101L, availability.single().satelliteId)
|
||||||
assertNotNull(exactPoint)
|
assertNotNull(exactPoint)
|
||||||
assertEquals(timeStart, exactPoint.time)
|
assertEquals(timeStart, exactPoint.time)
|
||||||
|
assertEquals(true, requestBodies.single().contains(""""movementModel":"KONDOR""""))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createService(serverUrl: String): BallisticsService {
|
private fun createService(serverUrl: String): BallisticsService {
|
||||||
@@ -77,7 +102,7 @@ class BallisticsServiceTest {
|
|||||||
return service
|
return service
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startServer(requests: MutableList<URI>): String {
|
private fun startServer(requests: MutableList<URI>, requestBodies: MutableList<String>): String {
|
||||||
val startedServer = HttpServer.create(InetSocketAddress(0), 0)
|
val startedServer = HttpServer.create(InetSocketAddress(0), 0)
|
||||||
listOf(
|
listOf(
|
||||||
"/api/satellites/101/asc-node",
|
"/api/satellites/101/asc-node",
|
||||||
@@ -103,6 +128,11 @@ class BallisticsServiceTest {
|
|||||||
"""[{"time":"2026-04-21T10:00:00","revolution":1,"vx":1.0,"vy":2.0,"vz":3.0,"x":4.0,"y":5.0,"z":6.0}]"""
|
"""[{"time":"2026-04-21T10:00:00","revolution":1,"vx":1.0,"vy":2.0,"vz":3.0,"x":4.0,"y":5.0,"z":6.0}]"""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
startedServer.createContext("/api/satellites/receive-rv") { exchange ->
|
||||||
|
requests.add(exchange.requestURI)
|
||||||
|
requestBodies.add(exchange.requestBody.bufferedReader().use { it.readText() })
|
||||||
|
respond(exchange, "")
|
||||||
|
}
|
||||||
startedServer.start()
|
startedServer.start()
|
||||||
server = startedServer
|
server = startedServer
|
||||||
return "http://localhost:${startedServer.address.port}"
|
return "http://localhost:${startedServer.address.port}"
|
||||||
|
|||||||
Reference in New Issue
Block a user