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); }
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; }); } }
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) { }
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(); } }
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); } }
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); }
protected BaseVehicle(Func <ISet <IZoneInfo> > getZoneInfosFunc, IZoneInfo currentPosition) { GetZoneInfosFunc = getZoneInfosFunc; Trail.Enqueue(currentPosition); }