Initial project import
This commit is contained in:
108
src/planejador_missao/rules.py
Normal file
108
src/planejador_missao/rules.py
Normal file
@@ -0,0 +1,108 @@
|
||||
"""Regras operacionais de disponibilidade, qualificacao e progressao."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date
|
||||
|
||||
import pandas as pd
|
||||
|
||||
from .utils import normalizar_texto
|
||||
|
||||
|
||||
def piloto_disponivel(tripulante: str, data_missao: date, indisponibilidades: pd.DataFrame) -> bool:
|
||||
trip = normalizar_texto(tripulante)
|
||||
conflitos = indisponibilidades[
|
||||
(indisponibilidades["tripulante"] == trip)
|
||||
& (indisponibilidades["inicio"] <= data_missao)
|
||||
& (indisponibilidades["fim"] >= data_missao)
|
||||
]
|
||||
return conflitos.empty
|
||||
|
||||
|
||||
def classe_principal(qualificacao: str) -> str:
|
||||
qual = normalizar_texto(qualificacao)
|
||||
for classe in ["IN", "PO", "PB", "AL"]:
|
||||
if classe in qual.split("/"):
|
||||
return classe
|
||||
if classe in qual.split():
|
||||
return classe
|
||||
return "OUTRO"
|
||||
|
||||
|
||||
def qualificacao_base_aeronave(tripulante: str, aeronave: str, cadastro: pd.DataFrame) -> str:
|
||||
linha = cadastro[cadastro["tripulante"] == normalizar_texto(tripulante)]
|
||||
if linha.empty:
|
||||
return "OUTRO"
|
||||
qt = [x for x in normalizar_texto(linha.iloc[0]["qt"]).split("/") if x]
|
||||
quals = [x for x in normalizar_texto(linha.iloc[0]["qualificacao"]).split("/") if x]
|
||||
if len(qt) == len(quals) and aeronave in qt:
|
||||
return classe_principal(quals[qt.index(aeronave)])
|
||||
return classe_principal(linha.iloc[0]["qualificacao"])
|
||||
|
||||
|
||||
def subprograma_concluido(progresso: pd.DataFrame, tripulante: str, aeronave: str, subprograma: str, catalogo: pd.DataFrame) -> bool:
|
||||
necessarias = set(catalogo[(catalogo["aeronave"] == aeronave) & (catalogo["subprograma"] == subprograma)]["oi"])
|
||||
if not necessarias:
|
||||
return False
|
||||
concluidas = set(
|
||||
progresso[
|
||||
(progresso["tripulante"] == normalizar_texto(tripulante))
|
||||
& (progresso["aeronave"] == aeronave)
|
||||
& (progresso["subprograma"] == subprograma)
|
||||
& (progresso["concluida"] == True)
|
||||
]["oi"]
|
||||
)
|
||||
return necessarias.issubset(concluidas)
|
||||
|
||||
|
||||
def qualificacao_operacional(tripulante: str, aeronave: str, cadastro: pd.DataFrame, progresso: pd.DataFrame, catalogo: pd.DataFrame) -> str:
|
||||
rank = {"OUTRO": 0, "AL": 1, "PB": 2, "PO": 3, "IN": 4}[qualificacao_base_aeronave(tripulante, aeronave, cadastro)]
|
||||
if subprograma_concluido(progresso, tripulante, aeronave, "SPFO-1", catalogo):
|
||||
rank = max(rank, 2)
|
||||
if subprograma_concluido(progresso, tripulante, aeronave, "SPFO-2", catalogo):
|
||||
rank = max(rank, 3)
|
||||
if aeronave == "C98" and subprograma_concluido(progresso, tripulante, aeronave, "SPQE-3", catalogo):
|
||||
rank = max(rank, 4)
|
||||
if aeronave == "C97" and subprograma_concluido(progresso, tripulante, aeronave, "SPQE-4", catalogo):
|
||||
rank = max(rank, 4)
|
||||
return {0: "OUTRO", 1: "AL", 2: "PB", 3: "PO", 4: "IN"}[rank]
|
||||
|
||||
|
||||
def concluiu_ois(progresso: pd.DataFrame, tripulante: str, aeronave: str, ois: list[str]) -> bool:
|
||||
concluidas = set(
|
||||
progresso[
|
||||
(progresso["tripulante"] == normalizar_texto(tripulante))
|
||||
& (progresso["aeronave"] == aeronave)
|
||||
& (progresso["concluida"] == True)
|
||||
]["oi"]
|
||||
)
|
||||
return set(ois).issubset(concluidas)
|
||||
|
||||
|
||||
def eh_instrutor_adaptado(tripulante: str, aeronave: str, cadastro: pd.DataFrame, progresso: pd.DataFrame, catalogo: pd.DataFrame) -> bool:
|
||||
trip = normalizar_texto(tripulante)
|
||||
instrutores_base = {
|
||||
"C95": {"MES", "BRI"},
|
||||
"C97": {"AEU", "MAT"},
|
||||
"C98": {"BRI", "FIA", "MDO", "SLS", "CFF"},
|
||||
}
|
||||
if trip in instrutores_base.get(aeronave, set()):
|
||||
return True
|
||||
if aeronave == "C97" and trip in {"SEI", "LPS"}:
|
||||
return concluiu_ois(progresso, trip, aeronave, ["01TL01D41", "04TL01N42"])
|
||||
if aeronave == "C98" and trip in {"MCH", "DOG"}:
|
||||
return concluiu_ois(progresso, trip, aeronave, ["01TL01D31", "04TL01N32"])
|
||||
return qualificacao_operacional(trip, aeronave, cadastro, progresso, catalogo) == "IN"
|
||||
|
||||
|
||||
def combinar_progresso_com_historico(progresso: pd.DataFrame, historico: pd.DataFrame, catalogo: pd.DataFrame) -> pd.DataFrame:
|
||||
if historico.empty:
|
||||
return progresso
|
||||
voadas = historico[(historico["oi"] != "") & (historico["horas_voadas"] > 0)]
|
||||
if voadas.empty:
|
||||
return progresso
|
||||
hist = voadas.merge(catalogo[["aeronave", "subprograma", "oi"]].drop_duplicates(), on=["aeronave", "oi"], how="left")
|
||||
hist = hist.dropna(subset=["subprograma"])
|
||||
hist = hist[["tripulante", "aeronave", "subprograma", "oi", "horas_voadas"]].rename(columns={"horas_voadas": "horas_realizadas"})
|
||||
hist["concluida"] = True
|
||||
return pd.concat([progresso, hist], ignore_index=True).drop_duplicates(["tripulante", "aeronave", "subprograma", "oi"])
|
||||
Reference in New Issue
Block a user