diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index c4e3115b44..f8ce1505fc 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -24,6 +24,8 @@
* [Pantry-calculateMaxDish()](#pantry---calculatemaxdish)
* [Delete Dish](#delete-dish)
* [Edit Price](#edit-price)
+ * [View Total Stock](#view-total-stock)
+ * [Buy Ingredient](#buy-ingredient)
* [Help](#help)
* [**Future Enhancements**](#future-enhancements)
* [Create an interface for `Pantry`](#create-an-interface-for-pantry)
@@ -36,7 +38,7 @@
* [User stories](#user-stories)
* [**Glossary**](#glossary)
-
+
--------------------------------------------------------------------------------------------------------------
## **Acknowledgements**
@@ -79,11 +81,20 @@ The bulk of the app’s work is done by the following components:
### How the architecture components interact with each other
-The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command `delete 1`.
+The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command `bye`.
![Architecture Encode Data](images/sequence/Architecture_Encode_Data.png)
*Figure 2: Architecture Encode Sequence Diagram*
+1. User enters the command `bye` to the `Ui`
+2. `Ui` passes the command as a string through the method `receiveUserInput('bye')` in `CafeCtrl`
+3. `CafeCtrl` passes the string to `Parser` through the method `parseCommand('bye')`
+4. `Parser` returns a new `exitCommand` object
+5. `CafeCtrl` calls the `execute()` method of `Command` and returns after execution is completed (Step 6)
+6. `CafeCtrl` calls the `saveAll()` command in `Storage` before terminating the application
+7. `saveMenu()`, `saveOrderList()`, and `savePantryStock` are executed within the `saveAll()` method (Steps 8 - 13)
+8. Application terminates.
+
### Ui component
API: [Ui.java]({repoURL}src/main/java/seedu/cafectrl/ui/Ui.java)
@@ -340,6 +351,31 @@ API: [EditPriceCommand.java]({repoURL}src/main/java/seedu/cafectrl/command/EditP
When the `execute()` method of `EditPriceCommand` is invoked in `Main`, it subsequently calls the `setPrice()` method on the `Dish` object to modify the price of the specific dish. Following this, the `showEditPriceMessages()` method in the `Ui` component is triggered to retrieve and display a message from `Messages` related to the successful execution of the price modification process. This sequence of actions orchestrates the flow of information and operations between the `Main`, `EditPriceCommand`, `Dish`, and `Ui` components, ensuring the seamless handling of the price editing functionality within the application.
+### View Total Stock
+![View Total Stock Execution](images/sequence/ViewTotalStockCommand_execute.png)
+
+*Figure 16: Execution of view_stock command*
+
+API: [ViewTotalStockCommand.java]({repoURL}src/main/java/seedu/cafectrl/command/ViewTotalStockCommand.java)
+
+When the `execute()` method of `ViewTotalStock` is invoked, an ArrayList of Ingredients are retrieved through the method `getPantryStock`. For each ingredient in the ArrayList, `ViewTotalStock` calls `showIngredientStock` from `Ui` to print out the list of ingredients in the ArrayList.
+
+### Buy Ingredient
+![Buy Ingredient Execution](images/sequence/BuyIngredientCommand_execute.png)
+
+*Figure 17: Execution of buy_ingredient command*
+
+API: [BuyIngredientCommand.java]({repoURL}src/main/java/seedu/cafectrl/command/BuyIngredientCommand.java)
+
+When the `execute()` method is invoked
+1. `addIngredient` in `BuyIngredientCommand` is called
+2. Looping from the **first to the last** element in an ArrayList of Ingredients called `ingredients`, `addIngredientToStock` from `Pantry` is invoked
+3. First, `pantryStock` is retrieved and `getIndexOfIngredient` is called to check if the new ingredient exists in `pantryStock`
+4. If ingredient exists (`ingredientIndex != -1`), `addIngredientQuantity` is called to update the quantity of the existing ingredient
+5. Else, a new `ingredient` object is returned
+6. Looping from the **last to the first** element in `ingredients`, the ingredient is added to the string to be printed `ingredientString` using the `buildBuyIngredientMessage` method which ignores repeated ingredients in the list
+7. Finally, `ingredientString` is shown to the user through `showToUser` method of `Ui`
+
### Help
![Help Execution](images/sequence/HelpCommand_execute.png)
diff --git a/docs/diagrams/ArchitectureDiagram.puml b/docs/diagrams/ArchitectureDiagram.puml
index 61e93c40dc..4827e3671d 100644
--- a/docs/diagrams/ArchitectureDiagram.puml
+++ b/docs/diagrams/ArchitectureDiagram.puml
@@ -7,7 +7,7 @@ rectangle {
rectangle Ui
rectangle Parser
rectangle Command
-rectangle Main
+rectangle CafeCtrl
rectangle Data
rectangle Storage
}
@@ -22,10 +22,10 @@ Command --> Data
Command ..> Ui
Storage --> Data
Storage ...> TextFiles
-Ui <- Main
-Main --> Parser
-Main --> Data
-Main --> Storage
+Ui <- CafeCtrl
+CafeCtrl --> Parser
+CafeCtrl --> Data
+CafeCtrl --> Storage
@enduml
\ No newline at end of file
diff --git a/docs/diagrams/sequence/Architecture_Encode_Data.puml b/docs/diagrams/sequence/Architecture_Encode_Data.puml
index 10d3101a8a..884fc5c0c2 100644
--- a/docs/diagrams/sequence/Architecture_Encode_Data.puml
+++ b/docs/diagrams/sequence/Architecture_Encode_Data.puml
@@ -1,40 +1,38 @@
-@startuml
-!define COMMAND class ListIngredientCommand
-!define UI class Ui
-!define MAIN class Main
-!define STORAGE class Storage
-!define DATA class Data
-!define PARSER class Parser
-!define COMMAND class Command
-
-autonumber
-Actor user
-
-loop userInput != "bye"
-user->Ui : 'delete 1'
-activate Ui
-Ui-> Main : userInput : String
-activate Main
-Main -> Parser : parseCommand()
-Activate Parser
-Parser -> Main : command: Command
-Deactivate Parser
-Main -> Command : delete.execute()
-Activate Command
-Command -> Data : menu.remove()
-Activate Data
-return
-return
-user -> Ui: 'bye'
-Ui-> Main : userInput : String
-end loop
-Main->Storage : saveMenu()
-Activate Storage
-Storage -> Storage: encodeMenu()
-Activate Storage
-return
-return
-return
-return
-
-@enduml
+@startuml
+!define UI class ":Ui"
+!define MAIN class ":CafeCtrl"
+!define STORAGE class ":Storage"
+!define DATA class ":Data"
+!define PARSER class ":Parser"
+!define COMMAND class ":Command"
+
+autonumber
+Actor user
+
+user -> ":Ui": 'bye'
+Activate ":Ui"
+":Ui"-> ":CafeCtrl" : receiveUserInput('bye')
+loop !exitCommand
+Activate ":CafeCtrl"
+":CafeCtrl" -> ":Parser" : parseCommand('bye')
+Activate ":Parser"
+return exitCommand: ":Command"
+":CafeCtrl" -> ":Command" : exitCommand.execute()
+Activate ":Command"
+return
+end loop
+":CafeCtrl"->":Storage" : saveAll()
+Activate ":Storage"
+":Storage" -> ":Storage": saveMenu()
+Activate ":Storage"
+return
+":Storage" -> ":Storage": saveOrderList()
+Activate ":Storage"
+return
+":Storage" -> ":Storage": savePantryStock()
+Activate ":Storage"
+return
+return
+return
+
+@enduml
diff --git a/docs/diagrams/sequence/BuyIngredientCommand_execute.puml b/docs/diagrams/sequence/BuyIngredientCommand_execute.puml
new file mode 100644
index 0000000000..02a9f650f0
--- /dev/null
+++ b/docs/diagrams/sequence/BuyIngredientCommand_execute.puml
@@ -0,0 +1,48 @@
+@startuml
+!define COMMAND class ":BuyIngredientCommand"
+!define UI class ":Ui"
+!define MENU class ":Menu"
+!define PANTRY class ":Pantry"
+
+autonumber
+
+-> ":BuyIngredientCommand" : execute()
+activate ":BuyIngredientCommand"
+
+":BuyIngredientCommand" -> ":BuyIngredientCommand" : addIngredient()
+activate ":BuyIngredientCommand"
+loop i < ingredients.size()
+":BuyIngredientCommand" -> ":Pantry" : addIngredientToStock(name: String, qty: int, unit: String)
+activate ":Pantry"
+":Pantry" -> ":Pantry" : getPantryStock()
+activate ":Pantry"
+return pantryStock: ArrayList
+
+":Pantry" -> ":Pantry" : getIndexOfIngredient(name: String)
+activate ":Pantry"
+return ingredientIndex: int
+alt ingredientIndex != -1
+":Pantry" -> ":Pantry" : addIngredientQuantity(qty: int, ingredientIndex: int, unit: String)
+activate ":Pantry"
+return ingredient: Ingredient
+":Pantry" --> ":BuyIngredientCommand" : ingredient: Ingredient
+else
+return ingredient: Ingredient
+end
+end loop
+
+loop i >= 0
+":BuyIngredientCommand" -> ":BuyIngredientCommand" : buildBuyIngredientMessage(ingredient: Ingredient)
+activate ":BuyIngredientCommand"
+return ingredientString: String
+end loop
+
+return
+":BuyIngredientCommand" -> ":Ui" : showToUser(ingredientString: String)
+activate ":Ui"
+return
+return
+
+
+
+@enduml
\ No newline at end of file
diff --git a/docs/diagrams/sequence/ViewTotalStockCommand_execute.puml b/docs/diagrams/sequence/ViewTotalStockCommand_execute.puml
new file mode 100644
index 0000000000..a2c96683cd
--- /dev/null
+++ b/docs/diagrams/sequence/ViewTotalStockCommand_execute.puml
@@ -0,0 +1,25 @@
+@startuml
+!define COMMAND class ":ViewTotalStockCommand"
+!define UI class ":Ui"
+!define PANTRY class ":Pantry"
+
+autonumber
+
+-> ":ViewTotalStockCommand" : execute()
+activate ":ViewTotalStockCommand"
+
+":ViewTotalStockCommand" -> ":Pantry" : getPantryStock().get(dishIndexToBeDeleted: int)
+activate ":Pantry"
+return (pantryStock: ArrayList)
+loop Ingredient ingredient : pantryStock
+":ViewTotalStockCommand" -> ":Ui" : showIngredientStock(name: String, qty: int, unit: String)
+activate ":Ui"
+":Ui" -> ":Ui" : showToUser(message: String)
+activate ":Ui"
+return
+return
+end loop
+return
+
+
+@enduml
\ No newline at end of file
diff --git a/docs/images/ArchitectureDiagram.png b/docs/images/ArchitectureDiagram.png
index 0a7913ceff..2ecaf0f488 100644
Binary files a/docs/images/ArchitectureDiagram.png and b/docs/images/ArchitectureDiagram.png differ
diff --git a/docs/images/aboutUs/shanice.jpg b/docs/images/aboutUs/shanice.jpg
index 051f897437..1593e26bdb 100644
Binary files a/docs/images/aboutUs/shanice.jpg and b/docs/images/aboutUs/shanice.jpg differ
diff --git a/docs/images/sequence/Architecture_Encode_Data.png b/docs/images/sequence/Architecture_Encode_Data.png
index 676498a48c..0da4335ab0 100644
Binary files a/docs/images/sequence/Architecture_Encode_Data.png and b/docs/images/sequence/Architecture_Encode_Data.png differ
diff --git a/docs/images/sequence/BuyIngredientCommand_execute.png b/docs/images/sequence/BuyIngredientCommand_execute.png
new file mode 100644
index 0000000000..9ec6dfea84
Binary files /dev/null and b/docs/images/sequence/BuyIngredientCommand_execute.png differ
diff --git a/docs/images/sequence/ViewTotalStockCommand_execute.png b/docs/images/sequence/ViewTotalStockCommand_execute.png
new file mode 100644
index 0000000000..4fd70f2f37
Binary files /dev/null and b/docs/images/sequence/ViewTotalStockCommand_execute.png differ
diff --git a/docs/images_PPP/shanice/bug_reporting.png b/docs/images_PPP/shanice/bug_reporting.png
new file mode 100644
index 0000000000..1a1638a777
Binary files /dev/null and b/docs/images_PPP/shanice/bug_reporting.png differ
diff --git a/docs/images_PPP/shanice/deleting_unused_method.png b/docs/images_PPP/shanice/deleting_unused_method.png
new file mode 100644
index 0000000000..0e43a1b667
Binary files /dev/null and b/docs/images_PPP/shanice/deleting_unused_method.png differ
diff --git a/docs/images_PPP/shanice/deleting_unused_method2.png b/docs/images_PPP/shanice/deleting_unused_method2.png
new file mode 100644
index 0000000000..10aa036e54
Binary files /dev/null and b/docs/images_PPP/shanice/deleting_unused_method2.png differ
diff --git a/docs/images_PPP/shanice/ensure_permission_given.png b/docs/images_PPP/shanice/ensure_permission_given.png
new file mode 100644
index 0000000000..0fd77be4ae
Binary files /dev/null and b/docs/images_PPP/shanice/ensure_permission_given.png differ
diff --git a/docs/team/NaychiMin.md b/docs/team/naychimin.md
similarity index 68%
rename from docs/team/NaychiMin.md
rename to docs/team/naychimin.md
index 8b007f94cb..e0badb8127 100644
--- a/docs/team/NaychiMin.md
+++ b/docs/team/naychimin.md
@@ -24,31 +24,19 @@ Café proprietors who prefer typing on CLI than any other interaction method and
1. **List Ingredient**
- Function: Allow the user to view the ingredients of the desired dish from the menu.
- Command Format: `list_ingredient index/INDEX_OF_DISH_TO_LIST`
- - Error Handling:
- - If the specified index is out of range, to prevent index out of bounds error.
- - If the specified index is of a wrong argument type to prevent number format exception.
- - If the specified index is empty.
- - Specific error messages will then be output to user along with recommended command format.
+ - Error Handling: If the specified index is out of range, of a wrong argument type or is empty.
2. **List Total Sales**
- Function: Allow the user to view the sale for each day across every day since the cafe has operated.
- Command Format: `list_total_sales`
- - Error Handling:
- - If the command has unnecessary arguments after the command.
- - Specific error messages will then be output to user along with recommended command format.
+ - Error Handling: If the command has unnecessary arguments after the command.
3. **Show Sale By Day**
- Function: Allow the user to view the sale for the desired day.
- Command Format: `list_sale day/DAY_TO_LIST`
- - Error Handling:
- - If the specified index is out of range, to prevent index out of bounds error.
- - If the specified index is of a wrong argument type to prevent number format exception.
- - If the specified index is empty or the argument tag is missing.
- - Specific error messages will then be output to user along with recommended command format.
+ - Error Handling: If the specified index is out of range, of a wrong argument type, is empty or the argument tag is missing.
4. **Data processing of 'add_order'**
- My group mate (Cazh1) did the parsing of the command, along with the implementation of needed classes such as Order, OrderList and Chef.
- My role was to seamlessly handle the logic of the data being processed after an order was added to an orderList for the following purposes:
- - Order completion determination
- - Restocking ingredient identification
- - This will be elaborated on in the section below.
+ - Order completion determination and Restocking ingredient identification
#### Enhancements
1. **Pantry Class**
@@ -57,44 +45,31 @@ Café proprietors who prefer typing on CLI than any other interaction method and
- My role, outlined in point 4 above, involved implementing key functions, including:
- `isDishCooked`:
- Implemented to determine the success of an order.
- - Returns a boolean, indicating the success of the order.
- - Manages the process of retrieving necessary ingredients from the `Menu` class, along with the retrieval of the quantity of ingredients in the current `Pantry` class.
- - Decreasing and updating the correct ingredient quantities in the Pantry Stock and not mixing it with the ingredients in the `Menu` class.
- - The accurate execution of this function is crucial for the overall success of order processing
- - which also affects other operations of the cafe, such as the amount of total sales to be displayed to users.
+ - The accurate execution of this function is crucial for the overall success of order processing as it affects other operations of the cafe, such as the amount of total sales to be displayed to users.
- `calculateDishAvailability`:
- Informs the user of the available quantity for each dish in the menu after each order.
- - Provides essential insights into the real-time status of dish availability, alerting users of the availability of each dish in the menu
- - Enables the target user(cafe manager) to keep track of dish availability and stay alerted of the dishes that are unavailable for the next order following an order being marked as successful.
+ - Provides essential insights into the real-time status of dish availability, alerting users of the availability of each dish in the menu.
- `calculateMaxDishes`:
- Handles the logic for calculating the number of dishes made.
- Manages the complex logic for determining restocked ingredients and their required quantities.
- - Presents the information in a structured table format for user clarity and comprehension.
- Pantry Class Development:
- - Creating the Pantry class was a significant learning opportunity, especially given my initial unfamiliarity with Object-Oriented Programming (OOP) concepts.
- - Developing the Pantry class presented a dual challenge – not only did I navigate a crucial learning curve of OOP, but I also ensured the modularity of functions to adhere to coding standards.
- - Interacting with various classes like Menu, Order, Chef, Dish, and Ingredients, the Pantry class played a pivotal role in the seamless functioning of our project.
+ - Creating the Pantry class was a significant learning opportunity, especially given my initial unfamiliarity with Object-Oriented Programming (OOP) concepts. Developing the Pantry class presented a challenge as I had to navigate a crucial learning curve of OOP, and try to ensure the modularity of functions while interacting with various classes.
- The exploration of Java stream filter, a concept introduced in lectures, notably enhanced the efficiency of implemented functionality and prevented arrow-head style code.
- Order and Pantry Coordination:
- My role served as the link between the add_order and buy_ingredients commands, serving as a cohesive link that unified the data(ingredients) processing aspect of order management.
- Order Processing: Seamlessly integrating logic for order success determination and the need for Pantry's ingredient stock management.
- Pantry Stock Management: My active contribution to the Pantry class connected the use of add_order command with subsequent use of the buy_ingredients command, making it a central hub for order processing, dish availability checks, and ingredient restocking prompts.
- - Dish Coordination: I ensured smooth coordination across various dish-related elements, covering determination of success of order to ingredient availability and restocking.
- - Ensuring the accuracy of the dish management process, my role provided a seamless flow from adding orders to procuring required ingredients. This critical link facilitated the effective functioning of the project, ensuring a cohesive and integrated approach to order handling.
2. **Encoding of Sales**
- Implemented encoding for the Sales object, involving:
- - Parsing through various attributes of the Sales object.
- - Converting the data to a string with the delimiter '|'.
+ - Parsing through various attributes of the Sales object using the delimiter '|'.
- Storing the data in a text file.
3. **Decoding of Sales**
- Executed decoding for the Sales object, encompassing:
- Parsing through the text file and separating contents using the delimiter '|'.
- Using parsed attributes to instantiate the Sales object for use in other command classes.
- - Implemented error handling during decoding:
- - Nonexistent dishes are filtered out.
- - Lines with missing delimiters or incorrect formatting in the text file are filtered out (collaboration with Cazh1).
+ - Implemented error handling during decoding: lines with missing delimiters or incorrect formatting in the text file are filtered out (collaboration with Cazh1).
4. **Parser**
- Implemented parsing and error handling for the commands listed in the section above.
diff --git a/docs/team/shanicetang.md b/docs/team/shanicetang.md
index 22843bc0c1..03bdee2642 100644
--- a/docs/team/shanicetang.md
+++ b/docs/team/shanicetang.md
@@ -13,45 +13,44 @@ CaféCRTL aims to optimize managing of inventory and cash flow in a restaurant.
Café proprietors who prefer typing on CLI than any other interaction method and are seeking for a software solution to optimize the management of their café's operations.
-----------------------------------------------------------------------------------------------
-
## Summary of Contributions
+
### Code Contributed
[Click here to see my code contribution :)](https://nus-cs2113-ay2324s1.github.io/tp-dashboard/?search=&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code&since=2023-09-22&tabOpen=true&tabType=authorship&tabAuthor=ShaniceTang&tabRepo=AY2324S1-CS2113-T17-2%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false)
### Enhancements Implemented
-
#### Features
-
1. **Delete Dish**
-- Function: Allow user to delete a specific dish on the menu
-- Command Format: `delete DISH_INDEX`
-- Error Handling: This command is able to detect missing argument tag, missing argument, and invalid index. The error message will be shown to the user.
-
+ - Function: Allow user to delete a specific dish on the menu
+ - Command Format: `delete DISH_INDEX`
+ - Error Handling: This command is able to detect missing argument tag, missing argument, and invalid index. The error message will be shown to the user.
+
2. **Buy Ingredient**
-- Function: Allow user to add ingredients to the Pantry. If ingredients have been previously added, its quantity will update accordingly
-- Command Format: `buy_ingredient ingredient/INGREDIENT1_NAME qty/INGREDIENT1_QTY[, ingredient/INGREDIENT2_NAME qty/INGREDIENT2_QTY, ...]`
-- Error Handling: This command is able to detect the following user errors and outputs the appropriate error messages
- - Missing argument tag / Missing arguments
- - Quantity value less than 1 or greater than 1,000,000
- - Empty / Invalid Units
-
+ - Function: Allow user to add ingredients to the Pantry. If ingredients have been previously added, its quantity will update accordingly
+ - Command Format: `buy_ingredient ingredient/INGREDIENT1_NAME qty/INGREDIENT1_QTY[, ingredient/INGREDIENT2_NAME qty/INGREDIENT2_QTY, ...]`
+ - Error Handling: This command is able to detect the following user errors and outputs the appropriate error messages
+ - Missing argument tag / Missing arguments
+ - Quantity value less than 1 or greater than 1,000,000
+ - Empty / Invalid Units
+
3. **View Total Stock**
-- Function: Allows user to view the total stock currently in the Pantry
-- Command Format: `view_stock`
+ - Function: Allows user to view the total stock currently in the Pantry
+ - Command Format: `view_stock`
### Enhancement
1. **Storage**
- Encoding of Menu object to a readable text file menu.txt
- Decoding of data in menu.txt to Menu object
-
+
2. **Parser**
- Implemented parsing for the features listed above
-- Improved precision of error handling by adding some checking methods: isInvalidQty, isEmptyUnit, isValidUnit
-
+- Improved precision of error handling by adding some checking methods: `isInvalidQty`, `isEmptyUnit`, `isValidUnit`, `checkForMismatchUnit`
+
3. **Pantry**
-- Implemented pantry class which helps user to keep track of their current stock. This enhancement plays a huge role to several commands as it allows the user to smoothly interact with the pantry, hence it is important to ensure its completeness by ensuring it is able to seamlessly handle pantry-related operations. For example, for my contribution to pantry class (adding of ingredients to stock), I had to consider the user adding the same ingredients within an input or using a different unit and handle those possibilities elegantly.
+- Implemented pantry class together with @NaychiMin which helps user to keep track of their current stock. This enhancement plays a huge role to several commands as it allows the user to smoothly interact with the pantry, hence it is important to ensure its completeness by ensuring it is able to seamlessly handle pantry-related operations. For example, for my contribution to pantry class (adding of ingredients to stock), I had to consider the user adding the same ingredients within an input or using a different unit and handle those possibilities elegantly.
- Allows user to add ingredients to pantry (through `buy_ingredient`) and updates the quantity of existing ingredients. This was a challenge to implement mostly due to the need to upkeep to coding quality. I had to achieve this without involving arrowhead code (which would have been the trivial solution) through abstraction and understanding what parameters I need to pass in and return.
- Ensures user uses the same unit for existing ingredients. To allow this to be implemented, I modified the Ingredient class upon approval from my team members to accept units as a separate attribute and helped modify other classes/methods that instantiates an Ingredient object.
+
4. **Messages & ErrorMessages**
- Provided meaningful messages that can be easily understood by the user
@@ -63,15 +62,23 @@ Café proprietors who prefer typing on CLI than any other interaction method and
### Contributions to DG
[DeveloperGuide](https://ay2324s1-cs2113-t17-2.github.io/tp/DeveloperGuide.html)
- Designed various UML diagrams: Architecture Diagram, Ui Component Class Diagram, Data Component Class Diagram, Delete Sequence Diagram
-- Added descriptions for Ui component and Delete Command
+- Added descriptions for Ui component, Delete Command, View Total Stock Command, and Buy Ingredient Command
#### Team-based Task
-1. **Logging**
-- This was challenging as I encountered the issue of the log messages being printed out to system console which ruined the Ui. :( The CS2113 textbook did not mention how to rectify this issue, so I had to do external research and eventually found a solution to store log messages into a log file without displaying at runtime. :)
+1. Logging
+ - This was challenging as I encountered the issue of the log messages being printed out to system console which ruined the Ui. :( The CS2113 textbook did not mention how to rectify this issue, so I had to do external research and eventually found a solution to store log messages into a log file without displaying at runtime. :)
+2. Maintaining issue tracker
+3. Testing application and report bugs found
+ ![](../images_PPP/shanice/bug_reporting.png)
### Review / Mentoring Contributions
-1. Reviewed and merged some PRs [#300](https://github.com/AY2324S1-CS2113-T17-2/tp/pull/300), ...
+1. Reviewed and merged some PRs [#300](https://github.com/AY2324S1-CS2113-T17-2/tp/pull/300), [#322](https://github.com/AY2324S1-CS2113-T17-2/tp/pull/322), [#283](https://github.com/AY2324S1-CS2113-T17-2/tp/pull/283), ...
2. Clarified and updated the team before making major changes to ensure everyone is on the same page <3
+ - Ensuring unused methods can be safely deleted with permission from the team member who wrote it
+ ![](../images_PPP/shanice/deleting_unused_method.png)
+ ![](../images_PPP/shanice/deleting_unused_method2.png)
+ - Ensuring team members give their permission before implementing
+ ![](../images_PPP/shanice/ensure_permission_given.png)
### Contributions Beyond the Project Team
1. Reported bugs in other teams' application: [#105](https://github.com/AY2324S1-CS2113-W12-3/tp/issues/105), [#101](https://github.com/AY2324S1-CS2113-W12-3/tp/issues/101)
diff --git a/docs/team/ziyi105.md b/docs/team/ziyi105.md
index bbaf0c7d8f..b0691732f6 100644
--- a/docs/team/ziyi105.md
+++ b/docs/team/ziyi105.md
@@ -33,14 +33,14 @@ Café proprietors who prefer typing on CLI than any other interaction method and
Extra info: This feature requires constant updating whenever a new feature is added. It is also very tedious to implement Junit test as the output is very long and keeps changing. Hence, I removed the Junit test in the last iteration as I feel that it is not necessary to have Junit test for a trivial `help` command.
3. **Encoding & Decoding of Pantry Stock Storage File**
- Function: When the user calls bye command, all the ingredients stored in pantry will be encoded into format of `INGREDIENT_NAME | QUANTITY | UNIT`. The encoded data will be written in Pantry_stock.txt file. When the user starts a new session, the data in the text file will be extracted out and be decoded to load the ingredients back to PantryStock class.
+ Function: When the user calls bye command, all the ingredients stored in pantry will be encoded into format of `INGREDIENT_NAME | QUANTITY | UNIT`. The encoded data will be written in pantry_stock.txt file. When the user starts a new session, the data in the text file will be extracted out and be decoded to load the ingredients back to PantryStock class.
Error Handling: This command will still check for the validity of each argument (e.g., length of ingredient name, type of unit), and skip the particular ingredient if any of the arguments is not valid. This can prevent the user from accidentally adding invalid ingredients to the text file.
### Enhancements
1. **Storage**
[Relevant PR](https://github.com/AY2324S1-CS2113-T17-2/tp/pull/143)
- Read and learned from the storage system in addressbook level 3 and adopted it in our project.
- - Implemented `Encoding.java`, `Decoding.java` and `Storage.java` with skeleton methods for my teammates to implement.
+ - Implemented `Encoder.java`, `Decoder.java` and `Storage.java` with skeleton methods for my teammates to implement.
2. **Parser**
Created `Parser.java` for other teammates to use. Implemented ParserUtil interface to reduce coupling of Parser.java and CafeCRTL.java.
@@ -111,6 +111,6 @@ Café proprietors who prefer typing on CLI than any other interaction method and
![Relevant Telegram screenshot 4](../images_PPP/ziyi/relevant_telagram_screenshot_4.png)
### Contributions beyond the Project Team
-1. Posted 8 posts in the forum.
+1. Posted 9 posts in the forum.
Examples of forum posts: [#37](https://github.com/nus-cs2113-AY2324S1/forum/issues/37), [#19](https://github.com/nus-cs2113-AY2324S1/forum/issues/19), [#31](https://github.com/nus-cs2113-AY2324S1/forum/issues/31)
2. Reviews on PR from other teams: [T18-1](https://github.com/nus-cs2113-AY2324S1/tp/pull/19#discussion_r1379823357)
\ No newline at end of file
diff --git a/src/main/java/seedu/cafectrl/CafeCtrl.java b/src/main/java/seedu/cafectrl/CafeCtrl.java
index bd18c8ebbe..da399ecd72 100644
--- a/src/main/java/seedu/cafectrl/CafeCtrl.java
+++ b/src/main/java/seedu/cafectrl/CafeCtrl.java
@@ -23,26 +23,25 @@
*/
public class CafeCtrl {
- private static Logger logger = Logger.getLogger(CafeCtrl.class.getName());
+ private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
private final Ui ui;
- private Menu menu;
+ private final Storage storage;
+ private final Pantry pantry;
+ private final Menu menu;
+ private final Sales sales;
+ private final CurrentDate currentDate;
+
private Command command;
- private Pantry pantry;
- private Sales sales;
- private CurrentDate currentDate;
- private Storage storage;
/**
* Private constructor for the CafeCtrl class, used for initializing the user interface and menu list.
*/
-
private CafeCtrl() {
initLogger();
this.ui = new Ui();
this.storage = new Storage(this.ui);
- this.sales = new Sales();
- this.menu = this.storage.loadMenu();
this.pantry = this.storage.loadPantryStock();
+ this.menu = this.storage.loadMenu();
this.sales = this.storage.loadOrderList(menu);
this.currentDate = new CurrentDate(sales);
@@ -59,6 +58,7 @@ private CafeCtrl() {
private void run() {
ui.showWelcome();
ui.printLine();
+
do {
try {
String fullUserInput = ui.receiveUserInput();
@@ -82,8 +82,9 @@ private void initLogger() {
logger.setUseParentHandlers(false);
try {
FileHandler fileHandler = new FileHandler("cafeCtrl.log");
- logger.addHandler(fileHandler);
SimpleFormatter formatter = new SimpleFormatter();
+
+ logger.addHandler(fileHandler);
fileHandler.setFormatter(formatter);
} catch (IOException e) {
e.printStackTrace();
@@ -94,6 +95,4 @@ public static void main(String[] args) {
CafeCtrl cafeCtrl = new CafeCtrl();
cafeCtrl.run();
}
-
}
-
diff --git a/src/main/java/seedu/cafectrl/command/BuyIngredientCommand.java b/src/main/java/seedu/cafectrl/command/BuyIngredientCommand.java
index 542e9032c5..f370c27b7f 100644
--- a/src/main/java/seedu/cafectrl/command/BuyIngredientCommand.java
+++ b/src/main/java/seedu/cafectrl/command/BuyIngredientCommand.java
@@ -90,8 +90,8 @@ private void buildBuyIngredientMessage(Ingredient ingredient) {
}
ingredientsToBePrinted.add(ingredient);
ingredientString += "Ingredient: " + ingredient.getName()
- + "\t\tQty: " + ingredient.getQty()
- + ingredient.getUnit() + "\n";
+ + "\nQty: " + ingredient.getQty()
+ + ingredient.getUnit() + "\n\n";
}
}
diff --git a/src/main/java/seedu/cafectrl/command/EditPriceCommand.java b/src/main/java/seedu/cafectrl/command/EditPriceCommand.java
index 6f72ac318a..c014e7cfa3 100644
--- a/src/main/java/seedu/cafectrl/command/EditPriceCommand.java
+++ b/src/main/java/seedu/cafectrl/command/EditPriceCommand.java
@@ -18,7 +18,7 @@ public class EditPriceCommand extends Command {
+ "edit_price dish/DISH_INDEX price/NEW_PRICE\n"
+ "Example: edit_price dish/1 price/4.50";
- private static Logger logger = Logger.getLogger(CafeCtrl.class.getName());
+ private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
protected Menu menu;
protected Ui ui;
private final int menuID;
diff --git a/src/main/java/seedu/cafectrl/command/HelpCommand.java b/src/main/java/seedu/cafectrl/command/HelpCommand.java
index 45d2d98d83..6f18624888 100644
--- a/src/main/java/seedu/cafectrl/command/HelpCommand.java
+++ b/src/main/java/seedu/cafectrl/command/HelpCommand.java
@@ -11,10 +11,9 @@
*/
public class HelpCommand extends Command {
public static final String COMMAND_WORD = "help";
- public static final String MESSAGE_USAGE = "To view all commands:\n"
- + COMMAND_WORD;
+ public static final String MESSAGE_USAGE = "To view all commands:\n" + COMMAND_WORD;
- private static Logger logger = Logger.getLogger(CafeCtrl.class.getName());
+ private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
protected Ui ui;
@@ -28,6 +27,7 @@ public HelpCommand(Ui ui) {
@Override
public void execute() {
logger.info("Executing HelpCommand...");
+
ui.printLine();
ui.showHelp();
}
diff --git a/src/main/java/seedu/cafectrl/command/ListSaleByDayCommand.java b/src/main/java/seedu/cafectrl/command/ListSaleByDayCommand.java
index 70f20a778f..2335589404 100644
--- a/src/main/java/seedu/cafectrl/command/ListSaleByDayCommand.java
+++ b/src/main/java/seedu/cafectrl/command/ListSaleByDayCommand.java
@@ -32,7 +32,7 @@ public ListSaleByDayCommand(int day, Ui ui, Sales sales, Menu menu) {
public void execute() {
logger.info("Executing ShowSalesByDayCommand...");
try {
- sales.printSaleByDay(ui, menu, day);
+ sales.printSaleByDay(ui, day);
} catch (Exception e) {
ui.showToUser(ErrorMessages.INVALID_SALE_DAY);
}
diff --git a/src/main/java/seedu/cafectrl/command/ListTotalSalesCommand.java b/src/main/java/seedu/cafectrl/command/ListTotalSalesCommand.java
index 6a28b5a60f..e402e8073a 100644
--- a/src/main/java/seedu/cafectrl/command/ListTotalSalesCommand.java
+++ b/src/main/java/seedu/cafectrl/command/ListTotalSalesCommand.java
@@ -24,6 +24,6 @@ public ListTotalSalesCommand(Sales sales, Ui ui, Menu menu) {
@Override
public void execute() {
logger.info("Executing ShowSalesCommand...");
- sales.printSales(ui, menu);
+ sales.printSales(ui);
}
}
diff --git a/src/main/java/seedu/cafectrl/data/Chef.java b/src/main/java/seedu/cafectrl/data/Chef.java
index 1a3c6f6393..7f00f122f6 100644
--- a/src/main/java/seedu/cafectrl/data/Chef.java
+++ b/src/main/java/seedu/cafectrl/data/Chef.java
@@ -3,19 +3,15 @@
import seedu.cafectrl.CafeCtrl;
import seedu.cafectrl.ui.Ui;
-import java.text.DecimalFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Chef {
- private static Logger logger = Logger.getLogger(CafeCtrl.class.getName());
+ private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
private final Order order;
private final Pantry pantry;
private final Ui ui;
- private Menu menu;
- private final DecimalFormat dollarValue = new DecimalFormat("0.00");
-
public Chef(Order order, Pantry pantry, Ui ui) {
this.order = order;
@@ -28,9 +24,11 @@ public void cookDish() {
try {
if (!order.getIsComplete()) {
ui.showChefMessage();
+
boolean isComplete = pantry.isDishCooked(order.getIngredientList());
- logger.info("Dish cooked: " + isComplete);
order.setComplete(isComplete);
+
+ logger.info("Dish cooked: " + isComplete);
}
} catch (Exception e) {
logger.log(Level.WARNING, "Unsuccessful order: " + e.getMessage(), e);
diff --git a/src/main/java/seedu/cafectrl/data/CurrentDate.java b/src/main/java/seedu/cafectrl/data/CurrentDate.java
index 654f4db0b4..3a0f502233 100644
--- a/src/main/java/seedu/cafectrl/data/CurrentDate.java
+++ b/src/main/java/seedu/cafectrl/data/CurrentDate.java
@@ -3,24 +3,28 @@
import java.util.ArrayList;
public class CurrentDate {
+ private static final int MIN_ORDER_LIST_SIZE = 0;
+ private static final int DAY_BASE_NUMBER = 0;
+ private static final int DAY_OFFSET = 1;
+ private static final int ORDER_LIST_SIZE_OFFSET = 1;
private int currentDay;
public CurrentDate() {
- currentDay = 0;
+ currentDay = DAY_BASE_NUMBER;
}
public CurrentDate(int day) {
- currentDay = day - 1;
+ currentDay = day - DAY_OFFSET;
}
public CurrentDate(Sales sales) {
setDate(sales);
}
public void nextDay() {
- currentDay += 1;
+ currentDay += DAY_OFFSET;
}
public void previousDay() {
- currentDay -= 1;
+ currentDay -= DAY_OFFSET;
}
public int getCurrentDay() {
@@ -30,15 +34,16 @@ public int getCurrentDay() {
/**
* Sets the current date to the latest date the user left off
*
- * @param sales Used to access the number of orderlist created
+ * @param sales Used to access the number of order list created
*/
public void setDate(Sales sales) {
ArrayList orderLists = sales.getOrderLists();
int orderListsSize = orderLists.size();
- if (orderListsSize > 0) {
- currentDay = orderListsSize - 1;
+
+ if (orderListsSize > MIN_ORDER_LIST_SIZE) {
+ currentDay = orderListsSize - ORDER_LIST_SIZE_OFFSET;
} else {
- currentDay = 0;
+ currentDay = DAY_BASE_NUMBER;
}
}
}
diff --git a/src/main/java/seedu/cafectrl/data/Menu.java b/src/main/java/seedu/cafectrl/data/Menu.java
index 3fd6d9e9cf..c6c9e90fd7 100644
--- a/src/main/java/seedu/cafectrl/data/Menu.java
+++ b/src/main/java/seedu/cafectrl/data/Menu.java
@@ -8,7 +8,7 @@
import java.util.logging.Logger;
public class Menu {
- private static Logger logger = Logger.getLogger(CafeCtrl.class.getName());
+ private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
private ArrayList menuItems;
public Menu() {
@@ -22,9 +22,11 @@ public Menu(ArrayList menuItems) {
public ArrayList getMenuItemsList() {
return menuItems;
}
+
public int getSize() {
return menuItems.size();
}
+
public Dish getDishFromId(int menuID) {
return menuItems.get(menuID);
}
@@ -39,25 +41,13 @@ public Dish getDishFromName(String dishName) {
String formattedDishName = dishName.toLowerCase().trim();
for (int i = 0; i < getSize(); i++) {
String menuDishName = getDishFromId(i).getName();
- String formattedMenuDishName = menuDishName.toLowerCase().trim();
- if (formattedMenuDishName.equals(formattedDishName)){
+ String formattedMenuDishName = menuDishName.trim();
+ if (formattedMenuDishName.equalsIgnoreCase(formattedDishName)) {
return getDishFromId(i);
}
}
return null;
}
- public void removeDish(int menuID) {
- menuItems.remove(menuID);
- }
- public void addDish(Dish dish) {
- menuItems.add(dish);
- }
-
- public boolean isValidDishIndex(int dishIndex) {
- logger.info("Checking if dish index " + dishIndex + " is valid...");
- int offSetDishIndex = dishIndex - Ui.OFFSET_LIST_INDEX;
- return offSetDishIndex >= 0 && offSetDishIndex < this.getSize();
- }
//@@author NaychiMin
/**
@@ -76,4 +66,26 @@ public ArrayList getAggregatedOrders() {
}
return aggregatedOrders;
}
+
+ //@@author ziyi105
+ /**
+ * Checks whether the dish index can be found in the menu
+ *
+ * @param dishIndex dish index to be checked
+ * @return true if it is valid, false otherwise
+ */
+ public boolean isValidDishIndex(int dishIndex) {
+ logger.info("Checking if dish index " + dishIndex + " is valid...");
+
+ int offSetDishIndex = dishIndex - Ui.OFFSET_LIST_INDEX;
+ return offSetDishIndex >= 0 && offSetDishIndex < this.getSize();
+ }
+
+ //@@author DextheChik3n
+ public void removeDish(int menuID) {
+ menuItems.remove(menuID);
+ }
+ public void addDish(Dish dish) {
+ menuItems.add(dish);
+ }
}
diff --git a/src/main/java/seedu/cafectrl/data/Order.java b/src/main/java/seedu/cafectrl/data/Order.java
index 6d8250ccfb..3904bd0400 100644
--- a/src/main/java/seedu/cafectrl/data/Order.java
+++ b/src/main/java/seedu/cafectrl/data/Order.java
@@ -11,19 +11,19 @@ public class Order {
private final Dish orderedDish;
private int dishQty;
private final ArrayList ingredientList;
- private boolean isComplete = false;
private float totalOrderCost;
+ private boolean isComplete = false;
public Order(Dish orderedDish, int dishQty) {
- this.dishQty = dishQty;
this.orderedDish = orderedDish;
+ this.dishQty = dishQty;
this.ingredientList = setIngredientList();
this.totalOrderCost = calculateTotalOrderCost();
}
public Order(Dish orderedDish, int dishQty, float orderCost, boolean isComplete) {
- this.dishQty = dishQty;
this.orderedDish = orderedDish;
+ this.dishQty = dishQty;
this.ingredientList = setIngredientList();
this.totalOrderCost = orderCost;
this.isComplete = isComplete;
@@ -59,6 +59,7 @@ private ArrayList setIngredientList() {
String ingredientName = ingredient.getName();
int ingredientQty = ingredient.getQty() * dishQty;
String ingredientUnit = ingredient.getUnit();
+
dishIngredient.add(new Ingredient(ingredientName, ingredientQty, ingredientUnit));
}
return dishIngredient;
diff --git a/src/main/java/seedu/cafectrl/data/OrderList.java b/src/main/java/seedu/cafectrl/data/OrderList.java
index 6be9faa622..20b338cc68 100644
--- a/src/main/java/seedu/cafectrl/data/OrderList.java
+++ b/src/main/java/seedu/cafectrl/data/OrderList.java
@@ -14,7 +14,7 @@
public class OrderList {
private static final DecimalFormat dollarValue = new DecimalFormat("0.00");
private static final String HEADER_FORMAT = "%-20s %-10s %-20s\n";
- private static Logger logger = Logger.getLogger(CafeCtrl.class.getName());
+ private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
private ArrayList orderList;
private float totalOrderListCost;
@@ -46,11 +46,16 @@ public void addCost(Order order) {
/**
* Prints the order list for a specific day, including dish names, quantities, and total cost prices.
*
- * @param menu The Menu object representing the cafe's menu.
*/
- public void printOrderList(Menu menu, Ui ui) {
+ public void printOrderList(Ui ui) {
logger.info("Printing order list...");
- ArrayList aggregatedOrders = menu.getAggregatedOrders();
+
+ if (orderList.isEmpty() || !hasCompletedOrders()) {
+ ui.showToUser("No sales for this day.");
+ return;
+ }
+
+ ArrayList aggregatedOrders = new ArrayList<>();
for (Order order : orderList) {
aggregateOrder(order, aggregatedOrders);
@@ -74,20 +79,29 @@ public void printOrderList(Menu menu, Ui ui) {
/**
* Aggregates orders by updating quantities and total order costs for the same dish.
*
- * @param order The Order object to be aggregated.
+ * @param order The Order object to be aggregated.
* @param aggregatedOrders The ArrayList of aggregated orders.
*/
private void aggregateOrder(Order order, ArrayList aggregatedOrders) {
logger.info("Aggregating order...");
+
if (order.getIsComplete()) {
int index = getIndexByDishName(aggregatedOrders, order.getDishName());
- aggregatedOrders.get(index)
- .setQuantity(aggregatedOrders.get(index).getQuantity() + order.getQuantity());
- aggregatedOrders.get(index)
- .setTotalOrderCost(aggregatedOrders.get(index).getTotalOrderCost() + order.getTotalOrderCost());
+ //if dish is not found in aggregated orders, add the dish into it
+ if (index == -1) {
+ aggregatedOrders.add(new Order(order.getOrderedDish(), order.getQuantity(), order.getTotalOrderCost(),
+ true));
+ } else {
+ //else add the quantities and totalCost accordingly
+ aggregatedOrders.get(index)
+ .setQuantity(aggregatedOrders.get(index).getQuantity() + order.getQuantity());
+ aggregatedOrders.get(index)
+ .setTotalOrderCost(aggregatedOrders.get(index).getTotalOrderCost() + order.getTotalOrderCost());
+ }
}
}
+ //@@author Shanice Tang
/**
* Finds the index of an order in the aggregated orders list based on the dish name.
*
@@ -100,12 +114,14 @@ private int getIndexByDishName(ArrayList aggregatedOrders, String dishNam
Order order = aggregatedOrders.get(i);
String orderDishName = order.getDishName().trim();
dishName = dishName.trim();
+
if (orderDishName.equalsIgnoreCase(dishName)) {
return i;
}
}
return -1;
}
+ //@@author
/**
* Calculates the total cost of all orders for a specific day.
@@ -116,6 +132,7 @@ private int getIndexByDishName(ArrayList aggregatedOrders, String dishNam
private float calculateTotalCost(ArrayList orders) {
logger.info("Calculating total cost...");
float totalCost = 0;
+
for (Order order : orders) {
totalCost += order.getTotalOrderCost();
logger.info("Total cost: " + totalCost);
diff --git a/src/main/java/seedu/cafectrl/data/Pantry.java b/src/main/java/seedu/cafectrl/data/Pantry.java
index 0ba78c86b2..f32324d67c 100644
--- a/src/main/java/seedu/cafectrl/data/Pantry.java
+++ b/src/main/java/seedu/cafectrl/data/Pantry.java
@@ -12,9 +12,10 @@
public class Pantry {
public static final int DEFAULT_ORDER_QTY = 1;
- private static Logger logger = Logger.getLogger(CafeCtrl.class.getName());
+ private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
+
+ private final Ui ui;
private ArrayList pantryStock;
- private Ui ui;
//@@author NaychiMin
public Pantry(Ui ui, ArrayList pantryStock) {
@@ -71,6 +72,7 @@ public Ingredient addIngredientToStock (String name, int qty, String unit) {
*/
private Ingredient addIngredientQuantity(int qty, int ingredientIndex, String unit) {
Ingredient ingredient = pantryStock.get(ingredientIndex);
+
if (!unit.equalsIgnoreCase(ingredient.getUnit())) {
logger.warning("Unit does not match previous unit");
throw new RuntimeException(ingredient.getName()
@@ -81,6 +83,7 @@ private Ingredient addIngredientQuantity(int qty, int ingredientIndex, String un
qty += ingredient.getQty(); //adds new qty to current qty
ingredient.setQty(qty);
logger.info("New quantity: " + qty);
+
return ingredient;
}
@@ -93,6 +96,7 @@ private Ingredient addIngredientQuantity(int qty, int ingredientIndex, String un
private int getIndexOfIngredient(String name) {
for (int i = 0; i < pantryStock.size(); i++) {
String ingredientName = pantryStock.get(i).getName().trim();
+
if (name.equalsIgnoreCase(ingredientName)) {
return i;
}
@@ -108,6 +112,7 @@ private int getIndexOfIngredient(String name) {
*/
public boolean isDishCooked(ArrayList dishIngredients) {
logger.info("Checking if dish can be cooked");
+
//for each ingredient that is used in the dish, update the stock of ingredient left.
for (Ingredient dishIngredient : dishIngredients) {
Ingredient usedIngredientFromStock = getIngredient(dishIngredient);
@@ -119,6 +124,7 @@ public boolean isDishCooked(ArrayList dishIngredients) {
int stockQuantity = usedIngredientFromStock.getQty();
int usedQuantity = dishIngredient.getQty();
int finalQuantity = stockQuantity - usedQuantity;
+
if (finalQuantity < 0) {
return false;
}
@@ -148,11 +154,13 @@ private Ingredient getIngredient(Ingredient dishIngredient) {
public void calculateDishAvailability(Menu menu, Order order) {
logger.info("Calculating dish availability...");
int menuSize = menu.getSize();
+
for (int i = 0; i < menuSize; i++) {
Dish dish = menu.getDishFromId(i);
ui.showToUser("Dish: " + dish.getName());
int numberOfDishes = calculateMaxDishes(dish, menu, order);
ui.showDishAvailability(numberOfDishes);
+
if (i != menuSize - 1) {
ui.printLine();
}
@@ -167,8 +175,9 @@ public void calculateDishAvailability(Menu menu, Order order) {
public int calculateMaxDishes(Dish dish, Menu menu, Order order) {
logger.info("Calculating max number of dishes possible...");
int maxNumofDish = Integer.MAX_VALUE;
- ArrayList dishIngredients = retrieveIngredientsForDish(dish.getName(), menu);
boolean isRestockHeaderDisplayed = false;
+ ArrayList dishIngredients = retrieveIngredientsForDish(dish.getName(), menu);
+
for (Ingredient dishIngredient : dishIngredients) {
int numOfDish = calculateMaxDishForEachIngredient(dishIngredient);
maxNumofDish = Math.min(numOfDish, maxNumofDish);
@@ -196,6 +205,7 @@ private boolean showRestockHeaderIfNeeded(boolean isRestockHeaderDisplayed) {
private void handleIncompleteDishCase(Ingredient dishIngredient, Order order, int numOfDish) {
int orderQuantity = order.getQuantity();
+
if (numOfDish < orderQuantity) {
handleRestock(dishIngredient, orderQuantity);
}
@@ -215,6 +225,7 @@ private void handleZeroDishCase(Ingredient dishIngredient, int numOfDish) {
private int calculateMaxDishForEachIngredient(Ingredient dishIngredient) {
logger.info("Calculating max dish for each ingredient...");
Ingredient usedIngredientFromStock = getIngredient(dishIngredient);
+
if (usedIngredientFromStock == null) {
return 0;
}
@@ -258,5 +269,3 @@ public ArrayList retrieveIngredientsForDish(String orderedDish, Menu
return dishIngredients;
}
}
-
-
diff --git a/src/main/java/seedu/cafectrl/data/Sales.java b/src/main/java/seedu/cafectrl/data/Sales.java
index c6cc37a096..4c8e310ffd 100644
--- a/src/main/java/seedu/cafectrl/data/Sales.java
+++ b/src/main/java/seedu/cafectrl/data/Sales.java
@@ -25,13 +25,13 @@ public Sales() {
public Sales(ArrayList orderLists) {
this.orderLists = orderLists;
- this.daysAccounted = orderLists.size() - 1;
+ this.daysAccounted = orderLists.size() - DAY_DISPLAY_OFFSET;
}
public Sales(OrderList orderList) {
this.orderLists = new ArrayList<>();
orderLists.add(orderList);
- this.daysAccounted = orderLists.size() - 1;
+ this.daysAccounted = orderLists.size() - DAY_DISPLAY_OFFSET;
}
public void addOrderList(OrderList orderList) {
@@ -39,7 +39,7 @@ public void addOrderList(OrderList orderList) {
}
public void nextDay() {
- this.daysAccounted += 1;
+ this.daysAccounted += DAY_DISPLAY_OFFSET;
}
public int getDaysAccounted() {
@@ -59,9 +59,8 @@ public OrderList getOrderList(int index) {
* Prints all sales data, organized by day, including dish names, quantities, and total cost prices.
*
* @param ui The Ui object for user interface interactions.
- * @param menu The Menu object representing the cafe's menu.
*/
- public void printSales(Ui ui, Menu menu) {
+ public void printSales(Ui ui) {
if(isOrderListsEmpty()) {
logger.info("Printing empty sales...");
ui.showToUser("No sales made.");
@@ -78,7 +77,7 @@ public void printSales(Ui ui, Menu menu) {
}
ui.showSalesTop(day + DAY_DISPLAY_OFFSET);
- orderList.printOrderList(menu, ui);
+ orderList.printOrderList(ui);
}
}
@@ -86,21 +85,20 @@ public void printSales(Ui ui, Menu menu) {
* Prints sales data for a specific day, including dish names, quantities, and total cost prices.
*
* @param ui The Ui object for user interface interactions.
- * @param menu The Menu object representing the cafe's menu.
* @param day The day for which sales data is to be printed.
*/
- public void printSaleByDay(Ui ui, Menu menu, int day) {
+ public void printSaleByDay(Ui ui, int day) {
logger.info("Printing sales by day...");
- int orderListIndex = day - 1;
+ int orderListIndex = day - DAY_DISPLAY_OFFSET;
try {
OrderList orderList = orderLists.get(orderListIndex);
if (orderList.isEmpty() || !orderList.hasCompletedOrders()) {
ui.showToUser("No sales for this day.");
return;
}
- ui.showSalesTop(day);
- orderList.printOrderList(menu, ui);
+ ui.showSalesTop(day);
+ orderList.printOrderList(ui);
} catch (Exception e) {
logger.log(Level.WARNING, "Unable to print sales for day " + day + "\n" + e.getMessage(), e);
ui.showToUser(ErrorMessages.INVALID_SALE_DAY);
@@ -115,5 +113,4 @@ public boolean isOrderListsEmpty() {
}
return true;
}
- //@@author
}
diff --git a/src/main/java/seedu/cafectrl/data/dish/Dish.java b/src/main/java/seedu/cafectrl/data/dish/Dish.java
index cf4c3c01a6..3921eaa5a3 100644
--- a/src/main/java/seedu/cafectrl/data/dish/Dish.java
+++ b/src/main/java/seedu/cafectrl/data/dish/Dish.java
@@ -4,11 +4,12 @@
import java.text.DecimalFormat;
public class Dish {
- private String name;
- private ArrayList ingredients;
- private float price;
private final DecimalFormat dollarValue = new DecimalFormat("0.00");
+ private final String name;
+ private final ArrayList ingredients;
+ private float price;
+
public Dish(String name, ArrayList ingredients, float price) {
this.name = name;
this.ingredients = ingredients;
@@ -39,12 +40,12 @@ public void setPrice(float newPrice) {
this.price = Math.abs(newPrice);
}
+ //@@author ziyi105
@Override
public String toString() {
return this.name + " $" + this.dollarValue.format(this.price);
}
- //@@author ziyi105
/**
* Compare the original price and new price
* @param otherPrice price value to be compared with
@@ -53,6 +54,7 @@ public String toString() {
public int comparePrice(float otherPrice) {
String formattedPrice = this.dollarValue.format(price);
String formattedNewPrice = this.dollarValue.format(otherPrice);
+
return formattedPrice.compareTo(formattedNewPrice);
}
}
diff --git a/src/main/java/seedu/cafectrl/data/dish/Ingredient.java b/src/main/java/seedu/cafectrl/data/dish/Ingredient.java
index a25b3b27c4..c6bbfddef1 100644
--- a/src/main/java/seedu/cafectrl/data/dish/Ingredient.java
+++ b/src/main/java/seedu/cafectrl/data/dish/Ingredient.java
@@ -1,20 +1,20 @@
package seedu.cafectrl.data.dish;
public class Ingredient {
- private String name;
+ private final String name;
+ private final String unit;
private int qty;
- private String unit;
public Ingredient(String name) {
this.name = name;
- this.qty = 0;
this.unit = null;
+ this.qty = 0;
}
public Ingredient(String name, int qty, String unit) {
this.name = name;
- this.qty = qty;
this.unit = unit;
+ this.qty = qty;
}
public String getName() {
@@ -38,8 +38,18 @@ public String toString() {
return name + " - " + qty + unit;
}
+ /**
+ * Compare the name of this ingredient to the other ingredient
+ *
+ * @param obj the other ingredient to be compared with
+ * @return true if they have the same name, false otherwise
+ */
@Override
public boolean equals(Object obj) {
- return this.toString().equals(obj.toString());
+ if (obj instanceof Ingredient) {
+ String otherName = ((Ingredient) obj).name;
+ return this.name.equals(otherName);
+ }
+ return false;
}
}
diff --git a/src/main/java/seedu/cafectrl/parser/Parser.java b/src/main/java/seedu/cafectrl/parser/Parser.java
index 09427e8f75..137d4fea0e 100644
--- a/src/main/java/seedu/cafectrl/parser/Parser.java
+++ b/src/main/java/seedu/cafectrl/parser/Parser.java
@@ -161,7 +161,6 @@ public Command parseCommand(Menu menu, String userInput, Ui ui,
}
}
- //All prepareCommand Classes
//@@author Cazh1
/**
* Prepares the ListMenuCommand
@@ -177,6 +176,7 @@ private static Command prepareListMenu(Menu menu, Ui ui) {
//@@author ziyi105
/**
* Parse argument in the context of edit price command
+ *
* @param menu menu of the current session
* @param arguments string that matches group arguments
* @return new EditDishCommand
@@ -229,7 +229,9 @@ private static Command prepareEditPriceCommand(Menu menu, String arguments, Ui u
//@@author DextheChik3n
/**
- * Parses the user input text into ingredients to form a Dish
that is added to the Menu
+ * Parses the user input text into ingredients to form a Dish
+ * that is added to the Menu
+ *
* @param arguments string that matches group arguments
* @param menu Menu of the current session
* @param ui Ui of the current session
@@ -309,7 +311,8 @@ private static void detectErrorPostDishNameParse(String dishName, Menu menu) thr
/**
* Parses the user's input text ingredients.
*
- * @param ingredientsListString user's input string of ingredients, multiple ingredients seperated by ',' is allowed
+ * @param ingredientsListString user's input string of ingredients,
+ * multiple ingredients seperated by ',' is allowed
* @param menu
* @return list of ingredients that consists of the dish
* @throws ParserException if the input string does not match the constraints
@@ -337,23 +340,27 @@ private static ArrayList parseIngredients(
}
private static void parseIngredient(
- boolean isExcludeRepeatedIngredients, Menu menu, String inputIngredient, ArrayList ingredients)
+ boolean isExcludeRepeatedIngredients, Menu menu,
+ String inputIngredient, ArrayList ingredients)
throws ParserException {
Matcher ingredientMatcher = detectErrorPreIngredientParse(inputIngredient);
String ingredientName = ingredientMatcher.group(INGREDIENT_NAME_REGEX_GROUP_LABEL).trim();
+
//ingredientQtyString contains the input text after the "qty/" argument
String ingredientQtyString = ingredientMatcher.group(INGREDIENT_QTY_REGEX_GROUP_LABEL).trim();
//check the formatting of text after ingredient qty argument (qty/)
final Pattern ingredientQtyFormatPattern = Pattern.compile(INGREDIENT_QTY_FORMAT_REGEX);
Matcher ingredientQtyMatcher = ingredientQtyFormatPattern.matcher(ingredientQtyString);
+
if (!ingredientQtyMatcher.matches()) {
throw new ParserException(ErrorMessages.INVALID_INGREDIENT_QTY_FORMAT);
}
String ingredientUnit = ingredientQtyMatcher.group(INGREDIENT_QTY_UNIT_REGEX_GROUP_LABEL);
- int ingredientQty = Integer.parseInt(ingredientQtyMatcher.group(INGREDIENT_QTY_VALUE_REGEX_GROUP_LABEL));
+ int ingredientQty = Integer.parseInt(ingredientQtyMatcher
+ .group(INGREDIENT_QTY_VALUE_REGEX_GROUP_LABEL));
detectErrorPostIngredientParse(isExcludeRepeatedIngredients,
ingredientName, ingredientQty, ingredientUnit, ingredients);
@@ -365,7 +372,8 @@ private static void parseIngredient(
ingredients.add(ingredient);
}
- private static Matcher detectErrorPreIngredientParse(String inputIngredient) throws ParserException {
+ private static Matcher detectErrorPreIngredientParse(String inputIngredient)
+ throws ParserException {
if (isRepeatedArgument(inputIngredient, INGREDIENT_ARGUMENT)) {
logger.log(Level.WARNING, "Repeated ingredient/ argument!");
throw new ParserException(ErrorMessages.REPEATED_INGREDIENT_ARGUMENT);
@@ -420,6 +428,7 @@ private static void detectErrorPostIngredientParse(
/**
* Converts text of price to float while also checking if the price input is within reasonable range
+ *
* @param priceText text input for price argument
* @return price in float format
* @throws ParserException if price is not within reasonable format and range
@@ -463,6 +472,7 @@ public static float parsePriceToFloat(String priceText) throws ParserException {
/**
* Checks in the menu if the dish name already exists.
+ *
* @param inputDishName dish name entered by the user
* @param menu contains all the existing Dishes
* @return true if dish name already exists in menu, false otherwise
@@ -486,6 +496,7 @@ public static boolean isRepeatedDishName(String inputDishName, Menu menu) throws
/**
* Checks in the ingredient list if the ingredient name already exists.
+ *
* @param inputName dish name entered by the user
* @param ingredients contains all the existing Ingredients
* @return true if ingredient name already exists in menu, false otherwise
@@ -511,6 +522,7 @@ public static boolean isRepeatedIngredientName(String inputName, ArrayList 1 match of the argument, false otherwise
@@ -552,17 +565,18 @@ public static boolean isRepeatedArgument(String inputText, String argument) {
//@@author NaychiMin
/**
- * Parses arguments in the context of the ListIngredient command.
- * @param menu menu of the current session
- * @param arguments string that matches group arguments
- * @return the prepared command
+ * Parses arguments in the context of the ListIngredient command.
+ *
+ * @param menu menu of the current session
+ * @param arguments string that matches group arguments
+ * @return the prepared command
*/
private static Command prepareListIngredient(Menu menu, String arguments, Ui ui) {
final Pattern prepareListPattern = Pattern.compile(LIST_INGREDIENTS_ARGUMENT_STRING);
Matcher matcher = prepareListPattern.matcher(arguments.trim());
if (!matcher.matches()) {
- logger.warning("Unmatching regex!");
+ logger.warning("Unmatched regex!");
return new IncorrectCommand(ErrorMessages.MISSING_ARGUMENT_FOR_LIST_INGREDIENTS
+ ListIngredientCommand.MESSAGE_USAGE, ui);
}
@@ -598,7 +612,7 @@ private static Command prepareDelete(Menu menu, String arguments, Ui ui) {
// Checks whether the overall pattern of delete price arguments is correct
if (!matcher.matches()) {
- logger.warning("Unmatching regex!");
+ logger.warning("Unmatched regex!");
return new IncorrectCommand(ErrorMessages.MISSING_ARGUMENT_FOR_DELETE, ui);
}
@@ -612,16 +626,32 @@ private static Command prepareDelete(Menu menu, String arguments, Ui ui) {
return new DeleteDishCommand(dishIndex, menu, ui);
}
+ /**
+ * Prepares a command to view the total stock in the pantry.
+ *
+ * @param ui The user interface to interact with the user.
+ * @param pantry The pantry containing ingredient stock information.
+ * @return A command to view the total stock.
+ */
private static Command prepareViewTotalStock(Ui ui, Pantry pantry) {
return new ViewTotalStockCommand(pantry, ui);
}
+ /**
+ * Prepares a command to buy ingredients based on the provided arguments.
+ *
+ * @param arguments The user input arguments for buying ingredients.
+ * @param ui The user interface to interact with the user.
+ * @param pantry The pantry to update with bought ingredients.
+ * @param menu The menu containing information about available dishes.
+ * @return A command to buy ingredients or an incorrect command if arguments are invalid.
+ */
private static Command prepareBuyIngredient(String arguments, Ui ui, Pantry pantry, Menu menu) {
Pattern buyIngredientArgumentsPattern = Pattern.compile(BUY_INGREDIENT_ARGUMENT_STRING);
Matcher matcher = buyIngredientArgumentsPattern.matcher(arguments.trim());
if (!matcher.matches()) {
- logger.warning("Unmatching regex!");
+ logger.warning("Unmatched regex!");
return new IncorrectCommand(ErrorMessages.INVALID_ARGUMENT_FOR_BUY_INGREDIENT
+ BuyIngredientCommand.MESSAGE_USAGE, ui);
}
@@ -648,9 +678,17 @@ public static boolean isInvalidQty(int ingredientQty) {
return ingredientQty < MIN_QTY || ingredientQty > MAX_QTY;
}
+ /**
+ * Checks for mismatched units between a new ingredient and existing ingredients in the menu.
+ *
+ * @param menu The menu containing information about available dishes.
+ * @param newIngredient The new ingredient to check for mismatched units.
+ * @throws ParserException If a mismatch in units is detected.
+ */
public static void checkForMismatchUnit(Menu menu, Ingredient newIngredient) throws ParserException {
logger.info("Checking for mismatched units...");
ArrayList dishArrayList = menu.getMenuItemsList();
+
for (Dish dish : dishArrayList) {
traverseIngredientsOfDish(newIngredient, dish);
}
@@ -658,6 +696,7 @@ public static void checkForMismatchUnit(Menu menu, Ingredient newIngredient) thr
private static void traverseIngredientsOfDish(Ingredient newIngredient, Dish dish) throws ParserException {
ArrayList ingredientArrayList = dish.getIngredients();
+
for (Ingredient currentIngredient : ingredientArrayList) {
logger.info("Comparing name: " + newIngredient.getName() + " and " + currentIngredient.getName());
compareIngredientName(newIngredient, currentIngredient);
@@ -685,6 +724,7 @@ private static void compareUnits(Ingredient newIngredient, Ingredient currentIng
//@@author ziyi105
/**
* Check whether a text contains special character
+ *
* @param text text to be checked
* @return true if it contains special character, false otherwise
*/
diff --git a/src/main/java/seedu/cafectrl/storage/Decoder.java b/src/main/java/seedu/cafectrl/storage/Decoder.java
index 619580062d..131dc36a82 100644
--- a/src/main/java/seedu/cafectrl/storage/Decoder.java
+++ b/src/main/java/seedu/cafectrl/storage/Decoder.java
@@ -41,17 +41,26 @@ public class Decoder {
public static Menu decodeMenuData(ArrayList textLines) {
logger.info("Decoding menu.txt to Menu...");
ArrayList menuDishList = new ArrayList<>();
+
for(String dishString : textLines) {
logger.info("Line to decode: " + dishString);
decodeDishString(dishString, menuDishList);
}
+
return new Menu(menuDishList);
}
+ /**
+ * Decodes a string representation of a dish and adds it to the menu's list of dishes.
+ *
+ * @param dishString The string containing dish information.
+ * @param menuDishList The list to which the decoded dish will be added.
+ */
private static void decodeDishString(String dishString, ArrayList menuDishList) {
try {
String[] dishStringArray = dishString.split(DIVIDER);
String dishName = dishStringArray[0].trim();
+ checkNameValidity(dishName);
float dishPrice = Float.parseFloat(dishStringArray[1]);
String[] ingredientStringArray = Arrays.copyOfRange(dishStringArray, 2, dishStringArray.length);
ArrayList ingredientsList = decodeIngredientData(ingredientStringArray);
@@ -62,6 +71,12 @@ private static void decodeDishString(String dishString, ArrayList menuDish
}
}
+ private static void checkNameValidity(String name) throws Exception {
+ if (Parser.isNameLengthInvalid(name) || name.isEmpty() || Parser.containsSpecialChar(name)) {
+ throw new Exception();
+ }
+ }
+
/**
* Decodes an array of strings representing ingredient data into a list of Ingredient objects.
*
@@ -74,7 +89,9 @@ private static ArrayList decodeIngredientData(String[] ingredientsSt
logger.info("Ingredient to decode: " + ingredientString);
String[] array = ingredientString.split(INGREDIENT_DIVIDER);
String name = array[0].trim();
+ checkNameValidity(name);
int qty = Integer.parseInt(array[1].trim());
+ checkQtyValidity(qty);
String unit = array[2].trim();
checkUnitValidity(unit);
ingredientList.add(new Ingredient(name, qty, unit));
@@ -82,16 +99,22 @@ private static ArrayList decodeIngredientData(String[] ingredientsSt
return ingredientList;
}
+ private static void checkQtyValidity(int qty) throws Exception {
+ if (Parser.isInvalidQty(qty)) {
+ throw new Exception();
+ }
+ }
+
private static void checkUnitValidity(String unit) throws Exception {
if (!Parser.isValidUnit(unit) || Parser.isEmptyUnit(unit)) {
throw new Exception();
}
}
- //@@author
//@@author ziyi105
/**
* Decodes raw string from pantry stock data file and create ingredient object from the data
+ *
* @param encodedPantryStock raw string from pantry stock data file
* @return a new pantry object with data from the pantry stock data file
*/
@@ -135,6 +158,7 @@ && isValidUnit(unit)) {
ui.showToUser(ErrorMessages.ERROR_IN_PANTRY_STOCK_DATA + encodedData);
}
}
+
return new Pantry(ui, pantryStock);
}
@@ -157,6 +181,7 @@ private static boolean isValidUnit(String unit) {
/**
* Checks whether the pantry stock is in the format of ingredient name | quantity (int) | unit
+ *
* @param decodedPantryStock string array of the raw data string from pantry stock data file
* split with "|"
* @return true if the format is correct, false otherwise
@@ -199,6 +224,7 @@ public static Sales decodeSales(ArrayList textLines, Menu menu) {
}
decodeSalesData(line, orderLists, menu);
}
+
if (orderLists.isEmpty()) {
return new Sales();
}
@@ -273,14 +299,12 @@ private static boolean isCompleteStatusAccurate(String orderLine, String complet
return false;
}
-
//@@author Cazh1
/**
* Increases the size of the orderlist when there is gap between the previous order and the next
*
* @param orderLists The current partially filled ArrayList of OrderList
* @param day The day of the next order
- * @return orderLists after filling in the gaps
*/
private static void fillOrderListSize(ArrayList orderLists, int day) {
while (orderLists.size() <= day) {
diff --git a/src/main/java/seedu/cafectrl/storage/Encoder.java b/src/main/java/seedu/cafectrl/storage/Encoder.java
index 89a2c8dd6d..17dc694d32 100644
--- a/src/main/java/seedu/cafectrl/storage/Encoder.java
+++ b/src/main/java/seedu/cafectrl/storage/Encoder.java
@@ -22,7 +22,7 @@ public class Encoder {
public static final String NULL_ORDER_DAY = "the last day has no orders but please account for it";
private static final String DIVIDER = " | ";
private static final String INGREDIENT_DIVIDER = " - ";
- private static Logger logger = Logger.getLogger(CafeCtrl.class.getName());
+ private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
//@@author Cazh1
/**
@@ -89,7 +89,8 @@ private static StringBuilder encodeIngredientList(ArrayList ingredie
//@@author ziyi105
/**
- * Encodes the pantry stock into format ingredient name | quantity | unit for storage.
+ * Encodes the pantry stock into format ingredient name | quantity | unit for storage
+ *
* @param pantry the pantry from current session
* @return an arrayList of string of ecoded pantry stock
*/
@@ -97,6 +98,7 @@ public static ArrayList encodePantryStock(Pantry pantry) {
// Convert pantry stock to a list of String
ArrayList pantryStockInString = new ArrayList<>();
ArrayList pantryStock = pantry.getPantryStock();
+
for (Ingredient ingredient : pantryStock) {
StringBuilder encodedIngredient = new StringBuilder();
encodedIngredient.append(ingredient.getName().trim());
@@ -127,11 +129,14 @@ public static ArrayList encodeSales(Sales sales) {
for (int day = 0; day < orderLists.size(); day++) {
logger.info("Encoding sales of day " + day);
+
//get orderList for each day from list of sales
OrderList orderList = sales.getOrderList(day);
+
//get order from each orderList obtained
for (Order order : orderList.getOrderList()) {
StringBuilder orderString = new StringBuilder();
+
//day of each orderList is index + 1
orderString.append((day + 1) + DIVIDER);
orderString.append(order.getDishName() + DIVIDER);
@@ -162,6 +167,7 @@ public static ArrayList encodeSales(Sales sales) {
private static ArrayList encodeLastSalesDay(ArrayList encodedList, OrderList orderList, int day) {
if (orderList.getSize() == 0) {
StringBuilder orderString = new StringBuilder();
+
//day of each orderList is index + 1
orderString.append((day + 1) + DIVIDER);
orderString.append(NULL_ORDER_DAY);
diff --git a/src/main/java/seedu/cafectrl/storage/Storage.java b/src/main/java/seedu/cafectrl/storage/Storage.java
index 3979aa8b26..4e9f8fee00 100644
--- a/src/main/java/seedu/cafectrl/storage/Storage.java
+++ b/src/main/java/seedu/cafectrl/storage/Storage.java
@@ -20,23 +20,23 @@
*/
public class Storage {
- private static Logger logger = Logger.getLogger(CafeCtrl.class.getName());
+ private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
protected FileManager fileManager;
protected Ui ui;
- private boolean isHashingEnabled = true;
+ private final boolean isHashingEnabled = true;
private boolean isMenuTampered = false;
private boolean isOrdersTampered = false;
private boolean isPantryStockTampered = false;
private boolean isHashStringTampered = false;
private boolean isTamperedMessagePrinted = false;
+
public Storage (Ui ui) {
this.fileManager = new FileManager(ui);
this.ui = ui;
}
//@@author Cazh1
-
private boolean isFileEmpty(ArrayList encodedStringArrayList) {
return encodedStringArrayList.isEmpty();
}
@@ -124,11 +124,14 @@ public Menu loadMenu() {
logger.log(Level.INFO, "Tampered Menu file");
detectTamper();
}
- return Decoder. decodeMenuData(encodedMenu);
+ return Decoder.decodeMenuData(encodedMenu);
} catch (FileNotFoundException e) {
logger.log(Level.WARNING, "menu.txt not found!\n" + e.getMessage(), e);
ui.showToUser(ErrorMessages.MENU_FILE_NOT_FOUND_MESSAGE, System.lineSeparator());
return new Menu();
+ } finally {
+ ui.showToUser(Messages.DONE_LOADING_MENU);
+ ui.printLine();
}
}
@@ -146,6 +149,7 @@ private void saveMenu(Menu menu) throws IOException {
//@@author ziyi105
/**
* Read and decode pantryStock data from text file and pass it to the menu
+ *
* @return pantryStock with data from the file
*/
public Pantry loadPantryStock() {
@@ -160,11 +164,15 @@ public Pantry loadPantryStock() {
} catch (FileNotFoundException e) {
ui.showToUser(ErrorMessages.PANTRY_FILE_NOT_FOUND_MESSAGE, System.lineSeparator());
return new Pantry(ui);
+ } finally {
+ ui.showToUser(Messages.DONE_LOADING_PANTRY_STOCK);
+ ui.printLine();
}
}
/**
* Encode and write the data from PantryStock to the text file
+ *
* @param pantry pantry from current session
* @throws IOException if the file is not found in the specified file path
*/
@@ -192,6 +200,9 @@ public Sales loadOrderList(Menu menu) {
logger.log(Level.WARNING, "orders.txt not found!\n" + e.getMessage(), e);
ui.showToUser(ErrorMessages.ORDER_LIST_FILE_NOT_FOUND_MESSAGE, System.lineSeparator());
return new Sales();
+ } finally {
+ ui.showToUser(Messages.DONE_LOADING_SALES);
+ ui.printLine();
}
}
@@ -209,6 +220,7 @@ private void saveOrderList(Sales sales) throws IOException {
//@@author ziyi105
/**
* Encode and write the data from menu, orderList and pantry to the respective text files
+ *
* @param menu menu from current session
* @param sales sale object from current session
* @param pantry pantry from current session
diff --git a/src/main/java/seedu/cafectrl/ui/Messages.java b/src/main/java/seedu/cafectrl/ui/Messages.java
index 659f255948..d1b83c08fa 100644
--- a/src/main/java/seedu/cafectrl/ui/Messages.java
+++ b/src/main/java/seedu/cafectrl/ui/Messages.java
@@ -92,9 +92,9 @@ public class Messages {
+ "Let's keep it classy and use the prescribed format below.\n";
public static final String SAVE_FILE_FORMAT_MENU = "Format for Menu.txt: \n"
- + "{Dish Name} | {Dish Price} | {Ingredient Name} {Ingredient Qty} {Ingredient Unit} |";
+ + "{Dish Name} | {Dish Price} | {Ingredient Name} - {Ingredient Qty} - {Ingredient Unit} |";
public static final String SAVE_FILE_FORMAT_ORDERS = "Format for Orders.txt: \n"
- + "{Order Day} | {Dish Name} | {Dish Order Qty} | {Total Order Cost} | {Order Complete Status}";
+ + "{Order Day} | {Dish Name} | {Dish Order Qty} | {Dish Price} | {Order Complete Status}";
public static final String SAVE_FILE_FORMAT_PANTRY_STOCK = "Format for Pantry_stock.txt: \n"
+ "{Ingredient Name} | {Ingredient Qty} | {Ingredient Unit}";
public static final String SALES_LAST_DAY_TEXT_TAMPERED = "Unfortunately, any empty order lists after "
@@ -108,4 +108,7 @@ public class Messages {
+ "got a makeover without permission.";
public static final String HASH_STRING_MESSAGE = "Please resist the temptation to play Picasso with this string.";
+ public static final String DONE_LOADING_MENU = "Done loading menu.txt!";
+ public static final String DONE_LOADING_PANTRY_STOCK = "Done loading pantry_stock.txt!";
+ public static final String DONE_LOADING_SALES = "Done loading orders.txt!";
}
diff --git a/src/main/java/seedu/cafectrl/ui/Ui.java b/src/main/java/seedu/cafectrl/ui/Ui.java
index cea648335c..fc396c978e 100644
--- a/src/main/java/seedu/cafectrl/ui/Ui.java
+++ b/src/main/java/seedu/cafectrl/ui/Ui.java
@@ -96,7 +96,7 @@ public void showDishPrice(Dish dish) {
showToUser(dishPriceString, Messages.INGREDIENTS_CORNER);
}
- //@@author
+ //@@author ShaniceTang
/**
* Shows delete message to user
*
@@ -122,6 +122,7 @@ public void showToUser(String... message) {
/**
* Shows menu to user is table format
+ *
* @param dishName
* @param dishPrice
*/
@@ -132,6 +133,7 @@ public void formatListMenu(String dishName, String dishPrice) {
/**
* show edit price message to user
+ *
* @param menuItem menuItem that has been modified
*/
public void showEditPriceMessage(String menuItem) {
@@ -283,8 +285,4 @@ public void showPreviousDay() {
public void showNextDay() {
showToUser(Messages.NEXT_DAY_COMMAND_MESSAGE);
}
-
- public void showDecodedInvalidDish(String dishName) {
- showToUser(dishName + Messages.INVALID_DISH + dishName);
- }
}
diff --git a/src/test/java/seedu/cafectrl/data/MenuTest.java b/src/test/java/seedu/cafectrl/data/MenuTest.java
deleted file mode 100644
index 6d45579158..0000000000
--- a/src/test/java/seedu/cafectrl/data/MenuTest.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package seedu.cafectrl.data;
-
-//import static org.junit.jupiter.api.Assertions.*;
-
-class MenuTest {
-
-}
diff --git a/src/test/java/seedu/cafectrl/parser/ParserTest.java b/src/test/java/seedu/cafectrl/parser/ParserTest.java
index ff009569b6..cc04074e57 100644
--- a/src/test/java/seedu/cafectrl/parser/ParserTest.java
+++ b/src/test/java/seedu/cafectrl/parser/ParserTest.java
@@ -989,6 +989,29 @@ void parseCommand_invalidArgsForBuyIngredient_returnErrorMessage() {
String feedbackToUser = incorrectCommand.feedbackToUser;
assertEquals(ErrorMessages.INVALID_UNIT_MESSAGE, feedbackToUser);
}
+
+ @Test
+ void isValidUnit_invalidUnit_returnFalse() {
+ assertFalse(Parser.isValidUnit("kg"));
+ }
+
+ @Test
+ void isEmptyUnit_emptyUnit_returnTrue() {
+ assertTrue(Parser.isEmptyUnit(""));
+ }
+
+ @Test
+ void checkForMismatchUnit_mismatchingUnit_throwParserException() {
+ Menu menu = new Menu();
+ ArrayList ingredients = new ArrayList<>();
+ ingredients.add(new Ingredient("chicken", 500, "g"));
+ Dish dish = new Dish("chicken rice", ingredients, 3.00F);
+ menu.addDish(dish);
+
+ Ingredient ingredient = new Ingredient("chicken", 500, "ml");
+
+ assertThrows(ParserException.class, () -> Parser.checkForMismatchUnit(menu, ingredient));
+ }
//@@author
@Test