Учет забронированных слотов при расчете комплексного плана
This commit is contained in:
+62
@@ -0,0 +1,62 @@
|
||||
package space.nstart.pcp.slots_service.model.satellite
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import space.nstart.pcp.pcp_types_lib.dto.requests.slots.BookedSlotStatus
|
||||
import space.nstart.pcp.pcp_types_lib.dto.requests.slots.SlotStatus
|
||||
import space.nstart.pcp.slots_service.entity.BookedSlotEntity
|
||||
import space.nstart.pcp.slots_service.entity.SlotEntity
|
||||
import java.time.LocalDateTime
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class TestSatelliteImplBookedBlockingTest {
|
||||
|
||||
@Test
|
||||
fun `non-booked slot inside active booked interval is marked busy and exact booked slot stays booked`() {
|
||||
val baseTime = LocalDateTime.of(2026, 5, 21, 0, 0)
|
||||
val satellite = TestSatelliteImpl(
|
||||
id = 1L,
|
||||
tnCalc = baseTime,
|
||||
durationCalc = 1,
|
||||
maxChainLength = 3,
|
||||
maxSurveyDuration = 300,
|
||||
mmi = 10
|
||||
)
|
||||
val bookedRawSlot = slot(slotId = 1L, slotNum = 1L, baseTime = baseTime, startSecond = 0, endSecond = 10)
|
||||
val candidateInsideBooked = slot(slotId = 2L, slotNum = 2L, baseTime = baseTime, startSecond = 2, endSecond = 8)
|
||||
val booked = BookedSlotEntity(slot = bookedRawSlot, cycle = 0).apply {
|
||||
status = BookedSlotStatus.PROCESSED.name
|
||||
}
|
||||
|
||||
val result = satellite.prepareCoverageSlots(
|
||||
slots = listOf(bookedRawSlot, candidateInsideBooked),
|
||||
bookedSlots = listOf(booked),
|
||||
timeStart = baseTime,
|
||||
timeStop = baseTime.plusSeconds(20),
|
||||
sign = null,
|
||||
states = null
|
||||
).map { it.slot }.associateBy { it.slotNumber }
|
||||
|
||||
assertEquals(SlotStatus.BOOKED, result.getValue(1L).state)
|
||||
assertEquals(SlotStatus.BUSY, result.getValue(2L).state)
|
||||
}
|
||||
|
||||
private fun slot(
|
||||
slotId: Long,
|
||||
slotNum: Long,
|
||||
baseTime: LocalDateTime,
|
||||
startSecond: Long,
|
||||
endSecond: Long
|
||||
) = SlotEntity(
|
||||
slotId = slotId,
|
||||
slotNum = slotNum,
|
||||
cycle = 0,
|
||||
satelliteId = 1L,
|
||||
coveringType = 0,
|
||||
tn = baseTime.plusSeconds(startSecond),
|
||||
tk = baseTime.plusSeconds(endSecond),
|
||||
roll = 10.0,
|
||||
contour = "POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))",
|
||||
revolution = 1L,
|
||||
revolutionSign = "ASC"
|
||||
)
|
||||
}
|
||||
+49
-4
@@ -81,6 +81,48 @@ class OccupiedIntervalPrefilterTest {
|
||||
assertEquals(listOf(candidate), filtered)
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun `available candidate inside reserved slots interval is rejected even with same roll`() {
|
||||
val satellite = testSatellite(maxSurveyDuration = 120, mmi = 5)
|
||||
val candidate = candidateSlot(roll = 10.0, startOffsetSeconds = 10, endOffsetSeconds = 20)
|
||||
val occupied = listOf(
|
||||
occupiedInterval(
|
||||
roll = 10.0,
|
||||
startOffsetSeconds = 0,
|
||||
endOffsetSeconds = 30,
|
||||
source = "SLOTS"
|
||||
)
|
||||
)
|
||||
|
||||
val filtered = OccupiedIntervalPrefilter.filterCandidates(listOf(candidate), occupied, satellite)
|
||||
|
||||
assertTrue(filtered.isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `booked candidate inside reserved slots interval is kept for coverage accounting`() {
|
||||
val satellite = testSatellite(maxSurveyDuration = 120, mmi = 5)
|
||||
val candidate = candidateSlot(
|
||||
roll = 10.0,
|
||||
startOffsetSeconds = 10,
|
||||
endOffsetSeconds = 20,
|
||||
state = SlotStatus.BOOKED
|
||||
)
|
||||
val occupied = listOf(
|
||||
occupiedInterval(
|
||||
roll = 10.0,
|
||||
startOffsetSeconds = 0,
|
||||
endOffsetSeconds = 30,
|
||||
source = "SLOTS"
|
||||
)
|
||||
)
|
||||
|
||||
val filtered = OccupiedIntervalPrefilter.filterCandidates(listOf(candidate), occupied, satellite)
|
||||
|
||||
assertEquals(listOf(candidate), filtered)
|
||||
}
|
||||
|
||||
private fun testSatellite(maxSurveyDuration: Int, mmi: Long): AbstractSatellite =
|
||||
object : AbstractSatellite(id = 22, maxSurveyDuration = maxSurveyDuration, mmi = mmi) {
|
||||
override fun prepareCoverageSlots(
|
||||
@@ -96,26 +138,29 @@ class OccupiedIntervalPrefilterTest {
|
||||
private fun occupiedInterval(
|
||||
roll: Double,
|
||||
startOffsetSeconds: Long,
|
||||
endOffsetSeconds: Long
|
||||
endOffsetSeconds: Long,
|
||||
source: String = "TEST"
|
||||
) = OccupiedIntervalDTO(
|
||||
satelliteId = 22,
|
||||
startTime = baseTime().plusSeconds(startOffsetSeconds),
|
||||
endTime = baseTime().plusSeconds(endOffsetSeconds),
|
||||
roll = roll,
|
||||
source = "TEST"
|
||||
source = source
|
||||
)
|
||||
|
||||
private fun candidateSlot(
|
||||
roll: Double,
|
||||
startOffsetSeconds: Long,
|
||||
endOffsetSeconds: Long
|
||||
endOffsetSeconds: Long,
|
||||
state: SlotStatus = SlotStatus.AVAILABLE
|
||||
) = SlotDTO(
|
||||
cycle = 0,
|
||||
satelliteId = 22,
|
||||
tn = baseTime().plusSeconds(startOffsetSeconds),
|
||||
tk = baseTime().plusSeconds(endOffsetSeconds),
|
||||
roll = roll,
|
||||
contour = "POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))"
|
||||
contour = "POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))",
|
||||
state = state
|
||||
)
|
||||
|
||||
private fun baseTime(): LocalDateTime = LocalDateTime.of(2026, 3, 26, 10, 0, 0)
|
||||
|
||||
Reference in New Issue
Block a user