namespace EMQual; public static class QualData { /// /// Executes the program. /// public static void Run() { var matches = ReadMatchesFromFile("Data/matches.csv"); PrintMatches(matches); Console.WriteLine(); var countryNames = ExtractUniqueCountryNames(matches); var selCountry = AskForCountry(countryNames); var countryMatches = FilterMatchesByCountry(matches, selCountry); PrintMatches(countryMatches); } /// /// Reads match information from a CSV file at the provided location. /// If the file does not exist or does not contain relevant or some /// corrupted data an empty array is returned. /// /// The relative path to the CSV file /// An array containing parsed match data records public static Match[] ReadMatchesFromFile(string filePath) { if (!File.Exists(filePath)) { return Array.Empty(); } string[] lines = File.ReadAllLines(filePath); lines = lines.Skip(1).ToArray(); if (lines.Length == 0) { return Array.Empty(); } int index = 0; Match[] matches = new Match[lines.Length]; foreach(var line in lines) { if (TryParseMatch(line, out Match? match)) { matches[index++] = match!; } else { return Array.Empty(); } } return matches; //again, would be much easier with a list /*var matches = new List(); foreach (var line in lines) { if (TryParseMatch(line, out Match? match)) { matches.Add(match!); } else { return Array.Empty(); } } return matches.ToArray();*/ } /// /// Attempts to parse a line with semicolon separated data for a match. /// /// Line to parse /// Parsed match object; null if parsing fails /// True if the line could be parsed successfully; false otherwise public static bool TryParseMatch(string line, out Match? match) { match = null; string[] parts = line.Split(';'); if (parts.Length != 4) { return false; } foreach (var part in parts) { if (part.Length == 0) { return false; } } int[] goals = new int[2]; if (!int.TryParse(parts[2], out goals[0]) || !int.TryParse(parts[3], out goals[1])) { return false; } if(goals[0] < 0 || goals[1] < 0) { return false; } match = new Match(new TeamResult(parts[0], goals[0]), new TeamResult(parts[1], goals[1])); return true; } /// /// Determines if the supplied string is contained in the provided array of strings. /// Case is ignored. /// /// Value to check for /// Array of values to check in /// True if the value is found; false otherwise public static bool IsContained(string value, string[] possibleValues) { foreach (var possibleValue in possibleValues) { if (string.Equals(possibleValue, value, StringComparison.InvariantCultureIgnoreCase)) { return true; } } return false; } /// /// Returns an array containing the names of all countries which have participated /// in at least one match exactly one time. /// /// Array of all matches played /// An array of unique country names public static string[] ExtractUniqueCountryNames(Match[] matches) { int uniqueCount = 0; string[] tempCountryNames = new string[matches.Length * 2]; foreach (var match in matches) { TeamResult homeTeam = match.HomeTeam; TeamResult guestTeam = match.GuestTeam; if (!IsContained(homeTeam.TeamName, tempCountryNames)) { tempCountryNames[uniqueCount++] = homeTeam.TeamName; } if (!IsContained(guestTeam.TeamName, tempCountryNames)) { tempCountryNames[uniqueCount++] = guestTeam.TeamName; } } string[] countryNames = new string[uniqueCount]; for (int i = 0; i < uniqueCount; i++) { countryNames[i] = tempCountryNames[i]; } return countryNames; //Would be much easier with a list, but unfortunately the task requires an array /*string[] countryNames = []; foreach (var match in matches) { TeamResult homeTeam = match.HomeTeam; TeamResult guestTeam = match.GuestTeam; if (!IsContained(homeTeam.TeamName, countryNames)) { countryNames = countryNames.Append(homeTeam.TeamName).ToArray(); } if (!IsContained(guestTeam.TeamName, countryNames)) { countryNames = countryNames.Append(guestTeam.TeamName).ToArray(); } } return countryNames;*/ } /// /// Returns a new array of matches, based on the supplied full collection, but /// with filtered to only contain matches the provided country participated in. /// /// Array of all matches played /// Name of the country to filter for /// Array of matches in which the supplied country participated public static Match[] FilterMatchesByCountry(Match[] allMatches, string countryName) { int count = 0; foreach (var match in allMatches) { if (IsCountryMatch(match, countryName)) { count++; } } Match[] filteredMatches = new Match[count]; int index = 0; for (int i = 0; i < allMatches.Length; i++) { if (IsCountryMatch(allMatches[i], countryName)) { filteredMatches[index++] = allMatches[i]; } } return filteredMatches; //Mister Haslinger, please allow me to use lists /*Match[] filteredMatches = []; foreach (var match in allMatches) { if (IsCountryMatch(match, countryName)) { filteredMatches = filteredMatches.Append(match).ToArray(); } } return filteredMatches;*/ } /// /// Determines if the supplied match is one the provided country participated in. /// /// Match to check /// Country for which to check /// True if the country participated in the match; false otherwise public static bool IsCountryMatch(Match match, string countryName) { TeamResult homeTeam = match.HomeTeam; TeamResult guestTeam = match.GuestTeam; return homeTeam.TeamName == countryName || guestTeam.TeamName == countryName; } /// /// Prints the matches to the terminal. /// /// Array of matches to print private static void PrintMatches(Match[] matches) { Console.WriteLine($"{"Home",-15} {"Guest",-20}"); for(int i = 0; i < 39; i++) { Console.Write("="); } Console.WriteLine(); foreach (var match in matches) { TeamResult homeTeam = match.HomeTeam; TeamResult guestTeam = match.GuestTeam; Console.WriteLine($"{homeTeam.TeamName,-14} | {guestTeam.TeamName, -15} => {homeTeam.Goals}:{guestTeam.Goals}"); } } /// /// Asks the user to enter a country to filter for. /// The user can only enter one of the existing countries. Case is not relevant. /// If the user enters something invalid the input request is retried until the user gets it right. /// /// Array containing the names of possible countries to pick from /// The name of the country the user selected private static string AskForCountry(string[] possibleCountries) { string country; bool isContained; do { Console.Write("Enter the name of a country to filter: "); country = Console.ReadLine()!; isContained = IsContained(country, possibleCountries); if (!isContained) { Console.WriteLine("Invalid input, try again..."); } } while (!isContained); return country; } }