public static void UpdateStats(ShooterData shooter, ShooterMatchData data, MatchData match)
        {
            if (shooter.DatesOfMatches.All(d => d != match.Date))
            {
                shooter.DatesOfMatches.Add(match.Date);

                if (match.Champions.Any(c => c.ShooterId == shooter.Id))
                {
                    ++shooter.DC;
                }

                if (data.DNF)
                {
                    ++shooter.DNF;
                }

                shooter.FN += data.FN;
                shooter.NT += data.NT;
                shooter.PD += data.PD;
                shooter.PE += data.PE;
                ++shooter.TotalMatches;
                shooter.TotalTime += data.TotalTime;

                if (!data.DNF)
                {
                    shooter.TotalTimeWithoutDnf += data.TotalTime;
                }
            }
        }
        private void ExtractShootersScores(string[] lines, List<ShooterData> shooters)
        {
            int startLine = 0;

            for (int i = 0; i < lines.Length; ++i)
            {
                if (lines[i].StartsWith("Penalties"))
                {
                    startLine = i;
                    break;
                }
            }

            int stages = lines[startLine].Trim().Last().ToString().CastToIntOrThrow();
            match.NumberOfStages = stages;

            string division = string.Empty;
            string classification = string.Empty;
            string[] columns = new string[0];
            int offset = 0;

            while (startLine < lines.Length)
            {
                if (offset >= columns.Length)
                {
                    ++startLine;
                    offset = 0;

                    if (startLine >= lines.Length)
                    {
                        break;
                    }

                    columns = lines[startLine].Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
                }

                if (lines[startLine].Contains("Total Match Penalties:"))
                {
                    break;
                }

                if (columns.Length == 0 || string.IsNullOrWhiteSpace(lines[startLine]) || lines[startLine].Contains("Penalties") ||
                    lines[startLine].Contains("Key to Abbreviations") || lines[startLine].Contains("Specific Results:") ||
                    lines[startLine].Contains("All Participants") || lines[startLine].Contains("IDPA") || lines[startLine].Contains("file://") ||
                    lines[startLine].Contains("1 od "))
                {
                    offset = columns.Length;
                    continue;
                }

                if (columns[offset].IsNumber() && columns.Length < 3)
                {
                    offset = columns.Length;
                    continue;
                }

                if (ClassificationHelper.IsDivision(columns[offset]))
                {
                    division = columns[offset];
                    classification = columns[offset + 1];

                    offset += 2;
                }

                if (offset >= columns.Length)
                {
                    continue;
                }

                ShooterMatchData data = new ShooterMatchData();
                data.Division = division;
                data.Classification = classification;

                if (columns[offset] == "DC")
                {
                    data.DC = true;
                    ++offset;

                    // May happen sometimes
                    if (offset >= columns.Length)
                    {
                        ++startLine;
                        offset = 0;

                        if (startLine >= lines.Length)
                        {
                            break;
                        }

                        columns = lines[startLine].Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    }
                }
                else if (columns[offset].IsNumber())
                {
                    ++offset;
                }
                else if (columns[offset].Length > 3 && columns[offset].StartsWith("DC"))
                {
                    columns[offset] = columns[offset].Substring(2);
                    data.DC = true;
                }

                string fullName = columns[offset].RemoveInitialDigits() + " " + columns[offset + 1];
                offset += 2;

                if (columns[offset] == "-")
                {
                    fullName += " - " + columns[offset + 1];
                    offset += 2;
                }

                var shooter = ShooterHelper.AddOrGet(fullName, shooters, match);
                ShooterHelper.UpdateShooter(shooter, division, classification, match);

                data.ShooterId = shooter.Id;
                data.ShooterFullName = shooter.FullName;

                // If shooter has completed entire match
                if (columns[offset] != "---")
                {
                    data.TotalTime = columns[offset].CastToDoubleOrThrow();
                }
                else
                {
                    data.DNF = true;
                }

                ++offset;

                try
                {
                    // PD,NT,PE,FN
                    data.PD = columns[offset++].CastToIntOrThrow();
                    data.NT = columns[offset++].CastToIntOrThrow();
                    data.PE = columns[offset++].CastToIntOrThrow();
                    data.FN = columns[offset++].CastToIntOrThrow();
                }
                catch
                {
                    data.HasPotentialErrors = true;

                    --offset;
                    while (offset < columns.Length)
                    {
                        if (columns[offset].Contains("("))
                        {
                            break;
                        }

                        ++offset;
                    }

                    if (offset >= columns.Length)
                    {
                        throw new ParseException();
                    }
                }

                for (int i = 0; i < stages; ++i)
                {
                    var score = ScoreData.Parse(columns[offset]);
                    data.Scores.Add(score);

                    ++offset;
                }

                ShooterHelper.UpdateStats(shooter, data, match);
                match.ScoresByShooter.Add(data);
            }
        }