Skip to content

Commit

Permalink
Merge pull request #394 from DextheChik3n/373-edit-add-dish-messages-…
Browse files Browse the repository at this point in the history
…v2.1

Refactor and add more error handling
  • Loading branch information
Cazh1 authored Nov 13, 2023
2 parents eaed86f + 3cdc854 commit 234c862
Show file tree
Hide file tree
Showing 16 changed files with 162 additions and 88 deletions.
Binary file modified docs/images/aboutUs/dexter.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion src/main/java/seedu/cafectrl/data/Chef.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.util.logging.Level;
import java.util.logging.Logger;


public class Chef {
private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
private final Order order;
Expand Down
1 change: 1 addition & 0 deletions src/main/java/seedu/cafectrl/data/Order.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ public void setQuantity(int quantity) {
public void setTotalOrderCost(float cost) {
this.totalOrderCost = cost;
}

public Dish getOrderedDish() {
return orderedDish;
}
Expand Down
1 change: 0 additions & 1 deletion src/main/java/seedu/cafectrl/data/OrderList.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
*/
public class OrderList {
private static final DecimalFormat dollarValue = new DecimalFormat("0.00");
private static final String HEADER_FORMAT = "%-20s %-10s %-20s\n";
private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
private ArrayList<Order> orderList;
private float totalOrderListCost;
Expand Down
1 change: 1 addition & 0 deletions src/main/java/seedu/cafectrl/data/dish/Dish.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public ArrayList<Ingredient> getIngredients() {
public float getPrice() {
return price;
}

public String getPriceString() {
return this.dollarValue.format(this.price);
}
Expand Down
53 changes: 43 additions & 10 deletions src/main/java/seedu/cafectrl/parser/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public class Parser implements ParserUtil {
+ "qty/\\s*(?<ingredientQty>.*)\\s*";
private static final String INGREDIENT_NAME_REGEX_GROUP_LABEL = "ingredientName";
private static final String INGREDIENT_QTY_REGEX_GROUP_LABEL = "ingredientQty";
private static final String INGREDIENT_QTY_FORMAT_REGEX = "^\\s*(?<value>[0-9]*)\\s*(?<unit>[a-zA-z]*)\\s*$";
private static final String INGREDIENT_QTY_FORMAT_REGEX = "^\\s*(?<value>[+-]*[0-9]*)\\s*(?<unit>[a-zA-z]*)\\s*$";
private static final String INGREDIENT_QTY_VALUE_REGEX_GROUP_LABEL = "value";
private static final String INGREDIENT_QTY_UNIT_REGEX_GROUP_LABEL = "unit";
private static final String ADD_DISH_NAME_ARGUMENT = "name/";
Expand All @@ -68,8 +68,7 @@ public class Parser implements ParserUtil {
/** Add Order Command Handler Patterns*/
private static final int DISH_NAME_MATCHER_GROUP_NUM = 1;
private static final int ORDER_QTY_MATCHER_GROUP_NUM = 2;
private static final String ADD_ORDER_ARGUMENT_STRING = "name/([A-Za-z0-9\\s]+) "
+ "qty/([A-Za-z0-9\\s]+)";
private static final String ADD_ORDER_ARGUMENT_STRING = "name/(.*) qty/(.*)";

/** The rest of Command Handler Patterns*/

Expand Down Expand Up @@ -250,11 +249,11 @@ private static Command prepareAdd(String arguments, Menu menu, Ui ui) {

// To retrieve specific arguments from arguments
//the dishName needs .trim() because the regex accepts whitespaces in the "name/" argument
String dishName = matcher.group(DISH_NAME_MATCHER_GROUP_LABEL).trim();
String dishName = matcher.group(DISH_NAME_MATCHER_GROUP_LABEL).trim().toLowerCase();
float dishPrice = parsePriceToFloat(matcher.group(PRICE_MATCHER_GROUP_LABEL));
String ingredientsListString = matcher.group(INGREDIENTS_MATCHER_GROUP_LABEL);

detectErrorPostDishNameParse(dishName, menu);
detectErrorPostDishNameParse(dishName, menu, true);

ArrayList<Ingredient> ingredients = parseIngredients(ingredientsListString, true, menu);
Dish dish = new Dish(dishName, ingredients, dishPrice);
Expand Down Expand Up @@ -293,14 +292,15 @@ private static Matcher detectErrorInPreAddParse(String arguments) throws ParserE
return matcher;
}

private static void detectErrorPostDishNameParse(String dishName, Menu menu) throws ParserException {
private static void detectErrorPostDishNameParse(String dishName, Menu menu, boolean isCheckRepeatedDishName)
throws ParserException {
if (dishName.isEmpty()) {
logger.warning("Dish name empty!");
throw new ParserException(ErrorMessages.MISSING_DISH_NAME);
} else if (isNameLengthInvalid(dishName)) {
logger.warning("Invalid name length!");
throw new ParserException(ErrorMessages.INVALID_DISH_NAME_LENGTH_MESSAGE);
} else if (isRepeatedDishName(dishName, menu)) {
} else if (isCheckRepeatedDishName && isRepeatedDishName(dishName, menu)) {
logger.warning("Repeated dish!");
throw new ParserException(ErrorMessages.REPEATED_DISH_MESSAGE);
} else if (containsSpecialChar(dishName)) {
Expand Down Expand Up @@ -346,7 +346,7 @@ private static void parseIngredient(
throws ParserException {
Matcher ingredientMatcher = detectErrorPreIngredientParse(inputIngredient);

String ingredientName = ingredientMatcher.group(INGREDIENT_NAME_REGEX_GROUP_LABEL).trim();
String ingredientName = ingredientMatcher.group(INGREDIENT_NAME_REGEX_GROUP_LABEL).trim().toLowerCase();

//ingredientQtyString contains the input text after the "qty/" argument
String ingredientQtyString = ingredientMatcher.group(INGREDIENT_QTY_REGEX_GROUP_LABEL).trim();
Expand Down Expand Up @@ -769,8 +769,10 @@ private static Command prepareOrder(Menu menu, String arguments, Ui ui,

try {
// To retrieve specific arguments from arguments
String dishName = matcher.group(DISH_NAME_MATCHER_GROUP_NUM);
int dishQty = Integer.parseInt(matcher.group(ORDER_QTY_MATCHER_GROUP_NUM));
String dishName = matcher.group(DISH_NAME_MATCHER_GROUP_NUM).trim();
int dishQty = parseQtyToInt(matcher.group(ORDER_QTY_MATCHER_GROUP_NUM).trim());

detectErrorPostDishNameParse(dishName, menu, false);

Dish orderedDish = menu.getDishFromName(dishName);
if (orderedDish == null) {
Expand All @@ -780,6 +782,10 @@ private static Command prepareOrder(Menu menu, String arguments, Ui ui,
Order order = new Order(orderedDish, dishQty);

return new AddOrderCommand(order, ui, pantry, orderList, menu);
} catch (ParserException e) {
return new IncorrectCommand(e.getMessage(), ui);
} catch (NumberFormatException e) {
return new IncorrectCommand(ErrorMessages.INVALID_INT_ORDER_QTY, ui);
} catch (Exception e) {
return new IncorrectCommand(ErrorMessages.INVALID_ADD_ORDER_FORMAT_MESSAGE
+ AddOrderCommand.MESSAGE_USAGE + e.getMessage(), ui);
Expand Down Expand Up @@ -813,6 +819,33 @@ private static Command prepareNextDay(Ui ui, Sales sales, CurrentDate currentDat
return new NextDayCommand(ui, sales, currentDate);
}

//@@author DextheChik3n
/**
* Parses the quantity text string into integer and checks if the input is valid
*
* @param qtyText text that consist of the order dish quantity
* @return int value of the quantity
* @throws ParserException if the input string does not match the constraints
*/
public static int parseQtyToInt(String qtyText) throws ParserException {
if (qtyText.isEmpty()) {
throw new ParserException(ErrorMessages.MISSING_ORDER_QTY);
}

int dishQty = Integer.parseInt(qtyText);

int maxDishQty = 10000;
int minDishQty = 1;

if (dishQty < minDishQty) {
throw new ParserException(ErrorMessages.BELOW_MIN_ORDER_QTY);
} else if (dishQty > maxDishQty) {
throw new ParserException(ErrorMessages.EXCEED_MAX_ORDER_QTY);
}

return dishQty;
}

//@@author NaychiMin
/**
* Prepares a command to display all sales items.
Expand Down

This file was deleted.

78 changes: 55 additions & 23 deletions src/main/java/seedu/cafectrl/storage/Decoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,35 @@
* Pantry stock, and OrderList, allowing retrieval of data stored in a file.
*/
public class Decoder {

private static final Ui ui = new Ui();
private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
private static final String DIVIDER = "\\| ";
private static final String INGREDIENT_DIVIDER = " - ";
private static final Ui ui = new Ui();
private static Logger logger = Logger.getLogger(CafeCtrl.class.getName());

/** For menu decoder */
private static final int MAX_INGREDIENTS_STRING_ARRAY_SIZE = 1;
private static final int DISH_NAME_INDEX_DISH_ARRAY = 0;
private static final int DISH_PRICE_INDEX_DISH_ARRAY = 1;
private static final int DISH_INGREDIENT_START_INDEX = 2;
private static final int NAME_INDEX_INGREDIENT_ARRAY = 0;
private static final int QTY_INDEX_INGREDIENT_ARRAY = 1;
private static final int UNIT_INDEX_INGREDIENT_ARRAY = 2;

/** for stock pantry decoder */
private static final int NAME_INDEX_PANTRY = 0;
private static final int QTY_INDEX_PANTRY = 1;
private static final int UNIT_INDEX_PANTRY = 2;
private static final int MAX_PANTRY_ARRAY_SIZE = 3;

/** for sales decoder */
private static final int DAY_INDEX_SALES = 0;
private static final int DISH_NAME_INDEX_SALES = 1;
private static final int QTY_INDEX_SALES = 2;
private static final int DISH_PRICE_INDEX_SALES = 3;
private static final int STATUS_INDEX_SALES = 4;
private static final String TRUE_STRING = "true";
private static final String FALSE_STRING = "false";
private static final int MIN_DISH_PRICE = 0;

//@@author ShaniceTang
/**
Expand Down Expand Up @@ -61,11 +85,15 @@ private static void decodeDishString(String dishString, ArrayList<Dish> menuDish
String dishName = "";
try {
String[] dishStringArray = dishString.split(DIVIDER);
dishName = dishStringArray[0].trim().toLowerCase();
dishName = dishStringArray[DISH_NAME_INDEX_DISH_ARRAY].trim().toLowerCase();

checkNameValidity(dishName);
float dishPrice = Parser.parsePriceToFloat(dishStringArray[1]);
String[] ingredientStringArray = Arrays.copyOfRange(dishStringArray, 2, dishStringArray.length);

float dishPrice = Parser.parsePriceToFloat(dishStringArray[DISH_PRICE_INDEX_DISH_ARRAY]);
String[] ingredientStringArray = Arrays.copyOfRange(
dishStringArray, DISH_INGREDIENT_START_INDEX, dishStringArray.length);
ArrayList<Ingredient> ingredientsList = decodeIngredientData(ingredientStringArray);

menuDishList.add(new Dish(dishName, ingredientsList, dishPrice));
} catch (ParserException e) {
logger.log(Level.WARNING, "Dish has invalid price: " + e.getMessage(), e);
Expand Down Expand Up @@ -94,19 +122,23 @@ private static void checkNameValidity(String name) throws Exception {
private static ArrayList<Ingredient> decodeIngredientData(String[] ingredientsStringArray) throws Exception {
ArrayList<Ingredient> ingredientList = new ArrayList<>();

if (ingredientsStringArray.length < 1) {
if (ingredientsStringArray.length < MAX_INGREDIENTS_STRING_ARRAY_SIZE) {
throw new RuntimeException(ErrorMessages.MISSING_INGREDIENT_MENU_DATA);
}

for(String ingredientString : ingredientsStringArray) {
logger.info("Ingredient to decode: " + ingredientString);

String[] array = ingredientString.split(INGREDIENT_DIVIDER);
String name = array[0].trim().toLowerCase();
String name = array[NAME_INDEX_INGREDIENT_ARRAY].trim().toLowerCase();
checkNameValidity(name);
int qty = Integer.parseInt(array[1].trim());

int qty = Integer.parseInt(array[QTY_INDEX_INGREDIENT_ARRAY].trim());
checkQtyValidity(qty);
String unit = array[2].trim();

String unit = array[UNIT_INDEX_INGREDIENT_ARRAY].trim();
checkUnitValidity(unit);

ingredientList.add(new Ingredient(name, qty, unit));
}
return ingredientList;
Expand Down Expand Up @@ -146,9 +178,9 @@ public static Pantry decodePantryStockData(ArrayList<String> encodedPantryStock)
ui.showToUser(ErrorMessages.ERROR_IN_PANTRY_STOCK_DATA + encodedData);
continue;
}
String ingredientName = decodedData[0].trim();
String qtyText = decodedData[1].trim();
String unit = decodedData[2].trim();
String ingredientName = decodedData[NAME_INDEX_PANTRY].trim().toLowerCase();
String qtyText = decodedData[QTY_INDEX_PANTRY].trim();
String unit = decodedData[UNIT_INDEX_PANTRY].trim();

// Check whether qty is an integer
int qty;
Expand Down Expand Up @@ -200,11 +232,11 @@ private static boolean isValidUnit(String unit) {
* @return true if the format is correct, false otherwise
*/
private static boolean isValidPantryStockFormat(String[] decodedPantryStock) {
if (decodedPantryStock.length != 3) {
if (decodedPantryStock.length != MAX_PANTRY_ARRAY_SIZE) {
return false;
} else {
try {
Integer.parseInt(decodedPantryStock[1].trim());
Integer.parseInt(decodedPantryStock[QTY_INDEX_PANTRY].trim());
} catch (NumberFormatException e) {
return false;
}
Expand Down Expand Up @@ -254,8 +286,8 @@ public static Sales decodeSales(ArrayList<String> textLines, Menu menu) {
private static void decodeSalesData(String orderLine, ArrayList<OrderList> orderLists, Menu menu) {
try {
String[] orderData = orderLine.split(DIVIDER);
int day = Integer.parseInt(orderData[0].trim()) - Sales.DAY_DISPLAY_OFFSET;
String dishName = orderData[1].trim();
int day = Integer.parseInt(orderData[DAY_INDEX_SALES].trim()) - Sales.DAY_DISPLAY_OFFSET;
String dishName = orderData[DISH_NAME_INDEX_SALES].trim().toLowerCase();

//@@author Cazh1
//keeps track of the number of days cafe has been operating for
Expand All @@ -265,9 +297,9 @@ private static void decodeSalesData(String orderLine, ArrayList<OrderList> order
}
//@@author

int quantity = Integer.parseInt(orderData[2].trim());
float decodedDishPrice = Float.parseFloat(orderData[3].trim());
String completeStatus = orderData[4].trim();
int quantity = Integer.parseInt(orderData[QTY_INDEX_SALES].trim());
float decodedDishPrice = Float.parseFloat(orderData[DISH_PRICE_INDEX_SALES].trim());
String completeStatus = orderData[STATUS_INDEX_SALES].trim();
float totalOrderCost = quantity * decodedDishPrice;

checkNameValidity(dishName);
Expand All @@ -291,16 +323,16 @@ && isValidQty(orderLine, quantity)
}

private static boolean isCompleteStatusAccurate(String orderLine, String completeStatus) {
if (completeStatus.equalsIgnoreCase("true")
|| completeStatus.equalsIgnoreCase("false")) {
if (completeStatus.equalsIgnoreCase(TRUE_STRING)
|| completeStatus.equalsIgnoreCase(FALSE_STRING)) {
return true;
}
ui.showToUser(ErrorMessages.INVALID_ORDER_STATUS + orderLine);
return false;
}

private static boolean isValidPrice(String orderLine, Float decodedDishPrice) {
if (decodedDishPrice >= 0) {
if (decodedDishPrice >= MIN_DISH_PRICE) {
return true;
}
ui.showToUser(ErrorMessages.INVALID_DISH_PRICE + orderLine);
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/seedu/cafectrl/storage/Encoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ public class Encoder {
private static final String DIVIDER = " | ";
private static final String INGREDIENT_DIVIDER = " - ";
private static final Logger logger = Logger.getLogger(CafeCtrl.class.getName());
private static final String LINE_BREAK = "\n";
private static final String EMPTY_STRING = "";
private static final String CARRIAGE_RETURN = "\r";
private static final String TWO_DECIMAL_PLACE_FORMAT = "%.2f";

//@@author Cazh1
/**
Expand All @@ -35,7 +39,9 @@ private static ArrayList<String> hashEncoding(ArrayList<String> stringArrayList)
String stringArrayListAsString = String.join(", ", stringArrayList).trim();

//The generated String has line breaks, this removes line breaks
String stringArrayListAsStringInOneLine = stringArrayListAsString.replace("\n", "").replace("\r", "");
String stringArrayListAsStringInOneLine = stringArrayListAsString
.replace(LINE_BREAK, EMPTY_STRING)
.replace(CARRIAGE_RETURN, EMPTY_STRING);

//Generate Hash from content
int stringArrayListHash = stringArrayListAsStringInOneLine.hashCode();
Expand Down Expand Up @@ -138,15 +144,19 @@ public static ArrayList<String> encodeSales(Sales sales) {
StringBuilder orderString = new StringBuilder();

//day of each orderList is index + 1
float orderedDishPrice = order.getOrderedDish().getPrice();
String orderedDishPriceString = String.format(TWO_DECIMAL_PLACE_FORMAT, orderedDishPrice);

orderString.append((day + 1) + DIVIDER);
orderString.append(order.getDishName() + DIVIDER);
orderString.append(order.getQuantity() + DIVIDER);
orderString.append(String.format("%.2f", order.getOrderedDish().getPrice()) + DIVIDER);
orderString.append(orderedDishPriceString + DIVIDER);
orderString.append(order.getIsComplete());
orderString.append(System.lineSeparator());
encodedList.add(String.valueOf(orderString));
logger.info("Encoded order: " + orderString);
}

if (day == sales.getDaysAccounted()) {
encodedList = encodeLastSalesDay(encodedList, orderList, day);
}
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/seedu/cafectrl/storage/FileManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/
public class FileManager {

public static final String USER_BASE_DIRECTORY = "user.dir";
private static Logger logger = Logger.getLogger(CafeCtrl.class.getName());
private final Ui ui;

Expand All @@ -35,7 +36,7 @@ public FileManager(Ui ui) {
*/
public ArrayList<String> readTextFile(String filePath) throws FileNotFoundException {
logger.info("Reading text file...");
String userWorkingDirectory = System.getProperty("user.dir");
String userWorkingDirectory = System.getProperty(USER_BASE_DIRECTORY);
Path dataFilePath = Paths.get(userWorkingDirectory, filePath);
File textFile = new File(String.valueOf(dataFilePath));
ArrayList<String> textLines = new ArrayList<>();
Expand All @@ -62,7 +63,7 @@ public void checkFileExists(String filePath) throws Exception {
throw new Exception(ErrorMessages.MISSING_FILEPATH);
}

String userWorkingDirectory = System.getProperty("user.dir");
String userWorkingDirectory = System.getProperty(USER_BASE_DIRECTORY);
Path dataFilePath = Paths.get(userWorkingDirectory, filePath);
Path dataFolderPath = dataFilePath.getParent();
File textFile = new File(String.valueOf(dataFilePath));
Expand Down
Loading

0 comments on commit 234c862

Please sign in to comment.