public static Boolean TryParse(String path, out Configuration aConfiguration)
        {
            Errors = new List <String>();
            ActualIntersectingKeys    = new Boolean[26];
            ActualNonIntersectingKeys = new Boolean[26];
            ActualKeys     = new List <string>();
            aConfiguration = new Configuration(path);

            if (aConfiguration.ConfigurationFileName.IndexOfAny(Path.GetInvalidFileNameChars()) > -1)
            {
                Errors.Add(String.Format(ConfigurationErrors.FilenameError, path));
            }
            else
            {
                StreamReader fileIn = new StreamReader(path);

                // Validate file.
                while (!fileIn.EndOfStream)
                {
                    // New UPDATE
                    // Read a line.
                    String line = fileIn.ReadLine();
                    line = BufferClass.Concatenation(line);
                    // Parse a configuration item.
                    ConfigurationFileItem aConfigurationItem;
                    if (ConfigurationFileItem.TryParse(line, out aConfigurationItem))
                    {
                        if (aConfigurationItem.KeyValue != null && ActualKeys.Contains(aConfigurationItem.KeyValue.Key))
                        {
                            Errors.Add(String.Format(ConfigurationErrors.DuplicateKeyError, aConfigurationItem.KeyValue.OriginalKeyValue));
                        }
                        else
                        {
                            // Record that this key has been found.
                            if (aConfigurationItem.KeyValue != null)
                            {
                                ActualKeys.Add(aConfigurationItem.KeyValue.Key);
                            }

                            // Process the key-value.
                            if (aConfigurationItem.IsLogFile)
                            {
                                // Get the value representing an invalid score.
                                aConfiguration.LogFileName = aConfigurationItem.KeyValue.Value.Trim();
                                if (Validator.IsDelimited(aConfiguration.LogFileName, Crozzle.StringDelimiters))
                                {
                                    aConfiguration.LogFileName = aConfiguration.LogFileName.Trim(Crozzle.StringDelimiters);
                                    if (!Validator.IsFilename(aConfiguration.LogFileName))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMinimumNumberOfUniqueWords)
                            {
                                // Get the value of the minimum number of unique words allowed in the wordlist.
                                int minimum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out minimum))
                                {
                                    aConfiguration.MinimumNumberOfUniqueWords = minimum;
                                    if (!Validator.TryRange(minimum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMaximumNumberOfUniqueWords)
                            {
                                // Get the value of the maximum number of unique words allowed in the wordlist.
                                int maximum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out maximum))
                                {
                                    aConfiguration.MaximumNumberOfUniqueWords = maximum;
                                    if (!Validator.TryRange(maximum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsInvalidCrozzleScore)
                            {
                                // Get the value representing an invalid score.
                                aConfiguration.InvalidCrozzleScore = aConfigurationItem.KeyValue.Value.Trim();
                                if (Validator.IsDelimited(aConfiguration.InvalidCrozzleScore, Crozzle.StringDelimiters))
                                {
                                    aConfiguration.InvalidCrozzleScore = aConfiguration.InvalidCrozzleScore.Trim(Crozzle.StringDelimiters);
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsUppercase)
                            {
                                // Get the Boolean value that determines whether to display the crozzle letters in uppercase or lowercase.
                                Boolean uppercase = true;
                                if (!Validator.IsMatch(aConfigurationItem.KeyValue.Value, allowedBooleans))
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                                aConfiguration.Uppercase = uppercase;
                            }
                            else if (aConfigurationItem.IsStyle)
                            {
                                // Get the value of the HTML style to display the crozzle in an HTML table.
                                aConfiguration.Style = aConfigurationItem.KeyValue.Value.Trim();
                                if (Validator.IsDelimited(aConfiguration.Style, Crozzle.StringDelimiters))
                                {
                                    aConfiguration.Style = aConfiguration.Style.Trim(Crozzle.StringDelimiters);
                                    if (!Validator.IsStyleTag(aConfiguration.Style))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.StyleError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsBGcolourEmptyTD)
                            {
                                // Get the value of the background colour for an empty TD (HTML table data).
                                aConfiguration.BGcolourEmptyTD = aConfigurationItem.KeyValue.Value.Trim();
                                if (!Validator.IsHexColourCode(aConfiguration.BGcolourEmptyTD))
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ColourError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsBGcolourNonEmptyTD)
                            {
                                // Get the value of the background colour for a non empty TD (HTML table data).
                                aConfiguration.BGcolourNonEmptyTD = aConfigurationItem.KeyValue.Value.Trim();
                                if (!Validator.IsHexColourCode(aConfiguration.BGcolourNonEmptyTD))
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ColourError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMinimumNumberOfRows)
                            {
                                // Get the value of the minimum number of rows per crozzle.
                                int minimum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out minimum))
                                {
                                    aConfiguration.MinimumNumberOfRows = minimum;
                                    if (!Validator.TryRange(minimum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMaximumNumberOfRows)
                            {
                                // Get the value of the maximum number of rows per crozzle.
                                int maximum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out maximum))
                                {
                                    aConfiguration.MaximumNumberOfRows = maximum;
                                    if (!Validator.TryRange(maximum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMinimumNumberOfColumns)
                            {
                                // Get the value of the minimum number of columns per crozzle.
                                int minimum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out minimum))
                                {
                                    aConfiguration.MinimumNumberOfColumns = minimum;
                                    if (!Validator.TryRange(minimum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMaximumNumberOfColumns)
                            {
                                // Get the value of the maximum number of columns per crozzle.
                                int maximum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out maximum))
                                {
                                    aConfiguration.MaximumNumberOfColumns = maximum;
                                    if (!Validator.TryRange(maximum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMinimumHorizontalWords)
                            {
                                // Get the value of the minimum number of horizontal words in a crozzle.
                                int minimum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out minimum))
                                {
                                    aConfiguration.MinimumHorizontalWords = minimum;
                                    if (!Validator.TryRange(minimum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMaximumHorizontalWords)
                            {
                                // Get the value of the maximum number of horizontal words in a crozzle.
                                int maximum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out maximum))
                                {
                                    aConfiguration.MaximumHorizontalWords = maximum;
                                    if (!Validator.TryRange(maximum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMinimumVerticalWords)
                            {
                                // Get the value of the minimum number of vertical words in a crozzle.
                                int minimum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out minimum))
                                {
                                    aConfiguration.MinimumVerticalWords = minimum;
                                    if (!Validator.TryRange(minimum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMaximumVerticalWords)
                            {
                                // Get the value of the maximum number of vertical words in a crozzle.
                                int maximum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out maximum))
                                {
                                    aConfiguration.MaximumVerticalWords = maximum;
                                    if (!Validator.TryRange(maximum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMinimumIntersectionsInHorizontalWords)
                            {
                                // Get the value of the minimum number of the intersections in a horizontal word.
                                int minimum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out minimum))
                                {
                                    aConfiguration.MinimumIntersectionsInHorizontalWords = minimum;
                                    if (!Validator.TryRange(minimum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMaximumIntersectionsInHorizontalWords)
                            {
                                // Get the value of the maximum number of the intersections in a horizontal word.
                                int maximum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out maximum))
                                {
                                    aConfiguration.MaximumIntersectionsInHorizontalWords = maximum;
                                    if (!Validator.TryRange(maximum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMinimumIntersectionsInVerticalWords)
                            {
                                // Get the value of the minimum number of the intersections in a vertical word.
                                int minimum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out minimum))
                                {
                                    aConfiguration.MinimumIntersectionsInVerticalWords = minimum;
                                    if (!Validator.TryRange(minimum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMaximumIntersectionsInVerticalWords)
                            {
                                // Get the value of the maximum number of the intersections in a vertical word.
                                int maximum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out maximum))
                                {
                                    aConfiguration.MaximumIntersectionsInVerticalWords = maximum;
                                    if (!Validator.TryRange(maximum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMinimumNumberOfTheSameWord)
                            {
                                // Get the value of the minimum number of the same word per crozzle limit.
                                int minimum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out minimum))
                                {
                                    aConfiguration.MinimumNumberOfTheSameWord = minimum;
                                    if (!Validator.TryRange(minimum, 0, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMaximumNumberOfTheSameWord)
                            {
                                // Get the value of the maximum number of the same word per crozzle limit.
                                int maximum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out maximum))
                                {
                                    aConfiguration.MaximumNumberOfTheSameWord = maximum;
                                    if (!Validator.TryRange(maximum, 0, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMinimumNumberOfGroups)
                            {
                                // Get the value of the minimum number of groups per crozzle limit.
                                int minimum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out minimum))
                                {
                                    aConfiguration.MinimumNumberOfGroups = minimum;
                                    if (!Validator.TryRange(minimum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsMaximumNumberOfGroups)
                            {
                                // Get the value of the maximum number of groups per crozzle limit.
                                int maximum;
                                if (Validator.IsInt32(aConfigurationItem.KeyValue.Value.Trim(), out maximum))
                                {
                                    aConfiguration.MaximumNumberOfGroups = maximum;
                                    if (!Validator.TryRange(maximum, 1, Int32.MaxValue))
                                    {
                                        Errors.Add(String.Format(ConfigurationErrors.IntegerError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                    }
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, aConfigurationItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsIntersecting)
                            {
                                // New UPDATE
                                // Get the value of each INTERSECTING point.
                                KeyValue originalKeyValue   = aConfigurationItem.KeyValue;
                                String   originalName       = aConfigurationItem.Name;
                                String[] originalNameLetter = originalName.Split('-');
                                string   letterChar         = originalNameLetter[originalNameLetter.Length - 1];
                                int      points;
                                // Validation for letter score
                                if (Validator.IsInt32(originalKeyValue.Value, out points))
                                {
                                    int index = (int)letterChar[0] - (int)'A';
                                    aConfiguration.IntersectingPointsPerLetter[index] = points;
                                    ActualIntersectingKeys[index] = true;
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, originalKeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                            else if (aConfigurationItem.IsNonIntersecting)
                            {
                                // New UPDATE
                                // Get the value of each NONINTERSECTING point.
                                KeyValue originalKeyValue   = aConfigurationItem.KeyValue;
                                String   originalName       = aConfigurationItem.Name;
                                String[] originalNameLetter = originalName.Split('-');
                                string   letterChar         = originalNameLetter[originalNameLetter.Length - 1];
                                int      points;
                                // Validation for letter score
                                if (Validator.IsInt32(originalKeyValue.Value, out points))
                                {
                                    int index = (int)letterChar[0] - (int)'A';
                                    aConfiguration.NonIntersectingPointsPerLetter[index] = points;
                                    ActualNonIntersectingKeys[index] = true;
                                }
                                else
                                {
                                    Errors.Add(String.Format(ConfigurationErrors.ValueError, originalKeyValue.OriginalKeyValue, Validator.Errors[0]));
                                }
                            }
                        }
                    }
                    else
                    {
                        Errors.AddRange(ConfigurationFileItem.Errors);
                    }
                }

                // Close files.
                fileIn.Close();

                // Check which keys are missing from the configuration file.
                foreach (string expectedKey in ExpectedKeys)
                {
                    if (!ActualKeys.Contains(expectedKey))
                    {
                        Errors.Add(String.Format(ConfigurationErrors.MissingKeyError, expectedKey));
                    }
                }

                for (char ch = 'A'; ch <= 'Z'; ch++)
                {
                    if (!ActualIntersectingKeys[(int)ch - (int)'A'])
                    {
                        Errors.Add(String.Format(ConfigurationErrors.MissingIntersectionKeyError, ch.ToString()));
                    }
                }
                for (char ch = 'A'; ch <= 'Z'; ch++)
                {
                    if (!ActualNonIntersectingKeys[(int)ch - (int)'A'])
                    {
                        Errors.Add(String.Format(ConfigurationErrors.MissingNonIntersectionKeyError, ch.ToString()));
                    }
                }

                // Check that minimum values are <= to their maximmum counterpart values.
                // New UPDATE
                // Keys are changed
                if (ActualKeys.Contains("SEQUENCES-IN-FILE-MINIMUM") && ActualKeys.Contains("SEQUENCES-IN-FILE-MAXIMUM"))
                {
                    if (aConfiguration.MinimumNumberOfUniqueWords > aConfiguration.MaximumNumberOfUniqueWords)
                    {
                        Errors.Add(String.Format(ConfigurationErrors.MinGreaterThanMaxError, "SEQUENCES-IN-FILE-MINIMUM",
                                                 aConfiguration.MinimumNumberOfUniqueWords, aConfiguration.MaximumNumberOfUniqueWords));
                    }
                }
                if (ActualKeys.Contains("CROZZLE-SIZE-MINIMUM-ROWS") && ActualKeys.Contains("CROZZLE-SIZE-MAXIMUM-ROWS"))
                {
                    if (aConfiguration.MinimumNumberOfRows > aConfiguration.MaximumNumberOfRows)
                    {
                        Errors.Add(String.Format(ConfigurationErrors.MinGreaterThanMaxError, "CROZZLE-SIZE-MINIMUM-ROWS",
                                                 aConfiguration.MinimumNumberOfRows, aConfiguration.MaximumNumberOfRows));
                    }
                }
                if (ActualKeys.Contains("CROZZLE-SIZE-MINIMUM-COLUMNS") && ActualKeys.Contains("CROZZLE-SIZE-MAXIMUM-COLUMNS"))
                {
                    if (aConfiguration.MinimumNumberOfColumns > aConfiguration.MaximumNumberOfColumns)
                    {
                        Errors.Add(String.Format(ConfigurationErrors.MinGreaterThanMaxError, "CROZZLE-SIZE-MINIMUM-COLUMNS",
                                                 aConfiguration.MinimumNumberOfColumns, aConfiguration.MaximumNumberOfColumns));
                    }
                }
                if (ActualKeys.Contains("SEQUENCES-IN-CROZZLE-MINIMUM-HORIZONTAL") && ActualKeys.Contains("SEQUENCES-IN-CROZZLE-MAXIMUM-HORIZONTAL"))
                {
                    if (aConfiguration.MinimumHorizontalWords > aConfiguration.MaximumHorizontalWords)
                    {
                        Errors.Add(String.Format(ConfigurationErrors.MinGreaterThanMaxError, "SEQUENCES-IN-CROZZLE-MAXIMUM-HORIZONTAL",
                                                 aConfiguration.MinimumHorizontalWords, aConfiguration.MaximumHorizontalWords));
                    }
                }
                if (ActualKeys.Contains("SEQUENCES-IN-CROZZLE-MINIMUM-VERTICAL") && ActualKeys.Contains("SEQUENCES-IN-CROZZLE-MAXIMUM-VERTICAL"))
                {
                    if (aConfiguration.MinimumVerticalWords > aConfiguration.MaximumVerticalWords)
                    {
                        Errors.Add(String.Format(ConfigurationErrors.MinGreaterThanMaxError, "SEQUENCES-IN-CROZZLE-MINIMUM-VERTICAL",
                                                 aConfiguration.MinimumVerticalWords, aConfiguration.MaximumVerticalWords));
                    }
                }
                if (ActualKeys.Contains("INTERSECTIONS-IN-SEQUENCES-MINIMUM-HORIZONTAL") && ActualKeys.Contains("INTERSECTIONS-IN-SEQUENCES-MAXIMUM-HORIZONTAL"))
                {
                    if (aConfiguration.MinimumIntersectionsInHorizontalWords > aConfiguration.MaximumIntersectionsInHorizontalWords)
                    {
                        Errors.Add(String.Format(ConfigurationErrors.MinGreaterThanMaxError, "INTERSECTIONS-IN-SEQUENCES-MINIMUM-HORIZONTAL",
                                                 aConfiguration.MinimumIntersectionsInHorizontalWords, aConfiguration.MaximumIntersectionsInHorizontalWords));
                    }
                }
                if (ActualKeys.Contains("INTERSECTIONS-IN-SEQUENCES-MINIMUM-VERTICAL") && ActualKeys.Contains("INTERSECTIONS-IN-SEQUENCES-MAXIMUM-VERTICAL"))
                {
                    if (aConfiguration.MinimumIntersectionsInVerticalWords > aConfiguration.MaximumIntersectionsInVerticalWords)
                    {
                        Errors.Add(String.Format(ConfigurationErrors.MinGreaterThanMaxError, "INTERSECTIONS-IN-SEQUENCES-MAXIMUM-VERTICAL",
                                                 aConfiguration.MinimumIntersectionsInVerticalWords, aConfiguration.MaximumIntersectionsInVerticalWords));
                    }
                }
                if (ActualKeys.Contains("DUPLICATE-SEQUENCES-MINIMUM") && ActualKeys.Contains("DUPLICATE-SEQUENCES-MAXIMUM"))
                {
                    if (aConfiguration.MinimumNumberOfTheSameWord > aConfiguration.MaximumNumberOfTheSameWord)
                    {
                        Errors.Add(String.Format(ConfigurationErrors.MinGreaterThanMaxError, "DUPLICATE-SEQUENCES-MINIMUM",
                                                 aConfiguration.MinimumNumberOfTheSameWord, aConfiguration.MaximumNumberOfTheSameWord));
                    }
                }
                if (ActualKeys.Contains("VALID-GROUPS-MINIMUM") && ActualKeys.Contains("VALID-GROUPS-MAXIMUM"))
                {
                    if (aConfiguration.MinimumNumberOfGroups > aConfiguration.MaximumNumberOfGroups)
                    {
                        Errors.Add(String.Format(ConfigurationErrors.MinGreaterThanMaxError, "VALID-GROUPS-MINIMUM",
                                                 aConfiguration.MinimumNumberOfGroups, aConfiguration.MaximumNumberOfGroups));
                    }
                }
            }

            // Store validity.
            aConfiguration.Valid = Errors.Count == 0;
            return(aConfiguration.Valid);
        }
        public static Boolean TryParse(String path, Configuration aConfiguration, WordList wordList, out Crozzle aCrozzle)
        {
            Errors   = new List <String>();
            aCrozzle = new Crozzle(path, aConfiguration, wordList);
            // UPDATED
            // Open file.
            StreamReader  fileIn   = new StreamReader(path);
            List <String> wordData = new List <string>();

            // Validate file.
            while (!fileIn.EndOfStream)
            {
                // Read a line.
                String line = fileIn.ReadLine();
                line = BufferClass.Concatenation(line);
                // Parse a crozzle file item.
                CrozzleFileItem aCrozzleFileItem;
                if (CrozzleFileItem.TryParse(line, out aCrozzleFileItem))
                {
                    if (aCrozzleFileItem.IsConfigurationFile)
                    {
                        // Get the configuration file name.
                        String configurationPath = aCrozzleFileItem.KeyValue.Value;
                        if (configurationPath == null)
                        {
                            Errors.Add(CrozzleFileErrors.ConfigurationFilenameMissing);
                        }
                        else
                        {
                            configurationPath = configurationPath.Trim();
                            if (Validator.IsDelimited(configurationPath, StringDelimiters))
                            {
                                configurationPath = configurationPath.Trim(StringDelimiters);
                            }

                            if (!Path.IsPathRooted(configurationPath))
                            {
                                String directoryName = Path.GetDirectoryName(path);
                                configurationPath = directoryName + @"\" + configurationPath;
                            }

                            aCrozzle.ConfigurationPath = configurationPath;
                        }
                    }
                    else if (aCrozzleFileItem.isSequenceFile)
                    {
                        // Get the word list file name.
                        String wordListPath = aCrozzleFileItem.KeyValue.Value;
                        if (wordListPath == null)
                        {
                            Errors.Add(CrozzleFileErrors.WordlistFilenameMissing);
                        }
                        else
                        {
                            wordListPath = wordListPath.Trim();
                            if (Validator.IsDelimited(wordListPath, StringDelimiters))
                            {
                                wordListPath = wordListPath.Trim(StringDelimiters);
                            }

                            if (!Path.IsPathRooted(wordListPath))
                            {
                                String directoryName = Path.GetDirectoryName(path);
                                wordListPath = directoryName + @"\" + wordListPath;
                            }
                            aCrozzle.WordListPath = wordListPath;
                        }
                    }
                    else if (aCrozzleFileItem.isSize)
                    {
                        // Get the number of rows.
                        // UPDATED
                        // from originally 2 line of size to one line of size
                        int      rows;
                        int      cols;
                        string[] ColsRows = aCrozzleFileItem.KeyValue.Value.Split(',');
                        if (Validator.IsInt32(ColsRows[0], out rows))
                        {
                            aCrozzle.Rows = rows;
                        }
                        else
                        {
                            Errors.Add(String.Format(CrozzleFileErrors.RowError, aCrozzleFileItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                        }
                        if (Validator.IsInt32(ColsRows[1], out cols))
                        {
                            aCrozzle.Columns = cols;
                        }
                        else
                        {
                            Errors.Add(String.Format(CrozzleFileErrors.RowError, aCrozzleFileItem.KeyValue.OriginalKeyValue, Validator.Errors[0]));
                        }
                    }
                    else if (aCrozzleFileItem.isVertical)
                    {
                        // Collect potential word data for a horizontal word.
                        wordData.Add(aCrozzleFileItem.KeyValue.OriginalKeyValue);
                    }
                    else if (aCrozzleFileItem.isHorizontal)
                    {
                        // Collect potential word data for a vertical word.
                        wordData.Add(aCrozzleFileItem.KeyValue.OriginalKeyValue);
                    }
                }
                else
                {
                    Errors.AddRange(CrozzleFileItem.Errors);
                }
            }

            // Close files.
            fileIn.Close();


            // Get potential word data list.
            WordDataList wordDataList;

            if (!WordDataList.TryParse(wordData, aCrozzle, out wordDataList))
            {
                Errors.AddRange(WordDataList.Errors);
            }
            aCrozzle.WordDataList = wordDataList;


            // Validate file sections.
            // Check the configuration file name.
            if (aCrozzle.Configuration != null)
            {
                if (aCrozzle.Configuration.ConfigurationPath != aCrozzle.ConfigurationPath)
                {
                    Errors.Add(String.Format(CrozzleFileErrors.ConfigurationFilenameError, aCrozzle.ConfigurationPath, aCrozzle.Configuration.ConfigurationFileName));
                }
            }

            // Check the word list file name.
            if (aCrozzle.WordList != null)
            {
                if (aCrozzle.WordList.WordlistPath != aCrozzle.WordListPath)
                {
                    Errors.Add(String.Format(CrozzleFileErrors.WordlistFilenameError, aCrozzle.WordListPath, aCrozzle.WordList.WordlistFileName));
                }
            }

            // Raw word data of horizontal and vertical words were obtained when reading the crozzle file,
            // but now we need to create crozzle rows and crozzle columns that represent the crozzle.
            aCrozzle.CreateCrozzleRows(aCrozzle.WordDataList);
            aCrozzle.CreateCrozzleColumns(aCrozzle.WordDataList);

            // Store validity.
            aCrozzle.FileValid = Errors.Count == 0;
            return(aCrozzle.FileValid);
        }