/* * Program: UpdateGrades.exe * Module: Program.cs * Date: August 11, 2023 * Description: Allows a user to modify the * course grades data in grades.xml. It will also display a listing * of the grades data in the console window. * NOTE: This project targets .NET 7. If necessary, you can edit the project's * Target Framework property to target another version. */ using System.Diagnostics.Metrics; using System.Xml; namespace UpdateGrades { internal class Program { // Constants for the input and output file paths (they're in the main solution folder) const string InputFile = @"..\..\..\..\grades.xml"; const string OutputFile = @"..\..\..\..\grades-updated.xml"; static void Main() { //Output title Console.WriteLine("Student Grades Update\n"); // Creating XmlDocument object XmlDocument doc = new XmlDocument(); // Assuming the program will only run once, we won't use a while loop here // Try catch block to catch xml or any other exceptions try { // Loading xml document using InputFile doc.Load(InputFile); // Calling DisplayGrades and passing our doc to it DisplayGrades(doc); // Calling DisplayGPA and passing our doc to it DisplayGPA(doc); // Gaining user input for course they want to change Console.Write("\nEnter a course to change: "); string courseCode = Console.ReadLine() ?? ""; // Gaining user input for letter grade they want to change to Console.Write("\nEnter the new letter grade: "); string grade = Console.ReadLine() ?? ""; // Calling UpdateGrade and passing our doc, course code, and grade to it to update them UpdateGrade(doc, courseCode, grade); // Displaying updated doc DisplayGrades(doc); DisplayGPA(doc); // Saving doc to different output file doc.Save(OutputFile); } catch (XmlException err) { Console.WriteLine("\nXML ERROR: " + err.Message); } catch (Exception err) { Console.WriteLine("\nERROR: " + err.Message); } } static void DisplayGrades(XmlDocument doc) { // Outputting table header Console.WriteLine("Course Letter Grade Point Credits"); // Getting node list of courses XmlNodeList courses = doc.DocumentElement.GetElementsByTagName("course"); // Going through each course and displaying its data foreach (XmlNode course in courses) { Console.WriteLine($"{course.Attributes["code"].Value, -13}{course["letter-grade"].InnerText, -12}{course["grade-point"].InnerText, -16}{course["credits"].InnerText, -9}"); } } static void DisplayGPA(XmlDocument doc) { // Creating required variables double totalCredits = 0, totalPoints = 0; // Getting node list of courses XmlNodeList courses = doc.DocumentElement.GetElementsByTagName("course"); // Going through each course and adding total credits and points foreach (XmlNode course in courses) { totalCredits += double.Parse(course["credits"].InnerText); totalPoints += double.Parse(course["grade-point"].InnerText) * double.Parse(course["credits"].InnerText); } // Calculating and outputting GPA Console.WriteLine($"\nGrade Point Average: {totalPoints / totalCredits}"); } static void UpdateGrade(XmlDocument doc, string courseCode, string grade) { XmlNode newCourse = null; // Getting node list of courses XmlNodeList courses = doc.DocumentElement.GetElementsByTagName("course"); // Going through each course to find the user selected one foreach (XmlNode course in courses) { // If found, update the data if (course.Attributes["code"].Value == courseCode) { newCourse = course; newCourse["letter-grade"].InnerText = grade; newCourse["grade-point"].InnerText = LetterToGradePoint(grade).ToString(); } } // If still null, output error if (newCourse == null) { Console.WriteLine($"No course with code {courseCode} exists."); } } static double LetterToGradePoint(string grade) { // Dictionary to hold our Letter grade to GPA data so we can match letter grades to their respective GPA Dictionary<string, double> gradePoints = new Dictionary<string, double> { {"A+", 4.2}, {"A", 4.0}, {"B+", 3.5}, {"B", 3.0}, {"C+", 2.5}, {"C", 2.0}, {"D+", 1.5}, {"D", 1.0}, {"F", 0.0} }; return gradePoints.ContainsKey(grade) ? gradePoints[grade] : 0.0; } } }