Example #1
0
		public Resource(Task task, Workpiece workpiece)
		{
			Task = task;
			Workpiece = workpiece;
		}
		private IEnumerable<Tuple<Agent, Capability[]>> Convert(Task task, int[] path)
		{
			var previous = -1;
			var usedCarts = new List<Agent>();

			for (var i = 0; i < path.Length;)
			{
				var current = path[i];

				if (previous != -1)
				{
					// Find a cart that connects both robots, the path matrix contains the next robot we have to go to
					foreach (var nextRobot in GetShortestPath(previous, current))
					{
						yield return Transport(previous, nextRobot, usedCarts);

						if (nextRobot != current)
							yield return Tuple.Create(Agents[path[i]], new Capability[0]);

						previous = nextRobot;
					}
				}

				// Collect the capabilities that this robot should apply
				var capabilities = 
					path
					.Skip(i)
					.TakeWhile(robot => robot == current)
					.Select((_, index) => task.Capabilities[i + index])
					.ToArray();

				yield return Tuple.Create(Agents[path[i]], capabilities);
				previous = current;

				i += capabilities.Length;
			}
		}
		/// <summary>
		///   Recursively checks if there is a valid path with the given prefix for the task.
		///   If so, returns true and <param name="path" /> contains the path. Otherwise, returns false.
		/// </summary>
		private bool FindPath(Task task, int[] path, int prefixLength)
		{
			// termination case: the path is already complete
			if (prefixLength == task.Capabilities.Length)
				return true;

			var last = path[prefixLength - 1];

			// special handling: see if the last robot can't do the next capability as well
			if (CanSatisfyNext(task, prefixLength, last))
			{
				path[prefixLength] = last;
				if (FindPath(task, path, prefixLength + 1))
					return true;
			}
			else // otherwise check connected robots
			{
				for (int next = 0; next < _availableRobots.Length; ++next) // go through all stations
				{
					// if connected to last robot and can fulfill next capability
					if (_pathMatrix[last, next] != -1 && CanSatisfyNext(task, prefixLength, next) && next != last)
					{
						path[prefixLength] = next; // try a path over next
						if (FindPath(task, path, prefixLength + 1)) // if there is such a path, return true
							return true;
					}
				}
			}

			return false; // there is no valid path with the given prefix
		}
		/// <summary>
		///   Checks if the given robot can satisfy all the demanded capabilities.
		/// </summary>
		/// <param name="task">The task for which a path is searched.</param>
		/// <param name="capability">The zero-based index of the task's capability that should be applied next.</param>
		/// <param name="robot">The robot which should be next on the path.</param>
		/// <returns>True if choosing station as next path entry would not exceed its capabilities.</returns>
		private bool CanSatisfyNext(Task task, int capability, int robot)
		{
			return _availableRobots[robot].AvailableCapabilities.Any(c => c.IsEquivalentTo(task.Capabilities[capability]));
		}
		/// <summary>
		///   Finds a sequence of connected robots that are able to fulfill the
		///   <param name="task" />'s capabilities.
		/// </summary>
		/// <returns>
		///   An array of robot identifiers, one for each capability.
		/// </returns>
		private int[] FindPath(Task task)
		{
			var path = new int[task.Capabilities.Length];

			for (var first = 0; first < _availableRobots.Length; ++first)
			{
				if (CanSatisfyNext(task, 0, first))
				{
					path[0] = first;
					if (FindPath(task, path, 1))
						return path;
				}
			}

			return null;
		}