Skip to content

Conversation

@Carlton369
Copy link

No description provided.

@Carlton369 Carlton369 changed the title Update README.md [CS2113-T13-1] KitchenCTRL Mar 6, 2025
Copy link

@yijiano yijiano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good effort so far, but please improve on your standardisation, as well as clean up your code.

Comment on lines 1 to 85
package logic.commands;

import model.Ingredient;
import model.Recipe;
import java.util.ArrayList;
import model.catalogue.IngredientCatalogue;

public class Commands {

// Add ingredient to inventory
public static void addIngredient(IngredientCatalogue inventory, String name, int quantity) {
for (Ingredient ing : inventory.getItems()) {
if (ing.getIngredientName().equalsIgnoreCase(name)) {
ing.setQuantity(ing.getQuantity() + quantity);
return;
}
}
inventory.addItem(new Ingredient(name, quantity));
}

// Edit ingredient quantity
public void editIngredient(IngredientCatalogue inventory,String name, int newQuantity) {
for (Ingredient ing : inventory.getItems()) {
if (ing.getIngredientName().equalsIgnoreCase(name)) {
ing.setQuantity(newQuantity);
return;
}
}
}

// List all ingredients in inventory
public void listIngredients(IngredientCatalogue inventory) {
for (Ingredient ing : inventory.getItems()) {
System.out.println(ing.getIngredientName() + ": " + ing.getQuantity());
}
}

// Delete an ingredient from inventory
public void deleteIngredient(IngredientCatalogue inventory, Ingredient ingredientToDelete) {
inventory.deleteItem(ingredientToDelete);
}

/*
* Checks if there are enough ingredients in inventory to cook recipe
*
* @paramin recipe
* @paramout arraylist of missing ingredients and quantity
*/
public static ArrayList<Ingredient> getMissingIngredients(IngredientCatalogue inventory, Recipe targetRecipe) {
ArrayList<Ingredient> missingIngredients = new ArrayList<>();
ArrayList<Ingredient> inventoryItems = inventory.getItems();
ArrayList<Ingredient> targetRecipeIngredients = targetRecipe.getItems();

for (Ingredient requiredIngredient : targetRecipeIngredients) {
if (!inventoryItems.contains(requiredIngredient)) {
missingIngredients.add(requiredIngredient);
} else {
int index = inventoryItems.indexOf(requiredIngredient);
Ingredient availableIngredient = inventoryItems.get(index);
if (availableIngredient.getQuantity() < requiredIngredient.getQuantity()) {
int shortage = requiredIngredient.getQuantity() - availableIngredient.getQuantity();
missingIngredients.add(new Ingredient(requiredIngredient.getIngredientName(), shortage));
}
}
}
return missingIngredients;
}

public static void cookRecipe(IngredientCatalogue inventory, Recipe recipeToCook) {
ArrayList<Ingredient> missingIngredients = getMissingIngredients(inventory, recipeToCook);
if (!missingIngredients.isEmpty()) {
return;
}

ArrayList<Ingredient> inventoryItems = inventory.getItems();
ArrayList<Ingredient> ingredientsToCook = recipeToCook.getItems();

for (Ingredient requiredIngredient : ingredientsToCook) {
int index = inventoryItems.indexOf(requiredIngredient);
Ingredient ingredientInInventory = inventoryItems.get(index);
ingredientInInventory.subtractQuantity(requiredIngredient.getQuantity());
}

}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this even being used? If not, please remove this.

private Ui ui;

/**
* Main entry-point for the java.duke.Duke application.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update this comment


private void exit() {
ui.showGoodbyeMessage();
System.exit(0);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt this is needed, you can just allow the app to close gracefully.

Comment on lines 87 to 105
public static void carltonTest() {
IngredientCatalogue inventory = new IngredientCatalogue();
inventory.addItem(new Ingredient("White sugar", 50));
inventory.addItem(new Ingredient("Egg", 3));
inventory.addItem(new Ingredient("Flour", 50));

Recipe recipe = new Recipe();
recipe.addItem(new Ingredient("White sugar", 20));
recipe.addItem(new Ingredient("Egg", 1));
recipe.addItem(new Ingredient("Flour", 10));


System.out.println(recipe);
System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
System.out.println("PRINTING MISSING");
Commands.cookRecipe(inventory, recipe);
inventory.listItems();
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could have been refactored as a JUnit test instead.


public class Parser {
public Command parseCommand(String userInput) {
String[] commands = userInput.split(" ", 2);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it is still readable, maybe change the name from commands to something less ambiguous here.

return Files.readAllLines(filePath);
}
} catch (Exception e) {
System.err.println("Error loading file: " + e.getMessage());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider implementing logging for these error cases.

@Override
public CommandResult addItem(Ingredient ingredient) {
items.add(ingredient);
return null;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you can print an empty CommandResult instead of just null?

Comment on lines 9 to 15
public Command(String args) {

}

public Command() {

}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a difference between these two constructors?

Comment on lines 17 to 24
public CommandResult execute() { // Ensure this method exists
return null;
}

public CommandResult execute(IngredientCatalogue inventory) {
throw new UnsupportedOperationException("override me");
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the intention is to override this method, perhaps this can be an abstract method.

Comment on lines 21 to 22
assert name != null && !name.trim().isEmpty() : "Ingredient name must not be null or empty";
assert quantity > 0 : "Ingredient quantity must be greater than zero";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please implement proper guard clauses instead of just using assertions.

This applies to most of the command classes.

rchlai added a commit to rchlai/tp that referenced this pull request Mar 31, 2025
Copy link

@yijiano yijiano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good effort, keep up the good work. Also, thanks for reading my previosu review and making the necessary changes.

String[] keywordList = ingredientName.toLowerCase().split(" ");

return items.stream()
.filter(currIngredient -> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using other stream operations such as findFirst which would be more clear.

Comment on lines 200 to 204
// Create the calculation message
String calculations = existingIngredient.getIngredientName() + ": " +
"Initial quantity = " + initialQuantity + ", " +
"Subtracted = " + decreaseQuantity + ", " +
"Remaining = " + existingIngredient.getQuantity();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe there is a way to refactor this so that it can be a method/class of its own?

Comment on lines 142 to 145
for (int i = 0; i < similarRecipe.size(); i++) {
System.out.println("Type '" + (i + 1) + "' to delete: " + similarRecipe.get(i).getRecipeName());
}
System.out.println("Type '-1' to cancel this action.");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this check can be abstracted out? Especially since this check has been used several times.

Comment on lines 133 to 146
case INVENTORY, RECIPE -> {
// Expecting: add <ingredientName> <quantity>
String[] parts = args.split(" ", 2);
if (parts.length < 2) {
throw new IllegalArgumentException("Invalid format! Usage: add <name> <quantity>");
}

String name = parts[0].trim();
int quantity;
try {
quantity = Integer.parseInt(parts[1].trim());
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Quantity must be a valid integer!");
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe abstract this out so that this method is not so complex. Also, try to follow the switch statement as stated in the code style.

Comment on lines 35 to 49
public AddCommand(String name, int quantity) {
assert name != null && !name.trim().isEmpty() : "Name must not be null or empty";

assert screen == RECIPEBOOK || quantity > 0 : "Quantity must be greater than zero";

this.name = name;
this.quantity = quantity;
}

public AddCommand(String name) {
assert name != null && !name.trim().isEmpty() : "Name must not be null or empty";

this.name = name;
this.quantity = 0; // irrelevant for recipebook screen
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use try-catch rather than just assert to catch malformed inputs.

Comment on lines 57 to 62
return items.stream()
.filter(currRecipe -> {
String name = getRecipeNameLowercase(currRecipe);
return Arrays.stream(keywordList).allMatch(name::contains);
})
.collect(Collectors.toCollection(ArrayList::new));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stream operation findFirst might do well here

Comment on lines 107 to 110
if (choice == 0) {
addRecipe(recipe);
return new CommandResult(recipe.getRecipeName() + " added to recipe book.");
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if block can be merged with the above.

return new CommandResult(recipe.getRecipeName() + " does not exist in the recipe book.");
}

if (similarRecipe.size() == SINGLE_MATCH && isExactMatchFound(similarRecipe.get(FIRST_ITEM_INDEX), recipe)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The if blocks can be combined, and if needed abstract out the condition to its own method/boolean variable.

*/
public void updateItem(T oldItem, T newItem) {
int index = items.indexOf(oldItem);
if (index != -1) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you can re-use your AddItem method?

Comment on lines +45 to +56
for (Ingredient requiredIngredient : recipeIngredients) {
if (!inventoryItems.contains(requiredIngredient)) {
missingIngredients.add(requiredIngredient);
} else {
int index = inventoryItems.indexOf(requiredIngredient);
Ingredient availableIngredient = inventoryItems.get(index);
if (availableIngredient.getQuantity() < requiredIngredient.getQuantity()) {
int shortage = requiredIngredient.getQuantity() - availableIngredient.getQuantity();
missingIngredients.add(new Ingredient(requiredIngredient.getIngredientName(), shortage));
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make this method simpler (abstract out the steps/conditions)?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class logo is wrong, should be : instead.

|v1.0| user |enter commands into the system| interact with it and perform necessary actions efficiently |
|v1.0| user |save and retrieve data| have accessible and up-to-date information |
|v2.0| user |find a to-do item by name| locate a to-do without having to go through the entire list |
| Version | As a ... | I want to ... | So that I can ... |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could add a column for priority, overall looks good!

@@ -11,7 +11,7 @@ KitchenCTRL uses the following tools for development:
The design and implementation of KitchenCTRL has been broken down into various sections
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

The commands package provides a structured way to define and execute operations in the application. By inheriting from the Command class, each command ensures consistency and adheres to the application's design principles. The CookRecipeCommand is a concrete example of how commands are implemented to perform specific tasks.

### Model Component
![Model UML diagram](diagrams/model.png)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class logo seems to be incorrect.

Copy link

@IgoyAI IgoyAI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check the UML Diagram. Overall good already.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

presence of non-standard icons

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

presence of non-standard icons

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The methods in IngredientCatalogue and RecipeCatalogue (e.g., addItem, deleteItem) return CommandResult, but CommandResult itself does not appear in the diagram. If CommandResult is a class or interface, consider adding it or showing the relationship.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The diagram suggests that a Recipe can contain multiple Ingredient objects, but there is no line or association from Recipe to Ingredient. If your code has something like a List inside Recipe, you should show that in the diagram with an association or composition arrow.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

presence of non-standard icons

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

presence of non-standard icons

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

presence of non-standard icons

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Parser uses or depends on Command objects, you might want to show that relationship in the diagram (e.g., an arrow from Parser to Command indicating it instantiates or calls execute()).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The diagram shows two execute() methods with different signatures on the Command class (e.g., one returning CommandResult and another taking different parameters). Make sure these match the actual method signatures in your code.

ChingWhee and others added 30 commits April 8, 2025 12:06
updating add->edit jump functionality to recipeobok
Updated guides for exiting and saving
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.