micromissiles-unity/Assets/Scripts/Assignment/ThreatAssignment.cs

79 lines
3.0 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
2024-09-12 15:44:55 -07:00
using Unity.VisualScripting;
using UnityEngine;
using System.Diagnostics.Contracts;
// The threat assignment class assigns interceptors to the targets based
// on the threat level of the targets.
2024-09-13 22:45:25 -07:00
public class ThreatAssignment : IAssignment {
2024-09-24 19:59:25 -07:00
// Assign a target to each interceptor that has not been assigned a target yet.
[Pure]
public IEnumerable<IAssignment.AssignmentItem> Assign(in IReadOnlyList<Interceptor> interceptors, in IReadOnlyList<ThreatData> targets) {
2024-09-13 22:45:25 -07:00
List<IAssignment.AssignmentItem> assignments = new List<IAssignment.AssignmentItem>();
List<Interceptor> assignableInterceptors = IAssignment.GetAssignableInterceptors(interceptors);
if (assignableInterceptors.Count == 0) {
Debug.LogWarning("No assignable interceptors found");
2024-09-13 22:45:25 -07:00
return assignments;
}
List<ThreatData> activeThreats = IAssignment.GetActiveThreats(targets);
if (activeThreats.Count == 0) {
Debug.LogWarning("No active threats found");
2024-09-13 22:45:25 -07:00
return assignments;
}
2024-09-13 22:45:25 -07:00
Vector3 positionToDefend = Vector3.zero;
List<ThreatInfo> threatInfos =
CalculateThreatLevels(activeThreats, positionToDefend);
// Sort ThreatInfo first by ThreatData.Status (UNASSIGNED first, then ASSIGNED)
// Within each group, order by ThreatLevel descending
threatInfos = threatInfos.OrderByDescending(t => t.ThreatData.Status == ThreatStatus.UNASSIGNED)
.ThenByDescending(t => t.ThreatLevel)
.ToList();
var assignableInterceptorsEnumerator = assignableInterceptors.GetEnumerator();
if (assignableInterceptorsEnumerator.MoveNext()) // Move to the first element
{
foreach (ThreatInfo threatInfo in threatInfos) {
assignments.Add(new IAssignment.AssignmentItem(assignableInterceptorsEnumerator.Current, threatInfo.ThreatData.Threat));
if (!assignableInterceptorsEnumerator.MoveNext()) {
break;
}
2024-09-13 22:45:25 -07:00
}
}
2024-09-13 22:45:25 -07:00
return assignments;
}
private List<ThreatInfo> CalculateThreatLevels(List<ThreatData> threatTable,
Vector3 defensePosition) {
2024-09-13 22:45:25 -07:00
List<ThreatInfo> threatInfos = new List<ThreatInfo>();
foreach (ThreatData threatData in threatTable) {
Threat threat = threatData.Threat;
float distanceToMean = Vector3.Distance(threat.transform.position, defensePosition);
float velocityMagnitude = threat.GetVelocity().magnitude;
2024-09-13 22:45:25 -07:00
// Calculate threat level based on proximity and velocity
float threatLevel = (1 / distanceToMean) * velocityMagnitude;
threatInfos.Add(new ThreatInfo(threatData, threatLevel));
2024-09-13 22:45:25 -07:00
}
// Sort threats in descending order
return threatInfos.OrderByDescending(t => t.ThreatLevel).ToList();
}
private class ThreatInfo {
public ThreatData ThreatData { get; }
2024-09-13 22:45:25 -07:00
public float ThreatLevel { get; }
public ThreatInfo(ThreatData threatData, float threatLevel) {
ThreatData = threatData;
2024-09-13 22:45:25 -07:00
ThreatLevel = threatLevel;
}
2024-09-13 22:45:25 -07:00
}
}