public static async Task <IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest request, ILogger log) { if (request == null) { return(new BadRequestResult()); } if (!request.Query.ContainsKey(NumberOfGamesParameter) || !int.TryParse(request.Query[NumberOfGamesParameter], out var numberOfGames) || numberOfGames <= 0) { return(new BadRequestObjectResult($"Query parameter {NumberOfGamesParameter} must be supplied and have an integer value greater than zero.")); } if (!request.Query.ContainsKey(SwitchDoorParameter) || !bool.TryParse(request.Query[SwitchDoorParameter], out var switchDoor)) { return(new BadRequestObjectResult($"Query parameter {SwitchDoorParameter} must be supplied and have a boolean value.")); } log.LogInformation($"Azure Function \"Simulation\" performing simulation of {numberOfGames} games with strategy{(switchDoor ? " " : " do not ")}switch door."); var simulation = new InformedHostSimulation(); var result = simulation.Run(numberOfGames, switchDoor); var response = new SimulationResponse(result); return(new JsonResult(response)); }
public void SimulateModelInvalid() { var jsonMessage = SimulationModelData.fixSampleScenarioInvalid; IList <string> errorMessage = new List <string> { "Invalid type. Expected String but got Null. Path 'computeInfo[0].sentTime', line 1, position 271.", "Invalid type. Expected String but got Null. Path 'computeInfo[3].receivedTime', line 1, position 513.", "Invalid type. Expected String but got Null. Path 'computeInfo[3].sentTime', line 1, position 529.", "Invalid type. Expected Object but got Null. Path 'project', line 1, position 647.", "Invalid type. Expected Array but got Null. Path 'population.endpointModel[1].inputData', line 1, position 1214.", "Invalid type. Expected String but got Null. Path 'design.hypothesis', line 1, position 1919." }; var expectedResult = new SimulationResponse() { ErrorMessages = errorMessage, QueueMessage = null }; var simulationService = new Mock <ISimulationModelService>(); simulationService.Setup(service => service.SimulateModel("FixSampleJsonSchema.json", JsonConvert.SerializeObject(jsonMessage))).Returns(expectedResult); var actualResult = simulationService.Object.SimulateModel("FixSampleJsonSchema.json", JsonConvert.SerializeObject(jsonMessage)); Assert.NotNull(actualResult); Assert.Equal(expectedResult.ErrorMessages, actualResult.ErrorMessages); Assert.Equal(expectedResult.QueueMessage, actualResult.QueueMessage); }
public static void StopAsync() { Debug.Assert(Instance.CurrentSimulation != null); if (Instance.masterManager != null) { Instance.masterManager.BroadcastSimulationStop(); } Instance.Actions.Enqueue(() => { var simulation = Instance.CurrentSimulation; using (var db = DatabaseManager.Open()) { try { simulation.Status = "Stopping"; NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); if (ApiManager.Instance != null) { SceneManager.MoveGameObjectToScene(ApiManager.Instance.gameObject, SceneManager.GetActiveScene()); } SIM.LogSimulation(SIM.Simulation.ApplicationClick, "Exit"); var loader = SceneManager.LoadSceneAsync(Instance.LoaderScene); loader.completed += op => { if (op.isDone) { AssetBundle.UnloadAllAssetBundles(false); Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.START); simulation.Status = "Valid"; NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); Instance.CurrentSimulation = null; if (Instance.masterManager != null) { Instance.masterManager.StopConnection(); } } }; } catch (Exception ex) { Debug.Log($"Failed to stop '{simulation.Name}' simulation"); Debug.LogException(ex); // NOTE: In case of failure we have to update Simulation state simulation.Status = "Invalid"; simulation.Error = ex.Message; db.Update(simulation); // TODO: take ex.Message and append it to response here NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); } } }); }
public async Task <SimulationResult> WaitForResult(SimulationResponse response, int pollSeconds) { while (response.Status == InvocationStatus.InProgress) { await Task.Delay(TimeSpan.FromSeconds(pollSeconds)); response = await _api.Skills.SimulationResult(_locale.SkillID, _locale.Stage.Stage.Value, response.Id); } return(response.Result); }
public void SimulateModelValid() { object jsonMessage = SimulationModelData.fixSampleScenarioValid; var expectedResult = new SimulationResponse() { ErrorMessages = null, QueueMessage = @"{'msgVersion':1.0,'msgType':'engine','msgId':123456789,'target':{'location':'//regstry.docker.com/cytel/','name':'2-arm-TimeToEvent-GroupSequential','id':123,'version':1.0},'computeInfo':[{'stage':'SimulationService','receivedTime':'20200402-12:23:31.342','sentTime':'20200402-12:23:33.348'},{'stage':'InputQueue','receivedTime':'20200402-12:23:31.342','sentTime':'20200402-12:23:33.348'},{'stage':'MonolithEngine','receivedTime':'20200402-12:23:33.349','sentTime':'20200402-12:23:53.350'},{'stage':'OutputQueue','receivedTime':'20200402-12:23:53.352','sentTime':'20200402-12:23:53.369'},{'stage':'StorageService','receivedTime':'20200402-12:23:31.342','sentTime':'20200402-12:23:33.348'}],'project':{'scenarioId':'bd57e927227311eaa3270b9e81dab55e','projectName':'Project Name','timeUnit':'Month','controlArm':'Salvage Chemo','treatmentArm':'Quizartinib','numberOfSim':10000,'simSeed':1234567},'population':{'populationId':'bd57e92722731we1ea3270b9e81dab55e','name':'Population Name','virtualPopulationSize':10000,'endpointModel':[{'name':'Overall Survival','endpoint':'Overall Survival','type':'Time to Event','modelName':'Exponential','inputMethod':'Median Survival Time','inputData':[{'control':0.0,'treatment':0.0,'hazardRatio':0.0},{'control':0.0,'treatment':0.0,'hazardRatio':0.0}]},{'name':'Progress Free Survival','endpoint':'Progress Free Survival','type':'Time to Event','modelName':'Exponential','inputMethod':'Median Survival Time','inputData':[{'control':0.0,'treatment':0.0,'hazardRatio':0.0},{'control':0.0,'treatment':0.0,'hazardRatio':0.0}]}],'dropoutRateModel':{'modelName':'Probability of Dropout','inputMethod':'Exponential','inputData':[{'byTime':10.0,'control':0.0,'treatment':0.0},{'byTime':12.0,'control':0.0,'treatment':0.0}]}},'enrollment':{'name':'Enrollment Name 1','inputMethod':'Accrual Rate','distribution':'Uniform','sites':[{'geography':'USA','siteInititationTime':0,'avgPatientsEnrolled':20,'enrollmentCap':33.0},{'geography':'UK','siteInititationTime':0,'avgPatientsEnrolled':22,'enrollmentCap':44.0}],'enrollmentId':'fg57e92722731we1ea4570b9e81dab55e'},'design':{'name':'Name of Design','primaryEndpoint':'Overall Survival','numberOfArms':2,'regulatoryRiskAssessment':'Low','statisticalDesign':'Fixed Sample','hypothesis':'Superiority','numberOfEvents':120,'sampleSize':400,'allocationRatio':3.0,'subjectsAreFollowedType':'Fixed Period','subjectsAreFollowedPeriod':3,'type1Error':0.0,'testStatistics':'Logrank','testType':'1-Sided','tailType':'Left Tail','criticalPoint':-1.0},'simulationResults':{}}" }; var simulationService = new Mock <ISimulationModelService>(); simulationService.Setup(service => service.SimulateModel("FixSampleJsonSchema.json", JsonConvert.SerializeObject(jsonMessage))) .Returns(expectedResult); var actualResult = simulationService.Object.SimulateModel("FixSampleJsonSchema.json", JsonConvert.SerializeObject(jsonMessage)); Assert.NotNull(actualResult); Assert.Equal(expectedResult.ErrorMessages, actualResult.ErrorMessages); Assert.Equal(expectedResult.QueueMessage, actualResult.QueueMessage); }
static void SetupScene(SimulationModel simulation) { Dictionary <string, GameObject> cachedVehicles = new Dictionary <string, GameObject>(); using (var db = DatabaseManager.Open()) { try { foreach (var agentConfig in Instance.SimConfig.Agents) { var bundlePath = agentConfig.AssetBundle; AssetBundle textureBundle = null; AssetBundle vehicleBundle = null; if (cachedVehicles.ContainsKey(agentConfig.Name)) { agentConfig.Prefab = cachedVehicles[agentConfig.Name]; continue; } using (ZipFile zip = new ZipFile(bundlePath)) { Manifest manifest; ZipEntry entry = zip.GetEntry("manifest"); using (var ms = zip.GetInputStream(entry)) { int streamSize = (int)entry.Size; byte[] buffer = new byte[streamSize]; streamSize = ms.Read(buffer, 0, streamSize); manifest = new Deserializer().Deserialize <Manifest>(Encoding.UTF8.GetString(buffer, 0, streamSize)); } if (manifest.bundleFormat != BundleConfig.VehicleBundleFormatVersion) { zip.Close(); // TODO: proper exception throw new ZipException("BundleFormat version mismatch"); } var texStream = zip.GetInputStream(zip.GetEntry($"{manifest.bundleGuid}_vehicle_textures")); textureBundle = AssetBundle.LoadFromStream(texStream, 0, 1 << 20); string platform = SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows ? "windows" : "linux"; var mapStream = zip.GetInputStream(zip.GetEntry($"{manifest.bundleGuid}_vehicle_main_{platform}")); vehicleBundle = AssetBundle.LoadFromStream(mapStream, 0, 1 << 20); if (vehicleBundle == null) { throw new Exception($"Failed to load '{agentConfig.Name}' vehicle asset bundle"); } try { var vehicleAssets = vehicleBundle.GetAllAssetNames(); if (vehicleAssets.Length != 1) { throw new Exception($"Unsupported '{agentConfig.Name}' vehicle asset bundle, only 1 asset expected"); } // TODO: make this async if (!AssetBundle.GetAllLoadedAssetBundles().Contains(textureBundle)) { textureBundle?.LoadAllAssets(); } agentConfig.Prefab = vehicleBundle.LoadAsset <GameObject>(vehicleAssets[0]); cachedVehicles.Add(agentConfig.Name, agentConfig.Prefab); } finally { textureBundle?.Unload(false); vehicleBundle.Unload(false); } } } var sim = CreateSimulationManager(); Instance.CurrentSimulation = simulation; Instance.CurrentSimulation.Status = "Running"; // Notify WebUI simulation is running NotificationManager.SendNotification("simulation", SimulationResponse.Create(Loader.Instance.CurrentSimulation), Loader.Instance.CurrentSimulation.Owner); if (Instance.SimConfig.Clusters.Length == 0) { // Flash main window to let user know simulation is ready WindowFlasher.Flash(); } } catch (ZipException ex) { Debug.Log($"Failed to start '{simulation.Name}' simulation - out of date asset bundles"); Debug.LogException(ex); // NOTE: In case of failure we have to update Simulation state simulation.Status = "Invalid"; simulation.Error = "Out of date Vehicle AssetBundle. Please check content website for updated bundle or rebuild the bundle."; db.Update(simulation); // TODO: take ex.Message and append it to response here NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); ResetLoaderScene(); } catch (Exception ex) { Debug.Log($"Failed to start '{simulation.Name}' simulation"); Debug.LogException(ex); // NOTE: In case of failure we have to update Simulation state simulation.Status = "Invalid"; simulation.Error = ex.Message; db.Update(simulation); // TODO: take ex.Message and append it to response here NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); ResetLoaderScene(); } } }
public static void StartAsync(SimulationModel simulation) { Debug.Assert(Instance.CurrentSimulation == null); Instance.Actions.Enqueue(() => { using (var db = DatabaseManager.Open()) { AssetBundle textureBundle = null; AssetBundle mapBundle = null; try { if (Config.Headless && (simulation.Headless.HasValue && !simulation.Headless.Value)) { throw new Exception("Simulator is configured to run in headless mode, only headless simulations are allowed"); } simulation.Status = "Starting"; NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.PROGRESS); Instance.SimConfig = new SimulationConfig() { Name = simulation.Name, Clusters = db.Single <ClusterModel>(simulation.Cluster).Ips.Split(',').Where(c => c != "127.0.0.1").ToArray(), ClusterName = db.Single <ClusterModel>(simulation.Cluster).Name, ApiOnly = simulation.ApiOnly.GetValueOrDefault(), Headless = simulation.Headless.GetValueOrDefault(), Interactive = simulation.Interactive.GetValueOrDefault(), TimeOfDay = simulation.TimeOfDay.GetValueOrDefault(new DateTime(1980, 3, 24, 12, 0, 0)), Rain = simulation.Rain.GetValueOrDefault(), Fog = simulation.Fog.GetValueOrDefault(), Wetness = simulation.Wetness.GetValueOrDefault(), Cloudiness = simulation.Cloudiness.GetValueOrDefault(), UseTraffic = simulation.UseTraffic.GetValueOrDefault(), UsePedestrians = simulation.UsePedestrians.GetValueOrDefault(), Seed = simulation.Seed, }; if (simulation.Vehicles == null || simulation.Vehicles.Length == 0 || simulation.ApiOnly.GetValueOrDefault()) { Instance.SimConfig.Agents = Array.Empty <AgentConfig>(); } else { Instance.SimConfig.Agents = simulation.Vehicles.Select(v => { var vehicle = db.SingleOrDefault <VehicleModel>(v.Vehicle); var config = new AgentConfig() { Name = vehicle.Name, Url = vehicle.Url, AssetBundle = vehicle.LocalPath, Connection = v.Connection, Sensors = vehicle.Sensors, }; if (!string.IsNullOrEmpty(vehicle.BridgeType)) { config.Bridge = Config.Bridges.Find(bridge => bridge.Name == vehicle.BridgeType); if (config.Bridge == null) { throw new Exception($"Bridge {vehicle.BridgeType} not found"); } } return(config); }).ToArray(); } // load environment if (Instance.SimConfig.ApiOnly) { var api = Instantiate(Instance.ApiManagerPrefab); api.name = "ApiManager"; Instance.CurrentSimulation = simulation; // ready to go! Instance.CurrentSimulation.Status = "Running"; NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.READY); } else { var mapModel = db.Single <MapModel>(simulation.Map); var mapBundlePath = mapModel.LocalPath; mapBundle = null; textureBundle = null; ZipFile zip = new ZipFile(mapBundlePath); { string manfile; ZipEntry entry = zip.GetEntry("manifest"); using (var ms = zip.GetInputStream(entry)) { int streamSize = (int)entry.Size; byte[] buffer = new byte[streamSize]; streamSize = ms.Read(buffer, 0, streamSize); manfile = Encoding.UTF8.GetString(buffer); } Manifest manifest = new Deserializer().Deserialize <Manifest>(manfile); if (manifest.bundleFormat != BundleConfig.MapBundleFormatVersion) { zip.Close(); // TODO: proper exception throw new ZipException("BundleFormat version mismatch"); } if (zip.FindEntry($"{manifest.bundleGuid}_environment_textures", false) != -1) { var texStream = zip.GetInputStream(zip.GetEntry($"{manifest.bundleGuid}_environment_textures")); textureBundle = AssetBundle.LoadFromStream(texStream, 0, 1 << 20); } string platform = SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows ? "windows" : "linux"; var mapStream = zip.GetInputStream(zip.GetEntry($"{manifest.bundleGuid}_environment_main_{platform}")); mapBundle = AssetBundle.LoadFromStream(mapStream, 0, 1 << 20); if (mapBundle == null) { throw new Exception($"Failed to load environment from '{mapModel.Name}' asset bundle"); } textureBundle?.LoadAllAssets(); var scenes = mapBundle.GetAllScenePaths(); if (scenes.Length != 1) { throw new Exception($"Unsupported environment in '{mapModel.Name}' asset bundle, only 1 scene expected"); } var sceneName = Path.GetFileNameWithoutExtension(scenes[0]); Instance.SimConfig.MapName = sceneName; Instance.SimConfig.MapUrl = mapModel.Url; var isMasterSimulation = Instance.SimConfig.Clusters.Length > 0; var loader = SceneManager.LoadSceneAsync(sceneName, isMasterSimulation? LoadSceneMode.Additive : LoadSceneMode.Single); loader.completed += op => { if (op.isDone) { if (isMasterSimulation) { SceneManager.SetActiveScene(SceneManager.GetSceneByName(sceneName)); } textureBundle?.Unload(false); mapBundle.Unload(false); zip.Close(); SetupScene(simulation); } }; } } } catch (ZipException ex) { Debug.Log($"Failed to start '{simulation.Name}' simulation"); Debug.LogException(ex); // NOTE: In case of failure we have to update Simulation state simulation.Status = "Invalid"; simulation.Error = "Out of date Map AssetBundle. Please check content website for updated bundle or rebuild the bundle."; db.Update(simulation); if (SceneManager.GetActiveScene().name != Instance.LoaderScene) { SceneManager.LoadScene(Instance.LoaderScene); } textureBundle?.Unload(false); mapBundle?.Unload(false); AssetBundle.UnloadAllAssetBundles(true); Instance.CurrentSimulation = null; // TODO: take ex.Message and append it to response here NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); } catch (Exception ex) { Debug.Log($"Failed to start '{simulation.Name}' simulation"); Debug.LogException(ex); // NOTE: In case of failure we have to update Simulation state simulation.Status = "Invalid"; simulation.Error = ex.Message; db.Update(simulation); if (SceneManager.GetActiveScene().name != Instance.LoaderScene) { SceneManager.LoadScene(Instance.LoaderScene); } textureBundle?.Unload(false); mapBundle?.Unload(false); AssetBundle.UnloadAllAssetBundles(true); Instance.CurrentSimulation = null; // TODO: take ex.Message and append it to response here NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); } } }); }
/// <summary> /// Download required for the simulation vehicle bundles from the server /// </summary> /// <param name="load">Load command from the server</param> /// <param name="mapBundlePath">Path where the map bundle will be saved</param> private void LoadMapBundle(Commands.Load load, string mapBundlePath) { var vehicleBundles = new List <string>(); DownloadVehicleBundles(load, vehicleBundles, () => { if (MasterPeer == null) { Debug.LogWarning("Master peer has disconnected while loading the simulation scene."); Loader.ResetLoaderScene(); return; } var zip = new ZipFile(mapBundlePath); { string manfile; ZipEntry entry = zip.GetEntry("manifest"); using (var ms = zip.GetInputStream(entry)) { int streamSize = (int)entry.Size; byte[] buffer = new byte[streamSize]; streamSize = ms.Read(buffer, 0, streamSize); manfile = Encoding.UTF8.GetString(buffer); } Manifest manifest = new Deserializer().Deserialize <Manifest>(manfile); AssetBundle textureBundle = null; if (zip.FindEntry(($"{manifest.assetGuid}_environment_textures"), false) != -1) { var texStream = zip.GetInputStream(zip.GetEntry($"{manifest.assetGuid}_environment_textures")); textureBundle = AssetBundle.LoadFromStream(texStream, 0, 1 << 20); } string platform = SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows ? "windows" : "linux"; var mapStream = zip.GetInputStream(zip.GetEntry($"{manifest.assetGuid}_environment_main_{platform}")); var mapBundle = AssetBundle.LoadFromStream(mapStream, 0, 1 << 20); if (mapBundle == null) { throw new Exception($"Failed to load environment from '{load.MapName}' asset bundle"); } textureBundle?.LoadAllAssets(); var scenes = mapBundle.GetAllScenePaths(); if (scenes.Length != 1) { throw new Exception( $"Unsupported environment in '{load.MapName}' asset bundle, only 1 scene expected"); } var sceneName = Path.GetFileNameWithoutExtension(scenes[0]); var loader = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive); loader.completed += op => { if (op.isDone) { SceneManager.SetActiveScene(SceneManager.GetSceneByName(sceneName)); textureBundle?.Unload(false); mapBundle.Unload(false); zip.Close(); try { var prefabs = LoadVehicleBundles(vehicleBundles); Loader.Instance.SimConfig = new SimulationConfig() { Name = load.Name, ApiOnly = load.ApiOnly, Headless = load.Headless, Interactive = load.Interactive, TimeOfDay = DateTime.ParseExact(load.TimeOfDay, "o", CultureInfo.InvariantCulture), Rain = load.Rain, Fog = load.Fog, Wetness = load.Wetness, Cloudiness = load.Cloudiness, UseTraffic = load.UseTraffic, UsePedestrians = load.UsePedestrians, Agents = load.Agents.Zip(prefabs, (agent, prefab) => { var config = new AgentConfig() { Name = agent.Name, Prefab = prefab, Connection = agent.Connection, Sensors = agent.Sensors, }; if (!string.IsNullOrEmpty(agent.Bridge)) { config.Bridge = Web.Config.Bridges.Find(bridge => bridge.Name == agent.Bridge); if (config.Bridge == null) { throw new Exception($"Bridge {agent.Bridge} not found"); } } return(config); }).ToArray(), }; Loader.Instance.CurrentSimulation = CreateSimulationModel(Loader.Instance.SimConfig); Loader.Instance.CurrentSimulation.Status = "Running"; if (Loader.Instance.SimConfig.ApiOnly) { var api = Instantiate(Loader.Instance.ApiManagerPrefab); api.name = "ApiManager"; } var simulatorManager = Loader.CreateSimulatorManager(); if (load.UseSeed) { simulatorManager.Init(load.Seed); } else { simulatorManager.Init(); } InitializeSimulation(simulatorManager.gameObject); // Notify WebUI simulation is running NotificationManager.SendNotification("simulation", SimulationResponse.Create(Loader.Instance.CurrentSimulation), Loader.Instance.CurrentSimulation.Owner); Debug.Log($"Client ready to start"); var result = new Commands.LoadResult() { Success = true, }; Loader.Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.READY); if (MasterPeer == null) { Debug.LogWarning("Master peer has disconnected while loading the simulation scene."); Loader.ResetLoaderScene(); return; } var resultData = PacketsProcessor.Write(result); var message = MessagesPool.Instance.GetMessage(resultData.Length); message.AddressKey = Key; message.Content.PushBytes(resultData); message.Type = DistributedMessageType.ReliableOrdered; UnicastMessage(MasterPeer.PeerEndPoint, message); State = SimulationState.Ready; } catch (Exception ex) { Debug.LogException(ex); var err = new Commands.LoadResult() { Success = false, ErrorMessage = ex.ToString(), }; var errData = PacketsProcessor.Write(err); var message = MessagesPool.Instance.GetMessage(errData.Length); message.AddressKey = Key; message.Content.PushBytes(errData); message.Type = DistributedMessageType.ReliableOrdered; UnicastMessage(MasterPeer.PeerEndPoint, message); Loader.ResetLoaderScene(); } } }; } }); }
static void SetupScene(SimulationModel simulation) { using (var db = DatabaseManager.Open()) { try { foreach (var agentConfig in Instance.SimConfig.Agents) { var bundlePath = agentConfig.AssetBundle; // TODO: make this async var vehicleBundle = AssetBundle.LoadFromFile(bundlePath); if (vehicleBundle == null) { throw new Exception($"Failed to load '{agentConfig.Name}' vehicle asset bundle"); } try { var vehicleAssets = vehicleBundle.GetAllAssetNames(); if (vehicleAssets.Length != 1) { throw new Exception($"Unsupported '{agentConfig.Name}' vehicle asset bundle, only 1 asset expected"); } // TODO: make this async agentConfig.Prefab = vehicleBundle.LoadAsset <GameObject>(vehicleAssets[0]); } finally { vehicleBundle.Unload(false); } } var sim = CreateSimulationManager(); // TODO: connect to cluster instances //if (Instance.SimConfig.Clusters.Length > 0) //{ // SimulatorManager.SetTimeScale(0); // Instance.PendingSimulation = simulation; // StartNetworkMaster(); // Instance.Master.AddClients(Instance.SimConfig.Clusters); //} //else { Instance.CurrentSimulation = simulation; // Notify WebUI simulation is running Instance.CurrentSimulation.Status = "Running"; NotificationManager.SendNotification("simulation", SimulationResponse.Create(Instance.CurrentSimulation), Instance.CurrentSimulation.Owner); // Flash main window to let user know simulation is ready WindowFlasher.Flash(); } } catch (Exception ex) { Debug.Log($"Failed to start '{simulation.Name}' simulation"); Debug.LogException(ex); // NOTE: In case of failure we have to update Simulation state simulation.Status = "Invalid"; db.Update(simulation); // TODO: take ex.Message and append it to response here NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); ResetLoaderScene(); } } }
public static void StartAsync(SimulationModel simulation) { Debug.Assert(Instance.CurrentSimulation == null); Instance.Actions.Enqueue(() => { using (var db = DatabaseManager.Open()) { AssetBundle mapBundle = null; try { if (Config.Headless && (simulation.Headless.HasValue && !simulation.Headless.Value)) { throw new Exception("Simulator is configured to run in headless mode, only headless simulations are allowed"); } simulation.Status = "Starting"; NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.PROGRESS); Instance.SimConfig = new SimulationConfig() { Name = simulation.Name, Clusters = db.Single <ClusterModel>(simulation.Cluster).Ips.Split(',').Where(c => c != "127.0.0.1").ToArray(), ClusterName = db.Single <ClusterModel>(simulation.Cluster).Name, ApiOnly = simulation.ApiOnly.GetValueOrDefault(), Headless = simulation.Headless.GetValueOrDefault(), Interactive = simulation.Interactive.GetValueOrDefault(), TimeOfDay = simulation.TimeOfDay.GetValueOrDefault(DateTime.MinValue.AddHours(12)), Rain = simulation.Rain.GetValueOrDefault(), Fog = simulation.Fog.GetValueOrDefault(), Wetness = simulation.Wetness.GetValueOrDefault(), Cloudiness = simulation.Cloudiness.GetValueOrDefault(), UseTraffic = simulation.UseTraffic.GetValueOrDefault(), UsePedestrians = simulation.UsePedestrians.GetValueOrDefault(), Seed = simulation.Seed, }; if (simulation.Vehicles == null || simulation.Vehicles.Length == 0 || simulation.ApiOnly.GetValueOrDefault()) { Instance.SimConfig.Agents = Array.Empty <AgentConfig>(); } else { Instance.SimConfig.Agents = simulation.Vehicles.Select(v => { var vehicle = db.SingleOrDefault <VehicleModel>(v.Vehicle); var config = new AgentConfig() { Name = vehicle.Name, AssetBundle = vehicle.LocalPath, Connection = v.Connection, Sensors = vehicle.Sensors, }; if (!string.IsNullOrEmpty(vehicle.BridgeType)) { config.Bridge = Config.Bridges.Find(bridge => bridge.Name == vehicle.BridgeType); if (config.Bridge == null) { throw new Exception($"Bridge {vehicle.BridgeType} not found"); } } return(config); }).ToArray(); } // load environment if (Instance.SimConfig.ApiOnly) { var api = Instantiate(Instance.ApiManagerPrefab); api.name = "ApiManager"; Instance.CurrentSimulation = simulation; // ready to go! Instance.CurrentSimulation.Status = "Running"; NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); Instance.LoaderUI.SetLoaderUIState(LoaderUI.LoaderUIStateType.READY); } else { var mapModel = db.Single <MapModel>(simulation.Map); var mapBundlePath = mapModel.LocalPath; // TODO: make this async mapBundle = AssetBundle.LoadFromFile(mapBundlePath); if (mapBundle == null) { throw new Exception($"Failed to load environment from '{mapModel.Name}' asset bundle"); } var scenes = mapBundle.GetAllScenePaths(); if (scenes.Length != 1) { throw new Exception($"Unsupported environment in '{mapModel.Name}' asset bundle, only 1 scene expected"); } var sceneName = Path.GetFileNameWithoutExtension(scenes[0]); Instance.SimConfig.MapName = sceneName; var loader = SceneManager.LoadSceneAsync(sceneName); loader.completed += op => { if (op.isDone) { mapBundle.Unload(false); SetupScene(simulation); } }; } } catch (Exception ex) { Debug.Log($"Failed to start '{simulation.Name}' simulation"); Debug.LogException(ex); // NOTE: In case of failure we have to update Simulation state simulation.Status = "Invalid"; db.Update(simulation); if (SceneManager.GetActiveScene().name != Instance.LoaderScene) { SceneManager.LoadScene(Instance.LoaderScene); } mapBundle?.Unload(false); AssetBundle.UnloadAllAssetBundles(true); Instance.CurrentSimulation = null; // TODO: take ex.Message and append it to response here NotificationManager.SendNotification("simulation", SimulationResponse.Create(simulation), simulation.Owner); } } }); }