< Summary

Class:ThreatAssignment
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/Assignment/ThreatAssignment.cs
Covered lines:38
Uncovered lines:4
Coverable lines:42
Total lines:80
Line coverage:90.4% (38 of 42)
Covered branches:0
Total branches:0
Covered methods:5
Total methods:5
Method coverage:100% (5 of 5)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Assign(...)0%8.468080.65%
CalculateThreatLevels(...)0%330100%
ThreatInfo(...)0%110100%

File(s)

/github/workspace/Assets/Scripts/Assignment/ThreatAssignment.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using Unity.VisualScripting;
 5using UnityEngine;
 6using System.Diagnostics.Contracts;
 7
 8// The threat assignment class assigns interceptors to the targets based
 9// on the threat level of the targets.
 10public class ThreatAssignment : IAssignment {
 11  // Assign a target to each interceptor that has not been assigned a target yet.
 12  [Pure]
 13  public IEnumerable<IAssignment.AssignmentItem> Assign(in IReadOnlyList<Interceptor> interceptors,
 214                                                        in IReadOnlyList<ThreatData> targets) {
 215    List<IAssignment.AssignmentItem> assignments = new List<IAssignment.AssignmentItem>();
 16
 217    List<Interceptor> assignableInterceptors = IAssignment.GetAssignableInterceptors(interceptors);
 218    if (assignableInterceptors.Count == 0) {
 019      Debug.LogWarning("No assignable interceptors found");
 020      return assignments;
 21    }
 22
 223    List<ThreatData> activeThreats = IAssignment.GetActiveThreats(targets);
 224    if (activeThreats.Count == 0) {
 025      Debug.LogWarning("No active threats found");
 026      return assignments;
 27    }
 28
 229    Vector3 positionToDefend = Vector3.zero;
 230    List<ThreatInfo> threatInfos = CalculateThreatLevels(activeThreats, positionToDefend);
 31
 32    // Sort ThreatInfo first by ThreatData.Status (UNASSIGNED first, then ASSIGNED)
 33    // Within each group, order by ThreatLevel descending
 734    threatInfos = threatInfos.OrderBy(t => t.ThreatData.assignedInterceptorCount)
 535                      .ThenByDescending(t => t.ThreatLevel)
 36                      .ToList();
 37
 238    var assignableInterceptorsEnumerator = assignableInterceptors.GetEnumerator();
 239    if (assignableInterceptorsEnumerator.MoveNext())  // Move to the first element
 240    {
 2041      foreach (ThreatInfo threatInfo in threatInfos) {
 542        assignments.Add(new IAssignment.AssignmentItem(assignableInterceptorsEnumerator.Current,
 43                                                       threatInfo.ThreatData.Threat));
 644        if (!assignableInterceptorsEnumerator.MoveNext()) {
 145          break;
 46        }
 447      }
 248    }
 249    return assignments;
 250  }
 51
 52  private List<ThreatInfo> CalculateThreatLevels(List<ThreatData> threatTable,
 253                                                 Vector3 defensePosition) {
 254    List<ThreatInfo> threatInfos = new List<ThreatInfo>();
 55
 2156    foreach (ThreatData threatData in threatTable) {
 557      Threat threat = threatData.Threat;
 558      float distanceToMean = Vector3.Distance(threat.transform.position, defensePosition);
 559      float velocityMagnitude = threat.GetVelocity().magnitude;
 60
 61      // Calculate threat level based on proximity and velocity
 562      float threatLevel = (1 / distanceToMean) * velocityMagnitude;
 63
 564      threatInfos.Add(new ThreatInfo(threatData, threatLevel));
 565    }
 66
 67    // Sort threats in descending order
 768    return threatInfos.OrderByDescending(t => t.ThreatLevel).ToList();
 269  }
 70
 71  private class ThreatInfo {
 1072    public ThreatData ThreatData { get; }
 1073    public float ThreatLevel { get; }
 74
 1075    public ThreatInfo(ThreatData threatData, float threatLevel) {
 576      ThreatData = threatData;
 577      ThreatLevel = threatLevel;
 578    }
 79  }
 80}