diff --git a/src/main/java/seedu/address/model/property/Price.java b/src/main/java/seedu/address/model/property/Price.java index d955329f359..24c08b432d9 100644 --- a/src/main/java/seedu/address/model/property/Price.java +++ b/src/main/java/seedu/address/model/property/Price.java @@ -1,5 +1,6 @@ package seedu.address.model.property; +import static java.util.Objects.isNull; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.AppUtil.checkArgument; @@ -35,6 +36,16 @@ public static boolean isValidPrice(String test) { return test.matches(VALIDATION_REGEX); } + /** + * Returns true if the other price is lower or equal this price + * + * @param other the other budget being compared + * @return whether the other budget is lower or equal to this budget + */ + public boolean isInRangePrice(Price other) { + return isNull(other) || amount <= other.amount; + } + @Override public String toString() { return "$" + value; diff --git a/src/main/java/seedu/address/model/property/PriceAndTagsInRangePredicate.java b/src/main/java/seedu/address/model/property/PriceAndTagsInRangePredicate.java new file mode 100644 index 00000000000..59748323195 --- /dev/null +++ b/src/main/java/seedu/address/model/property/PriceAndTagsInRangePredicate.java @@ -0,0 +1,54 @@ +package seedu.address.model.property; + +import java.util.Set; +import java.util.function.Predicate; + +import seedu.address.commons.util.ToStringBuilder; +import seedu.address.model.tag.Tag; + +/** + * Tests that a {@code Property}'s {@code Price} and/or {@code Tags} are in range of the specified price and/or tags. + */ +public class PriceAndTagsInRangePredicate implements Predicate { + private final Price price; + private final Set tags; + + /** + * Constructs a {@code PriceAndTagsInRangePredicate}. + * + * @param price the specified price if any + * @param tags the specified tags if any + */ + public PriceAndTagsInRangePredicate(Price price, Set tags) { + this.price = price; + this.tags = tags; + } + + @Override + public boolean test(Property property) { + return property.getTags().containsAll(tags) && property.getPrice().isInRangePrice(price); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof PriceAndTagsInRangePredicate)) { + return false; + } + + PriceAndTagsInRangePredicate otherBudgetAndTagsInRangePredicate = (PriceAndTagsInRangePredicate) other; + return price.equals(otherBudgetAndTagsInRangePredicate.price) + && tags.equals(otherBudgetAndTagsInRangePredicate.tags); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("price", price) + .add("tags", tags).toString(); + } +} diff --git a/src/test/java/seedu/address/model/property/PriceAndTagsInRangePredicateTest.java b/src/test/java/seedu/address/model/property/PriceAndTagsInRangePredicateTest.java new file mode 100644 index 00000000000..b356af90961 --- /dev/null +++ b/src/test/java/seedu/address/model/property/PriceAndTagsInRangePredicateTest.java @@ -0,0 +1,195 @@ +package seedu.address.model.property; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.HashSet; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import seedu.address.model.tag.Tag; +import seedu.address.testutil.PropertyBuilder; + +public class PriceAndTagsInRangePredicateTest { + @Test + public void equals() { + Price firstPrice = new Price("1000000"); + Price secondPrice = new Price("2000000"); + + Tag firstTag = new Tag("sunny"); + Tag secondTag = new Tag("bright"); + + Set firstTags = new HashSet<>(); + Set secondTags = new HashSet<>(); + + firstTags.add(firstTag); + secondTags.add(secondTag); + + PriceAndTagsInRangePredicate firstPredicate = new PriceAndTagsInRangePredicate(firstPrice, firstTags); + PriceAndTagsInRangePredicate secondPredicate = new PriceAndTagsInRangePredicate(secondPrice, firstTags); + PriceAndTagsInRangePredicate thirdPredicate = new PriceAndTagsInRangePredicate(firstPrice, secondTags); + PriceAndTagsInRangePredicate fourthPredicate = new PriceAndTagsInRangePredicate(secondPrice, secondTags); + + // same object -> returns true + assertTrue(firstPredicate.equals(firstPredicate)); + + // same values -> returns true + PriceAndTagsInRangePredicate firstPredicateCopy = new PriceAndTagsInRangePredicate(firstPrice, firstTags); + assertTrue(firstPredicate.equals(firstPredicateCopy)); + + // different types -> returns false + assertFalse(firstPredicate.equals(1)); + + // null -> returns false + assertFalse(firstPredicate.equals(null)); + + // different budget -> returns false + assertFalse(firstPredicate.equals(secondPredicate)); + + // different tags -> return false + assertFalse(firstPredicate.equals(thirdPredicate)); + + // different tags and budget -> return false + assertFalse(firstPredicate.equals(fourthPredicate)); + } + + @Test + public void test_budgetAndTagsInRangeReturnTrue() { + String lowPriceString = "100000"; + String highPriceString = "1000000000"; + + Price highPrice = new Price(highPriceString); + + String firstTagString = "sunny"; + String secondTagString = "bright"; + + Tag firstTag = new Tag(firstTagString); + Tag secondTag = new Tag(secondTagString); + + Set emptyTags = new HashSet<>(); + Set singleTags = new HashSet<>(); + Set someTags = new HashSet<>(); + + singleTags.add(firstTag); + someTags.add(firstTag); + someTags.add(secondTag); + + // Same price with empty tag + PriceAndTagsInRangePredicate predicate = new PriceAndTagsInRangePredicate(highPrice, emptyTags); + assertTrue(predicate.test(new PropertyBuilder().withPrice(highPriceString).build())); + assertTrue(predicate.test(new PropertyBuilder() + .withPrice(highPriceString).withTags(firstTagString).build())); + + // Higher price with empty tag + assertTrue(predicate.test(new PropertyBuilder().withPrice(lowPriceString).build())); + assertTrue(predicate.test(new PropertyBuilder().withPrice(lowPriceString).withTags(firstTagString).build())); + + + // No price with single tag + predicate = new PriceAndTagsInRangePredicate(null, singleTags); + assertTrue(predicate.test(new PropertyBuilder().withTags(firstTagString).build())); + assertTrue(predicate.test(new PropertyBuilder().withTags(firstTagString, secondTagString).build())); + + // Same price with single tag + predicate = new PriceAndTagsInRangePredicate(highPrice, singleTags); + assertTrue(predicate.test(new PropertyBuilder() + .withPrice(highPriceString).withTags(firstTagString).build())); + assertTrue(predicate.test(new PropertyBuilder() + .withPrice(highPriceString).withTags(firstTagString, secondTagString).build())); + + // Higher price with single tag + assertTrue(predicate.test(new PropertyBuilder().withPrice(lowPriceString).withTags(firstTagString).build())); + assertTrue(predicate.test(new PropertyBuilder() + .withPrice(lowPriceString).withTags(firstTagString, secondTagString).build())); + + // No price with multiple tags + predicate = new PriceAndTagsInRangePredicate(null, someTags); + assertTrue(predicate.test(new PropertyBuilder().withTags(firstTagString, secondTagString).build())); + + // Same price with multiple tags + predicate = new PriceAndTagsInRangePredicate(highPrice, someTags); + assertTrue(predicate.test(new PropertyBuilder() + .withPrice(highPriceString).withTags(firstTagString, secondTagString).build())); + + // Higher price with multiple tags + assertTrue(predicate.test(new PropertyBuilder() + .withPrice(lowPriceString).withTags(firstTagString, secondTagString).build())); + } + + @Test + public void test_budgetAndTagsInRangeReturnFalse() { + String lowPriceString = "100000"; + String highPriceString = "1000000000"; + + Price lowPrice = new Price(lowPriceString); + + String firstTagString = "sunny"; + String secondTagString = "bright"; + String thirdTagString = "square"; + + Tag firstTag = new Tag(firstTagString); + Tag secondTag = new Tag(secondTagString); + + Set emptyTags = new HashSet<>(); + Set singleTags = new HashSet<>(); + Set someTags = new HashSet<>(); + + singleTags.add(firstTag); + someTags.add(firstTag); + someTags.add(secondTag); + + // Lower price with empty tag + PriceAndTagsInRangePredicate predicate = new PriceAndTagsInRangePredicate(lowPrice, emptyTags); + assertFalse(predicate.test(new PropertyBuilder().withPrice(highPriceString).build())); + assertFalse(predicate.test(new PropertyBuilder() + .withPrice(highPriceString).withTags(firstTagString).build())); + + // No price with single tag + predicate = new PriceAndTagsInRangePredicate(null, singleTags); + assertFalse(predicate.test(new PropertyBuilder().withTags(secondTagString).build())); + + // Same price with single tag + predicate = new PriceAndTagsInRangePredicate(lowPrice, singleTags); + assertFalse(predicate.test(new PropertyBuilder().withPrice(lowPriceString).build())); + assertFalse(predicate.test(new PropertyBuilder() + .withPrice(lowPriceString).withTags(secondTagString).build())); + + // Lower price with single tag + assertFalse(predicate.test(new PropertyBuilder().withPrice(highPriceString).build())); + assertFalse(predicate.test(new PropertyBuilder() + .withPrice(highPriceString).withTags(firstTagString).build())); + assertFalse(predicate.test(new PropertyBuilder() + .withPrice(highPriceString).withTags(secondTagString).build())); + assertFalse(predicate.test(new PropertyBuilder() + .withPrice(highPriceString).withTags(firstTagString, secondTagString).build())); + + // No price with multiple tags + predicate = new PriceAndTagsInRangePredicate(null, someTags); + assertFalse(predicate.test(new PropertyBuilder().build())); + assertFalse(predicate.test(new PropertyBuilder().withTags(firstTagString).build())); + assertFalse(predicate.test(new PropertyBuilder() + .withTags(firstTagString, thirdTagString).build())); + + // Same price with multiple tags + predicate = new PriceAndTagsInRangePredicate(lowPrice, someTags); + assertFalse(predicate.test(new PropertyBuilder().withPrice(lowPriceString).build())); + assertFalse(predicate.test(new PropertyBuilder() + .withPrice(lowPriceString).withTags(firstTagString).build())); + assertFalse(predicate.test(new PropertyBuilder() + .withPrice(lowPriceString).withTags(thirdTagString).build())); + assertFalse(predicate.test(new PropertyBuilder() + .withPrice(lowPriceString).withTags(firstTagString, thirdTagString).build())); + + // Lower price with multiple tags + predicate = new PriceAndTagsInRangePredicate(lowPrice, someTags); + assertFalse(predicate.test(new PropertyBuilder().withPrice(highPriceString).build())); + assertFalse(predicate.test(new PropertyBuilder() + .withPrice(highPriceString).withTags(firstTagString).build())); + assertFalse(predicate.test(new PropertyBuilder() + .withPrice(highPriceString).withTags(firstTagString, secondTagString).build())); + assertFalse(predicate.test(new PropertyBuilder() + .withPrice(highPriceString).withTags(firstTagString, thirdTagString).build())); + + } +} diff --git a/src/test/java/seedu/address/model/property/PriceTest.java b/src/test/java/seedu/address/model/property/PriceTest.java index f864ed210e0..6724cd95dbe 100644 --- a/src/test/java/seedu/address/model/property/PriceTest.java +++ b/src/test/java/seedu/address/model/property/PriceTest.java @@ -47,6 +47,21 @@ public void isValidPrice() { assertTrue(Price.isValidPrice(LONG_VALID_PRICE)); // long budget } + @Test + public void isInRangeBudget() { + // null price + assertTrue(new Price(VALID_PRICE).isInRangePrice(null)); + + // smaller price + assertFalse(new Price(LONG_VALID_PRICE).isInRangePrice(new Price(VALID_PRICE))); + + // same price + assertTrue(new Price(VALID_PRICE).isInRangePrice(new Price(VALID_PRICE))); + + // bigger price + assertTrue(new Price(VALID_PRICE).isInRangePrice(new Price(LONG_VALID_PRICE))); + } + @Test public void equals() { Price price = new Price(VALID_PRICE);