Exemple #1
0
 private void SetupDebugWindow()
 {
     Task.Run(() =>
     {
         DebugMenu       = new DebugMenu(this);
         DebugMenu.Load += DebugMenu_Load;
         DebugMenu.ShowDialog();
     });
     SpinWait.SpinUntil(() => { return(DebugStarted); });
 }
        /// <summary>
        /// Gets the name of the player when already in the career profile.
        /// </summary>
        /// <returns></returns>
        internal string GetPlayerName(
#if DEBUG
#pragma warning disable 1573
            string debugLetters = ""
#pragma warning restore 1573
#endif
            )
        {
#if DEBUG
            if (debugLetters == null)
            {
                debugLetters = "";
            }
#endif
            // Generate and cache the alphabet.
            if (EnglishAlphabet == null)
            {
                EnglishAlphabet = GenerateAlphabet();
            }

            int   lineScanFade    = 80;                                      // The fade to detect a letter.
            int   letterCheckFade = 80;                                      // The fade to scan each pixel in the letter with.
            float cutoff          = .92f;                                    // The percent of pixels scanned a letter needs to be confirmed in order to be considered as the correct letter.
            int   cy                 = 131;                                  // The Y coordinate to scan at.
            int   xStart             = 131;                                  // The X coordinate to start scanning at.
            int   xEnd               = 270;                                  // The X coordinate to stop scanning at.
            int   maxSinceLastLetter = 10;                                   // The max number of pixels that need to past since the last detected letter to stop scanning.
            Tuple <char, char>[] prioritizeLetter = new Tuple <char, char>[] // Some characters look very similiar to eachother, this improves those conflicts.
            {
                new Tuple <char, char>('O', 'D'),
                new Tuple <char, char>('R', 'A'),
            };

            using (LockHandler.Interactive)
            {
                UpdateScreen();

                string playerName = string.Empty; // The name of the player.

                // Scan a line under the name in the career profile for text.
                for (int cx = xStart, sinceLastLetter = 0; cx < xEnd && sinceLastLetter < maxSinceLastLetter; cx++)
                {
                    if (Capture.CompareColor(cx, cy, Colors.WHITE, lineScanFade))
                    {
                        // A letter was detected.
                        sinceLastLetter = 0;
                        List <PlayerNameLetterResult> results = new List <PlayerNameLetterResult>(); // Stores the results of every letter scanned. The most likely letter will be used.
                        for (int ax = cx; ax <= cx + 1; ax++)                                        // Scan this pixel and the next pixel.
                        {
                            for (int i = 0; i < EnglishAlphabet.Length; i++)
                            {
                                List <Point> filledPixels = new List <Point>(); // All detected pixels.
                                float        total        = 0;                  // The total number of pixels.
                                float        match        = 0;                  // The pixels that match the Capture and the letter markup.
                                bool         failed       = false;
                                for (int lx = 0; lx < EnglishAlphabet.Markups[i].Width && !failed; lx++)
                                {
                                    for (int ly = 0; ly < EnglishAlphabet.Markups[i].Height && !failed; ly++)
                                    {
                                        PixelType pixelType = GetPixelType(EnglishAlphabet.Markups[i], lx, ly);

                                        if (pixelType != PixelType.Any)
                                        {
                                            // px and py is the Capture's relative letter position.
                                            int  px          = ax + lx;
                                            int  py          = cy + ly + 2 - EnglishAlphabet.Markups[i].Height;
                                            bool pixelFilled = Capture.CompareColor(px, py, Colors.WHITE, letterCheckFade);

                                            // If a required pixel is missing, fail the letter.
                                            failed = pixelType == PixelType.Required && !pixelFilled;
                                            if (failed)
                                            {
                                                break;
                                            }

                                            total++;
                                            if ((pixelFilled && (pixelType == PixelType.Filled || pixelType == PixelType.Required)) || (!pixelFilled && pixelType == PixelType.Empty))
                                            {
                                                match++;
                                                if (pixelType == PixelType.Filled || pixelType == PixelType.Required)
                                                {
                                                    filledPixels.Add(new Point(lx, ly));
                                                    #region DEBUG
#if DEBUG
                                                    if (DebugMenu != null)
                                                    {
                                                        DebugMenu.SetDebugImage(px, py, Color.Green);
                                                    }
#endif
                                                    #endregion
                                                }
                                                #region DEBUG
#if DEBUG
                                                else if (DebugMenu != null)
                                                {
                                                    DebugMenu.SetDebugImage(px, py, Color.DarkBlue);
                                                }
#endif
                                                #endregion
                                            }
                                            #region DEBUG
#if DEBUG
                                            else if (DebugMenu != null)
                                            {
                                                if (pixelType == PixelType.Filled)
                                                {
                                                    DebugMenu.SetDebugImage(px, py, Color.DarkRed);
                                                }
                                                else
                                                {
                                                    DebugMenu.SetDebugImage(px, py, Color.Yellow);
                                                }
                                            }
#endif
                                            #endregion
                                        }
                                    }
                                }

                                if (!failed)
                                {
                                    /*  Check if every pixel that was detected is connected. For example, || will return false, but H will return true.
                                     *  This makes letter scanning more certain for the BigNoodleTooOblique font because every pixel in the letters in that font is connected.
                                     *  If GetPlayerName() and GenerateAlphabet() is extended to other languages this may need to be removed because other languages use
                                     *  a different font whos characters are seperate; like 'i'. */
                                    bool  isConnected = PointsAreConnected(filledPixels);
                                    float result      = !isConnected ? 0 : match / total;

                                    // Add the result to the list.
                                    results.Add(new PlayerNameLetterResult(EnglishAlphabet.Letters[i], result, (int)total, (int)match, EnglishAlphabet.Markups[i], EnglishAlphabet.LetterLengths[i]));
                                    #region DEBUG
#if DEBUG
                                    if (DebugMenu != null)
                                    {
                                        Console.Write($"{EnglishAlphabet.Letters[i]} - R: ");
                                        if (result >= cutoff)
                                        {
                                            Console.BackgroundColor = ConsoleColor.DarkGreen;
                                            Console.Write($"{result}");
                                            Console.BackgroundColor = ConsoleColor.Black;
                                        }
                                        else
                                        {
                                            Console.Write($"{result}");
                                        }
                                        Console.WriteLine($" T: {total} - M: {match} - C: {isConnected}");
                                    }
#endif
                                    #endregion
                                }
                                #region DEBUG
#if DEBUG
                                else if (DebugMenu != null)
                                {
                                    Console.WriteLine($"{EnglishAlphabet.Letters[i]} vital pixel missing.");
                                }

                                if (DebugMenu != null)
                                {
                                    DebugMenu.InvalidateDebugImage();

                                    if (debugLetters.Contains(EnglishAlphabet.Letters[i]))
                                    {
                                        Console.ReadLine();
                                    }

                                    DebugMenu.ResetDebugImage();
                                }
#endif
                                #endregion
                            }
                        }

                        // Remove the results whos result is less than the cutoff or is null.
                        results = results.Where(result => result != null && result.Result >= cutoff).ToList();

                        /*  Get the most likely letter by the most matching pixels. OrderByDescending and ThenByDescending will order the list like so:
                         | Matching first,        | Then percent.
                         |  A - Matching: 50, Total: 55 (50 / 55 = 90%)
                         |  B - Matching: 50, Total: 60 (60 / 50 = 83%)
                         |  C - Matching: 45, Total: 45 (45 / 45 = 100%)
                         |
                         |  Getting the highest match is important because if the letter in the player's name is E, then L and F will have 100%
                         |  result also because L and F have the same lines as E. If the letter in the player's name is F, E won't be considered
                         |  because the lack of the bottom line brings it below the cutoff value. */
                        PlayerNameLetterResult mostLikely = results.OrderByDescending(result => result.Match).ThenByDescending(result => result.Result).FirstOrDefault();

                        // mostLikely will be null if no letters made it past the cutoff.
                        if (mostLikely != null)
                        {
                            // Some characters look very similiar to eachother, this improves those conflicts.
                            // The conflicts are manually set in the prioritizeLetter variable from earlier.
                            foreach (var prioritize in prioritizeLetter)
                            {
                                if (mostLikely.Letter == prioritize.Item1)                                                                                       // If the mostLikely letter should be prioritized to something else.
                                {
                                    int toCount = results.Count(r => r.Letter == prioritize.Item2);                                                              // The number of letters found in the results that the mostLikely's letter should be prioritized to.
                                    var bestTo  = results.OrderByDescending(result => result.Match).FirstOrDefault(result => result.Letter == prioritize.Item2); // Get the letter to prioritize to.
                                    // If there are 2 occurences of the letter that mostLikely should be prioritized to,
                                    // or the prioritized letter has a better result percent than the mostLikely letter,
                                    // change the mostlikely letter to the prioritized letter.
                                    if (toCount == 2 || (bestTo != null && bestTo.Result > mostLikely.Result))
                                    {
                                        mostLikely = bestTo;
                                    }
                                }
                            }
                            #region DEBUG
#if DEBUG
                            if (DebugMenu != null)
                            {
                                Console.BackgroundColor = ConsoleColor.DarkBlue;
                                Console.WriteLine($"Letter detected: {mostLikely.Letter}");
                                Console.BackgroundColor = ConsoleColor.Black;
                            }
#endif
                            #endregion
                            // Add the letter scanned to the player name.
                            playerName += mostLikely.Letter;

                            /*  Increase the spot scanned on the X axis by the width of the letter scanned.
                             *  This is required so when scanning letters like H, it will start scanning again
                             *  on the right side of H. If it started scanning again where 'H' was detected,
                             *  it could incorrectly identify 'I' from the line on the right side of H. */
                            cx += mostLikely.LetterLength;
                        }
                    } // Color check
                    else
                    {
                        sinceLastLetter++;
                    }
                } // Line scan

                return(playerName);
            }
        }