public static AutoEntryScanResult FromRawText(string raceId, string raceName, string rawText)
        {
            var result = new AutoEntryScanResult
            {
                RaceId   = raceId,
                RaceName = raceName
            };

            var lines = rawText.Split(new [] { '\n', '\r' });

            foreach (var line in lines)
            {
                if (line.ToLower().Contains("competitor"))
                {
                    result.Competitor = line.Substring(line.IndexOf(':') + 1).Trim();
                }
                else if (line.ToLower().Contains("sail number"))
                {
                    result.SailNumber = line.Substring(line.IndexOf(':') + 1).Trim();
                }
                else if (line.Contains("(") &&
                         line.Contains(")") &&
                         line.Contains(","))
                {
                    int i1 = line.IndexOf('(');
                    int i2 = line.IndexOf(',');
                    int i3 = line.IndexOf(')');
                    if (i1 < i2 && i2 < i3)
                    {
                        var latitudeString  = line.Substring(i1 + 1, i2 - i1 - 1);
                        var longitudeString = line.Substring(i2 + 1, i3 - i2 - 1);
                        if (decimal.TryParse(latitudeString, out decimal latitude) &&
                            decimal.TryParse(longitudeString, out decimal longitude))
                        {
                            result.Latitude  = latitude;
                            result.Longitude = longitude;
                        }
                    }
                }
            }

            return(result);
        }
        private List <AutoEntryScanResult> AnalyzeRace(string raceId, string raceName, string raceDir)
        {
            // So we're sure that decimal points are understood properly.
            Thread.CurrentThread.CurrentCulture   = CultureInfo.InvariantCulture;
            Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;

            // Go through the files.
            using var tess = new TesseractWrapper();
            var resultList = new List <AutoEntryScanResult>();

            foreach (var file in Directory.GetFiles(raceDir))
            {
                if (!file.ToLower().EndsWith("png"))
                {
                    continue;
                }

                string txtPath = file.Replace(".png", ".txt");
                string rawText;
                if (File.Exists(txtPath))
                {
                    // Use the existing raw text file (caching mechanism).
                    rawText = File.ReadAllText(txtPath);
                }
                else
                {
                    // Get raw text from image.
                    rawText = tess.GetTextFromImage(file);
                    File.WriteAllText(txtPath, rawText);
                }

                // Create result from raw text.
                resultList.Add(AutoEntryScanResult.FromRawText(raceId, raceName, rawText));
            }

            // Return result.
            return(resultList);
        }