public void lap_time_column_values_are_translated_into_set_status_messages_if_the_status_has_changed(SessionType session)
 {
     In(session).Assert(translator =>
     {
         SetGridColumnValueMessage message;
         LiveDriver driver = translator.GetDriver(1);
         // On track. Note that OUT is displayed when a driver exits the pit and is on thier OUT lap.
         message = new SetGridColumnValueMessage(1, GridColumn.LapTime, GridColumnColour.White, "OUT");
         Assert.MessagesAreEqual(
             new SetDriverStatusMessage(1, DriverStatus.OnTrack),
             translator.Translate(message)
         );
         Assert.Equal(DriverStatus.OnTrack, driver.Status);
         Assert.Null(translator.Translate(message));
         // In pit.
         message = new SetGridColumnValueMessage(1, GridColumn.LapTime, GridColumnColour.White, "IN PIT");
         Assert.MessagesAreEqual(
             new SetDriverStatusMessage(1, DriverStatus.InPits),
             translator.Translate(message)
         );
         Assert.Equal(DriverStatus.InPits, driver.Status);
         Assert.Null(translator.Translate(message));
         // Retired.
         message = new SetGridColumnValueMessage(1, GridColumn.LapTime, GridColumnColour.White, "RETIRED");
         Assert.MessagesAreEqual(
             new SetDriverStatusMessage(1, DriverStatus.Retired),
             translator.Translate(message)
         );
         Assert.Equal(DriverStatus.Retired, driver.Status);
         Assert.Null(translator.Translate(message));
     });
 }
 public void when_a_driver_is_not_on_the_track_lap_time_column_values_are_not_translated_into_set_lap_time_messages(SessionType session)
 {
     In(session).OnLap(5).Assert(translator =>
     {
         var driver = translator.GetDriver(1);
         var message = new SetGridColumnValueMessage(1, GridColumn.LapTime, GridColumnColour.White, "1:35.571");
         // In pits.
         driver.ChangeStatus(DriverStatus.InPits);
         Assert.Null(translator.Translate(message));
         // Out.
         driver.ChangeStatus(DriverStatus.Out);
         Assert.Null(translator.Translate(message));
         // Retired.
         driver.ChangeStatus(DriverStatus.Retired);
         Assert.Null(translator.Translate(message));
         // Stopped.
         driver.ChangeStatus(DriverStatus.Stopped);
         Assert.Null(translator.Translate(message));
     });
 }
 public void when_a_driver_is_not_pitted_and_the_pit_count_column_is_updated_we_do_not_expect_pit_time_updates()
 {
     In(SessionType.Race).Assert(translator =>
     {
         var driver = translator.GetDriver(1);
         var message = new SetGridColumnValueMessage(1, GridColumn.PitCount, GridColumnColour.White, "2");
         // On track.
         driver.ChangeStatus(DriverStatus.OnTrack);
         translator.Translate(message);
         Assert.False(driver.IsExpectingPitTimes);
         // Out.
         driver.ChangeStatus(DriverStatus.Out);
         translator.Translate(message);
         Assert.False(driver.IsExpectingPitTimes);
         // Retired.
         driver.ChangeStatus(DriverStatus.Retired);
         translator.Translate(message);
         Assert.False(driver.IsExpectingPitTimes);
         // Stopped.
         driver.ChangeStatus(DriverStatus.Stopped);
         translator.Translate(message);
         Assert.False(driver.IsExpectingPitTimes);
     });
 }
 public void sector_column_values_are_translated_into_set_status_messages_if_the_status_has_changed(GridColumn sector, SessionType session)
 {
     In(session).Assert(translator =>
     {
         SetGridColumnValueMessage message;
         LiveDriver driver = translator.GetDriver(1);
         // Out.
         message = new SetGridColumnValueMessage(1, sector, GridColumnColour.White, "OUT");
         Assert.MessagesAreEqual(
             new SetDriverStatusMessage(1, DriverStatus.Out),
             translator.Translate(message)
         );
         Assert.Equal(DriverStatus.Out, driver.Status);
         Assert.Null(translator.Translate(message));
         // Stopped.
         message = new SetGridColumnValueMessage(1, sector, GridColumnColour.White, "STOP");
         Assert.MessagesAreEqual(
             new SetDriverStatusMessage(1, DriverStatus.Stopped),
             translator.Translate(message)
         );
         Assert.Equal(DriverStatus.Stopped, driver.Status);
         Assert.Null(translator.Translate(message));
     });
 }
 private Message TranslateSetIntervalTimeValue(SetGridColumnValueMessage message)
 {
     if(GetDriver(message).IsRaceLeader)
     {
         // The interval column for the lead driver displays the current lap number.
         return new CompositeMessage(
             new SetRaceLapNumberMessage(LiveData.ParseInt32(message.Value)),
             new SetDriverIntervalMessage(message.DriverId, TimeGap.Zero));
     }
     if(message.Value.OrdinalEndsWith("L"))
     {
         // An L suffix indicates a lap interval, e.g. 1L
         return new SetDriverIntervalMessage(message.DriverId,
             new LapGap(LiveData.ParseInt32(message.Value.Substring(0, message.Value.Length - 1))));
     }
     return new SetDriverIntervalMessage(message.DriverId, new TimeGap(LiveData.ParseTime(message.Value)));
 }
        private Message TranslateSetSectorTimeValue(SetGridColumnValueMessage message, int sectorNumber)
        {
            var driver = GetDriver(message);

            if(message.Value.OrdinalEquals("OUT"))
            {
                return CreateStatusMessageIfChanged(driver, DriverStatus.Out);
            }
            if(message.Value.OrdinalEquals("STOP"))
            {
                return CreateStatusMessageIfChanged(driver, DriverStatus.Stopped);
            }
            if(driver.IsExpectingPitTimes)
            {
                return TranslateSetPitTimeValue(message, sectorNumber);
            }
            if(!driver.IsOnTrack)
            {
                return null;
            }
            var newTime = LiveData.ParseTime(message.Value);
            var newTimeType = LiveData.ToPostedTimeType(message.Colour);
            // As of China-2010 the feed sends value updates to previous columns with completely different
            // times and types. We can detect this when we receive an update for the previously completed
            // sector. If the sector number is not the one previously completed we process the message
            // normally.
            if(driver.IsPreviousSectorNumber(sectorNumber))
            {
                if(driver.GetLastSector(sectorNumber) == null)
                {
                    Log.WarnFormat("received value update to a previous sector but we have no" +
                        " previous sector times for the driver, cannot translate this message: {0}",
                        message);
                    return null;
                }
                return new ReplaceDriverSectorTimeMessage(driver.Id, sectorNumber,
                    new PostedTime(newTime, newTimeType, driver.GetLastSector(sectorNumber).LapNumber));
            }
            return TranslateSetDriverSectorTimeMessage(
                new SetDriverSectorTimeMessage(driver.Id, sectorNumber,
                    new PostedTime(newTime, newTimeType, driver.LapNumber)));
        }
 void IMessageVisitor.Visit(SetGridColumnValueMessage message)
 {
     Dispatch(message);
 }
        private Message TranslateSetQuallyTimeValue(SetGridColumnValueMessage message, int quallyNumber)
        {
            var driver = GetDriver(message);

            if(!(IsQuallySession && driver.IsOnTrack))
            {
                return null;
            }
            var time = LiveData.ParseTime(message.Value);
            // We do not receive lap times during a qually session so we simulate them using the qually times.
            // Note that this is not a complete solution as we only receive qually times when the driver
            // improves upon thier time (hence the use of PostedTimeType.PersonalBest).
            // TODO we could keep track of the best time and promote the time to session best.
            return new CompositeMessage(
                new SetDriverQuallyTimeMessage(message.DriverId, quallyNumber, time),
                new SetDriverLapTimeMessage(message.DriverId,
                    new PostedTime(time, PostedTimeType.PersonalBest, driver.LapNumber)));
        }
        private Message TranslateSetSectorClear(SetGridColumnValueMessage message, int sectorNumber)
        {
            var driver = GetDriver(message);
            var lastSectorTime = driver.GetLastSector(1);
            // The feed will only send a value / colour update for S1 if the value has changed. We
            // can detect this when the S2 time is cleared and we are expecting an S1 update.
            // Note that we do not translate the message when the S1 column is currently cleared,
            // this usually occurs during practice as the driver exits the pits and the previous
            // times are cleared.
            // Also, note that an S2 clear can be received when we do not have a previous S1 time,
            // usually at the start of a session.
            if(driver.IsOnTrack && driver.IsCurrentSectorNumber(1) && sectorNumber == 2 &&
                driver.ColumnHasValue(GridColumn.S1) && lastSectorTime != null)
            {
                return TranslateSetDriverSectorTimeMessage(
                    new SetDriverSectorTimeMessage(driver.Id, 1,
                        new PostedTime(lastSectorTime.Time, lastSectorTime.Type, driver.LapNumber)));
            }

            return null;
        }
 /// <inheritdoc/>
 public override void Visit(SetGridColumnValueMessage message)
 {
     Translated = TranslateSetGridColumnValueMessage(message);
 }
 private Message TranslateSetPitTimeValue(SetGridColumnValueMessage message, int sectorNumber)
 {
     if(sectorNumber != 3)
     {
         return null;
     }
     var driver = GetDriver(message);
     // After a driver pits, the pit times are displayed and the S3 column displays the length of the last pit
     // stop. Note: we subtract one as the lap number will have been incremented when the driver pitted.
     return new SetDriverPitTimeMessage(driver.Id,
         new PostedTime(LiveData.ParseTime(message.Value), PostedTimeType.Normal, Math.Max(driver.LapNumber - 1, 0)));
 }
 private Message TranslateSetGridColumnValueMessage(SetGridColumnValueMessage message)
 {
     if(message.ClearColumn)
     {
         switch(message.Column)
         {
             case GridColumn.S1:
                 return TranslateSetSectorClear(message, 1);
             case GridColumn.S2:
                 return TranslateSetSectorClear(message, 2);
             case GridColumn.S3:
                 return TranslateSetSectorClear(message, 3);
             default:
                 return null;
         }
     }
     switch(message.Column)
     {
         case GridColumn.CarNumber:
             return TranslateSetCarNumberValue(message);
         case GridColumn.DriverName:
             return TranslateSetNameValue(message);
         case GridColumn.LapTime:
             return TranslateSetLapTimeValue(message);
         case GridColumn.Gap:
             return TranslateSetGapTimeValue(message);
         case GridColumn.S1:
             return TranslateSetSectorTimeValue(message, 1);
         case GridColumn.S2:
             return TranslateSetSectorTimeValue(message, 2);
         case GridColumn.S3:
             return TranslateSetSectorTimeValue(message, 3);
         case GridColumn.Laps:
             return TranslateSetCompletedLapsValue(message);
         case GridColumn.Interval:
             return TranslateSetIntervalTimeValue(message);
         case GridColumn.Q1:
             return TranslateSetQuallyTimeValue(message, 1);
         case GridColumn.Q2:
             return TranslateSetQuallyTimeValue(message, 2);
         case GridColumn.Q3:
             return TranslateSetQuallyTimeValue(message, 3);
         case GridColumn.PitCount:
             return TranslateSetPitCountValue(message);
         default:
             return null;
     }
 }
 /// <inheritdoc/>
 public virtual void Visit(SetGridColumnValueMessage message)
 {
 }
        private Message TranslateSetCarNumberValue(SetGridColumnValueMessage message)
        {
            Message translated = null;
            LiveDriver driver = GetDriver(message);
            int carNumber = LiveData.ParseInt32(message.Value);
            DriverStatus status = LiveData.ToDriverStatus(message.Colour);

            if(driver.CarNumber != carNumber)
            {
                translated = new SetDriverCarNumberMessage(driver.Id, carNumber);
            }
            if(driver.Status != status)
            {
                Message temp = new SetDriverStatusMessage(driver.Id, status);
                translated = translated == null ? temp : new CompositeMessage(translated, temp);
            }

            return translated;
        }
 private static Message TranslateSetPitCountValue(SetGridColumnValueMessage message)
 {
     return new SetDriverPitCountMessage(message.DriverId, LiveData.ParseInt32(message.Value));
 }
 private static Message TranslateSetNameValue(SetGridColumnValueMessage message)
 {
     return new SetDriverNameMessage(message.DriverId, message.Value);
 }
 private static Message TranslateSetGapTimeValue(SetGridColumnValueMessage message)
 {
     if(message.Value.OrdinalEquals("LAP"))
     {
         // LAP is displayed in the gap column of the lead driver.
         return new SetDriverGapMessage(message.DriverId, TimeGap.Zero);
     }
     if(message.Value.OrdinalEndsWith("L"))
     {
         // An L suffix indicates a lap gap, e.g. 4L
         return new SetDriverGapMessage(message.DriverId,
             new LapGap(LiveData.ParseInt32(message.Value.Substring(0, message.Value.Length - 1))));
     }
     return new SetDriverGapMessage(message.DriverId, new TimeGap(LiveData.ParseTime(message.Value)));
 }
 private static Message TranslateSetCompletedLapsValue(SetGridColumnValueMessage message)
 {
     return new SetDriverLapNumberMessage(message.DriverId, LiveData.ParseInt32(message.Value));
 }
        private Message TranslateSetLapTimeValue(SetGridColumnValueMessage message)
        {
            var driver = GetDriver(message);

            if(message.Value.OrdinalEquals("OUT"))
            {
                return CreateStatusMessageIfChanged(driver, DriverStatus.OnTrack);
            }
            if(message.Value.OrdinalEquals("IN PIT"))
            {
                return CreateStatusMessageIfChanged(driver, DriverStatus.InPits);
            }
            if(message.Value.OrdinalEquals("RETIRED"))
            {
                return CreateStatusMessageIfChanged(driver, DriverStatus.Retired);
            }
            if(driver.IsOnTrack && IsSessionStarted)
            {
                return new SetDriverLapTimeMessage(driver.Id,
                    new PostedTime(LiveData.ParseTime(message.Value),
                        LiveData.ToPostedTimeType(message.Colour), driver.LapNumber));
            }
            return null;
        }
 /// <inheritdoc/>
 public override void Visit(SetGridColumnValueMessage message)
 {
     GetDriver(message).SetColumnHasValue(message.Column, !message.ClearColumn);
 }