private static void CreateCars(WorkerView dispatcher, Connection connection) { for (int i = 0; i < numberOfCars; i++) { RequestId <CreateEntityRequest> creationRequestId = CreationRequests.CreateCarEntity(dispatcher, connection); dispatcher.carCreationRequestIds.Add(creationRequestId); } }
private static void CreateNewBusesInList(WorkerView dispatcher, Connection connection, System.Collections.Generic.HashSet <string> newBusVehicleIds) { foreach (string busVehicleId in newBusVehicleIds) { if (!busVehicleIds.Contains(busVehicleId)) { if (BusOnMap(busVehicleId)) { RequestId <CreateEntityRequest> creationRequestId = CreationRequests.CreateBusEntity(dispatcher, connection, busVehicleId); dispatcher.carCreationRequestIds.Add(creationRequestId); requestIdToBusVehicleIdDict.Add(creationRequestId, busVehicleId); } } } }
private static void updateBusToNextStop(Connection connection, WorkerView dispatcher, EntityId entityId) { List <string> nextStops; if (dispatcher.busesNextStops.TryGetValue(entityId, out nextStops)) { // This could be optimised - redundent data is being sent string vehicleId = dispatcher.busesVehicleIds[entityId]; Map <string, string> arrivalTimes = dispatcher.busesArrivalEstimate[entityId]; nextStops.RemoveAt(0); var busComponentUpdate = Bus.Update.FromInitialData(new BusData(vehicleId, nextStops, arrivalTimes)); connection.SendComponentUpdate(Bus.Metaclass, entityId, busComponentUpdate); } else { connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "Couldn't get list of next stops for bus: " + entityId); } }
private static bool moveVehicleToBusStop(Connection connection, WorkerView dispatcher, MapReader mapReader, EntityId entityId, string busStopAtcoCode) { ulong busStopNodeId; if (mapReader.busStops.TryGetValue(busStopAtcoCode, out busStopNodeId)) { ulong nearestNodeId = mapReader.nearestRoadNodesToBusStops[busStopNodeId]; OsmNode nearestNode = mapReader.nodes[nearestNodeId]; var positionComponentUpdate = Position.Update.FromInitialData(new PositionData(nearestNode.coords)); var carComponentUpdate = Car.Update.FromInitialData(new CarData(nearestNodeId, nearestNodeId, nearestNode.waysOn.First())); connection.SendComponentUpdate(Position.Metaclass, entityId, positionComponentUpdate); // short curcuits by default connection.SendComponentUpdate(Car.Metaclass, entityId, carComponentUpdate); //updateBusToNextStop(connection, dispatcher, entityId); return(true); } return(false); }
private static List <string> UpdateBusesList(WorkerView dispatcher) { StaticConnection.SendLogMessage(LogLevel.Info, StaticLogName, "Updating bus list - stop list length " + dispatcher.busStopAtcoCodes.Count); List <string> newBusVehicleIds = new List <string>(); foreach (string atcoCode in dispatcher.busStopAtcoCodes.Values) { string json = string.Empty; string app_id = "d95991f2"; string app_key = "db59c31bd87e57bbe3512137ca40a450"; string url = @"https://api.tfl.gov.uk/StopPoint/" + atcoCode + @"/Arrivals?app_id=" + app_id + @"&app_key=" + app_key; try { HttpWebRequest request = WebRequest.CreateHttp(url); request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { json = reader.ReadToEnd(); } dynamic arrivals = JsonConvert.DeserializeObject(json); foreach (var bus in arrivals) { // Only create a bus if it is at most 5 minutes from at least 1 station if (bus.timeToStation < 300 && dispatcher.busStopAtcoCodes.ContainsValue((string)bus.naptanId)) { string vehicleId = bus.vehicleId; newBusVehicleIds.Add(vehicleId); } } } catch (WebException ex) { StaticConnection.SendLogMessage(LogLevel.Info, StaticLogName, "web exception - status " + ex.Status); } } return(newBusVehicleIds); }
private static bool newPosIsACarCrash(Connection connection, WorkerView dispatcher, Coordinates newCarPos, ulong newCarNode, ulong prevCarNode, EntityId entityId, double minDistance) { foreach (EntityId otherCarEntityId in dispatcher.carsInAuthority) { try { if (dispatcher.carNodeIds[otherCarEntityId] == newCarNode && dispatcher.prevCarNodeIds[otherCarEntityId] == prevCarNode && otherCarEntityId != entityId) { if (Coords.Dist(newCarPos, dispatcher.entityPositions[otherCarEntityId]) < minDistance) { return(true); } } } catch (System.Collections.Generic.KeyNotFoundException e) { //connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "Exception: " + e.Message); continue; } } return(false); }
private static int Main(string[] args) { if (args.Length != 4) { PrintUsage(); return(ErrorExitStatus); } // Avoid missing component errors because no components are directly used in this project // and the GeneratedCode assembly is not loaded but it should be Assembly.Load("GeneratedCode"); var connectionParameters = new ConnectionParameters { WorkerType = WorkerType, Network = { ConnectionType = NetworkConnectionType.Tcp } }; ServicePointManager.ServerCertificateValidationCallback += (o, cert, chain, errors) => true; using (var connection = ConnectWithReceptionist(args[1], Convert.ToUInt16(args[2]), args[3], connectionParameters)) { WorkerView dispatcher = new WorkerView(connection); var isConnected = true; ClassIsConnected = isConnected; string workerId = connection.GetWorkerId(); if (!staticVarsInitialised) { StaticConnection = connection; MapReader = InitialiseWorld.ReadMapFile("south_west_london_map.osm"); staticVarsInitialised = true; } if (workerId == "simulation0") { InitialiseWorld.createOsmNodes(MapReader, dispatcher, connection); InitialiseWorld.createBusStops(MapReader, dispatcher, connection); CreateCars(dispatcher, connection); } dispatcher.OnDisconnect(op => { Console.Error.WriteLine("[disconnect] " + op.Reason); isConnected = false; ClassIsConnected = isConnected; }); Stopwatch initalBusUpdateTimer = new Stopwatch(); initalBusUpdateTimer.Start(); Stopwatch busUpdateTimer = new Stopwatch(); busUpdateTimer.Start(); Stopwatch timer = new Stopwatch(); timer.Start(); while (isConnected) { if (initalBusUpdateTimer.Elapsed.TotalSeconds >= 20 || busUpdateTimer.Elapsed.TotalSeconds >= 120) { initalBusUpdateTimer.Reset(); System.Collections.Generic.HashSet <string> newBusVehicleListIds = new System.Collections.Generic.HashSet <string>(UpdateBusesList(dispatcher)); CreateNewBusesInList(dispatcher, connection, newBusVehicleListIds); busVehicleIds.Concat(newBusVehicleListIds); connection.SendLogMessage(LogLevel.Info, workerId, "Buses on map count: " + busVehicleIds.Count); busUpdateTimer.Restart(); } if (timer.Elapsed.TotalSeconds >= upateInterval) { Movement.MoveCars(connection, dispatcher, MapReader); timer.Restart(); } using (var opList = connection.GetOpList(GetOpListTimeoutInMilliseconds)) { dispatcher.Process(opList); } } } // This means we forcefully disconnected return(ErrorExitStatus); }
public static bool UpdateBusTimes(Connection connection, WorkerView dispatcher, EntityId busEntityId) { string busVehicleId; if (!dispatcher.busesVehicleIds.TryGetValue(busEntityId, out busVehicleId)) { StaticConnection.SendLogMessage(LogLevel.Error, StaticLogName, "Couldn't find busVehicleId for entity " + busEntityId); return(false); } string json = string.Empty; string app_id = "d95991f2"; string app_key = "db59c31bd87e57bbe3512137ca40a450"; string url = @"https://api.tfl.gov.uk/Vehicle/" + busVehicleId + @"/Arrivals?app_id=" + app_id + @"&app_key=" + app_key; StaticConnection.SendLogMessage(LogLevel.Info, StaticLogName, "sending request to: " + url); try { HttpWebRequest request = WebRequest.CreateHttp(url); request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { json = reader.ReadToEnd(); } dynamic arrivals = JsonConvert.DeserializeObject(json); List <string> nextStops = new List <string>(); dispatcher.busesNextStops.TryGetValue(busEntityId, out nextStops); Map <string, string> estimatedArrivals = new Map <string, string>(); foreach (var arrival in arrivals) { if (!estimatedArrivals.ContainsKey((string)arrival.naptanId)) { string expectedArrival = (string)arrival.expectedArrival; estimatedArrivals.Add(new System.Collections.Generic.KeyValuePair <string, string>((string)arrival.naptanId, expectedArrival)); if (DateTime.Parse(expectedArrival, System.Globalization.CultureInfo.InvariantCulture).CompareTo(DateTime.UtcNow) > 0) { // This could be optimised if (!nextStops.Contains((string)arrival.naptanId)) { nextStops.Insert(nextStops.Count, (string)arrival.naptanId); } } } } if (!MapReader.busStops.ContainsKey(nextStops.First())) { connection.SendDeleteEntityRequest(busEntityId, new Option <uint>()); StaticConnection.SendLogMessage(LogLevel.Info, StaticLogName, "Bus stop " + nextStops.First() + " was not found on map, DELETING entity " + busEntityId); string vehicleId; if (dispatcher.busesVehicleIds.TryGetValue(busEntityId, out vehicleId)) { Startup.busVehicleIds.Remove(vehicleId); } } var update = Bus.Update.FromInitialData(new BusData(busVehicleId, nextStops, estimatedArrivals)); StaticConnection.SendComponentUpdate(Bus.Metaclass, busEntityId, update); } catch (WebException ex) { StaticConnection.SendLogMessage(LogLevel.Info, StaticLogName, "web exception - status " + ex.Status); } return(true); }
public static void MoveCars(Connection connection, WorkerView dispatcher, MapReader mapReader) { Random random = new Random(); foreach (EntityId entityId in dispatcher.carsInAuthority) { Coordinates carPos; if (!dispatcher.entityPositions.TryGetValue(entityId, out carPos)) { connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "No car position for entityId: " + entityId.ToString()); } ulong currentNodeId; if (!dispatcher.carNodeIds.TryGetValue(entityId, out currentNodeId)) { connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "No car node for entityId: " + entityId.ToString() + " - randomising"); dispatcher.randomisePosition(entityId); continue; } ulong prevNodeId; if (!dispatcher.prevCarNodeIds.TryGetValue(entityId, out prevNodeId)) { connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "No prev car node for entityId: " + entityId.ToString()); } ulong currentRoadId; if (!dispatcher.carRoadIds.TryGetValue(entityId, out currentRoadId)) { connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "No car road id for entityId: " + entityId.ToString()); } ulong newCurrentNodeId = currentNodeId; ulong newPrevNodeId = prevNodeId; ulong newCurrentRoadId = currentRoadId; if (currentRoadId == 0) { connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "currentNodeId: " + currentNodeId + " prevNodeId: " + prevNodeId + " currentRoadId: " + currentRoadId + " for entityId: " + entityId.ToString()); } List <Coordinates> pathCoords = new List <Coordinates>(new Coordinates[] { mapReader.nodes[currentNodeId].coords }); List <ulong> pathNodes = new List <ulong>(new ulong[] { currentNodeId }); double newPathSegmentLength = 0; double pathLength = 0; bool pastFirstNode = false; ulong nextNodeId = currentNodeId; OsmNode nextNode = mapReader.nodes[nextNodeId]; double maxPathLength = 0; bool reachedSpeedLimit = false; bool bus = dispatcher.busesInAuthority.Contains(entityId); do { OsmNode currentCarNode; if (!mapReader.nodes.TryGetValue(pathNodes.Last(), out currentCarNode)) { connection.SendLogMessage(LogLevel.Info, connection.GetWorkerId(), "couldn't find current car node"); } // We need to pass the current node we're aiming for before proceeding to the next if (pastFirstNode) { List <ulong> attemptedNodes = new List <ulong>(); do { int highestSpeedLimit = 0; double smallestAngle = 180; ulong nearestNodeId = 0; DateTime predictedTime = new DateTime(); nextNodeId = currentCarNode.adjacentNodes[0]; Coordinates busStopToBusRelativeCoords = new Coordinates(); if (bus) { string nextStopAtcoCode = dispatcher.busesNextStops[entityId].First(); Map <string, string> arrivalEstimates = dispatcher.busesArrivalEstimate[entityId]; string nextStopExpectedTime; if (!arrivalEstimates.TryGetValue(nextStopAtcoCode, out nextStopExpectedTime)) { connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "Bus entity " + entityId + " couldn't get expected time for stop " + nextStopAtcoCode); goto EndOfThisEntityMovement; } predictedTime = DateTime.Parse(nextStopExpectedTime, System.Globalization.CultureInfo.InvariantCulture); int timeToBusStop = predictedTime.Subtract(DateTime.UtcNow).Seconds; //connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "Bus entity " + entityId + " should get to stop " + nextStopAtcoCode + " in " + timeToBusStop + " minutes"); ulong busStopNodeId; if (mapReader.busStops.TryGetValue(nextStopAtcoCode, out busStopNodeId)) { OsmNode busStopNode = mapReader.nodes[busStopNodeId]; busStopToBusRelativeCoords = Coords.Subtract(busStopNode.coords, carPos); nearestNodeId = mapReader.nearestRoadNodesToBusStops[busStopNodeId]; //connection.SendLogMessage(LogLevel.Info, connection.GetWorkerId(), "Bus entity " + entityId + " DID find stop" + nextStopAtcoCode); } else { connection.SendLogMessage(LogLevel.Info, connection.GetWorkerId(), "Bus entity " + entityId + " could not find stop " + nextStopAtcoCode + " DELETING"); connection.SendDeleteEntityRequest(entityId, new Option <uint>()); string vehicleId; if (dispatcher.busesVehicleIds.TryGetValue(entityId, out vehicleId)) { Startup.busVehicleIds.Remove(vehicleId); } goto EndOfThisEntityMovement; } if (timeToBusStop < 1 || Coords.Length(busStopToBusRelativeCoords) > 150) { if (moveVehicleToBusStop(connection, dispatcher, mapReader, entityId, nextStopAtcoCode)) { connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "Successfully teleported bus"); goto EndOfThisEntityMovement; } else { connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "Couldn't teleport bus"); } dispatcher.busesNextStops[entityId].RemoveAt(0); } } foreach (ulong nodeId in currentCarNode.adjacentNodes) { OsmNode node = mapReader.nodes[nodeId]; if (bus) { if (nodeId == nearestNodeId || currentCarNode.Id == nearestNodeId) { int timeToBusStop = predictedTime.Subtract(DateTime.UtcNow).Seconds; if (timeToBusStop > 30) { // time wasted } int timeSinceBusStop = DateTime.UtcNow.Subtract(predictedTime).Seconds; if (timeSinceBusStop < 30) { // wait at bus stop goto EndOfThisEntityMovement; } updateBusToNextStop(connection, dispatcher, entityId); } Coordinates nodeToBusRelativeCoodrs = Coords.Subtract(node.coords, carPos); double angleBetween = Coords.AngleBetween(busStopToBusRelativeCoords, nodeToBusRelativeCoodrs); if (angleBetween < smallestAngle && !attemptedNodes.Contains(nodeId)) { smallestAngle = angleBetween; nextNodeId = nodeId; } } else { foreach (ulong wayId in node.waysOn) { OsmWay way = mapReader.ways[wayId]; int limit = way.SpeedLimit; if (limit > highestSpeedLimit && !attemptedNodes.Contains(nodeId) && random.NextDouble() < 0.7) { highestSpeedLimit = limit; nextNodeId = nodeId; } } } } attemptedNodes.Add(nextNodeId); if (!mapReader.nodes.ContainsKey(nextNodeId)) { connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "couldn't find adjacent node"); } if (!mapReader.roadNodes.Contains(nextNodeId)) { connection.SendLogMessage(LogLevel.Error, connection.GetWorkerId(), "adjacent node is not in road nodes"); } }while (nextNodeId == prevNodeId && currentCarNode.adjacentNodes.Count > 1); newPrevNodeId = pathNodes.Last(); nextNode = mapReader.nodes[nextNodeId]; pathCoords.Add(nextNode.coords); pathNodes.Add(nextNodeId); } newPathSegmentLength = Coords.Dist(carPos, pathCoords.Last()); OsmWay currentRoadWay = mapReader.ways[currentRoadId]; maxPathLength = MilesPerHoursTo10metersPerTimeInterval(currentRoadWay.SpeedLimit); if (pathLength + newPathSegmentLength > maxPathLength) { double correctSegmentLength = maxPathLength - pathLength; Coordinates currentDirection = Coords.Subtract(pathCoords.Last(), carPos); carPos = Coords.Add(carPos, Coords.ScaleToLength(currentDirection, correctSegmentLength)); pathLength += correctSegmentLength; reachedSpeedLimit = true; } else { pathLength += newPathSegmentLength; carPos = nextNode.coords; } pastFirstNode = true; }while (!reachedSpeedLimit); if (newPosIsACarCrash(connection, dispatcher, carPos, nextNodeId, newPrevNodeId, entityId, maxPathLength * 0.8)) { continue; } newCurrentNodeId = nextNodeId; if (!nextNode.waysOn.Contains(currentRoadId)) { newCurrentRoadId = nextNode.waysOn.First(); } var positionComponentUpdate = Position.Update.FromInitialData(new PositionData(carPos)); var carComponentUpdate = Car.Update.FromInitialData(new CarData(newCurrentNodeId, newPrevNodeId, newCurrentRoadId)); connection.SendComponentUpdate(Position.Metaclass, entityId, positionComponentUpdate); // short-curcuits by default connection.SendComponentUpdate(Car.Metaclass, entityId, carComponentUpdate); EndOfThisEntityMovement :; } }