< Summary

Class:RunManager
Assembly:bamlab.micromissiles
File(s):/github/workspace/Assets/Scripts/Managers/RunManager.cs
Covered lines:0
Uncovered lines:87
Coverable lines:87
Total lines:139
Line coverage:0% (0 of 87)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:22
Method coverage:0% (0 of 22)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
RunManager()0%2100%
HasRunConfig()0%2100%
OnBeforeSceneLoad()0%12300%
InitializeFromRunConfig(...)0%2100%
Start()0%6200%
Awake()0%12300%
Run()0%20400%
Advance()0%42600%
RegisterSimulationStarted()0%2100%
RegisterSimulationEnded()0%6200%
TryGetCommandLineArg(...)0%2100%
GetArgValue(...)0%30500%

File(s)

/github/workspace/Assets/Scripts/Managers/RunManager.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using UnityEngine;
 4
 5// The run manager handles running the same simulation configuration multiple times.
 6// It implements the singleton pattern to ensure that only one instance exists.
 7public class RunManager : MonoBehaviour {
 8  private const string _configFlag = "--config";
 9
 010  public static RunManager Instance { get; private set; }
 11
 12  // Run configuration.
 013  public Configs.RunConfig RunConfig { get; set; }
 14
 15  // If true, the simulation is currently running.
 016  public bool IsRunning { get; private set; } = false;
 17
 018  public int RunIndex { get; private set; } = 0;
 19
 020  public int Seed { get; private set; } = 0;
 21
 022  public bool HasRunConfig() {
 023    return RunConfig != null;
 024  }
 25
 26  [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
 027  private static void OnBeforeSceneLoad() {
 028    string runConfigFile = TryGetCommandLineArg(_configFlag);
 029    if (runConfigFile == null) {
 030      return;
 31    }
 032    Configs.RunConfig runConfig = ConfigLoader.LoadRunConfig(runConfigFile);
 033    if (runConfig == null) {
 034      Debug.LogWarning(
 35          $"Failed to load run configuration from: {runConfigFile}. Application will not start batch mode.");
 036      return;
 37    }
 38
 39    // Create a game object to run coroutines.
 040    var gameObject = new GameObject("RunManager");
 041    DontDestroyOnLoad(gameObject);
 042    var runManager = gameObject.AddComponent<RunManager>();
 043    runManager.InitializeFromRunConfig(runConfig);
 044  }
 45
 046  private void InitializeFromRunConfig(Configs.RunConfig runConfig) {
 047    RunConfig = runConfig;
 048    IsRunning = false;
 049    RunIndex = 0;
 050    Seed = RunConfig.Seed;
 051  }
 52
 053  private void Start() {
 054    if (RunConfig != null) {
 055      Application.targetFrameRate = -1;
 56
 57      // Disable automatically restarting at the end of the simulation.
 058      SimManager.Instance.AutoRestartOnEnd = false;
 059      SimManager.Instance.OnSimulationStarted += RegisterSimulationStarted;
 060      SimManager.Instance.OnSimulationEnded += RegisterSimulationEnded;
 61
 062      StartCoroutine(Run());
 063    }
 064  }
 65
 066  private void Awake() {
 067    if (Instance != null && Instance != this) {
 068      Destroy(gameObject);
 069      return;
 70    }
 071    Instance = this;
 072    DontDestroyOnLoad(gameObject);
 073  }
 74
 075  private IEnumerator Run() {
 076    if (RunConfig.NumRuns == 0) {
 077      yield break;
 78    }
 79
 80    // Allow one frame for initialization to finish.
 081    yield return null;
 82
 83    // Seed the random number generator.
 084    UnityEngine.Random.InitState(Seed);
 85
 086    Debug.Log(
 87        $"Starting run {RunIndex + 1} with seed {Seed} and simulation config {RunConfig.SimulationConfigFile}.");
 088    SimManager.Instance.LoadNewSimulationConfig(RunConfig.SimulationConfigFile);
 089  }
 90
 091  private IEnumerator Advance() {
 92    // Allow one frame for cleanup to finish, such as simulation monitoring.
 093    yield return null;
 94
 095    ++RunIndex;
 096    if (RunIndex >= RunConfig.NumRuns) {
 097      Debug.Log($"Completed run {RunConfig.Name} with {RunConfig.NumRuns} runs.");
 098      SimManager.Instance.QuitSimulation();
 099      yield break;
 100    }
 0101    Seed += RunConfig.SeedStride;
 102
 0103    yield return Run();
 0104  }
 105
 0106  private void RegisterSimulationStarted() {
 0107    IsRunning = true;
 0108  }
 109
 0110  private void RegisterSimulationEnded() {
 0111    if (!IsRunning) {
 0112      return;
 113    }
 0114    IsRunning = false;
 0115    StartCoroutine(Advance());
 0116  }
 117
 0118  private static string TryGetCommandLineArg(string name) {
 0119    try {
 0120      var args = Environment.GetCommandLineArgs();
 0121      return GetArgValue(args, name);
 0122    } catch (Exception e) {
 0123      Debug.LogWarning($"Failed to parse command line args: {e.Message}");
 0124      return null;
 125    }
 0126  }
 127
 0128  private static string GetArgValue(string[] args, string name) {
 0129    for (int i = 0; i < args.Length; ++i) {
 0130      if (args[i].Equals(name, StringComparison.OrdinalIgnoreCase) && i + 1 < args.Length) {
 0131        return args[i + 1];
 132      }
 0133      if (args[i].StartsWith(name + "=", StringComparison.OrdinalIgnoreCase)) {
 0134        return args[i].Substring(name.Length + 1);
 135      }
 0136    }
 0137    return null;
 0138  }
 139}