public void CompareTo_ShouldConsiderDNFSlower() { Beacon martijnBeacon = new Beacon(new byte[] { 0, 0, 0, 0, 0, 1 }, 2); Rider martijn = new Rider("Martijn", martijnBeacon); //make a regular lap IdEvent startId = new IdEvent(DateTime.Now, martijn, "StartId", Direction.Enter); TimingEvent startTiming = new TimingEvent(DateTime.Now, martijn, 100, 0); IdEvent endId = new IdEvent(DateTime.Now, martijn, "EndId", Direction.Enter); TimingEvent endTiming = new TimingEvent(DateTime.Now, martijn, 200, 1); FinishedEvent finish = new FinishedEvent(startId, startTiming, endTiming, endId); Lap normalLap = new Lap(finish); //make a DNF lap IdEvent dnfStartId = new IdEvent(DateTime.Now, martijn, "StartId", Direction.Enter); ManualDNFEvent manualDnf = new ManualDNFEvent(dnfStartId, "staff"); UnitDNFEvent unitDnf = new UnitDNFEvent(finish, dnfStartId); Lap manualDnfLap = new Lap(manualDnf); Lap unitDnfLap = new Lap(unitDnf); //a dnf lap should always be slower (bigger) than a finished lap Assert.AreEqual(1, manualDnfLap.CompareTo(normalLap)); Assert.AreEqual(-1, normalLap.CompareTo(manualDnfLap)); Assert.AreEqual(1, unitDnfLap.CompareTo(normalLap)); Assert.AreEqual(-1, normalLap.CompareTo(unitDnfLap)); //dnf laps have no mutual ordering Assert.AreEqual(1, manualDnfLap.CompareTo(unitDnfLap)); Assert.AreEqual(1, unitDnfLap.CompareTo(manualDnfLap)); }
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); }
/// <summary> /// Get the first time at which the floor position of a given timing group is equal to a given value. /// </summary> /// <param name="floorposition">The target value of the timing group's floor position.</param> /// <param name="timingGroup">The timing group to search in.</param> /// <returns>The first time at which the floor postion of group <paramref name="timingGroup"/> is equal to <paramref name="floorposition"/></returns> public int GetFirstTimingFromFloorPosition(float floorposition, int timingGroup) { int maxIndex = timingEventGroups[timingGroup].Length; floorposition /= scrollSpeed; TimingEvent first = timingEventGroups[timingGroup][0]; if (first.bpm * (floorposition - first.baseFloorPosition) < 0) { return(Mathf.RoundToInt((floorposition - first.baseFloorPosition) / first.bpm)); } for (int i = 0; i < maxIndex - 1; i++) { TimingEvent curr = timingEventGroups[timingGroup][i]; TimingEvent next = timingEventGroups[timingGroup][i + 1]; if ((curr.baseFloorPosition < floorposition && next.baseFloorPosition > floorposition) || (curr.baseFloorPosition > floorposition && next.baseFloorPosition < floorposition)) { float result = (floorposition - curr.baseFloorPosition) / curr.bpm + curr.timing; return(Mathf.RoundToInt(result)); } } TimingEvent last = timingEventGroups[timingGroup][maxIndex - 1]; float lastresult = (floorposition - last.baseFloorPosition) / last.bpm + last.timing; return(Mathf.RoundToInt(lastresult)); }
/// <summary> /// Create necessary information for a given timing event group, including correct base floor positions. /// </summary> /// <param name="timingGroups">The raw aff timing components.</param> /// <param name="i">The index of the timing group to set up.</param> private void SetupTimingGroup(List <List <TimingRaw> > timingGroups, int i) { var tg = timingGroups[i]; tg.Sort((item1, item2) => item1.timing.CompareTo(item2.timing)); timingEventGroups[i] = new TimingEvent[tg.Count]; timingEventGroups[i][0] = new TimingEvent { timing = tg[0].timing, baseFloorPosition = 0, bpm = tg[0].bpm }; for (int j = 1; j < tg.Count; j++) { timingEventGroups[i][j] = new TimingEvent { timing = tg[j].timing, //Calculate the base floor position baseFloorPosition = tg[j - 1].bpm * (tg[j].timing - tg[j - 1].timing) + timingEventGroups[i][j - 1].baseFloorPosition, bpm = tg[j].bpm }; } }
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 virtual void TestEivlTsFull() { PhysicalQuantity low = new PhysicalQuantity(new BigDecimal("120"), Ca.Infoway.Messagebuilder.Domainvalue.Basic.UnitsOfMeasureCaseSensitive .CENTIMETRE); PhysicalQuantity high = new PhysicalQuantity(new BigDecimal("170"), Ca.Infoway.Messagebuilder.Domainvalue.Basic.UnitsOfMeasureCaseSensitive .CENTIMETRE); Interval <PhysicalQuantity> ivl = IntervalFactory.CreateLowHigh(low, high); TimingEvent timingEvent = Ca.Infoway.Messagebuilder.Domainvalue.Basic.TimingEvent.ACM; EventRelatedPeriodicIntervalTime @event = new EventRelatedPeriodicIntervalTime(ivl, timingEvent); string result = new EivlTsR2PropertyFormatter().Format(CreateContext("EIVL<TS>"), new EIVLImpl <EventRelatedPeriodicIntervalTime >(@event)); Assert.IsTrue(this.result.IsValid()); AssertXml("xml output", "<eventRelatedPeriod><event code=\"ACM\" codeSystem=\"2.16.840.1.113883.5.139\" codeSystemName=\"TimingEvent\" displayName=\"Acm\"/><offset><low unit=\"cm\" value=\"120\"/><high unit=\"cm\" value=\"170\"/></offset></eventRelatedPeriod>" , result, true); }
public void CompareTo_ShouldConsiderPernalties() { Beacon martijnBeacon = new Beacon(new byte[] { 0, 0, 0, 0, 0, 1 }, 2); Rider martijn = new Rider("Martijn", martijnBeacon); //make a fast lap with loads of penalties IdEvent startId = new IdEvent(DateTime.Now, martijn, "StartId", Direction.Enter); TimingEvent startTiming = new TimingEvent(DateTime.Now, martijn, 100, 0); IdEvent endId = new IdEvent(DateTime.Now, martijn, "EndId", Direction.Enter); TimingEvent endTiming = new TimingEvent(DateTime.Now, martijn, 200, 1); FinishedEvent fastFinish = new FinishedEvent(startId, startTiming, endTiming, endId); Lap fast = new Lap(fastFinish); fast.AddPenalties(new List <PenaltyEvent> { new PenaltyEvent(DateTime.Now, martijn, "reason", 1, "staff"), new PenaltyEvent(DateTime.Now, martijn, "reason", 2, "staff") }); //make a slower lap without penalties IdEvent slowStartId = new IdEvent(DateTime.Now, martijn, "StartId", Direction.Enter); TimingEvent slowStartTiming = new TimingEvent(DateTime.Now, martijn, 100, 0); IdEvent slowEndId = new IdEvent(DateTime.Now, martijn, "EndId", Direction.Enter); TimingEvent slowEndTiming = new TimingEvent(DateTime.Now, martijn, 300, 1); FinishedEvent slowFinish = new FinishedEvent(slowStartId, slowStartTiming, slowEndTiming, slowEndId); Lap slow = new Lap(slowFinish); //without penalties the lap time should dictate the ordering Assert.AreEqual(1, slow.CompareTo(fast, false)); Assert.AreEqual(-1, fast.CompareTo(slow, false)); //with penalties the slower lap is actually faster Assert.AreEqual(-1, slow.CompareTo(fast, true)); Assert.AreEqual(1, fast.CompareTo(slow, true)); //the default should take penalties into account Assert.AreEqual(-1, slow.CompareTo(fast)); Assert.AreEqual(1, fast.CompareTo(slow)); }
public void CompareTo_ShouldConsiderDSQOnFinshedLaps() { Beacon martijnBeacon = new Beacon(new byte[] { 0, 0, 0, 0, 0, 1 }, 2); Rider martijn = new Rider("Martijn", martijnBeacon); //make a fast lap IdEvent startId = new IdEvent(DateTime.Now, martijn, "StartId", Direction.Enter); TimingEvent startTiming = new TimingEvent(DateTime.Now, martijn, 100, 0); IdEvent endId = new IdEvent(DateTime.Now, martijn, "EndId", Direction.Enter); TimingEvent endTiming = new TimingEvent(DateTime.Now, martijn, 200, 1); FinishedEvent fastFinish = new FinishedEvent(startId, startTiming, endTiming, endId); Lap fast = new Lap(fastFinish); //make a slower lap without penalties IdEvent slowStartId = new IdEvent(DateTime.Now, martijn, "StartId", Direction.Enter); TimingEvent slowStartTiming = new TimingEvent(DateTime.Now, martijn, 100, 0); IdEvent slowEndId = new IdEvent(DateTime.Now, martijn, "EndId", Direction.Enter); TimingEvent slowEndTiming = new TimingEvent(DateTime.Now, martijn, 300, 1); FinishedEvent slowFinish = new FinishedEvent(slowStartId, slowStartTiming, slowEndTiming, slowEndId); Lap slow = new Lap(slowFinish); //when both are not DSQ the lap time should decide the order Assert.AreEqual(1, slow.CompareTo(fast)); Assert.AreEqual(-1, fast.CompareTo(slow)); fast.SetDsq(new DSQEvent(DateTime.Now, martijn, "staff", "reason")); //the faster lap has a DSQ, so it should be considered slower Assert.AreEqual(-1, slow.CompareTo(fast)); Assert.AreEqual(1, fast.CompareTo(slow)); slow.SetDsq(new DSQEvent(DateTime.Now, martijn, "staff", "reason")); //both are now DSQ lap time should decide order again Assert.AreEqual(1, slow.CompareTo(fast)); Assert.AreEqual(-1, fast.CompareTo(slow)); }
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); }
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 EventRelatedPeriodicIntervalTime(Interval <PhysicalQuantity> offset, TimingEvent timingEvent) { Offset = offset; Event = timingEvent; }
private bool EventShouldOccur(TimingEvent e, float previousTime, float currentTime) { return((e.time > previousSourceTime) && (e.time <= currentTime)); }
public ITrackerTimingEvent CreateTimingEvent(string categoryName, string action, string label) { return(TimingEvent.Create(elapsed => SendTiming(categoryName, action, label, (long)elapsed.TotalMilliseconds))); }