/// <summary>
        /// Check whether not using the same kind of 4 characters in a row.
        /// Length bonus: *1.15
        /// </summary>
        /// <param name="password"></param>
        /// <param name="charLength"></param>
        /// <returns></returns>
        protected double CheckNotUsingSameKindOfCharsInARow(string password, double charLength)
        {
            double returnValue = charLength;
            char[] passwordChars = password.ToCharArray();

            // When password length is less than 4, do nothing
            if (passwordChars.Length < 4)
            {
                return returnValue;
            }

            bool areAllCharFrameNeverUsingTheSameClass = true;
            for (int i = 0; i < passwordChars.Length - 3; i++)
            {
                PasswordTextClass[] pswdClass = new PasswordTextClass[4]
                    {
                        FormCreatePassword.GetPasswordClass(new String(passwordChars, i+0, 1)),
                        FormCreatePassword.GetPasswordClass(new String(passwordChars, i+1, 1)),
                        FormCreatePassword.GetPasswordClass(new String(passwordChars, i+2, 1)),
                        FormCreatePassword.GetPasswordClass(new String(passwordChars, i+3, 1))
                    };

                bool isTheSameClassInARow = true;
                for (int j = 1; j < pswdClass.Length; j++)
                {
                    isTheSameClassInARow = isTheSameClassInARow && (pswdClass[j] == pswdClass[0]);
                    if (!isTheSameClassInARow) break;
                }
                areAllCharFrameNeverUsingTheSameClass = areAllCharFrameNeverUsingTheSameClass && !isTheSameClassInARow;
            }

            if (areAllCharFrameNeverUsingTheSameClass)
            {
                // Add strength adjustment report
                this.Report(strings.General_NewPassword_Strength_TypeGood, String.Format(strings.General_NewPassword_Strength_SameClassNotInARow, 4), Color.Green);
                // Modify adjust value
                returnValue *= 1.15;
            }

            return returnValue;
        }
        /// <summary>
        /// Get pattern number for specified PasswordTextClass
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        private static int GetNumberOfPasswordPattern(PasswordTextClass c)
        {
            int lowers = Utility.Alphabet.Length;
            int uppers = Utility.ALPHABET.Length;
            int numerics = Utility.Numeric.Length;
            int symbols = Utility.Symbol.Length;
            int utf8_2bytes = 1920; // \u0080-\u07FF
            int utf8_3bytes = 63488; // \u0800-\uFFFF
            int utf8_4bytes = 1048576; // \u10000-\u10FFFF

            switch (c)
            {
                case PasswordTextClass.UseLowercaseOnly:
                    return lowers;
                case PasswordTextClass.UseUppercaseOnly:
                    return uppers;
                case PasswordTextClass.UseNumberOnly:
                    return numerics;
                case PasswordTextClass.UseSymbolOnly:
                    return symbols;
                case PasswordTextClass.UseLowerUpper:
                    return lowers + uppers;
                case PasswordTextClass.UseLowerNumber:
                    return lowers + numerics;
                case PasswordTextClass.UseLowerSymbol:
                    return lowers + symbols;
                case PasswordTextClass.UseUpperNumber:
                    return uppers + numerics;
                case PasswordTextClass.UseUpperSymbol:
                    return uppers + symbols;
                case PasswordTextClass.UseNumberSymbol:
                    return numerics + symbols;
                case PasswordTextClass.UseLowerUpperNumber:
                    return lowers + uppers + numerics;
                case PasswordTextClass.UseLowerUpperSymbol:
                    return lowers + uppers + symbols;
                case PasswordTextClass.UseLowerNumberSymbol:
                    return lowers + numerics + symbols;
                case PasswordTextClass.UseUpperNumberSymbol:
                    return uppers + numerics + symbols;
                case PasswordTextClass.UseLowerUpperNumberSymbol:
                    return lowers + uppers + numerics + symbols;
                case PasswordTextClass.Use4bytesUTF8Char:
                    return utf8_4bytes;
                case PasswordTextClass.Use3bytesUTF8Char:
                    return utf8_3bytes;
                case PasswordTextClass.Use2bytesUTF8Char:
                    return utf8_2bytes;
                default:
                    break;
            }

            return 0;
        }
        /// <summary>
        /// Convert class enum to its text
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        public static string GetPasswordClassText(PasswordTextClass c)
        {
            switch (c)
            {
                case PasswordTextClass.UseLowercaseOnly:
                    return strings.General_NewPassword_Strength_L;
                case PasswordTextClass.UseUppercaseOnly:
                    return strings.General_NewPassword_Strength_U;
                case PasswordTextClass.UseNumberOnly:
                    return strings.General_NewPassword_Strength_N;
                case PasswordTextClass.UseSymbolOnly:
                    return strings.General_NewPassword_Strength_S;
                case PasswordTextClass.UseLowerUpper:
                    return strings.General_NewPassword_Strength_LU;
                case PasswordTextClass.UseLowerNumber:
                    return strings.General_NewPassword_Strength_LN;
                case PasswordTextClass.UseLowerSymbol:
                    return strings.General_NewPassword_Strength_LS;
                case PasswordTextClass.UseUpperNumber:
                    return strings.General_NewPassword_Strength_UN;
                case PasswordTextClass.UseUpperSymbol:
                    return strings.General_NewPassword_Strength_US;
                case PasswordTextClass.UseNumberSymbol:
                    return strings.General_NewPassword_Strength_NS;
                case PasswordTextClass.UseLowerUpperNumber:
                    return strings.General_NewPassword_Strength_LUN;
                case PasswordTextClass.UseLowerUpperSymbol:
                    return strings.General_NewPassword_Strength_LUS;
                case PasswordTextClass.UseLowerNumberSymbol:
                    return strings.General_NewPassword_Strength_LNS;
                case PasswordTextClass.UseUpperNumberSymbol:
                    return strings.General_NewPassword_Strength_UNS;
                case PasswordTextClass.UseLowerUpperNumberSymbol:
                    return strings.General_NewPassword_Strength_LUNS;
                case PasswordTextClass.Use4bytesUTF8Char:
                    return strings.General_NewPassword_Strength_UTF8_4Bytes;
                case PasswordTextClass.Use3bytesUTF8Char:
                    return strings.General_NewPassword_Strength_UTF8_3Bytes;
                case PasswordTextClass.Use2bytesUTF8Char:
                    return strings.General_NewPassword_Strength_UTF8_2Bytes;
                default:
                    break;
            }

            return String.Empty;
        }
        /// <summary>
        /// Check whether using the same kind of 5 characters in a row.
        /// Length penalty: : -0.2
        /// </summary>
        /// <param name="password"></param>
        /// <param name="charLength"></param>
        /// <returns></returns>
        protected double CheckUsingSameKindOfCharsInARow(string password, double charLength)
        {
            double returnValue = charLength;
            char[] passwordChars = password.ToCharArray();

            // When password length is less than 5, do nothing
            if (passwordChars.Length < 5)
            {
                return returnValue;
            }

            for (int i = 0; i < passwordChars.Length - 4; i++)
            {
                PasswordTextClass[] pswdClass = new PasswordTextClass[5]
                    {
                        FormCreatePassword.GetPasswordClass(new String(passwordChars, i+0, 1)),
                        FormCreatePassword.GetPasswordClass(new String(passwordChars, i+1, 1)),
                        FormCreatePassword.GetPasswordClass(new String(passwordChars, i+2, 1)),
                        FormCreatePassword.GetPasswordClass(new String(passwordChars, i+3, 1)),
                        FormCreatePassword.GetPasswordClass(new String(passwordChars, i+4, 1))
                    };

                bool isTheSameClassInARow = true;
                for (int j = 1; j < pswdClass.Length; j++)
                {
                    isTheSameClassInARow = isTheSameClassInARow && (pswdClass[j] == pswdClass[0]);
                    if (!isTheSameClassInARow) break;
                }
                if (isTheSameClassInARow)
                {
                    // Add strength adjustment report
                    base.Report(strings.General_NewPassword_Strength_TypeBad, String.Format(strings.General_NewPassword_Strength_SameClassInARow, 5), Color.Red);
                    // Modify adjust value
                    returnValue -= 0.2;
                }
            }

            return returnValue;
        }