/* * Programmer and Original Programming Style: * Jeremiah Burke O'Neal * Bachelor of Science in Information Technology Management, 2009 * * Portfolio Program: * Information Technology Support Ticket Activity Report * * Academic Integrity and Transformation Notice: * * Jeremiah Burke O'Neal previously created a GPA calculator as part of a * college programming assignment. The original coursework is not included * in this file and should not be publicly distributed because another * student could copy it and improperly submit it as academic work. * * ChatGPT created this separate portfolio demonstration so it cannot be * used as a direct substitute for the original GPA assignment. ChatGPT * deliberately changed: * * 1. The program's purpose from calculating student GPA to analyzing * information technology support tickets. * 2. The input fields from student names, courses, grades, and credit hours * to ticket numbers, technical issue descriptions, priority levels, * resolution times, and completion status. * 3. The mathematical processing from grade-point calculations to ticket * totals, average resolution time, priority counts, and longest-ticket * identification. * 4. The data model from course records to SupportTicket objects. * 5. The program flow, method names, validation rules, report layout, * classes, prompts, variables, and calculations. * 6. The final output from a GPA report to an IT support activity report. * * Removing these comments would not turn this program into the original * coursework because the operative source code performs an entirely * different task. To recreate the former GPA assignment, a person would * need to independently replace the data model, inputs, calculations, * validation, terminology, and output. * * No software can honestly be guaranteed to be impossible to reverse * engineer. This version was instead designed to be functionally unrelated * to the original assignment and unsuitable for submission as that * assignment. * * ChatGPT Modification Summary: * This code resembles the detailed commenting, console interaction, * validation, class organization, and readable variable naming that * Jeremiah Burke O'Neal would use. ChatGPT modified the concept by creating * an original IT ticket analysis program with object-oriented records, * multiple validation methods, statistical calculations, and a formatted * operational summary. */ using System; using System.Collections.Generic; using static System.Console; namespace Jeremiah_IT_Ticket_Portfolio { class SupportTicket { public int TicketNumber { get; set; } public string IssueDescription { get; set; } public string PriorityLevel { get; set; } public decimal ResolutionHours { get; set; } public bool WasResolved { get; set; } public SupportTicket( int ticketNumber, string issueDescription, string priorityLevel, decimal resolutionHours, bool wasResolved) { TicketNumber = ticketNumber; IssueDescription = issueDescription; PriorityLevel = priorityLevel; ResolutionHours = resolutionHours; WasResolved = wasResolved; } /************************************************************ * * Returns a short display value for the ticket status. * ************************************************************/ public string GetStatusText() { if (WasResolved) { return "Resolved"; } return "Open"; } } class TicketActivityProgram { private static List ticketRecords = new List(); static void Main(string[] args) { DisplayProgramIntroduction(); GatherTicketRecords(); DisplayTicketReport(); WriteLine("\nPress any key to close the program..."); ReadKey(); } /************************************************************ * * Displays the name and purpose of the portfolio program. * ************************************************************/ private static void DisplayProgramIntroduction() { Clear(); WriteLine("Jeremiah O'Neal IT Support Ticket Report"); WriteLine("========================================"); WriteLine(); WriteLine("This program records completed and open IT"); WriteLine("support tickets and produces an activity report."); WriteLine(); WriteLine("Press any key to begin entering ticket records..."); ReadKey(); Clear(); } /************************************************************ * * Main loop used to collect IT support ticket information. * ************************************************************/ private static void GatherTicketRecords() { bool enterAnotherTicket = true; while (enterAnotherTicket) { WriteLine("\n----------------------------------------"); WriteLine("IT SUPPORT TICKET ENTRY"); WriteLine("----------------------------------------"); int ticketNumber = GetTicketNumber(); string issueDescription = GetIssueDescription(); string priorityLevel = GetPriorityLevel(); bool wasResolved = GetResolutionStatus(); decimal resolutionHours = 0.00M; if (wasResolved) { resolutionHours = GetResolutionHours(); } SupportTicket newTicket = new SupportTicket( ticketNumber, issueDescription, priorityLevel, resolutionHours, wasResolved ); ticketRecords.Add(newTicket); WriteLine("\nThe ticket record was added successfully."); enterAnotherTicket = AskToEnterAnotherTicket(); } } /************************************************************ * * Requires a positive and unused ticket number. * ************************************************************/ private static int GetTicketNumber() { int ticketNumber = 0; bool ticketNumberIsValid = false; while (!ticketNumberIsValid) { Write("\nTicket number: "); string enteredValue = ReadLine(); if (!int.TryParse(enteredValue, out ticketNumber)) { WriteLine( "The ticket number must contain whole numbers." ); continue; } if (ticketNumber <= 0) { WriteLine( "The ticket number must be greater than zero." ); continue; } if (TicketNumberAlreadyExists(ticketNumber)) { WriteLine( "That ticket number has already been entered." ); continue; } ticketNumberIsValid = true; } return ticketNumber; } /************************************************************ * * Checks the list for a duplicate ticket number. * ************************************************************/ private static bool TicketNumberAlreadyExists(int ticketNumber) { foreach (SupportTicket ticket in ticketRecords) { if (ticket.TicketNumber == ticketNumber) { return true; } } return false; } /************************************************************ * * Requires a description of the reported technical problem. * ************************************************************/ private static string GetIssueDescription() { string issueDescription = ""; while (String.IsNullOrWhiteSpace(issueDescription)) { Write("Issue description: "); issueDescription = ReadLine(); if (String.IsNullOrWhiteSpace(issueDescription)) { WriteLine( "The issue description cannot be left blank." ); } } return issueDescription.Trim(); } /************************************************************ * * Requires a Low, Medium, High, or Critical priority. * ************************************************************/ private static string GetPriorityLevel() { while (true) { Write( "Priority [Low, Medium, High, Critical]: " ); string priorityLevel = ReadLine(); if (priorityLevel != null) { priorityLevel = priorityLevel.Trim().ToLower(); } switch (priorityLevel) { case "low": return "Low"; case "medium": return "Medium"; case "high": return "High"; case "critical": return "Critical"; default: WriteLine( "Enter Low, Medium, High, or Critical." ); break; } } } /************************************************************ * * Determines whether the ticket is resolved or still open. * ************************************************************/ private static bool GetResolutionStatus() { while (true) { Write("Was the ticket resolved? [Y/N]: "); string response = ReadLine(); if (response != null) { response = response.Trim().ToUpper(); } if (response == "Y") { return true; } if (response == "N") { return false; } WriteLine("Please enter Y for yes or N for no."); } } /************************************************************ * * Requires a valid positive number of resolution hours. * ************************************************************/ private static decimal GetResolutionHours() { decimal resolutionHours = 0.00M; while (true) { Write("Time required to resolve, in hours: "); string enteredValue = ReadLine(); if (decimal.TryParse( enteredValue, out resolutionHours ) && resolutionHours >= 0.00M) { return resolutionHours; } WriteLine( "Enter zero or a positive decimal number." ); } } /************************************************************ * * Asks whether another ticket should be entered. * ************************************************************/ private static bool AskToEnterAnotherTicket() { while (true) { Write("\nEnter another IT ticket? [Y/N]: "); string response = ReadLine(); if (response != null) { response = response.Trim().ToUpper(); } if (response == "Y") { return true; } if (response == "N") { return false; } WriteLine("Please enter Y for yes or N for no."); } } /************************************************************ * * Counts tickets matching the requested priority level. * ************************************************************/ private static int CountPriorityTickets(string priorityLevel) { int priorityCount = 0; foreach (SupportTicket ticket in ticketRecords) { if (ticket.PriorityLevel == priorityLevel) { priorityCount++; } } return priorityCount; } /************************************************************ * * Counts tickets that have been successfully resolved. * ************************************************************/ private static int CountResolvedTickets() { int resolvedCount = 0; foreach (SupportTicket ticket in ticketRecords) { if (ticket.WasResolved) { resolvedCount++; } } return resolvedCount; } /************************************************************ * * Calculates the average time for resolved tickets only. * ************************************************************/ private static decimal CalculateAverageResolutionTime() { decimal totalResolutionHours = 0.00M; int resolvedTicketCount = 0; foreach (SupportTicket ticket in ticketRecords) { if (ticket.WasResolved) { totalResolutionHours += ticket.ResolutionHours; resolvedTicketCount++; } } if (resolvedTicketCount == 0) { return 0.00M; } return totalResolutionHours / resolvedTicketCount; } /************************************************************ * * Locates the resolved ticket requiring the most time. * ************************************************************/ private static SupportTicket FindLongestResolvedTicket() { SupportTicket longestTicket = null; foreach (SupportTicket ticket in ticketRecords) { if (!ticket.WasResolved) { continue; } if (longestTicket == null || ticket.ResolutionHours > longestTicket.ResolutionHours) { longestTicket = ticket; } } return longestTicket; } /************************************************************ * * Shortens long descriptions for the formatted report. * ************************************************************/ private static string ShortenDescription( string issueDescription) { const int maximumLength = 32; if (issueDescription.Length <= maximumLength) { return issueDescription; } return issueDescription.Substring( 0, maximumLength - 3 ) + "..."; } /************************************************************ * * Displays all ticket entries and calculated statistics. * ************************************************************/ private static void DisplayTicketReport() { Clear(); int resolvedTickets = CountResolvedTickets(); int openTickets = ticketRecords.Count - resolvedTickets; decimal averageResolutionTime = CalculateAverageResolutionTime(); SupportTicket longestTicket = FindLongestResolvedTicket(); WriteLine("IT SUPPORT TICKET ACTIVITY REPORT"); WriteLine("================================="); WriteLine(); WriteLine( "{0,-10} {1,-34} {2,-10} {3,-10} {4,8}", "Ticket", "Issue", "Priority", "Status", "Hours" ); WriteLine(new string('-', 78)); foreach (SupportTicket ticket in ticketRecords) { string displayHours = "N/A"; if (ticket.WasResolved) { displayHours = ticket.ResolutionHours.ToString("F2"); } WriteLine( "{0,-10} {1,-34} {2,-10} {3,-10} {4,8}", ticket.TicketNumber, ShortenDescription(ticket.IssueDescription), ticket.PriorityLevel, ticket.GetStatusText(), displayHours ); } WriteLine(new string('-', 78)); WriteLine(); WriteLine( "Total ticket records: {0}", ticketRecords.Count ); WriteLine( "Resolved tickets: {0}", resolvedTickets ); WriteLine( "Open tickets: {0}", openTickets ); WriteLine( "Low-priority tickets: {0}", CountPriorityTickets("Low") ); WriteLine( "Medium-priority tickets: {0}", CountPriorityTickets("Medium") ); WriteLine( "High-priority tickets: {0}", CountPriorityTickets("High") ); WriteLine( "Critical-priority tickets: {0}", CountPriorityTickets("Critical") ); WriteLine( "Average resolution time: {0:F2} hours", averageResolutionTime ); if (longestTicket != null) { WriteLine(); WriteLine( "Longest resolved ticket: #{0}", longestTicket.TicketNumber ); WriteLine( "Issue: {0}", longestTicket.IssueDescription ); WriteLine( "Resolution time: {0:F2} hours", longestTicket.ResolutionHours ); } else { WriteLine(); WriteLine( "No resolved tickets were entered." ); } } } }