Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rapport de patrouille #92

Merged
merged 19 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Export mission - refactor and test
  • Loading branch information
lwih committed Mar 12, 2024
commit af4791754909ecc536f58975a8a56b0ee1663cae
Original file line number Diff line number Diff line change
@@ -1,27 +1,17 @@
package fr.gouv.dgampa.rapportnav.domain.use_cases.mission.export

import fr.gouv.dgampa.rapportnav.config.UseCase
import fr.gouv.dgampa.rapportnav.domain.entities.mission.MissionActionEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.MissionEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.env.envActions.EnvActionControlEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.fish.fishActions.MissionAction
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.action.ActionStatusEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.action.ActionType
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.action.NavActionEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.crew.MissionCrewEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.export.MissionExportEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.generalInfo.MissionGeneralInfoEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.status.ActionStatusReason
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.status.ActionStatusType
import fr.gouv.dgampa.rapportnav.domain.repositories.mission.ExportParams
import fr.gouv.dgampa.rapportnav.domain.repositories.mission.IRpnExportRepository
import fr.gouv.dgampa.rapportnav.domain.repositories.mission.action.INavActionStatusRepository
import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.GetMissionById
import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.action.GroupActionByDate
import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.crew.GetAgentsCrewByMissionId
import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.generalInfo.GetMissionGeneralInfoByMissionId
import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.status.GetStatusDurations
import java.time.LocalDate
import org.slf4j.LoggerFactory

@UseCase
class ExportMission(
Expand All @@ -30,115 +20,31 @@ class ExportMission(
private val agentsCrewByMissionId: GetAgentsCrewByMissionId,
private val getMissionById: GetMissionById,
private val navActionStatus: INavActionStatusRepository,
private val getStatusDurations: GetStatusDurations,
private val groupActionByDate: GroupActionByDate,
private val formatActionToString: FormatActionToString,
private val mapStatusDurations: MapStatusDurations,
private val formatActionsForTimeline: FormatActionsForTimeline,
) {

private inline fun List<GetStatusDurations.ActionStatusWithDuration>.findDuration(predicate: (GetStatusDurations.ActionStatusWithDuration) -> Boolean): Int {
return find(predicate)?.value?.toInt() ?: 0
}

fun computeDurations(mission: MissionEntity, statuses: List<ActionStatusEntity>): Map<String, Map<String, Int>> {
val durations = getStatusDurations.computeActionDurations(
missionStartDateTime = mission.startDateTimeUtc,
missionEndDateTime = mission.endDateTimeUtc,
actions = statuses,
)

val atSeaDurations = mapOf(
"navigationEffective" to durations.findDuration { it.status == ActionStatusType.NAVIGATING },
"mouillage" to durations.findDuration { it.status == ActionStatusType.ANCHORED },
"total" to 0
).toMutableMap()
atSeaDurations["total"] = atSeaDurations.values.sum()

val dockingDurations = mapOf(
"maintenance" to durations.findDuration { it.reason == ActionStatusReason.MAINTENANCE },
"meteo" to durations.findDuration { it.reason == ActionStatusReason.WEATHER },
"representation" to durations.findDuration { it.reason == ActionStatusReason.REPRESENTATION },
"adminFormation" to durations.findDuration { it.reason == ActionStatusReason.ADMINISTRATION },
"autre" to durations.findDuration { it.reason == ActionStatusReason.OTHER },
"contrPol" to durations.findDuration { it.reason == ActionStatusReason.HARBOUR_CONTROL },
"total" to 0
).toMutableMap()
dockingDurations["total"] = dockingDurations.values.sum()

val unavailabilityDurations = mapOf(
"technique" to durations.findDuration { it.reason == ActionStatusReason.TECHNICAL },
"personnel" to durations.findDuration { it.reason == ActionStatusReason.PERSONNEL },
"total" to 0
).toMutableMap()
unavailabilityDurations["total"] = unavailabilityDurations.values.sum()

return mapOf(
"atSeaDurations" to atSeaDurations.toMap(),
"dockingDurations" to dockingDurations.toMap(),
"unavailabilityDurations" to unavailabilityDurations.toMap()
)
}


fun formatActionsForTimeline(actions: List<MissionActionEntity>?): Map<LocalDate, List<String>>? {

if (actions.isNullOrEmpty()) {
return null
}
// Group actions by date
val groupedActions = groupActionByDate.execute(actions = actions)

// Map each group to list of formatted strings
val formattedActions = groupedActions?.mapValues { (_, actionsOnDate) ->
actionsOnDate.mapNotNull { action ->
when (action) {
is MissionActionEntity.EnvAction -> {
if (action.envAction?.controlAction?.action is EnvActionControlEntity) {
formatActionToString.formatEnvControl(action.envAction.controlAction.action)
} else null
}

is MissionActionEntity.FishAction -> {
if (action.fishAction.controlAction?.action is MissionAction) {
formatActionToString.formatFishControl(action.fishAction.controlAction.action)
} else null
}

is MissionActionEntity.NavAction -> {
val navAction: NavActionEntity = action.navAction
when (navAction.actionType) {
ActionType.NOTE -> formatActionToString.formatNavNote(navAction.freeNoteAction)
ActionType.STATUS -> formatActionToString.formatNavStatus(navAction.statusAction)
ActionType.CONTROL -> formatActionToString.formatNavControl(navAction.controlAction)
else -> null
}
}
}
}
}
return formattedActions
}
private val logger = LoggerFactory.getLogger(ExportMission::class.java)

fun exportOdt(missionId: Int): MissionExportEntity? {
try {
val mission: MissionEntity? = getMissionById.execute(missionId = missionId)
if (mission == null) {
logger.error("[exportOdt] Mission not found for missionId: $missionId")
return null
}

val mission: MissionEntity? = getMissionById.execute(missionId = missionId)

return if (mission == null) {
null
} else {
val generalInfo: MissionGeneralInfoEntity? = getMissionGeneralInfoByMissionId.execute(missionId)
val agentsCrew: List<MissionCrewEntity> = agentsCrewByMissionId.execute(missionId = missionId)
val statuses = navActionStatus.findAllByMissionId(missionId = missionId).sortedBy { it.startDateTimeUtc }
.map { it.toActionStatusEntity() }


val durations = computeDurations(mission, statuses)

// TODO quelle formule utiliser? celle ci ou plutot missionEnd - missionStart ?
val durations = mapStatusDurations.execute(mission, statuses)
val missionDuration = (durations["atSeaDurations"]?.get("total") ?: 0) +
(durations["dockingDurations"]?.get("total") ?: 0) +
(durations["unavailabilityDurations"]?.get("total") ?: 0)

val timeline = formatActionsForTimeline(mission.actions)
val timeline = formatActionsForTimeline.formatTimeline(mission.actions)

val exportParams = ExportParams(
service = mission.openBy,
Expand All @@ -158,10 +64,12 @@ class ExportMission(
crew = agentsCrew,
timeline = timeline
)
// return null
exportRepository.exportOdt(exportParams)

return exportRepository.exportOdt(exportParams)
} catch (e: Exception) {
logger.error("[exportOdt] error occurred during exportOdt: ${e.message}")
return null
}

}

}
Original file line number Diff line number Diff line change
@@ -1,20 +1,70 @@
package fr.gouv.dgampa.rapportnav.domain.use_cases.mission.export

import fr.gouv.dgampa.rapportnav.config.UseCase
import fr.gouv.dgampa.rapportnav.domain.entities.mission.MissionActionEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.env.envActions.EnvActionControlEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.fish.fishActions.InfractionType
import fr.gouv.dgampa.rapportnav.domain.entities.mission.fish.fishActions.MissionAction
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.action.ActionControlEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.action.ActionFreeNoteEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.action.ActionStatusEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.action.*
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.status.mapActionStatusTypeToHumanString
import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.action.GroupActionByDate
import java.time.LocalDate
import java.time.ZonedDateTime

@UseCase
class FormatActionToString() {
class FormatActionsForTimeline(
private val groupActionByDate: GroupActionByDate,
) {

fun formatTimeline(actions: List<MissionActionEntity>?): Map<LocalDate, List<String>>? {

if (actions.isNullOrEmpty()) {
return null
}
// Group actions by date
val groupedActions = groupActionByDate.execute(actions = actions)

// Map each group to list of formatted strings
return groupedActions?.mapValues { (_, actionsOnDate) ->
actionsOnDate.mapNotNull { action ->
formatAction(action)
}
}
}

private fun formatAction(action: MissionActionEntity): String? {
return when (action) {
is MissionActionEntity.EnvAction -> formatEnvAction(action)
is MissionActionEntity.FishAction -> formatFishAction(action)
is MissionActionEntity.NavAction -> formatNavAction(action)
}
}

private fun formatEnvAction(action: MissionActionEntity.EnvAction): String? {
return action.envAction?.controlAction?.action?.let { envControlAction ->
formatEnvControl(envControlAction)
}
}

private fun formatFishAction(action: MissionActionEntity.FishAction): String? {
return action.fishAction.controlAction?.action?.let { fishControlAction ->
formatFishControl(fishControlAction)
}
}

private fun formatNavAction(action: MissionActionEntity.NavAction): String? {
val navAction = action.navAction
return when (navAction.actionType) {
ActionType.NOTE -> formatNavNote(navAction.freeNoteAction)
ActionType.STATUS -> formatNavStatus(navAction.statusAction)
ActionType.CONTROL -> formatNavControl(navAction.controlAction)
else -> null
}
}


fun formatTime(dateTime: ZonedDateTime?): String? {
return dateTime?.let { it.toLocalTime().toString().padStart(5, '0') } ?: "N/A"
return dateTime?.toLocalTime()?.toString()?.padStart(5, '0') ?: "N/A"
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package fr.gouv.dgampa.rapportnav.domain.use_cases.mission.export

import fr.gouv.dgampa.rapportnav.config.UseCase
import fr.gouv.dgampa.rapportnav.domain.entities.mission.MissionEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.action.ActionStatusEntity
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.status.ActionStatusReason
import fr.gouv.dgampa.rapportnav.domain.entities.mission.nav.status.ActionStatusType
import fr.gouv.dgampa.rapportnav.domain.use_cases.mission.status.GetStatusDurations

@UseCase
class MapStatusDurations(
private val getStatusDurations: GetStatusDurations,
) {

private inline fun List<GetStatusDurations.ActionStatusWithDuration>.findDuration(predicate: (GetStatusDurations.ActionStatusWithDuration) -> Boolean): Int {
return find(predicate)?.value?.toInt() ?: 0
}

fun execute(mission: MissionEntity, statuses: List<ActionStatusEntity>): Map<String, Map<String, Int>> {
val durations = getStatusDurations.computeActionDurations(
missionStartDateTime = mission.startDateTimeUtc,
missionEndDateTime = mission.endDateTimeUtc,
actions = statuses,
)

val atSeaDurations = mapOf(
"navigationEffective" to durations.findDuration { it.status == ActionStatusType.NAVIGATING },
"mouillage" to durations.findDuration { it.status == ActionStatusType.ANCHORED },
"total" to 0
).toMutableMap()
atSeaDurations["total"] = atSeaDurations.values.sum()

val dockingDurations = mapOf(
"maintenance" to durations.findDuration { it.reason == ActionStatusReason.MAINTENANCE },
"meteo" to durations.findDuration { it.reason == ActionStatusReason.WEATHER },
"representation" to durations.findDuration { it.reason == ActionStatusReason.REPRESENTATION },
"adminFormation" to durations.findDuration { it.reason == ActionStatusReason.ADMINISTRATION },
"autre" to durations.findDuration { it.reason == ActionStatusReason.OTHER },
"contrPol" to durations.findDuration { it.reason == ActionStatusReason.HARBOUR_CONTROL },
"total" to 0
).toMutableMap()
dockingDurations["total"] = dockingDurations.values.sum()

val unavailabilityDurations = mapOf(
"technique" to durations.findDuration { it.reason == ActionStatusReason.TECHNICAL },
"personnel" to durations.findDuration { it.reason == ActionStatusReason.PERSONNEL },
"total" to 0
).toMutableMap()
unavailabilityDurations["total"] = unavailabilityDurations.values.sum()

return mapOf(
"atSeaDurations" to atSeaDurations.toMap(),
"dockingDurations" to dockingDurations.toMap(),
"unavailabilityDurations" to unavailabilityDurations.toMap()
)
}
}

This file was deleted.

Loading
Loading