private void Update()
        {
            if (!startTime.HasValue)
            {
                return;
            }

            var lastPresented = race.Laps.LastPresented;

            if (lastPresented == null)
            {
                Start();
                return;
            }

            if (lastPresented.Presented == null)
            {
                return;
            }

            var passed = (double)calculator.LapPassedLength(race.Distance, lastPresented.Index + 1);

            if (lastPresented.Index >= calculator.Laps(race.Distance) - 1)
            {
                Seek(containingObject, TimeSpan.FromSeconds(passed), TimeSeekOrigin.BeginTime);
                return;
            }

            var    lapLength = calculator.LapPassedLength(race.Distance, lastPresented.Index + 2) - passed;
            double speed;

            if (estimatedLapTimes != null && estimatedLapTimes.Count > lastPresented.Index + 1)
            {
                var nextEstimatedLapTime = estimatedLapTimes[lastPresented.Index + 1];
                speed = lapLength / nextEstimatedLapTime.TotalSeconds;
            }
            else
            {
                var openingLapLength = calculator.LapPassedLength(race.Distance, 1);
                speed = (lastPresented.Index == 0 ? openingLapLength : lapLength) / lastPresented.Presented.LapTime.TotalSeconds;
            }

            passed += speed * Math.Max(0, (DateTime.Now - startTime.Value - lastPresented.Presented.Time).TotalSeconds);

            Duration = TimeSpan.FromSeconds(passed + lapLength);
            Begin(containingObject, true);
            Seek(containingObject, TimeSpan.FromSeconds(passed), TimeSeekOrigin.BeginTime);
            SetSpeedRatio(containingObject, speed);
        }
        private static void CommitRace(IDistance distance, IEnumerable <DistanceCombination> combinations, Race race, IDistanceDisciplineCalculator calculator, string headerLine, int timeInfoOffset)
        {
            TimeInfo timeInfo;

            if (!TryParseTimeInfo(headerLine.Substring(timeInfoOffset, 2), out timeInfo))
            {
                timeInfo = TimeInfo.None;
            }

            race.PresentedInstanceName = ResultInstanceName;

            var result   = race.Results?.SingleOrDefault(r => r.InstanceName == ResultInstanceName);
            var finalLap = race.Laps?.Presented().ElementAtOrDefault(calculator.Laps(distance) - 1);

            if (result == null || finalLap == null)
            {
                return;
            }

            var time = new RaceTime
            {
                Race               = race,
                InstanceName       = ResultInstanceName,
                PresentationSource = finalLap.PresentationSource,
                Time               = finalLap.Time,
                TimeInfo           = timeInfo
            };

            if (race.Times == null)
            {
                race.Times = new Collection <RaceTime>();
            }
            race.Times.Add(time);

            var classificationWeight = combinations.FirstOrDefault()?.ClassificationWeight ?? DefaultClassificationWeight;

            if (calculator.CanCalculateRacePoints(distance, classificationWeight, distance.ClassificationPrecision, result, time))
            {
                result.Points = calculator.CalculateRacePoints(distance, classificationWeight, distance.ClassificationPrecision, result, time);
            }
        }