diff --git a/.gitignore b/.gitignore index 8e67ca8..d0595a7 100644 --- a/.gitignore +++ b/.gitignore @@ -401,13 +401,13 @@ FodyWeavers.xsd - +.vscode/ .vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -!.vscode/*.code-snippets +.vscode/settings.json +.vscode/tasks.json +.vscode/launch.json +.vscode/extensions.json +.vscode/*.code-snippets # Local History for Visual Studio Code .history/ diff --git a/Library.sln b/Library.sln new file mode 100644 index 0000000..e82fbbc --- /dev/null +++ b/Library.sln @@ -0,0 +1,42 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataLayer", "Library\DataLayer\DataLayer.csproj", "{37F35CAD-0E16-44DE-B1EC-B8806B87AF27}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Library\Tests\Tests.csproj", "{E482E32E-3CA7-46DD-83C9-B094E0AD8BA3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Library", "Library", "{B858A003-F5DD-4F95-99D9-5A7560A0B8CF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogicLayer", "Library\LogicLayer\LogicLayer.csproj", "{34D82E95-A0C6-4C12-8BB0-6836280E2491}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {37F35CAD-0E16-44DE-B1EC-B8806B87AF27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {37F35CAD-0E16-44DE-B1EC-B8806B87AF27}.Debug|Any CPU.Build.0 = Debug|Any CPU + {37F35CAD-0E16-44DE-B1EC-B8806B87AF27}.Release|Any CPU.ActiveCfg = Release|Any CPU + {37F35CAD-0E16-44DE-B1EC-B8806B87AF27}.Release|Any CPU.Build.0 = Release|Any CPU + {E482E32E-3CA7-46DD-83C9-B094E0AD8BA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E482E32E-3CA7-46DD-83C9-B094E0AD8BA3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E482E32E-3CA7-46DD-83C9-B094E0AD8BA3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E482E32E-3CA7-46DD-83C9-B094E0AD8BA3}.Release|Any CPU.Build.0 = Release|Any CPU + {34D82E95-A0C6-4C12-8BB0-6836280E2491}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34D82E95-A0C6-4C12-8BB0-6836280E2491}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34D82E95-A0C6-4C12-8BB0-6836280E2491}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34D82E95-A0C6-4C12-8BB0-6836280E2491}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B8DC2F37-8FC7-433C-BA78-56CAE077B47B} + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {34D82E95-A0C6-4C12-8BB0-6836280E2491} = {B858A003-F5DD-4F95-99D9-5A7560A0B8CF} + EndGlobalSection +EndGlobal diff --git a/Library/DataLayer/API/IBook.cs b/Library/DataLayer/API/IBook.cs new file mode 100644 index 0000000..fdfd9b4 --- /dev/null +++ b/Library/DataLayer/API/IBook.cs @@ -0,0 +1,10 @@ +namespace DataLayer.API +{ + public interface IBook : IProduct + { + string Author { get; set; } + string Publisher { get; set; } + int Pages { get; set; } + DateTime PublicationDate { get; set; } + } +} \ No newline at end of file diff --git a/Library/DataLayer/API/IDataContext.cs b/Library/DataLayer/API/IDataContext.cs new file mode 100644 index 0000000..29f8bcd --- /dev/null +++ b/Library/DataLayer/API/IDataContext.cs @@ -0,0 +1,13 @@ +namespace DataLayer.API +{ + public interface IDataContext + { + public List Users { get; set; } + + public List Products { get; set; } + + public List Events { get; set; } + + public List States { get; set; } + } +} \ No newline at end of file diff --git a/Library/DataLayer/API/IDataFiller.cs b/Library/DataLayer/API/IDataFiller.cs new file mode 100644 index 0000000..1f07318 --- /dev/null +++ b/Library/DataLayer/API/IDataFiller.cs @@ -0,0 +1,7 @@ +namespace DataLayer.API +{ + public interface IDataFiller + { + void Fill(IDataContext context); + } +} \ No newline at end of file diff --git a/Library/DataLayer/API/IDataRepository.cs b/Library/DataLayer/API/IDataRepository.cs new file mode 100644 index 0000000..6c6cb65 --- /dev/null +++ b/Library/DataLayer/API/IDataRepository.cs @@ -0,0 +1,48 @@ +using DataLayer.Implementations; + +namespace DataLayer.API +{ + public interface IDataRepository + { + static IDataRepository CreateDataRepository(IDataContext dataContext) + { + return new DataRepository(dataContext); + } + + #region User + void AddUser(IUser user); + IUser GetUser(string guid); + List GetAllUsers(); + void RemoveUser(string guid); + bool DoesUserExist(string guid); + void UpdateUser(IUser updateUser); + #endregion + + #region Product + void AddProduct(IProduct product); + IProduct GetProduct(string guid); + List GetAllProducts(); + IProduct GetProductByState(string stateGuid); + bool DoesProductExist(string guid); + + void RemoveProduct(string guid); + #endregion + + #region Event + void AddEvent(IEvent @event); + IEvent GetEvent(string guid); + List GetAllEvents(); + List GetEventsByUser(string userGuid); + List GetEventsByProduct(string productGuid); + List GetEventsByState(string stateGuid); + void RemoveEvent(string guid); + #endregion + + #region State + void AddState(IState state); + IState GetState(string guid); + List GetAllStates(); + void RemoveState(string guid); + #endregion + } +} \ No newline at end of file diff --git a/Library/DataLayer/API/IEvent.cs b/Library/DataLayer/API/IEvent.cs new file mode 100644 index 0000000..4bc8a34 --- /dev/null +++ b/Library/DataLayer/API/IEvent.cs @@ -0,0 +1,10 @@ +namespace DataLayer.API +{ + public interface IEvent + { + string Guid { get; } + IUser User { get; } + IState State { get; } + DateTime CreatedAt { get; } + } +} diff --git a/Library/DataLayer/API/IProduct.cs b/Library/DataLayer/API/IProduct.cs new file mode 100644 index 0000000..3e971ce --- /dev/null +++ b/Library/DataLayer/API/IProduct.cs @@ -0,0 +1,9 @@ +namespace DataLayer.API +{ + public interface IProduct + { + string Guid { get; } + string Name { get; set; } + double Price { get; set; } + } +} \ No newline at end of file diff --git a/Library/DataLayer/API/IState.cs b/Library/DataLayer/API/IState.cs new file mode 100644 index 0000000..eeecc5d --- /dev/null +++ b/Library/DataLayer/API/IState.cs @@ -0,0 +1,10 @@ +namespace DataLayer.API +{ + public interface IState + { + IProduct Product { get; set; } + int Quantity { get; set; } + DateTime LastUpdatedDate { get; } + string Guid { get; } + } +} diff --git a/Library/DataLayer/API/IUser.cs b/Library/DataLayer/API/IUser.cs new file mode 100644 index 0000000..5df25fe --- /dev/null +++ b/Library/DataLayer/API/IUser.cs @@ -0,0 +1,16 @@ +namespace DataLayer.API +{ + public interface IUser + { + // guid, because is more commonly used in contexts of the Microsoft ecosystem + string Guid { get; } + string FirstName { get; set; } + string LastName { get; set; } + string Email { get; set; } + double Balance { get; set; } + // stick to E.164 standard? + int PhoneNumber { get; set; } + // string Role { get; set; } + Dictionary ProductsDic { get; set; } + } +} \ No newline at end of file diff --git a/Task_0/DistanceCalculator/DistanceCalculator.csproj b/Library/DataLayer/DataLayer.csproj similarity index 81% rename from Task_0/DistanceCalculator/DistanceCalculator.csproj rename to Library/DataLayer/DataLayer.csproj index 2150e37..e1b91f9 100644 --- a/Task_0/DistanceCalculator/DistanceCalculator.csproj +++ b/Library/DataLayer/DataLayer.csproj @@ -1,10 +1,9 @@  - Exe net8.0 enable enable - + \ No newline at end of file diff --git a/Library/DataLayer/Implementations/Book.cs b/Library/DataLayer/Implementations/Book.cs new file mode 100644 index 0000000..3b30b73 --- /dev/null +++ b/Library/DataLayer/Implementations/Book.cs @@ -0,0 +1,25 @@ +using DataLayer.API; + +namespace DataLayer.Implementations +{ + public class Book : IBook + { + public Book(string name, double price, string author, string publisher, int pages, DateTime publicationDate) + { + Guid = System.Guid.NewGuid().ToString(); + Name = name; + Price = price; + Author = author; + Publisher = publisher; + Pages = pages; + PublicationDate = publicationDate; + } + public string Guid { get; } + public string Name { get; set; } + public double Price { get; set; } + public string Author { get; set; } + public string Publisher { get; set; } + public int Pages { get; set; } + public DateTime PublicationDate { get; set; } + } +} \ No newline at end of file diff --git a/Library/DataLayer/Implementations/DataContex.cs b/Library/DataLayer/Implementations/DataContex.cs new file mode 100644 index 0000000..2885775 --- /dev/null +++ b/Library/DataLayer/Implementations/DataContex.cs @@ -0,0 +1,21 @@ +using DataLayer.API; + +namespace DataLayer.Implementations +{ + public class DataContext : IDataContext + { + public List Users { get; set; } + public List Products { get; set; } + public List Events { get; set; } + public List States { get; set; } + + public DataContext() + { + Users = new List(); + Products = new List(); + Events = new List(); + States = new List(); + } + + } +} \ No newline at end of file diff --git a/Library/DataLayer/Implementations/DataFillers/PresetFiller.cs b/Library/DataLayer/Implementations/DataFillers/PresetFiller.cs new file mode 100644 index 0000000..be5a032 --- /dev/null +++ b/Library/DataLayer/Implementations/DataFillers/PresetFiller.cs @@ -0,0 +1,37 @@ +using DataLayer.API; +using DataLayer.Implementations.Events; + +namespace DataLayer.Implementations +{ + public class PresetFiller : IDataFiller + { + public void Fill(IDataContext context) + { + context.Users.Add(new User("John", "Doe", "johndoe@email", 100, 123456789, null)); + context.Users.Add(new User("Jane", "Doe", "janedoe@email", 200, 111111111, null)); + context.Users.Add(new User("Alice", "Smith", "alicesmith@email", 300, 121212121, null)); + context.Users.Add(new User("Bob", "Smith", "bobsmith@email", 400, 987654321, null)); + context.Users.Add(new User("Charlie", "Brown", "charliebrown@email", 500, 999999999, null)); + + context.Products.Add(new Book("Old Man and the Sea", 10, "Ernest Hemingway", "Charles Sons", 300, new DateTime(1952, 1, 1))); + context.Products.Add(new Book("The Great Gatsby", 20, "F. Scott Fitzgerald", "Charles Sons", 400, new DateTime(1925, 1, 1))); + context.Products.Add(new Book("To Kill a Mockingbird", 30, "Harper Lee", "Charles Sons", 500, new DateTime(1960, 1, 1))); + context.Products.Add(new Book("1984", 40, "George Orwell", "Charles Sons", 600, new DateTime(1949, 1, 1))); + context.Products.Add(new Book("Brave New World", 50, "Aldous Huxley", "Charles Sons", 700, new DateTime(1932, 1, 1))); + + context.States.Add(new State(context.Products[0], 5)); + context.States.Add(new State(context.Products[1], 5)); + context.States.Add(new State(context.Products[2], 5)); + context.States.Add(new State(context.Products[3], 5)); + context.States.Add(new State(context.Products[4], 5)); + + context.Events.Add(new Borrow(context.Users[0], context.States[0])); + context.Events.Add(new Borrow(context.Users[1], context.States[1])); + context.Events.Add(new Borrow(context.Users[3], context.States[3])); + context.Events.Add(new Return(context.Users[0], context.States[0])); + context.Events.Add(new Return(context.Users[1], context.States[1])); + context.Events.Add(new Return(context.Users[3], context.States[3])); + context.Events.Add(new Delivery(context.Users[4], context.States[4], 10)); + } + } +} \ No newline at end of file diff --git a/Library/DataLayer/Implementations/DataFillers/RandomFiller.cs b/Library/DataLayer/Implementations/DataFillers/RandomFiller.cs new file mode 100644 index 0000000..922f2c7 --- /dev/null +++ b/Library/DataLayer/Implementations/DataFillers/RandomFiller.cs @@ -0,0 +1,158 @@ +using System; +using DataLayer.API; +using DataLayer.Implementations.Events; + +namespace DataLayer.Implementations +{ + public class RandomFiller : IDataFiller + { + private Random random = new Random(); + public void Fill(IDataContext context) + { + int usersCount = random.Next(5, 11); + for (int i = 0; i < usersCount; i++) + { + context.Users.Add(new User( + GetRandomFirstName(), + GetRandomLastName(), + $"{GetRandomFirstName().ToLower()}{GetRandomLastName().ToLower()}@email.com", + random.Next(100, 1000), + GetRandomPhoneNumber(), + null + )); + } + + int productsCount = random.Next(5, 11); + for (int i = 0; i < productsCount; i++) + { + context.Products.Add(new Book( + GetRandomTitle(), + random.Next(10, 100), + GetRandomAuthor(), + GetRandomPublisher(), + random.Next(50, 1000), + GetRandomDate() + )); + } + + int statesCount = context.Products.Count; + for (int i = 0; i < statesCount; i++) + { + context.States.Add(new State( + context.Products[i], + random.Next(1, 10) + )); + } + + int eventsCount = random.Next(5, 11); + int borrowsCount = 0; + List usersBorrowing = new List(); + List statesBorrowed = new List(); + for (int i = 0; i < eventsCount; i++) + { + int userIndex = random.Next(context.Users.Count); + int stateIndex = random.Next(context.States.Count); + int randomEvent = random.Next(3); + if (randomEvent == 0) + { + context.Events.Add(new Borrow(context.Users[userIndex], context.States[stateIndex])); + borrowsCount++; + usersBorrowing.Add(context.Users[userIndex]); + statesBorrowed.Add(context.States[stateIndex]); + } + else if (randomEvent == 1 && borrowsCount > 0) + { + context.Events.Add(new Return(usersBorrowing[borrowsCount-1], statesBorrowed[borrowsCount-1])); + borrowsCount--; + usersBorrowing.RemoveAt(borrowsCount); + statesBorrowed.RemoveAt(borrowsCount); + } + else if (randomEvent == 1 && borrowsCount == 0) + { + i--; + } + else if (randomEvent == 2) + { + context.Events.Add(new Delivery(context.Users[userIndex], context.States[stateIndex], random.Next(1, 10))); + } + } + } + private string GetRandomFirstName() + { + string[] firstNames = { + "John", "Jane", "Alice", "Bob", "Charlie", + "Michael", "Emily", "David", "Sarah", "Daniel", + "Matthew", "Jessica", "Andrew", "Jennifer", "James", + "Linda", "William", "Karen", "Joseph", "Maria", + "Robert", "Susan", "Christopher", "Nancy", "Daniel", + "Karen", "Thomas", "Lisa", "Brian", "Margaret", + "Steven", "Betty", "Timothy", "Dorothy", "Kevin", + "Sandra", "Richard", "Ashley", "Mark", "Kimberly", + "Jeffrey", "Donna", "Scott", "Emily", "Charles", + "Carol", "Paul", "Michelle", "Anthony", "Laura" + }; + return firstNames[random.Next(firstNames.Length)]; + } + private string GetRandomLastName() + { + string[] lastNames = { + "Smith", "Johnson", "Williams", "Brown", "Jones", + "Garcia", "Miller", "Davis", "Rodriguez", "Martinez", + "Hernandez", "Lopez", "Gonzalez", "Wilson", "Anderson", + "Thomas", "Taylor", "Moore", "Jackson", "Martin", + "Lee", "Perez", "Thompson", "White", "Harris", + "Sanchez", "Clark", "Ramirez", "Lewis", "Robinson", + "Walker", "Young", "Allen", "King", "Wright", + "Scott", "Torres", "Nguyen", "Hill", "Flores", + "Green", "Adams", "Nelson", "Baker", "Hall", + "Rivera", "Campbell", "Mitchell", "Carter", "Roberts" + }; + return lastNames[random.Next(lastNames.Length)]; + } + private int GetRandomPhoneNumber() + { + return random.Next(100000000, 1000000000); // 9-digit random number + } + private string GetRandomTitle() + { + string[] titles = { + "The Catcher in the Rye", "To Kill a Mockingbird", "1984", "The Great Gatsby", "Pride and Prejudice", + "Harry Potter and the Philosopher's Stone", "The Hobbit", "The Lord of the Rings", "The Hunger Games", "The Da Vinci Code", + "The Chronicles of Narnia", "Twilight", "The Alchemist", "The Fault in Our Stars", "The Kite Runner", + "A Song of Ice and Fire", "The Hitchhiker's Guide to the Galaxy", "The Shining", "The Girl with the Dragon Tattoo", "Gone Girl", + "Brave New World", "Animal Farm", "The Adventures of Huckleberry Finn", "Moby-Dick", "Frankenstein", + "Dracula", "Alice's Adventures in Wonderland", "The War of the Worlds", "The Picture of Dorian Gray", "The Bell Jar" + }; + return titles[random.Next(titles.Length)]; + } + private string GetRandomAuthor() + { + string[] authors = { + "J.D. Salinger", "Harper Lee", "George Orwell", "F. Scott Fitzgerald", "Jane Austen", + "J.K. Rowling", "J.R.R. Tolkien", "George R.R. Martin", "Suzanne Collins", "Dan Brown", + "C.S. Lewis", "Stephenie Meyer", "Paulo Coelho", "John Green", "Khaled Hosseini", + "George R.R. Martin", "Douglas Adams", "Stephen King", "Stieg Larsson", "Gillian Flynn", + "Aldous Huxley", "George Orwell", "Mark Twain", "Herman Melville", "Mary Shelley", + "Bram Stoker", "Lewis Carroll", "H.G. Wells", "Oscar Wilde", "Sylvia Plath" + }; + return authors[random.Next(authors.Length)]; + } + private string GetRandomPublisher() + { + string[] publishers = { + "Random House", "Penguin Books", "HarperCollins", "Simon & Schuster", "Hachette Livre", + "Macmillan Publishers", "Scholastic Corporation", "Pearson Education", "Bloomsbury Publishing", "Oxford University Press", + "Cambridge University Press", "Wiley", "Springer Nature", "McGraw-Hill Education", "Cengage", + "Houghton Mifflin Harcourt", "Elsevier", "Taylor & Francis", "Harvard University Press", "MIT Press" + }; + return publishers[random.Next(publishers.Length)]; + } + private DateTime GetRandomDate() + { + // Random date between 1900 and now + DateTime start = new DateTime(1900, 1, 1); + int range = (DateTime.Today - start).Days; + return start.AddDays(random.Next(range)); + } + } +} \ No newline at end of file diff --git a/Library/DataLayer/Implementations/DataRepository.cs b/Library/DataLayer/Implementations/DataRepository.cs new file mode 100644 index 0000000..b6744fe --- /dev/null +++ b/Library/DataLayer/Implementations/DataRepository.cs @@ -0,0 +1,155 @@ +using DataLayer.API; + +namespace DataLayer.Implementations +{ + public class DataRepository : IDataRepository + { + private IDataContext _dataContext; + + // Init the data context + public DataRepository(IDataContext dataContext) + { + _dataContext = dataContext; + } + + #region User + public void AddUser(IUser user) + { + _dataContext.Users.Add(user); + } + public IUser GetUser(string guid) + { + IUser? user = _dataContext.Users.FirstOrDefault(u => u.Guid == guid) ?? throw new Exception("User does not exist"); + + return user; + } + public List GetAllUsers() + { + return _dataContext.Users; + } + public void RemoveUser(string guid) + { + IUser user = _dataContext.Users.FirstOrDefault(user => user.Guid == guid) ?? throw new Exception("User does not exist"); + + _dataContext.Users.Remove(user); + } + public bool DoesUserExist(string guid) + { + return _dataContext.Users.Exists(e => e.Guid == guid); + } + public void UpdateUser(IUser updateUser) + { + IUser? userToBeUpdated = _dataContext.Users.FirstOrDefault(u => u.Guid == updateUser.Guid); + + if (userToBeUpdated == null) + { + throw new Exception("Cannot update user that does not exist"); + } + + userToBeUpdated = updateUser; + } + + #endregion + + #region Product + public void AddProduct(IProduct product) + { + _dataContext.Products.Add(product); + } + public IProduct GetProduct(string guid) + { + IProduct product = _dataContext.Products.FirstOrDefault(product => product.Guid == guid) ?? throw new Exception("Product does not exist"); + + return product; + } + public List GetAllProducts() + { + return _dataContext.Products; + } + public IProduct GetProductByState(string stateGuid) + { + IProduct? product = _dataContext.States.FirstOrDefault(state => state.Guid == stateGuid)?.Product; + if (product == null) + { + throw new Exception("Product does not exist"); + } + + return product; + } + public bool DoesProductExist(string guid) + { + return _dataContext.Products.Exists(e => e.Guid == guid); + } + public void RemoveProduct(string guid) + { + IProduct product = _dataContext.Products.FirstOrDefault(product => product.Guid == guid) ?? throw new Exception("Product does not exist"); + + _dataContext.Products.Remove(product); + } + #endregion + + #region Event + public void AddEvent(IEvent @event) + { + _dataContext.Events.Add(@event); + } + public IEvent GetEvent(string guid) + { + IEvent @event = _dataContext.Events.FirstOrDefault(@event => @event.Guid == guid) ?? throw new Exception("Event does not exist"); + + return @event; + } + public List GetAllEvents() + { + return _dataContext.Events; + } + public List GetEventsByUser(string userGuid) + { + List events = _dataContext.Events.Where(@event => @event.User.Guid == userGuid).ToList(); + + return events; + } + public List GetEventsByProduct(string productGuid) + { + List events = _dataContext.Events.Where(@event => @event.State.Product.Guid == productGuid).ToList(); + + return events; + } + public List GetEventsByState(string stateGuid) + { + List events = _dataContext.Events.Where(@event => @event.State.Guid == stateGuid).ToList(); + + return events; + } + public void RemoveEvent(string guid) + { + IEvent @event = _dataContext.Events.FirstOrDefault(@event => @event.Guid == guid) ?? throw new Exception("Event does not exist"); + + _dataContext.Events.Remove(@event); + } + #endregion + + #region State + public void AddState(IState state) + { + _dataContext.States.Add(state); + } + public List GetAllStates() + { + return _dataContext.States; + } + public IState GetState(string guid) + { + IState state = _dataContext.States.FirstOrDefault(state => state.Guid == guid) ?? throw new Exception("State does not exist"); + + return state; + } + public void RemoveState(string guid) + { + IState state = _dataContext.States.FirstOrDefault(state => state.Guid == guid) ?? throw new Exception("State does not exist"); + + _dataContext.States.Remove(state); + } + #endregion + } +} \ No newline at end of file diff --git a/Library/DataLayer/Implementations/Events/Borrow.cs b/Library/DataLayer/Implementations/Events/Borrow.cs new file mode 100644 index 0000000..942acaa --- /dev/null +++ b/Library/DataLayer/Implementations/Events/Borrow.cs @@ -0,0 +1,36 @@ +using DataLayer.API; + +namespace DataLayer.Implementations.Events +{ + public class Borrow : IEvent + { + public Borrow(IUser user, IState state, string? guid = null) + { + Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; + User = user; + State = state; + CreatedAt = DateTime.Now; + + // Check if the product is available + if (state.Quantity <= 0) + { + throw new Exception("Product is not available"); + } + + // Should we allow borrowing the product if the user already has it? + + // Check if user has enough credits to borrow the product + if (user.Balance < state.Product.Price) + { + throw new Exception("User balance is not enough to borrow the product"); + } + + user.ProductsDic.Add(state.Product.Guid, state.Product); + state.Quantity--; + } + public string Guid { get; } + public IUser User { get; } + public IState State { get; } + public DateTime CreatedAt { get; } + } +} \ No newline at end of file diff --git a/Library/DataLayer/Implementations/Events/Delivery.cs b/Library/DataLayer/Implementations/Events/Delivery.cs new file mode 100644 index 0000000..f555592 --- /dev/null +++ b/Library/DataLayer/Implementations/Events/Delivery.cs @@ -0,0 +1,27 @@ +using DataLayer.API; + +namespace DataLayer.Implementations.Events +{ + public class Delivery : IEvent + { + public Delivery(IUser user, IState state, int amount, string? guid = null) + { + Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; + User = user; + State = state; + CreatedAt = DateTime.Now; + + if(amount <= 0) + { + throw new Exception("Amount must be greater than 0"); + } + + state.Quantity += amount; + } + + public string Guid { get; } + public IUser User { get; } + public IState State { get; } + public DateTime CreatedAt { get; } + } +} diff --git a/Library/DataLayer/Implementations/Events/Return.cs b/Library/DataLayer/Implementations/Events/Return.cs new file mode 100644 index 0000000..fde3417 --- /dev/null +++ b/Library/DataLayer/Implementations/Events/Return.cs @@ -0,0 +1,28 @@ +using DataLayer.API; + +namespace DataLayer.Implementations.Events +{ + public class Return : IEvent + { + public Return(IUser user, IState state, string? guid = null) + { + Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; + User = user; + State = state; + CreatedAt = DateTime.Now; + + // Check if the product is in the user's inventory because we can't return a product that we don't have + if (!user.ProductsDic.ContainsKey(state.Product.Guid)) + { + throw new Exception("Product not found in user's inventory"); + } + + user.ProductsDic.Remove(state.Product.Guid); + state.Quantity++; + } + public string Guid { get; } + public IUser User { get; } + public IState State { get; } + public DateTime CreatedAt { get; } + } +} \ No newline at end of file diff --git a/Library/DataLayer/Implementations/State.cs b/Library/DataLayer/Implementations/State.cs new file mode 100644 index 0000000..8240a04 --- /dev/null +++ b/Library/DataLayer/Implementations/State.cs @@ -0,0 +1,30 @@ +using DataLayer.API; + +namespace DataLayer.Implementations +{ + public class State : IState + { + private int _quantity; + private DateTime _lastUpdatedDate; + public State(IProduct product, int quantity = 0, string? guid = null) + { + Guid = string.IsNullOrEmpty(guid) ? System.Guid.NewGuid().ToString() : guid; + Product = product; + Quantity = quantity; + _lastUpdatedDate = DateTime.Now; + } + public IProduct Product { get; set; } + public int Quantity + { + get => _quantity; + set + { + _quantity = value; + _lastUpdatedDate = DateTime.Now; + } + } + public DateTime LastUpdatedDate { get => _lastUpdatedDate; } + public double Price { get; set; } + public string Guid { get; } + } +} \ No newline at end of file diff --git a/Library/DataLayer/Implementations/User.cs b/Library/DataLayer/Implementations/User.cs new file mode 100644 index 0000000..916033f --- /dev/null +++ b/Library/DataLayer/Implementations/User.cs @@ -0,0 +1,32 @@ +using DataLayer.API; + +namespace DataLayer.Implementations +{ + public class User : IUser + { + public User(string firstName, string lastName, string email, double balance, int phoneNumber, Dictionary? productsDic) + { + Guid = System.Guid.NewGuid().ToString(); + FirstName = firstName; + LastName = lastName; + Email = email; + Balance = balance; + PhoneNumber = phoneNumber; + ProductsDic = productsDic ?? new Dictionary(); + } + + public string Guid { get; } + + public string FirstName { get; set; } + + public string LastName { get; set; } + + public string Email { get; set; } + + public double Balance { get; set; } + + public int PhoneNumber { get; set; } + + public Dictionary ProductsDic { get; set; } + } +} \ No newline at end of file diff --git a/Library/LogicLayer/API/IDataService.cs b/Library/LogicLayer/API/IDataService.cs new file mode 100644 index 0000000..9fee60a --- /dev/null +++ b/Library/LogicLayer/API/IDataService.cs @@ -0,0 +1,19 @@ +using DataLayer.API; +using DataLayer.Implementations.Events; + +namespace LogicLayer.API +{ + public interface IDataService + { + void BorrowProduct(IUser user, IState state); + void ReturnProduct(IUser user, IState state); + void DeliverProduct(IUser user, IState state, int amount); + + // Maybe add in the future + // void RegisterUser(string firstName, string lastName, string email, double balance, int phoneNumber); + // void RegisterProduct + // void UpdateUserBalance + // void UpdateProductPrice + // bool CheckProductAvailability + } +} \ No newline at end of file diff --git a/Library/LogicLayer/Implementations/DataService.cs b/Library/LogicLayer/Implementations/DataService.cs new file mode 100644 index 0000000..d3bea51 --- /dev/null +++ b/Library/LogicLayer/Implementations/DataService.cs @@ -0,0 +1,83 @@ +using DataLayer.API; +using DataLayer.Implementations.Events; +using LogicLayer.API; + +namespace LogicLayer.Implementations +{ + public class DataService : IDataService + { + private IDataRepository _dataRepository; + public DataService(IDataRepository dataRepository) + { + _dataRepository = dataRepository; + } + public void DeliverProduct(IUser user, IState state, int amount) + { + + // Check if such product exists + if (!_dataRepository.DoesProductExist(state.Product.Guid)) + { + throw new Exception("Product not found"); + } + + if (!_dataRepository.DoesUserExist(user.Guid)) + { + throw new Exception("User not found"); + } + + try + { + _dataRepository.AddEvent(new Delivery(user, state, amount)); + } + catch (Exception e) + { + throw new Exception("Unable to perform deliver: " + e.Message, e); ; + } + + } + + public void BorrowProduct(IUser user, IState state) + { + // Check if such product exists + if (!_dataRepository.DoesProductExist(state.Product.Guid)) + { + throw new Exception("Product not found"); + } + if (!_dataRepository.DoesUserExist(user.Guid)) + { + throw new Exception("User not found"); + } + + try + { + _dataRepository.AddEvent(new Borrow(user, state)); + } + catch (Exception e) + { + throw new Exception("Unable to perform borrow: " + e.Message, e); ; + } + } + public void ReturnProduct(IUser user, IState state) + { + // Check if such product exists + if (!_dataRepository.DoesProductExist(state.Product.Guid)) + { + throw new Exception("Product not found"); + } + if (!_dataRepository.DoesUserExist(user.Guid)) + { + throw new Exception("User not found"); + } + + try + { + _dataRepository.AddEvent(new Return(user, state)); + } + catch (Exception e) + { + throw new Exception("Unable to perform return: " + e.Message, e); ; + } + } + + } +} \ No newline at end of file diff --git a/Library/LogicLayer/LogicLayer.csproj b/Library/LogicLayer/LogicLayer.csproj new file mode 100644 index 0000000..987cdc2 --- /dev/null +++ b/Library/LogicLayer/LogicLayer.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/Library/LogicLayer/Program.cs b/Library/LogicLayer/Program.cs new file mode 100644 index 0000000..3751555 --- /dev/null +++ b/Library/LogicLayer/Program.cs @@ -0,0 +1,2 @@ +// See https://aka.ms/new-console-template for more information +Console.WriteLine("Hello, World!"); diff --git a/Library/Tests/DataLayerTests.cs b/Library/Tests/DataLayerTests.cs new file mode 100644 index 0000000..4932c78 --- /dev/null +++ b/Library/Tests/DataLayerTests.cs @@ -0,0 +1,201 @@ +using DataLayer.Implementations; +using DataLayer.Implementations.Events; +using DataLayer.API; + +namespace Tests; + +[TestClass] +public class DataLayerTests +{ + [TestMethod] + public void UserTests() + { + const string firstName = "John"; + const string lastName = "Doe"; + const string email = "Doe"; + const double balance = 100.0; + const int phoneNumber = 1234567890; + + IUser user = new User(firstName, lastName, email, balance, phoneNumber, null); + + Assert.AreEqual(firstName, user.FirstName); + Assert.AreEqual(lastName, user.LastName); + Assert.AreEqual(email, user.Email); + Assert.AreEqual(balance, user.Balance); + Assert.AreEqual(phoneNumber, user.PhoneNumber); + Assert.IsNotNull(user.Guid); + + Book book1 = new Book("Book1", 10.0, "Author1", "Publisher1", 100, new DateTime(2022, 1, 1)); + Book book2 = new Book("Book2", 20.0, "Author2", "Publisher2", 200, new DateTime(2022, 2, 2)); + + Dictionary BooksCollection = new Dictionary + { + { book1.Guid, book1 }, + { book2.Guid, book2 } + }; + + user.ProductsDic = BooksCollection; + + Assert.AreEqual(book1, user.ProductsDic[book1.Guid]); + Assert.AreEqual(book2, user.ProductsDic[book2.Guid]); + + IDataRepository dataRepository = IDataRepository.CreateDataRepository(new DataContext()); + + dataRepository.AddUser(user); + + Assert.IsTrue(dataRepository.GetAllUsers().Contains(user)); + + Assert.ThrowsException(() => dataRepository.GetUser("For sure not even a valid guid")); + + Assert.AreEqual(user, dataRepository.GetUser(user.Guid)); + + Assert.IsTrue(dataRepository.DoesUserExist(user.Guid)); + Assert.IsFalse(dataRepository.DoesUserExist("For sure not even a valid guid")); + + user.FirstName = "New Name is Jane"; + + dataRepository.UpdateUser(user); + user = dataRepository.GetUser(user.Guid); + + Assert.AreEqual("New Name is Jane", user.FirstName); + + dataRepository.RemoveUser(user.Guid); + Assert.AreEqual(0, dataRepository.GetAllUsers().Count); + + } + + [TestMethod] + public void BookTests() + { + const string name = "Sample Book"; + const string author = "John Doe"; + const string publisher = "Publisher X"; + const double price = 29.99; + const int pages = 299; + DateTime publicationDate = new DateTime(2022, 1, 1); + + IBook book = new Book(name, price, author, publisher, pages, publicationDate); + + Assert.AreEqual(name, book.Name); + Assert.AreEqual(author, book.Author); + Assert.AreEqual(publisher, book.Publisher); + Assert.AreEqual(price, book.Price); + Assert.AreEqual(pages, book.Pages); + Assert.AreEqual(publicationDate, book.PublicationDate); + + + Book book1 = new Book("Book1", 10.0, "Author1", "Publisher1", 100, new DateTime(2022, 1, 1)); + + IDataRepository dataRepository = IDataRepository.CreateDataRepository(new DataContext()); + + dataRepository.AddProduct(book); + + Assert.IsTrue(dataRepository.GetAllProducts().Contains(book)); + + Assert.ThrowsException(() => dataRepository.GetProduct("For sure not even a valid guid")); + } + + [TestMethod] + public void StateTests() + { + IProduct bookProduct = new Book("Buszujący w Zbożu", 10.0, " J.D. Salinger", "Albatros", 100, new DateTime(1951, 7, 16)); + + const int amountOfBooks = 10; + double wholeStockPrice = bookProduct.Price * amountOfBooks; + + IState bookProductState = new State(bookProduct, amountOfBooks); + + Assert.AreEqual(bookProduct, bookProductState.Product); + Assert.AreEqual(amountOfBooks, bookProductState.Quantity); + Assert.IsTrue((DateTime.Now - bookProductState.LastUpdatedDate).TotalSeconds < 1); + Assert.AreEqual(wholeStockPrice, bookProductState.Product.Price * bookProductState.Quantity); + } + + [TestMethod] + public void BorrowEventTests() + { + // TODO: Implement BorrowEventTests + + } + + [TestMethod] + public void ReturnEventTests() + { + // TODO: Implement ReturnEventTests + } + + [TestMethod] + public void DeliveryEventTests() + { + // TODO: Implement DeliveryEventTests + } + + [TestMethod] + public void DataContextTests() + { + DataContext dataContext = new DataContext(); + + Assert.IsNotNull(dataContext.Users); + Assert.IsNotNull(dataContext.Products); + Assert.IsNotNull(dataContext.States); + Assert.IsNotNull(dataContext.Events); + } + + [TestMethod] + public void DataRepositoryTests() + { + IDataRepository dataRepository = IDataRepository.CreateDataRepository(new DataContext()); + + IUser user = new User("John", "Doe", "Doe", 100.0, 1234567890, null); + IProduct product = new Book("Book1", 10.0, "Author1", "Publisher1", 100, new DateTime(2022, 1, 1)); + IState state = new State(product, 10, "1234567890"); + + dataRepository.AddUser(user); + dataRepository.AddProduct(product); + dataRepository.AddState(state); + + Assert.IsTrue(dataRepository.GetAllUsers().Contains(user)); + Assert.IsTrue(dataRepository.GetAllProducts().Contains(product)); + Assert.IsTrue(dataRepository.GetAllStates().Contains(state)); + + Assert.AreEqual(user, dataRepository.GetUser(user.Guid)); + Assert.AreEqual(product, dataRepository.GetProduct(product.Guid)); + Assert.AreEqual(state, dataRepository.GetState(state.Guid)); + + Assert.ThrowsException(() => dataRepository.GetUser("For sure not even a valid guid")); + Assert.ThrowsException(() => dataRepository.GetProduct("For sure not even a valid guid")); + Assert.ThrowsException(() => dataRepository.GetState("For sure not even a valid guid")); + + dataRepository.RemoveUser(user.Guid); + dataRepository.RemoveProduct(product.Guid); + dataRepository.RemoveState(state.Guid); + + Assert.IsFalse(dataRepository.GetAllUsers().Contains(user)); + Assert.IsFalse(dataRepository.GetAllProducts().Contains(product)); + Assert.IsFalse(dataRepository.GetAllStates().Contains(state)); + } + + [TestMethod] + public void DataFillerTests() + { + IDataContext dataContext = new DataContext(); + IDataFiller dataFiller = new PresetFiller(); + + dataFiller.Fill(dataContext); + + Assert.AreEqual(5, dataContext.Users.Count); + Assert.AreEqual(5, dataContext.Products.Count); + Assert.AreEqual(5, dataContext.States.Count); + Assert.AreEqual(7, dataContext.Events.Count); + + dataContext = new DataContext(); + dataFiller = new RandomFiller(); + + dataFiller.Fill(dataContext); + + Assert.IsTrue(dataContext.Users.Count >= 5 && dataContext.Users.Count <= 11); + Assert.IsTrue(dataContext.Products.Count >= 5 && dataContext.Products.Count <= 11); + Assert.AreEqual(dataContext.Products.Count, dataContext.States.Count); + Assert.IsTrue(dataContext.Events.Count >= 5 && dataContext.Events.Count <= 11); + } +} diff --git a/Library/Tests/LogicLayerTests.cs b/Library/Tests/LogicLayerTests.cs new file mode 100644 index 0000000..4bc313f --- /dev/null +++ b/Library/Tests/LogicLayerTests.cs @@ -0,0 +1,93 @@ +using DataLayer.Implementations; +using DataLayer.API; +using LogicLayer.Implementations; +using LogicLayer.API; + +namespace Tests; + +[TestClass] +public class LogicLayerTests +{ + [TestMethod] + public void TestDeliverProduct_Success() + { + // Arrange + IDataRepository dataRepository = IDataRepository.CreateDataRepository(new DataContext()); + + var testUser1 = new User("User 1", "1", "1@gmail.com", 1000, 1234567890, null); + + const int amountOfBooksOnStart = 5; + IProduct bookProduct1 = new Book("Buszujący w Zbożu", 10.0, " J.D. Salinger", "Albatros", 258, new DateTime(1951, 7, 16)); + + var stateOfBookProduct1 = new State(bookProduct1, amountOfBooksOnStart); + + dataRepository.AddUser(testUser1); + dataRepository.AddProduct(bookProduct1); + dataRepository.AddState(stateOfBookProduct1); + + IDataService dataService = new DataService(dataRepository); + + // Act + const int amountOfBooksToDeliver = 5; + dataService.DeliverProduct(testUser1, stateOfBookProduct1, amountOfBooksToDeliver); + + // Assert + Assert.AreEqual(amountOfBooksOnStart + amountOfBooksToDeliver, stateOfBookProduct1.Quantity); + } + + [TestMethod] + public void TestBorrowProduct_Success() + { + // Arrange + IDataRepository dataRepository = IDataRepository.CreateDataRepository(new DataContext()); + + var testUser1 = new User("User 1", "1", "1@gmail.com", 1000, 1234567890, null); + + const int amountOfBooksOnStart = 5; + IProduct bookProduct1 = new Book("Buszujący w Zbożu", 10.0, " J.D. Salinger", "Albatros", 258, new DateTime(1951, 7, 16)); + + var stateOfBookProduct1 = new State(bookProduct1, amountOfBooksOnStart); + + dataRepository.AddUser(testUser1); + dataRepository.AddProduct(bookProduct1); + dataRepository.AddState(stateOfBookProduct1); + + IDataService dataService = new DataService(dataRepository); + + // Act + dataService.BorrowProduct(testUser1, stateOfBookProduct1); + + // Assert + Assert.IsTrue(testUser1.ProductsDic.ContainsKey(bookProduct1.Guid)); + Assert.AreEqual(amountOfBooksOnStart - 1, stateOfBookProduct1.Quantity); + } + + [TestMethod] + public void TestReturnProduct_Success() + { + // Arrange + IDataRepository dataRepository = IDataRepository.CreateDataRepository(new DataContext()); + + var testUser1 = new User("User 1", "1", "1@gmail.com", 1000, 1234567890, null); + + const int amountOfBooksOnStart = 5; + IProduct bookProduct1 = new Book("Buszujący w Zbożu", 10.0, " J.D. Salinger", "Albatros", 258, new DateTime(1951, 7, 16)); + + var stateOfBookProduct1 = new State(bookProduct1, amountOfBooksOnStart); + + dataRepository.AddUser(testUser1); + dataRepository.AddProduct(bookProduct1); + dataRepository.AddState(stateOfBookProduct1); + + IDataService dataService = new DataService(dataRepository); + + dataService.BorrowProduct(testUser1, stateOfBookProduct1); + + // Act + dataService.ReturnProduct(testUser1, stateOfBookProduct1); + + // Assert + Assert.IsFalse(testUser1.ProductsDic.ContainsKey(bookProduct1.Guid)); + Assert.AreEqual(amountOfBooksOnStart, stateOfBookProduct1.Quantity); + } +} \ No newline at end of file diff --git a/Task_0/DistanceCalculatorTests/DistanceCalculatorTests.csproj b/Library/Tests/Tests.csproj similarity index 83% rename from Task_0/DistanceCalculatorTests/DistanceCalculatorTests.csproj rename to Library/Tests/Tests.csproj index b8f9c03..f14fa5a 100644 --- a/Task_0/DistanceCalculatorTests/DistanceCalculatorTests.csproj +++ b/Library/Tests/Tests.csproj @@ -13,7 +13,7 @@ - + @@ -21,7 +21,8 @@ - + + \ No newline at end of file diff --git a/Task_0/DistanceCalculator.sln b/Task_0/DistanceCalculator.sln deleted file mode 100644 index 5e69c28..0000000 --- a/Task_0/DistanceCalculator.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.5.002.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DistanceCalculatorTests", "DistanceCalculatorTests\DistanceCalculatorTests.csproj", "{C669DFFA-E38F-4496-AA5C-EFA20D77D4E0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DistanceCalculator", "DistanceCalculator\DistanceCalculator.csproj", "{E1B0F168-4A94-476E-B3E9-1F1D65DF6C25}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C669DFFA-E38F-4496-AA5C-EFA20D77D4E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C669DFFA-E38F-4496-AA5C-EFA20D77D4E0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C669DFFA-E38F-4496-AA5C-EFA20D77D4E0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C669DFFA-E38F-4496-AA5C-EFA20D77D4E0}.Release|Any CPU.Build.0 = Release|Any CPU - {E1B0F168-4A94-476E-B3E9-1F1D65DF6C25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E1B0F168-4A94-476E-B3E9-1F1D65DF6C25}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E1B0F168-4A94-476E-B3E9-1F1D65DF6C25}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E1B0F168-4A94-476E-B3E9-1F1D65DF6C25}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {0BA0AB8E-FD21-491D-A0A8-97992369C07E} - EndGlobalSection -EndGlobal diff --git a/Task_0/DistanceCalculator/PointSample.cs b/Task_0/DistanceCalculator/PointSample.cs deleted file mode 100644 index 2ca152b..0000000 --- a/Task_0/DistanceCalculator/PointSample.cs +++ /dev/null @@ -1,66 +0,0 @@ - -namespace PointSample -{ - public class Point(int x, int y) - { - private int _x = x; - private int _y = y; - - public int GetX() - { - return _x; - } - - public void SetX(int x) - { - _x = x; - } - - public int GetY() - { - return _y; - } - - public void SetY(int y) - { - _y = y; - } - } - - public class DistanceCalculator - { - public static double CalculateDistanceBetween2Points(Point point1, Point point2) - { - if (point1 == null) - { - throw new ArgumentNullException(nameof(point1), "Point 1 cannot be null"); - } - - if (point2 == null) - { - throw new ArgumentNullException(nameof(point2), "Point 2 cannot be null"); - } - - int deltaX = point1.GetX() - point2.GetX(); - int deltaY = point1.GetY() - point2.GetY(); - - return Math.Sqrt(Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2)); - } - } - - - class Program - { - static void Main(string[] args) - { - Point point1 = new Point(1, 1); - Point point2 = new Point(4, 5); - - double distance = DistanceCalculator.CalculateDistanceBetween2Points(point1, point2); - - Console.WriteLine($"Distance between point1 and point2: {distance}"); - } - } -} - - diff --git a/Task_0/DistanceCalculatorTests/DistanceCalculatorTests.cs b/Task_0/DistanceCalculatorTests/DistanceCalculatorTests.cs deleted file mode 100644 index 14f9bc8..0000000 --- a/Task_0/DistanceCalculatorTests/DistanceCalculatorTests.cs +++ /dev/null @@ -1,50 +0,0 @@ -using PointSample; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace PointSample.DistanceCalculatorTests -{ - - [TestClass] - public class DistanceCalculatorTests - { - [TestMethod] - public void CalculateDistanceBetween2Points_SamePoint_ReturnsZero() - { - Point point1 = new Point(3, 4); - Point point2 = new Point(3, 4); - - double distance = DistanceCalculator.CalculateDistanceBetween2Points(point1, point2); - - Assert.AreEqual(0, distance); - } - - [TestMethod] - public void CalculateDistanceBetween2Points_ValidPoints_ReturnsCorrectDistance() - { - Point point1 = new Point(1, 1); - Point point2 = new Point(4, 5); - - double distance = DistanceCalculator.CalculateDistanceBetween2Points(point1, point2); - - Assert.AreEqual(5, distance); - } - - [TestMethod] - public void CalculateDistanceBetween2Points_NullPoint1_ThrowsArgumentNullException() - { - Point point1 = null; - Point point2 = new Point(4, 5); - - Assert.ThrowsException(() => DistanceCalculator.CalculateDistanceBetween2Points(point1, point2)); - } - - [TestMethod] - public void CalculateDistanceBetween2Points_NullPoint2_ThrowsArgumentNullException() - { - Point point1 = new Point(1, 1); - Point point2 = null; - - Assert.ThrowsException(() => DistanceCalculator.CalculateDistanceBetween2Points(point1, point2)); - } - } -}