/// <summary> /// Select one of the given possible routes. /// Returns null if no route should be taken. /// </summary> /// <param name="possibleRoutes">A list of routes to choose from</param> /// <param name="loc">The loc to choose for</param> /// <param name="fromBlock">The block from which the next route will leave</param> /// <param name="locDirection">The direction the loc is facing in the <see cref="fromBlock"/>.</param> public IRouteState SelectRoute(IList <IRouteState> possibleRoutes, ILocState loc, IBlockState fromBlock, BlockSide locDirection) { // Look for a direct match var directRoutes = possibleRoutes.Where(x => x.To == targetBlock).ToList(); if (directRoutes.Any()) { return(new DefaultRouteSelector().SelectRoute(directRoutes, loc, fromBlock, locDirection)); } // Look for routes that get us closer to the target block. var sequences = FindRouteSequences(fromBlock, locDirection.Invert(), targetBlock).ToList(); // Filter sequences to start with possible routes var possibleSequences = sequences.Where(x => possibleRoutes.Contains(x.First)).OrderBy(x => x.Length).ToList(); // Any sequences left? if (possibleSequences.Count == 0) { return(null); } // Take the first possible sequence. return(possibleSequences[0].First); }
/// <summary> /// Find all route sequences that lead from the given side of the given "from" block to the given "to" block. /// </summary> public static IEnumerable <IRouteSequence> FindRouteSequences(IBlockState fromBlock, BlockSide fromBlockEnterSide, IBlockState toBlock) { var railway = fromBlock.RailwayState; var fromBlockLeaveSide = fromBlockEnterSide.Invert(); var startRoutes = railway.RouteStates.Where(x => (x.From == fromBlock) && (x.FromBlockSide == fromBlockLeaveSide)).ToList(); var initialSequences = startRoutes.Select(x => new RouteSequence(x)); return(FindRouteSequences(initialSequences, railway, toBlock, railway.RouteStates.Count)); }
/// <summary> /// Default ctor /// </summary> public Item(ILocState loc, IBlockState block, BlockSide currentBlockEnterSide, LocDirection direction) { this.loc = loc; this.block = block; this.currentBlockEnterSide = currentBlockEnterSide; this.direction = direction; Checked = true; Text = loc.Description; var facingText = (currentBlockEnterSide.Invert() == BlockSide.Front) ? Strings.FacingFrontOfBlock : Strings.FacingBackOfBlock; SubItems.Add(string.Format(Strings.XFacingY, block.Description, facingText)); SubItems.Add(direction == LocDirection.Forward ? "Forward" : "Reverse"); }
/// <summary> /// Assign the current loc to the selected block facing the given side. /// </summary> private void Assign(BlockSide side) { var block = SelectedBlock; if ((loc != null) && (block != null)) { var task = Task <bool> .Factory.StartNew(() => loc.AssignTo(block, side.Invert())); task.ContinueWith(t => { if (t.Result) { UpdateBlocks(); UpdateControls(); } else { var msg = string.Format("Cannot lock block '{0}'", block); MessageBox.Show(msg, Strings.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); } }, TaskScheduler.FromCurrentSynchronizationContext()); } }