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 Local Development Environments Advanced Tooling Finishing TreeStory

João Matos
João Matos
4,967 Points

TreeStory Return error

All tests pass except the last one, it keeps saying that I need to present the treestory to the user, but it is presenting! What is wrong?

The output is:

Write the new story: Introduce a word for first prompt: Introduce a word for second prompt: Introduce a word for second prompt:

Your TreeStory:

Testing PASS_1 and then dweeb

com/teamtreehouse/Main.java
package com.teamtreehouse;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) {
    // write your code here
        try{
            Prompter pmp = new Prompter();
            String story = pmp.getStory();
            Template tmpl = new Template(story);
            String storyResult = pmp.run(tmpl);
            System.out.printf("%n%nYour TreeStory:%n%n%s", storyResult);
        } catch (IOException e) {
            System.out.println("enter story");
            e.printStackTrace();
        }
    }
}
com/teamtreehouse/Prompter.java
package com.teamtreehouse;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.Arrays;
import java.util.Scanner;

import static java.lang.System.exit;


public class Prompter {
    private BufferedReader mReader;
    private Set<String> mCensoredWords;
    private String mStory;

    public Prompter() throws IOException{
        mReader = new BufferedReader(new InputStreamReader(System.in));
        System.out.printf("Write the new story:   ");
        mStory = mReader.readLine();
        loadCensoredWords();
    }

    public String getStory() {
        return mStory;
    }

    private void loadCensoredWords() {
        mCensoredWords = new HashSet<String>();
        Path file = Paths.get("resources", "censored_words.txt");
        List<String> words = null;
        try {
            words = Files.readAllLines(file);
        } catch (IOException e) {
            System.out.println("Couldn't load censored words");
            e.printStackTrace();
        }
        mCensoredWords.addAll(words);
    }

    public String run(Template tmpl) {
        List<String> results = null;
        try {
            results = promptForWords(tmpl);
        } catch (IOException e) {
            System.out.println("There was a problem prompting for words");
            e.printStackTrace();
            exit(0);
        }
        String storyToPrint = tmpl.render(results);
        return storyToPrint;
    }

    /**
     * Prompts user for each of the blanks
     *
     * @param tmpl The compiled template
     * @return
     * @throws IOException
     */
    public List<String> promptForWords(Template tmpl) throws IOException {
        List<String> words = new ArrayList<String>();
        for (String phrase : tmpl.getPlaceHolders()) {
            String word = promptForWord(phrase);
            words.add(word);
        }
        return words;
    }

    /**
     * Prompts the user for the answer to the fill in the blank.  Value is guaranteed to be not in the censored words list.
     *
     * @param phrase The word that the user should be prompted.  eg: adjective, proper noun, name
     * @return What the user responded
     */
    public String promptForWord(String phrase) throws IOException{
        String entryWord = null;
        int flag = 0;

        try {
            while (flag == 0) {
                System.out.printf("Introduce a word for %s:   ", phrase);
                entryWord = mReader.readLine();
                if (!entryWord.isEmpty()) {
                    for (String word : mCensoredWords) {
                        if (entryWord.equals(word)){
                            flag = 0;
                        } else{
                            flag = 1;
                        }
                    }
                }
            }
            return entryWord;
        } catch(IOException e){
            System.out.printf("The word you entered is censored!%n");
            e = new IOException("@#$!");
            throw e;
        }

    }
}
pseudo-tests.md
#  This is essentially what I am testing 
1.  The user is prompted for a new string template (the one with the double underscores in it).

  a. The prompter class has a new method that prompts for the story template, and that method is called.

2.  The user is then prompted for each word that has been double underscored.

   a. The answer is checked to see if it is contained in the censored words.
      User is continually prompted until they enter a valid word

3.  The user is presented with the completed story

1 Answer

Christopher Augg
Christopher Augg
21,223 Points

João,

You will want to move the Prompter pmp = new Prompter(); out of the try/catch block. We should only be concerned with placing methods that throw exceptions within them. Also, you should declare String story before the try/catch block as well. We don't want story being local to the try/catch block only.

Your code is not meeting the requirements:

  1. The user is prompted for a new string template (the one with the double underscores in it).
    • a. The prompter class has a new method that prompts for the story template, and that method is called.

The getStory() method is only returning a String without prompting the user. The specifications need a method that is called that will prompt the user to enter in a new story template like:

Write a story with __ name __ __ adjective __ __ verb __ __ noun __ and press enter.

It also does not throw an IOException and would not require the try/catch block as written. Furthermore, the instructions provided in the starter code require that your System.out.printf() statement is moved to the run method within the Prompter class.

Here is an example outline with hints for your main class:

package com.teamtreehouse;

import java.io.IOException;

public class Main {

    public static void main(String[] args) {

        // Instantiate prompter object

        // Declare String Story and initialize it to null

        /* Prompt the user to provide a new story template by calling a newly 
         * implemented method in the Prompter class and assign it to story. 
         * Like the promptForWord method, it should throw the IOException.
         * Therefore, story should be surrounded with a try/catch block
         */

        Template tmpl = new Template(story);

        prompter.run(tmpl);

    }
}

Example for getStory: (I would rename this to promptForStory as it helps in understanding its true functionality)

public String promptForStory() throws IOException {

        // declare a String variable called result
        // print out a message to the console of what the user should enter.
        // call mReader.readLine(); and assign to result
        // return result
    }

I also see some issues with your promptForWord method as you are doing try/catches inside the method that are not required and I thought that I would introduce you to the contains() method. Here is an example for it as well:

public String promptForWord(String phrase) throws IOException {

        // We first print out a statement asking the user to enter a word.
        // phrase will be either adjective, verb, noun, etc.
        System.out.printf("Introduce a word for %s:  ", phrase);

        // We now prompt the user to type it in and assign it to a string
        String entryWord = mReader.readLine();

        // Now we continue to prompt the user while mCensoredWords 
        // contains the word that is censored. When the user enters
        // an appropriate word, the while loop breaks and returns entryWord
        while (mCensoredWords.contains(entryWord)){
            System.out.print("The word you entered is censored, try again!");
            entryWord = mReader.readLine();
        }
        return entryWord;
    }

I hope I covered enough to help you resolve your issues. Please let me know if I can help you further.

Regards,

Chris