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); }
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; }
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); }
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)); }
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); }
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); }
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); }
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); } }
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); }
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); }
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); }
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(); }); }
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); }
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); }
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); }
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); }
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; }
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); }