Add OARMP routing engine, dashboard and documentation
- 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>
This commit is contained in:
75
scripts/04_generate_flight_strings.py
Normal file
75
scripts/04_generate_flight_strings.py
Normal file
@@ -0,0 +1,75 @@
|
||||
"""
|
||||
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)")
|
||||
Reference in New Issue
Block a user