Exemplo n.º 1
0
 public LocationEvent(Skier skier, DateTimeOffset time)
 {
     SkierId   = skier.Id;
     Latitude  = skier.Location.Latitude;
     Longitude = skier.Location.Longitude;
     EventTime = time;
 }
Exemplo n.º 2
0
        private void LoadUnloadSkiers(SimulatedChairlift lift, long currentTime)
        {
            for (int i = 0; i < lift.ChairLift.PassengerCount && lift.SkiersWaiting.Count > 0; i++)
            {
                Skier skier = lift.SkiersWaiting.Dequeue();
                skier.StartTimeForCurrentStage = currentTime;
                skier.Location = lift.ChairLift.Top; // TODO: interpolate location between bottom and top
                Debug.Assert(!lift.SkiersRiding.Contains(skier));
                lift.SkiersRiding.Enqueue(skier);
            }

            for (int i = 0; i < lift.ChairLift.PassengerCount && lift.SkiersRiding.Count > 0; i++)
            {
                Skier skier = lift.SkiersRiding.Peek();
                if (currentTime - skier.StartTimeForCurrentStage >= lift.ChairLift.TimeToTop)
                {
                    skier = lift.SkiersRiding.Dequeue();
                    skier.StartTimeForCurrentStage = currentTime;
                    skier.Location = lift.ChairLift.Top;
                    // TODO: randomize new chairlift target
                    Debug.Assert(!lift.SkiersSkiingToThisLift.Contains(skier));
                    lift.SkiersSkiingToThisLift.Add(skier);
                }

                Debug.Assert(lift.SkiersRiding.Contains(skier) ^ lift.SkiersSkiingToThisLift.Contains(skier));
            }

            lift.LastLoadTime = currentTime;
        }
Exemplo n.º 3
0
        private void ReportOut(long currentTime, List <SimulatedChairlift> simulatedLifts, Skier reference, Stopwatch watch)
        {
            Console.WriteLine($"------------{currentTime}");

            string ridingLift    = simulatedLifts.SingleOrDefault(l => l.SkiersRiding.Contains(reference))?.ChairLift.Name ?? "<none>";
            string waitingLift   = simulatedLifts.SingleOrDefault(l => l.SkiersWaiting.Contains(reference))?.ChairLift.Name ?? "<none>";
            string skiiingToLift = simulatedLifts.SingleOrDefault(l => l.SkiersSkiingToThisLift.Contains(reference))?.ChairLift.Name ?? "<none>";

            if (ridingLift != "<none>" && waitingLift != "<none>" ||
                ridingLift != "<none>" && skiiingToLift != "<none>" ||
                waitingLift != "<none>" && skiiingToLift != "<none>")
            {
                Debug.Assert(false);
            }
            Console.WriteLine($"{reference.Id}\t{reference.Location.Latitude}\t{waitingLift}\t{ridingLift}\t{skiiingToLift}\t{watch.ElapsedMilliseconds}");

            string line = "waiting";

            foreach (var lift in simulatedLifts)
            {
                line += $"\t{lift.SkiersWaiting.Count}";
            }
            Console.WriteLine(line);

            line = "riding";
            foreach (var lift in simulatedLifts)
            {
                line += $"\t{lift.SkiersRiding.Count}";
            }
            Console.WriteLine(line);
        }
Exemplo n.º 4
0
        public void Start()
        {
            Random random = new Random();

            List <SimulatedChairlift> simulatedLifts = Lifts.Select(l => new SimulatedChairlift(l)).ToList();

            // TODO: add new skiers gradually
            List <Skier> skiers = new List <Skier>(_skierCount);

            for (int i = 0; i < _skierCount; i++)
            {
                // TODO: skew towards easier runs
                int   lift  = random.Next(0, Lifts.Length);
                Skier skier = new Skier {
                    Location = simulatedLifts[lift].ChairLift.Bottom
                };
                simulatedLifts[lift].SkiersWaiting.Enqueue(skier);
                skiers.Add(skier);
            }

            Skier reference = simulatedLifts[0].SkiersWaiting.Peek();

            long      currentTime = 0;
            Stopwatch watch       = new Stopwatch();

            while (true)
            {
                watch.Restart();

                foreach (SimulatedChairlift lift in simulatedLifts)
                {
                    if (currentTime - lift.LastLoadTime >= lift.ChairLift.TimeBetweenLoads)
                    {
                        LoadUnloadSkiers(lift, currentTime);
                    }

                    // TODO: variability in time-to-bottom
                    Func <Skier, bool> doneWithRunPredicate = s => currentTime - s.StartTimeForCurrentStage >= lift.ChairLift.AverageTimeDown;

                    MoveSkiersToWaiting(currentTime, lift, doneWithRunPredicate);
                }

                currentTime++;
                watch.Stop();
                if (watch.Elapsed < _oneSecond)
                {
                    Thread.Sleep(_oneSecond - watch.Elapsed);
                }

                if (currentTime % _reportPeriod == 0)
                {
                    // Create a real timeline for events by assuming the simulation starts at 8 AM and goes on in real time
                    DateTimeOffset now       = DateTimeOffset.Now;
                    DateTimeOffset eventTime = new DateTimeOffset(now.Year, now.Month, now.Day, 8, 0, 0, now.Offset);
                    eventTime = eventTime.Add(TimeSpan.FromSeconds(currentTime));
                    // Create a copy of the list and of the data since we'll send this in the background and want
                    // a stable view of the state of the simulation
                    SendLocationEvents(skiers.Select(s => new LocationEvent(s, eventTime)).ToList());
                }

                if (currentTime % 4 == 0)
                {
                    ReportOut(currentTime, simulatedLifts, reference, watch);
                }

                CheckInput(currentTime, simulatedLifts);
            }
        }