Example #1
0
        public void OnTimer_ForStart_WitWaitingRider_ShouldMatchWithRider()
        {
            Beacon beacon  = new Beacon(new byte[] { 0, 0, 0, 0, 0, 1 }, 0);
            Rider  martijn = new Rider("Martijn", beacon);

            //rider enters start box
            startId.EmitIdEvent(martijn, new DateTime(2000, 1, 1, 1, 1, 1));

            //rider triggers timing gate
            timer.EmitTriggerEvent(100, "Timer", 0, new DateTime(2000, 1, 1, 1, 1, 1));

            source.Cancel();

            RaceSummary summary = race.Result;
            var         state   = subject.GetState;

            //we expect an EnteredEvent and a TimingEvent, in that order
            Assert.AreEqual(2, summary.Events.Count);

            IdEvent     id    = summary.Events[0] as IdEvent;
            TimingEvent start = summary.Events[1] as TimingEvent;

            Assert.AreEqual(state.onTrack[0].id, id);
            Assert.AreEqual(state.onTrack[0].timer, start);

            Assert.AreEqual("Martijn", start.Rider.Name);
            Assert.AreEqual(100L, start.Microseconds);
            Assert.AreEqual(new DateTime(2000, 1, 1, 1, 1, 1), start.Time);

            Assert.AreEqual(0, state.waiting.Count);
            Assert.AreEqual(0, state.unmatchedIds.Count);
            Assert.AreEqual(0, state.unmatchedTimes.Count);
        }
Example #2
0
        public SimulationTimingUnit(RaceSummary race)
            : base(race)
        {
            FinishedEvent finish = race.Events.Find(r => r is FinishedEvent) as FinishedEvent;

            StartId = finish.TimeStart.GateId;
            EndId   = finish.TimeEnd.GateId;
        }
Example #3
0
        public void RaceSummary_ReadAndWrite_ShouldBeSymmetric()
        {
            Beacon martijnBeacon = new Beacon(new byte[] { 0, 0, 0, 0, 0, 1 }, 2);

            martijnBeacon.Rssi          = 3;
            martijnBeacon.MeasuredPower = 4;

            Beacon bertBeacon = new Beacon(new byte[] { 0, 0, 0, 0, 0, 5 }, 6);

            bertBeacon.Rssi          = 7;
            bertBeacon.MeasuredPower = 8;

            IdEvent     entered = new IdEvent(new DateTime(2000, 1, 1), new Rider("Martijn", martijnBeacon), "StartId", Direction.Enter);
            TimingEvent timing  = new TimingEvent(new DateTime(2000, 1, 1), new Rider("Bert", bertBeacon), 100, 1);

            TrackerConfig config = new TrackerConfig
            {
                EndMatchTimeout   = 9,
                StartTimingGateId = 10,
                EndTimingGateId   = 11
            };

            RaceSummary subject = new RaceSummary(new List <RaceEvent> {
                entered, timing
            }, config, "StartId", "EndId");

            MemoryStream stream = new MemoryStream();

            subject.WriteSummary(stream);

            stream.Seek(0, SeekOrigin.Begin);

            RaceSummary parsed = RaceSummary.ReadSummary(stream);

            foreach ((Rider r1, Rider r2) in subject.Riders.Zip(parsed.Riders))
            {
                Assert.IsTrue(CompareRiders(r1, r2));
            }

            CollectionAssert.AreEqual(subject.Events.Select(e => e.EventId).ToList(), parsed.Events.Select(e => e.EventId).ToList());
            CollectionAssert.AreEqual(subject.Events.Select(e => e.GetType()).ToList(), parsed.Events.Select(e => e.GetType()).ToList());

            foreach ((RaceEvent e1, RaceEvent e2) in subject.Events.Zip(parsed.Events))
            {
                Assert.IsTrue(CompareRiders(e1.Rider, e2.Rider));
            }

            Assert.AreEqual("StartId", parsed.StartId);
            Assert.AreEqual("EndId", parsed.EndId);

            Assert.AreEqual(config.StartTimingGateId, parsed.Config.StartTimingGateId);
            Assert.AreEqual(config.EndTimingGateId, parsed.Config.EndTimingGateId);
            Assert.AreEqual(config.EndMatchTimeout, parsed.Config.EndMatchTimeout);
        }
Example #4
0
        public StatusCodeResult Simulate([FromBody] JObject summary)
        {
            byte[]      text = Encoding.UTF8.GetBytes(summary.ToString());
            RaceSummary parsed;

            using (MemoryStream stream = new MemoryStream(text))
            {
                parsed = RaceSummary.ReadSummary(stream);
            }
            manager.Start(parsed);
            return(new StatusCodeResult(200));
        }
Example #5
0
        public void OnTimer_ForStart_WithoutWaitingRider_ShouldIgnoreEvent()
        {
            //0 is the start gate
            timer.EmitTriggerEvent(100, "Timer", 0, new DateTime(2000, 1, 1, 1, 1, 1));

            source.Cancel();

            RaceSummary summary = race.Result;
            var         state   = subject.GetState;

            Assert.AreEqual(0, summary.Events.Count);
            Assert.AreEqual(0, state.onTrack.Count);
            Assert.AreEqual(0, state.waiting.Count);
        }
Example #6
0
        public void DSQ_WithoutRiderOnTrack_ShouldBeIgnored()
        {
            subject.AddEvent(new DSQEventArgs(DateTime.Now, "nope", "staff", "test"));

            source.Cancel();
            RaceSummary summary = race.Result;

            //The dsq event is still recorded, but its not applied to any lap
            Assert.AreEqual(1, summary.Events.Count);
            DSQEvent dsq = summary.Events[0] as DSQEvent;

            Assert.IsNull(dsq.Rider);
            Assert.AreEqual("test", dsq.Reason);
            Assert.AreEqual("staff", dsq.StaffName);
        }
Example #7
0
        public void Penalty_WithoutRiderOnTrack_ShouldBeIgnored()
        {
            subject.AddEvent(new PenaltyEventArgs(DateTime.Now, "nope", "staff", "test", 1));

            source.Cancel();
            RaceSummary summary = race.Result;

            //The penalty event is still recorded, but its not applied to any lap
            Assert.AreEqual(1, summary.Events.Count);
            PenaltyEvent penalty = summary.Events[0] as PenaltyEvent;

            Assert.IsNull(penalty.Rider);
            Assert.AreEqual("test", penalty.Reason);
            Assert.AreEqual("staff", penalty.StaffName);
            Assert.AreEqual(1, penalty.Seconds);
        }
Example #8
0
        public void OnTimer_ForEnd_ShouldRespectTimeout(int timeDifference)
        {
            Beacon martijnBeacon = new Beacon(new byte[] { 0, 0, 0, 0, 0, 1 }, 0);
            Rider  martijn       = new Rider("Martijn", martijnBeacon);

            subject.AddRider(martijn);

            //rider enters start box
            startId.EmitIdEvent(martijn, new DateTime(2000, 1, 1, 1, 1, 1));

            //rider triggers timing gate
            timer.EmitTriggerEvent(100, "Timer", 0, new DateTime(2000, 1, 1, 1, 1, 20));

            //rider triggers id in stop box
            endId.EmitIdEvent(martijn, new DateTime(2000, 1, 1, 1, 2, 20));

            //end timer triggered 11 seconds apart, should not match
            timer.EmitTriggerEvent(500, "Timer", 1, new DateTime(2000, 1, 1, 1, 2, 20 + timeDifference + Math.Sign(timeDifference)));

            //end timer triggered 10 seconds apart, should match
            timer.EmitTriggerEvent(500, "Timer", 1, new DateTime(2000, 1, 1, 1, 2, 20 + timeDifference));

            source.Cancel();
            RaceSummary summary = race.Result;
            var         state   = subject.GetState;

            FinishedEvent finish = summary.Events.Last() as FinishedEvent;

            Assert.AreEqual(20 + timeDifference, finish.TimeEnd.Time.Second);

            //There should be nothing going on in the race at this point
            Assert.AreEqual(0, state.waiting.Count);
            Assert.AreEqual(0, state.unmatchedIds.Count);
            Assert.AreEqual(0, state.onTrack.Count);

            //depending on whether the timeDifference is negative or positive the unmatched id should be cleared
            //on positive timeDifference the unmatched time is not old enough to be cleared
            if (timeDifference > 0)
            {
                Assert.AreEqual(1, state.unmatchedTimes.Count);
            }
            else
            {
                Assert.AreEqual(0, state.unmatchedTimes.Count);
            }
        }
Example #9
0
        protected override int OnExecute(CommandLineApplication app)
        {
            RaceManager manager = new RaceManager();
            RaceSummary summary;

            using (Stream reader = new FileStream(SummaryFile, FileMode.Open))
            {
                summary = RaceSummary.ReadSummary(reader);
            }


            manager.Start(summary);

            manager.CombinedTasks.Wait();

            return(0);
        }
Example #10
0
        public void OnEndId_WithoutRiderOnTrack_ShouldIgnoreEvent()
        {
            Beacon beacon  = new Beacon(new byte[] { 0, 0, 0, 0, 0, 1 }, 0);
            Rider  martijn = new Rider("Martijn", beacon);

            endId.EmitIdEvent(martijn, new DateTime(2000, 1, 1, 1, 1, 1));

            source.Cancel();

            RaceSummary summary = race.Result;
            var         state   = subject.GetState;

            Assert.AreEqual(0, summary.Events.Count);
            Assert.AreEqual(0, state.onTrack.Count);
            Assert.AreEqual(0, state.waiting.Count);
            Assert.AreEqual(0, state.unmatchedIds.Count);
            Assert.AreEqual(0, state.unmatchedTimes.Count);
        }
Example #11
0
        public async Task <IList <RaceSummary> > GetRaceSummary()
        {
            var raceSummaries = new List <RaceSummary>();
            var races         = await context.RaceRepository.GetAll();

            var bets = await context.BetRepository.GetAll();

            if (races != null && races.Count > 0)
            {
                foreach (var race in races)
                {
                    var raceBets    = bets.Where(b => b.RaceId == race.Id);
                    var raceSummary = new RaceSummary();
                    raceSummary.Status = race.Status;
                    raceSummary.Stake  = raceBets.Sum(s => s.Stake);
                    var horseIdBetCountMap = raceBets.GroupBy(s => s.HorseId).ToDictionary(s => s.Key, s => new { BetCount = s.Count(), TotalStake = s.Sum(b => b.Stake) });
                    raceSummary.Hourses = new List <HorseSummary>();
                    foreach (var horse in race.Horses)
                    {
                        var horseSummary = new HorseSummary();
                        horseSummary.Id   = horse.Id;
                        horseSummary.Name = horse.Name;

                        if (horseIdBetCountMap.ContainsKey(horse.Id))
                        {
                            var betValue = horseIdBetCountMap[horse.Id];
                            horseSummary.BetCount = betValue.BetCount;
                            //Consider the formula that Payout will be Stake for all customer * odds
                            horseSummary.PayOut = betValue.TotalStake * horse.Odds;
                        }
                        else
                        {
                            horseSummary.BetCount = 0;
                            horseSummary.PayOut   = 0;
                        }
                        raceSummary.Hourses.Add(horseSummary);
                    }

                    raceSummaries.Add(raceSummary);
                }
            }
            return(raceSummaries);
        }
Example #12
0
        public void OnEndId_WithDifferentRiderOnTrack_ShouldIgnoreEvent()
        {
            Beacon martijnBeacon = new Beacon(new byte[] { 0, 0, 0, 0, 0, 1 }, 0);
            Rider  martijn       = new Rider("Martijn", martijnBeacon);

            Beacon richardBeacon = new Beacon(new byte[] { 0, 0, 0, 0, 0, 2 }, 0);
            Rider  richard       = new Rider("Richard", richardBeacon);

            //rider enters start box
            startId.EmitIdEvent(martijn, new DateTime(2000, 1, 1, 1, 1, 1));

            //rider triggers timing gate
            timer.EmitTriggerEvent(100, "Timer", 0, new DateTime(2000, 1, 1, 1, 1, 1));

            //rider not on track triggers end id
            endId.EmitIdEvent(richard, new DateTime(2000, 1, 1, 1, 1, 1));

            source.Cancel();

            RaceSummary summary = race.Result;
            var         state   = subject.GetState;

            //we expect only the events for Martijn tto be recorded
            Assert.AreEqual(2, summary.Events.Count);

            IdEvent     id    = summary.Events[0] as IdEvent;
            TimingEvent start = summary.Events[1] as TimingEvent;

            Assert.AreEqual(state.onTrack[0].id, id);
            Assert.AreEqual(state.onTrack[0].timer, start);

            Assert.AreEqual("Martijn", start.Rider.Name);
            Assert.AreEqual(100L, start.Microseconds);
            Assert.AreEqual(new DateTime(2000, 1, 1, 1, 1, 1), start.Time);

            //no riders should be waiting at the start.
            //no end times or ids shoudl be waiting to be matched
            Assert.AreEqual(0, state.waiting.Count);
            Assert.AreEqual(0, state.unmatchedIds.Count);
            Assert.AreEqual(0, state.unmatchedTimes.Count);
        }
        /// <summary>
        /// Simulates a race from a json that contains all the race events
        /// </summary>
        /// <param name="simulationData"></param>
        public void Start(RaceSummary simulationData)
        {
            Stop();

            XmlConfigurator.Configure(new FileInfo("logConfig.xml"));

            //we need the simulation specific methods in the constructor
            SimulationRiderIdUnit startId    = new SimulationRiderIdUnit(simulationData.StartId, simulationData);
            SimulationRiderIdUnit endId      = new SimulationRiderIdUnit(simulationData.EndId, simulationData);
            SimulationTimingUnit  timingUnit = new SimulationTimingUnit(simulationData);

            displays.Add(timingUnit);
            startGate = startId;
            endGate   = endId;
            timing    = timingUnit;

            startId.Initialize();
            endId.Initialize();
            timingUnit.Initialize();

            tracker = new RaceTracker(timing, startId, endId, simulationData.Config, simulationData.Riders);
            HookEvents(tracker);

            var trackTask = tracker.Run(source.Token);

            var startTask = startId.Run(source.Token);
            var endTask   = endId.Run(source.Token);
            var timeTask  = timingUnit.Run(source.Token);

            //will complete when all units run out of events to simulate
            var unitsTask = Task.WhenAll(startTask, endTask, timeTask);

            CombinedTasks = Task.Run(() =>
            {
                unitsTask.Wait();
                source.Cancel();
                trackTask.Wait();
            });
        }
Example #14
0
        public void OnStartId_ShouldSaveEvent()
        {
            Beacon beacon  = new Beacon(new byte[] { 0, 0, 0, 0, 0, 1 }, 0);
            Rider  martijn = new Rider("Martijn", beacon);

            startId.EmitIdEvent(martijn, new DateTime(2000, 1, 1, 1, 1, 1));

            source.Cancel();

            RaceSummary summary = race.Result;
            var         state   = subject.GetState;

            Assert.AreEqual(1, summary.Events.Count);

            IdEvent entered = summary.Events[0] as IdEvent;

            Assert.AreEqual(entered, state.waiting[0]);

            Assert.AreEqual("Martijn", entered.Rider.Name);
            CollectionAssert.AreEqual(new byte[] { 0, 0, 0, 0, 0, 1 }, entered.Rider.Beacon.Identifier);
            Assert.AreEqual(new DateTime(2000, 1, 1, 1, 1, 1), entered.Time);
        }
Example #15
0
        public void OnTimer_ForEnd_WithoutRiderLeft_ShouldSaveEvent()
        {
            //1 is the end gate
            timer.EmitTriggerEvent(100, "Timer", 1, new DateTime(2000, 1, 1, 1, 1, 1));

            source.Cancel();

            RaceSummary summary = race.Result;
            var         state   = subject.GetState;

            //It is possible for the end timing gate to be triggered before the rider id is caught be the end id unit
            //save the timer event for later matching
            Assert.AreEqual(1, summary.Events.Count);

            //the state should match the summary
            TimingEvent end = summary.Events[0] as TimingEvent;

            Assert.AreEqual(state.unmatchedTimes[0], end);

            Assert.AreEqual(null, end.Rider); //a lone timer event cannot have a rider
            Assert.AreEqual(100L, end.Microseconds);
            Assert.AreEqual(new DateTime(2000, 1, 1, 1, 1, 1), end.Time);
        }
Example #16
0
        public void RaceWithMultipleOnTrack_AndDNF_ShouldWork()
        {
            SimulateRaceWithDNF();

            source.Cancel();
            RaceSummary summary = race.Result;
            var         state   = subject.GetState;

            List <FinishedEvent> finishes = summary.Events.Where(e => e is FinishedEvent).Select(e => e as FinishedEvent).ToList();
            UnitDNFEvent         dnf      = summary.Events.Last() as UnitDNFEvent;

            Assert.AreEqual("Martijn", finishes[0].Rider.Name);
            Assert.AreEqual("Bert", finishes[1].Rider.Name);

            Assert.AreEqual("Richard", dnf.Rider.Name);
            Assert.AreEqual("Bert", dnf.OtherRider.Rider.Name);

            //There should be nothing going on in the race at this point
            Assert.AreEqual(0, state.waiting.Count);
            Assert.AreEqual(0, state.unmatchedIds.Count);
            Assert.AreEqual(0, state.onTrack.Count);
            Assert.AreEqual(0, state.unmatchedTimes.Count);
        }
Example #17
0
        public void OnEndId_WithAccidentalEndId_ShouldMatch()
        {
            Beacon martijnBeacon = new Beacon(new byte[] { 0, 0, 0, 0, 0, 1 }, 0);
            Rider  martijn       = new Rider("Martijn", martijnBeacon);

            subject.AddRider(martijn);

            //rider enters start box
            startId.EmitIdEvent(martijn, new DateTime(2000, 1, 1, 1, 1, 1));

            //rider triggers timing gate
            timer.EmitTriggerEvent(100, "Timer", 0, new DateTime(2000, 1, 1, 1, 1, 1));

            //rider triggers id in stop box accidentally (maybe the track was constructed to pass too close to stop box
            endId.EmitIdEvent(martijn, new DateTime(2000, 1, 1, 1, 2, 20));

            //rider triggers id in stop box for real five seconds later
            endId.EmitIdEvent(martijn, new DateTime(2000, 1, 1, 1, 2, 25));

            //end timer triggered 1 second later
            timer.EmitTriggerEvent(500, "Timer", 1, new DateTime(2000, 1, 1, 1, 2, 26));

            source.Cancel();
            RaceSummary summary = race.Result;
            var         state   = subject.GetState;

            FinishedEvent finish = summary.Events.Last() as FinishedEvent;

            Assert.AreEqual(25, finish.Left.Time.Second);

            //There should be nothing going on in the race at this point, except for the lingering end id event
            Assert.AreEqual(0, state.waiting.Count);
            Assert.AreEqual(0, state.onTrack.Count);
            Assert.AreEqual(0, state.unmatchedTimes.Count);

            Assert.AreEqual(1, state.unmatchedIds.Count);
        }
Example #18
0
 public BaseSimulationUnit(RaceSummary race)
 {
     this.race = race;
 }
 /// <summary>
 /// Creates a new Rider id unit that simulates the events fom the provided race
 /// </summary>
 /// <param name="start">When true this sensor will simulate events for riders entering the track, when false for leaving the track</param>
 public SimulationRiderIdUnit(string unitId, RaceSummary race)
     : base(race)
 {
     this.UnitId = unitId;
 }
Example #20
0
        public void OnEndId_WithMatchingTiming_ShouldCompleteLap(bool includeUnmatchedTime, bool includeUnmatchedId, bool flipEndEvents)
        {
            Beacon martijnBeacon = new Beacon(new byte[] { 0, 0, 0, 0, 0, 1 }, 0);
            Rider  martijn       = new Rider("Martijn", martijnBeacon);

            subject.AddRider(martijn);

            Beacon richardBeacon = new Beacon(new byte[] { 0, 0, 0, 0, 0, 2 }, 0);
            Rider  richard       = new Rider("Richard", richardBeacon);

            subject.AddRider(richard);

            //rider enters start box
            startId.EmitIdEvent(martijn, new DateTime(2000, 1, 1, 1, 1, 1));

            //rider triggers timing gate
            timer.EmitTriggerEvent(100, "Timer", 0, new DateTime(2000, 1, 1, 1, 1, 2));

            //somebody walks through end timing gate 10 secs after rider has started
            if (includeUnmatchedTime)
            {
                timer.EmitTriggerEvent(400, "Timer", 1, new DateTime(2000, 1, 1, 1, 1, 12));
            }

            //a different rider gets too close to the stop box
            if (includeUnmatchedId)
            {
                endId.EmitIdEvent(richard, new DateTime(2000, 1, 1, 1, 1, 30));
            }

            List <Action> endEvents = new List <Action>
            {
                //rider triggers id in stop box
                () => endId.EmitIdEvent(martijn, new DateTime(2000, 1, 1, 1, 2, 1)),

                //rider triggers timing in stop box
                () => timer.EmitTriggerEvent(500, "Timer", 1, new DateTime(2000, 1, 1, 1, 2, 2))
            };

            if (flipEndEvents)
            {
                endEvents.Reverse();
            }

            foreach (Action a in endEvents)
            {
                a.Invoke();
            }

            source.Cancel();
            RaceSummary summary = race.Result;
            var         state   = subject.GetState;

            FinishedEvent finish = race.Result.Events.Last() as FinishedEvent;

            //Martijn should have done a lightning fast 400 microsecond lap
            Assert.AreEqual("Martijn", finish.Rider.Name);
            Assert.AreEqual(400L, finish.LapTime);

            //There should be nothing going on in the race at this point
            Assert.AreEqual(0, state.waiting.Count);
            Assert.AreEqual(0, state.unmatchedIds.Count);
            Assert.AreEqual(0, state.unmatchedTimes.Count);
            Assert.AreEqual(0, state.onTrack.Count);
        }