diff --git a/services/slots-service/src/main/kotlin/space/nstart/pcp/slots_service/controller/SlotController.kt b/services/slots-service/src/main/kotlin/space/nstart/pcp/slots_service/controller/SlotController.kt index 30627a7..392da65 100644 --- a/services/slots-service/src/main/kotlin/space/nstart/pcp/slots_service/controller/SlotController.kt +++ b/services/slots-service/src/main/kotlin/space/nstart/pcp/slots_service/controller/SlotController.kt @@ -103,8 +103,10 @@ class SlotController { @RequestParam("sun") sun : Double?, @Parameter(description = "Вариант расчета покрытия") @RequestParam("coverageStrategy", required = false) coverageStrategy: SlotCoverageStrategy?, + @Parameter(description = "Вернуть и занятые бронью слоты (BUSY) — для обзора; по умолчанию только доступные/забронированные") + @RequestParam("all", required = false) all: Boolean?, ) : List - = slotService.reqCover(requestId, timeStart, timeStop, sign, cov, satellites, sun, coverageStrategy).toList() + = slotService.reqCover(requestId, timeStart, timeStop, sign, cov, satellites, sun, coverageStrategy, all == true).toList() @GetMapping("interval") @Operation(summary = "Получение всех слотов на заданном интервале времени") diff --git a/services/slots-service/src/main/kotlin/space/nstart/pcp/slots_service/service/SlotService.kt b/services/slots-service/src/main/kotlin/space/nstart/pcp/slots_service/service/SlotService.kt index 63aaf4b..8e87501 100644 --- a/services/slots-service/src/main/kotlin/space/nstart/pcp/slots_service/service/SlotService.kt +++ b/services/slots-service/src/main/kotlin/space/nstart/pcp/slots_service/service/SlotService.kt @@ -1216,7 +1216,8 @@ class SlotService { states: List? = null, sats : List? = null, sun : Double? = null, - coverageStrategy: SlotCoverageStrategy? = SlotCoverageStrategy.GREEDY + coverageStrategy: SlotCoverageStrategy? = SlotCoverageStrategy.GREEDY, + includeBusy: Boolean = false ): Iterable { val target = buildCoverageTargets( items = listOf(SlotCoverageTargetDTO(targetId = 1, wkt = wkt)) @@ -1235,7 +1236,8 @@ class SlotService { batchContext = batchContext, cov = cov, sun = sun, - coverageStrategy = coverageStrategy + coverageStrategy = coverageStrategy, + includeBusy = includeBusy ) logger.info( "polySlots finish: targetId={}, candidateSlots={}, sunFilteredSlots={}, returnedSlots={}, sun={}", @@ -1668,10 +1670,14 @@ class SlotService { batchContext: CoverageBatchContext, cov: Boolean?, sun: Double?, - coverageStrategy: SlotCoverageStrategy? + coverageStrategy: SlotCoverageStrategy?, + // true — добавить в результат и занятые бронью слоты (BUSY) для обзора. В расчёт покрытия + // (solver) они не попадают: selectedSlots остаётся только из AVAILABLE/BOOKED. + includeBusy: Boolean = false ): CoverageSelectionResult { val totalStartedAtMs = System.currentTimeMillis() val selectedSlots = mutableListOf() + val busySlots = mutableListOf() val targetSlotIdsBySatelliteId = batchContext.rawSlotIdsByTargetIdAndSatelliteId[target.targetId].orEmpty() val sourceSlotIds = targetSlotIdsBySatelliteId.values.sumOf { it.size } var preparedSlotsBeforeOccupiedFilter = 0 @@ -1710,6 +1716,12 @@ class SlotService { val sunFilterResult = filterBySunAngle(filteredSlots, sun) sunFilteredSlots += sunFilterResult.filteredCount selectedSlots.addAll(sunFilterResult.slots) + // «Показать все слоты»: добавляем и занятые бронью (BUSY) для обзора — тот же + // sun-фильтр, чтобы не показывать заведомо непригодные по Солнцу. + if (includeBusy) { + val busyPrepared = preparedSlotsIncludingBlocked.filter { it.state == SlotStatus.BUSY } + busySlots.addAll(filterBySunAngle(busyPrepared, sun).slots) + } } } logger.debug( @@ -1815,15 +1827,17 @@ class SlotService { candidateSelectionMs, totalMs ) + // Без покрытия («Показать все слоты»): при includeBusy возвращаем и занятые бронью слоты. + val resultSlots = if (includeBusy) selectedSlots + busySlots else selectedSlots return CoverageSelectionResult( - slots = selectedSlots, + slots = resultSlots, sourceSlotIds = sourceSlotIds, preparedSlotsBeforeOccupiedFilter = preparedSlotsBeforeOccupiedFilter, occupiedFilteredSlots = occupiedFilteredSlots, candidateSlotsBeforeSunFilter = candidateSlotsBeforeSunFilter, sunFilteredSlots = sunFilteredSlots, solverInputSlots = selectedSlots.size, - solverOutputSlots = selectedSlots.size, + solverOutputSlots = resultSlots.size, candidateSelectionDurationMs = candidateSelectionMs, solverDurationMs = 0L, totalDurationMs = totalMs @@ -1870,9 +1884,12 @@ class SlotService { cov: Boolean?, sats : List? = null, sun : Double? = null, - coverageStrategy: SlotCoverageStrategy? = SlotCoverageStrategy.GREEDY + coverageStrategy: SlotCoverageStrategy? = SlotCoverageStrategy.GREEDY, + // true — вернуть и занятые бронью слоты (BUSY) для обзора («Показать все слоты»). + // Бронировать их нельзя, в расчёт покрытия они не идут. + includeBusy: Boolean = false ): Iterable { - logger.info("Запрос покрытия заявки $id") + logger.info("Запрос покрытия заявки $id (includeBusy=$includeBusy)") val req = earthService.reqcells(id)?.request?.contour ?: throw CustomErrorException("Нет такой заявки!!!!") logger.info("Получена заявка : $req") return polySlots( @@ -1881,10 +1898,12 @@ class SlotService { timeStop, sign, cov, - listOf(SlotStatus.AVAILABLE, SlotStatus.BOOKED), + if (includeBusy) listOf(SlotStatus.AVAILABLE, SlotStatus.BOOKED, SlotStatus.BUSY) + else listOf(SlotStatus.AVAILABLE, SlotStatus.BOOKED), sats, sun, - coverageStrategy + coverageStrategy, + includeBusy ) }