diff --git a/.gitignore b/.gitignore index 5e59b862ba4..5534e7b3e50 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,6 @@ src/main/resources/docs/ /*.iml # Storage/log files -/data/ /config.json /preferences.json /*.log.* diff --git a/README.adoc b/README.adoc index e36efe534bb..5dcc22436ef 100644 --- a/README.adoc +++ b/README.adoc @@ -1,11 +1,10 @@ -= Address Book (Level 3) += HealthyBaby ifdef::env-github,env-browser[:relfileprefix: docs/] -https://travis-ci.org/se-edu/addressbook-level3[image:https://travis-ci.org/se-edu/addressbook-level3.svg?branch=master[Build Status]] -https://ci.appveyor.com/project/damithc/addressbook-level3[image:https://ci.appveyor.com/api/projects/status/3boko2x2vr5cc3w2?svg=true[Build status]] -https://coveralls.io/github/se-edu/addressbook-level3?branch=master[image:https://coveralls.io/repos/github/se-edu/addressbook-level3/badge.svg?branch=master[Coverage Status]] +https://travis-ci.org/AY1920S2-CS2103T-T10-1/main[image:https://travis-ci.org/AY1920S2-CS2103T-T10-1/main.svg?branch=master[Build Status]] +https://coveralls.io/github/AY1920S2-CS2103T-T10-1/main/badge.svg?branch=master[image:https://coveralls.io/repos/github/AY1920S2-CS2103T-T10-1/main/badge.svg?branch=master[Coverage Status]] https://www.codacy.com/app/damith/addressbook-level3?utm_source=github.com&utm_medium=referral&utm_content=se-edu/addressbook-level3&utm_campaign=Badge_Grade[image:https://api.codacy.com/project/badge/Grade/fc0b7775cf7f4fdeaf08776f3d8e364a[Codacy Badge]] - +https://ci.appveyor.com/project/beatricetay/main/branch/master[image:https://ci.appveyor.com/api/projects/status/c6c2aoltu3mhq0rr/branch/master?svg=true[Build status]] ifdef::env-github[] image::docs/images/Ui.png[width="600"] @@ -15,20 +14,21 @@ ifndef::env-github[] image::images/Ui.png[width="600"] endif::[] -* This is a desktop Address Book application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). -* It is a Java sample application intended for students learning Software Engineering while using Java as the main programming language. -* It is *written in OOP fashion*. It provides a *reasonably well-written* code example that is *significantly bigger* (around 6 KLoC)than what students usually write in beginner-level SE modules. +* This is a desktop application named Healthy Baby which allows its users to search for recipes and set personal goals. +* It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). +* It is a Java application intended for university students who wish to lead a healthier lifestyle. +* It is *written in OOP fashion*. == Site Map * <> * <> -* <> * <> * <> == Acknowledgements +* This project was inspired by the AddressBook-Level3 project by https://se-education.org[SE-EDU initiative] * Some parts of this sample application were inspired by the excellent http://code.makery.ch/library/javafx-8-tutorial/[Java FX tutorial] by _Marco Jakob_. * Libraries used: https://openjfx.io/[JavaFX], https://github.com/FasterXML/jackson[Jackson], https://github.com/junit-team/junit5[JUnit5] diff --git a/build.gradle b/build.gradle index 93029ef8262..dbfcd05544c 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ plugins { } // Specifies the entry point of the application -mainClassName = 'seedu.address.Main' +mainClassName = 'seedu.recipe.Main' sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 @@ -67,7 +67,7 @@ dependencies { } shadowJar { - archiveName = 'addressbook.jar' + archiveName = 'healthybaby.jar' destinationDir = file("${buildDir}/jar/") } @@ -133,8 +133,8 @@ asciidoctor { idprefix: '', // for compatibility with GitHub preview idseparator: '-', 'site-root': "${sourceDir}", // must be the same as sourceDir, do not modify - 'site-name': 'AddressBook-Level3', - 'site-githuburl': 'https://github.com/se-edu/addressbook-level3', + 'site-name': 'HealthyBaby', + 'site-githuburl': 'https://github.com/AY1920S2-CS2103T-T10-1/main', 'site-seedu': true, // delete this line if your project is not a fork (not a SE-EDU project) ] diff --git a/data/cookedrecords.json b/data/cookedrecords.json new file mode 100644 index 00000000000..780930120f3 --- /dev/null +++ b/data/cookedrecords.json @@ -0,0 +1,11 @@ +{ + "records" : [ { + "name" : "Asian BBQ Chicken", + "date" : "2020-04-13", + "goals" : [ "Bulk like the Hulk" ] + }, { + "name" : "Sweet and Sour Chicken", + "date" : "2020-04-13", + "goals" : [ "Bulk like the Hulk", "Herbivore", "Fruity Fiesta" ] + } ] +} diff --git a/data/plannedbook.json b/data/plannedbook.json new file mode 100644 index 00000000000..8640ef9f7a5 --- /dev/null +++ b/data/plannedbook.json @@ -0,0 +1,45 @@ +{ + "plannedRecipes" : [ { + "recipe" : { + "name" : "Asian BBQ Chicken", + "time" : "30", + "isFavourite" : false, + "grains" : [ ], + "vegetables" : [ "1.0tbsp, Garlic & ginger (finely chopped)" ], + "proteins" : [ "100.0g, Chicken breast" ], + "fruits" : [ ], + "others" : [ "2.0tbsp, Char siew sauce", "1.0tsp, Honey", "1.0tbsp, Rice vinegar", "1.0tsp, Salt & pepper", "0.5tsp, Sesame oil" ], + "steps" : [ "In a bowl, mix all the ingredients to create marinade. Mix the chicken with the marinade.", "Pan sear the chicken from both sides.", "Serve with rice." ], + "goals" : [ "Bulk like the Hulk" ] + }, + "date" : "2020-04-20" + }, { + "recipe" : { + "name" : "Asian BBQ Chicken", + "time" : "30", + "isFavourite" : false, + "grains" : [ ], + "vegetables" : [ "1.0tbsp, Garlic & ginger (finely chopped)" ], + "proteins" : [ "100.0g, Chicken breast" ], + "fruits" : [ ], + "others" : [ "2.0tbsp, Char siew sauce", "1.0tsp, Honey", "1.0tbsp, Rice vinegar", "1.0tsp, Salt & pepper", "0.5tsp, Sesame oil" ], + "steps" : [ "In a bowl, mix all the ingredients to create marinade. Mix the chicken with the marinade.", "Pan sear the chicken from both sides.", "Serve with rice." ], + "goals" : [ "Bulk like the Hulk" ] + }, + "date" : "2020-05-12" + }, { + "recipe" : { + "name" : "Sweet and Sour Chicken", + "time" : "20", + "isFavourite" : false, + "grains" : [ ], + "vegetables" : [ "1.0cup, Bell peppers", "1.0cup, Carrots (diced)", "1.0cup, Chinese cabbage (diced)", "10.0g, Garlic cloves", "10.0g, Knob ginger", "1.0cup, Onions (diced)" ], + "proteins" : [ "300.0g, Chicken", "50.0g, Egg" ], + "fruits" : [ "1.0cup, Pineapple (diced)", "1.0tbsp, Tomato juice" ], + "others" : [ "10.0g, Coriander (optional)", "1.5tsp, Corn flour", "1.0tsp, Light soya sauce", "1.0tbsp, Vegetable oil" ], + "steps" : [ "Pound garlic and ginger into a paste. Marinade chicken in the paste, along with corn flour, soy sauce, and salt.", "In a wok, take some oil, saute the carrots, cabbage, onions, and bell peppers. Add tomato juice and bring to a slight boil.", "Fry the chicken and add to the wok along with some stock and set to simmer.", "Garnish with coriander and serve with rice." ], + "goals" : [ "Bulk like the Hulk", "Herbivore", "Fruity Fiesta" ] + }, + "date" : "2020-05-12" + } ] +} diff --git a/data/quotebook.json b/data/quotebook.json new file mode 100644 index 00000000000..c88fb7aaa91 --- /dev/null +++ b/data/quotebook.json @@ -0,0 +1,21 @@ +{ + "quotes" : [ { + "content" : "Skip the diet, just eat healthy!", + "quotes" : [ ] + }, { + "content" : "I don't eat junk food because I love my body!", + "quotes" : [ ] + }, { + "content" : "Nothing tastes as good as healthy", + "quotes" : [ ] + }, { + "content" : "I'm doing this for me", + "quotes" : [ ] + }, { + "content" : "Work for it!", + "quotes" : [ ] + }, { + "content" : "Mindset is what separates the best from the rest", + "quotes" : [ ] + } ] +} diff --git a/data/recipebook.json b/data/recipebook.json new file mode 100644 index 00000000000..aa806b8bbea --- /dev/null +++ b/data/recipebook.json @@ -0,0 +1,135 @@ +{ + "recipes" : [ { + "name" : "Asian BBQ Chicken", + "time" : "30", + "isFavourite" : false, + "grains" : [ ], + "vegetables" : [ "1.0tbsp, Garlic & ginger (finely chopped)" ], + "proteins" : [ "100.0g, Chicken breast" ], + "fruits" : [ ], + "others" : [ "2.0tbsp, Char siew sauce", "1.0tsp, Honey", "1.0tbsp, Rice vinegar", "1.0tsp, Salt & pepper", "0.5tsp, Sesame oil" ], + "steps" : [ "In a bowl, mix all the ingredients to create marinade. Mix the chicken with the marinade.", "Pan sear the chicken from both sides.", "Serve with rice." ], + "goals" : [ "Bulk like the Hulk" ] + }, { + "name" : "Sweet and Sour Chicken", + "time" : "20", + "isFavourite" : false, + "grains" : [ ], + "vegetables" : [ "1.0cup, Bell peppers", "1.0cup, Carrots (diced)", "1.0cup, Chinese cabbage (diced)", "10.0g, Garlic cloves", "10.0g, Knob ginger", "1.0cup, Onions (diced)" ], + "proteins" : [ "300.0g, Chicken", "50.0g, Egg" ], + "fruits" : [ "1.0cup, Pineapple (diced)", "1.0tbsp, Tomato juice" ], + "others" : [ "10.0g, Coriander (optional)", "1.5tsp, Corn flour", "1.0tsp, Light soya sauce", "1.0tbsp, Vegetable oil" ], + "steps" : [ "Pound garlic and ginger into a paste. Marinade chicken in the paste, along with corn flour, soy sauce, and salt.", "In a wok, take some oil, saute the carrots, cabbage, onions, and bell peppers. Add tomato juice and bring to a slight boil.", "Fry the chicken and add to the wok along with some stock and set to simmer.", "Garnish with coriander and serve with rice." ], + "goals" : [ "Bulk like the Hulk", "Herbivore", "Fruity Fiesta" ] + }, { + "name" : "Quick Carrot Daikon Stir-fry", + "time" : "25", + "isFavourite" : false, + "grains" : [ ], + "vegetables" : [ "120.0g, Carrot (julienned)", "50.0g, Daikon radish (peeled and julienned)", "30.0g, Garlic (smashed and chopped)", "30.0g, Ginger (julienned)", "30.0g, Scallions" ], + "proteins" : [ "50.0g, Egg" ], + "fruits" : [ ], + "others" : [ "1.5tbsp, Oyster sauce", "0.5tsp, Salt", "0.5tsp, Sesame oil", "1.0tbsp, Shaoxing wine", "3.0tbsp, Vegetable oil", "0.3cup, Water", "0.3tsp, White pepper" ], + "steps" : [ "Heat oil in wok over medium heat. Add ginger and garlic and cook for 20 seconds.", "Add carrot and stir-fry for 30 seconds - oil should turn orange colour. Add in daikon, turn up heat to high and stir-fry for another 30 seconds.", "Add shaoxing wine, oyster sauce, white pepper, sesame oil, salt, water, and white parts of the scallions. Stir to combine, cover, turn down heat to medium. Simmer for 5-8 minutes until tender.", "Uncover, add in rest of the scallions and mix everything well. When daikon is translucent and tender, the dish is done." ], + "goals" : [ "Herbivore" ] + }, { + "name" : "Chinese Tomato Egg Stir-fry", + "time" : "10", + "isFavourite" : false, + "grains" : [ ], + "vegetables" : [ "10.0g, Scallion", "30.0g, Tomatoes" ], + "proteins" : [ "50.0g, Egg" ], + "fruits" : [ ], + "others" : [ "0.8tsp, Salt", "0.5tsp, Sesame oil", "1.0tsp, Shaoxing wine", "2.0tsp, Sugar", "3.0tbsp, Vegetable oil", "0.3cup, Water", "0.3tsp, White pepper" ], + "steps" : [ "Cut tomatoes into small wedges and finely chop scallion", "Crack eggs into bowl and season with ¼ tsp salt, white pepper", "sesame oil, and shaoxing wine. Beat the eggs.", "Preheat wok over medium heat until it starts to smoke. Add 2 tbsp of oil and immediately add eggs. Scramble the eggs and remove from wok immediately. Set aside.", "Add the remaining tbsp of oil to the wok, turn up heat to high, add tomatoes and scallions. Stir-fry for 1min, then add sugar, 0.5 tsp salt, and water. If water cooks off too quickly, add a little more water. Add the cooked eggs.", "Mix everything together, cover the wok, cook for 1-2mins until the tomatoes are completely softened.", "Uncover, continue to stir-fry over high heat until sauce thickens to your liking. Serve!" ], + "goals" : [ ] + }, { + "name" : "5 Ingredient Spelt Spaghetti", + "time" : "25", + "isFavourite" : false, + "grains" : [ "80.0g, Spelt spaghetti" ], + "vegetables" : [ "2.0cup, Arugula (salad rockets)", "50.0g, Leek", "300.0g, Tomatoes", "300.0g, Zucchini" ], + "proteins" : [ "50.0g, Egg" ], + "fruits" : [ ], + "others" : [ "1.0tbsp, Fresh basil", "2.0tbsp, Italian herbs", "0.5tbsp, Olive oil", "1.0tbsp, Pepper", "2.0tbsp, Salt", "2.0tbsp, Xucker ketchup" ], + "steps" : [ "Thinly slice Tomatoes and Leek and shred your Zucchini.", "Heat up Oil in a large Pan on a medium-high Level and roast Leek until golden.", "Now add Zucchini.", "When the Zucchini´s roasted, stir in Tomatoes and turn down Heat to a lower Level.", "Let cook for 5-7 Minutes until it turn into a Sauce.", "Meanwhile, prepare Spaghetti according to the Directions stated on the Package.", "Then, add Ketchup, Basil, Italian Herbs and Salt, Pepper as desired.", "Finally, stir in Arugula and cooked Noodles and serve on a Plate with Poached Egg, Parmesan and more fresh Basil." ], + "goals" : [ "Wholesome Wholemeal", "Herbivore" ] + }, { + "name" : "Bacon, Spinach Caramelized Onion Pasta", + "time" : "25", + "isFavourite" : false, + "grains" : [ "170.0g, Whole wheat penne pasta" ], + "vegetables" : [ "10.0g, Large yellow onion diced", "1.0cup, Spinach" ], + "proteins" : [ "120.0g, Chopped bacon" ], + "fruits" : [ ], + "others" : [ "1.0tbsp, Brown sugar", "2.0tbsp, Butter", "1.0tbsp, Garlic powder", "0.5cup, Parmesan cheese sprinkles", "1.0tbsp, Pepper", "1.0tbsp, Salt" ], + "steps" : [ "In a large skillet, add your bacon and cook for 1-2 mins until bacon is halfway done", "In that same pan, and some butter, sugar, spices, and onion; sautee until the onion becomes tender, and bacon starts to crisp up.", "Boil pasta in salted water until al dente", "Once the pasta is done, drain it loosely, but leave a tiny amount of water and add it to the skillet with the bacon, and onion mixture.", "Mix in the spinach and stir until tender", "Sprinkle with Parmesan before serving." ], + "goals" : [ "Wholesome Wholemeal", "Bulk like the Hulk", "Herbivore" ] + }, { + "name" : "Healthy Chicken Salad Sandwich", + "time" : "10", + "isFavourite" : false, + "grains" : [ "80.0g, Whole wheat pita (toasted)" ], + "vegetables" : [ "55.0g, Butter lettuce (chopped)", "120.0g, Celery (chopped small)" ], + "proteins" : [ "200.0g, Chicken breasts (large, cooked)", "350.0g, Greek yogurt (non-fat)", "30.0g, Mixed nuts (chopped)" ], + "fruits" : [ ], + "others" : [ "1.0tbsp, Dijon mustard (whole grain dijon)", "1.0tbsp, Garlic salt", "3.0tbsp, Mayonnaise" ], + "steps" : [ "Toast one pita.", "Prep ingredients by cooking, and then shredding or chopping 1/2 large chicken breast, chop 1-2 stalks celery to get 1/4 c chopped celery, quarter a handful of grapes to get 1/4 cup quartered grapes, prepare lettuce by washing/chopping it if needed. Also prepare nuts by chopping them if needed, making 1 tbsp chopped nuts.", "Make chicken salad by adding shredded/chopped chicken to a small mixing bowl, then add 1/4 c Greek yogurt, 1/4 c mayo, 1/4 tsp garlic salt, 1 tsp Dijon mustard.", "Mix together well. Once all incorporated, add in 1/4 c chopped celery, 1/4 c quartered red grapes, and 1 T chopped mixed nuts. Stir together.", "Fill pita with chicken salad mixture and lettuce. Enjoy. Store chicken salad in airtight container for up to 5 days" ], + "goals" : [ "Wholesome Wholemeal", "Bulk like the Hulk" ] + }, { + "name" : "All Veggie Sandwich", + "time" : "10", + "isFavourite" : false, + "grains" : [ "300.0g, Whole-wheat bread" ], + "vegetables" : [ "1.0cup, Baby spinach leaves", "1.0cup, Fresh pea shoots or your favorite fresh sprouts", "20.0g, Red bell pepper(seeded and sliced))", "50.0g, Ripe avocados", "40.0g, Thinly sliced cucumber" ], + "proteins" : [ ], + "fruits" : [ ], + "others" : [ "1.0tbsp, Cilantro leaves", "2.0tbsp, Kosher salt and fresh black pepper", "4.0tbsp, Plain hummus" ], + "steps" : [ "Spread 1 tablespoon of hummus on each slice of bread.", "Then add the avocado pulp of 1/2 avocado per slice and lightly mash with a fork.", "Depending on the size of your bread slices you may need to use little less avocado. I used about 1 avocado per sandwich.", "Layer on spinach leaves, cucumber slices, red pepper, pea shoots, and cilantro leaves. Generously season with salt and pepper. Top with other slice of bread and enjoy." ], + "goals" : [ "Wholesome Wholemeal", "Herbivore" ] + }, { + "name" : "Summer Asian Slaw", + "time" : "25", + "isFavourite" : false, + "grains" : [ ], + "vegetables" : [ "15.0g, Fresh basil (thai basil, and/or mint)", "10.0g, Pepitas (with or without sesame seeds)", "20.0g, Poblano", "30.0g, Red bell", "10.0g, Scallions", "200.0g, Shredded red and/or green cabbage", "15.0g, Thai chiles (dice)" ], + "proteins" : [ "3.0tbsp, Cashew or peanut butter", "20.0g, Toasted peanuts" ], + "fruits" : [ "0.5tbsp, Lime juice", "50.0g, Ripe peach (thinly sliced)" ], + "others" : [ "15.0g, Chopped cilantro (including stems)", "1.0tbsp, Sea salt", "0.3tbsp, Sesame oil", "1.0tbsp, Water", "0.5tbsp, White miso paste" ], + "steps" : [ "Make the dressing: In a small bowl, whisk together the cashew butter, miso paste, lime juice, sesame oil, and ginger. Whisk in enough water to create a drizzable consistency. Set aside.", "In a dry cast-iron skillet over medium heat, char the peppers whole, rotating until the edges have a little char, about 2 minutes per side. Remove. When cool to the touch, slice in half lengthwise, remove the stem, ribbing, and seeds and slice horizontally into thin strips.", "In a large bowl, combine the cabbage, peppers, scallions, cilantro, basil, chiles, and ¾ of the dressing. Toss until combined. Add the remaining dressing, if desired, and season to taste with a few pinches of sea salt. Serve topped with the toasted nuts, seeds, and sliced peaches." ], + "goals" : [ "Herbivore" ] + }, { + "name" : "Avocado Couscous Grapefruit salad with honey lime dressing", + "time" : "35", + "isFavourite" : false, + "grains" : [ "0.8cup, Uncooked whole wheat couscous", "100.0g, White beans" ], + "vegetables" : [ ], + "proteins" : [ ], + "fruits" : [ "3.0tbsp, Freshly squeezed lime juice (for dressing)", "300.0g, Large avocados", "200.0g, Large ruby red grapefruit" ], + "others" : [ "3.0tbsp, Chopped fresh mint", "0.5cup, Crumbled feta cheese", "2.0tbsp, Extra virgin olive oil", "3.0tbsp, Finely chopped fresh cilantro", "2.0tbsp, Honey", "0.3tbsp, Kosher salt", "0.8cup, Low sodium stock" ], + "steps" : [ "In a small saucepan, bring the stock to a boil. Remove from the heat, stir in the couscous, then cover at let sit 5 minutes. Fluff with fork and set aside.", "In a small bowl or large measuring cup,whisk together the dressing ingredients: lime juice, honey, olive oil, and salt, or shake all of the ingredients together in a mason jar with a tight-fitting lid.", "In a large bowl, combine beans and couscous. Pour dressing over top and stir to combine. Add the avocados, grapefruit, feta, mint, and cilantro. Toss gently. Serve chilled or at room temperature." ], + "goals" : [ "Wholesome Wholemeal", "Fruity Fiesta" ] + }, { + "name" : "Teriyaki chicken noodle bowl", + "time" : "35", + "isFavourite" : false, + "grains" : [ ], + "vegetables" : [ "50.0g, Cloves garlic(minced)", "0.3tbsp, Freshly grated ginger", "20.0g, Green onion (thinly sliced)" ], + "proteins" : [ "100.0g, Boneless and skinless chicken thighs(cut into 1-inch chunks)" ], + "fruits" : [ ], + "others" : [ "3.0tsp, Brown sugar(packed)", "4.0tbsp, Cornstarch", "0.5tbsp, Honey", "0.3tbsp, Olive oil", "4.0tsp, Reduced sodium soy sauce", "150.0g, Refrigerated yaki-soba, seasoning sauce packets discarded", "0.3tbsp, Sesame seeds" ], + "steps" : [ "In a large pot of boiling water, add Yaki-Soba until loosened, about 1-2 minutes; drain well.", "In a small bowl, whisk together cornstarch and 1/4 cup water; set aside.", "In a small saucepan over medium heat, add soy sauce, brown sugar, garlic, ginger, honey and 1 cup water; bring to a simmer. Stir in cornstarch mixture until thickened enough to coat the back of a spoon, about 2 minutes; let cool to room temperature. Reserve 1/4 cup and set aside.", "In a gallon size Ziploc bag or large bowl, combine soy sauce mixture and chicken; marinate for at least 30 minutes to overnight, turning the bag occasionally. Drain the chicken from the marinade.", "Heat olive oil in a large skillet over medium heat. Add chicken and cook until golden brown and cooked through, about 3-4 minutes; set aside.", "Stir in Yaki-Soba and 1/4 cup reserved soy sauce mixture until well combined, about 2 minutes.", "Serve immediately, garnished with sesame seeds and green onion, if desired." ], + "goals" : [ "Bulk like the Hulk" ] + }, { + "name" : "Overnight Oatmeal", + "time" : "10", + "isFavourite" : false, + "grains" : [ "1.0cup, Steel cut oats" ], + "vegetables" : [ ], + "proteins" : [ ], + "fruits" : [ "1.0cup, Dried cranberries", "1.0cup, Dried figs" ], + "others" : [ "0.5cup, Milk", "4.0cup, Water" ], + "steps" : [ "In a slow cooker, combine all ingredients and set to low heat. Cover and let cook for 8 to 9 hours.", "Stir and remove to serving bowls. This method works best if started before you go to bed." ], + "goals" : [ "Wholesome Wholemeal", "Fruity Fiesta" ] + } ] +} diff --git a/docs/AboutUs.adoc b/docs/AboutUs.adoc index 458e6134f45..734793be812 100644 --- a/docs/AboutUs.adoc +++ b/docs/AboutUs.adoc @@ -4,53 +4,45 @@ :imagesDir: images :stylesDir: stylesheets -AddressBook - Level 3 was developed by the https://se-edu.github.io/docs/Team.html[se-edu] team. + -_{The dummy content given below serves as a placeholder to be used by future forks of the project.}_ + +HealthyBaby (HYBB) was developed by the https://github.com/AY1920S2-CS2103T-T10-1/main[AY1920S2-CS2103T-T10-1] team. + {empty} + We are a team based in the http://www.comp.nus.edu.sg[School of Computing, National University of Singapore]. == Project Team -=== John Doe -image::damithc.jpg[width="150", align="left"] -{empty}[http://www.comp.nus.edu.sg/~damithch[homepage]] [https://github.com/damithc[github]] [<>] +=== Tiyari Harshita +image::tharshita.png[width="150", align="left"] +{empty}[https://github.com/tharshita[github]] [<>] -Role: Project Advisor - -''' - -=== John Roe -image::lejolly.jpg[width="150", align="left"] -{empty}[http://github.com/lejolly[github]] [<>] - -Role: Team Lead + -Responsibilities: UI +Role: Developer + +Responsibilities: Testing + Scheduling and tracking + Developing `Goals` component ''' -=== Johnny Doe -image::yijinl.jpg[width="150", align="left"] -{empty}[http://github.com/yijinl[github]] [<>] +=== Lee Yue Tong +image::yuuton9.png[width="150", align="left"] +{empty}[https://github.com/YuuTon9[github]] [<>] Role: Developer + -Responsibilities: Data +Responsibilities: Testing + Code quality + Developing `Achievements` component ''' -=== Johnny Roe -image::m133225.jpg[width="150", align="left"] -{empty}[http://github.com/m133225[github]] [<>] +=== Beatrice Tay +image::beatricetay.png[width="150", align="left"] +{empty}[https://github.com/beatricetay[github]] [<>] -Role: Developer + -Responsibilities: Dev Ops + Threading +Role: Team Lead + +Responsibilities: Overall project coordination + Integration + Developing `Planning` component ''' -=== Benson Meier -image::yl_coder.jpg[width="150", align="left"] -{empty}[http://github.com/yl-coder[github]] [<>] +=== Brian Pek +image::pekchinsiongbrian.png[width="150", align="left"] +{empty}[https://github.com/pekchinsiongbrian[github]] [<>] Role: Developer + -Responsibilities: UI +Responsibilities: Documentation + Deliverables and deadlines + Developing `Advanced Filter`, `Undo/Redo`, and `Recipe +Customisation` components ''' diff --git a/docs/ContactUs.adoc b/docs/ContactUs.adoc index 81be279ef6d..d13bc3e2933 100644 --- a/docs/ContactUs.adoc +++ b/docs/ContactUs.adoc @@ -2,6 +2,10 @@ :site-section: ContactUs :stylesDir: stylesheets -* *Bug reports, Suggestions* : Post in our https://github.com/se-edu/addressbook-level3/issues[issue tracker] if you noticed bugs or have suggestions on how to improve. +* *Bug reports, Suggestions* : Post in our https://github.com/AY1920S2-CS2103T-T10-1/main/issues[issue tracker] if you noticed bugs or have suggestions on how to improve. * *Contributing* : We welcome pull requests. Follow the process described https://github.com/oss-generic/process[here] -* *Email us* : You can also reach us at `damith [at] comp.nus.edu.sg` +* *Email us* : You can also reach us at the following emails: + ** Harshita: `harshita.tiyari@u.nus.edu` + ** Yue Tong: `leeyuetong@u.nus.edu` + ** Beatrice: `beatricetayyt@gmail.com` + ** Brian: `pekchinsiongbrian@gmail.com` diff --git a/docs/DevOps.adoc b/docs/DevOps.adoc index 2aa5a6bc0c1..177f8332b4f 100644 --- a/docs/DevOps.adoc +++ b/docs/DevOps.adoc @@ -1,4 +1,4 @@ -= AddressBook Level 3 - Dev Ops += HealthyBaby - Dev Ops :site-section: DeveloperGuide :toc: :toc-title: @@ -12,7 +12,7 @@ ifdef::env-github[] :note-caption: :information_source: :warning-caption: :warning: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level3/tree/master +:repoURL: https://github.com/AY1920S2-CS2103T-T10-1/main == Build Automation @@ -34,7 +34,7 @@ When a pull request has changes to asciidoc files, you can use https://www.netli Here are the steps to create a new release. -. Update the version number in link:{repoURL}/src/main/java/seedu/address/MainApp.java[`MainApp.java`]. +. Update the version number in link:{repoURL}/src/main/java/seedu/recipe/MainApp.java[`MainApp.java`]. . Generate a JAR file <>. . Tag the repo with the version number. e.g. `v0.1` . https://help.github.com/articles/creating-releases/[Create a new release using GitHub] and upload the JAR file you created. diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 3d65905a853..0a52cf4836c 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -1,4 +1,4 @@ -= AddressBook Level 3 - Developer Guide += HealthyBaby - Developer Guide :site-section: DeveloperGuide :toc: :toc-title: @@ -12,9 +12,10 @@ ifdef::env-github[] :note-caption: :information_source: :warning-caption: :warning: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level3/tree/master +:repoURL: https://github.com/AY1920S2-CS2103T-T10-1/main -By: `Team SE-EDU`      Since: `Jun 2016`      Licence: `MIT` +end +By: `Team HYBB`      Since: `Mar 2020`      Licence: `MIT` == Setting up @@ -34,7 +35,7 @@ The *_Architecture Diagram_* given above explains the high-level design of the A The `.puml` files used to create diagrams in this document can be found in the link:{repoURL}/docs/diagrams/[diagrams] folder. Refer to the <> to learn how to create and edit diagrams. -`Main` has two classes called link:{repoURL}/src/main/java/seedu/address/Main.java[`Main`] and link:{repoURL}/src/main/java/seedu/address/MainApp.java[`MainApp`]. It is responsible for, +`Main` has two classes called link:{repoURL}/src/main/java/seedu/recipe/Main.java[`Main`] and link:{repoURL}/src/main/java/seedu/recipe/MainApp.java[`MainApp`]. It is responsible for, * At app launch: Initializes the components in the correct sequence, and connects them up with each other. * At shut down: Shuts down the components and invokes cleanup method where necessary. @@ -77,11 +78,11 @@ The sections below give more details of each component. .Structure of the UI Component image::UiClassDiagram.png[] -*API* : link:{repoURL}/src/main/java/seedu/address/ui/Ui.java[`Ui.java`] +*API* : link:{repoURL}/src/main/java/seedu/recipe/ui/Ui.java[`Ui.java`] -The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class. +The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `RecipeListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class. -The `UI` component uses JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the link:{repoURL}/src/main/java/seedu/address/ui/MainWindow.java[`MainWindow`] is specified in link:{repoURL}/src/main/resources/view/MainWindow.fxml[`MainWindow.fxml`] +The `UI` component uses JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the link:{repoURL}/src/main/java/seedu/recipe/ui/MainWindow.java[`MainWindow`] is specified in link:{repoURL}/src/main/resources/view/MainWindow.fxml[`MainWindow.fxml`] The `UI` component, @@ -96,12 +97,12 @@ The `UI` component, image::LogicClassDiagram.png[] *API* : -link:{repoURL}/src/main/java/seedu/address/logic/Logic.java[`Logic.java`] +link:{repoURL}/src/main/java/seedu/recipe/logic/Logic.java[`Logic.java`] -. `Logic` uses the `AddressBookParser` class to parse the user command. +. `Logic` uses the `RecipeBookParser` class to parse the user command. . This results in a `Command` object which is executed by the `LogicManager`. -. The command execution can affect the `Model` (e.g. adding a person). -. The result of the command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`. +. The command execution can affect the `Model` (e.g. adding a recipe). +. The result of the command execution is encapsulated as a `CommandResult` object which is passed git back to the `Ui`. . In addition, the `CommandResult` object can also instruct the `Ui` to perform certain actions, such as displaying help to the user. Given below is the Sequence Diagram for interactions within the `Logic` component for the `execute("delete 1")` API call. @@ -114,22 +115,84 @@ NOTE: The lifeline for `DeleteCommandParser` should end at the destroy marker (X [[Design-Model]] === Model component -.Structure of the Model Component +.Simplified Structure of the Model Component image::ModelClassDiagram.png[] -*API* : link:{repoURL}/src/main/java/seedu/address/model/Model.java[`Model.java`] +*API* : link:{repoURL}/src/main/java/seedu/recipe/model/Model.java[`Model.java`] -The `Model`, +The diagram above has been simplified in order to provide a clearer Overview of the Model component. + +The `Model` consists of 4 main sections: recipe, plan, record and quote. + +For more details on each of the main sections of the `Model`, please refer to the corresponding models +illustrated in the next few sections of this document. -* stores a `UserPref` object that represents the user's preferences. -* stores the Address Book data. -* exposes an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. -* does not depend on any of the other three components. +The `Model` component stores a, -[NOTE] -As a more OOP model, we can store a `Tag` list in `Address Book`, which `Person` can reference. This would allow `Address Book` to only require one `Tag` object per unique `Tag`, instead of each `Person` needing their own `Tag` object. An example of how such a model may look like is given below. + - + -image:BetterModelClassDiagram.png[] +* `UserPref` object that represents the user's preferences. +* `RecipeBook` object that stores all recipes. +* `PlannedBook` object that stores all plans. +* `CookedRecordBook` object that stores the records of all the cooked recipes. +* `QuoteBook` object that stores all quotes. + +It also exposes five unmodifiable lists that can be 'observed' by the `UI`: + + +* `ObservableList` +* `ObservableList` +* `ObservableList` +* `ObservableList` +* `ObservableList` + +The `UI` can be bound to these lists so that the `UI` automatically updates when the data in the list changes. + + +The `Model` does not depend on any of the other three components. + + +==== Recipe Model +.Structure of the Recipe Model +image::ModelRecipeClassDiagram.png[] + +The Recipe Model stores the `UniqueRecipeList` containing all recipes. + +Each `Recipe` consists of, + +* One `Name` +* One `Time` +* Any number of `Step` +* At least one `Ingredient` + +For a more comprehensive description on the structure of a Recipe, please refer to +<> in our User Guide. + +==== Plan Model +.Structure of the Plan Model +image::ModelPlanClassDiagram.png[] + +The Plan Model stores the, + +* `UniquePlannedList` which contains all plans +* `PlannedRecipeMap` which maintains the mapping from `Recipe` to all the plans that uses this `Recipe` + +Each `Plan` consists of, + +* One `Date` +* One `Recipe` + +==== Record Model +.Structure of the Record Model +image::ModelRecordClassDiagram.png[] + +The Record Model stores the `UniqueRecordList` which contains all records. + +Each `Record` consists of, + +* One `Date` +* One `Name` from a `Recipe` +* One set of `Goal` list + +==== Quote Model +.Structure of the Quote Model +image::ModelQuoteClassDiagram.png[] + +The Quote Model stores the `UniqueQuoteList` which contains all quotes. + +Each `Quote` consists of one `Content`. [[Design-Storage]] === Storage component @@ -137,110 +200,654 @@ image:BetterModelClassDiagram.png[] .Structure of the Storage Component image::StorageClassDiagram.png[] -*API* : link:{repoURL}/src/main/java/seedu/address/storage/Storage.java[`Storage.java`] +*API* : link:{repoURL}/src/main/java/seedu/recipe/storage/Storage.java[`Storage.java`] + +In the figure above, we can see that we are maintaining 5 different storages. These storages aim to keep the memory of: + +* `UserPrefs` +* `RecipeBook` +* `PlannedBook` +* `CookedRecords` +* `QuoteBook` The `Storage` component, * can save `UserPref` objects in json format and read it back. -* can save the Address Book data in json format and read it back. +* can save the HYBB data in json format and read it back. [[Design-Commons]] === Common classes -Classes used by multiple components are in the `seedu.addressbook.commons` package. +Classes used by multiple components are in the `seedu.recipe.commons` package. == Implementation This section describes some noteworthy details on how certain features are implemented. -// tag::undoredo[] -=== [Proposed] Undo/Redo feature -==== Proposed Implementation +// tag::basic[] +=== Basic commands -The undo/redo mechanism is facilitated by `VersionedAddressBook`. -It extends `AddressBook` with an undo/redo history, stored internally as an `addressBookStateList` and `currentStatePointer`. -Additionally, it implements the following operations: +==== Switch command (Harshita) +The `switch` command is facilitated by the `MainWindow`, `MainTabPanel`, `SwitchCommandParser` and `SwitchCommandParser`. -* `VersionedAddressBook#commit()` -- Saves the current address book state in its history. -* `VersionedAddressBook#undo()` -- Restores the previous address book state from its history. -* `VersionedAddressBook#redo()` -- Restores a previously undone address book state from its history. +The following lists in sequential order the process of how `switch` behaves with user input. -These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively. +*The user launches HYBB and the default start tab is set to the recipes tab. -Given below is an example usage scenario and how the undo/redo mechanism behaves at each step. +*The user now executes `switch planning` to view the planning tab. -Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state. +*`LogicManager` uses `RecipeBookParser#parseCommand()` to parse the input from the user upon execution of the `switch` command. -image::UndoRedoState0.png[] +*`RecipeBookParser` determines which command is being used and creates `SwitchCommandParser` to parse the input +from the user to obtain the arguments. -Step 2. The user executes `delete 5` command to delete the 5th person in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state. +*`SwitchCommandParser` parses the argument and checks its validity. If it is invalid, +`SwitchCommandParser` throws an exception and terminates. Else, it returns a `SwitchCommand` that contains a `Tab`. -image::UndoRedoState1.png[] +* `LogicManager` uses `SwitchCommand#execute()` to switch to the planning tab. -Step 3. The user executes `add n/David ...` to add a new person. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`. +* `SwitchCommand` returns a `CommandResult` to the `LogicManager` with the `Tab`. `LogicManager` then +returns the `CommandResult` to `MainWindow`. -image::UndoRedoState2.png[] +* `MainWindow` checks if there is a change in state for `Tab` and if switching is needed. If there is, `MainWindow` uses +`MainWindow#handleSwitchTab()` to switch tab. Else, `MainWindow` does nothing. + +The following activity diagram shows the flow of activites from when the `switch` command is executed. + + +image::SwitchActivityDiagram.png[] + +// tag::editcommand[] +==== Edit command (Beatrice) +The edit feature allows users to edit the properties of a Recipe with ease using the `edit` command. + + +This feature is facilitated by the `EditCommand` class. + + +The following activity diagram illustrates how the `EditCommand` is used. + + +.Activity Diagram for edit command +image::EditActivityDiagram.png[] + +===== Implementation +This section explains how the `edit` command is implemented. + +1. User specified arguments are passed to the `EditCommandParser` and the arguments are broken up by the `ArgumentTokenizer` and +`ArgumentMultimap`. + +2. The arguments will then be parsed by `ParserUtil` and passed into `EditRecipeDescriptor`. +An error will be thrown if the inputs were invalid or if no properties of the Recipe were edited. + +3. A new `EditCommand` object will be created containing the new properties of the `Recipe`. + +4. `EditCommand#execute()` will then get the latest list of recipes from `Model` and obtain the `Recipe` that is +being edited. + +5. This `Recipe` is passed into `EditCommand#createEditedRecipe()` which creates a new `Recipe` with the edited properties. + +6. `Model#setRecipe()` will then replace the `Recipe` being edited with the new `Recipe` and update the list of recipes and plans. + +7. The success message will be returned to the user by the `CommandResult`. + +The following sequence diagram summarizes the steps taken so far: + +.Edit sequence diagram +image::EditSequenceDiagram.png[] [NOTE] -If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`. +The lifeline for EditCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, +the lifeline reaches the end of diagram. + +[WARNING] +The details of some methods, like the the usage of `EditRecipeDecriptor`, was omitted to reduce clutter in the diagram. + +The edited recipe will be updated in both the list of recipes and plans. +The following section explains in detail the implementation behind how each list is updated in the +`RecipeBook` and `PlannedBook` class. + +1. Continuing off from Step 8, `ModelManager#setRecipe()` will be called to replace the target `Recipe` with the +edited `Recipe`. (`ModelManager` implements `Model`) + +2. The target and edited `Recipe` is passed into `RecipeBook#setRecipe()` and `UniqueRecipeList#setRecipe()`, which +will replace the target with the edited `Recipe` in the recipe list. + +3. The same arguments are then passed into `PlannedBook#setRecipe()` which will get a list of all the plans that uses +the target `Recipe` from `PlannedRecipeMap`. + +4. If there are no plans that uses `Recipe`, the process stops. However if plans exists, the `PlannedBook` +will iterate through each old plan and update each plan. + +Step 4. is an example of how the `PlannedRecipeMap` can be used to ease the cost of updating each plan. + +The following sequence diagram summarizes how the `Recipe` and all its related `Plan` are updated +when the `Recipe` is edited. + +.Edit sequence diagram focusing on Model +image::EditModelSequenceDiagram.png[] + +===== Design Considerations + +====== Aspect: How recipes are edited + +* **Alternative 1 (current choice):** The `EditRecipeDescriptor` class is used to make sense of user input and mimics +the `Recipe` class with the same properties. +** Pros: Multiple fields can be edited in one go. +** Cons: Might make testing harder since there are many properties in a Recipe and an edit command can take on any +combination of each property. + +* **Alternative 2:** Allow each property in the `Recipe` to have its own `edit` command. +** Pros: Implementation of each command will be simpler. +** Cons: Editing a recipe will be harder and more troublesome for the user. + +We decided to stick with alternative 1, which is the implementation inherited by AB3, as we believe that being able +to edit multiple fields in one go provides much more versatility and convenience to the user. Additionally, although +there are many properties to test, it is still a finite number and testing can be done with adequate time. + +====== Aspect: Data structure to support plans +Please refer to <> for the design considerations for plans. + +// end::editcommand[] + +// tag::favouriteunfavourite[] +==== Favourite and Unfavourite commands (Brian) +===== Implementation +For brevity, we will only talk about the `favourite` command. Note that the `unfavourite` command is implemented in the +same way. + +1. The user input received by `FavouriteCommandParser#parse` will pass on the user input to +`ParserUtil#parseMultipleIndex` to verify if the indexes keyed in are non-zero, unsigned integers. An error is thrown +if any of the indexes do not meet this requirement. ++ +On top of verifying the validity of the indexes, `ParserUtil#parseMultipleIndex` will remove any duplicate indexes +and sort them. It returns a sorted array of one-based indexes. + +2. A new `FavouriteCommand` object will be created with the array of indexes and returned to the `LogicManager`. + +3. The `FavouriteCommand#execute` method is executed. First, the array of indexes will be checked against the +_currently displayed recipe list_ to ensure that there exists a corresponding recipe index. An error will be thrown if +a user specified recipe index is out of bounds. + +4. Next, we check if the specified recipe(s) is already a favourite. If it is not a favourite yet, we use an +`EditRecipeDescriptor` to set the recipe's `isFavourite` to true. + +5. Finally, we display the names of the recipes that have been newly made favourites, and the names of the recipes that +were already favourites. + +Here is a sample sequence diagram that shows what happens when the user inputs `favourite 3`: + +.Favourite command sequence diagram +image::FavouriteCommandSequenceDiagram.png[] + +This operation favourites recipe 2 and 3. +// end::favouriteunfavourite[] + +// tag::undoredo[] +==== Undo and Redo commands (Brian) +The implementation of undo and redo was adapted from AB3. However, HYBB requires more book-keeping because on top +of the `RecipeBook`, we have a `PlannedBook`, a `CookedRecordBook`, and a `QuoteBook` to keep track of as well. + +For brevity, we will only talk about the `undo` command. Note that the `redo` command is implemented in the same way. + +===== Implementation (before undo is called) +1. Whenever a command that changes the state of any of the books (RecipeBook, PlannedBook, CookedRecordBook, or +QuoteBook) is called, `Model#commitBook` is called as well. + +2. `Model#commitBook` will first purge all redundant states in `MultipleBookStateManager` (ie. if the user called undo +before and is now committing a new book, he will not be able to redo the actions of those undos anymore). This is the +behavior that most modern desktop applications like Microsoft Word adopt. + +3. `Model#commitBook` also saves the `CommandType` and `Tab` of the command in 2 separate stacks in +`MultipleBookStateManager`. Finally, it saves the new state of the affected book(s) in an ArrayList of that book type. + +Note #1: `CommandType` tells you which book(s) the command affects, while `Tab` tells you which tab should be +displayed upon execution of the command. + +Note #2: All 4 ArrayLists of the 4 book types have a "current pointer" each, which points to the respective states of +the books that the `Model` is currently using (ie. what the user is seeing). + +The following diagram summarizes what happens when the user executes a command that changes the state of any book: + +.Activity diagram when a command is executed +image::CommitActivityDiagram.png[] + +===== Implementation (when undo is called) +1. `Model#canUndo` is called to check if there are sufficient actions to be undone. An error is thrown if there are +insufficient actions to be undone. -Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undoAddressBook()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous address book state, and restores the address book to that state. +2. If able to undo, `Model#undoBook` is called. The `CommandType` stack is popped to know which book(s) need undoing. +At the same time, the "current pointer" of the corresponding book ArrayList(s) is/are shifted backwards. All 4 books +in `Model` are then set to the version of the book that each "current pointer" is pointing to. +This class diagram shows the components of `MultipleBookStateManager`: + +.Class diagram for MultipleBookStateManager +image::MultipleBookStateManagerClassDiagram.png[] + + +The following diagrams show what happens after the execution of various commands: + +.When the app is first opened +image::UndoRedoState0.png[] + +.When "delete 5" is called, the state of RecipeBook is changed. This new state is added to ArrayList. +image::UndoRedoState1.png[] + +.When "favourite 3" is called, the state of RecipeBook is changed. This new state is added to ArrayList. +image::UndoRedoState2.png[] + +.When "undo" is called, the current state pointer of ArrayList is shifted back and the Model's RecipeBook is set to this version. image::UndoRedoState3.png[] -[NOTE] -If the `currentStatePointer` is at index 0, pointing to the initial address book state, then there are no previous address book states to restore. The `undo` command uses `Model#canUndoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the undo. +.When a command like "list" (that does not change the state of any book) is called, the current state pointer remains where it is (ie. there is no change of states). +image::UndoRedoState4.png[] + +.If a command like "clear" (that changes the state of a book) is called while the current pointer is not pointing to the latest version, all versions after the current pointer will be purged and the newest version will be added to the ArrayList. +image::UndoRedoState5.png[] + +===== Design Considerations +====== Aspect: How undo and redo executes +One concern we had while choosing the design of the undo and redo features was the amount of memory that has to be used +to keep track of the different states of the 3 books. + +On top of the ArrayLists of different book types, we also needed to have 2 additional stacks to keep track of the +corresponding `CommandType` and `Tab`. -The following sequence diagram shows how the undo operation works: +We eventually decided on the current implementation because we do not expect the user to make that many changes to the +books in a single session. We also do not expect the size of any book to grow so huge that a single commit would take +up all the memory capacity. In other words, we foresee that the "cons" of our current choice will not happen (it would +take really abnormal user behavior for it to reach that stage). + +* **Alternative 1 (current choice):** Saves the entire recipe book. +** Pros: Easy to implement. +** Cons: May use up a lot of memory space within a single session 1) if there is a large number of book commits +and/or 2) if the magnitude of a single commit is large (ie. the book being committed is huge just by itself). + +* **Alternative 2:** Individual command knows how to undo/redo by itself. +** Pros: Will use less memory. +** Cons: Tedious to ensure the correctness of the implementation of each individual command. Furthermore, some commands +affect multiple books, making book-keeping even more complicated (and hence, susceptible to error). +// end::undoredo[] -image::UndoSequenceDiagram.png[] +// end::basic[] -NOTE: The lifeline for `UndoCommand` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram. +// tag::recipecustomisation[] +=== Recipe customisation commands (Brian) +The following commands: `addingredient`, `editingredient`, `deleteingredient`, `addstep`, `editstep`, and `deletestep` +were implemented to overcome the limitations of the `edit` command. These recipe customisation commands allow the user +to make targeted changes to the ingredient or step fields instead of having to rewrite the entire field using `edit`. + +==== Implementation +1. The commands listed above make use of `EditRecipeDescriptor` (ERD) to add, edit, or delete ingredients or steps. +This is done by comparing the contents of the ERD to the contents of the field to be edited and making the necessary +changes described below (note that at this point of time, the ERD is already populated with the user's input): + +* If the command is `addingredient` or `addstep`, the existing ingredients or steps from the recipe will be added to +the ERD. + +* If the command is `editingredient` or `editstep`, the ERD will be checked against the recipe to see if the +ingredients or step exists in the recipe. If it exists, the remaining ingredients or steps that were not changed +will be added to the ERD. Otherwise, an exception is thrown. + +* If the command is `deleteingredient` or `deletestep`, the ERD will be checked against the recipe to see if the +ingredients or step exists in the recipe. If it exists, the ERD will be re-populated with the existing ingredients or +steps from the recipe, less the ones that were specified by the user. Otherwise, an exception is thrown. + +2. With the ERD fields set, the specified recipe is edited by `EditCommand#createEditedRecipe` using the ERD. + +3. Finally, `Model#setRecipe` will replace the old version of the recipe in RecipeBook with the newly edited one. +`Model#commitBook` will commit the new state of the RecipeBook to the `MultipleBookStateManager` so that the user will +be able to undo this command if he wishes to. + +.General activity diagram for recipe customisation commands +image::RecipeCustomisationCommandsActivityDiagram.png[] +//end::recipecustomisation[] + +// tag::advancedfilter[] +=== Filter command (Brian) +The advanced filter feature uses the `filter` command to search for recipes according to the set of keywords provided +by the user. Think of it as a greatly enhanced and more robust version of the `find` command, which only allows the +user to find recipes by their name. + +==== Implementation +This section explains how the `filter` command is implemented. + +1. User specified keywords are directed to `FilterCommandParser#parse` where `ArgumentTokenizer` and +`ArgumentMultimap` are used to parse the user input. An exception will be thrown if no keywords are specified at all. + +2. The parsed user input is then fed into `RecipeMatchesKeywordPredicate` where a `Predicate`, p, is created. This +predicate will subsequently be used as the filter to get all recipes that meet the user specified criteria. + +3. A new `FilterCommand` object will be created with the predicate, p, and be returned to the `LogicManager`. + +4. The `FilterCommand#execute` method is executed and `Model#updateFilteredRecipeList` is called. This tests +every recipe in the database against the predicate, p, and updates the filtered recipe list with recipes that meet the +user specified criteria. + +5. Once complete, this filtered recipe list is displayed to the user. + +Here is a sample sequence diagram that shows what happens when the user inputs `filter favourites t/20 ig/Pasta`: + +.Advanced filter sequence diagram +image::AdvancedFilterSequenceDiagram.png[] + + +This operation displays all recipes that 1) are marked as favourites, 2) take 20 minutes or less to prepare, +and 3) contains pasta as an ingredient. + +==== Design Considerations +===== Aspect: Consistency of user input format +One concern we had while implementing this feature was the sheer number of commands and prefixes that our app had. +Eventually, the current implementation was chosen because we didn't want to define a new format for `filter` +keywords which might potentially confuse our users. -The `redo` command does the opposite -- it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state. +* **Alternative 1 (current choice):** Use the existing prefixes and format in the user input. +** Pros: The existing `ArgumentTokenizer` and `ArgumentMultimap` classes already have capabilities to parse user input +that is in a certain format. Thus, using the same format saves us time and effort in implementing our own parser. It +also spares the user from having to remember multiple formats / keywords. +** Cons: The user has to be familiar with the prefixes and other special keywords in order to use this feature to its +fullest potential. + +* **Alternative 2:** Define new keywords that the user can use. These keywords could be "more english-like" as opposed +to using shortened tags as prefixes. +** Pros: Easy to remember these keywords since they are more english-like. +** Cons: We must implement our own parser which is tedious. The user will also have to remember a new set of keywords +on top of the existing prefixes. This is double work for the user. +// end::advancedfilter[] + +// tag::planning[] +=== Plan command (Beatrice) +The plan feature allows users to plan for recipes that they wish to cook at a certain date. + +This feature is facilitated by the `PlanCommand` class. + + +==== Implementation +This section explains how the `plan` command is implemented. + +1. User specified arguments are passed to the `PlanCommandParser` which uses `ArgumentTokenizer` and +`ArgumentMultimap` to break up the user input. + +2. The arguments are parsed by `ParserUtil` and if no invalid inputs were found, a `PlanCommand` object will be created. + +3. `PlanCommand#execute()` gets the latest list of recipes from `Model`. + +4. For every `Index`, a new `Plan` object is created and added into the `Model`. This is done by passing the `Plan` +and the `Recipe` that is being planned into the `UniquePlannedList` and `PlannedRecipeMap`. + +5. The `Plan` is added to the `UniquePlannedList` and the `Plan` is added to the list of plans at the `Recipe` key + in the `PlannedRecipeMap`. + +6. The success message will be returned to the user by the `CommandResult`. + +The diagram below summarises the steps taken: + +.Plan sequence diagram +image::PlanningSequenceDiagram.png[] [NOTE] -If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone address book states to restore. The `redo` command uses `Model#canRedoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo. +The lifeline for EditCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, +the lifeline reaches the end of diagram. -Step 5. The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged. -image::UndoRedoState4.png[] +==== Design Considerations -Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book states after the `currentStatePointer` will be purged. We designed it this way because it no longer makes sense to redo the `add n/David ...` command. This is the behavior that most modern desktop applications follow. +===== Aspect: Data structure to support plans -image::UndoRedoState5.png[] +* **Alternative 1 (current choice):** Use a `UniquePlannedList` with an `ObservableList` to display the list of plans, +and an internal `PlannedRecipeMap` that maintains the mapping between a `Recipe` and all plans that were +made for the recipe. +** Pros: The `UniquePlannedList` provides the list of plans and updates the UI for every change in plan. In the +background, the `PlannedRecipeMap` is maintained and used to ease the cost of iterating through an entire list of +plans to search for all the plans that uses a specific `Recipe`. +** Cons: Performance might not be optimised as `UniqueRecipeList` still uses a list. -The following activity diagram summarizes what happens when a user executes a new command: +* **Alternative 2:** Maintain the recipes and plans in one `ObservableMap` instead. +** Pros: Performance will be better by using a Map than a List. +** Cons: There are no official javafx classes that supports an sorted `ObservableMap` or a filtered `ObservableMap`. +We will have to write and maintain our own implementation or import from other libraries. + +We decided to use alternative 1, as the cons of alternative 2 are too heavy. The plans need to be sorted +in a chronological order, and future implementations of the `viewWeek` and `viewMonth` command will require the plans +to be filtered as well. + +Additionally, we would not have enough time in the scope of this project to write a fully functional +implementation, and importing from other libraries introduces the risk of running into bugs if the the dependencies +were not maintained in the future. +// end::planning[] + +// tag::goals[] +=== Goals feature (Harshita) +The main functionalities and commands associated with the entire goals feature are `add`, `addIngredient`, `edit`, `editIngredient`, + `cooked`, `listGoals` and 'removeGoals'. Goals are auto-generated and added to a recipe every time `add`, `addIngredient`, `edit` or `editIngredient` is executed. + +==== Details of Implementation (Auto-generation of goals) +The following sequence diagram shows how goals are generated through the example of `addIngredient` command execution + +.Add command sequence diagram +image::AddSequenceDiagram.png[] +.Reference Frame for Add command sequence diagram +image::AddRefSequenceDiagram.png[] + +A recipe is initially created with an empty goals set from parser and `calculateGoals()` is then called in the `AddCommand`. + +Each ingredient type that is associated with a goal (`Vegetable`, `Protein`, `Fruit`, `Grain`) is listed as an enum type +in MainIngredientType. This ensures that invalid goals are not created and simplifies the mapping between `MainIngredientType` +and `Goal`. + +The calculation of goals then occurs through looping through each ingredient type and executing the method call to +`Recipe#calculateIngredientQuantity()`. +This would obtain the total quantity for each ingredient, firstly by calling `Ingredient#getMainIngredientType()` +to ensure the validity of ingredients beings calculated (e.g. any instance of 'Other' ingredient would throw an `InvalidStateException`). +Secondly, by obtaining the quantity in grams through the method calls to `Ingredient#getQuantity()' and 'Quantity#convertToGram()`. + +After the calculation for each main ingredient type is completed, an instance of `MainIngredientTypeMagnitude` is created. +It acts as a container to store the quantities and conduct the checks for whether these quantities meet the minimum quantity +requirement for their respective food group. This calculation and checks are done through the method call to +`MainIngredientTypeMagnitude#getMainTypes()` which would then return a set of `MainIngredientType` that successfully met the +minimum requirement. + +Lastly, after looping through this set and creating each goal with the mapping from `MainIngredientType` to `Goal` done +(e.g. `MainIngredientType.FRUIT` leads to the creation of goal with goal name generated as "Fruity Fiesta"), the goals will +be updated in the particular instance of `Recipe r` and `Model#addRecipe(r)` would then update `RecipeBook` in storage. + +The immutability of each object is supported to ensure the correctness of undo and redo functionality. + +==== Details of Implementation (Statistics of cooked recipes) + +.Activity diagram when a cooked command is entered +image::CookedActivityDiagram.png[] + +After `CookedCommand#execute(model)` is called, the series of checks shown in the above diagram is done to determine +if the recipe can be marked as cooked. With multiple recipes inputted (eg `cooked` 1 2 3, the series of checks will +loop through for for each recipe. + +The checks ensure that all the recipes inputted are valid, else the `CookedCommand` +throws an exception and terminates. If successful, a new `Record` containing the `Name`, current `Date` and set of `Goals` +associated with the recipe is created and `Model#addRecord(record)` would then update `CookedRecordBook` in storage. + +Furthermore, if the recipe marked as cooked was included in the Planned Recipes for the day, +it will be removed from the planned list. + +With reference to the structure of the CookedRecords Model, + +.Class diagram of Record +image::ModelRecordClassDiagram.png[] + +We can see above that once a record is added to the UniqueRecordList two Observable lists will be updated for each +addition of `Record`. Firstly, it is the `internalRecordsList` that stores unique `Record`. Secondly, based on this list, +an `internalGoalsTally` that stores `GoalCount` will be updated each time. This `GoalCount` consists of one of the four main goal +and its respective tally and this observable list is what the pie chart will be listening to for updates and will change +each time the `internalGoalsTally` has been updated as well. + +Hence the `cooked` command is essential in not only archiving data, but also giving the user personalised statistics +on their overall goal distribution that resembles the Healthy Eating Plate. The immutability of each object is +supported to ensure the correctness of undo and redo functionality as well. -image::CommitActivityDiagram.png[] ==== Design Considerations -===== Aspect: How undo & redo executes +===== Aspect: How goals are being tagged + +* **Alternative 1 (current choice):** System generates tags for each recipe based on food algorithm. +** Pros: Higher accuracy and makes use of inputs of ingredients class. +** Cons: Would require several criteria checks that may not be intuitive and would require the use of artificial intelligence for the highest accuracy. + +* **Alternative 2 :** User chooses from 4 given goals and user adds the tags to the recipes. +** Pros: Easy to implement. User can filter their preferred goals easily. +** Cons: Is dependant on user's understanding and not universal understanding of what may be deemed healthy. + +Alternative 1 was chosen as standardising the goals give the recipes more meaning, especially when we are able +to calculate statistics and present in in an meaningful and appealing way for users when it models the Healthy eating Plate. +Furthermore, custom goals would not have checks would not have been implemented. for users to filter preferred recipes, +the command `favourite` as been implemented. + +===== Aspect: How to determine the criteria for each goal + +* **Alternative 1 (current choice):** Check by quantity +** Pros: More accurate and can be modelled against ideal ratio of a healthy meal. +** Cons: Harder to implement as we need to standardise the ingredient measurements, not as intuitive. -* **Alternative 1 (current choice):** Saves the entire address book. +* **Alternative 2 :** Check by variety ** Pros: Easy to implement. -** Cons: May have performance issues in terms of memory usage. -* **Alternative 2:** Individual command knows how to undo/redo by itself. -** Pros: Will use less memory (e.g. for `delete`, just save the person being deleted). -** Cons: We must ensure that the implementation of each individual command are correct. +** Cons: Not as accurate as one grain of rice or 1 grape would still be counted as variety despite the small portion. -===== Aspect: Data structure to support the undo/redo commands +Alternative 1 was chosen because of its higher accuracy, although conversion between different measurement may be +overestimated. The command `deleteGoal` was then created in order to enable users to delete goals they deem inaccurate. -* **Alternative 1 (current choice):** Use a list to store the history of address book states. -** Pros: Easy for new Computer Science student undergraduates to understand, who are likely to be the new incoming developers of our project. -** Cons: Logic is duplicated twice. For example, when a new command is executed, we must remember to update both `HistoryManager` and `VersionedAddressBook`. -* **Alternative 2:** Use `HistoryManager` for undo/redo -** Pros: We do not need to maintain a separate list, and just reuse what is already in the codebase. -** Cons: Requires dealing with commands that have already been undone: We must remember to skip these commands. Violates Single Responsibility Principle and Separation of Concerns as `HistoryManager` now needs to do two different things. -// end::undoredo[] +===== Aspect: How the check for goal is done + +* **Alternative 1 (current choice):** Check every time a recipe is added or edited and store this data +** Pros: More consistent for the user in keeping track of their goals. +** Cons: Harder to implement as repetitive checks are needed every time ingredients are added or modified. +Will be more expensive to calculate with a larger database. + +* **Alternative 2 :** Calculate the goals for each recipe every time it is retrieved from storage and set in RecipeList. +** Pros: Easier to implement as only one check is needed for when the recipes are set. +** Cons: Goals will reset each time the application is open. If goal has been deleted by user with `deleteGoal`, it will +not be updated the next time the user opens the application as the checks will be the same. + +Alternative 1 was chosen as it optimizes the function of deleteGoal`, taking user preference into consideration. + +===== Aspect: How to store data for records + +* **Alternative 1 (current choice):** Store in a json file called records and calculate goal tally the first time +it is set and update accordingly +** Pros: A custom date can be set and it will be easier to iterate through the list to obtain goal tally. +** Cons: Duplicate data will be stored and is harder to implement. + +* **Alternative 2 :** Use recipebook and add boolean attribute isCooked +** Pros: Easy to implement. +** Cons: Restricted usage, unable to implement date and do statistical analysis for the user. + +* **Alternative 3 :** Store goal tally in a new json file. +** Pros: No need to iterate through recipe list each time and would be less expensive with a larger database. +** Cons: Only contains four values. + +Alternative 1 was chosen as it optimizes the functions and uses of a Record and the scale for a personal data +base is smaller, storage would not be an issue. Records need to be iterated through when set initially anyway, hence +the association between GoalCount and Record makes the tally process more efficient. +end::goals[] + +// tag::quote[] +=== Quote Command (Yue Tong) +The quote command feature uses the `quote` command for users to input their own quotes to add on to the existing set of +quotes that is already in the database. This allows the users to add in customised quotes that would suit their preferance +more if the current list of quotes is not to their liking. + +The following sequence diagram illustrates how the `QuoteCommand` is used. + +.Quote command sequence diagram +image::QuoteSequenceDiagram.png[] +[NOTE] +The lifeline for EditCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, +the lifeline reaches the end of diagram. + +[NOTE] +`Undo` button currently does not work for adding of quotes as there is no remove function currently implemented for quote +==== Implementation + +This section explains how the `quote` command is implemented. + +1. User specified arguments are passed to the `QuoteCommandParser#parse` which will then parse the user input to verify if the +quote field is empty. An error is thrown if the user had keyed in an empty field for quote. + +2. A new `QuoteCommand` object will be created with a `Content` field to store the quote and returned to the `LogicManager` + +3. The `QuoteCommand#execute` method is executed and `Model#addQuote` is called. This attempts to add the quote to the +database and verify if any duplicate quote exists in the database via `Model#hasQuote`. If a duplicate quote is detected +in the database, an error will be thrown to indicate that the quote already exists in the database. + +4. Once the quote has been successfully updated to the database, the result window informs the user that the quote has +been successfully added. + +The following activity diagram further illustrates how the `QuoteCommand` is used. + +.Quote command activity diagram +image::QuoteActivityDiagram.png[] + +==== Design Considerations +===== Aspect: How quote command executes + +* **Alternative 1 (current choice):** The `QuoteCommand` only accepts adding of quotes + +** Pros: Maintaining the database for quotes is easier +** Cons: Users will not be able to remove a quote if it is not to their liking and undo function does not work for quote command + +* **Alternative 2:** The `QuoteCommand` accepts both adding and removal of quotes +** Pros: Users can customize whicher quotes they want to be displayed +** Cons: If they user deletes the quote that is on display for Quote of the Day in the Achievement tab, this could cause +display problems and as `UniqueQuotesList` is a hidden list, users will have to type out the quote completely similar in order to locate it +//end::quote[] + +// tag::streak[] +=== Streak feature(Yue Tong) + +The Streak feature mainly deals with keeping track of the cooked meals that the user has logged into the system. The command +that Streak is associated with is `CookedCommand` as every user input of `cooked` will result in the streak log to be reflected when `cooked` is executed. The changes are reflected in two main attributes, Current streak and +High streak. + +The following sequence diagram illustrates how the `QuoteCommand` is used. + +.Quote command sequence diagram +image::StreakActivityDiagram.png[] + +==== Implementation + +The streak feature uses data from the `UniqueRecordList` to parse through the recipes that the user has already cooked +and extract the dates from these recipes to determine the current streak for the user and the highest streak score the +user has attained as of yet. + +The `UniqueRecordList` provides Streak with an observableList so that a listener could be added to it to make sure that +the streak always auto-updates whenever a new `CookedRecord` is added in to the database. Via the addListener, whenever +a new record is detected, the streaks are calculated again through parsing of the `CookedRecords` list and updated in +real time in the achievement tab. + +==== Design Considerations +===== Aspect: How streak is stored + +* **Alternative 1 (current choice):** Streak is calculated and updated via access to `UniqueRecordList` + +** Pros: Easier to access `CookedRecord` list when there is direct access to `UniqueRecordList` and to update in real time +** Cons: There is more co-dependency among classes and there may be performance issues if `UniqueRecordList` is too large + +* **Alternative 2:** Streak has its own database and json file to keep track of streaks +** Pros: Lesser time is required to re-calculate streaks every time a cookedRecord is updated as streak can just be +added and subtracted from its recorded data in the database +** Cons: A database section will be dedicated to just storing one number and without access to the `UniqueRecordsList` +it is harder for Streak to be updated realtime when cookedRecord is updated. -// tag::dataencryption[] -=== [Proposed] Data Encryption +===== Aspect: How streak is calculated -_{Explain here how the data encryption feature will be implemented}_ +* **Alternative 1 (current choice):** Accumulative streaks is calculated based on whether there is a 1-day difference +between 2 consecutive cooked recipes -// end::dataencryption[] +** Pros: Easier to compute compared to implementing via a midnight deadline basis to calculate accumulative streaks +** Cons: Streaks are not necessarily accounted for within a 24-hour period + +* **Alternative 2:** Accumulative streaks is calculated based on a stricter within 24-hour new logged cooked recipes +** Pros: The accountability is higher for users to actually accomplish their streaks by having to cook recipes within a +24-hour period and not be able to go for more than a day without cooking new recipes without having their streaks +jeopardised. +** Cons: It is easier for users to lose their streaks and more difficult for users to ascertain when is the deadline to +maintain their streaks +//end::streak[] === Logging @@ -279,13 +886,17 @@ Refer to the guide <>. *Target user profile*: -* has a need to manage a significant number of contacts +* university students +* wishes to lead a healthier lifestyle +* has trouble thinking about what to cook * prefer desktop apps over other types * can type fast * prefers typing over mouse input * is reasonably comfortable using CLI apps -*Value proposition*: manage contacts faster than a typical mouse/GUI driven app +*Value proposition*: +Focuses on healthy, simple recipes with short cooking time with ingredients filter to +minimise food wastage. [appendix] == User Stories @@ -297,33 +908,109 @@ Priorities: High (must have) - `* * \*`, Medium (nice to have) - `* \*`, Low (un |Priority |As a ... |I want to ... |So that I can... |`* * *` |new user |see usage instructions |refer to instructions when I forget how to use the App -|`* * *` |user |add a new person | +|`* * *` |picky eater |filter food preferences |cook food that matches my taste -|`* * *` |user |delete a person |remove entries that I no longer need +|`* * *` |frugal user |easily search for recipes with the ingredients I already have |use up all the food in my fridge -|`* * *` |user |find a person by name |locate details of persons without having to go through the entire list +|`* * *` |frequent user |save my favourite recipes |quickly navigate to them without having to search them up again -|`* *` |user |hide <> by default |minimize chance of someone else seeing them by accident +|`* * *` |goal-oriented student |track my progress |see how far I came and how much further I have to go to reach my goal -|`*` |user with many persons in the address book |sort persons by name |locate a person easily -|======================================================================= +|`* * *` |user with many recipes in the recipe book |filter recipes by various criteria |locate a recipe easily -_{More to be added}_ +|`* * *` |user with allergies |exclude ingredients that I am allergic to |obtain recipes that are catered to me + +|`* * *` |user struggling to eat healthier |receive motivation for eating healthy meals |stay motivated on my goal + +|`* * *` |user who cooks regularly |add my own recipes with the goals they fall under |progress in my goals when I cook my own unique meals + +|`* * *` |unmotivated user |choose a goal for myself |cook more meals and be motivated by my progress + +|`* * *` |unmotivated user |track my streak of healthy meals |motivated to keep eating healthy + +|`* * *` |user who loses motivation easily |look at daily quotes to remind myself |remember why I wanted to continue to be healthy + +|`* *` |user who dislikes food wastage |see what ingredients I need to buy when I grocery shop |only buy ingredients that I will use + +|`* *` |busy student |get a list of the ingredients I need for the week in one go |save time and not make wasted trips + +|`* *` |busy student |pre-select meals for certain days |save time from ruminating over what to cook + +|`* *` |bodybuilder |search for protein-rich recipes specifically |build my muscles + +|`* *` |busy student |filter recipes by preparation time |choose meals that can be done quickly + +|`* *` |avid planner |choose recipes and place them in a timetable for the week |plan my meals beforehand + +|`*` |novice cook |filter recipes by difficulty level |select easier recipes + +|`*` |user who is passionate about cooking |share the recipes on social media |show my friends what I have cooked today + +|`*` |adventurous user |filter the recipes by cuisine |try a new cuisine every time + +|`*` |user who prefers hard-copy materials |save my favourite recipes locally |print them out + +|`*` |frequent party host |scale up the amount of ingredients needed |make the correct amount of food + +|`*` |student on budget |choose recipes that require lower cost |save money + +|`*` |adventurous user |ask for suggested recipes |choose a random recipe and start cooking + +|`*` |adventurous user |mix up recipes |try something completely new + +|`*` |motivational user |add custom quotes to app online |motivate other users with different quotes + +|======================================================================= [appendix] == Use Cases -(For all use cases below, the *System* is the `AddressBook` and the *Actor* is the `user`, unless specified otherwise) +(For all use cases below, the *System* is `HealthyBaby` and the *Actor* is the `user`, unless specified otherwise) + +[discrete] +=== Use case: Add recipe + +*MSS* + +1. User requests to add recipe +2. HealthyBaby creates a new recipe with the specified name ++ +Use case ends. + +*Extensions* + +[none] +* 2a. The name/time/ingredients fields are empty. ++ +[none] +** 2a1. HealthyBaby shows an error message. ++ +Use case resumes at step 1. + +[none] +* 2b. The given name already exists. ++ +[none] +** 2b1. HealthyBaby shows an error message. ++ +Use case resumes at step 1. + +* 2c. The user tries to add goals that do not exist in the goals list. ++ +[none] +** 2c1. HealthyBaby shows an error message. ++ +Use case resumes at step 1. [discrete] -=== Use case: Delete person +=== Use case: Delete recipe *MSS* -1. User requests to list persons -2. AddressBook shows a list of persons -3. User requests to delete a specific person in the list -4. AddressBook deletes the person +1. User requests to list recipes +2. HealthyBaby shows a list of recipes +3. User requests to delete a specific recipe in the list +4. HealthyBaby deletes the recipe + Use case ends. @@ -337,18 +1024,85 @@ Use case ends. * 3a. The given index is invalid. + [none] -** 3a1. AddressBook shows an error message. +** 3a1. RecipeBook shows an error message. + Use case resumes at step 2. -_{More to be added}_ +[discrete] +=== Use case: Find recipe + +*MSS* + +1. User enters desired recipe name into CLI +2. HealthyBaby shows the desired recipe ++ +Use case ends. + +*Extensions* + +[none] +* 2a. The desired recipe name does not exist in the list. ++ +[none] +** 2a1. HealthyBaby tells the user that 0 recipes are listed. ++ +Use case ends. + +[discrete] +=== Use case: Plan for a recipe + +*MSS* + +1. User enters the recipe index and date that they would like to plan for +2. HealthyBaby adds the new plan to the list of plans +3. HealthyBaby displays the success message, switches to the planning tab and displays the updated list of plans. ++ +Use case ends. + +*Extensions* + +[none] +* 2a. The given recipe index is invalid. ++ +[none] +** 2a1. HealthyBaby shows an error message. ++ +Use case ends. + +[none] +* 2b. The given date is invalid. ++ +[none] +** 2b1. HealthyBaby shows an error message. ++ +Use case ends. + +[none] +* 2c. A similar plan with the same recipe and date already exists in the list. ++ +[none] +** 2c1. HealthyBaby shows an error message. ++ +Use case ends. + +[discrete] +=== Use case: Clear entire recipe list + +*MSS* + +1. User enters the clear command +2. HealthyBaby clears the entire recipe and plans list ++ +Use case ends. + [appendix] == Non Functional Requirements . Should work on any <> as long as it has Java `11` or above installed. -. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage. +. Should be able to hold up to 1000 recipes without a noticeable sluggishness in performance for typical usage. . A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse. +. The software should be portable (i.e. works on and can be moved to different operating systems) _{More to be added}_ @@ -358,25 +1112,8 @@ _{More to be added}_ [[mainstream-os]] Mainstream OS:: Windows, Linux, Unix, OS-X -[[private-contact-detail]] Private contact detail:: -A contact detail that is not meant to be shared with others - -[appendix] -== Product Survey - -*Product Name* - -Author: ... - -Pros: - -* ... -* ... - -Cons: - -* ... -* ... +[[main-nutritional-food-group]] Main Nutritional Food Group:: +HYBB identifies Grain, Vegetable, Protein and Fruit to be the main nutritional food groups. [appendix] == Instructions for Manual Testing @@ -387,39 +1124,211 @@ Given below are instructions to test the app manually. These instructions only provide a starting point for testers to work on; testers are expected to do more _exploratory_ testing. === Launch and Shutdown - . Initial launch - .. Download the jar file and copy into an empty folder .. Double-click the jar file + Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum. . Saving window preferences - .. Resize the window to an optimum size. Move the window to a different location. Close the window. .. Re-launch the app by double-clicking the jar file. + Expected: The most recent window size and location is retained. -_{ more test cases ... }_ - -=== Deleting a person - -. Deleting a person while all persons are listed - -.. Prerequisites: List all persons using the `list` command. Multiple persons in the list. +=== Deleting a recipe +. Deleting a recipe while all recipes are listed and no plans exist +.. Prerequisites: List all recipes using the `list` command. + +Multiple recipes in the list must be present. If required, add recipes by using the `add` command. + +Plan list is empty. If required, clear plans by using the `clearPlan` command. .. Test case: `delete 1` + - Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated. + Expected: First recipe is deleted from the list. Name of the deleted recipe shown in the result box. .. Test case: `delete 0` + - Expected: No person is deleted. Error details shown in the status message. Status bar remains the same. -.. Other incorrect delete commands to try: `delete`, `delete x` (where x is larger than the list size) _{give more}_ + + Expected: No recipe is deleted. Error details shown in the result box. +.. Other incorrect delete commands to try: `delete`, `delete x` (where x is larger than the list size) + + Expected: Similar to previous. + +. Deleting a recipe while all recipes are listed and plans exist +.. Prerequisites: List all recipes using the `list` command. + +Multiple recipes in the list must be present. If required, add recipes by using the `add` command. + +Plan list contains a plan for the recipe at recipe index 1. If required, add a plan using the `plan` command. +.. Test case: `delete 1` + + Expected: First recipe is deleted from the list. Name of the deleted recipe shown in the result box. +The plan for recipe 1 is removed from the list of plans in the 'Planning' tab. + +=== Favourite a recipe +. Favouriting a recipe while all recipes are listed +.. Prerequisites: List all recipes using the `list` command. There must be at least 2 recipes for all the following test +cases to work as expected. +.. Test case: `favourite 1` + + Expected: A star appears beside the recipe name, indicating that it has been marked as a favourite and a success +message appears in the message box. +.. Test case: `favourite 0` + + Expected: No recipe is favourited. An error message appears in the message box. +.. Test case: `favourite 1 2` + + Expected: A star appears beside the names of recipe 1 and 2, indicating that they have been marked as favourites and +a success message appears in the message box. + +=== Unfavourite a recipe +. Unfavouriting a recipe while all recipes are listed +.. Prerequisites: List all recipes using the `list` command. Recipe 1 must be favourited as well. +.. Test case: `unfavourite 1` + + Expected: The star beside recipe 1 disappears, indicating that it has been removed from favourites and a success +message appears in the message box. +.. Test case: `unfavourite 0` + + Expected: No recipe is unfavourited. An error message appears in the message box. + +=== Filtering recipes +. Filters recipes that match the given criteria +.. Prerequisites: List all recipes using the `list` command. At least one recipe should be favourited and at least one +recipe should contain a grain ingredient called "Bread" +.. Test case: `filter favourites` + + Expected: Only recipes that are favourites (has a star beside its name) are displayed. +.. Test case: `filter ig/Bread` + + Expected: Only recipes that have a grain ingredient called "Bread" are displayed. + +=== Undo and Redo +. Undoes the previous action, followed by restoring the action that was undone +.. Prerequisites: List all recipes using the `list` command. Recipe 1 should not be favourited and should not contain a +grain ingredient called "Bread" +.. Test case: `favourite 1`, followed by `undo`, followed by `redo` + Expected: A star appears beside recipe 1's name upon favouriting it, disappears upon undoing, and reappears upon +redoing. +.. Test case: `addingredient 1 ig/2g, Bread`, followed by `undo`, followed by `redo` + Expected: A bread ingredient appears under the "Grains" section of recipe 1 upon addingredient, disappears upon +undoing, and reappears upon redoing. + +=== Clearing the recipe list +. Clearing the list while plans are present. +.. Prerequisites: Plan a recipe using the `plan` command. +.. Test case: `clear` + + Expected: All recipes and plans are cleared from the list. + +. Clearing the list while plans are not present. +.. Prerequisites: No plans are present. Clear the plans by using the `clearPlan` command. +.. Test case: `clear` + + Expected: All recipes are cleared from the list. + +=== Adding plans +. Adding a plan to an empty plan list. +.. Prerequisites: No plans are present. If required, clear the plans by using the `clearPlan` command. + +At least one recipe exist in the recipe list. If required, add recipes by using the `add` command. +.. Test case: `plan 1 d/2020-05-20` + + Expected: Recipe at index 1 is planned on 20 May 2020. +.. Test case: `plan -1 d/2020-05-20` + + Expected: Plan is not added. Error details shown in the result box. +Other incorrect plan commands to try: `plan`, `plan 0`, `plan x` (where x is larger than the list size) + + Expected: Similar to previous. +.. Test case: `plan 1 d/2019-05-20` + + Expected: Plan is not added. Error details shown in the result box. + +. Adding multiple plans to an empty plan list. +.. Prerequisites: No plans are present. If required, clear the plans by using the `clearPlan` command. + +Multiple recipes exist in the recipe list. If required, add recipes by using the `add` command. +.. Test case: `plan 1 2 3 d/2020-05-20` + + Expected: Recipes at indexes 1, 2 and 3 are planned on 20 May 2020. +.. Test case: `plan 1 -2 3 d/2020-05-20` + + Expected: No plans are added. Error details shown in the result box. +.. Test case: `plan 1 2 3 d/2019-05-20` + + Expected: Plan is not added. Error details shown in the result box. + +. Adding plan(s) to a plan list that is not empty. +.. Prerequisites: A plan for the recipe at recipe index 1 exists. If required, plan for the recipe by using the `plan` command. +.. Test case: `plan 1 d/2020-05-20` + + Expected: No plans are added. Duplicate message is shown in the result box. +.. Test case: `plan 1 -2 3 d/2020-05-20` + + +=== Deleting plans +. Deleting a plan while plans exist. +.. Prerequisites: Plans are present. If required, add plans by using the `plan` command. +.. Test case: `deletePlan 1` + + Expected: Plan at plan index 1 is deleted. +.. Test case: `deletePlan -1` + + Expected: Plan is not deleted. Error details shown in the result box. +Other incorrect plan commands to try: `deletePlan`, `deletePlan 0`, `deletePlan x` (where x is larger than the list size) + + Expected: Similar to previous. + +. Deleting a plan while multiple plans exist. +.. Prerequisites: More than one plan are present. If required, add plans by using the `plan` command. +.. Test case: `deletePlan 1 2` + + Expected: Plan at plan indexes 1 and 2 are deleted. +.. Test case: `deletePlan 1 -2` + + Expected: Plan is not deleted. Error details shown in the result box. +Other incorrect plan commands to try: `deletePlan 1 0`, `deletePlan 2 x`, (where x is larger than the list size) + Expected: Similar to previous. +=== Clearing plans +. Clearing plans while plans exist. +.. Prerequisites: Plans are present. If required, add plans by using the `plan` command. +.. Test case: `clearPlan` + + Expected: All plans in the plan list are cleared. + +=== Obtaining grocery list +. Obtain grocery list while plans exist. +.. Prerequisites: Plans are present. If required, add plans by using the `plan` command. +.. Test case: `groceryList` + + Expected: A window appears, listing all the ingredients used for the recipes in the plans. + +. Obtain grocery list while no plans exist. +.. Prerequisites: Plan list is empty. If required, clear plans by using the `clearPlan` command. +.. Test case: `groceryList` + + Expected: No window appears. Error details shown in the result box. + +. Update and show grocery list while grocery list window is minimised. +.. Prerequisites: Plans are present. If required, add plans by using the `plan` command. +Grocery list window is opened then minimised. If required, open the window first by using the `groceryList` command, +then minimise that window. +.. Test case: `groceryList` + + Expected: Window with updated grocery list appears. + +=== Cooking recipes +. Mark a recipe as cooked +.. Prerequisites: Recipes are present. If required, add recipes by using the `add` command. +.. Test case: `cooked 1` + + Expected: The result box below informs the user that the recipe has been cooked. + +. Cooking a recipe that has already been cooked. +.. Prerequisites: Records list contains records cooked within the day. +.. Test case: `cooked 1` + + Expected: The result box below informs the user that the recipe is a duplicated and cannot be added in. + +. Cooking multiple recipes +.. Prerequisites: Recipes are present. If required, add recipes by using the `add` command. +.. Test case: `cooked 1 2 3` + + Expected: The result box below informs the user that the recipes have been cooked. + + +=== Adding quotes +. Quote displays while quotelist is not empty. +.. Prerequisites: Quotes are present. If required, add quotes by using the `quote` command. +.. Test case: `quote Today is a good day` + + Expected: The result box below informs the user that the quote has been added. + +. Adding a quote while it already exists in the list +.. Prerequisites: Quotes list contains quote. If required, add the same quote by using the `quote` command. +.. Test case: `quote Skip the diet, just eat healthy!` + + Expected: The result box below informs the user that the quote is a duplicated and cannot be added in. + _{ more test cases ... }_ === Saving data -. Dealing with missing/corrupted data files - -.. _{explain how to simulate a missing/corrupted file and the expected behavior}_ +. Dealing with missing data files. +.. Close the jar file. +.. Delete one or more files from the data folder. +.. Double-click the jar file. + + Expected: Deleting the files would result in these corresponding results: +... Recipebook: Default recipes in 'Recipes' +... Quotebook: Default quotes in 'Achievements' +... Plannedbook: An empty plan list in 'Planning' +... Cookedrecords: An empty cooked meals list with no pie chart in 'Goals' + +. Dealing with corrupted data files. +.. Close the jar file. +.. Type '~!@' in any of the files in the data folder and save the file. +.. Double-click the jar file. + + Expected: Adding corrupted data into the files would result in these corresponding results: +... Recipebook: An empty recipe list in 'Recipes' as well as an empty plan list in 'Planning' +... Quotebook: An empty quote list in 'Quotes' and default quote in 'Achievements' +... Plannedbook: An empty plan list in 'Planning' +... Cookedrecords: An empty cooked meals list with no pie chard in 'Goals' _{ more test cases ... }_ diff --git a/docs/Documentation.adoc b/docs/Documentation.adoc index ad90ac87bda..795ea1a4032 100644 --- a/docs/Documentation.adoc +++ b/docs/Documentation.adoc @@ -1,4 +1,4 @@ -= AddressBook Level 3 - Documentation += HealthyBaby - Documentation :site-section: DeveloperGuide :toc: :toc-title: @@ -12,7 +12,7 @@ ifdef::env-github[] :note-caption: :information_source: :warning-caption: :warning: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level3/tree/master +:repoURL: https://github.com/AY1920S2-CS2103T-T10-1/main == Introduction diff --git a/docs/LearningOutcomes.adoc b/docs/LearningOutcomes.adoc deleted file mode 100644 index 436c1777617..00000000000 --- a/docs/LearningOutcomes.adoc +++ /dev/null @@ -1,216 +0,0 @@ -= Learning Outcomes -:site-section: LearningOutcomes -:toc: macro -:toc-title: -:toclevels: 1 -:imagesDir: images -:stylesDir: stylesheets -ifdef::env-github[] -:note-caption: :information_source: -endif::[] - -After studying this code and completing the corresponding exercises, you should be able to, - -toc::[] - -== Utilize User Stories `[LO-UserStories]` - -=== References - -* https://se-edu.github.io/se-book/specifyingRequirements/userStories/[se-edu/se-book: Requirements: Specifying Requirements: User Stories] - -=== Exercise: Add more user stories - -* Assume you are planing to expand the functionality of the AddressBook (but keep it as a CLI application). -What other user stories do you think AddressBook should support? Add those user stories to the `DeveloperGuide.adoc`. - -== Utilize use cases `[LO-UseCases]` - -=== References - -* https://se-edu.github.io/se-book/specifyingRequirements/useCases/[se-edu/se-book: Requirements: Specifying Requirements: Use Cases] - -=== Exercise: Add a 'Rename tag' use case - -* Add a use case to the `DeveloperGuide.adoc` to cover the case of _renaming of an existing tag_. -e.g. rename the tag `friends` to `buddies` (i.e. all persons who had the `friends` tag will now have -a `buddies` tag instead) -Assume that AddressBook confirms the change with the user before carrying out the operation. - -== Use Non Functional Requirements `[LO-NFR]` - -=== References - -* https://se-edu.github.io/se-book/requirements/nonFunctionalRequirements/[se-edu/se-book: Requirements: Non-Functional Requirements] - -=== Exercise: Add more NFRs - -* Add some more NFRs to the `DeveloperGuide.adoc` - -== Use Polymorphism `[LO-Polymorphism]` - -Note how the `Command::execute()` method shows polymorphic behavior. - -=== References - -* https://se-edu.github.io/se-book/oop/polymorphism/[se-edu/se-book: Paradigms: OOP: Polymorphism] -* https://se-edu.github.io/se-book/cppToJava/inheritance/polymorphism/[se-edu/se-book: C++ to Java: OOP: Polymorphism] - -=== Exercise: Add a polymorphic `isMutating` method - -* Add a method `boolean isMutating()` to the `Command` class. This method will return `true` for -command types that mutate the data. e.g. `AddCommand` -* Currently, AddressBook data are saved to the file after every command. -Take advantage of the the new method you added to limit file saving to only for command types that mutate data. -i.e. `add` command should always save the data while `list` command should never save data to the file. - -[NOTE] -==== -There may be better ways to limit file saving to commands that mutate data. The above approach, while not -optimal, will give you chance to implement a polymorphic behavior. -==== - -== Use abstract classes/methods `[LO-Abstract]` - -=== References - -* https://se-edu.github.io/se-book/oop/inheritance/abstractClasses/[se-edu/se-book: Paradigms: OOP: Abstract Classes] -* https://se-edu.github.io/se-book/cppToJava/inheritance/abstractClassesAndMethods/[se-edu/se-book: C++ to Java: OOP: Abstract Classes] - -=== Exercise: Make `Command#execute()` method abstract - -* Make the `Command#execute()` method abstract (hint: refer to the comment given below the method) - -== Use interfaces `[LO-Interfaces]` - -Note how the `AddressBook` class implements the `ReadOnlyAddressBook` interface so that clients who don't need write access to the `AddressBook` can access the `AddressBook` through the `ReadOnlyAddressBook` interface instead. - -image::ReadOnlyAddressBookUsage.png[width=500] - -=== References - -* https://se-edu.github.io/se-book/oop/inheritance/interfaces/[se-edu/se-book: Paradigms: OOP: Abstract Interfaces] -* https://se-edu.github.io/se-book/cppToJava/inheritance/interfaces/[se-edu/se-book: C++ to Java: OOP: Abstract Interfaces] - -=== Exercise: Add a `Printable` interface - -* Add a `Printable` interface as follows. -+ -image::PrintableInterface.png[width=400] -* `Override` the `getPrintableString` in classes `Name`, `Phone`, `Email`, and `Address` so that each produces a printable string representation of the object. e.g. `Name: John Smith`, `Phone: 12349862` -* Add the following method in a suitable place of some other class. Note how the method depends on the Interface. -+ -[source,java] ----- -/** - * Returns a concatenated version of the printable strings of each object. - */ -String getPrintableString(Printable... printables) { ----- -+ -The above method can be used to get a printable string representing a bunch of person details. -For example, you should be able to call that method like this: -+ -[source,java] ----- -// p is a Person object -return getPrintableString(p.getPhone(), p.getEmail(), p.getAddress()); ----- - -== Follow Liskov Substitution Principle `[LO-LSP]` - -=== References - -* https://se-edu.github.io/se-book/principles/liskovSubstitutionPrinciple/[se-edu/se-book: Principles: Liskov Substitution Principle] - -=== Exercise: Add an exception to an overridden method - -* Add a `throws Exception` clause to the `AddCommand::execute` method. Notice how Java compiler will not allow it, -unless you add the same `throws` clause to the parent class method. This is because if a child class throws -an exception that is not specified by the Parent's contract, the child class is no longer substitutable in place of -the parent class. -* Also note that while in the above example the compiler enforces LSP, there are other situations where it is up to -the programmer to enforce it. For example, if the method in the parent class works for `null` input, the overridden -method in the child class should not reject `null` inputs. This will not be enforced by the compiler. - -== Use Java-FX for GUI programming `[LO-JavaFx]` - -=== References - -* https://se-edu.github.io/se-book/javaTools/javaFXBasic/[se-edu/se-book: Tools: Java: JavaFX: Basic] - -=== Exercise: Enhance GUI - -* Do some enhancements to the AddressBook GUI. e.g. add an application icon, change font size/style - -== Analyze Coupling and Cohesion of designs `[LO-CouplingCohesion]` - -* Notice how having a separate `ParserUtil` class to handle user input validation, space trimming etc. of model data (an application of the Single Responsibility Principle) improves the _cohesion_ of the model component (since it does not need to be concerned with handling user input) as well as the `ParserUtil` class. - -=== References - -* https://se-edu.github.io/se-book/designFundamentals/coupling/[se-edu/se-book: Design: Design Principles: Coupling] -* https://se-edu.github.io/se-book/designFundamentals/cohesion/[se-edu/se-book: Design: Design Principles: Cohesion] - -=== Exercise: Identify places to reduce coupling and increase cohesion - -* Where else in the design coupling can be reduced further, or cohesion can be increased further? - -[[apply-dependency-inversion-principle-lo-dip]] -== Apply Dependency Inversion Principle `[LO-DIP]` - -* Note how the `LogicManager` class doesn't depend on `StorageManager` directly, but rather the interface `Storage`. -This is an application of the Dependency Inversion Principle. -+ -image::LogicStorageDIP.png[width=300] -* Where else in the code do you notice the application of DIP? - -=== References - -* https://se-edu.github.io/se-book/principles/dependencyInversionPrinciple/[se-edu/se-book: Principles: Dependency Inversion Principle] - -== Use Dependency Injection `[LO-DI]` - -Notice how the `LogicManager` class does not depend on the `StorageManager` class, but depends on the `Storage` interface. -This allows us to use _Dependency Injection_ to test the `LogicManager` class without getting the `StorageManager` class involved. - -=== References - -* https://se-edu.github.io/se-book/testing/dependencyInjection/[se-edu/se-book: Quality Assurance: Testing: Dependency Injection] - -=== Exercise: Facilitate injecting a StorageStub - -* Notice how `LogicManagerTest` tests `LogicManager` by constructing a `StorageManager` object. -* Implement `StorageStub` such that calls to its `save*` methods do nothing (i.e. empty method body). -* Update `LogicManagerTest` to work with the `StorageStub` instead of the actual `StorageManager` object. -i.e. `LogicManagerTest` injects a `StorageStub` object when constructing a `LogicManager` before testing it. -+ -image::DependencyInjection.png[width=600] -* The example above uses <> as a means to achieve DI. -Note that there is another way to inject a `StorageStub` object, as shown below. -In this case we do not apply the DIP but we still achieve DI. -+ -image::DependencyInjectionWithoutDIP.png[width=250] - -== Apply Open-Closed Principle `[LO-OCP]` - -=== References - -* https://se-edu.github.io/se-book/principles/openClosedPrinciple/[se-edu/se-book: Principles: Open-Closed Principle] - -=== Exercise: Analyze OCP-compliance of the `LogicManager` class - -* Consider adding a new command to the Address Book. e.g. an `edit` command. Notice how little you need to change in the `LogicManager` class to extend its behavior so that it can execute the new command. -That is because `LogicManager` follows the OCP i.e. `LogicManager` is _open to be extended_ with more commands but _closed for modifications_. -* Is it possible to make the `AddressBookParser` class more OCP-compliant in terms of extending it to handle more -command types? -* In terms of how it saves data, is `LogicManager` more OCP-compliant -due to the application of DIP as given in <>? -How can you improve ``LogicManager``'s OCP-compliance further so that it can not only work with different types -of storages, but different number of storages (e.g. save to both a text file and a database). - -== Work in a 3KLoC code base `[LO-3KLoC]` - -=== Exercise: Enhance AddressBook - -* Enhance AddressBook in some way. e.g. add a new command diff --git a/docs/SettingUp.adoc b/docs/SettingUp.adoc index c0659782fab..81a4e6a45ef 100644 --- a/docs/SettingUp.adoc +++ b/docs/SettingUp.adoc @@ -1,4 +1,4 @@ -= AddressBook Level 3 - Setting Up += HealthyBaby - Setting Up :site-section: DeveloperGuide :toc: :toc-title: @@ -12,7 +12,7 @@ ifdef::env-github[] :note-caption: :information_source: :warning-caption: :warning: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level3/tree/master +:repoURL: https://github.com/AY1920S2-CS2103T-T10-1/main == Prerequisites diff --git a/docs/Testing.adoc b/docs/Testing.adoc index 5767b92912c..edb449f70d2 100644 --- a/docs/Testing.adoc +++ b/docs/Testing.adoc @@ -1,4 +1,4 @@ -= AddressBook Level 3 - Testing += HealthyBaby - Testing :site-section: DeveloperGuide :toc: :toc-title: @@ -12,7 +12,7 @@ ifdef::env-github[] :note-caption: :information_source: :warning-caption: :warning: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level3/tree/master +:repoURL: https://github.com/AY1920S2-CS2103T-T10-1/main == Running Tests @@ -35,11 +35,11 @@ See <> for more info on how to run tests using G We have three types of tests: . _Unit tests_ targeting the lowest level methods/classes. + -e.g. `seedu.address.commons.StringUtilTest` +e.g. `seedu.recipe.commons.StringUtilTest` . _Integration tests_ that are checking the integration of multiple code units (those code units are assumed to be working). + -e.g. `seedu.address.storage.StorageManagerTest` +e.g. `seedu.recipe.storage.StorageManagerTest` . Hybrids of unit and integration tests. These test are checking multiple code units as well as how the are connected together. + -e.g. `seedu.address.logic.LogicManagerTest` +e.g. `seedu.recipe.logic.LogicManagerTest` == Troubleshooting Testing diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 4e5d297a19f..4e11f33ca29 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -1,4 +1,4 @@ -= AddressBook Level 3 - User Guide += HealthyBaby - User Guide :site-section: UserGuide :toc: :toc-title: @@ -10,168 +10,689 @@ :experimental: ifdef::env-github[] :tip-caption: :bulb: +:warning-caption: :warning: :note-caption: :information_source: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level3 +:repoURL: https://github.com/AY1920S2-CS2103T-T10-1/main -By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT` +By: `Team HYBB` Since: `Mar 2020` Licence: `MIT` == Introduction -AddressBook Level 3 (AB3) is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB3 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB3 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy! +*HealthyBaby* (HYBB) is a desktop application that provides you with a database of quick, easy, and healthy recipes. +Are you a *university student* staying on campus and are tired of purchasing the same few unhealthy meals? Looking for +healthier options but searching for and planning recipes are a hassle for you? HYBB is just the app for you! +HYBB helps alleviate the challenges faced while maintaining healthy eating habits, easing the transition from eating +out everyday to cooking healthy meals regularly. + +*Value proposition*: Focuses on healthy, simple recipes with short cooking time with ingredients filter to +minimise food wastage. + +HYBB is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of +a Graphical User Interface (GUI). +Through our convenient filters, searching and planning for new healthy recipes will be a breeze. + +Get motivated through our eye-catching goals and achievements. + +Interested? Jump to the <> to get started. Enjoy! + +== Overview (Harshita) +The main features of HYBB are as follows: + +=== Filter +HYBB enables filtering by specific components in the recipes such as goals, favourites, and ingredients in order to +reduce the time needed to find recipes that suit your needs. + +=== Planning +This feature enables students to plan their meals in advance and provides an easy grocery list for your shopping needs. + +=== Goals +This feature enables students to monitor their healthy eating progress, HYBB provides a history of all cooked meals along with +statistics based on 4 main goals: “Wholesome Wholemeals”, “Bulk like a Hulk”, “Herbivore” and "Fruity Fiesta". + +=== Achievements +This feature aims to encourage students to continue their healthy eating by showing visual evidence of their progress +through streaks and daily motivational quotes. == Quick Start -. Ensure you have Java `11` or above installed in your Computer. -. Download the latest `addressbook.jar` link:{repoURL}/releases[here]. -. Copy the file to the folder you want to use as the home folder for your Address Book. -. Double-click the file to start the app. The GUI should appear in a few seconds. +. Ensure you have `Java 11` or above installed in your Computer. +. Download the latest `healthybaby.jar` link:{repoURL}/releases[here]. +. Copy the file to the folder you want to use as the home folder for your HealthyBaby application. +. Double-click the file to start the app. The Graphical User Interface should appear in a few seconds. + image::Ui.png[width="790"] + -. Type the command in the command box and press kbd:[Enter] to execute it. + -e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. +. Enter a command in the command box to execute it. The result of the command will appear in the result box directly below the command box. ++ +e.g. Entering *`help`* will open the help window. . Some example commands you can try: -* *`list`* : lists all contacts -* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Address Book. -* **`delete`**`3` : deletes the 3rd contact shown in the current list -* *`exit`* : exits the app +* **`list`** : lists all recipes +* **`delete 3`** : deletes the 3rd recipe shown in the current list +* **`undo`** : undoes the previous action +* **`exit`** : exits the app . Refer to <> for details of each command. -[[Features]] -== Features +== The Anatomy of a Recipe +You can store the following information in a recipe: + +*Name* - Name of the recipe + +*Time* - Time taken for the recipe to be cooked, measured in minutes + +*Ingredients* - Ingredients used in the recipe, broken down into five categories (Grains, Vegetables, Proteins, Fruits, Others) + +*Steps* - Steps taken to cook the meal + +*Goals* - Goal that the recipe falls under + + +=== Goals (Harshita) +HYBB supports the following goals that model the Healthy Eating Plate. Goals are automatically added to a recipe you add or edit if they meet the recommended nutritional quantity specified for their respective food group. +|=== +|Goal |Food Group represented by Goal + +|Herbivore | Vegetables +|Fruity Fiesta | Fruits +|Bulk like the Hulk | Healthy Proteins +|Wholesome Wholemeals | Whole Grains +|=== + +=== Ingredients (Beatrice) +You can use the following units to measure how much of each ingredient is needed in the recipe. + +|=== +|Unit |Description + +|g |Grams +|ml |Milliliters +|tbsp |Tablespoon +|tsp |Teaspoon +|cup |Cups +|=== + +// tag::GUI[] +== HealthyBaby's User Interface (Beatrice) +Upon opening *HYBB*, you will see our Graphical User Interface. + +.HealthyBaby's User Interface +image::AnnotatedUserInterface.png[] + +The *Command Box* is where you can enter commands to tell HYBB what to do. + +The *Result Box* is where you can see whether the command you have given was successful or unsuccessful. + +The *Tab Panel* can be clicked to switch between tabs. + +Alternatively, if you wish to switch between tabs by typing instead of clicking, you can type `switch [tab name]` +into the Command Box instead. + +For more information, please refer to <>. + +The *Display Panel* displays the information for the current tab you are on. +// end::GUI[] + +== Notations Used +=== List of Tags +You can use the following tags to converse with HYBB. + +|=== +|Tag |Description + +|n/ |Name of recipe +|t/ |Time taken to prepare and cook recipe, measured in minutes +|ig/ |Grain ingredient (e.g. rice, bread, spaghetti) +|iv/ |Vegetable ingredient (e.g. spinach, cabbage, carrot) +|ip/ |Protein ingredient (e.g. chicken, salmon, tofu) +|if/ |Fruit ingredient (e.g. grapes, honeydew, watermelon) +|io/ |Other ingredient, for any other ingredient that do not belong in the above 4 categories (e.g. oyster sauce, +pepper, sesame oil) +|s/ |Steps of the recipe +|=== + +=== Legend +From sections 6 to 11, the following notations may be used. + +[cols="1a,1"] +|=== +|Notation |Meaning + +|[ ] |Necessary field +|< > |Optional field. e.g. `n/name ` can be used as `n/Spicy Chicken s/Step 1` or just `n/Spicy Chicken` +|[ < > ] |At least one of the optional fields is necessary +|… | One or more of this same field can be added. + +e.g. if the command specifies `...`, you may either leave +the field empty, or you may specify one or more protein ingredients. + +e.g. if the command specifies `[recipe index]...`, you may specify one or more recipe indexes. +|💡 | Tips for usage and things to take note of +|=== -==== -*Command Format* -* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`. -* Items in square brackets are optional e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`. -* Items with `…`​ after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. -* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable. -==== +[TIP] +Parameters can be in any order e.g. if the command specifies `n/name t/time`, `t/time n/name` is also acceptable. + +Also, commands are case-insensitive, but tags are case-sensitive. -=== Viewing help : `help` +[[Features]] +== Basic Commands +=== Viewing help : `help` +Gives you a short summary of all the available commands. + Format: `help` -=== Adding a person: `add` +=== Switch the current tab: `switch` (Harshita) +Switches the current tab you are in and changes the display. + +Format: `switch` [tab name] -Adds a person to the address book + -Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` +Example: `switch planning` + +Switches the current tab to the planning tab. [TIP] -A person can have any number of tags (including 0) +Tabs available: recipes, planning, goals, achievements. -Examples: +=== List all recipes: `list` +Lists all the recipes present in the database. + +Format: `list` -* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` -* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` +=== Find a recipe: `find` (Brian) +Searches for existing recipes by their names using the keyword(s) that you have specified. + +Format: `find [keyword] ...` -=== Listing all persons : `list` +Example 1: `find /strict Avocado Chicken` + +Finds recipes that contain the words "Avocado" *or* "Chicken" in their names (ie. only one of them has to be present). -Shows a list of all persons in the address book. + -Format: `list` +[TIP] +Using `/strict` will treat all subsequent keywords as *separate keywords* (separated by the space), +as seen in Example 1. + +{nbsp} + +It will also search for an *exact match* of each specified keyword (e.g. If you are searching for a recipe that +has "Avocado" in its name, `find /strict Avo` _will not_ be able to find it. Instead, use `find /strict Avocado` or +see Example 2) + +Example 2: `find Avocado Chicken` + +Finds recipes that contain the single keyword "Avocado Chicken". + +[TIP] +Without `/strict`, all the keywords will be taken as a *single keyword* and it *does not* require an exact match for a +recipe to be found (e.g. `find Avo` will be able to find recipes that has "Avocado" in its name) + +=== Add a recipe: `add` +Adds a recipe to the recipe book + +Format: `add [n/name] [t/time] [... ... ... ... ...] +...` + +Example: `add n/Chicken Rice t/30 ip/300g, Chicken Thigh ig/300g, Rice s/Boil chicken + s/While chicken is cooking, add sesame oil and crushed ginger into rice and cook it + s/When chicken is done, dip it into iced water + s/Serve while rice is hot` + +Adds a new recipe entry that contains the following description: + + +.Expected output +image::AddExample.png[] + +[TIP] +Multiple steps and multiple ingredients for a recipe can be added in this one command. + + +[TIP] +The compulsory fields needed in a recipe are the *name, time and at least one of the ingredient fields.* +You can add these fields first, then edit the recipe as needed using the various edit commands available +(Refer to section 6.6 and 7). + + +[TIP] +Name and time fields that require one input. If more than one name or more than one time is given, +HYBB will take the later input. + +For example, `add n/Chicken Rice n/Chicken with Rice t/30, ip/300g, Chicken Thigh` +would create a new recipe with the name Chicken with Rice. + +=== Edit a recipe : `edit` +Edits an existing recipe. This is the command used for editing entire fields at a time. + +Format: `edit [recipe index] [ ... ... ... ... +... ...]` + +Example: `edit 4 n/Chicken Rice t/20` + +Renames the 4th recipe to Chicken Rice, and sets the preparation time to 20 minutes (from whatever amount it was before). + +[TIP] +Using this command to edit a field that might have multiple entities like ‘vegetable ingredients’ or 'steps' will +overwrite the entire field. +For example, if the 4th recipe currently has a list of 5 vegetable ingredients, running `edit 4 iv/50g, Lettuce` will +replace the *entire* list of vegetable ingredients with only 50g of Lettuce. + + +[TIP] +To make changes to a single entity in a field without having to rewrite everything, please refer to +<>. + + +[TIP] +For fields that can only contain one entry like name and time, if more than one name or more than one time is given, +HYBB will take the later input. + +For example, `edit 4 t/10 t/20` +would change the time taken to 20 minutes for the recipe at index 4. -=== Editing a person : `edit` +=== Delete a recipe : `delete` (Brian) +Deletes the recipe(s) that you have specified. + +Format: `delete [recipe index] ...` -Edits an existing person in the address book. + -Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...` +Example: `delete 1 3 4` + +Deletes recipe 1, 3, and 4 from the recipe book. -**** -* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. The index *must be a positive integer* 1, 2, 3, ... -* At least one of the optional fields must be provided. -* Existing values will be updated to the input values. -* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative. -* You can remove all the person's tags by typing `t/` without specifying any tags after it. -**** +[TIP] +You can *delete, favourite, or unfavourite* multiple recipes at the same time (at least one recipe must be selected). -Examples: +[TIP] +If you specify a recipe number that does not exist in the list of recipes _that you are currently viewing_, none of your +selected recipes will be deleted, favourited, or unfavourited. -* `edit 1 p/91234567 e/johndoe@example.com` + -Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively. -* `edit 2 n/Betsy Crower t/` + -Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. +=== Favourite a recipe: `favourite` (Brian) +Favourites the recipe(s) that you have specified. + +Format: `favourite [recipe index] ...` -=== Locating persons by name: `find` +Example: `favourite 1 3 4` + +Favourites recipes 1, 3, and 4. -Finds persons whose names contain any of the given keywords. + -Format: `find KEYWORD [MORE_KEYWORDS]` +=== Unfavourite a recipe: `unfavourite` (Brian) +Unfavourites the recipe(s) that you have specified. + +Format: `unfavourite [recipe index] ...` -**** -* The search is case insensitive. e.g `hans` will match `Hans` -* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans` -* Only the name is searched. -* Only full words will be matched e.g. `Han` will not match `Hans` -* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` -**** +Example: `unfavourite 1 3 4` + +Unfavourites recipes 1, 3, and 4. -Examples: +// tag::undoredo[] +=== Undo a previous action: `undo` (Brian) +Undoes a previous action. + +Format: `undo or ` -* `find John` + -Returns `john` and `John Doe` -* `find Betsy Tim John` + -Returns any person having names `Betsy`, `Tim`, or `John` +Example 1: `undo` + +Undoes only the previous action. -// tag::delete[] -=== Deleting a person : `delete` +Example 2: `undo 3` + +Undoes the 3 previous actions. If there are less than 3 actions to undo, you will not be allowed to undo. -Deletes the specified person from the address book. + -Format: `delete INDEX` +Example 3: `undo all` + +Undoes all previous actions. -**** -* Deletes the person at the specified `INDEX`. -* The index refers to the index number shown in the displayed person list. -* The index *must be a positive integer* 1, 2, 3, ... -**** +[TIP] +For both undo and redo, the number of actions that you specify (if any) has to be a non-zero unsigned integer! -Examples: +=== Redo a previous undo: `redo` (Brian) +Restores actions that have been previously undone using `undo`. +Format: `redo or ` -* `list` + -`delete 2` + -Deletes the 2nd person in the address book. -* `find Betsy` + -`delete 1` + -Deletes the 1st person in the results of the `find` command. +Example 1: `redo` + +Restores the actions that have been undone by the previous undo. -// end::delete[] -=== Clearing all entries : `clear` +Example 2: `redo 3` + +Restores the actions that have been undone by the previous 3 undo-s. If there are less than 3 actions to restore, you +not be allowed to redo. -Clears all entries from the address book. + +Example 3: `redo all` + +Restores the actions that have been undone by all previous undo-s. +// end::undoredo[] + +=== Clear the recipe book : `clear` +Clears the recipe book. After entering this command, the recipe book will be empty and all planned recipes +will be removed. + Format: `clear` -=== Exiting the program : `exit` +[WARNING] +All recipes and plans, including default ones, will be removed. + +[TIP] +You can `undo` this command if it was performed by accident. -Exits the program. + +=== Exit the program : `exit` +Saves HYBB and exits the program. + Format: `exit` === Saving the data - -Address book data are saved in the hard disk automatically after any command that changes the data. + +HYBB's data is saved in the hard disk automatically after any command that changes the data. + There is no need to save manually. -// tag::dataencryption[] -=== Encrypting data files `[coming in v2.0]` +// tag::recipecustomisation[] +== Recipe Customisation Commands (Brian) +As we see from the `edit` command in section 6.6, if you want to add, edit, or delete a single ingredient or step, +you would have to rewrite the whole field that you wish to edit. This would be troublesome if the field contains +multiple ingredients or steps that you may not necessarily want to edit. Therefore, the following commands are used in +occasions like these! + +=== Add Ingredients to a Recipe: `addIngredient` (Brian) +Adds more ingredients to an existing recipe. + +Format: `addIngredient [recipe index] [... ... ... ... ...]` + +Example: `addIngredient 2 ig/50g, Bread io/5g, Butter` + +Adds 50g of Bread and 5g of Butter to recipe 2. + +[TIP] +You can add multiple ingredients at a time (at least one ingredient must be added). + +[TIP] +If you add an ingredient that already exists in the recipe, that existing ingredient will be replaced with the new one. + +=== Edit Ingredient Quantity in a Recipe: `editIngredient` (Brian) +Edits the quantity of an ingredient in an existing recipe. + +Format: `editIngredient [recipe index] [... ... ... ...]` + +Example: `editIngredient 3 ig/50g, Bread` + +Searches for Bread in recipe 3 and changes its quantity to 50g. An error message will appear if Bread does not exist in +recipe 3's ingredients set. + +[TIP] +You can edit multiple ingredients at a time (at least one ingredient must be edited). + +=== Delete Ingredients in a Recipe: `deleteIngredient` (Brian) +Deletes the specified ingredient(s) from an existing recipe. + +Format: `deleteIngredient [recipe index] [... ... ... +... ...]` + +Example: `deleteIngredient 3 ig/Rice iv/Kailan` + +Searches for Rice and Kailan in recipe 3 and deletes them. An error message will appear if Rice and/or Kailan does not +exist in recipe 3's ingredients set. + +[TIP] +You can delete multiple ingredients at a time (at least one ingredient must be deleted). + +[TIP] +There is no need to specify quantity here. Just the ingredient name will do! + +[TIP] +If you type an ingredient prefix (e.g. "ig/") but don't specify any ingredients, all ingredients of that type will be +deleted. + +=== Add Steps to a Recipe: `addStep` (Brian) +Adds more steps to an existing recipe. + +Format: `addStep [recipe index] [s/step] ...` + +Example: `addStep 1 s/New step s/Another new step` + +Adds 2 new steps to recipe 1. + +[TIP] +You can add multiple steps at a time (at least one step must be added). + +=== Edit a Step in a Recipe: `editStep` (Brian) +Edits the specified step in an existing recipe. + +Format: `editStep [recipe index] [step index] [s/new step]` + +Example: `editStep 3 4 s/Edited new step` + +Replaces step 4 of recipe 3 with “Edited new step”. If you specify more than one step, only the first one will be used +to replace the old step. + +=== Delete Steps in a Recipe: `deleteStep` (Brian) +Deletes the specified step(s) from an existing recipe. + +Format: `deleteStep [recipe index] [step index] ...` + +Example: `deleteStep 3 2 3 5` + +Deletes steps 2, 3, and 5 of recipe 3. + +[TIP] +You can delete multiple steps at a time (at least one step must be deleted). +// end::recipecustomisation[] + +// tag::advancedfilter[] +== Filter Command (Brian) +This command is not to be confused with the `Find` command, which only searches for recipes by their names. The +`Filter` command is a more robust search command that allows you to search for recipes using _various criteria_. + +[TIP] +You can combine the input of the next few subsections to filter the recipes by multiple criteria! -_{explain how the user can enable/disable data encryption}_ -// end::dataencryption[] +=== Filter by ingredients (Brian) +Finds recipes that contains the specified ingredients. + +Format: `filter ... ... ... ... ...` -== FAQ +Example 1: `filter ig/Rice iv/Cabbage` + +Finds recipes that contains Rice and Cabbage. + +Example 2: `filter ig/exclude Pasta ip/Chicken` + +Finds recipes that *does not* contain Pasta and contains Chicken. + +[TIP] +Notice the use of the keyword "exclude" in Example 2? Use this to exclude ingredients that you do not want! + +=== Filter by goals (Brian) +Finds recipes that are tagged with the specified goal. + +Format: `filter [g/goal] ...` + +Example: `filter g/Herbivore` + +Finds recipes that are tagged with the `Herbivore` goal. + +=== Filter by favourites (Brian) +Finds recipes that are tagged as favourites. + +Format: `filter favourites` + +=== Filter by preparation time (Brian) +Finds recipes that have preparation time less than or equals to the specified time (in minutes). + +Format: `filter [t/time] or [t/time range]` + +Example 1: `filter t/15` + +Finds recipes that have 15 minutes or less of preparation time. + +Example 2: `filter t/20-30` + +Finds recipes that have 20 to 30 minutes (inclusive) of preparation time. +// end::advancedfilter[] + + +// tag::planning[] +== Planning Command (Beatrice) +Most of the planning commands take place in the planning tab. + +Switch to the planning tab by typing `switch planning` or by clicking on Planning from the *Tab Panel*. + + +You should get the following interface: + +.Planning Tab +image::PlanTab.png[] +The *Display Panel* for the planing tab lists all the plans that you have made. + + +You can the see the details of each plan from the list of plans. + +.Details of each plan +image::PlanTab_Plan.png[] + +=== Plan a recipe: `plan` (Beatrice) +Plans a recipe that you would like to cook on a certain day in the future. + +Format: `plan [recipe index] [d/yyyy-mm-dd]` + +Example 1: `plan 1 d/2020-05-27` + +Plans the recipe at _recipe index_ 1 on 27 May 2020 and adds this plan into the plan list. + + +Example 2: `plan 1 2 3 d/2020-05-27` + +Plans the recipes at _recipe indexes_ 1, 2 and 3 on 27 May 2020 and adds these three plans into +the plan list. + +[TIP] +As long as at least one index is specified, you can plan as many recipes as you want in one go. For example, we can +plan for five recipes in one command. `plan 1 2 3 4 5 d/2020-05-27` will plan for the recipes at _recipe indexes_ +1, 2, 3, 4 and 5 on 27 May 2020. + +[WARNING] +Valid indexes are integer numbers ranging from 1 to the current plan list size. If one of the indexes given was +invalid, the command will not be successful. + +[WARNING] +Valid dates start from the today's date and are in the format yyyy-mm-dd. +This means that we cannot make a plan on yesterday's date. + +=== Delete a plan: `deletePlan` (Beatrice) +Deletes a plan. + +Format: `deletePlan [plan index]...` + +Example 1: `deletePlan 3` + +Deletes the 3rd plan. + +Example 2: `deletePlan 3 5 8` + +Deletes the 3rd, 5th and 8th plan. + +[TIP] +As long as at least one index is specified, you can delete as many plans as you want in one go. For example, we can +delete five plans in one command. `deletePlan 1 2 3 4 5` will delete all plans at plan indexes 1, 2, 3, 4 and 5. + +[WARNING] +Valid indexes are integer numbers ranging from 1 to the current plan list size. If one of the indexes given was +invalid, the command will not be successful. + +[TIP] +Using the `cooked` command in <> will automatically delete today's plan for +the recipe that is cooked. + + +=== Clear all planned recipes: `clearPlan` (Beatrice) +Clears all the plans you have made. + +Format: `clearPlan` + +[WARNING] +All plans will be removed. + +[TIP] +You can `undo` this command if it was performed by accident. + +=== Obtain ingredients for planned recipes: `groceryList` (Beatrice) +Lists the ingredients needed for all recipes that have been planned. + +Click on 'Copy' to copy all the ingredients into your clipboard. + +Simplify your next grocery shopping experience by pasting this list into your preferred social networking +application (like Telegram or Whatsapp) and sending it to yourself for an easy reference from your +mobile phone. + +Alternatively, you can paste the list into a word document and print it out. + +You can print this list out by pasting the text into a word document to +Format: `groceryList` + +[WARNING] +If no plans have been made, the grocery list will not be generated. + +=== View this week's planned recipes: `viewWeek` [Coming in v2.0] +View all the plans for the week. + +Format: `viewWeek` + +=== View this month's planned recipes: `viewMonth` [Coming in v2.0] +View all the plans for the month. + +Format: `viewMonth` +// end::planning[] + +== Goals Command (Harshita) + +=== Remove goal: `deleteGoal` (Harshita) +Deletes a goal that has been auto-generated through the addition or editing of a recipe from a specific recipe. + +Format: `deleteGoal [recipe index] [goal]` + +Example 1: `deleteGoal 2 Bulk like the Hulk` + +Deletes goal named Bulk like the Hulk from the 2nd recipe if it exists. + +[TIP] +Ensure that the capitalisation of the goal is the same! Check out `listGoals` if unsure. + +=== List goals being tracked: `listGoals` (Harshita) +Lists all goals tracked by HYBB. + +Format: `listGoals` + +Example 1: `listGoals` + +Displays the 4 main goals being tracked in the *Result Box*. + +=== Track cooked meals: `cooked` (Harshita) +Tracks all cooked meals and adds to the progress of their respective goals. + +Format: `cooked [recipe index] ...` + +Example 1: `cooked 2` + +Marks the 2nd recipe as cooked. + +[TIP] +You can mark multiple recipes as cooked at the same time (at least one recipe must be marked). + +Example 2: `cooked 3 4 8` + +Marks the 3rd, 4th and 8th recipe as cooked. + +[WARNING] +If you specify a recipe number that has already been cooked within the day or does not exist in the list of recipes +_under the recipes tab_, none of your selected recipes will be marked as cooked. + +[WARNING] +If a plan for the recipe being cooked exists today, using `cooked` will automatically delete these plans. + +[TIP] +A history of all cooked meals, along with a pie chart based on your meals cooked, can be found under the goals tab. + +.Goal tab +image::goalsTab.png[width="790"] + +[TIP] +The pie chart represents the goals tally according to your cooked meal history and models the Healthy Eating Plate! + +=== Show progress of goals: `chart` [Coming in v2.0] +Shows weekly progress of respective goal through graph. + +Format: `chart [g/goal]` + +=== Analyse images added: `analyse` [Coming in v2.0] +Auto-generates goals and statistics through the use of Artificial Intelligence. + + +== Achievement Command (Yue Tong) + +=== Add motivational quote : `quote` +Adds a quote by the user to the quote database to store for future(randomised) display of quote in Achievement tab. +Format: `quote` [quote] + +Example 1: `quote Today was yesterday's tomorrow` + +Adds quote "Today was yesterday's tomorrow" to quote database. + +// tag::achievement[] +.Achievement tab +image::QuotesTab.png[width="790"] + +=== Display streak: `streak` [Coming in v2.0] +Displays line chart of all logged streaks by user +Format: `streak` + +=== Remove quote: `remove quote` [Coming in v2.0] +Removes quote indicated by user + +Format: `remove quote` [quote] + +=== Remove quote: `change quote` [Coming in v2.0] +Changes currently displayed quote to a new randomised one + +Format: `change quote` +//end::achievement[] + +== FAQ (Harshita) *Q*: How do I transfer my data to another Computer? + -*A*: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous Address Book folder. +*A*: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the +data of your previous HYBB folder. + +*Q*: How does the auto-generation of goals work? + +*A*: HYBB analyses the ingredients added or edited in a recipe and auto-generates goals for you. The recipe being tagged by a goal suggests that the minimum requirement per meal for the respective food group, as recommended by the National Institute of Health, has been met. + +*Q*: Why is there a deleteGoal command and no addGoal command? + +*A*: As this is the beta version of HYBB, the auto-generation of goals is designed to either accurately calculate quantity or err on the side of overestimation. This would allow you to remove any goal you deem inaccurate based on your own judgement. You can look forward to future releases which will integrate artificial intelligence into HYBB to auto-generate goals more accurately! + +*Q*: Why are there no safeguards for adding ingredients? + +*A*: Currently, HYBB is designed to help you manage your customized recipe list. Hence, the addition of ingredients and under which tag(ip/ iv/ ig/ if/ io/) they fall would be solely based on your judgement! For future releases, we will ensure more safeguards to prevent invalid inputs based on common knowledge. + +*Q*: What are recipe indexes and plan indexes? + +*A*: Recipe indexes are the numbers beside each recipe in the 'Recipes' tab. +On the other hand, plan indexes are the numbers beside each plan in the 'Planning' tab. + +== Glossary (Harshita) +|=== +|Term |Definition + +|Command Line Interface | Text-based interface used for entering commands. +|Healthy Eating Plate | Refers to My Healthy Plate designed for Singaporeans by the Health Promotion Board. It is a visual guide that shows you what to eat in the right amounts for each meal, so that you can plan your portions accordingly. +|=== == Command Summary -* *Add* `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` + -e.g. `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague` -* *Clear* : `clear` -* *Delete* : `delete INDEX` + -e.g. `delete 3` -* *Edit* : `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]...` + -e.g. `edit 2 n/James Lee e/jameslee@example.com` -* *Find* : `find KEYWORD [MORE_KEYWORDS]` + -e.g. `find James Jake` -* *List* : `list` -* *Help* : `help` +|=== +|Command |Action + +|`help` |View help +|`switch` |Switch to the desired tab +|`list` |List all recipes +|`find` |Find recipes by name +|`add` |Add a recipe +|`edit` |Edit a recipe +|`delete` |Delete recipes +|`favourite` |Favourite recipes +|`unfavourite` |Unfavourite recipes +|`clear` |Clear the recipe book +|`exit` |Exit the programme +|`addIngredient` |Add ingredients to a recipe +|`editIngredient` |Edit ingredients’ quantities in a recipe +|`deleteIngredient` |Delete ingredients in a recipe +|`addStep` |Add steps to a recipe +|`editStep` |Edit a step in a recipe +|`deleteStep` |Delete steps in a recipe +|`filter` |Search for recipes by (multiple) criteria +|`plan` |Plan recipes +|`deletePlan` |Delete plans +|`clearPlan` |Clear all plans +|`groceryList` |List all ingredients used in the planned recipes +|`deleteGoal` |Deletes specified goal from a recipe +|`listGoals` |Lists all available goals +|`cooked` |Records a recipe as cooked +|`quote` |Adds a new quote +|=== diff --git a/docs/UsingTravis.adoc b/docs/UsingTravis.adoc index 887c0b09068..7df940e1e72 100644 --- a/docs/UsingTravis.adoc +++ b/docs/UsingTravis.adoc @@ -70,7 +70,7 @@ image:travis_build.png[Travis build] Using this account, generate a personal access token https://github.com/settings/tokens/new[here]. + [NOTE] -Personal access tokens are like passwords so make sure you keep them secret! If the personal access token is leaked, please delete it and generate a new one. +Recipeal access tokens are like passwords so make sure you keep them secret! If the personal access token is leaked, please delete it and generate a new one. + [NOTE] We use a new user account to generate the token for team projects to prevent team members from gaining access to other team members' repos. + diff --git a/docs/diagrams/AddRefSequenceDiagram.puml b/docs/diagrams/AddRefSequenceDiagram.puml new file mode 100644 index 00000000000..c226bd69273 --- /dev/null +++ b/docs/diagrams/AddRefSequenceDiagram.puml @@ -0,0 +1,33 @@ +@startuml +!include style.puml + +skinparam sequenceGroup { + borderColor black + borderThickness 1 + FontName Arial + FontStyle normal + HeaderFontStyle normal + BodyBackgroundColor azure +} + + +participant "r:Recipe" as Recipe MODEL_COLOR +participant "Ingredient" as Ingredient MODEL_COLOR +participant "q:Quantity" as Quantity MODEL_COLOR + + +loop each ingredient in ingredients +Recipe -> Ingredient : getMainIngredientType() +activate Ingredient +Ingredient -> Quantity : getQuantity() +activate Quantity +Quantity -> Quantity : convertToGram() +activate Quantity +Quantity --> Quantity +deactivate Quantity +Quantity --> Ingredient : q +deactivate Quantity +Ingredient --> Recipe: q +deactivate Ingredient +end +@enduml diff --git a/docs/diagrams/AddSequenceDiagram.puml b/docs/diagrams/AddSequenceDiagram.puml new file mode 100644 index 00000000000..220c022cf6b --- /dev/null +++ b/docs/diagrams/AddSequenceDiagram.puml @@ -0,0 +1,78 @@ +@startuml +!include style.puml + +skinparam sequenceGroup { + borderColor black + borderThickness 1 + FontName Arial + FontStyle normal + HeaderFontStyle normal + BodyBackgroundColor azure +} + +box Logic LOGIC_COLOR_T1 +participant "a:AddCommand" as AddCommand LOGIC_COLOR +participant ":CommandResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant "r:Recipe" as Recipe MODEL_COLOR +participant ":MainIngredientTypeMagnitude" as MainIngredientTypeMagnitude MODEL_COLOR +participant ":Goal" as Goal MODEL_COLOR +participant ":Model" as Model MODEL_COLOR + +end box + +[-> AddCommand : execute() +activate AddCommand + +AddCommand -> Recipe : calculateGoals() +activate Recipe + +loop each ingredientType in MainIngredientType +Recipe -> Recipe : calculateIngredientQuantity() +activate Recipe + +ref over Recipe : get total quantity for each ingredientType + +Recipe --> Recipe : totalMagnitude +deactivate Recipe +end +create MainIngredientTypeMagnitude +Recipe -> MainIngredientTypeMagnitude : new MainIngredientTypeMagnitude() +activate MainIngredientTypeMagnitude +MainIngredientTypeMagnitude --> Recipe +deactivate MainIngredientTypeMagnitude + +Recipe -> MainIngredientTypeMagnitude : getMainTypes() +activate MainIngredientTypeMagnitude +MainIngredientTypeMagnitude --> Recipe : set of MainIngredientType +deactivate MainIngredientTypeMagnitude + +loop each mainIngredientType in set of MainIngredientType +create Goal +Recipe -> Goal : new Goal(mainIngredientType) +activate Goal +Goal --> Recipe +deactivate Goal +end + +Recipe -> Recipe: updateGoals() +Recipe --> AddCommand +deactivate Recipe + +AddCommand -> Model : addRecipe(r) +activate Model +Model --> AddCommand +deactivate Model + +create CommandResult +AddCommand -> CommandResult +activate CommandResult +CommandResult --> AddCommand +deactivate CommandResult + +[<--AddCommand : result +deactivate AddCommand + +@enduml diff --git a/docs/diagrams/AdvancedFilterSequenceDiagram.puml b/docs/diagrams/AdvancedFilterSequenceDiagram.puml new file mode 100644 index 00000000000..0ff957dc743 --- /dev/null +++ b/docs/diagrams/AdvancedFilterSequenceDiagram.puml @@ -0,0 +1,70 @@ +@startuml +!include style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":RecipeBookParser" as RecipeBookParser LOGIC_COLOR +participant ":FilterCommandParser" as FilterCommandParser LOGIC_COLOR +participant "p:RecipeMatchesKeywordsPredicate" as RecipeMatchesKeywordsPredicate LOGIC_COLOR +participant "f:FilterCommand" as FilterCommand LOGIC_COLOR +participant ":CommandResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Model" as Model MODEL_COLOR +end box + +-> LogicManager: execute("filter favourites t/20 ig/Pasta") +activate LogicManager + +LogicManager -> RecipeBookParser: parseCommand("filter favourites t/20 ig/Pasta") +activate RecipeBookParser + +create FilterCommandParser +RecipeBookParser -> FilterCommandParser: parse("favourites t/20 ig/Pasta") +activate FilterCommandParser + +create RecipeMatchesKeywordsPredicate +FilterCommandParser -> RecipeMatchesKeywordsPredicate +activate RecipeMatchesKeywordsPredicate + +RecipeMatchesKeywordsPredicate --> FilterCommandParser: p +deactivate RecipeMatchesKeywordsPredicate + +create FilterCommand +FilterCommandParser -> FilterCommand +activate FilterCommand + +FilterCommand --> FilterCommandParser: f +deactivate FilterCommand + +FilterCommandParser --> RecipeBookParser: f +deactivate FilterCommandParser + +RecipeBookParser --> LogicManager: f +deactivate RecipeBookParser +destroy FilterCommandParser + +LogicManager -> FilterCommand: execute() +activate FilterCommand + +FilterCommand -> Model: updateFilteredRecipeList(p) +activate Model + +Model --> FilterCommand +deactivate Model + +create CommandResult +FilterCommand -> CommandResult +activate CommandResult + +CommandResult --> FilterCommand: result +deactivate CommandResult + +FilterCommand --> LogicManager: result +deactivate FilterCommand + +<-- LogicManager: result +deactivate LogicManager + +@enduml diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml index d1e2ae93675..ef5fe1855e2 100644 --- a/docs/diagrams/ArchitectureSequenceDiagram.puml +++ b/docs/diagrams/ArchitectureSequenceDiagram.puml @@ -13,13 +13,13 @@ activate ui UI_COLOR ui -[UI_COLOR]> logic : execute("delete 1") activate logic LOGIC_COLOR -logic -[LOGIC_COLOR]> model : deletePerson(p) +logic -[LOGIC_COLOR]> model : deleteRecipe(p) activate model MODEL_COLOR model -[MODEL_COLOR]-> logic deactivate model -logic -[LOGIC_COLOR]> storage : saveAddressBook(addressBook) +logic -[LOGIC_COLOR]> storage : saveRecipeBook(recipeBook) activate storage STORAGE_COLOR storage -[STORAGE_COLOR]> storage : Save to file diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/BetterModelClassDiagram.puml index 7790472da52..94fc7434efd 100644 --- a/docs/diagrams/BetterModelClassDiagram.puml +++ b/docs/diagrams/BetterModelClassDiagram.puml @@ -4,18 +4,18 @@ skinparam arrowThickness 1.1 skinparam arrowColor MODEL_COLOR skinparam classBackgroundColor MODEL_COLOR -AddressBook *-right-> "1" UniquePersonList +AddressBook *-right-> "1" UniqueRecipeList AddressBook *-right-> "1" UniqueTagList -UniqueTagList -[hidden]down- UniquePersonList -UniqueTagList -[hidden]down- UniquePersonList +UniqueTagList -[hidden]down- UniqueRecipeList +UniqueTagList -[hidden]down- UniqueRecipeList UniqueTagList *-right-> "*" Tag -UniquePersonList o-right-> Person +UniqueRecipeList o-right-> Recipe -Person o-up-> "*" Tag +Recipe o-up-> "*" Tag -Person *--> Name -Person *--> Phone -Person *--> Email -Person *--> Address +Recipe *--> Name +Recipe *--> Phone +Recipe *--> Step +Recipe *--> Address @enduml diff --git a/docs/diagrams/CommitActivityDiagram.puml b/docs/diagrams/CommitActivityDiagram.puml index 7f8fe407f89..16645558bf1 100644 --- a/docs/diagrams/CommitActivityDiagram.puml +++ b/docs/diagrams/CommitActivityDiagram.puml @@ -5,10 +5,11 @@ start 'Since the beta syntax does not support placing the condition outside the 'diamond we place it as the true branch instead. -if () then ([command commits AddressBook]) - :Purge redunant states; - :Save AddressBook to - addressBookStateList; +if () then ( [command + commits book]) + :Purge redundant states; + :Save book, commandType, and tab + to MultipleBookStateManager; else ([else]) endif stop diff --git a/docs/diagrams/CookedActivityDiagram.puml b/docs/diagrams/CookedActivityDiagram.puml new file mode 100644 index 00000000000..c7402190471 --- /dev/null +++ b/docs/diagrams/CookedActivityDiagram.puml @@ -0,0 +1,29 @@ + + +@startuml +start +:User enters "cooked 1"; + +'Since the beta syntax does not support placing the condition outside the +'diamond we place it as the true branch instead. + +if () then ([Model does not\n have recipe with the\n given recipe index]) + :Throw exception + for no such recipe; +elseif () then ([Recipe has already\n been cooked]) + :Throw exception + for recipe already + cooked within the day; +else ([else]) + :Recipe successfully + marked as cooked; + + -Recipe appears in \nhistory list of cooked\nmeals + if () then ([Recipe cooked \ncontains goals]) + :Pie chart updates to \nshow new goal distribution; + +endif +endif + +stop +@enduml diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeleteSequenceDiagram.puml index 1dc2311b245..33128dd5373 100644 --- a/docs/diagrams/DeleteSequenceDiagram.puml +++ b/docs/diagrams/DeleteSequenceDiagram.puml @@ -3,7 +3,7 @@ box Logic LOGIC_COLOR_T1 participant ":LogicManager" as LogicManager LOGIC_COLOR -participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR +participant ":RecipeBookParser" as RecipeBookParser LOGIC_COLOR participant ":DeleteCommandParser" as DeleteCommandParser LOGIC_COLOR participant "d:DeleteCommand" as DeleteCommand LOGIC_COLOR participant ":CommandResult" as CommandResult LOGIC_COLOR @@ -16,17 +16,17 @@ end box [-> LogicManager : execute("delete 1") activate LogicManager -LogicManager -> AddressBookParser : parseCommand("delete 1") -activate AddressBookParser +LogicManager -> RecipeBookParser : parseCommand("delete 1") +activate RecipeBookParser create DeleteCommandParser -AddressBookParser -> DeleteCommandParser +RecipeBookParser -> DeleteCommandParser activate DeleteCommandParser -DeleteCommandParser --> AddressBookParser +DeleteCommandParser --> RecipeBookParser deactivate DeleteCommandParser -AddressBookParser -> DeleteCommandParser : parse("1") +RecipeBookParser -> DeleteCommandParser : parse("1") activate DeleteCommandParser create DeleteCommand @@ -36,19 +36,19 @@ activate DeleteCommand DeleteCommand --> DeleteCommandParser : d deactivate DeleteCommand -DeleteCommandParser --> AddressBookParser : d +DeleteCommandParser --> RecipeBookParser : d deactivate DeleteCommandParser 'Hidden arrow to position the destroy marker below the end of the activation bar. -DeleteCommandParser -[hidden]-> AddressBookParser +DeleteCommandParser -[hidden]-> RecipeBookParser destroy DeleteCommandParser -AddressBookParser --> LogicManager : d -deactivate AddressBookParser +RecipeBookParser --> LogicManager : d +deactivate RecipeBookParser LogicManager -> DeleteCommand : execute() activate DeleteCommand -DeleteCommand -> Model : deletePerson(1) +DeleteCommand -> Model : deleteRecipe(1) activate Model Model --> DeleteCommand diff --git a/docs/diagrams/EditActivityDiagram.puml b/docs/diagrams/EditActivityDiagram.puml new file mode 100644 index 00000000000..7685ea8d16f --- /dev/null +++ b/docs/diagrams/EditActivityDiagram.puml @@ -0,0 +1,27 @@ +@startuml +start +:User enters edit command; + +if () then ([user enters invalid index]) +:Display invalid index error message; + +else ([else]) + if () then ([user enters invalid values\nfor properties (name, time, etc..)]) + :Display invalid value error message; + + else ([else]) + if () then ([user does not edit any properties]) + :Display error message with \nproper edit command's usage example; + + else ([else]) + :Edit recipe; + if () then ([Plans exists \nfor recipe]) + :Edit plans; + else ( [else]) + endif + endif + endif +endif +stop + +@enduml diff --git a/docs/diagrams/EditModelSequenceDiagram.puml b/docs/diagrams/EditModelSequenceDiagram.puml new file mode 100644 index 00000000000..4900e5fa18e --- /dev/null +++ b/docs/diagrams/EditModelSequenceDiagram.puml @@ -0,0 +1,77 @@ +@startuml +!include style.puml + +box Model MODEL_COLOR_T1 +participant ":ModelManager" as ModelManager MODEL_COLOR +participant ":RecipeBook" as RecipeBook MODEL_COLOR +participant ":UniqueRecipeList" as UniqueRecipeList MODEL_COLOR +participant ":PlannedBook" as PlannedBook MODEL_COLOR +participant ":PlannedRecipeMap" as PlannedRecipeMap MODEL_COLOR +participant ":UniquePlannedList" as UniquePlannedList MODEL_COLOR +participant ":Plan" as OldPlan MODEL_COLOR +participant "newPlan:Plan" as NewPlan MODEL_COLOR +end box + +[-> ModelManager : setRecipe(target, editedR) +activate ModelManager + +ModelManager -> RecipeBook : setRecipe(target, editedR) +activate RecipeBook + +RecipeBook -> UniqueRecipeList : setRecipe(target, editedR) +activate UniqueRecipeList + +UniqueRecipeList --> RecipeBook +deactivate UniqueRecipeList + +RecipeBook --> ModelManager +deactivate RecipeBook + +ModelManager -> PlannedBook : setRecipe(target, editedR) +activate PlannedBook + +PlannedBook -> PlannedRecipeMap : getPlans(target) +activate PlannedRecipeMap + +PlannedRecipeMap --> PlannedBook +deactivate PlannedRecipeMap + +alt oldPlans exist + loop for all oldPlan that uses target recipe + + PlannedBook -> OldPlan : setRecipe(editedR) + activate OldPlan + + create NewPlan + OldPlan -> NewPlan + activate NewPlan + + NewPlan --> OldPlan : newPlan + deactivate NewPlan + + OldPlan --> PlannedBook : newPlan + deactivate OldPlan + + PlannedBook -> UniquePlannedList : setPlan(oldPlan, newPlan) + activate UniquePlannedList + + UniquePlannedList --> PlannedBook + deactivate UniquePlannedList + end + + PlannedBook -> PlannedRecipeMap : setRecipe(target, editedR, newPlans) + activate PlannedRecipeMap + + PlannedRecipeMap --> PlannedBook + deactivate PlannedRecipeMap + +end + +PlannedBook --> ModelManager +deactivate PlannedBook + + +[<-- ModelManager +deactivate ModelManager + +@enduml diff --git a/docs/diagrams/EditSequenceDiagram.puml b/docs/diagrams/EditSequenceDiagram.puml new file mode 100644 index 00000000000..4c16f6b6542 --- /dev/null +++ b/docs/diagrams/EditSequenceDiagram.puml @@ -0,0 +1,114 @@ +@startuml +!include style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":RecipeBookParser" as RecipeBookParser LOGIC_COLOR +participant ":EditCommandParser" as EditCommandParser LOGIC_COLOR +participant ":ParserUtil" as ParserUtil LOGIC_COLOR +participant "editDescriptor:EditRecipeDescriptor" as EditRecipeDescriptor LOGIC_COLOR +participant "edit:EditCommand" as EditCommand LOGIC_COLOR +participant "cr:CommandResult" as CommandResult LOGIC_COLOR + +end box + +box Model MODEL_COLOR_T1 +participant ":Model" as Model MODEL_COLOR +participant "name:Name" as Name MODEL_COLOR +participant "editedR:Recipe" as Recipe MODEL_COLOR +end box + +[-> LogicManager : execute("edit 3 n/Chicken rice") +activate LogicManager + +LogicManager -> RecipeBookParser : parseCommand("edit 3 n/Chicken rice") +activate RecipeBookParser + +create EditCommandParser +RecipeBookParser -> EditCommandParser +activate EditCommandParser + +EditCommandParser --> RecipeBookParser +deactivate EditCommandParser + +RecipeBookParser -> EditCommandParser : parse("3 n/Chicken rice") +activate EditCommandParser + +create EditRecipeDescriptor +EditCommandParser -> EditRecipeDescriptor +activate EditRecipeDescriptor + +EditRecipeDescriptor --> EditCommandParser : editDescriptor +deactivate EditRecipeDescriptor + +EditCommandParser --> ParserUtil : parseName("Chicken rice") +activate ParserUtil + +create Name +ParserUtil -> Name +activate Name + +Name --> ParserUtil : name +deactivate Name + +ParserUtil --> EditCommandParser : name +deactivate ParserUtil + +create EditCommand +EditCommandParser -> EditCommand +activate EditCommand + +EditCommand --> EditCommandParser : edit +deactivate EditCommand + +EditCommandParser --> RecipeBookParser : edit +deactivate EditCommandParser +'Hidden arrow to position the destroy marker below the end of the activation bar. +EditCommandParser -[hidden]-> RecipeBookParser +destroy EditCommandParser + +RecipeBookParser --> LogicManager : edit +deactivate RecipeBookParser + +LogicManager -> EditCommand : execute() +activate EditCommand + +EditCommand -> Model : getFilteredRecipeList() +activate Model +Model --> EditCommand : recipeList +deactivate Model + +EditCommand -> EditCommand : createEditedRecipe() +activate EditCommand + +create Recipe +EditCommand -> Recipe +activate Recipe +Recipe --> EditCommand : editedR +deactivate Recipe +EditCommand --> EditCommand : editedR +deactivate EditCommand + +EditCommand -> Model : setRecipe(target, editedR) +activate Model +Model --> EditCommand +deactivate Model + +EditCommand -> Model : commitBook() +activate Model +Model --> EditCommand +deactivate Model + +create CommandResult +EditCommand -> CommandResult +activate CommandResult +CommandResult --> EditCommand : cr +deactivate CommandResult + +EditCommand --> LogicManager : cr +deactivate EditCommand + +[<--LogicManager +deactivate LogicManager + +@enduml diff --git a/docs/diagrams/FavouriteCommandSequenceDiagram.puml b/docs/diagrams/FavouriteCommandSequenceDiagram.puml new file mode 100644 index 00000000000..0f8b9d26cda --- /dev/null +++ b/docs/diagrams/FavouriteCommandSequenceDiagram.puml @@ -0,0 +1,77 @@ +@startuml +!include style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":RecipeBookParser" as RecipeBookParser LOGIC_COLOR +participant ":FavouriteCommandParser" as FavouriteCommandParser LOGIC_COLOR +participant "ParserUtil" as ParserUtil LOGIC_COLOR +participant "f:FavouriteCommand" as FavouriteCommand LOGIC_COLOR +participant ":CommandResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Model" as Model MODEL_COLOR +end box + +-> LogicManager: execute("favourite 3") +activate LogicManager + +LogicManager -> RecipeBookParser: parseCommand("favourite 3") +activate RecipeBookParser + +create FavouriteCommandParser +RecipeBookParser -> FavouriteCommandParser: parse("3") +activate FavouriteCommandParser + +FavouriteCommandParser -> ParserUtil +activate ParserUtil +ParserUtil --> FavouriteCommandParser: Index[] +deactivate ParserUtil + +create FavouriteCommand +FavouriteCommandParser -> FavouriteCommand +activate FavouriteCommand + +FavouriteCommand --> FavouriteCommandParser: f +deactivate FavouriteCommand + +FavouriteCommandParser --> RecipeBookParser: f +deactivate FavouriteCommandParser + +RecipeBookParser --> LogicManager: f +deactivate RecipeBookParser +destroy FavouriteCommandParser + +LogicManager -> FavouriteCommand: execute() +activate FavouriteCommand + +FavouriteCommand -> Model: setRecipe() +activate Model +Model --> FavouriteCommand +deactivate Model + +FavouriteCommand -> Model: updateFilteredPlannedList() +activate Model +Model --> FavouriteCommand +deactivate Model + +FavouriteCommand -> Model: commitBook() +activate Model +Model --> FavouriteCommand +deactivate Model + +create CommandResult +FavouriteCommand -> CommandResult +activate CommandResult + +CommandResult --> FavouriteCommand: result +deactivate CommandResult + +FavouriteCommand --> LogicManager: result +deactivate FavouriteCommand + +<-- LogicManager: result +deactivate LogicManager + +@enduml diff --git a/docs/diagrams/LogicClassDiagram.puml b/docs/diagrams/LogicClassDiagram.puml index 016ef33e2e2..cf23a298811 100644 --- a/docs/diagrams/LogicClassDiagram.puml +++ b/docs/diagrams/LogicClassDiagram.puml @@ -8,7 +8,7 @@ package Logic { package Parser { Interface Parser <> -Class AddressBookParser +Class RecipeBookParser Class XYZCommandParser Class CliSyntax Class ParserUtil @@ -35,8 +35,8 @@ Class HiddenOutside #FFFFFF HiddenOutside ..> Logic LogicManager .up.|> Logic -LogicManager -->"1" AddressBookParser -AddressBookParser .left.> XYZCommandParser: creates > +LogicManager -->"1" RecipeBookParser +RecipeBookParser .left.> XYZCommandParser: creates > XYZCommandParser ..> XYZCommand : creates > XYZCommandParser ..|> Parser diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml index e85a00d4107..4c86ca55889 100644 --- a/docs/diagrams/ModelClassDiagram.puml +++ b/docs/diagrams/ModelClassDiagram.puml @@ -1,56 +1,55 @@ @startuml !include style.puml + skinparam arrowThickness 1.1 skinparam arrowColor MODEL_COLOR skinparam classBackgroundColor MODEL_COLOR +Class HiddenOutside #FFFFFF + Package Model <>{ -Interface ReadOnlyAddressBook <> + Interface Model <> Interface ObservableList <> -Class AddressBook -Class ReadOnlyAddressBook +Interface ReadOnlyRecipeBook <> +Interface ReadOnlyUserPrefs <> +Interface ReadOnlyPlannedBook <> +Interface ReadOnlyCookedRecordBook <> +Interface ReadOnlyQuoteBook <> + +Class RecipeBook +Class ReadOnlyRecipeBook +Class PlannedBook +Class ReadOnlyPlannedBook +Class CookedRecordBook +Class ReadOnlyCookedRecordBook +Class QuoteBook +Class ReadOnlyQuoteBook Class Model Class ModelManager +Class MultipleBookStateManager Class UserPrefs Class ReadOnlyUserPrefs -Package Person { -Class Person -Class Address -Class Email -Class Name -Class Phone -Class UniquePersonList -} +HiddenOutside ...> Model -Package Tag { -Class Tag -} -} - -Class HiddenOutside #FFFFFF -HiddenOutside ..> Model - -AddressBook .up.|> ReadOnlyAddressBook +RecipeBook .up.|> ReadOnlyRecipeBook +PlannedBook .up.|> ReadOnlyPlannedBook +CookedRecordBook .up.|> ReadOnlyCookedRecordBook +QuoteBook .up.|> ReadOnlyQuoteBook ModelManager .up.|> Model Model .right.> ObservableList -ModelManager o--> "1" AddressBook -ModelManager o-left-> "1" UserPrefs +ModelManager o-- "1" UserPrefs +ModelManager o-- "1" CookedRecordBook +ModelManager o-- "1" RecipeBook +ModelManager o-- " 1" QuoteBook +ModelManager o-- "1" PlannedBook +ModelManager o-- "1" MultipleBookStateManager UserPrefs .up.|> ReadOnlyUserPrefs -AddressBook *--> "1" UniquePersonList -UniquePersonList o--> "*" Person -Person *--> Name -Person *--> Phone -Person *--> Email -Person *--> Address -Person *--> "*" Tag - -Name -[hidden]right-> Phone -Phone -[hidden]right-> Address -Address -[hidden]right-> Email +CookedRecordBook -[hidden]right-> RecipeBook +RecipeBook -[hidden]right-> QuoteBook +QuoteBook -[hidden]right-> PlannedBook -ModelManager -->"1" Person : filtered list @enduml diff --git a/docs/diagrams/ModelPlanClassDiagram.puml b/docs/diagrams/ModelPlanClassDiagram.puml new file mode 100644 index 00000000000..d43c62b855b --- /dev/null +++ b/docs/diagrams/ModelPlanClassDiagram.puml @@ -0,0 +1,43 @@ +@startuml +!include style.puml + +skinparam arrowThickness 1.1 +skinparam arrowColor MODEL_COLOR +skinparam classBackgroundColor MODEL_COLOR + +Class HiddenOutside #FFFFFF + +Package Model <>{ + +Interface Model <> +Class Model +Class ModelManager +class PlannedBook + +Package Plan { + class UniquePlannedList + class Plan + class PlannedRecipeMap +} +class Date + +Package Recipe { + + class Recipe + class Hidden #FFFFFF +} +HiddenOutside ...> Model +ModelManager o-- "1" PlannedBook +ModelManager .up.|> Model +ModelManager --> "1" Plan : filtered list + +Recipe -up[hidden]- Hidden +PlannedBook *-down-" 1" UniquePlannedList +PlannedBook *-down-"1" PlannedRecipeMap +UniquePlannedList o-- "*" Plan +PlannedRecipeMap o-- "*" Plan +PlannedRecipeMap o-- "*" Recipe +Plan o-- "1" Recipe +Plan *-- "1" Date + +@enduml diff --git a/docs/diagrams/ModelQuoteClassDiagram.puml b/docs/diagrams/ModelQuoteClassDiagram.puml new file mode 100644 index 00000000000..e902ad43a28 --- /dev/null +++ b/docs/diagrams/ModelQuoteClassDiagram.puml @@ -0,0 +1,32 @@ +@startuml +!include style.puml + +skinparam arrowThickness 1.1 +skinparam arrowColor MODEL_COLOR +skinparam classBackgroundColor MODEL_COLOR + + +Class HiddenOutside #FFFFFF + +Package Model <>{ + +Interface Model <> +Class Model +Class ModelManager +class QuoteBook + +Package Quote { + class UniqueQuoteList + class Quote + class Content +} +HiddenOutside ...> Model +ModelManager o-- "1" QuoteBook +ModelManager .up.|> Model +ModelManager --> "1" Quote : filtered list + +QuoteBook *-down-"1" UniqueQuoteList +UniqueQuoteList o-- "*" Quote +Quote o-- "1" Content + +@enduml diff --git a/docs/diagrams/ModelRecipeClassDiagram.puml b/docs/diagrams/ModelRecipeClassDiagram.puml new file mode 100644 index 00000000000..ed40ec48453 --- /dev/null +++ b/docs/diagrams/ModelRecipeClassDiagram.puml @@ -0,0 +1,72 @@ +@startuml +!include style.puml + +skinparam arrowThickness 1.1 +skinparam arrowColor MODEL_COLOR +skinparam classBackgroundColor MODEL_COLOR + +Class HiddenOutside #FFFFFF + +Package Model <>{ + +Interface Model <> +Class Model +Class ModelManager + +Package Recipe { +Class Recipe +Class Name +Class Time +Class Step +Class UniqueRecipeList + +Package Ingredient <> { +Class "{abstract}\nIngredient" as Ingredient +Class Grain +Class Vegetable +Class Protein +Class Fruit +Class Other +Class Quantity +Enum Unit <> + +Class HiddenOne #FFFFFF +Class HiddenTwo #FFFFFF +Class HiddenThree #FFFFFF +Class HiddenFour #FFFFFF +} +} + +HiddenOutside ...> Model +ModelManager o-- "1" RecipeBook +ModelManager .up.|> Model +ModelManager --> "1" Recipe : filtered list + +RecipeBook *-- "1" UniqueRecipeList +UniqueRecipeList o-- " *" Recipe +Recipe *-- "1" Name +Recipe *-- "1" Time +Recipe *-- " *" Step +Recipe *-- "1..* " Ingredient + +HiddenOne -down- Grain +HiddenTwo -down- Vegetable +Ingredient <|-- Protein +HiddenThree -down- Fruit +HiddenFour -down- Other + +'HiddenOne -right- HiddenFour + +Grain -[hidden]right-> Vegetable +Vegetable -[hidden]right-> Protein +Protein -[hidden]right-> Fruit +Fruit -[hidden]right-> Other + +'will be formatting this outside PUML instead + +Ingredient *-right- "1" Quantity +Quantity -up-> "1" Unit +Name -[hidden]right-> Time +Time -[hidden]right-> Step + +@enduml diff --git a/docs/diagrams/ModelRecordClassDiagram.puml b/docs/diagrams/ModelRecordClassDiagram.puml new file mode 100644 index 00000000000..0e135cffce8 --- /dev/null +++ b/docs/diagrams/ModelRecordClassDiagram.puml @@ -0,0 +1,46 @@ +@startuml +!include style.puml + +skinparam arrowThickness 1.1 +skinparam arrowColor MODEL_COLOR +skinparam classBackgroundColor MODEL_COLOR +Class HiddenOutside #FFFFFF + +Package Model <>{ + +Interface Model <> +Class Model +Class ModelManager + +class CookedRecordBook +class Date + +Package Record { + class UniqueRecordList + class Record +} + +Package Recipe { + class Name +} + +Package Goal { + class Goal + class GoalCount +} + +HiddenOutside ...> Model +ModelManager o-- "1" CookedRecordBook +ModelManager .up.|> Model +ModelManager --> "1" Record : filteredRecordList + +CookedRecordBook *-down-"1" UniqueRecordList +UniqueRecordList o-- "*" Record +Record o-- "1" Name +Record *-- "1" Date +Record o-up- "0..4" Goal + +UniqueRecordList o-- "4" GoalCount +ModelManager --> "1" GoalCount : filteredGoalsTally + +@enduml diff --git a/docs/diagrams/MultipleBookStateManagerClassDiagram.puml b/docs/diagrams/MultipleBookStateManagerClassDiagram.puml new file mode 100644 index 00000000000..925a5ade646 --- /dev/null +++ b/docs/diagrams/MultipleBookStateManagerClassDiagram.puml @@ -0,0 +1,14 @@ +@startuml +!include style.puml +skinparam arrowThickness 1.1 +skinparam arrowColor MODEL_COLOR +skinparam classBackgroundColor MODEL_COLOR + +MultipleBookStateManager o-down-> "1..*" ReadOnlyRecipeBook +MultipleBookStateManager o-down-> "1..*" ReadOnlyPlannedBook +MultipleBookStateManager o-down-> " 1..*" ReadOnlyCookedRecordBook +MultipleBookStateManager o-down-> " 1..*" ReadOnlyQuoteBook +MultipleBookStateManager o-up-> "*" CommandType +MultipleBookStateManager o-up-> "*" Tab + +@enduml diff --git a/docs/diagrams/PlanningSequenceDiagram.puml b/docs/diagrams/PlanningSequenceDiagram.puml new file mode 100644 index 00000000000..f0bc0be4ecf --- /dev/null +++ b/docs/diagrams/PlanningSequenceDiagram.puml @@ -0,0 +1,128 @@ +@startuml +!include style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":RecipeBookParser" as RecipeBookParser LOGIC_COLOR +participant ":PlanCommandParser" as PlanCommandParser LOGIC_COLOR +participant ":ParserUtil" as ParserUtil LOGIC_COLOR +participant "planCom:PlanCommand" as PlanCommand LOGIC_COLOR +participant "cr:CommandResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Model" as Model MODEL_COLOR +participant "plan:Plan" as Plan MODEL_COLOR +participant ":PlannedBook" as PlannedBook MODEL_COLOR +participant ":UniquePlannedList" as UniquePlannedList MODEL_COLOR +participant ":PlannedRecipeMap" as PlannedRecipeMap MODEL_COLOR +end box + +[-> LogicManager : execute("plan 2 3 d/2020-05-27") +activate LogicManager + +LogicManager -> RecipeBookParser : parseCommand("plan 2 3 d/2020-05-27") +activate RecipeBookParser + +create PlanCommandParser +RecipeBookParser -> PlanCommandParser +activate PlanCommandParser + +PlanCommandParser --> RecipeBookParser +deactivate PlanCommandParser + +RecipeBookParser -> PlanCommandParser : parse("2 3 d/2020-05-27") +activate PlanCommandParser + +PlanCommandParser -> ParserUtil : parseDate("2020-05-27") +activate ParserUtil + +ParserUtil --> PlanCommandParser : date +deactivate ParserUtil + +PlanCommandParser -> ParserUtil : parseMultipleIndex("2 3") +activate ParserUtil + +ParserUtil --> PlanCommandParser : indexes +deactivate ParserUtil + +create PlanCommand +PlanCommandParser -> PlanCommand +activate PlanCommand + +PlanCommand --> PlanCommandParser : planCom +deactivate PlanCommand + +PlanCommandParser --> RecipeBookParser : planCom +deactivate PlanCommandParser +'Hidden arrow to position the destroy marker below the end of the activation bar. +PlanCommandParser -[hidden]-> RecipeBookParser +destroy PlanCommandParser + +RecipeBookParser --> LogicManager : planCom +deactivate RecipeBookParser + +LogicManager -> PlanCommand : execute() +activate PlanCommand + +PlanCommand -> Model : getFilteredRecipeList() +activate Model + +Model --> PlanCommand : recipeList +deactivate Model + +loop for all indexes + create Plan + PlanCommand -> Plan + activate Plan + + Plan --> PlanCommand : plan + deactivate Plan + + PlanCommand -> Model : addPlan(recipe, plan) + activate Model + + Model -> PlannedBook : addPlan(recipe, plan) + activate PlannedBook + + PlannedBook -> UniquePlannedList : addPlan(plan) + activate UniquePlannedList + + UniquePlannedList --> PlannedBook + deactivate UniquePlannedList + + PlannedBook -> PlannedRecipeMap : addPlan(recipe, plan) + activate PlannedRecipeMap + + PlannedRecipeMap --> PlannedBook + deactivate PlannedRecipeMap + + PlannedBook --> Model + deactivate PlannedBook + + Model --> PlanCommand + deactivate Model + +end loop + +PlanCommand -> Model : commitBook() +activate Model + +Model --> PlanCommand +deactivate Model + +create CommandResult +PlanCommand -> CommandResult +activate CommandResult +CommandResult --> PlanCommand : cr +deactivate CommandResult + +PlanCommand --> LogicManager : cr +deactivate PlanCommand + + + +[<--LogicManager +deactivate LogicManager + +@enduml diff --git a/docs/diagrams/QuoteActivityDiagram.puml b/docs/diagrams/QuoteActivityDiagram.puml new file mode 100644 index 00000000000..81564669a85 --- /dev/null +++ b/docs/diagrams/QuoteActivityDiagram.puml @@ -0,0 +1,16 @@ +@startuml +start +:User enters quote command; + +if () then ([user enters valid string]) + :Enters new Quote; + if () then ([quote is unique]) + :Adds new quote; + else ([else]) + :Display duplicate quote error message; + endif +else ([else]) + :Display invalid field error message; + endif +stop +@enduml diff --git a/docs/diagrams/QuoteSequenceDiagram.puml b/docs/diagrams/QuoteSequenceDiagram.puml new file mode 100644 index 00000000000..999488941ea --- /dev/null +++ b/docs/diagrams/QuoteSequenceDiagram.puml @@ -0,0 +1,69 @@ +@startuml +!include style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":RecipeBookParser" as RecipeBookParser LOGIC_COLOR +participant ":QuoteCommandParser" as QuoteCommandParser LOGIC_COLOR +participant "q:QuoteCommand" as QuoteCommand LOGIC_COLOR +participant ":CommandResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Model" as Model MODEL_COLOR +end box + +[-> LogicManager : execute("quote q") +activate LogicManager + +LogicManager -> RecipeBookParser : parseCommand("quote q") +activate RecipeBookParser + +create QuoteCommandParser +RecipeBookParser -> QuoteCommandParser +activate QuoteCommandParser + +QuoteCommandParser --> RecipeBookParser +deactivate QuoteCommandParser + +RecipeBookParser -> QuoteCommandParser : parse("q") +activate QuoteCommandParser + +create QuoteCommand +QuoteCommandParser -> QuoteCommand +activate QuoteCommand + +QuoteCommand --> QuoteCommandParser : q +deactivate QuoteCommand + +QuoteCommandParser --> RecipeBookParser : q +deactivate QuoteCommandParser +'Hidden arrow to position the destroy marker below the end of the activation bar. +QuoteCommandParser -[hidden]-> RecipeBookParser +destroy QuoteCommandParser + +RecipeBookParser --> LogicManager : d +deactivate RecipeBookParser + +LogicManager -> QuoteCommand : execute() +activate QuoteCommand + +QuoteCommand -> Model : addQuote(q) +activate Model + +Model --> QuoteCommand +deactivate Model + +create CommandResult +QuoteCommand -> CommandResult +activate CommandResult + +CommandResult --> QuoteCommand +deactivate CommandResult + +QuoteCommand --> LogicManager : result +deactivate QuoteCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/RecipeCustomisationCommandsActivityDiagram.puml b/docs/diagrams/RecipeCustomisationCommandsActivityDiagram.puml new file mode 100644 index 00000000000..3f14c3e7626 --- /dev/null +++ b/docs/diagrams/RecipeCustomisationCommandsActivityDiagram.puml @@ -0,0 +1,40 @@ +@startuml +start +:User executes recipe customisation command; +:EditRecipeDescriptor (ERD) is populated with parsed user input; +'Since the beta syntax does not support placing the condition outside the +'diamond we place it as the true branch instead. + +if () then ( [addingredient / addstep]) + : Add existing + ingredients / steps + to the ERD; +else () + if () then ([editingredient / editstep]) + if () then ( [ingredients / step + exists in recipe]) + : Add unchanged + ingredients / steps + to the ERD; + else ([else]) + :Throws Exception; + stop + endif + else ([deleteingredient / deletestep]) + if () then ( [ingredient / step + exists in recipe]) + :ERD re-populated with existing + ingredients / steps less those + specified by the user; + else ([else]) + :Throws Exception; + stop + endif + endif +endif + +:Create edited recipe; +:Change old version of the recipe in Model to the newly edited version; +:Commit book to MultipleBookStateManager; +stop +@enduml diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml index 6adb2e156bf..b5cca3465c0 100644 --- a/docs/diagrams/StorageClassDiagram.puml +++ b/docs/diagrams/StorageClassDiagram.puml @@ -6,19 +6,38 @@ skinparam classBackgroundColor STORAGE_COLOR Interface Storage <> Interface UserPrefsStorage <> -Interface AddressBookStorage <> +Interface RecipeBookStorage <> +Interface PlannedBookStorage <> +Interface CookedRecordBookStorage <> +Interface QuoteBookStorage <> Class StorageManager Class JsonUserPrefsStorage -Class JsonAddressBookStorage +Class JsonRecipeBookStorage StorageManager .left.|> Storage -StorageManager o-right-> UserPrefsStorage -StorageManager o--> AddressBookStorage +StorageManager o-right-> "1" UserPrefsStorage +StorageManager o--> "1" RecipeBookStorage +StorageManager o--> "1" PlannedBookStorage +StorageManager o--> "1" CookedRecordBookStorage +StorageManager o--> "1" QuoteBookStorage JsonUserPrefsStorage .left.|> UserPrefsStorage -JsonAddressBookStorage .left.|> AddressBookStorage -JsonAddressBookStorage .down.> JsonSerializableAddressBookStorage -JsonSerializableAddressBookStorage .right.> JsonSerializablePerson -JsonSerializablePerson .right.> JsonAdaptedTag +JsonRecipeBookStorage .up.|> RecipeBookStorage +JsonRecipeBookStorage .down.> JsonSerializableRecipeBookStorage +JsonSerializableRecipeBookStorage .down.> JsonSerializableRecipe + +JsonPlannedBookStorage .up.|> PlannedBookStorage +JsonPlannedBookStorage .down.> JsonSerializablePlannedBookStorage +JsonSerializablePlannedBookStorage .down.> JsonSerializablePlan + +JsonCookedRecordBookStorage .up.|> CookedRecordBookStorage +JsonCookedRecordBookStorage .down.> JsonSerializableCookedRecordBookStorage +JsonSerializableCookedRecordBookStorage .down.> JsonSerializableRecord + +JsonQuoteBookStorage .up.|> QuoteBookStorage +JsonQuoteBookStorage .down.> JsonSerializableQuoteBookStorage +JsonSerializableQuoteBookStorage .down.> JsonSerializableQuote +JsonSerializableQuote .down.> JsonAdaptedQuote + @enduml diff --git a/docs/diagrams/StreakActivityDiagram.puml b/docs/diagrams/StreakActivityDiagram.puml new file mode 100644 index 00000000000..918c7388f7b --- /dev/null +++ b/docs/diagrams/StreakActivityDiagram.puml @@ -0,0 +1,16 @@ +@startuml +start +:User enters valid cooked command; +:Recalculates streak; + +if () then ([Increment in streak]) + :Updates current streak; + if () then ([Streak high score changes]) + :Updates Streak high score; + else ([else]) + endif +else ([else]) + endif +:Updates Streak in achievement tab; +stop +@enduml diff --git a/docs/diagrams/SwitchActivityDiagram.puml b/docs/diagrams/SwitchActivityDiagram.puml new file mode 100644 index 00000000000..6d9397d94e9 --- /dev/null +++ b/docs/diagrams/SwitchActivityDiagram.puml @@ -0,0 +1,37 @@ +@startuml +start +:User executes Switch command; +:SwitchCommandParser parses user input; +if() then ([isEmpty]) +:Throws Exception; +stop + +else([else]) + if() then ([recipes]) + :Returns SwitchCommand(Tab.RECIPES); + else([else]) + if() then ([planning]) + :Returns SwitchCommand(Tab.PLANNING); + else([else]) + if() then ([goals]) + :Returns SwitchCommand(Tab.GOALS); + else([else]) + if() then ([achievements]) + :Returns SwitchCommand(Tab.ACHIEVEMENT); + else([else]) + :Throws Exception; + stop + endif + endif + endif + endif +endif +:LogicManager executes SwitchCommand; +:Returns CommandResult; +if() then([isSwitchTab]) +:handleSwitchTab; +else([else]) +endif +stop + +@enduml diff --git a/docs/diagrams/UiClassDiagram.puml b/docs/diagrams/UiClassDiagram.puml index 92746f9fcf7..c0be3b69cf7 100644 --- a/docs/diagrams/UiClassDiagram.puml +++ b/docs/diagrams/UiClassDiagram.puml @@ -5,17 +5,26 @@ skinparam arrowColor UI_COLOR_T4 skinparam classBackgroundColor UI_COLOR package UI <>{ -Interface Ui <> -Class "{abstract}\nUiPart" as UiPart -Class UiManager -Class MainWindow -Class HelpWindow -Class ResultDisplay -Class PersonListPanel -Class PersonCard -Class StatusBarFooter -Class CommandBox -} + Interface Ui <> + Class "{abstract}\nUiPart" as UiPart + Class UiManager + Class MainWindow + Class HelpWindow + Class GroceryListWindow + Class ResultDisplay + Class StatusBarFooter + Class CommandBox + Class MainTabPanel + package { + Class RecipeListPanel + Class RecipeCard + Class PlanningListPanel + Class PlanningCard + Class CookedListPanel + Class CookedCard + Class AchievementCard + } + } package Model <> { Class HiddenModel #FFFFFF @@ -29,32 +38,50 @@ Class HiddenOutside #FFFFFF HiddenOutside ..> Ui UiManager .left.|> Ui -UiManager -down-> MainWindow +UiManager -down- MainWindow MainWindow --> HelpWindow -MainWindow *-down-> CommandBox -MainWindow *-down-> ResultDisplay -MainWindow *-down-> PersonListPanel -MainWindow *-down-> StatusBarFooter +MainWindow --> GroceryListWindow +MainWindow *-down- CommandBox +MainWindow *-down- ResultDisplay +MainWindow *-down- StatusBarFooter +MainWindow *-down- MainTabPanel + +MainTabPanel *-down- RecipeListPanel +RecipeListPanel -down- RecipeCard +MainTabPanel *-down- PlanningListPanel +PlanningListPanel -down- PlanningCard +MainTabPanel *-down- CookedListPanel +CookedListPanel -down- CookedCard +MainTabPanel *-down- AchievementCard -PersonListPanel -down-> PersonCard MainWindow -left-|> UiPart ResultDisplay --|> UiPart CommandBox --|> UiPart -PersonListPanel --|> UiPart -PersonCard --|> UiPart +GroceryListWindow --|> UiPart +RecipeListPanel --|> UiPart +PlanningListPanel --|> UiPart +CookedListPanel --|> UiPart +AchievementCard --|> UiPart +RecipeCard --|> UiPart +PlanningCard --|> UiPart +CookedCard --|> UiPart StatusBarFooter --|> UiPart -HelpWindow -down-|> UiPart +HelpWindow --|> UiPart -PersonCard ..> Model +RecipeCard .down.> Model +PlanningCard .down.> Model +CookedCard .down.> Model +AchievementCard .down.> Model UiManager -right-> Logic MainWindow -left-> Logic -PersonListPanel -[hidden]left- HelpWindow +RecipeListPanel -[hidden]left- HelpWindow HelpWindow -[hidden]left- CommandBox CommandBox -[hidden]left- ResultDisplay ResultDisplay -[hidden]left- StatusBarFooter +GroceryListWindow -[hidden]left- StatusBarFooter MainWindow -[hidden]-|> UiPart @enduml diff --git a/docs/diagrams/UndoRedoState0.puml b/docs/diagrams/UndoRedoState0.puml index 96e30744d24..f8c1d1033e4 100644 --- a/docs/diagrams/UndoRedoState0.puml +++ b/docs/diagrams/UndoRedoState0.puml @@ -3,12 +3,12 @@ skinparam ClassFontColor #000000 skinparam ClassBorderColor #000000 -title Initial state +title Initial state of ArrayList \n in MultipleBookStateManager -package States { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" +package ArrayList { + class State1 as "__rb0:RecipeBook__" + class State2 as "__rb1:RecipeBook__" + class State3 as "__rb2:RecipeBook__" } State1 -[hidden]right-> State2 State2 -[hidden]right-> State3 diff --git a/docs/diagrams/UndoRedoState1.puml b/docs/diagrams/UndoRedoState1.puml index 01fcb9b2b96..de44c1b3b85 100644 --- a/docs/diagrams/UndoRedoState1.puml +++ b/docs/diagrams/UndoRedoState1.puml @@ -5,10 +5,10 @@ skinparam ClassBorderColor #000000 title After command "delete 5" -package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" +package ArrayList { + class State1 as "__rb0:RecipeBook__" + class State2 as "__rb1:RecipeBook__" + class State3 as "__rb2:RecipeBook__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoRedoState2.puml b/docs/diagrams/UndoRedoState2.puml index bccc230a5d1..0c1cf27ca1a 100644 --- a/docs/diagrams/UndoRedoState2.puml +++ b/docs/diagrams/UndoRedoState2.puml @@ -3,12 +3,12 @@ skinparam ClassFontColor #000000 skinparam ClassBorderColor #000000 -title After command "add n/David" +title After command "favourite 3" -package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" +package ArrayList { + class State1 as "__rb0:RecipeBook__" + class State2 as "__rb1:RecipeBook__" + class State3 as "__rb2:RecipeBook__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoRedoState3.puml b/docs/diagrams/UndoRedoState3.puml index ea29c9483e4..5d7d6a86cfb 100644 --- a/docs/diagrams/UndoRedoState3.puml +++ b/docs/diagrams/UndoRedoState3.puml @@ -5,10 +5,10 @@ skinparam ClassBorderColor #000000 title After command "undo" -package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" +package ArrayList { + class State1 as "__rb0:RecipeBook__" + class State2 as "__rb1:RecipeBook__" + class State3 as "__rb2:RecipeBook__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoRedoState4.puml b/docs/diagrams/UndoRedoState4.puml index 1b784cece80..557c1adee6c 100644 --- a/docs/diagrams/UndoRedoState4.puml +++ b/docs/diagrams/UndoRedoState4.puml @@ -5,10 +5,10 @@ skinparam ClassBorderColor #000000 title After command "list" -package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" +package ArrayList { + class State1 as "__rb0:RecipeBook__" + class State2 as "__rb1:RecipeBook__" + class State3 as "__rb2:RecipeBook__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoRedoState5.puml b/docs/diagrams/UndoRedoState5.puml index 88927be32bc..b3252b60e17 100644 --- a/docs/diagrams/UndoRedoState5.puml +++ b/docs/diagrams/UndoRedoState5.puml @@ -5,10 +5,10 @@ skinparam ClassBorderColor #000000 title After command "clear" -package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab3:AddressBook__" +package ArrayList { + class State1 as "__rb0:RecipeBook__" + class State2 as "__rb1:RecipeBook__" + class State3 as "__rb3:RecipeBook__" } State1 -[hidden]right-> State2 @@ -17,5 +17,5 @@ State2 -[hidden]right-> State3 class Pointer as "Current State" #FFFFF Pointer -up-> State3 -note right on link: State ab2 deleted. +note right on link: State rb2 deleted. @end diff --git a/docs/diagrams/tracing/LogicSequenceDiagram.puml b/docs/diagrams/tracing/LogicSequenceDiagram.puml index fdcbe1c0ccc..1c2a722fb74 100644 --- a/docs/diagrams/tracing/LogicSequenceDiagram.puml +++ b/docs/diagrams/tracing/LogicSequenceDiagram.puml @@ -2,7 +2,7 @@ !include ../style.puml Participant ":LogicManager" as logic LOGIC_COLOR -Participant ":AddressBookParser" as abp LOGIC_COLOR +Participant ":RecipeBookParser" as abp LOGIC_COLOR Participant ":EditCommandParser" as ecp LOGIC_COLOR Participant "command:EditCommand" as ec LOGIC_COLOR @@ -13,7 +13,7 @@ create ecp abp -> ecp abp -> ecp ++: parse(arguments) create ec -ecp -> ec ++: index, editPersonDescriptor +ecp -> ec ++: index, editRecipeDescriptor ec --> ecp -- ecp --> abp --: command abp --> logic --: command diff --git a/docs/images/AddExample.png b/docs/images/AddExample.png new file mode 100644 index 00000000000..e20a4de8e2f Binary files /dev/null and b/docs/images/AddExample.png differ diff --git a/docs/images/AddRefSequenceDiagram.png b/docs/images/AddRefSequenceDiagram.png new file mode 100644 index 00000000000..bdeea547de8 Binary files /dev/null and b/docs/images/AddRefSequenceDiagram.png differ diff --git a/docs/images/AddSequenceDiagram.png b/docs/images/AddSequenceDiagram.png new file mode 100644 index 00000000000..74de360ecd5 Binary files /dev/null and b/docs/images/AddSequenceDiagram.png differ diff --git a/docs/images/AdvancedFilterSequenceDiagram.png b/docs/images/AdvancedFilterSequenceDiagram.png new file mode 100644 index 00000000000..f81adb6319f Binary files /dev/null and b/docs/images/AdvancedFilterSequenceDiagram.png differ diff --git a/docs/images/AnnotatedUserInterface.png b/docs/images/AnnotatedUserInterface.png new file mode 100644 index 00000000000..fc6142e2fb1 Binary files /dev/null and b/docs/images/AnnotatedUserInterface.png differ diff --git a/docs/images/ArchitectureSequenceDiagram.png b/docs/images/ArchitectureSequenceDiagram.png index aa198138f8f..b3760c9fad6 100644 Binary files a/docs/images/ArchitectureSequenceDiagram.png and b/docs/images/ArchitectureSequenceDiagram.png differ diff --git a/docs/images/CommitActivityDiagram.png b/docs/images/CommitActivityDiagram.png index 4de4fa4bf2b..a52e7249811 100644 Binary files a/docs/images/CommitActivityDiagram.png and b/docs/images/CommitActivityDiagram.png differ diff --git a/docs/images/CookedActivityDiagram.png b/docs/images/CookedActivityDiagram.png new file mode 100644 index 00000000000..d1c0396018a Binary files /dev/null and b/docs/images/CookedActivityDiagram.png differ diff --git a/docs/images/DeleteSequenceDiagram.png b/docs/images/DeleteSequenceDiagram.png index fa327b39618..dc252fce63c 100644 Binary files a/docs/images/DeleteSequenceDiagram.png and b/docs/images/DeleteSequenceDiagram.png differ diff --git a/docs/images/EditActivityDiagram.png b/docs/images/EditActivityDiagram.png new file mode 100644 index 00000000000..85b666ef1ba Binary files /dev/null and b/docs/images/EditActivityDiagram.png differ diff --git a/docs/images/EditModelSequenceDiagram.png b/docs/images/EditModelSequenceDiagram.png new file mode 100644 index 00000000000..7bda79b34bf Binary files /dev/null and b/docs/images/EditModelSequenceDiagram.png differ diff --git a/docs/images/EditSequenceDiagram.png b/docs/images/EditSequenceDiagram.png new file mode 100644 index 00000000000..712fcb0b70f Binary files /dev/null and b/docs/images/EditSequenceDiagram.png differ diff --git a/docs/images/FavouriteCommandSequenceDiagram.png b/docs/images/FavouriteCommandSequenceDiagram.png new file mode 100644 index 00000000000..7762250a12a Binary files /dev/null and b/docs/images/FavouriteCommandSequenceDiagram.png differ diff --git a/docs/images/LogicClassDiagram.png b/docs/images/LogicClassDiagram.png index b9e853cef12..4e2f17f02eb 100644 Binary files a/docs/images/LogicClassDiagram.png and b/docs/images/LogicClassDiagram.png differ diff --git a/docs/images/LogicSequenceDiagram.png b/docs/images/LogicSequenceDiagram.png new file mode 100644 index 00000000000..9811ef42cf9 Binary files /dev/null and b/docs/images/LogicSequenceDiagram.png differ diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png index 280064118cf..93e473cf7fb 100644 Binary files a/docs/images/ModelClassDiagram.png and b/docs/images/ModelClassDiagram.png differ diff --git a/docs/images/ModelPlanClassDiagram.png b/docs/images/ModelPlanClassDiagram.png new file mode 100644 index 00000000000..bb028571e82 Binary files /dev/null and b/docs/images/ModelPlanClassDiagram.png differ diff --git a/docs/images/ModelQuoteClassDiagram.png b/docs/images/ModelQuoteClassDiagram.png new file mode 100644 index 00000000000..0853f28a6bd Binary files /dev/null and b/docs/images/ModelQuoteClassDiagram.png differ diff --git a/docs/images/ModelRecipeClassDiagram.png b/docs/images/ModelRecipeClassDiagram.png new file mode 100644 index 00000000000..c2cbead90ce Binary files /dev/null and b/docs/images/ModelRecipeClassDiagram.png differ diff --git a/docs/images/ModelRecordClassDiagram.png b/docs/images/ModelRecordClassDiagram.png new file mode 100644 index 00000000000..d9bcb4fb675 Binary files /dev/null and b/docs/images/ModelRecordClassDiagram.png differ diff --git a/docs/images/MultipleBookStateManagerClassDiagram.png b/docs/images/MultipleBookStateManagerClassDiagram.png new file mode 100644 index 00000000000..2a65eaa6f4d Binary files /dev/null and b/docs/images/MultipleBookStateManagerClassDiagram.png differ diff --git a/docs/images/PlanTab.png b/docs/images/PlanTab.png new file mode 100644 index 00000000000..74d6d430a47 Binary files /dev/null and b/docs/images/PlanTab.png differ diff --git a/docs/images/PlanTab_Plan.png b/docs/images/PlanTab_Plan.png new file mode 100644 index 00000000000..d3956991d26 Binary files /dev/null and b/docs/images/PlanTab_Plan.png differ diff --git a/docs/images/PlanningSequenceDiagram.png b/docs/images/PlanningSequenceDiagram.png new file mode 100644 index 00000000000..1464a8dc1b0 Binary files /dev/null and b/docs/images/PlanningSequenceDiagram.png differ diff --git a/docs/images/QuoteActivityDiagram.PNG b/docs/images/QuoteActivityDiagram.PNG new file mode 100644 index 00000000000..257363b1796 Binary files /dev/null and b/docs/images/QuoteActivityDiagram.PNG differ diff --git a/docs/images/QuoteSequenceDiagram.PNG b/docs/images/QuoteSequenceDiagram.PNG new file mode 100644 index 00000000000..bbd64902b42 Binary files /dev/null and b/docs/images/QuoteSequenceDiagram.PNG differ diff --git a/docs/images/QuotesTab.PNG b/docs/images/QuotesTab.PNG new file mode 100644 index 00000000000..79075ecc77f Binary files /dev/null and b/docs/images/QuotesTab.PNG differ diff --git a/docs/images/RecipeCustomisationCommandsActivityDiagram.png b/docs/images/RecipeCustomisationCommandsActivityDiagram.png new file mode 100644 index 00000000000..b5fc9e3977f Binary files /dev/null and b/docs/images/RecipeCustomisationCommandsActivityDiagram.png differ diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png index d87c1216820..382bd22b87f 100644 Binary files a/docs/images/StorageClassDiagram.png and b/docs/images/StorageClassDiagram.png differ diff --git a/docs/images/StreakActivityDiagram.PNG b/docs/images/StreakActivityDiagram.PNG new file mode 100644 index 00000000000..e0181685f2a Binary files /dev/null and b/docs/images/StreakActivityDiagram.PNG differ diff --git a/docs/images/SwitchActivityDiagram.png b/docs/images/SwitchActivityDiagram.png new file mode 100644 index 00000000000..4bed210c0ab Binary files /dev/null and b/docs/images/SwitchActivityDiagram.png differ diff --git a/docs/images/Ui.png b/docs/images/Ui.png index 5bd77847aa2..33744fdc289 100644 Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ diff --git a/docs/images/UiClassDiagram.png b/docs/images/UiClassDiagram.png index 7b4b3dbea45..c1255c20855 100644 Binary files a/docs/images/UiClassDiagram.png and b/docs/images/UiClassDiagram.png differ diff --git a/docs/images/UndoRedoState0.png b/docs/images/UndoRedoState0.png index 8f7538cd884..66500194b93 100644 Binary files a/docs/images/UndoRedoState0.png and b/docs/images/UndoRedoState0.png differ diff --git a/docs/images/UndoRedoState1.png b/docs/images/UndoRedoState1.png index df9908d0948..40bb07d79df 100644 Binary files a/docs/images/UndoRedoState1.png and b/docs/images/UndoRedoState1.png differ diff --git a/docs/images/UndoRedoState2.png b/docs/images/UndoRedoState2.png index 36519c1015b..96dc701a6e7 100644 Binary files a/docs/images/UndoRedoState2.png and b/docs/images/UndoRedoState2.png differ diff --git a/docs/images/UndoRedoState3.png b/docs/images/UndoRedoState3.png index 19959d01712..e9922bb950f 100644 Binary files a/docs/images/UndoRedoState3.png and b/docs/images/UndoRedoState3.png differ diff --git a/docs/images/UndoRedoState4.png b/docs/images/UndoRedoState4.png index 4c623e4f2c5..2eae0ffae8c 100644 Binary files a/docs/images/UndoRedoState4.png and b/docs/images/UndoRedoState4.png differ diff --git a/docs/images/UndoRedoState5.png b/docs/images/UndoRedoState5.png index 84ad2afa6bd..8d3ce344f23 100644 Binary files a/docs/images/UndoRedoState5.png and b/docs/images/UndoRedoState5.png differ diff --git a/docs/images/beatricetay.png b/docs/images/beatricetay.png new file mode 100644 index 00000000000..8c32b2a3d26 Binary files /dev/null and b/docs/images/beatricetay.png differ diff --git a/docs/images/damithc.jpg b/docs/images/damithc.jpg deleted file mode 100644 index 12754388389..00000000000 Binary files a/docs/images/damithc.jpg and /dev/null differ diff --git a/docs/images/goalsTab.png b/docs/images/goalsTab.png new file mode 100644 index 00000000000..34aaae18564 Binary files /dev/null and b/docs/images/goalsTab.png differ diff --git a/docs/images/lejolly.jpg b/docs/images/lejolly.jpg deleted file mode 100644 index 2d1d94e0cf5..00000000000 Binary files a/docs/images/lejolly.jpg and /dev/null differ diff --git a/docs/images/m133225.jpg b/docs/images/m133225.jpg deleted file mode 100644 index fd14fb94593..00000000000 Binary files a/docs/images/m133225.jpg and /dev/null differ diff --git a/docs/images/pekchinsiongbrian.png b/docs/images/pekchinsiongbrian.png new file mode 100644 index 00000000000..dc62bc62322 Binary files /dev/null and b/docs/images/pekchinsiongbrian.png differ diff --git a/docs/images/placeholder.png b/docs/images/placeholder.png new file mode 100644 index 00000000000..562891c12b4 Binary files /dev/null and b/docs/images/placeholder.png differ diff --git a/docs/images/tharshita.png b/docs/images/tharshita.png new file mode 100644 index 00000000000..515ca0b07e0 Binary files /dev/null and b/docs/images/tharshita.png differ diff --git a/docs/images/yijinl.jpg b/docs/images/yijinl.jpg deleted file mode 100644 index adbf62ad940..00000000000 Binary files a/docs/images/yijinl.jpg and /dev/null differ diff --git a/docs/images/yl_coder.jpg b/docs/images/yl_coder.jpg deleted file mode 100644 index 17b48a73227..00000000000 Binary files a/docs/images/yl_coder.jpg and /dev/null differ diff --git a/docs/images/yuuton9.png b/docs/images/yuuton9.png new file mode 100644 index 00000000000..0c2a1bdba35 Binary files /dev/null and b/docs/images/yuuton9.png differ diff --git a/docs/team/beatricetay.adoc b/docs/team/beatricetay.adoc new file mode 100644 index 00000000000..d33a1afe671 --- /dev/null +++ b/docs/team/beatricetay.adoc @@ -0,0 +1,87 @@ += Beatrice Tay - Project Portfolio +:site-section: AboutUs +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: HealthyBaby + +--- + +== Overview + +*HealthyBaby* (HYBB) is a desktop application targeted towards university students that provides users with a database of quick, easy, and healthy recipes. +HYBB helps alleviate the challenges faced while maintaining healthy eating habits, easing the transition from eating +out everyday to cooking healthy meals regularly. + +The user interacts with HYBB using a Command Line Interface, and it has a Graphical User Interface created with JavaFX. + +It is written in Java, and has about 18 kLoC. + +== Summary of contributions + +* *Major enhancement*: Added the *Planning feature* +** What it does: Allows the user to plan and remove the plans for a recipe on a certain date. The user is also able to +obtain all ingredients required for the planned recipes on a simple grocery list. +** Justification: Assists users in making healthy cooking easier as the user +can plan for recipes containing Goals for the nutritional food group that they want to focus on. +Users can save money and reduce food wastage by planning for recipes with similar ingredients and purchasing only +items that they need using the grocery list command. +** Highlights: This enhancement is affected by recipes being modified, as the plans of the modified recipe needs to be +updated as well. Ensuring that each plan is deleted or updated after each modification was challenging as HYBB supports +many recipe customisation methods (9 in total). + +* *Minor enhancement*: Added Ingredient and Quantity classes to allow HYBB to estimate the portion of each food +group in the recipes. + +* *Code contributed*: + https://nus-cs2103-ay1920s2.github.io/tp-dashboard/#search=beatricetay&sort=groupTitle&sortWithin=title&since=2020-02-14&timeframe=commit&mergegroup=false&groupSelect=groupByRepos&breakdown=false[RepoSense] + +* *Other contributions*: + +** Project management: +*** Managed releases `v1.2.1` - `v1.3.1` (3 releases) on GitHub + +** Enhancements to existing features: +*** Did cosmetic tweaks to the GUI: (Pull requests +https://github.com/AY1920S2-CS2103T-T10-1/main/pull/192[#192], +https://github.com/AY1920S2-CS2103T-T10-1/main/pull/195[#195]) + +** Documentation: +*** Did cosmetic tweaks to existing contents of the User Guide: https://github.com[#14] + +** Community: +*** PRs reviewed (with non-trivial review comments): +https://github.com/nus-cs2103-AY1920S2/addressbook-level3/pull/3[#3], +https://github.com/nus-cs2103-AY1920S2/addressbook-level3/pull/26[#26], +https://github.com/nus-cs2103-AY1920S2/addressbook-level3/pull/33[#33] + +*** Reported bugs and suggestions for other teams in the class (example: +https://github.com/beatricetay/ped/issues[1]) + +** Tools: +*** Integrated AppVeyor and CoverAll to the repo (https://github.com/AY1920S2-CS2103T-T10-1/main/pull/23[#23]) + +== Contributions to the User Guide + + +|=== +|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._ +|=== + +include::../UserGuide.adoc[tag=GUI] + + +include::../UserGuide.adoc[tag=planning] + +== Contributions to the Developer Guide + +|=== +|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._ +|=== + +include::../DeveloperGuide.adoc[tag=editcommand] + +include::../DeveloperGuide.adoc[tag=planning] + +--- + diff --git a/docs/team/johndoe.adoc b/docs/team/johndoe.adoc deleted file mode 100644 index f39e76e49b2..00000000000 --- a/docs/team/johndoe.adoc +++ /dev/null @@ -1,72 +0,0 @@ -= John Doe - Project Portfolio -:site-section: AboutUs -:imagesDir: ../images -:stylesDir: ../stylesheets - -== PROJECT: AddressBook - Level 3 - ---- - -== Overview - -AddressBook - Level 3 is a desktop address book application used for teaching Software Engineering principles. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC. - -== Summary of contributions - -* *Major enhancement*: added *the ability to undo/redo previous commands* -** What it does: allows the user to undo all previous commands one at a time. Preceding undo commands can be reversed by using the redo command. -** Justification: This feature improves the product significantly because a user can make mistakes in commands and the app should provide a convenient way to rectify them. -** Highlights: This enhancement affects existing commands and commands to be added in future. It required an in-depth analysis of design alternatives. The implementation too was challenging as it required changes to existing commands. -** Credits: _{mention here if you reused any code/ideas from elsewhere or if a third-party library is heavily used in the feature so that a reader can make a more accurate judgement of how much effort went into the feature}_ - -* *Minor enhancement*: added a history command that allows the user to navigate to previous commands using up/down keys. - -* *Code contributed*: [https://github.com[Functional code]] [https://github.com[Test code]] _{give links to collated code files}_ - -* *Other contributions*: - -** Project management: -*** Managed releases `v1.3` - `v1.5rc` (3 releases) on GitHub -** Enhancements to existing features: -*** Updated the GUI color scheme (Pull requests https://github.com[#33], https://github.com[#34]) -*** Wrote additional tests for existing features to increase coverage from 88% to 92% (Pull requests https://github.com[#36], https://github.com[#38]) -** Documentation: -*** Did cosmetic tweaks to existing contents of the User Guide: https://github.com[#14] -** Community: -*** PRs reviewed (with non-trivial review comments): https://github.com[#12], https://github.com[#32], https://github.com[#19], https://github.com[#42] -*** Contributed to forum discussions (examples: https://github.com[1], https://github.com[2], https://github.com[3], https://github.com[4]) -*** Reported bugs and suggestions for other teams in the class (examples: https://github.com[1], https://github.com[2], https://github.com[3]) -*** Some parts of the history feature I added was adopted by several other class mates (https://github.com[1], https://github.com[2]) -** Tools: -*** Integrated a third party library (Natty) to the project (https://github.com[#42]) -*** Integrated a new Github plugin (CircleCI) to the team repo - -_{you can add/remove categories in the list above}_ - -== Contributions to the User Guide - - -|=== -|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._ -|=== - -include::../UserGuide.adoc[tag=delete] - -include::../UserGuide.adoc[tag=dataencryption] - -== Contributions to the Developer Guide - -|=== -|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._ -|=== - -include::../DeveloperGuide.adoc[tag=undoredo] - -include::../DeveloperGuide.adoc[tag=dataencryption] - - -== PROJECT: PowerPointLabs - ---- - -_{Optionally, you may include other projects in your portfolio.}_ diff --git a/docs/team/pekchinsiongbrian.adoc b/docs/team/pekchinsiongbrian.adoc new file mode 100644 index 00000000000..01b5d135640 --- /dev/null +++ b/docs/team/pekchinsiongbrian.adoc @@ -0,0 +1,107 @@ += Brian Pek - Project Portfolio +:site-section: AboutUs +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: HealthyBaby + +''' + +== Overview + +*HealthyBaby* (HYBB) is a desktop application targeted towards university students that provides users with a database +of quick, easy, and healthy recipes. HYBB helps alleviate the challenges faced while maintaining healthy eating habits, +easing the transition from eating out everyday to cooking healthy meals regularly. + +The user interacts with HYBB using a Command Line Interface, and it has a Graphical User Interface created with JavaFX. +It is written in Java, and has about 18 kLoC. + +== Summary of contributions + +* *Major enhancement 1*: Added the undo and redo feature +** *What it does*: It allows the user to undo the actions of previous commands. The user may choose undo one command at +a time, undo multiple commands at a time, or even undo all previous commands at once. Undo commands can be reversed by +using the redo command (with equal robustness). +** *Justification*: This feature vastly improves the user-friendliness of the app as the user can now conveniently +rectify any mistakes made. +** *Highlights*: HYBB maintains 4 different "books" (databases) and this feature involves keeping track of the changes +made to these 4 books. Since, most commands will make changes to at least one of these books when executed, designing +and implementing this feature was meaningful and challenging as it required a deep understanding of how each command +affects the 4 books. Essentially, this feature affects most of the existing commands and commands that are added in +future! ++ +Changes to existing commands had to made, and more data structures and tracking mechanisms had to +be added on to make undo/redo compatible with all the commands in HYBB. Though inspiration was intially taken from the +proposed undo/redo feature in AB3, the final implementation of undo/redo in HYBB is significantly different to suit our +needs. +** *Credits*: As mentioned above, this was inspired by the proposed undo/redo feature in AB3. + +* *Major enhancement 2*: Added recipe customisation commands (`addingredient`, `editingredient`, `deleteingredient`, +`addstep`, `editstep`, `editingredient`) +** *What they do*: These commands allow the user to edit the ingredients or steps of a recipe without having to rewrite +the entire field. +** *Justification*: The edit command inherited from AB3 was limited as it could only edit entire fields at once. +These commands vastly improve the user-friendliness of the app as the user can now make small changes without +having to rewrite the entire field (imagine if the recipe has 10 steps but the user only wants to edit 1 of them!) +** *Highlights*: Implementing these commands required a good understanding of how recipes are created and edited, and +how recipes interact with the RecipeBook (the database for all recipes) and the Model. + +* *Major enhancement 3*: Added the filter feature +** *What it does*: It allows users to search for recipes using various criteria such as prep time, ingredients used, or +by the goals tagged to the recipe. +** *Justification*: The find command inherited from AB3 was limited as it could only find recipes by name. This means +the user will have to roughly know a recipe's name beforehand. Not only is this inconvenient, but it doesn't tell the +user much about the recipe. The filter feature allows the user to find recipes with much more ease and makes the search +more targeted. E.g. people with allergies can find recipes without allergens, people with no time can find recipes with +short prep time etc. +** *Highlights*: Implementing this feature required a good understanding of how recipes are filtered (using predicates). +It was challenging because the construction of the predicate had to be precise and accurate, otherwise the wrong +recipes would be displayed to the user. + +* *Minor enhancement*: Added the ability to favourite and unfavourite recipes +** *What it does*: It allows the user to mark a recipe as "favourite" or unmark a favourited recipe. +** *Justification*: It is observed that humans are habitual creatures and will tend to eat the same things. Hence this +minor feature is to complement the filter feature, allowing the user to find all his favourites with one simple line: +`filter favourites` +** *Highlights*: Implementing this feature required a good understanding of how recipes are edited. This understanding +provided a good foundation for the implementation of the recipe customisation commands (which were implemented after +this feature). It also required a good understanding of how the UI components work with each other as I had to display +a star beside the recipe name if it's a favourite. + +* *Code contributed*: [https://nus-cs2103-ay1920s2.github.io/tp-dashboard/#=undefined&search=pekchinsiongbrian[RepoSense Report for Brian Pek]] + +* *Other contributions*: +** *Enhancements to existing features*: +*** Enhanced the `find` command to have 2 methods of searching with 2 corresponding levels of strictness +(Pull request https://github.com/AY1920S2-CS2103T-T10-1/main/pull/159[#159]) +*** Enhanced `ParserUtil` to be able to parse multiple indexes (instead of just one) (Pull request https://github.com/AY1920S2-CS2103T-T10-1/main/pull/68[#68]). +Initially, this was an enhancement for `delete` so that the user can delete multiple recipes at once, but subsequently, +it was taken up by other commands! +** *Community*: +*** PRs reviewed (with non-trivial review comments): https://github.com/AY1920S2-CS2103T-T10-1/main/pull/23[#23], +https://github.com/AY1920S2-CS2103T-T10-1/main/pull/95#discussion_r399608456[#95], +https://github.com/AY1920S2-CS2103T-T10-1/main/pull/105#discussion_r400787470[#105], +https://github.com/AY1920S2-CS2103T-T10-1/main/pull/164#discussion_r405227169[#164] +*** The multiple index input parsing enhancement was adopted by several other teammates (Pull request https://github.com/AY1920S2-CS2103T-T10-1/main/pull/107[#107], +https://github.com/AY1920S2-CS2103T-T10-1/main/pull/176[#176]) + +== Contributions to the User Guide + + +|=== +|_The following section is a portion of my contributions to the User Guide. They showcase my ability to write documentation targeting end-users._ +|=== + +include::../UserGuide.adoc[tag=recipecustomisation] + +include::../UserGuide.adoc[tag=advancedfilter] + +== Contributions to the Developer Guide + +|=== +|_The following section is a portion of my contributions to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._ +|=== + +include::../DeveloperGuide.adoc[tag=undoredo] + +include::../DeveloperGuide.adoc[tag=recipecustomisation] diff --git a/docs/team/tharshita.adoc b/docs/team/tharshita.adoc new file mode 100644 index 00000000000..7f27db920b8 --- /dev/null +++ b/docs/team/tharshita.adoc @@ -0,0 +1,96 @@ += Tiyari Harshita - Project Portfolio +:site-section: AboutUs +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: HealthyBaby + +--- + +== Overview + +*HealthyBaby* (HYBB) is a desktop application targeted towards university students that provides users with a database of quick, easy, and healthy recipes. +HYBB helps alleviate the challenges faced while maintaining healthy eating habits, easing the transition from eating +out everyday to cooking healthy meals regularly. The user interacts with HYBB using a Command Line Interface, and it has a Graphical User Interface created with JavaFX. + +This portfolio serves to demonstrate my proficiency in the various aspects of software engineering such as +coding, project management and technical writing skills in crafting documentation that fits the target user. +My role was to design and implement the code for the goals feature and switch feature which will be further elaborated in the +following sections. Also included are the details of the relevant documentation I have written in the user and +developer guide to assist users and other developers to understand these features. + +== Summary of contributions + +* *Major enhancement*: added *the goals feature* +I implemented the commands and functionality related to the goals feature. +** What it does: Auto generated goals for a recipe every time a recipe's ingredients are added or edited. Based on these goals, +when recipe is marked as cooked, an archive of past cooked meals can be seen as well as a pie chart representing the goals distribution +can be seen under the goals tab. +** Justification: This feature improves the product significantly because a user using a healthy recipe database would want to see +their history of cooked meals as well as statistics of their food distribution (represented by the goals distribution). +** Highlights: This enhancement affects existing add and edit commands and commands to be added in future such as planning. +It required an in-depth analysis of design alternatives so as to achieve the most accurate results. +The implementation too was challenging as it required changes to existing commands as well as working on all parts of the code such as +creating a new json file to store records, working with ui and fxml and listeners with pie charts. A great deal of designing and +abstraction was needed where code had to be continually changed and rewritten to be optimised and make proper use of inheritance +of ingredients for efficiency in calculating quantity. + +* *Minor enhancement*: added *the ability to switch between tabs* +I implemented the switch command that allows for switching between tabs. A great deal of planning and understanding +of the front-end code was needed in order to integrate the switch command. I designed and abstracted out the front end into +4 main tabs. + +* * https://nus-cs2103-ay1920s2.github.io/tp-dashboard/#=undefined&search=tharshita[Functional code and test code] +* * https://github.com/AY1920S2-CS2103T-T10-1/main/pull/107[example code] + + +* *Other contributions*: + +** Project management: +*** Managed the https://github.com/AY1920S2-CS2103T-T10-1/main/issues?q=is%3Aissue+author%3Atharshita+is%3Aclosed[issues] +covered for each milestone. Added each feature as issue and assigned it to teammates. +*** Initiated testing of the product before v1.4 and reported bugs and assigned them to person in charge. https://github.com/AY1920S2-CS2103T-T10-1/main/issues?q=is%3Aissue+label%3Atype.Bug+is%3Aclosed[bugs] +*** Did the major refactoring of code from addressbook to recipebook, adding classes and fields such as goal class, time class and steps class and +deleting unecessary fields https://github.com/AY1920S2-CS2103T-T10-1/main/pull/22[22] +** Enhancements to existing features: +*** Updated the GUI color scheme and changed logo of HYBB(Pull requests https://github.com/AY1920S2-CS2103T-T10-1/main/pull/69[#69]) +*** Created all 4 tabs and guided teammates on how to fill these tabs with their respective data. https://github.com/AY1920S2-CS2103T-T10-1/main/pull/118[#118] +*** Wrote additional tests for existing features to increase coverage (Pull requests https://github.com/AY1920S2-CS2103T-T10-1/main/pull/173[#173], https://github.com[#38]) +** Documentation: +*** Wrote the overview, FAQs and updated command summary, help command, introduction, switch and goals commands +*** wrote NFR, use cases and user stories https://github.com/AY1920S2-CS2103T-T10-1/main/commit/865a04f919fc36b4ffa6ac9a7de1b8439f80e1a5[PR] +*** Updated the UI and storage models in Developer's guide and wrote manual testing. +** Community: +*** PRs reviewed (with non-trivial review comments): https://github.com/AY1920S2-CS2103T-T10-1/main/pull/115[#115], https://github.com/AY1920S2-CS2103T-T10-1/main/pull/172[#172], https://github.com/AY1920S2-CS2103T-T10-1/main/pulls?q=is%3Apr+reviewed-by%3A%40me+is%3Aclosed[all], +*** Reviewed other team: https://github.com/AY1920S2-CS2103T-T10-2/main/pull/89[#89] +*** Reported bugs and suggestions for other teams in the class during tutorials and peer testing + + + + +== Contributions to the User Guide + + +|=== +|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._ +|=== +include::../UserGuide.adoc[tag=overview] +include::../UserGuide.adoc[tag=switch] +include::../UserGuide.adoc[tag=goalintro] +include::../UserGuide.adoc[tag=goals] +include::../UserGuide.adoc[tag=faq] + +== Contributions to the Developer Guide + +|=== +|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._ +|=== +include::../DeveloperGuide.adoc[tag=ui] + +include::../DeveloperGuide.adoc[tag=storage] + +include::../DeveloperGuide.adoc[tag=switch] + +include::../DeveloperGuide.adoc[tag=goals] + +include::../DeveloperGuide.adoc[tag=nfr] diff --git a/docs/team/yuuton9.adoc b/docs/team/yuuton9.adoc new file mode 100644 index 00000000000..cc8b3c6df94 --- /dev/null +++ b/docs/team/yuuton9.adoc @@ -0,0 +1,84 @@ += Lee Yue Tong - Project Portfolio +:site-section: AboutUs +:imagesDir: ../images +:stylesDir: ../stylesheets + +== PROJECT: HealthyBaby + +--- + +== Overview + +*HealthyBaby* (HYBB) is a desktop application targeted towards university students that provides users with a database of quick, easy, and healthy recipes. +HYBB helps alleviate the challenges faced while maintaining healthy eating habits, easing the transition from eating +out everyday to cooking healthy meals regularly. + +The user interacts with HYBB using a Command Line Interface, and it has a Graphical User Interface created with JavaFX. + +It is written in Java, and has about 18 kLoC. + +== Summary of contributions + +* *Major enhancement*: added *the ability to add quotes* +** What it does: allows the user to input their own customised quotes as long as it abides by the message constraints so that +they can choose to display quotes to their own liking at the quotes section in the achievement tab. +** Justification: This feature improves the product significantly because it provides motivation for the user to continue +their healthy diets as users tend to lose their motivations for keeping their diets consistently. By allowing users to input +their own quotes it does not restrict the users to the predetermined few default quotes. +** Highlights: This enhancement affected the current data structure used to contain the quotes and required a modifiable +file to allow users to input their own quotes. The implementation was more challenging as there has to be checks conducted +to ensure that duplicate quotes are rejected and quotes do not violate the stated format. +** Credits: _{}_ + +* *Major enhancement*: added *the ability to display streaks* +** What it does: allows the user to keep track of whether they're cooking the recipes consistently and to also check what +were their highest streaks. +** Justification: This feature improves the product significantly because it provides a visual and statistical view of the user's progress and +it is updated real time as the user logs in cooked recipes. As both current and high streaks are displayed, it provides visual motivation for the users to not break their streaks. +** Highlights: This enhancement requires data from CookedRecord, another part of the program that is largely unaffiliated wit streaks which made it challenging to link their data together. +The algorithm for calculating both the current streak and highest streak from the CookedRecord list provided was also more challenging as the history of cooked recipes had to be take into consideration highest streak. +** Credits: _{}_ + +* *Minor enhancement*: contributed to the help command that allows the user to view the commands available. + +* *Minor enhancement*: Created SampleDataUtil(and recipes json) file containing the default recipe. + +* *Code contributed*: [https://github.com[Functional code]] [https://github.com[Test code]] _{give links to collated code files}_ + +* *Other contributions*: + +** Project management: +*** Checked Checkstyles +** Enhancements to existing features: +*** Updated GUI for achievement tab (Pull requests https://github.com/AY1920S2-CS2103T-T10-1/main/pulls?page=1&q=is%3Apr+is%3Aclosed[#200]), +*** Added highest streak function (Pull requests https://github.com/AY1920S2-CS2103T-T10-1/main/pulls?page=1&q=is%3Apr+is%3Aclosed[#203]) +** Documentation: +*** Did tweaks to existing contents of the User Guide: https://github.com/AY1920S2-CS2103T-T10-1/main/blob/master/docs/UserGuide.adoc[#12]) +** Community: +*** Contributed to forum discussions (question: https://github.com/nus-cs2103-AY1920S2/forum/issues/99[99]), +** Tools: - + +== Contributions to the User Guide + + +|=== +|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._ +|=== + +include::../UserGuide.adoc[tag=achievement] + +== Contributions to the Developer Guide + +|=== +|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._ +|=== + +include::../DeveloperGuide.adoc[tag=quote] + +include::../DeveloperGuide.adoc[tag=streak] + +== PROJECT: PowerPointLabs + +--- + +_{Optionally, you may include other projects in your portfolio.}_ diff --git a/docs/templates/LICENSE b/docs/templates/LICENSE index 2073b44dee6..e4169fdef6f 100644 --- a/docs/templates/LICENSE +++ b/docs/templates/LICENSE @@ -5,11 +5,11 @@ MIT License Copyright (C) 2012-2018 Dan Allen, Ryan Waldron and the Asciidoctor Project -Permission is hereby granted, free of charge, to any person obtaining a copy +Permission is hereby granted, free of charge, to any recipe obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +copies of the Software, and to permit recipes to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in diff --git a/docs/tutorials/AddRemark.adoc b/docs/tutorials/AddRemark.adoc index 51044c36494..05410ae295d 100644 --- a/docs/tutorials/AddRemark.adoc +++ b/docs/tutorials/AddRemark.adoc @@ -34,14 +34,14 @@ For now, let's keep `RemarkCommand` as simple as possible and print some output. We accomplish that by returning a `CommandResult` with an accompanying message. .RemarkCommand.java -[source, java] +[source,java] ---- -package seedu.address.logic.commands; +package seedu.recipe.logic.commands; -import seedu.address.model.Model; +import seedu.recipe.model.Model; /** - * Changes the remark of an existing person in the address book. + * Changes the remark of an existing recipe in the address book. */ public class RemarkCommand extends Command { @@ -82,8 +82,8 @@ Following the convention in other commands, we add relevant messages as constant .RemarkCommand.java [source, java] ---- - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the remark of the person identified " - + "by the index number used in the last person listing. " + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the remark of the recipe identified " + + "by the index number used in the last recipe listing. " + "Existing remark will be overwritten by the input.\n" + "Parameters: INDEX (must be a positive integer) " + "r/ [REMARK]\n" @@ -108,9 +108,9 @@ We start by modifying the constructor of `RemarkCommand` to accept an `Index` an While we are at it, let's change the error message to echo the values. While this is not a replacement for tests, it is an obvious way to tell if our code is functioning as intended. -[source, java] +[source,java] ---- -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import static seedu.recipe.commons.util.CollectionUtil.requireAllNonNull; //... public class RemarkCommand extends Command { //... @@ -120,8 +120,8 @@ public class RemarkCommand extends Command { private final String remark; /** - * @param index of the person in the filtered person list to edit the remark - * @param remark of the person to be updated to + * @param index of the recipe in the filtered recipe list to edit the remark + * @param remark of the recipe to be updated to */ public RemarkCommand(Index index, String remark) { requireAllNonNull(index, remark); @@ -245,13 +245,13 @@ If you are stuck, check out the sample link:https://github.com/nus-cs2103-AY1920 == Add `Remark` to the model Now that we have all the information that we need, let's lay the groundwork for some _persistent_ changes. -We achieve that by working with the `Person` model. -Each field in a Person is implemented as a separate class (e.g. a `Name` object represents the person's name). -That means we should add a `Remark` class so that we can use a `Remark` object to represent a remark given to a person. +We achieve that by working with the `Recipe` model. +Each field in a Recipe is implemented as a separate class (e.g. a `Name` object represents the recipe's name). +That means we should add a `Remark` class so that we can use a `Remark` object to represent a remark given to a recipe. === Add a new `Remark` class -Create a new `Remark` in `seedu.address.model.person`. Since a `Remark` is a field that is similar to `Address`, we can reuse a significant bit of code. +Create a new `Remark` in `seedu.address.model.recipe`. Since a `Remark` is a field that is similar to `Address`, we can reuse a significant bit of code. A copy-paste and search-replace later, you should have something like link:https://github.com/nus-cs2103-AY1920S1/addressbook-level3/commit/b7a47c50c8e5f0430d343a23d2863446b6ce9298#diff-af2f075d24dfcd333876f0fbce321f25[this]. Note how `Remark` has no constrains and thus does not require input validation. @@ -263,17 +263,17 @@ These should be relatively simple changes. == Add a placeholder element for remark to the UI -Without getting too deep into `fxml`, let's go on a 5 minute adventure to get some placeholder text to show up for each person. +Without getting too deep into `fxml`, let's go on a 5 minute adventure to get some placeholder text to show up for each recipe. Simply add [source, java] -.PersonCard.java +.RecipeCard.java ``` @FXML private Label remark; ``` -to link:https://github.com/nus-cs2103-AY1920S1/addressbook-level3/commit/2758455583f0101ed918a318fc75679270843a0d#diff-0c6b6abcfac8c205e075294f25e851fe[`seedu.address.ui.PersonCard`]. +to link:https://github.com/nus-cs2103-AY1920S1/addressbook-level3/commit/2758455583f0101ed918a318fc75679270843a0d#diff-0c6b6abcfac8c205e075294f25e851fe[`seedu.recipe.ui.RecipeCard`]. `@FXML` is an annotation that marks a private or protected field and makes it accessible to FXML. It might sound like Greek to you right now, don't worry -- we will get back to it later. @@ -282,34 +282,34 @@ Then insert ```