< Summary

Class:UIManager
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/UI/UIManager.cs
Covered lines:110
Uncovered lines:60
Coverable lines:170
Total lines:254
Line coverage:64.7% (110 of 170)
Covered branches:0
Total branches:0
Covered methods:18
Total methods:30
Method coverage:60% (18 of 30)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
UIManager()0%110100%
Awake()0%2.032080%
Start()0%110100%
LogAction(...)0%110100%
LogActionMessage(...)0%110100%
LogActionWarning(...)0%2100%
LogActionError(...)0%2100%
ToggleConfigSelectorPanel()0%2100%
SetupConfigSelectorPanel()0%110100%
PopulateConfigDropdown()0%220100%
LoadSelectedConfig()0%2100%
ToggleUIMode()0%12300%
SetUIMode(...)0%110100%
GetUIMode()0%110100%
SetAgentPanelText(...)0%2100%
GetSwarmPanelText()0%2100%
UpdateSwarmPanel()0%6200%
UpdateSimTimeText()0%220100%
UpdateTotalCostText()0%2.032080%
FormatCost(...)0%4.434070%
RegisterSimulationEnded()0%110100%
UpdateSummaryText()0%110100%
RegisterNewInterceptor(...)0%2100%
RegisterNewThreat(...)0%110100%
RegisterAgentTerminated(...)0%12300%
RegisterInterceptorHit(...)0%2100%
RegisterInterceptorMiss(...)0%2100%
Update()0%110100%

File(s)

/github/workspace/Assets/Scripts/UI/UIManager.cs

#LineLine coverage
 1using System.Collections;
 2using System.Collections.Generic;
 3using System.IO;
 4using UnityEngine;
 5using UnityEngine.UI;
 6using TMPro;
 7using System;
 8
 9public class UIManager : MonoBehaviour {
 9710  public static UIManager Instance { get; private set; }
 11
 12  [SerializeField]
 13  [Tooltip("The UI panel that renders the tactical view for TACTICAL mode")]
 14  private GameObject _tacticalPanel;
 15
 16  [SerializeField]
 17  [Tooltip("The UI panel that renders the camera view for THREE_DIMENSIONAL mode")]
 18  private GameObject _cameraPanel;
 19
 20  [SerializeField]
 21
 22  private GameObject _configSelectorPanel;
 23  private TMP_Dropdown _configDropdown;
 24  public TextMeshProUGUI agentPanelText;
 25  public TextMeshProUGUI simTimeText;
 26  public TextMeshProUGUI interceptorCostText;
 27  public TextMeshProUGUI threatCostText;
 28  public TextMeshProUGUI netCostText;
 29
 30  public TextMeshProUGUI intrHitTextHandle;
 31  public TextMeshProUGUI intrMissTextHandle;
 32  public TextMeshProUGUI intrRemainTextHandle;
 33  public TextMeshProUGUI thrtRemainTextHandle;
 34
 35  public TextMeshProUGUI actionMessageTextHandle;
 36  public TextMeshProUGUI pActionMessageTextHandle;
 37  public TextMeshProUGUI ppActionMessageTextHandle;
 38  public TextMeshProUGUI ppppActionMessageTextHandle;
 39  public TextMeshProUGUI pppppActionMessageTextHandle;
 40
 141  private int _intrHitCount = 0;
 142  private int _intrMissCount = 0;
 143  private int _intrRemainCount = 0;
 144  private int _thrtRemainCount = 0;
 45  public TMP_FontAsset GlobalFont;
 46
 147  private UIMode curMode = UIMode.THREE_DIMENSIONAL;
 48
 149  void Awake() {
 150    if (Instance == null)
 151      Instance = this;
 52    else
 053      Destroy(gameObject);
 154  }
 55
 156  void Start() {
 157    SetUIMode(UIMode.THREE_DIMENSIONAL);
 158    _configSelectorPanel.SetActive(false);
 159    SetupConfigSelectorPanel();
 160    SimManager.Instance.OnNewInterceptor += RegisterNewInterceptor;
 161    SimManager.Instance.OnNewThreat += RegisterNewThreat;
 162    SimManager.Instance.OnSimulationEnded += RegisterSimulationEnded;
 163    actionMessageTextHandle.text = "";
 164    pActionMessageTextHandle.text = "";
 165    ppActionMessageTextHandle.text = "";
 166    ppppActionMessageTextHandle.text = "";
 167    pppppActionMessageTextHandle.text = "";
 168  }
 69
 3970  public void LogAction(string message, Color color) {
 71    // Shift existing messages to older slots with faded colors.
 3972    pppppActionMessageTextHandle.text = ppppActionMessageTextHandle.text;
 3973    pppppActionMessageTextHandle.color =
 74        ppppActionMessageTextHandle.color * 0.8f;  // Fade color by 20%.
 75
 3976    ppppActionMessageTextHandle.text = ppActionMessageTextHandle.text;
 3977    ppppActionMessageTextHandle.color = ppActionMessageTextHandle.color * 0.85f;
 78
 3979    ppActionMessageTextHandle.text = pActionMessageTextHandle.text;
 3980    ppActionMessageTextHandle.color = pActionMessageTextHandle.color * 0.85f;
 81
 3982    pActionMessageTextHandle.text = actionMessageTextHandle.text;
 3983    pActionMessageTextHandle.color = actionMessageTextHandle.color * 0.9f;
 84
 85    // Set new message.
 3986    actionMessageTextHandle.text = message;
 3987    actionMessageTextHandle.color = color;
 3988  }
 89
 3990  public void LogActionMessage(string message) {
 3991    LogAction(message, Color.white);
 3992  }
 93
 094  public void LogActionWarning(string message) {
 095    LogAction(message, Color.yellow);
 096  }
 97
 098  public void LogActionError(string message) {
 099    LogAction(message, Color.red);
 0100  }
 101
 0102  public void ToggleConfigSelectorPanel() {
 0103    _configSelectorPanel.SetActive(!_configSelectorPanel.activeSelf);
 0104  }
 105
 1106  private void SetupConfigSelectorPanel() {
 1107    _configSelectorPanel.GetComponentInChildren<Button>().onClick.AddListener(
 0108        delegate { LoadSelectedConfig(); });
 1109    _configDropdown = _configSelectorPanel.GetComponentInChildren<TMP_Dropdown>();
 1110    PopulateConfigDropdown();
 1111  }
 112
 1113  private void PopulateConfigDropdown() {
 1114    _configDropdown.ClearOptions();
 1115    string configPath = ConfigLoader.GetStreamingAssetsFilePath("Configs/Simulations");
 1116    string[] configFiles = Directory.GetFiles(configPath, "*.pbtxt");
 117
 1118    List<string> configFileNames = new List<string>();
 30119    foreach (string configFile in configFiles) {
 9120      configFileNames.Add(Path.GetFileName(configFile));
 9121    }
 1122    _configDropdown.AddOptions(configFileNames);
 1123  }
 0124  private void LoadSelectedConfig() {
 0125    string selectedConfig = _configDropdown.options[_configDropdown.value].text;
 0126    SimManager.Instance.LoadNewConfig(selectedConfig);
 0127    _configSelectorPanel.SetActive(false);
 0128  }
 129
 0130  public void ToggleUIMode() {
 0131    SetUIMode(curMode == UIMode.THREE_DIMENSIONAL ? UIMode.TACTICAL : UIMode.THREE_DIMENSIONAL);
 0132  }
 133
 1134  public void SetUIMode(UIMode mode) {
 1135    curMode = mode;
 1136    _cameraPanel.SetActive(mode == UIMode.THREE_DIMENSIONAL);
 1137    _tacticalPanel.SetActive(mode == UIMode.TACTICAL);
 1138  }
 139
 56140  public UIMode GetUIMode() {
 56141    return curMode;
 56142  }
 143
 0144  public void SetAgentPanelText(string text) {
 0145    agentPanelText.text = text;
 0146  }
 147
 0148  public string GetSwarmPanelText() {
 0149    return agentPanelText.text;
 0150  }
 151
 0152  private void UpdateSwarmPanel() {
 0153    string agentPanelText = "";
 0154    foreach (Agent agent in SimManager.Instance.GetActiveAgents()) {
 0155      string jobText = agent.name + "| Phase: " + agent.GetFlightPhase().ToString();
 0156      agentPanelText += jobText + "\n";
 0157    }
 0158    SetAgentPanelText(agentPanelText);
 0159  }
 160
 28161  private void UpdateSimTimeText() {
 28162    simTimeText.text =
 163        "Elapsed Sim Time: " + SimManager.Instance.GetElapsedSimulationTime().ToString("F2");
 28164    float expectedSimTimeAdvance = Time.unscaledDeltaTime * Time.timeScale;
 28165    float actualSimTimeAdvance = Time.deltaTime;
 166
 167    // Allow a small epsilon to account for floating-point precision errors.
 47168    if (actualSimTimeAdvance < expectedSimTimeAdvance - 0.001f) {
 19169      simTimeText.text += "\nThrottling time to meet physics rate";
 19170    }
 28171  }
 172
 28173  private void UpdateTotalCostText() {
 28174    double interceptorCost = SimManager.Instance.GetCostLaunchedInterceptors();
 28175    double threatCost = SimManager.Instance.GetCostDestroyedThreats();
 28176    double netCost = interceptorCost - threatCost;
 177
 28178    interceptorCostText.text = $"Interceptors\n(launched)\n${FormatCost(interceptorCost)}";
 28179    threatCostText.text = $"Threats\n(destroyed)\n${FormatCost(threatCost)}";
 28180    netCostText.text = $"Cost\ndifference\n${FormatCost(netCost)}";
 28181    if (netCost < 0) {
 0182      netCostText.color = Color.green;
 28183    } else {
 28184      netCostText.color = Color.red;
 28185    }
 28186  }
 187
 84188  private string FormatCost(double cost) {
 84189    double absCost = Math.Abs(cost);
 84190    if (absCost >= 1e9)
 0191      return $"{cost / 1e9:F2}B";
 84192    if (absCost >= 1e6)
 0193      return $"{cost / 1e6:F2}M";
 84194    if (absCost >= 1e3)
 0195      return $"{cost / 1e3:F2}k";
 84196    return $"{cost:F2}";
 84197  }
 198
 9199  private void RegisterSimulationEnded() {
 9200    _intrRemainCount = 0;
 9201    _thrtRemainCount = 0;
 9202    _intrHitCount = 0;
 9203    _intrMissCount = 0;
 9204    UpdateSummaryText();
 9205  }
 206
 764207  private void UpdateSummaryText() {
 764208    intrRemainTextHandle.text = _intrRemainCount.ToString();
 764209    thrtRemainTextHandle.text = _thrtRemainCount.ToString();
 764210    intrHitTextHandle.text = _intrHitCount.ToString();
 764211    intrMissTextHandle.text = _intrMissCount.ToString();
 764212  }
 213
 0214  private void RegisterNewInterceptor(Interceptor interceptor) {
 0215    ++_intrRemainCount;
 0216    interceptor.OnInterceptHit += RegisterInterceptorHit;
 0217    interceptor.OnInterceptMiss += RegisterInterceptorMiss;
 0218    interceptor.OnTerminated += RegisterAgentTerminated;
 0219    UpdateSummaryText();
 0220  }
 221
 755222  private void RegisterNewThreat(Threat threat) {
 755223    ++_thrtRemainCount;
 755224    threat.OnTerminated += RegisterAgentTerminated;
 755225    UpdateSummaryText();
 755226  }
 227
 0228  private void RegisterAgentTerminated(Agent agent) {
 0229    if (agent is Interceptor) {
 0230      --_intrRemainCount;
 0231    } else if (agent is Threat) {
 0232      --_thrtRemainCount;
 0233    }
 0234    UpdateSummaryText();
 0235  }
 236
 0237  private void RegisterInterceptorHit(Interceptor interceptor, Threat threat) {
 0238    ++_intrHitCount;
 0239    UpdateSummaryText();
 0240  }
 241
 0242  private void RegisterInterceptorMiss(Interceptor interceptor, Threat threat) {
 0243    ++_intrMissCount;
 0244    UpdateSummaryText();
 0245  }
 246
 28247  void Update() {
 248    // UpdateSwarmPanel();
 28249    UpdateSimTimeText();
 28250    UpdateTotalCostText();
 28251  }
 252}
 253
 254public enum UIMode { THREE_DIMENSIONAL, TACTICAL }