ATAS / src /decision.py
Eakempreet's picture
Docker + FastAPI backend + v11 HUD for HF Spaces deploy
12bc208
Raw
History Blame Contribute Delete
4.96 kB
"""
decision.py — Tactical Decision Layer
---------------------------------------
Receives ETA and hit probability from models.py and converts them into
a human-readable threat level and tactical recommendation.
This module knows nothing about models, physics, or metadata.
Its only job is: predictions in, decision out.
"""
from src.schemas import DECISION_THRESHOLDS
def get_recommendation(eta_seconds, hit_probability, no_aa_capability, enemy_generation, friendly_generation):
"""
Converts model predictions and platform data into a tactical recommendation.
Args:
eta_seconds (float): Predicted evasion time in seconds, clipped at 0.
hit_probability (float): Probability of hit after evasion maneuvers (0.0 - 1.0).
no_aa_capability (int): 1 if enemy has no air-to-air capability, 0 otherwise.
enemy_generation (float): Enemy aircraft generation (e.g. 4.0, 4.5, 5.0).
friendly_generation (float): Friendly aircraft generation (e.g. 4.0, 4.5, 5.0).
Returns:
str: Tactical recommendation string for the pilot.
"""
# Check first air-to-air capability
if no_aa_capability == 1:
return "NON-THREAT PLATFORM - MONITOR"
# Calculate the generational gap
gen_gap = friendly_generation - enemy_generation
# Define combat posture
if gen_gap >= DECISION_THRESHOLDS['gen_advantage_threshold']:
combat_posture = "Friendly advantage"
elif gen_gap <= -DECISION_THRESHOLDS['gen_disadvantage_threshold']:
combat_posture = "Enemy advantage"
else:
combat_posture = "Parity"
# Get the ETA status
if eta_seconds <= DECISION_THRESHOLDS['eta_critical']:
eta_status = "Low ETA"
else:
eta_status = "High ETA"
# Get the Hit probability status
if hit_probability >= DECISION_THRESHOLDS['hit_prob_high']:
hit_status = "High hit probability"
elif DECISION_THRESHOLDS['hit_prob_medium'] <= hit_probability <= DECISION_THRESHOLDS['hit_prob_high']:
hit_status = "Medium hit probability"
else:
hit_status = "Low hit probability"
# Get the recommendation based on decisions
if eta_status == "Low ETA":
if hit_status == "High hit probability":
# Critical threat - missile close, high chance of hit
if combat_posture == "Friendly advantage":
return "BREAK HARD + DEPLOY CM + COUNTER-ENGAGE"
elif combat_posture == "Parity":
return "BREAK HARD + DEPLOY CM"
else:
# Outmatched - survive first, disengage
return "BREAK HARD + DEPLOY CM + DISENGAGE IMMEDIATELY"
elif hit_status == "Medium hit probability":
# Elevated threat - missile close, uncertain outcome
if combat_posture == "Friendly advantage":
return "DEPLOY CM + DEFENSIVE MANEUVERS + ENGAGE"
elif combat_posture == "Parity":
return "DEPLOY CM + DEFENSIVE MANEUVERS"
else:
# Disadvantaged - don't risk engagement
return "DEPLOY CM + DEFENSIVE MANEUVERS + DISENGAGE"
else:
# Missile close but likely evadable - redirect and reassess
if combat_posture == "Friendly advantage":
return "DEPLOY CM + CHANGE FLIGHT PATH + ENGAGE"
elif combat_posture == "Parity":
return "DEPLOY CM + CHANGE FLIGHT PATH"
else:
return "DEPLOY CM + CHANGE FLIGHT PATH + DISENGAGE"
else:
if hit_status == "High hit probability":
# Time available but threat is serious - prepare now
if combat_posture == "Friendly advantage":
return "DEFENSIVE MANEUVERS + PREPARE CM + COUNTER-ENGAGE"
elif combat_posture == "Parity":
return "DEFENSIVE MANEUVERS + PREPARE CM"
else:
# Outmatched - use the time to create distance
return "DEFENSIVE MANEUVERS + PREPARE CM + MAINTAIN DISTANCE"
elif hit_status == "Medium hit probability":
# Uncertain threat with time to monitor - stay ready
if combat_posture == "Friendly advantage":
return "PREPARE CM + MONITOR + ENGAGE WHEN READY"
elif combat_posture == "Parity":
return "PREPARE CM + MONITOR TRAJECTORY"
else:
return "PREPARE CM + MAINTAIN DISTANCE"
else:
# Low threat - missile unlikely to hit, time available
if combat_posture == "Friendly advantage":
return "STAY SHARP + CLOSE AND ENGAGE"
elif combat_posture == "Parity":
return "STAY SHARP + MONITOR TRAJECTORY"
else:
# Disadvantaged even in low threat - keep distance
return "STAY SHARP + MAINTAIN DISTANCE"