- Complete routing engine: ingest, optimizer (CG+B&B), maintenance monitor, metrics, pipeline, quality checks - Streamlit dashboard with Input/Output tab structure, editable data editors, interactive Folium map with satellite layer and maintenance base highlights, FH stacked bar chart with TTM availability - CSV data files: AERONAVES, CHECKS, AIRPORTS, ESCALA DE VOO - README, CONTEXTO and CHANGELOG added - Remove legacy pre_process scripts and raw binary files (PDFs/xlsx) - Update .gitignore to exclude outputs/, data/, raw/*.pdf, raw/*.xlsx Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
76 lines
2.5 KiB
Python
76 lines
2.5 KiB
Python
"""
|
||
Script 04 – Generate and export flight strings.
|
||
|
||
Reads the saved solution CSVs and generates a per-aircraft "flight string"
|
||
report in human-readable format (console + Excel export).
|
||
"""
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parents[1]
|
||
sys.path.insert(0, str(ROOT))
|
||
|
||
import pandas as pd
|
||
|
||
from src.routing_engine.config import DEFAULT_CONFIG
|
||
|
||
cfg = DEFAULT_CONFIG
|
||
|
||
sched_path = cfg.schedules_dir / "flight_strings.csv"
|
||
maint_path = cfg.schedules_dir / "maintenance_events.csv"
|
||
|
||
if not sched_path.exists():
|
||
print("No schedule found. Run script 03 first.")
|
||
sys.exit(1)
|
||
|
||
sched = pd.read_csv(sched_path, parse_dates=["departure", "arrival"])
|
||
maint = pd.read_csv(maint_path, parse_dates=["maint_start", "maint_end"]) if maint_path.exists() else pd.DataFrame()
|
||
|
||
print("=" * 70)
|
||
print("FLIGHT STRINGS PER AIRCRAFT")
|
||
print("=" * 70)
|
||
|
||
for aircraft, group in sched.groupby("aircraft"):
|
||
print(f"\n{'-'*70}")
|
||
print(f" Aeronave: {aircraft}")
|
||
print(f"{'-'*70}")
|
||
|
||
total_fh = 0.0
|
||
for _, row in group.sort_values("departure").iterrows():
|
||
maint_flag = " <- MANUTENCAO ANTES" if row.get("maintenance_before") else ""
|
||
dep = pd.to_datetime(row["departure"])
|
||
arr = pd.to_datetime(row["arrival"])
|
||
fh = float(row.get("flight_hours", 0))
|
||
total_fh += fh
|
||
print(
|
||
f" {row['ofrag_id']:12s} "
|
||
f"{dep.strftime('%d/%m %H:%M')} -> {arr.strftime('%d/%m %H:%M')} "
|
||
f"({fh:.2f} FH){maint_flag}"
|
||
)
|
||
|
||
print(f" {'TOTAL':12s} {total_fh:.2f} FH")
|
||
|
||
if not maint.empty:
|
||
ac_maint = maint[maint["aircraft"] == aircraft]
|
||
if not ac_maint.empty:
|
||
print(f"\n Eventos de manutencao:")
|
||
for _, ev in ac_maint.iterrows():
|
||
print(
|
||
f" CHECK (ciclo {int(ev['check_cycle_index'])}) "
|
||
f"{pd.to_datetime(ev['maint_start']).strftime('%d/%m %H:%M')} -> "
|
||
f"{pd.to_datetime(ev['maint_end']).strftime('%d/%m %H:%M')} "
|
||
f"TTM perdido: {ev['ttm_loss_hours']:.2f} FH"
|
||
)
|
||
|
||
# Export to Excel
|
||
out_xlsx = cfg.exports_dir / "flight_strings.xlsx"
|
||
try:
|
||
with pd.ExcelWriter(out_xlsx, engine="openpyxl") as writer:
|
||
sched.to_excel(writer, sheet_name="Escala", index=False)
|
||
if not maint.empty:
|
||
maint.to_excel(writer, sheet_name="Manutencao", index=False)
|
||
print(f"\n\nExportado para Excel -> {out_xlsx}")
|
||
except ImportError:
|
||
print("\n(openpyxl not installed – Excel export skipped)")
|