public Ship(Func <ISet <IZoneInfo> > getZoneInfosFunc, IZoneInfo currentPosition, int speedInMilliseconds, int maxDistance) : base(getZoneInfosFunc, currentPosition) { SpeedInMilliseconds = speedInMilliseconds; _pathEnumeratorTask = new Task <IEnumerator <ShipPathNode> >(() => { var pathNode = new ShipPathNode(CurrentPosition, maxDistance); var enumerator = pathNode .EnumerateAllChildPathNodes() .Where(x => x.Distance < maxDistance) .GroupBy(x => CalculateDistance(CurrentPosition.Point, x.CurrentZoneInfo.Point)) .OrderByDescending(x => x.Key) .FirstOrDefault() ?.OrderBy(x => x.Distance) ?.FirstOrDefault() ?.EnumeratePathBackwards() ?.GetEnumerator() ?? new List <ShipPathNode>() { pathNode }.GetEnumerator(); enumerator.MoveNext(); return(enumerator); }); _pathEnumeratorTask.Start(); }
private ShipPathNode( IZoneInfo rootZoneInfo, IZoneInfo currentZoneInfo, ShipPathNode preceedingShipPathNode, ISet <IZoneInfo> seenPaths, int distance, int maxDistance ) { _maxDistance = maxDistance; if (rootZoneInfo == null) { throw new ArgumentNullException(nameof(rootZoneInfo)); } _rootZoneInfo = rootZoneInfo; if (currentZoneInfo == null) { throw new ArgumentNullException(nameof(currentZoneInfo)); } CurrentZoneInfo = currentZoneInfo; if (!seenPaths.Add(currentZoneInfo)) { throw new ArgumentException("'currentZoneInfo' was already added to this path.", nameof(currentZoneInfo)); } _preceedingShipPathNode = preceedingShipPathNode; Distance = distance; _childrenLazy = new Lazy <IEnumerable <ShipPathNode> >(() => CurrentZoneInfo .GetNorthEastSouthWest() .Where(x => Distance + 1 < maxDistance) .Where(x => x.HasMatch) .Where(x => _preceedingShipPathNode != null ? x.MatchingObject != _preceedingShipPathNode.CurrentZoneInfo : true) .Where(x => !seenPaths.Contains(x.MatchingObject)) .Where(x => IsSuitableForShip(x.MatchingObject)) .OrderByDescending(x => CalculateDistance(x.MatchingObject.Point, _rootZoneInfo.Point)) .Where(x => !seenPaths.Contains(x.MatchingObject)) .Select(x => new ShipPathNode( rootZoneInfo: rootZoneInfo, currentZoneInfo: x.MatchingObject, preceedingShipPathNode: this, seenPaths: seenPaths, distance: Distance + 1, maxDistance: _maxDistance ) ) ); }