public CompetitionClassModel ChangeRunResult(CompetitionRunResult runResult)
        {
            Guard.NotNull(runResult, nameof(runResult));

            var newResults = new List <CompetitionRunResult>();

            bool found = false;

            foreach (CompetitionRunResult result in Results)
            {
                if (result.Competitor.Number == runResult.Competitor.Number)
                {
                    newResults.Add(runResult);
                    found = true;
                }
                else
                {
                    newResults.Add(result);
                }
            }

            if (!found)
            {
                throw new KeyNotFoundException($"No competitor found with number {runResult.Competitor.Number}");
            }

            var newResultList = new ReadOnlyCollection <CompetitionRunResult>(newResults);

            return(new CompetitionClassModel(newResultList, ClassInfo, LastCompletedCompetitorNumber, IntermediateTimerCount,
                                             StartFinishMinDelayForSingleSensor, Alerts));
        }
コード例 #2
0
        private static Dictionary <int, CompetitionRunResult> ImportRunResultsFrom(string path)
        {
            DateTime currentTimeUtc = SystemContext.UtcNow();
            var      imported       = new Dictionary <int, CompetitionRunResult>();

            using var textReader = new StreamReader(path);

            var settings = new DelimitedValuesReaderSettings
            {
                Culture = Settings.Default.ImportExportCulture
            };

            using var valuesReader = new DelimitedValuesReader(textReader, settings);

            AssertRequiredColumnsExist(valuesReader);
            bool hasOptionalColumns = ContainsOptionalColumnNames(valuesReader);

            foreach (IDelimitedValuesReaderRow row in valuesReader)
            {
                try
                {
                    CompetitionRunResult runResult = GetRunResultFrom(row, hasOptionalColumns, currentTimeUtc);
                    imported[runResult.Competitor.Number] = runResult;
                }
                catch (Exception ex)
                {
                    throw new Exception($"Failed to read import file at row {valuesReader.LineNumber}: {ex.Message}", ex);
                }
            }

            return(imported);
        }
        public RankingChangeEventArgs([NotNull] [ItemNotNull] IReadOnlyCollection<CompetitionRunResult> rankings,
            [CanBeNull] CompetitionRunResult previousRunResult)
        {
            Guard.NotNull(rankings, nameof(rankings));

            Rankings = rankings;
            PreviousRunResult = previousRunResult;
        }
コード例 #4
0
        private static CompetitionRunResult CreateCompetitorForCompletion(bool hasFinished, bool isEliminated)
        {
            var result = new CompetitionRunResult(new Competitor(1, "A", "A"));

            if (isEliminated)
            {
                result = result.ChangeIsEliminated(true);
            }

            if (hasFinished)
            {
                result = result.ChangeTimings(new CompetitionRunTimings(
                    new RecordedTimeBuilder()
                        .At(TimeSpan.FromSeconds(10)).Build())
                    .ChangeFinishTime(new RecordedTimeBuilder()
                        .At(TimeSpan.FromSeconds(25)).Build()));
            }

            return result;
        }
コード例 #5
0
        public IEnumerable <CompetitionRunResult> ImportFrom(string path, bool mergeDeletes, bool skipTimings)
        {
            Guard.NotNullNorEmpty(path, nameof(path));

            var mergeRunResults = new List <CompetitionRunResult>();

            Dictionary <int, CompetitionRunResult> importRunResults = ImportRunResultsFrom(path);

            foreach (CompetitionRunResult existingRunResult in existingRunResults)
            {
                if (importRunResults.ContainsKey(existingRunResult.Competitor.Number))
                {
                    // Merge action: Content merge
                    CompetitionRunResult importRunResult = importRunResults[existingRunResult.Competitor.Number];
                    CompetitionRunResult mergeRunResult  = Merge(existingRunResult, importRunResult, skipTimings);

                    mergeRunResults.Add(mergeRunResult);
                    importRunResults.Remove(existingRunResult.Competitor.Number);
                }
                else
                {
                    if (mergeDeletes)
                    {
                        // Merge action: Delete
                    }
                    else
                    {
                        // Merge action: None
                        mergeRunResults.Add(existingRunResult);
                    }
                }
            }

            // Merge action: Add
            mergeRunResults.AddRange(importRunResults.Select(importRunResult => importRunResult.Value));

            return(mergeRunResults);
        }
コード例 #6
0
        private static CompetitionRunResult CreateCompetitorForPenaltyOverrun(bool penaltyTimeIsGreater,
            bool overrunTimeIsGreater)
        {
            TimeSpan overrunTime = overrunTimeIsGreater ? HighOverrunTime : LowOverrunTime;
            TimeSpan penaltyTime = penaltyTimeIsGreater ? HighPenaltyTime : LowPenaltyTime;

            var result = new CompetitionRunResult(new Competitor(1, "A", "A"));

            TimeSpan startTime = TimeSpan.FromSeconds(10);
            result = result.ChangeTimings(new CompetitionRunTimings(
                new RecordedTimeBuilder()
                    .At(startTime).Build())
                .ChangeFinishTime(new RecordedTimeBuilder()
                    .At(startTime + overrunTime + StandardCourseTime).Build()));

            int fr = (int) (penaltyTime - overrunTime).TotalSeconds;
            result = result.ChangeFaultCount(fr);

            return result;
        }
コード例 #7
0
 private static bool RunResultsAreEqual(CompetitionRunResult first, CompetitionRunResult second)
 {
     return(EqualitySupport.EqualsWithNulls(first.Timings, second.Timings, FinishTimesAreEqual) && first.FaultCount == second.FaultCount &&
            first.RefusalCount == second.RefusalCount && first.IsEliminated == second.IsEliminated);
 }
コード例 #8
0
 private static bool CompetitorsAreEqual(CompetitionRunResult first, CompetitionRunResult second)
 {
     return(first.Competitor == second.Competitor);
 }
コード例 #9
0
 private static bool CompetitorRunResultsAreEqual(CompetitionRunResult first, CompetitionRunResult second)
 {
     return(CompetitorsAreEqual(first, second) && RunResultsAreEqual(first, second));
 }
コード例 #10
0
 private static CompetitionRunResult Merge(CompetitionRunResult existing, CompetitionRunResult imported, bool skipTimings)
 {
     return(skipTimings ? existing.ChangeCompetitor(imported.Competitor) : MergeWithTimings());
 }
 public CompetitorAssessmentCalculator([NotNull] CompetitionRunResult competitor,
     [NotNull] CompetitionClassModel modelSnapshot)
 {
     Guard.NotNull(competitor, nameof(competitor));
     Guard.NotNull(modelSnapshot, nameof(modelSnapshot));
     this.competitor = competitor;
     this.modelSnapshot = modelSnapshot;
 }
コード例 #12
0
        private void AcceptButton_Click([CanBeNull] object sender, [NotNull] EventArgs e)
        {
            if (ParentForm == null || HasValidationErrors)
            {
                return;
            }

            CompetitionRunResult originalRunVersionNotNull = AssertOriginalRunVersionNotNull();

            CompetitionRunResult newRunVersion =
                originalRunVersionNotNull.ChangeTimings(ConvertFinishTimeFromScreen(true))
                    .ChangeFaultCount(ConvertFaultCountFromScreen())
                    .ChangeRefusalCount(ConvertRefusalCountFromScreen())
                    .ChangeIsEliminated(ConvertEliminatedFromScreen());

            var changingEventArgs = new RunResultChangingEventArgs(originalRunVersionNotNull, newRunVersion);
            RunResultChanging?.Invoke(this, changingEventArgs);

            if (changingEventArgs.ErrorMessage == null)
            {
                ShowAnimatedSuccess("Competitor updated.");

                originalRunVersion =
                    CacheManager.DefaultInstance.ActiveModel.GetRunResultFor(newRunVersion.Competitor.Number);
                RunResultChanged?.Invoke(this, EventArgs.Empty);
            }
            else
            {
                ShowAnimatedFailure(changingEventArgs.ErrorMessage);
            }
        }
コード例 #13
0
 public void OverwriteWith([CanBeNull] CompetitionRunResult runResult)
 {
     originalRunVersion = runResult;
     CopyValuesFrom(runResult);
 }
 void IVisualizationActor.SetOrClearPreviousCompetitorRun(CompetitionRunResult competitorRunResult)
 {
     builder.WithPreviousPlacement(competitorRunResult?.Placement ?? CirceHiddenPlacement);
 }
コード例 #15
0
        private static CompetitionRunResult CreateCompetitorForFinishWithNumber(bool finishTimeIsGreater,
            bool competitorNumberIsGreater)
        {
            int competitorNumber = competitorNumberIsGreater ? HighCompetitorNumber : LowCompetitorNumber;
            TimeSpan finishTime = TimeSpan.FromSeconds(finishTimeIsGreater ? 50 : 25);

            var result = new CompetitionRunResult(new Competitor(competitorNumber, "A", "A"));

            TimeSpan startTime = TimeSpan.FromSeconds(10);
            result = result.ChangeTimings(new CompetitionRunTimings(
                new RecordedTimeBuilder()
                    .At(startTime).Build())
                .ChangeFinishTime(new RecordedTimeBuilder()
                    .At(startTime + finishTime).Build()));

            return result;
        }
コード例 #16
0
        private static void SetTimeElapsedSinceStart(IDelimitedValuesWriterRow row, string columnName, CompetitionRunResult runResult, RecordedTime?time)
        {
            TimeSpanWithAccuracy?elapsed = GetElapsedSinceStart(runResult.Timings, time);

            if (elapsed != null)
            {
                row.SetCell(columnName, elapsed.Value);
            }
        }
コード例 #17
0
        private static CompetitionRunResult GetRunResultFrom([NotNull] IDelimitedValuesReaderRow row,
            bool hasOptionalColumns, DateTime startTimeUtc)
        {
            Competitor competitor = GetCompetitorFrom(row);
            var runResult = new CompetitionRunResult(competitor);

            if (hasOptionalColumns)
            {
                var faultCount = row.GetCell<int?>(ImportExportColumns.FaultCount);
                var refusalCount = row.GetCell<int?>(ImportExportColumns.RefusalCount);
                var isEliminated = row.GetCell<bool?>(ImportExportColumns.IsEliminated);

                // Note: We cannot reconstruct whether start time was high precision, because it does not roundtrip
                // through import/export. However, we do not need to know. A low-precision elapsed time is caused by 
                // either one or both times to be low precision. So although we lost some information, the nett effect
                // when the precision of an elapsed time is recalculated will be the same as long as we assume that the start
                // time was high precision.
                var startTime = new RecordedTime(TimeSpan.Zero, startTimeUtc);

                RecordedTime intermediateTime1 = GetTimeElapsedSinceStart(row, ImportExportColumns.IntermediateTime1,
                    startTime);
                RecordedTime intermediateTime2 = GetTimeElapsedSinceStart(row, ImportExportColumns.IntermediateTime2,
                    startTime);
                RecordedTime intermediateTime3 = GetTimeElapsedSinceStart(row, ImportExportColumns.IntermediateTime3,
                    startTime);
                RecordedTime finishTime = GetTimeElapsedSinceStart(row, ImportExportColumns.FinishTime, startTime);

                if (intermediateTime1 == null && intermediateTime2 == null && intermediateTime3 == null &&
                    finishTime == null)
                {
                    startTime = null;
                }

                bool runCompleted = finishTime != null || (isEliminated != null && isEliminated.Value);
                if (runCompleted)
                {
                    if (faultCount != null)
                    {
                        runResult = runResult.ChangeFaultCount(faultCount.Value);
                    }
                    if (refusalCount != null)
                    {
                        runResult = runResult.ChangeRefusalCount(refusalCount.Value);
                    }
                    if (isEliminated != null)
                    {
                        runResult = runResult.ChangeIsEliminated(isEliminated.Value);
                    }

                    if (startTime != null)
                    {
                        runResult =
                            runResult.ChangeTimings(
                                new CompetitionRunTimings(startTime).ChangeIntermediateTime1(intermediateTime1)
                                    .ChangeIntermediateTime2(intermediateTime2)
                                    .ChangeIntermediateTime3(intermediateTime3)
                                    .ChangeFinishTime(finishTime));
                    }
                }
            }

            return runResult;
        }
        private CompetitionRunResultRowInGrid([NotNull] CompetitionRunResult original, [NotNull] string handlerName,
            [NotNull] string dogName)
        {
            Guard.NotNull(original, nameof(original));
            Guard.NotNullNorEmpty(handlerName, nameof(handlerName));
            Guard.NotNullNorEmpty(dogName, nameof(dogName));

            this.original = original;
            HandlerName = handlerName;
            DogName = dogName;
            PlacementText = string.Empty;
        }
        void IVisualizationActor.SetOrClearPreviousCompetitorRun(CompetitionRunResult competitorRunResult)
        {
            if (competitorRunResult != null)
            {
                prevCompetitorNumberLabel.Text =
                    TextFormatting.FormatCompetitorNumber(competitorRunResult.Competitor.Number);
                prevTimeLabel.Text =
                    TextFormatting.FormatTime(
                        competitorRunResult.Timings?.FinishTime?.ElapsedSince(competitorRunResult.Timings.StartTime)
                            .TimeValue);
                prevFaultsValueLabel.Text = TextFormatting.FormatNumber(competitorRunResult.FaultCount, 2);
                prevRefusalsValueLabel.Text = TextFormatting.FormatNumber(competitorRunResult.RefusalCount, 2);

                Color foreColor = competitorRunResult.IsEliminated
                    ? RunHistoryLine.EliminationColor
                    : SystemColors.ControlText;
                prevTimeLabel.ForeColor = foreColor;
                prevPlacementLabel.ForeColor = foreColor;
                prevPlacementLabel.Text = competitorRunResult.IsEliminated
                    ? @"X"
                    : TextFormatting.FormatPlacement(competitorRunResult.Placement);
            }
            else
            {
                prevCompetitorNumberLabel.Text = string.Empty;
                prevTimeLabel.Text = string.Empty;
                prevFaultsValueLabel.Text = string.Empty;
                prevRefusalsValueLabel.Text = string.Empty;
                prevPlacementLabel.Text = string.Empty;
            }
        }
        private static CompetitionRunResult CreateCompetitorFor([NotNull] string name, bool hasFinished,
            bool isEliminated, bool otherHasFinished, bool penaltyTimeIsGreater, bool overrunTimeIsGreater,
            bool otherPenaltyTimeIsGreater, bool otherOverrunTimeIsGreater, bool finishTimeIsGreater,
            bool competitorNumberIsGreater, bool otherFinishTimeIsGreater, bool otherCompetitorNumberIsGreater)
        {
            int competitorNumber = !competitorNumberIsGreater && !otherCompetitorNumberIsGreater
                ? LowOrSameCompetitorNumber
                : (competitorNumberIsGreater ? HighCompetitorNumber : LowOrSameCompetitorNumber);

            var result = new CompetitionRunResult(new Competitor(competitorNumber, name, name));

            if (isEliminated)
            {
                result = result.ChangeIsEliminated(true);
            }

            if (hasFinished)
            {
                bool requireSameOverrunTime = !overrunTimeIsGreater && !otherOverrunTimeIsGreater;
                TimeSpan overrunTime = requireSameOverrunTime
                    ? (!otherHasFinished ? TimeSpan.Zero : LowOrSameOverrunTime)
                    : overrunTimeIsGreater ? HighOverrunTime : LowOrSameOverrunTime;

                bool requireSamePenaltyTime = !penaltyTimeIsGreater && !otherPenaltyTimeIsGreater;
                TimeSpan penaltyTime = requireSamePenaltyTime
                    ? (!otherHasFinished ? TimeSpan.Zero : LowOrSamePenaltyTime)
                    : penaltyTimeIsGreater ? HighPenaltyTime : LowOrSamePenaltyTime;

                bool requireSameFinishTime = !finishTimeIsGreater && !otherFinishTimeIsGreater;
                TimeSpan extraFinishTime = requireSameFinishTime
                    ? (!otherHasFinished ? TimeSpan.Zero : LowOrSameExtraFinishTime)
                    : finishTimeIsGreater ? HighExtraFinishTime : LowOrSameExtraFinishTime;

                TimeSpan startTime = TimeSpan.FromSeconds(10);

                TimeSpan finishTimeAbsolute = startTime + overrunTime + extraFinishTime;
                if (!otherHasFinished && (requireSameFinishTime || requireSameOverrunTime) && !overrunTimeIsGreater)
                {
                    // Other has not finished, but finish times must be the same.
                }
                else if (otherHasFinished && (finishTimeIsGreater || otherFinishTimeIsGreater) && requireSameOverrunTime)
                {
                    // Both finished, but overrun times must be the same.
                }
                else
                {
                    finishTimeAbsolute += StandardCourseTime;
                }

                result = result.ChangeTimings(new CompetitionRunTimings(
                    new RecordedTimeBuilder()
                        .At(startTime).Build())
                    .ChangeFinishTime(new RecordedTimeBuilder()
                        .At(finishTimeAbsolute).Build()));

                TimeSpan finishTimeElapsed = finishTimeAbsolute - startTime;
                TimeSpan actualOverrunTime = finishTimeElapsed > StandardCourseTime
                    ? finishTimeElapsed - StandardCourseTime
                    : TimeSpan.Zero;

                int fr = (int) (penaltyTime - actualOverrunTime).TotalSeconds;
                int refusals = GetRefusalsFor(fr, isEliminated);
                result = result.ChangeRefusalCount(refusals);

                int faults = fr - refusals;
                result = new FakeCompetitionRunResult(result, faults);
            }

            return result;
        }
コード例 #21
0
        private static CompetitionRunResult GetRunResultFrom(IDelimitedValuesReaderRow row, bool hasOptionalColumns, DateTime startTimeUtc)
        {
            Competitor competitor = GetCompetitorFrom(row);
            var        runResult  = new CompetitionRunResult(competitor);

            if (hasOptionalColumns)
            {
                int? faultCount   = row.GetCell <int?>(ImportExportColumns.FaultCount);
                int? refusalCount = row.GetCell <int?>(ImportExportColumns.RefusalCount);
                bool?isEliminated = row.GetCell <bool?>(ImportExportColumns.IsEliminated);

                // Note: We cannot reconstruct whether start time was high precision, because it does not roundtrip
                // through import/export. However, we do not need to know. A low-precision elapsed time is caused by
                // either one or both times to be low precision. So although we lost some information, the nett effect
                // when the precision of an elapsed time is recalculated will be the same as long as we assume that the start
                // time was high precision.
                var startTime = new RecordedTime(TimeSpan.Zero, startTimeUtc);

                RecordedTime?intermediateTime1 = GetTimeElapsedSinceStart(row, ImportExportColumns.IntermediateTime1, startTime);
                RecordedTime?intermediateTime2 = GetTimeElapsedSinceStart(row, ImportExportColumns.IntermediateTime2, startTime);
                RecordedTime?intermediateTime3 = GetTimeElapsedSinceStart(row, ImportExportColumns.IntermediateTime3, startTime);
                RecordedTime?finishTime        = GetTimeElapsedSinceStart(row, ImportExportColumns.FinishTime, startTime);

                if (intermediateTime1 == null && intermediateTime2 == null && intermediateTime3 == null && finishTime == null)
                {
                    startTime = null;
                }

                bool runCompleted = finishTime != null || (isEliminated != null && isEliminated.Value);

                if (runCompleted)
                {
                    if (faultCount != null)
                    {
                        runResult = runResult.ChangeFaultCount(faultCount.Value);
                    }

                    if (refusalCount != null)
                    {
                        runResult = runResult.ChangeRefusalCount(refusalCount.Value);
                    }

                    if (isEliminated != null)
                    {
                        runResult = runResult.ChangeIsEliminated(isEliminated.Value);
                    }

                    if (startTime != null)
                    {
                        // @formatter:keep_existing_linebreaks true

                        runResult = runResult
                                    .ChangeTimings(new CompetitionRunTimings(startTime)
                                                   .ChangeIntermediateTime1(intermediateTime1)
                                                   .ChangeIntermediateTime2(intermediateTime2)
                                                   .ChangeIntermediateTime3(intermediateTime3)
                                                   .ChangeFinishTime(finishTime));

                        // @formatter:keep_existing_linebreaks restore
                    }
                }
            }

            return(runResult);
        }