Пример #1
0
 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);
     }
 }
Пример #2
0
 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);
             }
         }
     }
 }
Пример #3
0
        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);
            }
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
 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);
 }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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 :;
            }
        }