Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Java Java Objects Delivering the MVP Applying a Discount Code

Alex Blake
Alex Blake
640 Points

Infinite Error Loop Treehouse Validator

This is driving me insane! Treehouse validator says "Great Job! Task 1 is validated". Then, when you complete task two it says "Oops! It looks like Task 1 is no longer passing."

I understand that there is code that can affect both tasks, but:

  1. Your validator tool should explain terms of validation better.
  2. It does not validate both tasks together. Therefore not allowing you to pass, or giving you any specific errors.
  3. It seems that both individual Tasks are fine on their own. No "preview" problems at all.

How can I get pass this?

Order.java
public class Order {
  private String itemName;
  private int priceInCents;
  private String discountCode;

  public Order(String itemName, int priceInCents) {
    this.itemName = itemName;
    this.priceInCents = priceInCents;
  }

  public String getItemName() {
    return itemName;
  }

  public int getPriceInCents() {
    return priceInCents;
  }

  public String getDiscountCode() {
    return discountCode;
  }

  public void applyDiscountCode(String discountCode) {
    this.discountCode = normalizeDiscountCode(discountCode);
  }

  private String normalizeDiscountCode (String discountCode) {
    // Check if letter
    for(int c=0 ; c < discountCode.length() ; c++)
    {
     // Check if character is valid
     char myLetter = discountCode.charAt(c);
      if (!Character.isLetter(myLetter) || myLetter != '$')
      {
        throw new IllegalArgumentException("Invalid discount code.");
      }
    }
   return discountCode.toUpperCase();
  }
}
Example.java
public class Example {

  public static void main(String[] args) {
    // This is here just for example use cases.

    Order order = new Order(
            "Yoda PEZ Dispenser",
            600);

    // These are valid.  They are letters and the $ character only
    order.applyDiscountCode("abc");
    order.getDiscountCode(); // ABC

    order.applyDiscountCode("$ale");
    order.getDiscountCode(); // $ALE


    try {
      // This will throw an exception because it contains numbers
      order.applyDiscountCode("ABC123");
    } catch (IllegalArgumentException iae) {
      System.out.println(iae.getMessage());  // Prints "Invalid discount code"
    }
    try {
      // This will throw as well, because it contains a symbol.
      order.applyDiscountCode("w@w");
    }catch (IllegalArgumentException iae) {
      System.out.println(iae.getMessage());  // Prints "Invalid discount code"
    }

  }
}

1 Answer

andren
andren
28,558 Points

The code validator for these challenge is indeed somewhat broken. if there is any syntax error or exception thrown that is not expected then it will always claim there is something wrong with task 1, regardless of what task the erroneous code was added in. The reason why returning to task 1 allows you to pass it is that when you return to a previous task the challenge workspace also reverts your code to the state that it was in during your work on that task, which in this case means it temporarily removes the code that is actually causing an issue. Then it restores it when you move back to task 2.

Anyway enough talk about the validator itself, there is in fact an issue with your solution, there is a logic error in your if statement that causes it to mark all characters as invalid. It's an extremely common logic error for this challenge.

Your if statement states that if the char is not a letter or it is not the $ symbol then it should throw an exception. Let's go though what that will actually result in with some sample input.

Let's say the char is the letter A. A is a letter, so the first condition is false, but A is not the $ symbol, so the second condition is true. With the || (OR) operator if either condition is true it will return true. So in this case an exception will be thrown. Even though A is a valid letter. The same happens for $, while it is the $ symbol it is not a letter so one of the conditions is still true.

Basically since a character cannot be both a letter and the $ symbol at the same time there is nothing that will actually pass through your if statement.

This issue can be solved in a few ways, but the simplest is just to change the || (OR) operator into the && (AND) operator. That will only return true if both of the conditions are true, which is the behavior you actually want.

Alex Blake
Alex Blake
640 Points

Thanks for detailed feedback! When you stare at the code for a while you start to miss things like this :)