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:
Eduardo Carlos
2026-06-17 11:52:34 -03:00
parent 32ad7c9f23
commit 3607965c88
43 changed files with 3419 additions and 1936 deletions

View 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)")