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 ) ) ); }
private ZoneInfoPathNode( IZoneInfo zoneInfo, Func <IZoneInfoPathNode, QueryResult <IZoneInfo, RelativeZoneInfoQuery>, bool> canBeJoinedFunc, Func <IZoneInfo, int?> getDestinationHashCode, IZoneInfoPathNode previousPathNode, IZoneInfoPathNode originParentPathNode, int distance, ZoneInfoDistanceTracker distanceTracker) { ZoneInfo = zoneInfo; PreviousPathNode = previousPathNode; _originParentPathNode = originParentPathNode ?? this; DestinationHashCode = getDestinationHashCode(zoneInfo); Distance = distance; _childPathsLazy = new Lazy <List <IZoneInfoPathNode> >(() => !distanceTracker.IsPreviouslyNotSeenOrSeenAtLargerDistance(ZoneInfo, distance, previousPathNode) ? Enumerable.Empty <IZoneInfoPathNode>().ToList() : ZoneInfo .GetNorthEastSouthWest() .Where(x => x.HasMatch) .Where(x => x.MatchingObject != PreviousPathNode?.ZoneInfo) .Where(x => distanceTracker.DoesNotExceedMaximumDistanceForAllCriteria(ZoneInfo, distance)) .Where(x => canBeJoinedFunc(this, x)) .Select(x => new ZoneInfoPathNode( zoneInfo: x.MatchingObject, canBeJoinedFunc: canBeJoinedFunc, getDestinationHashCode: getDestinationHashCode, previousPathNode: this, originParentPathNode: _originParentPathNode, distance: Distance + x.MatchingObject.GetDistanceScoreBasedOnConsumption(), distanceTracker: distanceTracker )) .ToList <IZoneInfoPathNode>()); }