diff --git a/build.gradle b/build.gradle index b448c45b61..0579ab08b4 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,7 @@ repositories { dependencies { testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.10.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.10.0' + implementation('com.github.freva:ascii-table:1.8.0') } test { @@ -43,5 +44,5 @@ checkstyle { run{ standardInput = System.in - enableAssertions = true; + enableAssertions = true } diff --git a/docs/UserGuide.md b/docs/UserGuide.md index fe66c2d870..a92a164c0e 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -11,19 +11,44 @@ Format: `help` Expected output: ``` -Here are the list of commands you can use: -1. new - Add a bouquet -2. delete - Delete a bouquets -3. mybouquets - List current saved bouquets -4. info - Provide information on chosen flower -5. add /q /to - add flower to a bouquet -6. remove /q /from - remove flower from a bouquet -7. flowers - Shows a list of flowers that can be added into mybouquets -8. flowers - Shows a list of flowers associated with said occasion -9. occasion - Shows a list of occasions associated with available flowers -10. save - Saves a bouquet to an external .txt file -11. recommend - Recommends a bouquet based on the chosen occasion and colour -12. bye - Exits the programme +Here is the table showing a list of commands you can use: ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| No. | Command | Explanation | Example | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 1 | new | Add a bouquet | new Birthday Bouquet | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 2 | delete | Delete a bouquets | delete Birthday Bouquet | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 3 | mybouquets | List current saved bouquets | mybouquets | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 4 | info | Provide information on chosen flower | info Rose | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 5 | add /c (optional) /q | Add flower to a bouquet | add Rose /c Red /q 5 /to Birthday Bouquet | +| | /to | | | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 6 | remove /c (optional) /q | Remove flower from a bouquet | remove Rose /c Red /q 5 /from Birthday Bouquet | +| | /from | | | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 7 | flowers | Shows a list of flowers that can be | flowers | +| | | added into mybouquets | | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 8 | flowers | Shows a list of flowers associated | flowers Valentines | +| | | with said occasion | | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 9 | occasion | Shows a list of occasions associated | occasion | +| | | with available flowers | | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 10 | save | Saves a bouquet to an external | save Birthday Bouquet | +| | | .txt file | | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 11 | recommend | Recommends a bouquet based on the | recommend | +| | | chosen occasion and colour | | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 12 | compare <1st flowerName> /vs/ <2nd flowerName> | Show information regarding two flowers | compare Rose /vs/ Lily | +| | | side-by-side for comparison | | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ +| 13 | bye | Exits the programme | bye | ++-----+----------------------------------------------------------+----------------------------------------+------------------------------------------------+ ``` ### Create a new bouquet: `new` @@ -118,12 +143,14 @@ Example: `info Lily` Expected Output: ``` -Here is page 1/1 of info regarding flowers whose name contains Lily: -1. Name: Lily -Colour: White -Occasions: Funeral, Wedding -Price: $2.50 -Meanings: Innocence +Here is a table of information about the flower Lily: ++-----+-------------+--------+--------------------+-------------+--------+-----------+ +| No. | Flower Name | Colour | Occasion | Meaning | Type | Price ($) | ++-----+-------------+--------+--------------------+-------------+--------+-----------+ +| 1 | Lily | White | [FUNERAL, WEDDING] | [Innocence] | FLOWER | 2.50 | ++-----+-------------+--------+--------------------+-------------+--------+-----------+ +| 2 | Lily | Orange | [] | [Hatred] | FLOWER | 2.50 | ++-----+-------------+--------+--------------------+-------------+--------+-----------+ ____________________________________________________________ ``` @@ -199,46 +226,46 @@ Recommends a bouquet based on the occasion and the recipient's preference Steps: 1. Type command: `recommend` -Expected output: -``` -For what occasion are you buying flowers for? -Here is the list of our available occasion: -Here are all the occasions associated with the available flowers: -- Funeral -- Wedding -- Valentines -- Mothers day -____________________________________________________________ -``` + Expected output: + ``` + For what occasion are you buying flowers for? + Here is the list of our available occasion: + Here are all the occasions associated with the available flowers: + - Funeral + - Wedding + - Valentines + - Mothers day + ____________________________________________________________ + ``` 2. Type occasion: `Funeral` - -Expected output: -``` -What colour would you like your bouquets to be? -Here is the list of colours available for the occasion: -- DARK_CRIMSON -- WHITE -``` + + Expected output: + ``` + What colour would you like your bouquets to be? + Here is the list of colours available for the occasion: + - DARK_CRIMSON + - WHITE + ``` 3. Select colour of bouquet: `WHITE` -Expected output: - -``` -Would you like to save this bouquet to your list? -Here is the full list of flowers in Recommended Bouquet: - - 3 x Lily - - 2 x Chrysanthemum -____________________________________________________________ -Type 'yes' to save, 'no' to discard -``` + Expected output: + + ``` + Would you like to save this bouquet to your list? + Here is the full list of flowers in Recommended Bouquet: + - 3 x Lily + - 2 x Chrysanthemum + ____________________________________________________________ + Type 'yes' to save, 'no' to discard + ``` 4. Confirm whether you want to add the recommended bouquet to your mybouquets list: `yes` - -``` -Added new bouquet to list: -Recommended Bouquet -____________________________________________________________ -``` + + ``` + Added new bouquet to list: + Recommended Bouquet + ____________________________________________________________ + ``` ### Save a bouquet to device: `save` Saves chosen bouquet, if it exists, locally to the users device @@ -255,6 +282,34 @@ Expected Output: Successfully saved moms bouquet. You can find it at 'florizz-out/saved/moms bouquet.txt' ``` +### Compare two flowers: `compare` +Compares the colour, occasion, meaning, type and price of flowers based on flower names + +Format: `compare /vs/ ` + +- Both flowers must exist in the database + +Examples: +- `compare Rose /vs/ Lily` + +Expected output: +``` +Here is a table of comparison between the two flowers: ++-----+-------------+--------------+------------------------------------+------------------------------------------+--------+-----------+ +| No. | Flower Name | Colour | Occasion | Meaning | Type | Price ($) | ++-----+-------------+--------------+------------------------------------+------------------------------------------+--------+-----------+ +| 1 | Rose | Dark crimson | [FUNERAL] | [Mourning] | FLOWER | 2.00 | ++-----+-------------+--------------+------------------------------------+------------------------------------------+--------+-----------+ +| 2 | Rose | Red | [VALENTINES, WEDDING, MOTHERS_DAY] | [Love] | FLOWER | 2.00 | ++-----+-------------+--------------+------------------------------------+------------------------------------------+--------+-----------+ +| 3 | Rose | Yellow | [] | [Jealousy, Decrease of love, Infidelity] | FLOWER | 2.00 | ++-----+-------------+--------------+------------------------------------+------------------------------------------+--------+-----------+ +| 4 | Lily | White | [FUNERAL, WEDDING] | [Innocence] | FLOWER | 2.50 | ++-----+-------------+--------------+------------------------------------+------------------------------------------+--------+-----------+ +| 5 | Lily | Orange | [] | [Hatred] | FLOWER | 2.50 | ++-----+-------------+--------------+------------------------------------+------------------------------------------+--------+-----------+ +``` + ### Exit programme: `bye` Exits the program. @@ -268,50 +323,52 @@ Enjoy your bouquet! Thank you for using Florizz! ### Fuzzy Logic -Florizz uses a type of fuzzy logic to rectifies typos in user input by utilising the Damerau-Levenshtein Distance -to measure the similarity between the user input and a valid command/item/occasion. +Florizz uses a type of fuzzy logic that rectifies typos in user input by utilising the Damerau-Levenshtein Distance +to measure the similarity between the user input and a valid command/flower/colour/occasion. The Damerau-Levenshtein distance measures the minimum number of single-character edits required to change one string into another. These edits can be insertions, deletions, substitutions and transpositions of individual characters. -When a typo is detected, Florizz will make a calculated guess as to the valid commands that a user is actually calling. +When a typo is detected, Florizz will make a calculated guess as to the valid command that a user is actually referring to. -Examples: -- `newq mybouquet1` -- `adds Chysanthenum /q 10 /to mybouquet1` -- `delate mybouquet1` +Examples of typos that Florizz can rectify include: + +1. Typo in spelling + - `flowerz Vlentine` + - `ads Ross /c ret /q 10 /to mybouquet1` +2. Incorrect placements of whitespaces + - `c o m p are R ose /v s/ L i ly` + - `m y b ouq ue ts` +3. Absence of whitespaces + - `flowersmothersday` + - `infoDaisy` + +Note: Fuzzy Logic only works for commands, flower names, colours and occasions, and it cannot rectify typos which +combine no. 1 with no. 2 or no. 3. Expected output: ``` -newq mybouquet1 ---> Your input is [newq] but I am guessing you mean [new] -Added new bouquet to list: -mybouquet1 -____________________________________________________________ -What can I do for you? +flowerz Vlentine +--> Your input is [flowerz] but I am guessing you mean [flowers] +--> Your input is [Vlentine] but I am guessing you mean [Valentines] ``` + ``` -adds Chysanthenum /q 10 /to mybouquet1 ---> Your input is [adds] but I am guessing you mean [add] ---> Your input is [Chysanthenum] but I am guessing you mean [Chrysanthemum] -You have successfully added the following: - - 10 x chrysanthemum -> Bouquet: mybouquet1 -Here is the list of your saved bouquets: -1. mybouquet1 : - - 10 x Chrysanthemum - Total estimated price = $10.00 -____________________________________________________________ -What can I do for you? +ads Ross /c ret /q 10 /to mybouquet1 +--> Your input is [ads] but I am guessing you mean [add] +--> Your input is [Ross] but I am guessing you mean [Rose] +--> Your input is [ret] but I am guessing you mean [Red] ``` ``` -delate mybouquet1 ---> Your input is [delate] but I am guessing you mean [delete] -Deleted bouquet: -mybouquet1 -____________________________________________________________ -What can I do for you? +c o m p are R ose /v s/ L i ly +--> Your input is [c o m p are R ose /v s/ L i ly] but I am guessing you mean [compare Rose /vs/ Lily] +``` + +``` +flowersmothersday +--> Your input is [flowersmothersday] but I am guessing you mean [flowers Mothers Day] ``` ### Autosave diff --git a/docs/team/jeffinsondarmawan.md b/docs/team/jeffinsondarmawan.md index 5602e1dc26..172e6d7dd4 100644 --- a/docs/team/jeffinsondarmawan.md +++ b/docs/team/jeffinsondarmawan.md @@ -24,12 +24,14 @@ Code Contribution: [Jeffinson Darmawan RepoSense Report](https://nus-cs2113-ay23 `info Rose` where Florizz will show information regarding that flower. Suppose that a user mistakenly input `invo Ross` and another user mistakenly input `zjgh bfre`. Without Fuzzy Logic, both `invo Ross` and `zjgh bfre` will be regarded as equaly invalid commands and the programme will throw an exception. However, one can make a - strong case that `invo Ross` is definitely closer to `info Rose` compared to `zjgh bfre`. Thus, Fuzzy Logic helps - users by correcting their typos due to accidental human errors and increase the overall convenience of using the - programme. Imagine having to retype `adds Rose /q 1 /to Bouquet for My 3th Anniversary with My Girlfriend` because - of a small mistake of having an "s" after "add" and repeating this over and over again! - - + strong case that `invo Ross` is definitely closer to `info Rose` compared to `zjgh bfre`. + - Justification: + Fuzzy Logic helps + users by correcting their typos due to accidental human errors and increase the overall convenience of using the + programme. This feature is especially useful for users who are prone to making typos in their inputs. By implementing + Fuzzy Logic, Florizz is able to correct these typos and provide the user with the intended output thereby reducing + the effect of human errors.Imagine having to retype `adds Rose /q 1 /to Bouquet for My 3th Anniversary with My Girlfriend` + because of a small mistake of having an "s" after "add" and repeating this over and over again! - How it works: Fuzzy Logic in Florizz works primarily in 3 ways. Firstly, applying @@ -46,13 +48,29 @@ Code Contribution: [Jeffinson Darmawan RepoSense Report](https://nus-cs2113-ay23 2. Listing Available Occasion (Pull Request [#26](https://github.com/AY2324S2-CS2113-T11-3/tp/pull/26)) - What it is: - `Occasion` lists out all the occasions which are associated will all flowers in our database. This + `occasion` lists out all the occasions which are associated will all flowers in our database. This allows users to have a quick look at what occasions they can choose for their flowers. Once users know what occasion they can input `flowers ` to see all the flowers associated with the occasion of choosing. - + - Justification: + This feature is especially useful for users who are unsure of what flowers to choose for a specific occasion. 3. Help Command (Pull Request [#16](https://github.com/AY2324S2-CS2113-T11-3/tp/pull/16)) - What it is: `help` assists users in using Florizz by showing a quick list of commands that users can use. + - Justification: + This feature is especially useful for new users who are unfamiliar with the commands available in Florizz. + - Highlights: + This feature uses an ASCII table to increase readability of the list of available commands. +4. Compare Command + - What it is: + `compare` allows users to compare the colour, occasion, meaning, type and price of two flowers. + - Justification: + When deciding which flowers to add to a bouquet, users might find it difficult to compare between different flowers + as they need to separately call the `info` command for each flower. + Thus, this feature is especially useful for users who are deciding between two flowers and want to know the + differences between them. + - Highlights: + This feature required the implementation of a new command and the creation of a new class to handle the comparison of two flowers. + It also uses an ASCII table to increase readability of the comparison results. **Enhancements:** 1. Applying appropriate exceptions to ensure valid integer inputs in all commands involving integers @@ -61,8 +79,9 @@ Code Contribution: [Jeffinson Darmawan RepoSense Report](https://nus-cs2113-ay23 3. Improving Parser class by applying FuzzyLogic.detectItem() (Pull Request [#71](https://github.com/AY2324S2-CS2113-T11-3/tp/pull/71)) 4. Wrote JUnit tests for `AddFlowerCommandTest`, `HelpTest`, `InfoCommandTest`, `ListOccasionCommandTest`, - `RemoveFlowerCommandTest`, `FuzzyLogicTest`, `ParserTest`, and wrote additional JUnit tests for `AddBouquetTest`, - `DeleteBouquetTest` which increases classes coverage from 54% to 61% and lines coverage from 29% to 50%. + `RemoveFlowerCommandTest`, `FuzzyLogicTest`, `ParserTest`, `CompareCommandTest` + and wrote additional JUnit tests for `AddBouquetTest`, + `DeleteBouquetTest` which increases classes coverage from 54% to 63% and lines coverage from 29% to 51%. **Documentation** 1. Developer Guide @@ -70,5 +89,9 @@ Code Contribution: [Jeffinson Darmawan RepoSense Report](https://nus-cs2113-ay23 - Added UML diagrams and implementation details for `remove` and `help` 2. User Guide (Pull Request [#106](https://github.com/AY2324S2-CS2113-T11-3/tp/pull/106)) - - Added documentation on Fuzzy Logic - - Updated documentation on `help`, `new`, `add` and `remove` \ No newline at end of file + - Added documentation on `compare` and Fuzzy Logic + - Updated documentation on `help`, `new`, `add` and `remove` + +**Tools** +1. Integrated a third party JTextUtil library called "freva ascii-table" to create ASCII tables for the `help` +and `compare` commands. (Link to Github Page: [Freva ASCII Table](https://github.com/freva/ascii-table)) \ No newline at end of file diff --git a/src/main/java/florizz/command/CompareCommand.java b/src/main/java/florizz/command/CompareCommand.java new file mode 100644 index 0000000000..4ba9b06af4 --- /dev/null +++ b/src/main/java/florizz/command/CompareCommand.java @@ -0,0 +1,49 @@ +package florizz.command; + +import florizz.core.FlorizzException; +import florizz.core.FlowerDictionary; +import florizz.core.Ui; +import florizz.objects.Bouquet; +import florizz.objects.Flower; + +import java.util.ArrayList; + +public class CompareCommand extends Command { + + private String firstFlowerName; + private String secondFlowerName; + + /** + * Constructor for the CompareCommand class. + * + * @param firstFlowerName The name of the first flower to compare + * @param secondFlowerName The name of the second flower to compare + */ + public CompareCommand(String firstFlowerName, String secondFlowerName) { + this.firstFlowerName = firstFlowerName; + this.secondFlowerName = secondFlowerName; + } + + /** + * Executes the CompareCommand by comparing two flowers. + * + * @param bouquetList The list of bouquets to search for the specified bouquet + * @param ui The user interface to interact with the user + * @return True if the command is executed successfully, false otherwise + */ + public boolean execute(ArrayList bouquetList, Ui ui) throws FlorizzException { + if (firstFlowerName.equals(secondFlowerName)) { + throw new FlorizzException("Unable to compare a flower with itself. Please input different flowers"); + } + + ArrayList firstFilteredFlowers = FlowerDictionary.filterByName(firstFlowerName); + ArrayList secondFilteredFlowers = FlowerDictionary.filterByName(secondFlowerName); + + if (firstFilteredFlowers.isEmpty() || secondFilteredFlowers.isEmpty()) { + throw new FlorizzException("Flower does not exist, type 'flowers' for a list of flowers"); + } + + ui.printCompareFlowers(firstFilteredFlowers, secondFilteredFlowers); + return true; + } +} diff --git a/src/main/java/florizz/command/InfoCommand.java b/src/main/java/florizz/command/InfoCommand.java index 4ab73b90be..7bde343326 100644 --- a/src/main/java/florizz/command/InfoCommand.java +++ b/src/main/java/florizz/command/InfoCommand.java @@ -30,7 +30,6 @@ public boolean execute(ArrayList bouquetList, Ui ui) throws FlorizzExce } else{ ui.printFlowerInfo(filteredFlowers, flowerName, 1); } - return true; } } diff --git a/src/main/java/florizz/core/FlowerDictionary.java b/src/main/java/florizz/core/FlowerDictionary.java index b41b02dc0f..dcf0a5bb4a 100644 --- a/src/main/java/florizz/core/FlowerDictionary.java +++ b/src/main/java/florizz/core/FlowerDictionary.java @@ -36,45 +36,46 @@ private static void add(String name, String colour, String[] occasions, */ public static void startup() { add("Orchid", "White", new String[]{"Wedding"}, 10.00, - new String[]{"Innocence", "Respect", "Beauty"}, Flower.Type.FLOWER); + new String[]{"Innocence", "Respect", "Beauty"}, Flower.Type.MAIN_FLOWER); add("Rose", "Dark Crimson", new String[]{"Funeral"}, 2.00, - new String[]{"Mourning"}, Flower.Type.FLOWER); + new String[]{"Mourning"}, Flower.Type.MAIN_FLOWER); add("Rose", "Red", new String[]{"Valentines", "Wedding", "Mothers Day"}, 2.00, - new String[]{"Love"}, Flower.Type.FLOWER); + new String[]{"Love"}, Flower.Type.MAIN_FLOWER); add("Rose", "Yellow", new String[]{}, 2.00, - new String[]{"Jealousy, Decrease of love, Infidelity"}, Flower.Type.FLOWER); + new String[]{"Jealousy, Decrease of love, Infidelity"}, Flower.Type.MAIN_FLOWER); add("Lily", "White", new String[]{"Funeral", "Wedding"}, 2.50, - new String[]{"Innocence"}, Flower.Type.FLOWER); + new String[]{"Innocence"}, Flower.Type.MAIN_FLOWER); add("Lily", "Orange", new String[]{}, 2.50, - new String[]{"Hatred"}, Flower.Type.FLOWER); + new String[]{"Hatred"}, Flower.Type.MAIN_FLOWER); add("Daisy", "White", new String[]{"Valentines"}, 0.50, - new String[]{"Innocence"}, Flower.Type.FLOWER); + new String[]{"Innocence"}, Flower.Type.MAIN_FLOWER); add("Chrysanthemum", "White", new String[]{"Funeral"}, 1.00, - new String[]{"Love", "Loyalty", "Innocence"}, Flower.Type.FLOWER); + new String[]{"Love", "Loyalty", "Innocence"}, Flower.Type.MAIN_FLOWER); add("Hydrangea", "Blue", new String[]{"Wedding"}, 9.00, - new String[]{"Forgiveness", "Gratitude"}, Flower.Type.FLOWER); + new String[]{"Forgiveness", "Gratitude"}, Flower.Type.MAIN_FLOWER); add("Carnation", "Pink", new String[]{"Mothers Day"}, 2.00, - new String[]{"Gratitude", "Love"}, Flower.Type.FLOWER); + new String[]{"Gratitude", "Love"}, Flower.Type.MAIN_FLOWER); add("Carnation", "Red", new String[]{"Valentines"}, 2.00, - new String[]{"My heart aches", "Deep Love"}, Flower.Type.FLOWER); + new String[]{"My heart aches", "Deep Love"}, Flower.Type.MAIN_FLOWER); // [Fillers have yet to be implemented] add("Baby Breath", "White", new String[]{"Wedding", "Valentines", "Mothers Day"}, 1.00, - new String[]{"Innocence", "Kindness", "Care", "Humble"}, Flower.Type.FLOWER); - add("Eucalyptus", "Green", new String[]{"Wedding"}, 1.5, new String[]{"Love", "Kindness"}, Flower.Type.FLOWER); - add("Dusty Miller", "Green", new String[]{}, 1.5, new String[]{}, Flower.Type.FILLER); - add("Pistacia", "Green", new String[]{}, 1.5, new String[]{}, Flower.Type.FILLER); - add("Pittosporum", "Green", new String[]{}, 1.5, new String[]{}, Flower.Type.FILLER); - add("Chamomile", "White", new String[]{}, 1.9, new String[]{}, Flower.Type.FILLER); - add("Astilbe", "Pink", new String[]{}, 2.8, new String[]{}, Flower.Type.FILLER); - add("Hypericum", "Red", new String[]{}, 2.0, new String[]{}, Flower.Type.FILLER); - add("Freesia", "White", new String[]{}, 1.9, new String[]{}, Flower.Type.FILLER); - add("Helichrysum", "Yellow", new String[]{}, 1.5, new String[]{}, Flower.Type.FILLER); - add("Limonium", "Red", new String[]{}, 1.8, new String[]{}, Flower.Type.FILLER); - add("Limonium", "Dark Crimson", new String[]{}, 1.8, new String[]{}, Flower.Type.FILLER); - add("Limonium Perezii", "Purple", new String[]{}, 1.8, new String[]{}, Flower.Type.FILLER); - add("Statice", "Blue", new String[]{}, 1.5, new String[]{}, Flower.Type.FILLER); - add("Statice", "Purple", new String[]{}, 1.5, new String[]{}, Flower.Type.FILLER); - add("Rice Flower", "Pink", new String[]{}, 1.8, new String[]{}, Flower.Type.FILLER); + new String[]{"Innocence", "Kindness", "Care", "Humble"}, Flower.Type.MAIN_FLOWER); + add("Eucalyptus", "Green", new String[]{"Wedding"}, 1.50, new String[]{"Love", "Kindness"} + , Flower.Type.MAIN_FLOWER); + add("Dusty Miller", "Green", new String[]{}, 1.50, new String[]{}, Flower.Type.FILLER); + add("Pistacia", "Green", new String[]{}, 1.50, new String[]{}, Flower.Type.FILLER); + add("Pittosporum", "Green", new String[]{}, 1.50, new String[]{}, Flower.Type.FILLER); + add("Chamomile", "White", new String[]{}, 1.90, new String[]{}, Flower.Type.FILLER); + add("Astilbe", "Pink", new String[]{}, 2.80, new String[]{}, Flower.Type.FILLER); + add("Hypericum", "Red", new String[]{}, 2.00, new String[]{}, Flower.Type.FILLER); + add("Freesia", "White", new String[]{}, 1.90, new String[]{}, Flower.Type.FILLER); + add("Helichrysum", "Yellow", new String[]{}, 1.50, new String[]{}, Flower.Type.FILLER); + add("Limonium", "Red", new String[]{}, 1.80, new String[]{}, Flower.Type.FILLER); + add("Limonium", "Dark Crimson", new String[]{}, 1.80, new String[]{}, Flower.Type.FILLER); + add("Limonium Perezii", "Purple", new String[]{}, 1.80, new String[]{}, Flower.Type.FILLER); + add("Statice", "Blue", new String[]{}, 1.50, new String[]{}, Flower.Type.FILLER); + add("Statice", "Purple", new String[]{}, 1.50, new String[]{}, Flower.Type.FILLER); + add("Rice Flower", "Pink", new String[]{}, 1.80, new String[]{}, Flower.Type.FILLER); } /** diff --git a/src/main/java/florizz/core/FuzzyLogic.java b/src/main/java/florizz/core/FuzzyLogic.java index d297654e77..edcf9c8030 100644 --- a/src/main/java/florizz/core/FuzzyLogic.java +++ b/src/main/java/florizz/core/FuzzyLogic.java @@ -34,6 +34,7 @@ public class FuzzyLogic { ITEMS.put("recommend", "Command: Get a recommended bouquet"); ITEMS.put("next", "Command: Goes to next page"); ITEMS.put("back", "Command: Goes to previous page"); + ITEMS.put("compare", "Command: Compare two flowers"); ITEMS.put("Orchid", "Flower"); ITEMS.put("Rose", "Flower"); ITEMS.put("Lily", "Flower"); @@ -59,6 +60,14 @@ public class FuzzyLogic { ITEMS.put("Limonium Perezii", "Flower"); ITEMS.put("Statice", "Flower"); ITEMS.put("Rice Flower", "Flower"); + ITEMS.put("Red", "Colour"); + ITEMS.put("Yellow", "Colour"); + ITEMS.put("White", "Colour"); + ITEMS.put("Blue", "Colour"); + ITEMS.put("Pink", "Colour"); + ITEMS.put("Green", "Colour"); + ITEMS.put("Purple", "Colour"); + ITEMS.put("Dark Crimson", "Colour"); } /** @@ -74,7 +83,7 @@ protected static String detectItem(String userInput) throws FlorizzException { } if (userInput.length() == 1) { - throw new FlorizzException("No matching command/item/occasion found for input: " + userInput); + throw new FlorizzException("No command/flower/occasion/colour matches the input: " + userInput); } String bestMatch = null; @@ -98,8 +107,8 @@ protected static String detectItem(String userInput) throws FlorizzException { } else if (bestDistance == 0) { return bestMatch; } else { - logger.log(Level.SEVERE, "No matching command/item/occasion found for input: {0}", userInput); - throw new FlorizzException("No matching command/item/occasion found for input: " + userInput); + logger.log(Level.SEVERE, "No command/flower/occasion/colour matches the input: {0}", userInput); + throw new FlorizzException("No command/flower/occasion/colour matches the input: " + userInput); } } @@ -174,6 +183,7 @@ protected static String processCommand(String userInput) throws FlorizzException } String correctedInput; String trimmedInput = userInput.trim(); + String[] words = trimmedInput.split(" "); int firstWhitespace = trimmedInput.indexOf(" "); if ((firstWhitespace != -1) && (userInput.startsWith("delete") @@ -182,6 +192,7 @@ protected static String processCommand(String userInput) throws FlorizzException || userInput.startsWith("remove") || userInput.startsWith("add") || userInput.startsWith("info") + || (userInput.startsWith("compare") && words.length == 4 || words.length == 5) || userInput.startsWith("flowers"))) { String[] arguments = new String[2]; arguments[0] = userInput.substring(0,firstWhitespace).toLowerCase(); @@ -211,75 +222,118 @@ protected static String processCommand(String userInput) throws FlorizzException * @throws FlorizzException if there is an issue processing the input. */ protected static String splitAndMergeInput(String userInput) throws FlorizzException { - try { - String correctedInput; - String mergedInput = mergeInput(userInput); - String splitMergedInput = splitInput(mergedInput); - String[] arguments = splitMergedInput.split(" "); - String bouquetName; - String removeArgument; - String addArgument; - Ui uiFuzzy = new Ui(); + String correctedInput; + String mergedInput = mergeInput(userInput); + String splitMergedInput = splitInput(mergedInput); + String[] arguments = splitMergedInput.split(" "); + String bouquetName; + String removeArgument; + String addArgument; + Ui uiFuzzy = new Ui(); - if (arguments.length == 1 && arguments[0] - .matches("(mybouquets|flowers|occasion|recommend|bye|help|back|next)")) { - correctedInput = arguments[0]; - uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); - } else if (arguments[0].matches("(info|flowers)")) { - if (Objects.equals(arguments[1].toLowerCase(), "mothersday")) { - arguments[1] = "Mothers Day"; - } - correctedInput = arguments[0] + " " + arguments[1]; - uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); - } else if (arguments[0].matches("(new)")) { - bouquetName = userInput.replaceFirst("n", "") - .replaceFirst("e", "") - .replaceFirst("w", "") - .strip(); - correctedInput = "new " + bouquetName; - uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); - } else if (arguments[0].matches("(delete)")) { - bouquetName = userInput.replaceFirst("d", "") - .replaceFirst("e", "") - .replaceFirst("l", "") - .replaceFirst("e", "") - .replaceFirst("t", "") - .replaceFirst("e", "") - .strip(); - correctedInput = "delete " + bouquetName; - uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); - } else if (arguments[0].matches("(save)")) { - bouquetName = userInput.replaceFirst("s", "") - .replaceFirst("a", "") - .replaceFirst("v", "") - .replaceFirst("e", "") - .strip(); - correctedInput = "save " + bouquetName; - uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); - } else if (arguments[0].matches("(remove)")) { - removeArgument = userInput.replaceFirst("r", "") - .replaceFirst("e", "") - .replaceFirst("m", "") - .replaceFirst("o", "") - .replaceFirst("v", "") - .replaceFirst("e", "") - .strip(); - correctedInput = "remove " + removeArgument; - uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); - } else if (arguments[0].matches("(add)")) { - addArgument = userInput.replaceFirst("a", "") - .replaceFirst("d", "") - .replaceFirst("d", "") - .strip(); - correctedInput = "add " + addArgument; - uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); + if (arguments[0] == null) { + throw new FlorizzException("Input cannot be empty."); + } + + if (arguments.length == 1 && arguments[0] + .matches("(mybouquets|flowers|occasion|recommend|bye|help|back|next)")) { + correctedInput = arguments[0]; + uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); + } else if (arguments[0].matches("(info|flowers)")) { + if (arguments.length == 1 && arguments[0].matches("(info)")) { + throw new FlorizzException("Incorrect format for " + arguments[0] + ". Correct format: " + + arguments[0] + " "); + } + if (arguments.length == 1 && arguments[0].matches("(flowers)")) { + throw new FlorizzException("Incorrect format for " + arguments[0] + ". Correct format: " + + arguments[0] + " "); + } + if (Objects.equals(arguments[1].toLowerCase(), "mothersday")) { + arguments[1] = "Mothers Day"; + } + correctedInput = arguments[0] + " " + arguments[1]; + uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); + } else if (arguments[0].matches("(new)")) { + if (arguments.length == 1) { + throw new FlorizzException("Incorrect format for new. Correct format: new "); + } + bouquetName = userInput.replaceFirst("n", "") + .replaceFirst("e", "") + .replaceFirst("w", "") + .strip(); + correctedInput = "new " + bouquetName; + uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); + } else if (arguments[0].matches("(delete)")) { + if (arguments.length == 1) { + throw new FlorizzException("Incorrect format for delete. Correct format: delete "); + } + bouquetName = userInput.replaceFirst("d", "") + .replaceFirst("e", "") + .replaceFirst("l", "") + .replaceFirst("e", "") + .replaceFirst("t", "") + .replaceFirst("e", "") + .strip(); + correctedInput = "delete " + bouquetName; + uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); + } else if (arguments[0].matches("(save)")) { + if (arguments.length == 1) { + throw new FlorizzException("Incorrect format for save. Correct format: save "); + } + bouquetName = userInput.replaceFirst("s", "") + .replaceFirst("a", "") + .replaceFirst("v", "") + .replaceFirst("e", "") + .strip(); + correctedInput = "save " + bouquetName; + uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); + } else if (arguments[0].matches("(remove)")) { + if (arguments.length == 1) { + throw new FlorizzException("Incorrect format for remove. Correct format: remove " + + " /c /q /from "); + } + removeArgument = userInput.replaceFirst("r", "") + .replaceFirst("e", "") + .replaceFirst("m", "") + .replaceFirst("o", "") + .replaceFirst("v", "") + .replaceFirst("e", "") + .strip(); + correctedInput = "remove " + removeArgument; + uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); + } else if (arguments[0].matches("(add)")) { + if (arguments.length == 1) { + throw new FlorizzException("Incorrect format for add. Correct format: add " + + " /c /q /to "); + } + addArgument = userInput.replaceFirst("a", "") + .replaceFirst("d", "") + .replaceFirst("d", "") + .strip(); + correctedInput = "add " + addArgument; + uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); + } else if (arguments[0].matches("(compare)")) { + if (arguments.length == 1) { + throw new FlorizzException("Incorrect format for compare. Correct format: compare " + + " /vs/ "); + } + String[] flowerNames; + if (arguments[1].contains("/vs/")) { + flowerNames = arguments[1].split("/vs/"); } else { - correctedInput = userInput; + throw new FlorizzException("Incorrect format for compare. Correct format: compare " + + " /vs/ "); } - return correctedInput; - } catch (Exception e) { - throw new FlorizzException("Error processing input: " + e.getMessage()); + + if (flowerNames.length != 2 || flowerNames[0].length() <= 2 || flowerNames[1].length() <= 2) { + throw new FlorizzException("Please input 2 flowers to compare."); + } + correctedInput = "compare " + flowerNames[0].strip() + " /vs/ " + flowerNames[1].strip(); + uiFuzzy.printFuzzyInputDetection(userInput, correctedInput); + } else { + correctedInput = userInput; } + return correctedInput; } /** @@ -320,6 +374,9 @@ protected static String splitInput(String userInput) throws FlorizzException { } else if (userInput.matches("(save)[a-zA-Z].+")) { String argumentSave = userInput.replaceFirst("save", ""); correctedInput = "save " + argumentSave; + } else if (userInput.matches("(compare)[a-zA-Z].+")) { + String argumentCompare = userInput.replaceFirst("compare", ""); + correctedInput = "compare " + argumentCompare; } if (correctedInput.isEmpty()) { diff --git a/src/main/java/florizz/core/Parser.java b/src/main/java/florizz/core/Parser.java index b1954ab5bc..29b1f2470b 100644 --- a/src/main/java/florizz/core/Parser.java +++ b/src/main/java/florizz/core/Parser.java @@ -1,20 +1,21 @@ package florizz.core; -import florizz.command.InfoCommand; -import florizz.command.HelpCommand; -import florizz.command.SaveCommand; -import florizz.command.FlowerCommand; -import florizz.command.ExitCommand; -import florizz.command.RemoveFlowerCommand; -import florizz.command.ListOccasionCommand; -import florizz.command.ListBouquetCommand; -import florizz.command.DeleteBouquetCommand; -import florizz.command.AddFlowerCommand; -import florizz.command.Command; import florizz.command.AddBouquetCommand; +import florizz.command.AddFlowerCommand; import florizz.command.BackCommand; +import florizz.command.Command; +import florizz.command.CompareCommand; +import florizz.command.DeleteBouquetCommand; +import florizz.command.ExitCommand; +import florizz.command.FlowerCommand; +import florizz.command.HelpCommand; +import florizz.command.InfoCommand; +import florizz.command.ListBouquetCommand; +import florizz.command.ListOccasionCommand; import florizz.command.NextCommand; import florizz.command.RecommendCommand; +import florizz.command.RemoveFlowerCommand; +import florizz.command.SaveCommand; import florizz.objects.Bouquet; import florizz.objects.Flower; @@ -94,6 +95,9 @@ public static Command parse (String input, boolean enableUi) throws FlorizzExcep case ("save"): command = new SaveCommand(decodedInput[1]); break; + case ("compare"): + command = handleCompareCommand(decodedInput[1], decodedInput[2]); + break; default: throw new FlorizzException("Unidentified input, type help to get a list of all commands!"); } @@ -115,7 +119,7 @@ public static Command parse (String input, boolean enableUi) throws FlorizzExcep * @return String[] output; output[0] = item ; output[1] = argument(s) */ public static String[] commandHandler(String input) throws FlorizzException { - String[] outputs = new String[2]; + String[] outputs = new String[3]; String trimmedInput = input.trim(); String processedInput = FuzzyLogic.processCommand(trimmedInput); int firstWhitespace = processedInput.indexOf(" "); @@ -148,6 +152,16 @@ public static String[] commandHandler(String input) throws FlorizzException { arguments[1] = trimmedArgument.substring(firstSlash).trim(); outputs[1] = arguments[0] + " " + arguments[1]; break; + case ("compare"): + outputs[1] = processedInput.substring(firstWhitespace).trim(); + String[] flowers = outputs[1].split(" /vs/ "); + if (flowers.length != 2) { + throw new FlorizzException("Incorrect usage of compare." + + " Correct format: compare /vs/ "); + } + outputs[1] = FuzzyLogic.detectItem(flowers[0]); + outputs[2] = FuzzyLogic.detectItem(flowers[1]); + break; default: outputs[1] = FuzzyLogic.detectItem(processedInput.substring(firstWhitespace).trim()); break; @@ -162,6 +176,22 @@ public static String[] commandHandler(String input) throws FlorizzException { return outputs; } + /** + * Handles the parsing and creation of a CompareCommand object based on user input. + * + * @param firstFlowerName The name of the first flower to compare. + * @param secondFlowerName The name of the second flower to compare. + * @return A CompareCommand object corresponding to the parsed input. + * @throws FlorizzException If the input does not contain the required flower names. + */ + private static CompareCommand handleCompareCommand(String firstFlowerName, String secondFlowerName) + throws FlorizzException { + if (firstFlowerName == null || secondFlowerName == null) { + throw new FlorizzException("Please specify two flowers to compare!"); + } + return new CompareCommand(firstFlowerName, secondFlowerName); + } + /** * remove prefix from an input string * e.g. "/to For Mom" -> " For Mom" @@ -253,12 +283,13 @@ private static AddFlowerCommand handleAddFlower(String argument, boolean enableU String bouquetName = removePrefix(argument.substring(prefixIndex), ADD_FLOWER_PREFIX).trim(); if (includeColour) { int colourIndex = argument.indexOf(COLOUR); - try{ + try { flowerName = argument.substring(0,colourIndex).trim(); - String colourString = removePrefix(argument.substring(colourIndex, quantityIndex), COLOUR).trim(); + String colourString = FuzzyLogic.detectItem( + removePrefix(argument.substring(colourIndex, quantityIndex), COLOUR).trim()); Flower.Colour colourToAdd = Flower.stringToColour(colourString); return new AddFlowerCommand(flowerName, colourToAdd, quantity, bouquetName, enableUi); - } catch( IllegalArgumentException error){ + } catch ( IllegalArgumentException error) { throw new FlorizzException("Tried to add a non recognised colour" + "Type 'flowers' to view all the currently available flowers and their colours."); } diff --git a/src/main/java/florizz/core/Ui.java b/src/main/java/florizz/core/Ui.java index 975f1a0720..3bf42df4d2 100644 --- a/src/main/java/florizz/core/Ui.java +++ b/src/main/java/florizz/core/Ui.java @@ -1,10 +1,16 @@ package florizz.core; +import com.github.freva.asciitable.AsciiTable; +import com.github.freva.asciitable.Column; +import com.github.freva.asciitable.HorizontalAlign; import florizz.objects.Bouquet; import florizz.objects.Flower; +import florizz.objects.TableData; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.NoSuchElementException; import java.util.Scanner; @@ -28,7 +34,7 @@ public void printIntroMessage(){ " |_| |_|\\___/|_| |_/___/___|\n" + "\n"; System.out.println("Hello from\n" + logo); - System.out.println("Type `help`, to view a list of valid commands!"); + System.out.println("Type `help`, to view a table of valid commands!"); } /** @@ -119,25 +125,61 @@ public void printFullBouquet(Bouquet bouquet) { } /** - * print all available command + * print all available commands */ public void printHelpMessage() { lastCommand = "OTHERS"; - System.out.println("Here are the list of commands you can use:"); - System.out.println("1. new - Add a bouquet"); - System.out.println("2. delete - Delete a bouquets"); - System.out.println("3. mybouquets - List current saved bouquets"); - System.out.println("4. info - Provide information on chosen flower"); - System.out.println("5. add /c (optional) /q " + - "/to - add flower to a bouquet"); - System.out.println("6. remove /c (optional) /q " + - "/from - remove flower from a bouquet"); - System.out.println("7. flowers - Shows a list of flowers that can be added into mybouquets"); - System.out.println("8. flowers - Shows a list of flowers associated with said occasion"); - System.out.println("9. occasion - Shows a list of occasions associated with available flowers"); - System.out.println("10. save - Saves a bouquet to an external .txt file"); - System.out.println("11. recommend - Recommends a bouquet based on the chosen occasion and colour"); - System.out.println("12. bye - Exits the programme"); + System.out.println("Here is the table showing a list of commands you can use:"); + List tableData = Arrays.asList( + new TableData(1, "new " + , "Add a bouquet" + , "new Birthday Bouquet"), + new TableData(2, "delete " + , "Delete a bouquets" + , "delete Birthday Bouquet"), + new TableData(3, "mybouquets" + , "List current saved bouquets" + , "mybouquets"), + new TableData(4, "info " + , "Provide information on chosen flower" + , "info Rose"), + new TableData(5, "add /c (optional) /q /to " + , "Add flower to a bouquet" + , "add Rose /c Red /q 5 /to Birthday Bouquet"), + new TableData(6, "remove /c (optional) /q /from " + , "Remove flower from a bouquet" + , "remove Rose /c Red /q 5 /from Birthday Bouquet"), + new TableData(7, "flowers" + , "Shows a list of flowers that can be added into mybouquets" + , "flowers"), + new TableData(8, "flowers " + , "Shows a list of flowers associated with said occasion" + , "flowers Valentines"), + new TableData(9, "occasion" + , "Shows a list of occasions associated with available flowers" + , "occasion"), + new TableData(10, "save " + , "Saves a bouquet to an external .txt file" + , "save Birthday Bouquet"), + new TableData(11, "recommend" + , "Recommends a bouquet based on the chosen occasion and colour" + , "recommend"), + new TableData(12, "compare <1st flowerName> /vs/ <2nd flowerName>" + , "Show information regarding two flowers side-by-side for comparison" + , "compare Rose /vs/ Lily"), + new TableData(13, "bye" + , "Exits the programme" + , "bye") + ); + System.out.println(AsciiTable.getTable(AsciiTable.BASIC_ASCII_NO_DATA_SEPARATORS, tableData, Arrays.asList( + new Column().header("No.").dataAlign(HorizontalAlign.CENTER) + .with((TableData data) -> Integer.toString(data.getId())), + new Column().header("Command").dataAlign(HorizontalAlign.LEFT) + .with(TableData::getCommand), + new Column().header("Explanation").dataAlign(HorizontalAlign.LEFT) + .with(TableData::getExplanation), + new Column().header("Example").dataAlign(HorizontalAlign.LEFT) + .with(TableData::getExample)))); printBreakLine(); } @@ -159,9 +201,6 @@ public void printExitMessage() { printBreakLine(); } - private static void printNextOrBack(int pageNo, int maxPages){ - - } /** * Prints a list of flowers with optional additional information. * @@ -218,14 +257,23 @@ public void printFilteredFlowers(ArrayList flowers, String filter, int p * @param targetFlower The name of the flower the user searched for. * @param flowers The list of flowers that contain that name. */ - public void printFlowerInfo(ArrayList flowers, String targetFlower, int pageNo) { - lastShownList = flowers; - lastPageNo = pageNo; - lastCommand = "INFO_FLOWERS " + targetFlower; - int maxPages = (int) Math.ceil((double)lastShownList.size() / PAGE_SIZE); - System.out.println("Here is page " + lastPageNo + "/" + maxPages + - " of info regarding flowers whose name contains " + targetFlower + ":"); - printFlowerList(true); + public void printFlowerInfo(ArrayList flowers, String targetFlower, int pageNo) throws FlorizzException { + List tableData = new ArrayList<>(List.of()); + int id = 1; + + for (Flower flower : flowers) { + tableData.add(new TableData(id, flower.getFlowerName(), flower.getColour(), flower.tableOccasionToString(), + flower.tableMeaningToString(), String.format("%.2f", flower.getPrice()) + , flower.getType().toString())); + id++; + } + System.out.println("Here is a table of information about the flower " + targetFlower + ":"); + try { + printFlowersTable(tableData); + printBreakLine(); + } catch (FlorizzException error){ + printError(error); + } } /** @@ -437,7 +485,7 @@ public void printSaveSuccess(String bouquetName) { * @param flowerName The name of the flower that the user is trying to choose its colour from * @return Flower the specific Flower with the correct colour. Is blank if user chose to cancel the command instead */ - public Flower chooseColour(ArrayList flowers, String flowerName){ + public Flower chooseColour(ArrayList flowers, String flowerName) throws FlorizzException { printGetFlowerColour(flowers, flowerName); while (true){ @@ -480,13 +528,67 @@ public Flower chooseColour(ArrayList flowers, String flowerName){ * @param flowers The list of flowers containing the flower with multiple colors * @param flowerName The name of the flower with multiple colors */ - public void printGetFlowerColour(ArrayList flowers, String flowerName){ + public void printGetFlowerColour(ArrayList flowers, String flowerName) throws FlorizzException { System.out.println("The flower you're looking for has more than one colour available, " + - "each with their own vastly different meanings. Here's some info:"); + "each with their own vastly different meanings."); printFlowerInfo(flowers, flowerName, 1); System.out.println("Type the colour you want to add into the bouquet, or 'cancel' to return to the main menu."); } + + /** + * Prints a table comparing two flowers. + */ + public void printCompareFlowers(ArrayList firstFilteredFlowers, ArrayList secondFilteredFlowers) + throws FlorizzException { + List tableData = new ArrayList<>(List.of()); + int id = 1; + + for (Flower flower : firstFilteredFlowers) { + tableData.add(new TableData(id, flower.getFlowerName(), flower.getColour(), flower.tableOccasionToString(), + flower.tableMeaningToString(), String.format("%.2f", flower.getPrice()) + , flower.getType().toString())); + id++; + } + for (Flower flower : secondFilteredFlowers) { + tableData.add(new TableData(id, flower.getFlowerName(), flower.getColour(), flower.tableOccasionToString(), + flower.tableMeaningToString(), String.format("%.2f", flower.getPrice()) + , flower.getType().toString())); + id++; + } + printBreakLine(); + System.out.println("Here is a table of comparison between the two flowers:"); + printFlowersTable(tableData); + printBreakLine(); + } + + /** + * Prints a table of flowers. + * + * @param tableData The list of flowers to be printed in a table + * @throws FlorizzException If there are no flowers to display + */ + protected void printFlowersTable(List tableData) throws FlorizzException{ + if (tableData.isEmpty()){ + throw new FlorizzException("No flowers to display."); + } + System.out.println(AsciiTable.getTable(AsciiTable.BASIC_ASCII_NO_DATA_SEPARATORS, tableData, Arrays.asList( + new Column().header("No.").dataAlign(HorizontalAlign.CENTER) + .with((TableData data) -> Integer.toString(data.getId())), + new Column().header("Flower Name").dataAlign(HorizontalAlign.LEFT) + .with(TableData::getFlowerName), + new Column().header("Colour").dataAlign(HorizontalAlign.LEFT) + .with(TableData::getFlowerColor), + new Column().header("Occasion").dataAlign(HorizontalAlign.LEFT) + .with(TableData::getFlowerOccasion), + new Column().header("Meaning").dataAlign(HorizontalAlign.LEFT) + .with(TableData::getFlowerMeaning), + new Column().header("Type").dataAlign(HorizontalAlign.LEFT) + .with(TableData::getType), + new Column().header("Price ($)").dataAlign(HorizontalAlign.RIGHT) + .with(TableData::getFlowerPrice)))); + } + /** * Prints a message indicating that the command has been canceled and the user is returning to the main menu. */ diff --git a/src/main/java/florizz/objects/Flower.java b/src/main/java/florizz/objects/Flower.java index 67046fa08d..98aef3fc09 100644 --- a/src/main/java/florizz/objects/Flower.java +++ b/src/main/java/florizz/objects/Flower.java @@ -31,7 +31,7 @@ public enum Occasion { } public enum Type { - FLOWER, FILLER + MAIN_FLOWER, FILLER } /** @@ -194,6 +194,9 @@ public Double getPrice () { return price; } + public ArrayList getMeanings() { + return meanings; + } /** * Generates a string representation of the Flower object. * @return A string representation of the Flower object. @@ -233,6 +236,48 @@ public String toString() { finalMeaning); } + /** + * Generates a string representation of the occasion of the Flower object for the table. + * @return A string representation of the occasion of the Flower object for the table. + */ + public String tableOccasionToString() { + String finalOccasion; + StringBuilder occasionsString = new StringBuilder(); + for (Occasion occasion : occasions){ + occasionsString.append(occasionToString(occasion)); + occasionsString.append(", "); + } + if (!(occasionsString.toString().isEmpty())) { + finalOccasion = occasionsString.substring(0,occasionsString.lastIndexOf(",")); + } else { + finalOccasion = "-"; + } + return finalOccasion; + } + + /** + * Generates a string representation of the meaning of the Flower object for the table. + * @return A string representation of the meaning of the Flower object for the table. + */ + public String tableMeaningToString() { + String finalMeaning; + StringBuilder meaningsString = new StringBuilder(); + for (String meaning : meanings){ + meaningsString.append(meaning); + meaningsString.append(", "); + } + if (!(meaningsString.toString().isEmpty())) { + finalMeaning = meaningsString.substring(0,meaningsString.lastIndexOf(",")); + } else { + finalMeaning = "-"; + } + return finalMeaning; + } + + public Type getType() { + return type; + } + @Override public boolean equals(Object obj) { if (obj == this) { diff --git a/src/main/java/florizz/objects/TableData.java b/src/main/java/florizz/objects/TableData.java new file mode 100644 index 0000000000..ad1f824441 --- /dev/null +++ b/src/main/java/florizz/objects/TableData.java @@ -0,0 +1,71 @@ +package florizz.objects; + +public class TableData { + private int id; + private String command; + private String explanation; + private String example; + private String flowerName; + private String flowerOccasion; + private String flowerPrice; + private String flowerColor; + private String flowerMeaning; + private String type; + + public TableData(int id, String command, String explanation, String example) { + this.id = id; + this.command = command; + this.explanation = explanation; + this.example = example; + } + + public TableData(int id, String flowerName, String flowerColor, String flowerOccasion, + String flowerMeaning, String flowerPrice, String type) { + this.id = id; + this.flowerName = flowerName; + this.flowerOccasion = flowerOccasion; + this.flowerColor = flowerColor; + this.flowerMeaning = flowerMeaning; + this.flowerPrice = flowerPrice; + this.type = type; + } + + public int getId() { + return id; + } + + public String getCommand() { + return command; + } + + public String getExplanation() { + return explanation; + } + + public String getExample() { + return example; + } + + public String getFlowerName() { + return flowerName; + } + + public String getFlowerOccasion() { + return flowerOccasion; + } + + public String getFlowerPrice() { + return flowerPrice; + } + + public String getFlowerColor() { + return flowerColor; + } + + public String getFlowerMeaning() { + return flowerMeaning; + } + public String getType() { + return type; + } +} diff --git a/src/test/java/florizz/command/CompareCommandTest.java b/src/test/java/florizz/command/CompareCommandTest.java new file mode 100644 index 0000000000..79129595fb --- /dev/null +++ b/src/test/java/florizz/command/CompareCommandTest.java @@ -0,0 +1,42 @@ +package florizz.command; + +import florizz.core.FlorizzException; +import florizz.core.Ui; +import florizz.objects.Bouquet; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CompareCommandTest { + + @Test + void testCompareExecute() { // Comparing two different flowers + CompareCommand testCompareCommand = new CompareCommand("Rose", "Lily"); + ArrayList testList = new ArrayList<>(); + Ui ui = new Ui(); + try { + assertTrue(testCompareCommand.execute(testList, ui)); + } catch (FlorizzException error) { + ui.printError(error); + } + } + + @Test + void testCompareException1() { // Comparing the same flower + ArrayList testList = new ArrayList<>(); + Ui ui = new Ui(); + CompareCommand testCompareCommand2 = new CompareCommand("Rose", "Rose"); + assertThrows(FlorizzException.class, () -> testCompareCommand2.execute(testList, ui)); + } + + @Test + void testCompareException2() { // Comparing a flower that does not exist + ArrayList testList = new ArrayList<>(); + Ui ui = new Ui(); + CompareCommand testCompareCommand3 = new CompareCommand("Rose", "Tulip"); + assertThrows(FlorizzException.class, () -> testCompareCommand3.execute(testList, ui)); + } +} diff --git a/text-ui-test/EXPECTED-UNIX.TXT b/text-ui-test/EXPECTED-UNIX.TXT index 91154c460d..75494afd42 100644 --- a/text-ui-test/EXPECTED-UNIX.TXT +++ b/text-ui-test/EXPECTED-UNIX.TXT @@ -8,22 +8,7 @@ Hello from |_| |_|\___/|_| |_/___/___| -Type `help`, to view a list of valid commands! -What can I do for you? -Here are the list of commands you can use: -1. new - Add a bouquet -2. delete - Delete a bouquets -3. mybouquets - List current saved bouquets -4. info - Provide information on chosen flower -5. add /c (optional) /q /to - add flower to a bouquet -6. remove /c (optional) /q /from - remove flower from a bouquet -7. flowers - Shows a list of flowers that can be added into mybouquets -8. flowers - Shows a list of flowers associated with said occasion -9. occasion - Shows a list of occasions associated with available flowers -10. save - Saves a bouquet to an external .txt file -11. recommend - Recommends a bouquet based on the chosen occasion and colour -12. bye - Exits the programme -____________________________________________________________ +Type `help`, to view a table of valid commands! What can I do for you? Added new bouquet to list: test diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 91154c460d..75494afd42 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -8,22 +8,7 @@ Hello from |_| |_|\___/|_| |_/___/___| -Type `help`, to view a list of valid commands! -What can I do for you? -Here are the list of commands you can use: -1. new - Add a bouquet -2. delete - Delete a bouquets -3. mybouquets - List current saved bouquets -4. info - Provide information on chosen flower -5. add /c (optional) /q /to - add flower to a bouquet -6. remove /c (optional) /q /from - remove flower from a bouquet -7. flowers - Shows a list of flowers that can be added into mybouquets -8. flowers - Shows a list of flowers associated with said occasion -9. occasion - Shows a list of occasions associated with available flowers -10. save - Saves a bouquet to an external .txt file -11. recommend - Recommends a bouquet based on the chosen occasion and colour -12. bye - Exits the programme -____________________________________________________________ +Type `help`, to view a table of valid commands! What can I do for you? Added new bouquet to list: test diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 468ae301eb..95dbd950c7 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,4 +1,3 @@ -help new test mybouquets bye \ No newline at end of file