285 lines
No EOL
9.3 KiB
C#
285 lines
No EOL
9.3 KiB
C#
namespace EMQual;
|
|
|
|
public static class QualData
|
|
{
|
|
/// <summary>
|
|
/// Executes the <see cref="QualData"/> program.
|
|
/// </summary>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="filePath">The relative path to the CSV file</param>
|
|
/// <returns>An array containing parsed match data records</returns>
|
|
public static Match[] ReadMatchesFromFile(string filePath)
|
|
{
|
|
if (!File.Exists(filePath))
|
|
{
|
|
return Array.Empty<Match>();
|
|
}
|
|
|
|
string[] lines = File.ReadAllLines(filePath);
|
|
lines = lines.Skip(1).ToArray();
|
|
if (lines.Length == 0)
|
|
{
|
|
return Array.Empty<Match>();
|
|
}
|
|
|
|
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<Match>();
|
|
}
|
|
}
|
|
|
|
return matches;
|
|
|
|
//again, would be much easier with a list
|
|
/*var matches = new List<Match>();
|
|
foreach (var line in lines)
|
|
{
|
|
if (TryParseMatch(line, out Match? match))
|
|
{
|
|
matches.Add(match!);
|
|
}
|
|
else
|
|
{
|
|
return Array.Empty<Match>();
|
|
}
|
|
}
|
|
return matches.ToArray();*/
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attempts to parse a line with semicolon separated data for a match.
|
|
/// </summary>
|
|
/// <param name="line">Line to parse</param>
|
|
/// <param name="match">Parsed match object; null if parsing fails</param>
|
|
/// <returns>True if the line could be parsed successfully; false otherwise</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines if the supplied string is contained in the provided array of strings.
|
|
/// Case is ignored.
|
|
/// </summary>
|
|
/// <param name="value">Value to check for</param>
|
|
/// <param name="possibleValues">Array of values to check in</param>
|
|
/// <returns>True if the value is found; false otherwise</returns>
|
|
public static bool IsContained(string value, string[] possibleValues)
|
|
{
|
|
foreach (var possibleValue in possibleValues)
|
|
{
|
|
if (string.Equals(possibleValue, value, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns an array containing the names of all countries which have participated
|
|
/// in at least one match exactly one time.
|
|
/// </summary>
|
|
/// <param name="matches">Array of all matches played</param>
|
|
/// <returns>An array of unique country names</returns>
|
|
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;*/
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a new array of matches, based on the supplied full collection, but
|
|
/// with filtered to only contain matches the provided country participated in.
|
|
/// </summary>
|
|
/// <param name="allMatches">Array of all matches played</param>
|
|
/// <param name="countryName">Name of the country to filter for</param>
|
|
/// <returns>Array of matches in which the supplied country participated</returns>
|
|
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;*/
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines if the supplied match is one the provided country participated in.
|
|
/// </summary>
|
|
/// <param name="match">Match to check</param>
|
|
/// <param name="countryName">Country for which to check</param>
|
|
/// <returns>True if the country participated in the match; false otherwise</returns>
|
|
public static bool IsCountryMatch(Match match, string countryName)
|
|
{
|
|
TeamResult homeTeam = match.HomeTeam;
|
|
TeamResult guestTeam = match.GuestTeam;
|
|
return homeTeam.TeamName == countryName || guestTeam.TeamName == countryName;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prints the matches to the terminal.
|
|
/// </summary>
|
|
/// <param name="matches">Array of matches to print</param>
|
|
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}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="possibleCountries">Array containing the names of possible countries to pick from</param>
|
|
/// <returns>The name of the country the user selected</returns>
|
|
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;
|
|
}
|
|
} |