private async Task <MazebotResult> PostSolution(MazebotResponse mazebotMaze, NavigationDetails solution) { MazebotResult result = null; if (solution.Arrived) { result = await _apiClient.SolveMazebotMaze(mazebotMaze.MazePath, solution.PathTaken); } return(result); }
public async void Navigate_On_Swarm_Mode_Should_Return_The_First_Task_That_Completes_With_Arrived_True_Result() { var result1 = new NavigationDetails { Arrived = true, PathTaken = "result1" }; var task1 = Task.Run(() => { Task.Delay(300); return(result1); }); var crawler1 = Substitute.For <IMazeCrawler>(); crawler1.Navigate().Returns(task1); var result2 = new NavigationDetails { Arrived = true, PathTaken = "result2" }; var task2 = Task.Run(() => { Task.Delay(500); return(result2); }); var crawler2 = Substitute.For <IMazeCrawler>(); crawler2.Navigate().Returns(task2); var task3 = Task.Run(() => { Task.Delay(100); return(new NavigationDetails { Arrived = false }); }); var crawler3 = Substitute.For <IMazeCrawler>(); crawler3.Navigate().Returns(task3); var crawlers = new [] { crawler1, crawler2, crawler3 }; var swarmCoordinator = Substitute.For <ISwarmCoordinator>(); swarmCoordinator.GetSwarm(Arg.Any <IMazeCrawlerState>()).Returns(crawlers); var crawlerCoordinator = Substitute.For <IMazeCrawlerCoordinator>(); crawlerCoordinator.RequestSwarm(Arg.Any <IMazeCrawlerState>()).Returns(swarmCoordinator); var context = new MazeCrawlerContext { Start = new Coordinates(0, 0), Destination = new Coordinates(0, 1), NavigationMap = new Map(new char[][] { new [] { Map.EMPTY, Map.EMPTY }, new [] { Map.EMPTY, Map.OCCPD } }), NavigationMode = CrawlerNavigationMode.Swarm, Coordinator = crawlerCoordinator }; var crawler = new MazeCrawler(context); var response = await crawler.Navigate(); response.Should().BeEquivalentTo(result1); }
#pragma warning disable CS1998,CS4014 private async Task <NavigationDetails> SwarmNavigate() { var swarmCoordinator = _coordinator.RequestSwarm(this); var swarm = swarmCoordinator.GetSwarm(this); Trace($"Received {swarm.Count()} crawler(s) from the swarm."); NavigationDetails result = null; var tasks = new Dictionary <int, Task>(); var cancelationSource = new CancellationTokenSource(); foreach (var crawler in swarm) { // Add the Navigate task of each MazeCrawler to a list and remove it once it completes. Trace($"Crawler {crawler.Id} to continue with the navigation."); var task = Task.Run(() => crawler.Navigate(), cancelationSource.Token); tasks.Add(task.Id, task); task.ContinueWith(completed => { lock (tasks) { Trace($"Swarm with task#{completed.Id} completed its navigation."); if (completed.IsCompletedSuccessfully && completed.Result.Arrived) { // Cancel the other Navigate tasks from the list since the destination Coordinates has been reached already. result = completed.Result; Trace($"Crawler with task#{completed.Id} arrived. Reporting arrival."); cancelationSource.Cancel(); } tasks.Remove(completed.Id); Trace($"Swarm has {tasks.Count()} task(s) left."); } }); while (tasks.Count() > 0) { await Task.Delay(25); } ; } cancelationSource.Dispose(); return(result ?? new NavigationDetails { Arrived = false }); }
public async void Navigate_Should_Call_Spawned_IMazeCrawler_Navigate() { _queen.ScanMap(new Coordinates(1, 2), new Coordinates(3, 4), new Map(new char[0][])); var expected = new NavigationDetails(); var crawler = Substitute.For <IMazeCrawler>(); crawler.Navigate().Returns(expected); _spawner.Spawn(Arg.Any <MazeCrawlerContext>()).Returns(crawler); var response = await _queen.Navigate(); await crawler.Received(1).Navigate(); response.Should().Be(expected); }
public async Task <NavigationDetails> Navigate() { Trace($"Starting navigation preference: {string.Join(',', _preference )}."); NavigationDetails response = null; switch (NavigationMode) { case CrawlerNavigationMode.Scout: // Scout will force the MazeCrawler to traverse by itself the map starting from its current Coordinates until it reaches the destination Coordinates (or a deadend is reached). response = Scout(); break; case CrawlerNavigationMode.Swarm: // Swarm will make the MazeCrawler to traverse the map by itself until it reaches a path that forks. // When this happens, the MazeCrawler will request for other MazeCrawlers and will force each of them to traverse the succeeding path (one for each fork on the path). response = await Swarm(); break; } return(response); }