From eac451c2646d7ad8b3d0a3ed83dab59076b73fbf Mon Sep 17 00:00:00 2001 From: David Wei Date: Fri, 24 Sep 2021 15:50:51 +1200 Subject: [PATCH 1/4] add comments for the found issues --- .gitignore | 1 + Order.Management/Circle.cs | 9 ++++++++- Order.Management/CuttingListReport.cs | 10 ++++++++-- Order.Management/InvoiceReport.cs | 3 +++ Order.Management/Order.cs | 1 + Order.Management/PaintingReport.cs | 4 +++- Order.Management/Shape.cs | 3 +++ 7 files changed, 27 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 4d9e991..26b926c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ local.appsettings.config # User-specific files +.idea/ *.suo *.user *.userosscache diff --git a/Order.Management/Circle.cs b/Order.Management/Circle.cs index 9824ecc..9d164a9 100644 --- a/Order.Management/Circle.cs +++ b/Order.Management/Circle.cs @@ -1,4 +1,5 @@ -using System; +// 0. Remove no longer required code conveniently could make code cleaner +using System; using System.Collections.Generic; using System.Text; @@ -6,25 +7,31 @@ namespace Order.Management { class Circle : Shape { + // 1. magic number public int circlePrice = 3; public Circle(int red, int blue, int yellow) { + // 2. hard-coded string Name = "Circle"; base.Price = circlePrice; AdditionalCharge = 1; + // 3. we could use a better way: 'base(red, blue, yellow)' assigning values to the fields that defined in base class base.NumberOfRedShape = red; base.NumberOfBlueShape = blue; base.NumberOfYellowShape = yellow; } + // 4. bad method name: you cannot know the exact meaning of `total`, a better name could be PriceTotal public override int Total() { return RedCirclesTotal() + BlueCirclesTotal() + YellowCirclesTotal(); } + // 5. if I were the author, I would like use properties for the following methods public int RedCirclesTotal() { return (base.NumberOfRedShape * Price); } + public int BlueCirclesTotal() { return (base.NumberOfBlueShape * Price); diff --git a/Order.Management/CuttingListReport.cs b/Order.Management/CuttingListReport.cs index 125d45f..aecaf0e 100644 --- a/Order.Management/CuttingListReport.cs +++ b/Order.Management/CuttingListReport.cs @@ -6,9 +6,12 @@ namespace Order.Management { class CuttingListReport : Order { + // 1. Inconsistent name convention: it should change to TableWidth + // 2. This property could be readonly. public int tableWidth = 20; public CuttingListReport(string customerName, string customerAddress, string dueDate, List shapes) { + // use base(parameters) instead of the `base.FieldName` way base.CustomerName = customerName; base.Address = customerAddress; base.DueDate = dueDate; @@ -21,6 +24,7 @@ public override void GenerateReport() Console.WriteLine(base.ToString()); generateTable(); } + // 1. Inconsistent name convention: it should change to GenerateTable public void generateTable() { PrintLine(); @@ -31,11 +35,13 @@ public void generateTable() PrintRow("Circle", base.OrderedBlocks[2].TotalQuantityOfShape().ToString()); PrintLine(); } + // 3. If a method could be private, make it private public void PrintLine() { Console.WriteLine(new string('-', tableWidth)); } + // 3. If a method could be private, make it private public void PrintRow(params string[] columns) { int width = (tableWidth - columns.Length) / columns.Length; @@ -49,10 +55,12 @@ public void PrintRow(params string[] columns) Console.WriteLine(row); } + // 3. If a method could be private, make it private public string AlignCentre(string text, int width) { text = text.Length > width ? text.Substring(0, width - 3) + "..." : text; + // 4. this check should be the very first check if (string.IsNullOrEmpty(text)) { return new string(' ', width); @@ -62,7 +70,5 @@ public string AlignCentre(string text, int width) return text.PadRight(width - (width - text.Length) / 2).PadLeft(width); } } - - } } diff --git a/Order.Management/InvoiceReport.cs b/Order.Management/InvoiceReport.cs index 78443c3..349a1fc 100644 --- a/Order.Management/InvoiceReport.cs +++ b/Order.Management/InvoiceReport.cs @@ -68,6 +68,7 @@ public void PrintLine() Console.WriteLine(new string('-', tableWidth)); } + // Duplicate Code, should move to a base Report Class public void PrintRow(params string[] columns) { int width = (tableWidth - columns.Length) / columns.Length; @@ -81,8 +82,10 @@ public void PrintRow(params string[] columns) Console.WriteLine(row); } + // Duplicate code public string AlignCentre(string text, int width) { + // Should extract into a getTrimmedText method text = text.Length > width ? text.Substring(0, width - 3) + "..." : text; if (string.IsNullOrEmpty(text)) diff --git a/Order.Management/Order.cs b/Order.Management/Order.cs index 235c789..9d72b18 100644 --- a/Order.Management/Order.cs +++ b/Order.Management/Order.cs @@ -6,6 +6,7 @@ namespace Order.Management { abstract class Order { + // 1. the following two fields could save into a Customer class public string CustomerName { get; set; } public string Address { get; set; } public string DueDate { get; set; } diff --git a/Order.Management/PaintingReport.cs b/Order.Management/PaintingReport.cs index 9b61c83..da65b5b 100644 --- a/Order.Management/PaintingReport.cs +++ b/Order.Management/PaintingReport.cs @@ -4,6 +4,7 @@ namespace Order.Management { + // 1. Reports should have its own base class instead of inheriting from Order though they have some common information class PaintingReport : Order { public int tableWidth = 73; @@ -26,12 +27,13 @@ public void generateTable() PrintLine(); PrintRow(" ", " Red ", " Blue ", " Yellow "); PrintLine(); + // 2. Please don't use [index] way unless you have no other choice PrintRow("Square", base.OrderedBlocks[0].NumberOfRedShape.ToString(), base.OrderedBlocks[0].NumberOfBlueShape.ToString(), base.OrderedBlocks[0].NumberOfYellowShape.ToString()); PrintRow("Triangle", base.OrderedBlocks[1].NumberOfRedShape.ToString(), base.OrderedBlocks[1].NumberOfBlueShape.ToString(), base.OrderedBlocks[1].NumberOfYellowShape.ToString()); PrintRow("Circle", base.OrderedBlocks[2].NumberOfRedShape.ToString(), base.OrderedBlocks[2].NumberOfBlueShape.ToString(), base.OrderedBlocks[2].NumberOfYellowShape.ToString()); PrintLine(); } - + public void PrintLine() { Console.WriteLine(new string('-', tableWidth)); diff --git a/Order.Management/Shape.cs b/Order.Management/Shape.cs index 7f5c61c..50f9492 100644 --- a/Order.Management/Shape.cs +++ b/Order.Management/Shape.cs @@ -8,10 +8,12 @@ abstract class Shape { public string Name { get; set; } public int Price { get; set; } + // 1. the following four fields are actually not attribute of a shape, it should belong to Order Information public int AdditionalCharge { get; set; } public int NumberOfRedShape { get; set; } public int NumberOfBlueShape { get; set; } public int NumberOfYellowShape { get; set; } + // 2. the following methods are similar to the fields above, it should move into the order class public int TotalQuantityOfShape() { return NumberOfRedShape + NumberOfBlueShape + NumberOfYellowShape; @@ -21,6 +23,7 @@ public int AdditionalChargeTotal() { return NumberOfRedShape * AdditionalCharge; } + // 3. bad method name, PriceTotal could be a better candidate public abstract int Total(); } From efe05dd513d85001ab4828feb15fffcb84fc380a Mon Sep 17 00:00:00 2001 From: David Wei Date: Sat, 25 Sep 2021 10:43:30 +1200 Subject: [PATCH 2/4] add approval test to verify later refactoring --- .../ProgramTest.TestMainOutputs.approved.txt | 41 +++++++++++++++++++ Order.Management.Test/Approvals/input.txt | 12 ++++++ .../Order.Management.Test.csproj | 31 ++++++++++++++ Order.Management.Test/ProgramTest.cs | 30 ++++++++++++++ Order.Management.sln | 6 +++ Order.Management/Program.cs | 21 +++++----- 6 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 Order.Management.Test/Approvals/ProgramTest.TestMainOutputs.approved.txt create mode 100644 Order.Management.Test/Approvals/input.txt create mode 100644 Order.Management.Test/Order.Management.Test.csproj create mode 100644 Order.Management.Test/ProgramTest.cs diff --git a/Order.Management.Test/Approvals/ProgramTest.TestMainOutputs.approved.txt b/Order.Management.Test/Approvals/ProgramTest.TestMainOutputs.approved.txt new file mode 100644 index 0000000..535bf93 --- /dev/null +++ b/Order.Management.Test/Approvals/ProgramTest.TestMainOutputs.approved.txt @@ -0,0 +1,41 @@ +Please input your Name: Please input your Address: Please input your Due Date: +Please input the number of Red Squares: Please input the number of Blue Squares: Please input the number of Yellow Squares: +Please input the number of Red Triangles: Please input the number of Blue Triangles: Please input the number of Yellow Triangles: +Please input the number of Red Circle: Please input the number of Blue Circle: Please input the number of Yellow Circle: +Your invoice report has been generated: + +Name: David Wei Address: 26A Croydon Street, Sydenham, Christchurch 8024 Due Date: 29-09-2021 Order #: 0 +------------------------------------------------------------------------- +| | Red | Blue | Yellow | +------------------------------------------------------------------------- +| Square | 1 | 2 | 3 | +| Triangle | 4 | 7 | 2 | +| Circle | 5 | 8 | 1 | +------------------------------------------------------------------------- + +Squares 6 @ $1 ppi = $6 +Triangles 13 @ $2 ppi = $26 +Circles 14 @ $3 ppi = $42 +Red Color Surcharge 10 @ $1 ppi = $10 + +Your cutting list has been generated: + +Name: David Wei Address: 26A Croydon Street, Sydenham, Christchurch 8024 Due Date: 29-09-2021 Order #: 0 +-------------------- +| | Qty | +-------------------- +| Square | 6 | +|Triangle | 13 | +| Circle | 14 | +-------------------- + +Your painting report has been generated: + +Name: David Wei Address: 26A Croydon Street, Sydenham, Christchurch 8024 Due Date: 29-09-2021 Order #: 0 +------------------------------------------------------------------------- +| | Red | Blue | Yellow | +------------------------------------------------------------------------- +| Square | 1 | 2 | 3 | +| Triangle | 4 | 7 | 2 | +| Circle | 5 | 8 | 1 | +------------------------------------------------------------------------- diff --git a/Order.Management.Test/Approvals/input.txt b/Order.Management.Test/Approvals/input.txt new file mode 100644 index 0000000..95b6feb --- /dev/null +++ b/Order.Management.Test/Approvals/input.txt @@ -0,0 +1,12 @@ +David Wei +26A Croydon Street, Sydenham, Christchurch 8024 +29-09-2021 +1 +2 +3 +4 +7 +2 +5 +8 +1 \ No newline at end of file diff --git a/Order.Management.Test/Order.Management.Test.csproj b/Order.Management.Test/Order.Management.Test.csproj new file mode 100644 index 0000000..52d1ed1 --- /dev/null +++ b/Order.Management.Test/Order.Management.Test.csproj @@ -0,0 +1,31 @@ + + + + netcoreapp3.1 + + false + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + Always + + + + + + + diff --git a/Order.Management.Test/ProgramTest.cs b/Order.Management.Test/ProgramTest.cs new file mode 100644 index 0000000..bb1112a --- /dev/null +++ b/Order.Management.Test/ProgramTest.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; +using System.Reflection; +using ApprovalTests; +using ApprovalTests.Namers; +using ApprovalTests.Reporters; +using Xunit; + +namespace Order.Management.Test +{ + [UseReporter(typeof(DiffReporter))] + [UseApprovalSubdirectory("Approvals")] + public class ProgramTest + { + [Fact] + public void TestMainOutputs() + { + using var fakeStdout = new StringWriter(); + Console.SetOut(fakeStdout); + + var currentDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + using var inputNames = new StreamReader($@"{currentDir}/Approvals/input.txt"); + // Tell console to get its input from the file, not from the keyboard + Console.SetIn(inputNames); + + Program.Main(new string[] { }); + Approvals.Verify(fakeStdout.ToString()); + } + } +} \ No newline at end of file diff --git a/Order.Management.sln b/Order.Management.sln index 400236d..f34bcd4 100644 --- a/Order.Management.sln +++ b/Order.Management.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.29519.87 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Order.Management", "Order.Management\Order.Management.csproj", "{1DAC7794-3F0E-4083-95A9-2E6FF9512C0C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Order.Management.Test", "Order.Management.Test\Order.Management.Test.csproj", "{AEA22CA0-3BCB-4793-994C-F81440CD8C99}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {1DAC7794-3F0E-4083-95A9-2E6FF9512C0C}.Debug|Any CPU.Build.0 = Debug|Any CPU {1DAC7794-3F0E-4083-95A9-2E6FF9512C0C}.Release|Any CPU.ActiveCfg = Release|Any CPU {1DAC7794-3F0E-4083-95A9-2E6FF9512C0C}.Release|Any CPU.Build.0 = Release|Any CPU + {AEA22CA0-3BCB-4793-994C-F81440CD8C99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AEA22CA0-3BCB-4793-994C-F81440CD8C99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AEA22CA0-3BCB-4793-994C-F81440CD8C99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AEA22CA0-3BCB-4793-994C-F81440CD8C99}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Order.Management/Program.cs b/Order.Management/Program.cs index 1422f85..d996c06 100644 --- a/Order.Management/Program.cs +++ b/Order.Management/Program.cs @@ -3,10 +3,11 @@ namespace Order.Management { - class Program + + public static class Program { // Main entry - static void Main(string[] args) + public static void Main(string[] args) { var (customerName, address, dueDate) = CustomerInfoInput(); @@ -18,9 +19,9 @@ static void Main(string[] args) PaintingReport(customerName, address, dueDate, orderedShapes); } - + // Order Circle Input - public static Circle OrderCirclesInput() + private static Circle OrderCirclesInput() { Console.Write("\nPlease input the number of Red Circle: "); int redCircle = Convert.ToInt32(userInput()); @@ -32,9 +33,9 @@ public static Circle OrderCirclesInput() Circle circle = new Circle(redCircle, blueCircle, yellowCircle); return circle; } - + // Order Squares Input - public static Square OrderSquaresInput() + private static Square OrderSquaresInput() { Console.Write("\nPlease input the number of Red Squares: "); int redSquare = Convert.ToInt32(userInput()); @@ -48,7 +49,7 @@ public static Square OrderSquaresInput() } // Order Triangles Input - public static Triangle OrderTrianglesInput() + private static Triangle OrderTrianglesInput() { Console.Write("\nPlease input the number of Red Triangles: "); int redTriangle = Convert.ToInt32(userInput()); @@ -74,21 +75,21 @@ public static string userInput() return input; } - // Generate Painting Report + // Generate Painting Report private static void PaintingReport(string customerName, string address, string dueDate, List orderedShapes) { PaintingReport paintingReport = new PaintingReport(customerName, address, dueDate, orderedShapes); paintingReport.GenerateReport(); } - // Generate Painting Report + // Generate Painting Report private static void CuttingListReport(string customerName, string address, string dueDate, List orderedShapes) { CuttingListReport cuttingListReport = new CuttingListReport(customerName, address, dueDate, orderedShapes); cuttingListReport.GenerateReport(); } - // Generate Invoice Report + // Generate Invoice Report private static void InvoiceReport(string customerName, string address, string dueDate, List orderedShapes) { InvoiceReport invoiceReport = new InvoiceReport(customerName, address, dueDate, orderedShapes); From 7cf616bf352b4367c9b212846ba8404f02024762 Mon Sep 17 00:00:00 2001 From: David Wei Date: Sat, 25 Sep 2021 07:26:15 +1200 Subject: [PATCH 3/4] step 1: refactoring done --- .../ProgramTest.TestMainOutputs.approved.txt | 12 +- Order.Management.Test/Approvals/input.txt | 2 +- .../Order.Management.Test.csproj | 2 +- Order.Management/Circle.cs | 44 -------- Order.Management/Constants.cs | 33 ++++++ Order.Management/CuttingListReport.cs | 68 +++-------- Order.Management/Enums/ShapeColours.cs | 9 ++ Order.Management/Enums/Shapes.cs | 29 +++++ .../Exceptions/BusinessException.cs | 12 ++ .../Exceptions/UnknownShapeException.cs | 10 ++ Order.Management/InvoiceReport.cs | 97 ++++------------ Order.Management/Models/Order.cs | 42 +++++++ Order.Management/Models/OrderItem.cs | 8 ++ Order.Management/Models/Shape.cs | 16 +++ Order.Management/Order.cs | 23 ---- Order.Management/PaintingReport.cs | 56 +-------- Order.Management/Program.cs | 106 +++++++----------- Order.Management/ReportBase.cs | 80 +++++++++++++ Order.Management/Shape.cs | 30 ----- Order.Management/Square.cs | 40 ------- Order.Management/Triangle.cs | 39 ------- 21 files changed, 328 insertions(+), 430 deletions(-) delete mode 100644 Order.Management/Circle.cs create mode 100644 Order.Management/Constants.cs create mode 100644 Order.Management/Enums/ShapeColours.cs create mode 100644 Order.Management/Enums/Shapes.cs create mode 100644 Order.Management/Exceptions/BusinessException.cs create mode 100644 Order.Management/Exceptions/UnknownShapeException.cs create mode 100644 Order.Management/Models/Order.cs create mode 100644 Order.Management/Models/OrderItem.cs create mode 100644 Order.Management/Models/Shape.cs delete mode 100644 Order.Management/Order.cs create mode 100644 Order.Management/ReportBase.cs delete mode 100644 Order.Management/Shape.cs delete mode 100644 Order.Management/Square.cs delete mode 100644 Order.Management/Triangle.cs diff --git a/Order.Management.Test/Approvals/ProgramTest.TestMainOutputs.approved.txt b/Order.Management.Test/Approvals/ProgramTest.TestMainOutputs.approved.txt index 535bf93..beac65e 100644 --- a/Order.Management.Test/Approvals/ProgramTest.TestMainOutputs.approved.txt +++ b/Order.Management.Test/Approvals/ProgramTest.TestMainOutputs.approved.txt @@ -1,7 +1,13 @@ Please input your Name: Please input your Address: Please input your Due Date: -Please input the number of Red Squares: Please input the number of Blue Squares: Please input the number of Yellow Squares: -Please input the number of Red Triangles: Please input the number of Blue Triangles: Please input the number of Yellow Triangles: -Please input the number of Red Circle: Please input the number of Blue Circle: Please input the number of Yellow Circle: +Please input the number of Red Square: +Please input the number of Blue Square: +Please input the number of Yellow Square: +Please input the number of Red Triangle: +Please input the number of Blue Triangle: +Please input the number of Yellow Triangle: +Please input the number of Red Circle: +Please input the number of Blue Circle: +Please input the number of Yellow Circle: Your invoice report has been generated: Name: David Wei Address: 26A Croydon Street, Sydenham, Christchurch 8024 Due Date: 29-09-2021 Order #: 0 diff --git a/Order.Management.Test/Approvals/input.txt b/Order.Management.Test/Approvals/input.txt index 95b6feb..15b3027 100644 --- a/Order.Management.Test/Approvals/input.txt +++ b/Order.Management.Test/Approvals/input.txt @@ -9,4 +9,4 @@ David Wei 2 5 8 -1 \ No newline at end of file +1 diff --git a/Order.Management.Test/Order.Management.Test.csproj b/Order.Management.Test/Order.Management.Test.csproj index 52d1ed1..9ab0d69 100644 --- a/Order.Management.Test/Order.Management.Test.csproj +++ b/Order.Management.Test/Order.Management.Test.csproj @@ -7,7 +7,7 @@ - + diff --git a/Order.Management/Circle.cs b/Order.Management/Circle.cs deleted file mode 100644 index 9d164a9..0000000 --- a/Order.Management/Circle.cs +++ /dev/null @@ -1,44 +0,0 @@ -// 0. Remove no longer required code conveniently could make code cleaner -using System; -using System.Collections.Generic; -using System.Text; - -namespace Order.Management -{ - class Circle : Shape - { - // 1. magic number - public int circlePrice = 3; - public Circle(int red, int blue, int yellow) - { - // 2. hard-coded string - Name = "Circle"; - base.Price = circlePrice; - AdditionalCharge = 1; - // 3. we could use a better way: 'base(red, blue, yellow)' assigning values to the fields that defined in base class - base.NumberOfRedShape = red; - base.NumberOfBlueShape = blue; - base.NumberOfYellowShape = yellow; - } - // 4. bad method name: you cannot know the exact meaning of `total`, a better name could be PriceTotal - public override int Total() - { - return RedCirclesTotal() + BlueCirclesTotal() + YellowCirclesTotal(); - } - - // 5. if I were the author, I would like use properties for the following methods - public int RedCirclesTotal() - { - return (base.NumberOfRedShape * Price); - } - - public int BlueCirclesTotal() - { - return (base.NumberOfBlueShape * Price); - } - public int YellowCirclesTotal() - { - return (base.NumberOfYellowShape * Price); - } - } -} diff --git a/Order.Management/Constants.cs b/Order.Management/Constants.cs new file mode 100644 index 0000000..0f0c3cb --- /dev/null +++ b/Order.Management/Constants.cs @@ -0,0 +1,33 @@ +using Microsoft.VisualBasic.CompilerServices; +using Order.Management.Enums; +using Order.Management.Exceptions; + +namespace Order.Management +{ + public static class Constants + { + // Constants for Reports + public const int TableWidth = 73; + public const int CuttingReportTableWidth = 20; + + // Constants for Orders + public const decimal CirclePrice = 3m; + public const decimal SquarePrice = 1m; + public const decimal TrianglePrice = 2m; + public const decimal AdditionalCharge = 1m; + + public static Shapes[] CurrentShapes = new[] + { + Shapes.Square, + Shapes.Triangle, + Shapes.Circle, + }; + + public static ShapeColours[] CurrentColours = new[] + { + ShapeColours.Red, + ShapeColours.Blue, + ShapeColours.Yellow, + }; + } +} \ No newline at end of file diff --git a/Order.Management/CuttingListReport.cs b/Order.Management/CuttingListReport.cs index aecaf0e..f96e181 100644 --- a/Order.Management/CuttingListReport.cs +++ b/Order.Management/CuttingListReport.cs @@ -1,74 +1,40 @@ using System; using System.Collections.Generic; -using System.Text; +using Order.Management.Enums; namespace Order.Management { - class CuttingListReport : Order + class CuttingListReport : ReportBase { - // 1. Inconsistent name convention: it should change to TableWidth - // 2. This property could be readonly. - public int tableWidth = 20; - public CuttingListReport(string customerName, string customerAddress, string dueDate, List shapes) - { - // use base(parameters) instead of the `base.FieldName` way - base.CustomerName = customerName; - base.Address = customerAddress; - base.DueDate = dueDate; - base.OrderedBlocks = shapes; - } - public override void GenerateReport() { + SetTableWidth(Constants.CuttingReportTableWidth); Console.WriteLine("\nYour cutting list has been generated: "); - Console.WriteLine(base.ToString()); - generateTable(); + Console.WriteLine(Order.ToString()); + GenerateTable(); } - // 1. Inconsistent name convention: it should change to GenerateTable - public void generateTable() + + private new void GenerateTable() { PrintLine(); PrintRow(" ", " Qty "); PrintLine(); - PrintRow("Square",base.OrderedBlocks[0].TotalQuantityOfShape().ToString()); - PrintRow("Triangle", base.OrderedBlocks[1].TotalQuantityOfShape().ToString()); - PrintRow("Circle", base.OrderedBlocks[2].TotalQuantityOfShape().ToString()); - PrintLine(); - } - // 3. If a method could be private, make it private - public void PrintLine() - { - Console.WriteLine(new string('-', tableWidth)); - } - - // 3. If a method could be private, make it private - public void PrintRow(params string[] columns) - { - int width = (tableWidth - columns.Length) / columns.Length; - string row = "|"; - foreach (string column in columns) + var shapesList = new List() + { + Shapes.Square, + Shapes.Triangle, + Shapes.Circle, + }; + foreach (Shapes shape in shapesList) { - row += AlignCentre(column, width) + "|"; + PrintRow( shape, Order.GetNumbersOfShape(shape)); } - - Console.WriteLine(row); + PrintLine(); } - // 3. If a method could be private, make it private - public string AlignCentre(string text, int width) + public CuttingListReport(Models.Order order) : base(order) { - text = text.Length > width ? text.Substring(0, width - 3) + "..." : text; - - // 4. this check should be the very first check - if (string.IsNullOrEmpty(text)) - { - return new string(' ', width); - } - else - { - return text.PadRight(width - (width - text.Length) / 2).PadLeft(width); - } } } } diff --git a/Order.Management/Enums/ShapeColours.cs b/Order.Management/Enums/ShapeColours.cs new file mode 100644 index 0000000..b784e02 --- /dev/null +++ b/Order.Management/Enums/ShapeColours.cs @@ -0,0 +1,9 @@ +namespace Order.Management.Enums +{ + public enum ShapeColours + { + Red, + Yellow, + Blue, + } +} \ No newline at end of file diff --git a/Order.Management/Enums/Shapes.cs b/Order.Management/Enums/Shapes.cs new file mode 100644 index 0000000..fdbeb12 --- /dev/null +++ b/Order.Management/Enums/Shapes.cs @@ -0,0 +1,29 @@ +using Order.Management.Exceptions; + +namespace Order.Management.Enums +{ + public enum Shapes + { + Circle, + Square, + Triangle, + } + + public static class ShapesExtensions + { + public static decimal GetUnitPrice(this Shapes shape) + { + switch (shape) + { + case Shapes.Circle: + return Constants.CirclePrice; + case Shapes.Square: + return Constants.SquarePrice; + case Shapes.Triangle: + return Constants.TrianglePrice; + default: + throw new UnknownShapeException(shape.ToString()); + } + } + } +} \ No newline at end of file diff --git a/Order.Management/Exceptions/BusinessException.cs b/Order.Management/Exceptions/BusinessException.cs new file mode 100644 index 0000000..a34fe4c --- /dev/null +++ b/Order.Management/Exceptions/BusinessException.cs @@ -0,0 +1,12 @@ +using System; + +namespace Order.Management.Exceptions +{ + public class BusinessException: Exception + { + protected BusinessException(string message): base(message) + { + + } + } +} \ No newline at end of file diff --git a/Order.Management/Exceptions/UnknownShapeException.cs b/Order.Management/Exceptions/UnknownShapeException.cs new file mode 100644 index 0000000..d9421ed --- /dev/null +++ b/Order.Management/Exceptions/UnknownShapeException.cs @@ -0,0 +1,10 @@ +namespace Order.Management.Exceptions +{ + public class UnknownShapeException: BusinessException + { + public UnknownShapeException(string shape): base("Invalid Shape: {shape}") + { + + } + } +} \ No newline at end of file diff --git a/Order.Management/InvoiceReport.cs b/Order.Management/InvoiceReport.cs index 349a1fc..6be5701 100644 --- a/Order.Management/InvoiceReport.cs +++ b/Order.Management/InvoiceReport.cs @@ -1,101 +1,42 @@ using System; -using System.Collections.Generic; -using System.Text; +using Order.Management.Enums; namespace Order.Management { - class InvoiceReport : Order + class InvoiceReport : ReportBase { - public int tableWidth = 73; - public InvoiceReport(string customerName, string customerAddress, string dueDate, List shapes) - { - base.CustomerName = customerName; - base.Address = customerAddress; - base.DueDate = dueDate; - base.OrderedBlocks = shapes; - } - public override void GenerateReport() { Console.WriteLine("\nYour invoice report has been generated: "); - Console.WriteLine(base.ToString()); + Console.WriteLine(Order.ToString()); GenerateTable(); - OrderSquareDetails(); - OrderTriangleDetails(); - OrderCircleDetails(); - RedPaintSurcharge(); + Console.WriteLine(); + ShowOrderDetailsInShape(); + ShowRedPaintSurcharge(); } - public void RedPaintSurcharge() + private void ShowOrderDetailsInShape() { - Console.WriteLine("Red Color Surcharge " + TotalAmountOfRedShapes() + " @ $" + base.OrderedBlocks[0].AdditionalCharge + " ppi = $" + TotalPriceRedPaintSurcharge()); + foreach (var shape in Constants.CurrentShapes) + { + PrintOrderDetailsByShape(shape); + } } - public int TotalAmountOfRedShapes() + private void ShowRedPaintSurcharge() { - return base.OrderedBlocks[0].NumberOfRedShape + base.OrderedBlocks[1].NumberOfRedShape + - base.OrderedBlocks[2].NumberOfRedShape; + Console.WriteLine( + $"Red Color Surcharge {Order.GetNumbersOfColour(ShapeColours.Red)} @ ${Constants.AdditionalCharge} ppi = ${Order.RedPaintSurcharge}"); } - public int TotalPriceRedPaintSurcharge() - { - return TotalAmountOfRedShapes() * base.OrderedBlocks[0].AdditionalCharge; - } - public void GenerateTable() + private void PrintOrderDetailsByShape(Shapes shape) { - PrintLine(); - PrintRow(" ", " Red ", " Blue ", " Yellow "); - PrintLine(); - PrintRow("Square", base.OrderedBlocks[0].NumberOfRedShape.ToString(), base.OrderedBlocks[0].NumberOfBlueShape.ToString(), base.OrderedBlocks[0].NumberOfYellowShape.ToString()); - PrintRow("Triangle", base.OrderedBlocks[1].NumberOfRedShape.ToString(), base.OrderedBlocks[1].NumberOfBlueShape.ToString(), base.OrderedBlocks[1].NumberOfYellowShape.ToString()); - PrintRow("Circle", base.OrderedBlocks[2].NumberOfRedShape.ToString(), base.OrderedBlocks[2].NumberOfBlueShape.ToString(), base.OrderedBlocks[2].NumberOfYellowShape.ToString()); - PrintLine(); - } - public void OrderSquareDetails() - { - Console.WriteLine("\nSquares " + base.OrderedBlocks[0].TotalQuantityOfShape() + " @ $" + base.OrderedBlocks[0].Price + " ppi = $" + base.OrderedBlocks[0].Total()); - } - public void OrderTriangleDetails() - { - Console.WriteLine("Triangles " + base.OrderedBlocks[1].TotalQuantityOfShape() + " @ $" + base.OrderedBlocks[1].Price + " ppi = $" + base.OrderedBlocks[1].Total()); - } - public void OrderCircleDetails() - { - Console.WriteLine("Circles " + base.OrderedBlocks[2].TotalQuantityOfShape() + " @ $" + base.OrderedBlocks[2].Price + " ppi = $" + base.OrderedBlocks[2].Total()); - } - public void PrintLine() - { - Console.WriteLine(new string('-', tableWidth)); + Console.WriteLine( + $"{shape}s {Order.GetNumbersOfShape(shape)} @ ${shape.GetUnitPrice()} ppi = ${Order.GetPriceTotalByShape(shape)}"); } - // Duplicate Code, should move to a base Report Class - public void PrintRow(params string[] columns) + public InvoiceReport(Models.Order order) : base(order) { - int width = (tableWidth - columns.Length) / columns.Length; - string row = "|"; - - foreach (string column in columns) - { - row += AlignCentre(column, width) + "|"; - } - - Console.WriteLine(row); - } - - // Duplicate code - public string AlignCentre(string text, int width) - { - // Should extract into a getTrimmedText method - text = text.Length > width ? text.Substring(0, width - 3) + "..." : text; - - if (string.IsNullOrEmpty(text)) - { - return new string(' ', width); - } - else - { - return text.PadRight(width - (width - text.Length) / 2).PadLeft(width); - } } } -} +} \ No newline at end of file diff --git a/Order.Management/Models/Order.cs b/Order.Management/Models/Order.cs new file mode 100644 index 0000000..7dfb450 --- /dev/null +++ b/Order.Management/Models/Order.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using System.Linq; +using Order.Management.Enums; + +namespace Order.Management.Models +{ + public class Order + { + public string CustomerName { get; set; } + public string Address { get; set; } + public string DueDate { get; set; } + public int OrderNumber { get; set; } + public List OrderedBlocks { get; set; } + + public decimal RedPaintSurcharge => GetNumbersOfColour(ShapeColours.Red) * Constants.AdditionalCharge; + + public int GetNumbersOfColour(ShapeColours colour) + { + return OrderedBlocks.Where(_ => _.Shape.Colour.Equals(colour)).ToList().Sum(_ => _.Quantity); + } + + public int GetNumbersOfShapeWithColour(Shapes shape, ShapeColours colour) + { + return OrderedBlocks.Where(_ => _.Shape.Name.Equals(shape) && _.Shape.Colour.Equals(colour)).ToList().Sum(_ => _.Quantity); + } + + public int GetNumbersOfShape(Shapes shape) + { + return OrderedBlocks.Where(_ => _.Shape.Name.Equals(shape)).ToList().Sum(_ => _.Quantity); + } + + public decimal GetPriceTotalByShape(Shapes shape) + { + return shape.GetUnitPrice() * GetNumbersOfShape(shape); + } + + public override string ToString() + { + return $"\nName: {CustomerName} Address: {Address} Due Date: {DueDate} Order #: {OrderNumber}"; + } + } +} diff --git a/Order.Management/Models/OrderItem.cs b/Order.Management/Models/OrderItem.cs new file mode 100644 index 0000000..9af1335 --- /dev/null +++ b/Order.Management/Models/OrderItem.cs @@ -0,0 +1,8 @@ +namespace Order.Management.Models +{ + public class OrderItem + { + public Shape Shape { get; set; } + public int Quantity { get; set; } + } +} \ No newline at end of file diff --git a/Order.Management/Models/Shape.cs b/Order.Management/Models/Shape.cs new file mode 100644 index 0000000..a9a63ca --- /dev/null +++ b/Order.Management/Models/Shape.cs @@ -0,0 +1,16 @@ +using Order.Management.Enums; + +namespace Order.Management.Models +{ + public class Shape + { + public Shapes Name { get; set; } + public ShapeColours Colour { get; set; } + + public Shape(Shapes name, ShapeColours colour) + { + Name = name; + Colour = colour; + } + } +} diff --git a/Order.Management/Order.cs b/Order.Management/Order.cs deleted file mode 100644 index 9d72b18..0000000 --- a/Order.Management/Order.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Order.Management -{ - abstract class Order - { - // 1. the following two fields could save into a Customer class - public string CustomerName { get; set; } - public string Address { get; set; } - public string DueDate { get; set; } - public int OrderNumber { get; set; } - public List OrderedBlocks { get; set; } - - public abstract void GenerateReport(); - - public string ToString() - { - return "\nName: " + CustomerName + " Address: " + Address + " Due Date: " + DueDate + " Order #: " + OrderNumber; - } - } -} diff --git a/Order.Management/PaintingReport.cs b/Order.Management/PaintingReport.cs index da65b5b..dc4079f 100644 --- a/Order.Management/PaintingReport.cs +++ b/Order.Management/PaintingReport.cs @@ -4,66 +4,18 @@ namespace Order.Management { - // 1. Reports should have its own base class instead of inheriting from Order though they have some common information - class PaintingReport : Order + class PaintingReport : ReportBase { - public int tableWidth = 73; - public PaintingReport(string customerName, string customerAddress, string dueDate, List shapes) - { - base.CustomerName = customerName; - base.Address = customerAddress; - base.DueDate = dueDate; - base.OrderedBlocks = shapes; - } public override void GenerateReport() { Console.WriteLine("\nYour painting report has been generated: "); - Console.WriteLine(base.ToString()); - generateTable(); + Console.WriteLine(Order.ToString()); + GenerateTable(); } - public void generateTable() - { - PrintLine(); - PrintRow(" ", " Red ", " Blue ", " Yellow "); - PrintLine(); - // 2. Please don't use [index] way unless you have no other choice - PrintRow("Square", base.OrderedBlocks[0].NumberOfRedShape.ToString(), base.OrderedBlocks[0].NumberOfBlueShape.ToString(), base.OrderedBlocks[0].NumberOfYellowShape.ToString()); - PrintRow("Triangle", base.OrderedBlocks[1].NumberOfRedShape.ToString(), base.OrderedBlocks[1].NumberOfBlueShape.ToString(), base.OrderedBlocks[1].NumberOfYellowShape.ToString()); - PrintRow("Circle", base.OrderedBlocks[2].NumberOfRedShape.ToString(), base.OrderedBlocks[2].NumberOfBlueShape.ToString(), base.OrderedBlocks[2].NumberOfYellowShape.ToString()); - PrintLine(); - } - - public void PrintLine() - { - Console.WriteLine(new string('-', tableWidth)); - } - public void PrintRow(params string[] columns) + public PaintingReport(Models.Order order) : base(order) { - int width = (tableWidth - columns.Length) / columns.Length; - string row = "|"; - - foreach (string column in columns) - { - row += AlignCentre(column, width) + "|"; - } - - Console.WriteLine(row); - } - - public string AlignCentre(string text, int width) - { - text = text.Length > width ? text.Substring(0, width - 3) + "..." : text; - - if (string.IsNullOrEmpty(text)) - { - return new string(' ', width); - } - else - { - return text.PadRight(width - (width - text.Length) / 2).PadLeft(width); - } } } } diff --git a/Order.Management/Program.cs b/Order.Management/Program.cs index d996c06..9d9860b 100644 --- a/Order.Management/Program.cs +++ b/Order.Management/Program.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; +using Order.Management.Enums; +using Order.Management.Models; namespace Order.Management { - public static class Program { // Main entry @@ -12,87 +13,52 @@ public static void Main(string[] args) var (customerName, address, dueDate) = CustomerInfoInput(); var orderedShapes = CustomerOrderInput(); + var order = new Models.Order() + { + Address = address, + CustomerName = customerName, + DueDate = dueDate, + OrderedBlocks = orderedShapes, + }; - InvoiceReport(customerName, address, dueDate, orderedShapes); - - CuttingListReport(customerName, address, dueDate, orderedShapes); - - PaintingReport(customerName, address, dueDate, orderedShapes); - } - - // Order Circle Input - private static Circle OrderCirclesInput() - { - Console.Write("\nPlease input the number of Red Circle: "); - int redCircle = Convert.ToInt32(userInput()); - Console.Write("Please input the number of Blue Circle: "); - int blueCircle = Convert.ToInt32(userInput()); - Console.Write("Please input the number of Yellow Circle: "); - int yellowCircle = Convert.ToInt32(userInput()); - - Circle circle = new Circle(redCircle, blueCircle, yellowCircle); - return circle; - } - - // Order Squares Input - private static Square OrderSquaresInput() - { - Console.Write("\nPlease input the number of Red Squares: "); - int redSquare = Convert.ToInt32(userInput()); - Console.Write("Please input the number of Blue Squares: "); - int blueSquare = Convert.ToInt32(userInput()); - Console.Write("Please input the number of Yellow Squares: "); - int yellowSquare = Convert.ToInt32(userInput()); - - Square square = new Square(redSquare, blueSquare, yellowSquare); - return square; - } + ShowInvoiceReport(order); - // Order Triangles Input - private static Triangle OrderTrianglesInput() - { - Console.Write("\nPlease input the number of Red Triangles: "); - int redTriangle = Convert.ToInt32(userInput()); - Console.Write("Please input the number of Blue Triangles: "); - int blueTriangle = Convert.ToInt32(userInput()); - Console.Write("Please input the number of Yellow Triangles: "); - int yellowTriangle = Convert.ToInt32(userInput()); + ShowCuttingListReport(order); - Triangle triangle = new Triangle(redTriangle, blueTriangle, yellowTriangle); - return triangle; + ShowPaintingReport(order); } // User Console Input - public static string userInput() + private static string UserInput() { string input = Console.ReadLine(); while (string.IsNullOrEmpty(input)) { Console.WriteLine("please enter valid details"); input = Console.ReadLine(); - } + return input; } // Generate Painting Report - private static void PaintingReport(string customerName, string address, string dueDate, List orderedShapes) + private static void ShowPaintingReport(Models.Order order) { - PaintingReport paintingReport = new PaintingReport(customerName, address, dueDate, orderedShapes); + PaintingReport paintingReport = new PaintingReport(order); paintingReport.GenerateReport(); } // Generate Painting Report - private static void CuttingListReport(string customerName, string address, string dueDate, List orderedShapes) + private static void ShowCuttingListReport(Models.Order order) { - CuttingListReport cuttingListReport = new CuttingListReport(customerName, address, dueDate, orderedShapes); + CuttingListReport cuttingListReport = new CuttingListReport(order); cuttingListReport.GenerateReport(); } // Generate Invoice Report - private static void InvoiceReport(string customerName, string address, string dueDate, List orderedShapes) + private static void ShowInvoiceReport(Models.Order order) { - InvoiceReport invoiceReport = new InvoiceReport(customerName, address, dueDate, orderedShapes); + InvoiceReport invoiceReport = new InvoiceReport(order); invoiceReport.GenerateReport(); } @@ -100,26 +66,30 @@ private static void InvoiceReport(string customerName, string address, string du private static (string customerName, string address, string dueDate) CustomerInfoInput() { Console.Write("Please input your Name: "); - string customerName = userInput(); + string customerName = UserInput(); Console.Write("Please input your Address: "); - string address = userInput(); + string address = UserInput(); Console.Write("Please input your Due Date: "); - string dueDate = userInput(); + string dueDate = UserInput(); return (customerName, address, dueDate); } // Get order input - private static List CustomerOrderInput() + private static List CustomerOrderInput() { - Square square = OrderSquaresInput(); - Triangle triangle = OrderTrianglesInput(); - Circle circle = OrderCirclesInput(); - - var orderedShapes = new List(); - orderedShapes.Add(square); - orderedShapes.Add(triangle); - orderedShapes.Add(circle); - return orderedShapes; + var orderItemList = new List(); + foreach(var shape in Constants.CurrentShapes) + foreach (ShapeColours colour in Constants.CurrentColours) + { + Console.Write($"\nPlease input the number of {colour} {shape}: "); + int quantity = Convert.ToInt32(UserInput()); + orderItemList.Add(new OrderItem() + { + Shape = new Shape(shape, colour), + Quantity = quantity + }); + } + return orderItemList; } } -} +} \ No newline at end of file diff --git a/Order.Management/ReportBase.cs b/Order.Management/ReportBase.cs new file mode 100644 index 0000000..c7562ab --- /dev/null +++ b/Order.Management/ReportBase.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using Order.Management.Enums; + +namespace Order.Management +{ + public abstract class ReportBase + { + private int _tableWidth; + protected readonly Models.Order Order; + + protected ReportBase(Models.Order order) + { + Order = order; + _tableWidth = Constants.TableWidth; + } + + protected void SetTableWidth(int width) + { + _tableWidth = width; + } + + protected void GenerateTable() + { + PrintLine(); + PrintRow(" ", " Red ", " Blue ", " Yellow "); + PrintLine(); + var shapesList = new List() + { + Shapes.Square, + Shapes.Triangle, + Shapes.Circle, + }; + foreach (Shapes shape in shapesList) + { + PrintRow( + shape, + Order.GetNumbersOfShapeWithColour(shape, ShapeColours.Red), + Order.GetNumbersOfShapeWithColour(shape, ShapeColours.Blue), + Order.GetNumbersOfShapeWithColour(shape, ShapeColours.Yellow) + ); + } + PrintLine(); + } + + public abstract void GenerateReport(); + + protected void PrintLine() + { + Console.WriteLine(new string('-', _tableWidth)); + } + + protected void PrintRow(params object[] columns) + { + int width = (_tableWidth - columns.Length) / columns.Length; + string row = "|"; + + foreach (object column in columns) + { + row += AlignCentre(column.ToString(), width) + "|"; + } + + Console.WriteLine(row); + } + + private string AlignCentre(string text, int width) + { + text = text.Length > width ? text.Substring(0, width - 3) + "..." : text; + + if (string.IsNullOrEmpty(text)) + { + return new string(' ', width); + } + else + { + return text.PadRight(width - (width - text.Length) / 2).PadLeft(width); + } + } + } +} \ No newline at end of file diff --git a/Order.Management/Shape.cs b/Order.Management/Shape.cs deleted file mode 100644 index 50f9492..0000000 --- a/Order.Management/Shape.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Order.Management -{ - abstract class Shape - { - public string Name { get; set; } - public int Price { get; set; } - // 1. the following four fields are actually not attribute of a shape, it should belong to Order Information - public int AdditionalCharge { get; set; } - public int NumberOfRedShape { get; set; } - public int NumberOfBlueShape { get; set; } - public int NumberOfYellowShape { get; set; } - // 2. the following methods are similar to the fields above, it should move into the order class - public int TotalQuantityOfShape() - { - return NumberOfRedShape + NumberOfBlueShape + NumberOfYellowShape; - } - - public int AdditionalChargeTotal() - { - return NumberOfRedShape * AdditionalCharge; - } - // 3. bad method name, PriceTotal could be a better candidate - public abstract int Total(); - - } -} diff --git a/Order.Management/Square.cs b/Order.Management/Square.cs deleted file mode 100644 index 017601e..0000000 --- a/Order.Management/Square.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Order.Management -{ - class Square : Shape - { - - public int SquarePrice = 1; - - public Square(int numberOfRedSquares, int numberOfBlueSquares, int numberOfYellowSquares) - { - Name = "Square"; - base.Price = SquarePrice; - AdditionalCharge = 1; - base.NumberOfRedShape = numberOfRedSquares; - base.NumberOfBlueShape = numberOfBlueSquares; - base.NumberOfYellowShape = numberOfYellowSquares; - } - - public override int Total() - { - return RedSquaresTotal() + BlueSquaresTotal() + YellowSquaresTotal(); - } - - public int RedSquaresTotal() - { - return (base.NumberOfRedShape * Price); - } - public int BlueSquaresTotal() - { - return (base.NumberOfBlueShape * Price); - } - public int YellowSquaresTotal() - { - return (base.NumberOfYellowShape * Price); - } - } -} diff --git a/Order.Management/Triangle.cs b/Order.Management/Triangle.cs deleted file mode 100644 index dbf48ff..0000000 --- a/Order.Management/Triangle.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Order.Management -{ - class Triangle : Shape - { - public int TrianglePrice = 2; - public Triangle(int numberOfRedTriangles, int numberOfBlueTriangles, int numberOfYellowTriangles) - { - Name = "Triangle"; - base.Price = TrianglePrice; - AdditionalCharge = 1; - base.NumberOfRedShape = numberOfRedTriangles; - base.NumberOfBlueShape = numberOfBlueTriangles; - base.NumberOfYellowShape = numberOfYellowTriangles; - } - - public override int Total() - { - return RedTrianglesTotal() + BlueTrianglesTotal() + YellowTrianglesTotal(); - } - - public int RedTrianglesTotal() - { - return (base.NumberOfRedShape * Price); - } - public int BlueTrianglesTotal() - { - return (base.NumberOfBlueShape * Price); - } - public int YellowTrianglesTotal() - { - return (base.NumberOfYellowShape * Price); - } - -} -} From 9ac903a40ae61016be84391c385cf5b63668101e Mon Sep 17 00:00:00 2001 From: David Wei Date: Mon, 27 Sep 2021 22:12:23 +1300 Subject: [PATCH 4/4] add OrderTest test case --- Order.Management.Test/OrderTest.cs | 143 +++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 Order.Management.Test/OrderTest.cs diff --git a/Order.Management.Test/OrderTest.cs b/Order.Management.Test/OrderTest.cs new file mode 100644 index 0000000..44b3e45 --- /dev/null +++ b/Order.Management.Test/OrderTest.cs @@ -0,0 +1,143 @@ +using System.Collections.Generic; +using System.Management; +using System.Runtime.InteropServices; +using Order.Management.Enums; +using Xunit; +using Order.Management.Models; + +namespace Order.Management.Test +{ + public class OrderTest + { + public static IEnumerable OrderWithColorTotalData => + GetSampleOrderList(QuantitySample, QuantityTotalByColorSample); + + public static IEnumerable OrderWithShapeTotalData => + GetSampleOrderList(QuantitySample, QuantityTotalByShapeSample); + + + [Theory] + [MemberData(nameof(OrderWithColorTotalData))] + void OrderColorTotalTestTheory(Models.Order order, int[] expectTotalByColor) + { + int red = expectTotalByColor[0]; + int blue = expectTotalByColor[1]; + int yellow = expectTotalByColor[2]; + Assert.Equal(order.GetNumbersOfColour(ShapeColours.Red), red); + Assert.Equal(order.GetNumbersOfColour(ShapeColours.Blue), blue); + Assert.Equal(order.GetNumbersOfColour(ShapeColours.Yellow), yellow); + } + + [Theory] + [MemberData(nameof(OrderWithShapeTotalData))] + void OrderShapeTotalTestTheory(Models.Order order, int[] expectTotalByShape) + { + int squareTotal = expectTotalByShape[0]; + int triangleTotal = expectTotalByShape[1]; + int circleTotal = expectTotalByShape[2]; + Assert.Equal(order.GetNumbersOfShape(Shapes.Square), squareTotal); + Assert.Equal(order.GetNumbersOfShape(Shapes.Triangle), triangleTotal); + Assert.Equal(order.GetNumbersOfShape(Shapes.Circle), circleTotal); + } + + private static int[][] QuantitySample { get; } = + { + new[] + { + //Red, Blue, Yellow + 1, 2, 3, //square + 4, 7, 2, //triangle + 5, 8, 1, //circle + }, + new[] + { + //Red, Blue, Yellow + 1, 2, 3, + 2, 5, 6, + 3, 8, 1, + }, + new[] + { + //Red, Blue, Yellow + 0, 3, 4, + 1, 5, 8, + 9, 2, 3, + }, + }; + + private static int[][] QuantityTotalByColorSample { get; } = + { + new[] + { + //Red, Blue, Yellow + 10, 17, 6, + }, + new[] + { + //Red, Blue, Yellow + 6, 15, 10, + }, + new[] + { + //Red, Blue, Yellow + 10, 10, 15, + }, + }; + + private static int[][] QuantityTotalByShapeSample { get; } = + { + new[] + { + //Square, Triangle, Circle + 6, 13, 14, + }, + new[] + { + //Square, Triangle, Circle + 6, 13, 12, + }, + new[] + { + //Square, Triangle, Circle + 7, 14, 14, + }, + }; + + private static IEnumerable GetSampleOrderList(int[][] quantitySample, int[][] quantityTotalSample) + { + var index = 0; + foreach (var quantityList in quantitySample) + { + var order = new Models.Order + { + CustomerName = "David Wei", + Address = "21 Stanbury Avenue, Somerfield, Christchurch 8024", + DueDate = "28-09-2021", + OrderNumber = 1000, + OrderedBlocks = GetSampleOrderItemList(quantityList) + }; + yield return new object[] {order, quantityTotalSample[index]}; + index++; + } + } + + private static List GetSampleOrderItemList(int[] quantityList) + { + var orderItemList = new List(); + var quantityIndex = 0; + foreach (var shape in Constants.CurrentShapes) + foreach (ShapeColours colour in Constants.CurrentColours) + { + var quantity = quantityList[quantityIndex]; + orderItemList.Add(new OrderItem() + { + Shape = new Shape(shape, colour), + Quantity = quantity, + }); + quantityIndex++; + } + + return orderItemList; + } + } +} \ No newline at end of file