using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CarManagerV3 { /// /// Class Car represents a car with various attributes such as make, model, year, color, mileage, and price. /// public class Car { private int id; private string make; private string model; private int year; private string color; private int mileage; private decimal price; private int order; public int Id { get => id; set { if (value < 0) throw new ArgumentException("Id cannot be negative."); id = value; } } public string Make { get => make; set { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Make cannot be empty."); make = value; } } public string Model { get => model; set { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Model cannot be empty."); model = value; } } public int Year { get => year; set { if (value < 1886 || value > DateTime.Now.Year + 1) throw new ArgumentException("Year must be between 1886 and next year."); Console.WriteLine($"Updating year to {year}"); year = value; } } public string Color { get => color; set { if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Color cannot be empty."); color = value; } } public int Mileage { get => mileage; set { if (value < 0) throw new ArgumentException("Mileage cannot be negative."); mileage = value; } } public decimal Price { get => price; set { if (value < 0) throw new ArgumentException("Price cannot be negative."); price = value; } } public int Order { get => order; set => order = value; } //TODO: Make Id read-only CUID. Allows for better integrity, especially when merging. //TODO: Add buying price and automatic calculation of profit/loss with selling price suggestion. //TODO: Add Buying Date. //TODO: Add sold boolean and Sold Date. //TODO: Add "hidden" attribute for cars that are not for sale anymore but should be kept in the database for records. /// /// Initializes a new instance of the class. /// /// The unique identifier as an Integer. /// The make / manufacturer of the car. /// The model. /// The year the car was built. /// The color of the car. /// The current mileage on the car. /// The selling-price of the car. /// The order. public Car(int id, string make, string model, int year, string color, int mileage, decimal price, int order = 0) { // Sets the properties using the setters to ensure validation is applied. this.Id = id; this.Make = make; this.Model = model; this.Year = year; this.Color = color; this.Mileage = mileage; this.Price = price; this.Order = order; } /// /// Converts to string in a custom readable format. /// /// For Example: /// Skoda Fabia (2015) /// /// /// /// A that represents this instance. /// public override string ToString() { return $"{this.Make} {this.Model} ({this.Year})"; } /// /// Converts to default CSV savable string. /// /// public string ToCsvString() { return $"{this.Id};{this.Make};{this.Model};{this.Year};{this.Color};{this.Mileage};{this.Price}"; } //TODO: Add error handling for malformed CSV strings and detection for missing fields. //TODO: Add support for different CSV formats (e.g., different delimiters, quoted fields, etc.). //TODO: Add support for nil or optional fields. //TODO: Add detectin for invalid data / nonsensical values (e.g., negative mileage or year in the future). / Validate it actually is a car. /// /// Creates a instance from a CSV string in the default format. /// /// The CSV Line. /// /// A new instance. /// public static Car FromCsvString(string csv) { try { string[] parts = csv.Split(';'); Car temp = new Car(int.Parse(parts[0]), parts[1], parts[2], int.Parse(parts[3]), parts[4], int.Parse(parts[5]), decimal.Parse(parts[6])); if (temp.Year < 1886 || temp.Year > DateTime.Now.Year + 1) throw new Exception($"Invalid year: {temp.Year}"); if (temp.Mileage < 0) throw new Exception($"Mileage cannot be negative: {temp.Mileage}"); if (temp.Price < 0) throw new Exception($"Price cannot be negative: {temp.Price}"); return temp; } catch (Exception ex) { Console.Error.WriteLine($"Error parsing CSV Car string: {ex.Message}"); return null; } } /// /// Determines whether this is any different from the provided . /// /// The to check against /// /// true if the specified other is changed; otherwise, false. /// public bool IsChanged(Car other) { return this.Make != other.Make || this.Model != other.Model || this.Year != other.Year || this.Color != other.Color || this.Mileage != other.Mileage || this.Price != other.Price || this.Color != other.Color; } /// /// Clones this instance. /// /// An identical but seperate public Car Clone() { return new Car(this.Id, this.Make, this.Model, this.Year, this.Color, this.Mileage, this.Price); } } }