< Summary

Class:ThreatAssignment
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/Assignment/ThreatAssignment.cs
Covered lines:7
Uncovered lines:35
Coverable lines:42
Total lines:80
Line coverage:16.6% (7 of 42)
Covered branches:0
Total branches:0
Covered methods:1
Total methods:5
Method coverage:20% (1 of 5)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Assign(...)0%34.138025.81%
CalculateThreatLevels(...)0%12300%
ThreatInfo(...)0%2100%

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,
 114                                                        in IReadOnlyList<ThreatData> targets) {
 115    List<IAssignment.AssignmentItem> assignments = new List<IAssignment.AssignmentItem>();
 16
 117    List<Interceptor> assignableInterceptors = IAssignment.GetAssignableInterceptors(interceptors);
 218    if (assignableInterceptors.Count == 0) {
 119      Debug.LogWarning("No assignable interceptors found");
 120      return assignments;
 21    }
 22
 023    List<ThreatData> activeThreats = IAssignment.GetActiveThreats(targets);
 024    if (activeThreats.Count == 0) {
 025      Debug.LogWarning("No active threats found");
 026      return assignments;
 27    }
 28
 029    Vector3 positionToDefend = Vector3.zero;
 030    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
 034    threatInfos = threatInfos.OrderBy(t => t.ThreatData.assignedInterceptorCount)
 035                      .ThenByDescending(t => t.ThreatLevel)
 36                      .ToList();
 37
 038    var assignableInterceptorsEnumerator = assignableInterceptors.GetEnumerator();
 039    if (assignableInterceptorsEnumerator.MoveNext())  // Move to the first element
 040    {
 041      foreach (ThreatInfo threatInfo in threatInfos) {
 042        assignments.Add(new IAssignment.AssignmentItem(assignableInterceptorsEnumerator.Current,
 43                                                       threatInfo.ThreatData.Threat));
 044        if (!assignableInterceptorsEnumerator.MoveNext()) {
 045          break;
 46        }
 047      }
 048    }
 049    return assignments;
 150  }
 51
 52  private List<ThreatInfo> CalculateThreatLevels(List<ThreatData> threatTable,
 053                                                 Vector3 defensePosition) {
 054    List<ThreatInfo> threatInfos = new List<ThreatInfo>();
 55
 056    foreach (ThreatData threatData in threatTable) {
 057      Threat threat = threatData.Threat;
 058      float distanceToMean = Vector3.Distance(threat.transform.position, defensePosition);
 059      float velocityMagnitude = threat.GetVelocity().magnitude;
 60
 61      // Calculate threat level based on proximity and velocity
 062      float threatLevel = (1 / distanceToMean) * velocityMagnitude;
 63
 064      threatInfos.Add(new ThreatInfo(threatData, threatLevel));
 065    }
 66
 67    // Sort threats in descending order
 068    return threatInfos.OrderByDescending(t => t.ThreatLevel).ToList();
 069  }
 70
 71  private class ThreatInfo {
 072    public ThreatData ThreatData { get; }
 073    public float ThreatLevel { get; }
 74
 075    public ThreatInfo(ThreatData threatData, float threatLevel) {
 076      ThreatData = threatData;
 077      ThreatLevel = threatLevel;
 078    }
 79  }
 80}