Skip to content
This repository was archived by the owner on Dec 11, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions src/main/java/com/google/sps/data/Meal.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package com.google.sps.data;

import java.util.ArrayList;
import java.util.List;

public class Meal {
private final Long id;
Expand Down Expand Up @@ -50,4 +51,28 @@ public ArrayList<String> getIngredients() {
public String getType() {
return this.type;
}

/**
* Counts the number of keywords that are matching in recipe.
* @param params list of strings with keywords, that describe search request.
* @return amount of occurrences of keywords from params in this meal.
*/
public int getFrequency(List<String> params) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'd suggest adding a unit test for this method in a MealTest.java file.
A test that would check the exact number returned by this method for some instances.

int frequency = 0;
for (String param : params) {
if (title.contains(param) ||
description.contains(param) ||
type.contains(param)) {
frequency++;
continue;
}
for (String ingredient : ingredients) {
if (ingredient.contains(param)) {
frequency++;
continue;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This continue will skip the remaining part of the inner loop and go to the next iteration. However, there's nothing happening after the continue, therefore this keyword does nothing (FWIU). This continue doesn't really do anything.
As a result, if a meal has 3 ingredients:

  • chocolate flakes
  • chocolate milk
  • chocolate whatever

then as long as the word "chocolate" is not in the title / description / type, returned frequency will be 3. However, if the title does include the word "chocolate", we'll return early with frequency == 1. It looks like a tiny bug.

I believe you may have meant to break the outer loop instead. I think the simplest solution is to extract the second for loop to a method, e.g. bool doesKeywordAppearInIngredients(String keyword). Then you could drop all those continue keywords from this method and just have a single if.

}
}
}
return frequency;
}
}
34 changes: 13 additions & 21 deletions src/main/java/com/google/sps/servlets/MealServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.TreeMap;
import java.util.stream.Collectors;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
Expand Down Expand Up @@ -97,9 +98,19 @@ private void getMealList(HttpServletRequest request, HttpServletResponse respons
// Every object Meal adds if it contains at least one keyword in at least one field
// (type, title, description, ingredients).
List<Meal> searchedMeal = new ArrayList<>();
TreeMap<Integer, List<Meal>> sortedMeal = new TreeMap<>();
for (Meal meal : meals) {
if (isResultOfSearch(meal, params)) {
searchedMeal.add(meal);
int frequency = meal.getFrequency(params);
if (frequency > 0) {
sortedMeal.putIfAbsent(frequency, new ArrayList<>());
List<Meal> list = sortedMeal.get(frequency);
list.add(meal);
}
}
for (int key : sortedMeal.descendingKeySet()) {
List<Meal> list = sortedMeal.get(key);
if (list != null) {
searchedMeal.addAll(list);
}
}
response.setContentType("application/json");
Expand Down Expand Up @@ -187,25 +198,6 @@ private Meal pickRandomMeal(List<Meal> mealList) {
return (Meal)mealList.get(index);
}

private Boolean isResultOfSearch(Meal meal, List<String> params) {
for (String param : params) {
if (meal.getTitle().contains(param)) {
return true;
}
if (meal.getDescription().contains(param)) {
return true;
}
if (meal.getType().contains(param)) {
return true;
}
for (String ingredient : meal.getIngredients()) {
if (ingredient.contains(param)) {
return true;
}
}
}
return false;
}
private String getParameter(HttpServletRequest request, String name, String defaultValue) {
String value = request.getParameter(name);
if (value == null) {
Expand Down
4 changes: 3 additions & 1 deletion src/test/java/com/google/sps/MealServletTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,11 @@ public void getMealListTest() throws IOException, ServletException {

// Get a list of objects Meal from datastore by search request "potato onion".
// (Check if meal that has both occurrences of searching keywords would be added only once).
// Expected result: a JSON String of list with one object MEAL_1.
// Expected result: a JSON String of list with objects in order: MEAL_1, PIZZA_2.
@Test
public void getMealListWithTwoKeyWordsTest() throws IOException, ServletException {
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
ds.put(DataConverter.createMealEntity(PIZZA_2));
ds.put(DataConverter.createMealEntity(MEAL_1));
ds.put(DataConverter.createMealEntity(MEAL_2));

Expand All @@ -188,6 +189,7 @@ public void getMealListWithTwoKeyWordsTest() throws IOException, ServletExceptio

List<Meal> meals = new ArrayList<>();
meals.add(MEAL_1);
meals.add(PIZZA_2);
Gson gson = new Gson();
String expected = gson.toJson(meals);
String actual = response.getContentAsString().trim();
Expand Down