Example #1
0
            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();
            }
        public bool DoesNotExceedMaximumDistanceForAllCriteria(IZoneInfo zoneInfo, int distance)
        {
            if (distance >= MaximumDistance)
            {
                return(false);
            }
            foreach (var kvp in _findFuncs.ToDictionary(x => x.Key, x => x.Value))
            {
                if (kvp.Key(zoneInfo))
                {
                    if (kvp.Value.HasValue)
                    {
                        var currentDistance = kvp.Value;
                        if (currentDistance > distance)
                        {
                            _findFuncs[kvp.Key] = distance;
                        }
                    }
                    else
                    {
                        _findFuncs[kvp.Key] = distance;
                    }
                }
            }

            if (_findFuncs.All(x => x.Value.HasValue))
            {
                var maxDistance = _findFuncs.Max(x => x.Value.Value);

                return(maxDistance >= distance);
            }
            return(true);
        }
Example #3
0
        private void TestWithAmountOfHarbors(int numberOfHarbours)
        {
            var terraFormingOptions = new TerraformingOptions()
            {
                VerticalRiver   = true,
                HorizontalRiver = true
            };

            terraFormingOptions.SetZoneWidthAndHeight(TerraformingOptions.MinWidthAndHeight);
            var area           = new Area(new AreaOptions(() => new Mock <ILandValueCalculator>().Object, terraFormingOptions, new ProcessOptions(() => false, () => false), () => new Mock <ICityServiceStrengthLevels>().Object));
            var shipController = new ShipController(() => area.EnumerateZoneInfos().OfType <IZoneInfo>().ToHashSet(), TimeSpan.FromMilliseconds(1), 1);

            var harbourFactory = new Func <SeaPortZoneClusterConsumption>(
                () => new SeaPortZoneClusterConsumption(
                    () => new ZoneInfoFinder(x => QueryResult <IZoneInfo> .Create(area.EnumerateZoneInfos().SingleOrDefault(y => y.ConsumptionState.GetZoneConsumption() == x))),
                    new ElectricitySupplierBehaviour(10)));

            foreach (var iteration in Enumerable.Range(0, numberOfHarbours))
            {
                var result = area.EnumerateZoneInfos().FirstOrDefault(x => area.ConsumeZoneAt(x, harbourFactory()).Success);

                Assert.IsNotNull(result);
            }
            Assert.AreNotEqual(0, area.CalculatePowergridStatistics());

            var shipDict = new Dictionary <IShip, IZoneInfo>();

            IZoneInfo previousPosition = null;

            foreach (var attempt in Enumerable.Range(0, 10))
            {
                shipController.ForEachActiveVehicle(true, ship =>
                {
                    if (!shipDict.ContainsKey(ship))
                    {
                        shipDict.Add(ship, null);
                    }
                    previousPosition = ship.CurrentPosition;
                    shipDict[ship]   = previousPosition;
                });
                if ((numberOfHarbours * ShipController.AmountOfShipsPerHarbour == shipDict.Count) && shipDict.Values.All(x => x != null))
                {
                    break;
                }
                System.Threading.Thread.Sleep(100);
            }
            Assert.AreEqual(numberOfHarbours * ShipController.AmountOfShipsPerHarbour, shipDict.Count);

            foreach (var iteration in Enumerable.Range(0, 3))
            {
                System.Threading.Thread.Sleep(10);

                shipController.ForEachActiveVehicle(true, ship =>
                {
                    Assert.AreNotSame(previousPosition, ship.CurrentPosition);
                    previousPosition = ship.CurrentPosition;
                });
            }
        }
Example #4
0
 public ShipPathNode(IZoneInfo zoneInfo, int maxDistance)
     : this(
         rootZoneInfo : zoneInfo,
         currentZoneInfo : zoneInfo,
         preceedingShipPathNode : null,
         seenPaths : new HashSet <IZoneInfo>(),
         distance : 0,
         maxDistance : maxDistance
         )
 {
 }
 public ZoneInfoPathNode(IZoneInfo zoneInfo, Func <IZoneInfoPathNode, QueryResult <IZoneInfo, RelativeZoneInfoQuery>, bool> canBeJoinedFunc, Func <IZoneInfo, int?> getDestinationHashCode, ZoneInfoDistanceTracker distanceTracker)
     : this(
         zoneInfo : zoneInfo,
         canBeJoinedFunc : canBeJoinedFunc,
         getDestinationHashCode : getDestinationHashCode,
         previousPathNode : null,
         originParentPathNode : null,
         distance : 0,
         distanceTracker : distanceTracker)
 {
 }
Example #6
0
 public Airplane(Func <ISet <IZoneInfo> > getZoneInfosFunc, IZoneInfo currentPosition,
                 Func <IZoneInfo, QueryResult <IZoneInfo, RelativeZoneInfoQuery> > directionQuery,
                 Func <IZoneInfo, QueryResult <IZoneInfo, RelativeZoneInfoQuery> > alternateDirectionQuery,
                 int alternateRate
                 )
     : base(getZoneInfosFunc, currentPosition)
 {
     _directionQuery          = directionQuery;
     _alternateDirectionQuery = alternateDirectionQuery;
     _alternateRate           = alternateRate;
     _directionEnumerator     = DirectionQuery().GetEnumerator();
 }
 protected void Move(IZoneInfo next)
 {
     Trail.Enqueue(next);
     if (Trail.Count == 6)
     {
         Trail.Dequeue();
     }
     else if (Trail.Count > 6)
     {
         throw new InvalidOperationException();
     }
 }
Example #8
0
                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>());
        }
        public bool IsPreviouslyNotSeenOrSeenAtLargerDistance(IZoneInfo node, int distance, IZoneInfoPathNode previousPathNode)
        {
            var currentConsumption  = node.ConsumptionState.GetZoneConsumption();
            var previousConsumption = previousPathNode?.ZoneInfo.ConsumptionState.GetZoneConsumption();

            if (currentConsumption is IntersectingZoneConsumption)
            {
                var currentConsumptionAsIntersection = currentConsumption as IntersectingZoneConsumption;
                if (!_intersectionsAndSeenTypes.ContainsKey(currentConsumptionAsIntersection))
                {
                    _intersectionsAndSeenTypes.Add(currentConsumptionAsIntersection, new HashSet <Type>());
                }
                if (previousConsumption != null)
                {
                    return(_intersectionsAndSeenTypes[currentConsumptionAsIntersection].Add(previousConsumption.GetType()));
                }
                else
                {
                    throw new InvalidOperationException();
                }
            }

            if (_nodesAndDistances.ContainsKey(node))
            {
                if (_nodesAndDistances[node].Distance > distance)
                {
                    _nodesAndDistances[node].UpdateDistance(distance);
                    return(true);
                }
                return(false);
            }
            else
            {
                _nodesAndDistances.Add(node, new DistanceAndConsumption(distance));
                return(true);
            }
        }
Example #11
0
        public GrowthZoneInfoPathNode(IZoneInfo zoneInfo, ZoneClusterMemberConsumption clusterMemberConsumption, ProcessOptions processOptions, HashSet <BaseGrowthZoneClusterConsumption> undesirableGrowthZones)
            : base(
                zoneInfo: zoneInfo,
                canBeJoinedFunc: (previousPath, currentZoneInfo) =>
        {
            var matchingPath = previousPath;

            if (processOptions.GetStepByStepGrowthCyclingToggled())
            {
                Thread.Sleep(50);
            }

            var evaluatingNonIntersection = false;

            while (!evaluatingNonIntersection)
            {
                var intersection =
                    matchingPath.ZoneInfo.ConsumptionState.GetZoneConsumption() as
                    IntersectingZoneConsumption;

                if (intersection != null)
                {
                    matchingPath = matchingPath.PreviousPathNode;
                }
                else
                {
                    evaluatingNonIntersection = true;
                }
            }
            matchingPath.ZoneInfo.GrowthAlgorithmHighlightState.SetState(HighlightState.Examined);
            currentZoneInfo.MatchingObject.GrowthAlgorithmHighlightState.SetState(HighlightState.Examined);

            Func <bool> isSuccessFunc       = null;
            string currentIsSuccessFuncDesc = String.Empty;

            Action <string, Func <bool> > assignIsSuccessOverrideFuncAction = (description, action) =>
            {
                isSuccessFunc            = action;
                currentIsSuccessFuncDesc = description;
            };

            Action <string, Func <bool> > assignIsSuccessFuncAction = (description, action) =>
            {
                if (isSuccessFunc != null)
                {
                    throw new InvalidOperationException($"Could not set {description} as the 'IsSuccessFunc'. {currentIsSuccessFuncDesc} Is currently set.");
                }
                assignIsSuccessOverrideFuncAction(description, action);
            };

            // If the current zone is a growth zone...
            currentZoneInfo
            .MatchingObject
            .WithZoneClusterIf <BaseGrowthZoneClusterConsumption>(growthZone =>
            {
                if (!growthZone.HasPower)
                {
                    return;
                }

                // And the previous path member was also a growth zone, then
                // they must both be part of the zone cluster that originated this
                // path...
                matchingPath
                .ZoneInfo
                .WithZoneClusterIf <BaseGrowthZoneClusterConsumption>(res =>
                                                                      assignIsSuccessFuncAction("BaseGrowthZoneClusterConsumption",
                                                                                                () =>
                                                                                                res == clusterMemberConsumption.ParentBaseZoneClusterConsumption &&
                                                                                                growthZone == clusterMemberConsumption.ParentBaseZoneClusterConsumption)
                                                                      );

                // And the previous zone was a road zone...
                matchingPath
                .ZoneInfo
                .WithNetworkConsumptionIf <RoadZoneConsumption>(previousRoadZone => assignIsSuccessFuncAction("RoadZoneConsumption", () => true));
            });

            // If the current zone is a road...
            currentZoneInfo
            .MatchingObject
            .WithNetworkConsumptionIf <RoadZoneConsumption>(currentRoadZone =>
            {
                // And the previous zone was a growth zone...
                matchingPath
                .ZoneInfo
                .WithZoneClusterIf <BaseGrowthZoneClusterConsumption>(res => assignIsSuccessFuncAction(
                                                                          "BaseGrowthZoneClusterConsumption", () =>
                                                                          (res ==
                                                                           clusterMemberConsumption
                                                                           .ParentBaseZoneClusterConsumption)));

                // And the previous zone was a trainstation...
                matchingPath
                .ZoneInfo
                .WithZoneClusterIf <TrainStationZoneClusterConsumption>(res => assignIsSuccessOverrideFuncAction("RoadZoneConsumption/TrainStationZoneClusterConsumption", () => true));

                // And the previous one was also a road...
                matchingPath
                .ZoneInfo
                .WithNetworkConsumptionIf <RoadZoneConsumption>(
                    previousRoadZone => assignIsSuccessFuncAction("RoadZoneConsumption", () => true));
            });

            // If the current zone is a railroad...
            currentZoneInfo
            .MatchingObject
            .WithNetworkConsumptionIf <RailRoadZoneConsumption>(currentRailRoad =>
            {
                // And the previous one was also a railroad...
                matchingPath
                .ZoneInfo
                .WithNetworkConsumptionIf <RailRoadZoneConsumption>(
                    previousRailRoadZone => assignIsSuccessFuncAction("RailRoadZoneConsumption", () => true));

                // And the previous zone was a trainstation zone...
                matchingPath
                .ZoneInfo
                .WithZoneClusterIf <TrainStationZoneClusterConsumption>(res =>
                {
                    if (res.HasPower)
                    {
                        assignIsSuccessOverrideFuncAction(
                            "RailRoadZoneConsumption/TrainStationZoneClusterConsumption",
                            () => true
                            );
                    }
                });
            });

            // If the current zone is a trainstation zone...
            currentZoneInfo
            .MatchingObject
            .WithZoneClusterIf <TrainStationZoneClusterConsumption>(growthZone =>
            {
                if (!growthZone.HasPower)
                {
                    return;
                }

                // And the previous zone was part of the same trainstation...
                matchingPath
                .ZoneInfo
                .WithZoneClusterIf <TrainStationZoneClusterConsumption>(res => assignIsSuccessFuncAction("TrainStationZoneClusterConsumption/TrainStationZoneClusterConsumption", () => growthZone == res));

                // And the previous one was a road...
                matchingPath
                .ZoneInfo
                .WithNetworkConsumptionIf <RoadZoneConsumption>(
                    previousRoadZone => assignIsSuccessFuncAction("RoadZoneConsumption", () => true));

                // And the previous one was a road...
                matchingPath
                .ZoneInfo
                .WithNetworkConsumptionIf <RailRoadZoneConsumption>(
                    previousRoadZone => assignIsSuccessFuncAction("RailRoadZoneConsumption", () => true));
            });

            return(isSuccessFunc != null &&
                   isSuccessFunc());
        },
                getDestinationHashCode: (match) =>
        {
            var destinationHashCode = default(int?);

            if (clusterMemberConsumption.ParentBaseZoneClusterConsumption is IndustrialZoneClusterConsumption)
            {
                match.WithZoneClusterIf <ResidentialZoneClusterConsumption>(
                    cluster =>
                {
                    if (undesirableGrowthZones.Contains(cluster))
                    {
                        return;
                    }
                    if (cluster.GetType() !=
                        clusterMemberConsumption.ParentBaseZoneClusterConsumption
                        .GetType())
                    {
                        destinationHashCode = cluster.GetHashCode();
                    }
                });
            }
            else
            {
                match.WithZoneClusterIf <BaseGrowthZoneClusterConsumption>(
                    cluster =>
                {
                    if (undesirableGrowthZones.Contains(cluster))
                    {
                        return;
                    }
                    if (cluster.GetType() !=
                        clusterMemberConsumption.ParentBaseZoneClusterConsumption
                        .GetType())
                    {
                        destinationHashCode = cluster.GetHashCode();
                    }
                });
            }
            return(destinationHashCode);
        },
                distanceTracker: new ZoneInfoDistanceTracker(new Func <Func <IZoneInfo, bool>[]>(() =>
        {
            if (clusterMemberConsumption.ParentBaseZoneClusterConsumption is ResidentialZoneClusterConsumption)
            {
                return(new Func <IZoneInfo, bool>[]
                {
                    x => x.IsGrowthZoneClusterOfType <CommercialZoneClusterConsumption>(),
                    x => x.IsGrowthZoneClusterOfType <IndustrialZoneClusterConsumption>()
                });
            }
            if (clusterMemberConsumption.ParentBaseZoneClusterConsumption is CommercialZoneClusterConsumption)
            {
                return(new Func <IZoneInfo, bool>[]
                {
                    x => x.IsGrowthZoneClusterOfType <ResidentialZoneClusterConsumption>(),
                    x => x.IsGrowthZoneClusterOfType <IndustrialZoneClusterConsumption>()
                });
            }
            if (clusterMemberConsumption.ParentBaseZoneClusterConsumption is IndustrialZoneClusterConsumption)
            {
                return(new Func <IZoneInfo, bool>[]
                {
                    x => x.IsGrowthZoneClusterOfType <ResidentialZoneClusterConsumption>()
                });
            }

            throw new InvalidOperationException();
        })()
                                                             )
                )
        {
            OriginBaseZoneClusterConsumption = clusterMemberConsumption.ParentBaseZoneClusterConsumption;
        }
 public Train(Func <ISet <IZoneInfo> > getZoneInfosFunc, IZoneInfo currentPosition)
     : base(getZoneInfosFunc, currentPosition)
 {
 }
        public static void TurnOffZone(this IWriteProcessor processor, IZoneInfo zone)
        {
            var command = new TurnOffZoneCommand(zone.Id);

            processor.ExecuteCommand(command);
        }
        public static void SetZoneLevel(this IWriteProcessor processor, IZoneInfo zone, int level)
        {
            var command = new SetZoneLevelCommand(zone.Id, level);

            processor.ExecuteCommand(command);
        }
        public static void SendGetZoneStatus(this IWriteProcessor processor, IZoneInfo zone)
        {
            var command = new GetZoneStatusCommand(zone.Id);

            processor.ExecuteCommand(command);
        }
Example #16
0
 protected BaseVehicle(Func <ISet <IZoneInfo> > getZoneInfosFunc, IZoneInfo currentPosition)
 {
     GetZoneInfosFunc = getZoneInfosFunc;
     Trail.Enqueue(currentPosition);
 }