Declarative-Languages / Declarative Language Practical 2 / UpdateGrades / Program.cs
Program.cs
Raw
/*
 *  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;
        }
    }
}