function base = base_quantities(atm, inputs, varargin)
% BASE_QUANTITIES  Magnitudes base a la altitud dada (ISA).
% USO:
%   base = base_quantities();                          % usa defaults (30kft)
%   base = base_quantities(atm, inputs);               % con tus structs
%   base = base_quantities(atm, inputs,'verbose',true) % imprime resumen
%
% SALIDA (base): q0 [lbf/ft^2], q0S [lbf], k [-], TSFC [1/hr], meta (aux)

    % -------- Defaults si faltan entradas --------
    if nargin < 1 || isempty(atm)
        atm = isa_std_atmos(30000); % default 30 kft
    end
    if nargin < 2 || isempty(inputs)
        inputs = struct('S',992.8,'AR',7.51,'e',0.612, ...
                        'TSFC_nom',0.60,'TSFC_bleed',0.608,'use_bleed',true);
    end

    % -------- Opción verbose --------
    p=inputParser; p.addParameter('verbose',false,@(x)islogical(x)||isnumeric(x));
    p.parse(varargin{:}); verbose = logical(p.Results.verbose);

    % -------- Cálculos --------
    a   = atm.a_fts;            % [ft/s]
    rho = atm.rho;              % [slug/ft^3]
    S   = inputs.S;             % [ft^2]
    q0  = 0.5*rho*a^2;          % [lbf/ft^2]
    q0S = q0*S;                 % [lbf]
    k   = 1/(pi*inputs.AR*inputs.e);
    TSFC = inputs.TSFC_nom; if isfield(inputs,'use_bleed') && inputs.use_bleed, TSFC=inputs.TSFC_bleed; end

    base.q0=q0; base.q0S=q0S; base.k=k; base.TSFC=TSFC;
    base.meta = struct('S',S,'AR',inputs.AR,'e',inputs.e,'sigma',getf(atm,'sigma',NaN));

    if verbose
        fprintf('\n=== Magnitudes base @ h = %.0f ft ===\n', getf(atm,'h_ft',NaN));
        expl('a',a,'ft/s','Velocidad del sonido (ISA)'); 
        expl('rho',rho,'slug/ft^3','Densidad del aire (ISA)');
        expl('S',S,'ft^2','Área alar');
        expl('AR',inputs.AR,'-','Alargamiento'); expl('e',inputs.e,'-','Eficiencia de Oswald');
        expl('q0',q0,'lbf/ft^2','q_0 = 0.5 ρ a^2'); expl('q0S',q0S,'lbf','q_0 S');
        expl('k',k,'-','Coef. inducido = 1/(πAR e)'); expl('TSFC',TSFC,'1/hr','Consumo específico');
        sig = getf(atm,'sigma',NaN); if ~isnan(sig), expl('sigma',sig,'-','Relación de densidad'); end
        fprintf('\n');
    end
end

function v=getf(s,f,def), if isfield(s,f), v=s.(f); else, v=def; end, end
function expl(symb,val,unit,txt)
    if isnumeric(val), sval=num2str(val,'%.5g'); else, sval=char(val); end
    fprintf('  %-6s = %-12s [%s]  %s\n', symb,sval,unit,txt);
end





% ============================================================
%   AIRCRAFT PERFORMANCE & DESIGN – PIPELINE ASIGNACIONES 1–4
% ============================================================
%
% 🔹 Propósito
% Este conjunto de funciones automatiza los cálculos de 
% performance (Asignaciones 1–4), permitiendo trabajar tanto
% con CD0 base constante como con la curva ΔCD0(M) digitalizada.
% Los módulos están diseñados para ejecutarse en cadena y 
% generar tablas, gráficas y resúmenes con explicación.
%
% 🔹 Flujo de ejecución principal (pipeline)
%
% run_airperf.m
%   └─> isa_std_atmos     → atm
%   └─> base_quantities   → base
%   └─> build_CD0_total   → CD0tot
%   └─> build_drag_table  → T
%   └─> check_mach_cap    → cap
%   └─> breguet_ER        → breg
%   └─> describe_airperf_outputs(atm, base, CD0tot, T, cap, breg)
%
% 🔹 Descripción de cada módulo
%
% isa_std_atmos(h_ft)
%   ENTRADA: altitud [ft]
%   SALIDA : atm struct con:
%       T_K, T_R, a_fts, rho, sigma
%   → Modelo de atmósfera estándar (ISA).
%
% base_quantities(atm, inputs)
%   ENTRADA: atm, struct inputs con {S, W, AR, e, TSFC, T_SL_tot}
%   SALIDA : base struct con:
%       q0, q0S, k, TSFC corregido
%   → Calcula magnitudes base aerodinámicas.
%
% build_CD0_total(M_grid, CD0_base, dCD0)
%   ENTRADA: malla Mach, CD0_base, curva ΔCD0(M)
%   SALIDA : CD0tot vector
%   → Construye la curva de arrastre parasitario.
%     (dos caminos: CD0_base constante o digitalización ΔCD0).
%
% build_drag_table(M_grid, CD0tot, base, inputs)
%   ENTRADA: Mach grid, CD0tot, base, inputs
%   SALIDA : tabla T con columnas:
%       M, C_D0, C_D, C_L, D_par, D_ind, D_tot
%   → Calcula arrastres parasitario, inducido y total.
%
% check_mach_cap(M_cap, CD0tot, base, inputs)
%   ENTRADA: Mach operativo
%   SALIDA : cap struct con:
%       C_D_cap, D_cap, T_avail
%   → Compara empuje disponible vs arrastre.
%     Determina si gobierna Mach límite o empuje.
%
% breguet_ER(inputs, base, atm)
%   ENTRADA: TSFC, (L/D), Wi/Wf, Mach operativo
%   SALIDA : breg struct con:
%       E (endurance), R (range)
%   → Implementa ecuaciones de Breguet.
%
% describe_airperf_outputs(atm, base, CD0tot, T, cap, breg)
%   ENTRADA: todos los structs anteriores
%   SALIDA : impresión en consola con unidades y explicación
%   → Resume y documenta resultados.
%
% 🔹 Notas de uso
% - Siempre arrancar desde run_airperf.m
% - Cada módulo puede probarse aislado llamando con sus argumentos.
% - Diseñado para Matlab Online con entrada/salida clara y
%   documentada para reportes técnicos en LaTeX.
%
% ============================================================
