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

How do I prompt for the completed TreeStory?

Hi there, I'm one step away from completing this challenge and the necessary treestory code. The only todo I have left is printing out the completed TreeStory. But I just can't seem to figure out how to do it. This is pretty important, so could someone please help?? Thanks!

com/teamtreehouse/Main.java
// After you've completed the TODOs locally paste Main.java here
com/teamtreehouse/Prompter.java
// After you've completed the TODOs locally paste Prompter.java here
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

3 Answers

Kevin Faust
Kevin Faust
15,353 Points

Hey Gabriel,

I believe this is the solution you are looking for:

Since the last method we call is the run() method in our main file, we should print out our results in that method. lets take a look:

public void 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();
            System.exit(0);
        }
        // Print out the results that were gathered here by rendering the template
        System.out.println(tmpl.render(results));
    }

By the last line, we have gotten our list of user input variables/words. As you can see on the last line, we call the render() method and pass in our list of words.

public String render(List<String> values) {
        // String.format accepts the templates and Object... (a variable amount of objects)
        return String.format(mCompiled, values.toArray());
    }

the render method takes that list, converts it to an array, and each %s in our mCompiled string gets replaced with the user input variable. we now have our completed treestory

im not sure if this was the answer you were looking for. If you still need help, id be happy to help!

Happy coding and all the best,

Kevin

Hi Kevin, Thanks a lot that was really helpful. Just one thing though. My code looks a bit different from your's, but as long as its working I don't think that matters. Anyway, I'm not sure where to put the code that you gave me. Could you perhaps post it in a file, so I can see where it is supposed to rest in relation to my other code? Thanks!

Omg I think I got it...I'll keep you posted.

Hi Kevin, my code works beautifully in my IntelliJ, but the challenge doesn't think I did so hot, here is my code, could you check it for me? Thanks!

HERE IS MY PROMPTER.JAVA CODE

package com.teamtreehouse;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


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

    public Prompter() {
        mReader = new BufferedReader(new InputStreamReader(System.in));
        loadCensoredWords();
    }

    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 void 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();
            System.exit(0);
        }

        System.out.println(tmpl.render(results));

    }


    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;
    }



    public String promptForWord(String phrase) throws IOException {
        String word = "";
        do {
            System.out.printf("Please write a(n) %s:", phrase);
            word = mReader.readLine();

            if (this.mCensoredWords.contains(word)) {
                System.out.println(" This is a censored word! Try again! ");
            }

        } while (mCensoredWords.contains(word));

        return word;
    }
}

THEN HERE IS MY MAIN.JAVA CODE

package com.teamtreehouse;

import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        Prompter prompter = new Prompter();
        System.out.println("Your TreeStory:\n-----\n");
        String story = "Thanks __name__ for helping me out.  You are really a __adjective__ __noun__ and I owe you a __noun__.";
        System.out.printf("%s%n", story);
        Template tmpl = new Template(story);
        prompter.run(tmpl);

    }
}
Kevin Faust
Kevin Faust
15,353 Points

Hey Gabriel,

I actually had a lot of question on this the first I did this also. It worked perfectly in the ide but the code challenge refused to make it work. However there are two things I will point out. First is that in the promptForWord() method, what if the user inputted a word that was capitalized? what if there were spaces before the word? It would pass and we cant let that happen. Simply use the toLowerCase() and trim() method. There is also a bit of a cleaner way to do this. Instead of using a do-while loop with an if statement mixed in there, we could just use a while statement.

   public String promptForWord(String phrase) throws IOException {
        System.out.printf("Please enter your word for %s: %n", phrase);
        String entryWord = mReader.readLine();

        while (mCensoredWords.contains(entryWord.toLowerCase().trim())) {
            System.out.printf("Be nice, please try another word for %s. %n", phrase);
            entryWord = mReader.readLine();
        }

        return entryWord.trim();
    }

My code is a bit different but the concept remains the same. Ask for a word, take an input, and then run the while statement. In the contains() method, we take the word, change it to lower case and then trim the white space. If you can see in our censored_words.txt file, all the words are lower case. If you simply added the lower case and trim method to your code, yours would work perfectly fine as well.

The next problem is in your main file. You are actually supposed to use your own story instead of that default story. Instead of this:

String story = "Thanks __name__ for helping me out.  You are really a __adjective__ __noun__ and I owe you a __noun__.";

you want to take an input from the user that has those underscore variables inside it. if they dont put any of those underscore variables then we will just return their input. Once again I will post my code and explain it and you can apply it to your code:

   public static void main(String[] args) {
        // write your code here
        BufferedReader mReader = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("Make a story! Write a fill in the blank story with an underscore on each side of the variable like _noun/adjective/etc_");
        // Instantiate a new Prompter object and prompt for the story template
        Prompter prompter = new Prompter();
        String story = null;
        try {
            story = prompter.promptForStory();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        Template tmpl = new Template(story);
        prompter.run(tmpl);
    }

Let's break down what I got. So first we set up our buffered reader input. We then print out what we want the user should do. In my case i told them to write a story with those underscore variables. I then created the prompter object because now we will have to use the prompter. first off i make our story string to null for a placeholder.

it then calls a method inside the prompter class:

 public String promptForStory() throws IOException {
        return mReader.readLine();
    }

this just takes the input from the user. i put the method in here otherwise our main file would be all messy. So we take an input and store that as our new story string. and then we proceed to creating a new template with it and then running our code in the end

I hope this solves your problems and you now have a better understanding of what we do.

Even for me this was challenging at first because the instructions weren't the clearest

Happy coding and best of luck,

Kevin

Hey again Kevin, ok, I'm so sorry to keep heckling you like this, but those changes just didn't work. Do you have a full file of all your code? My code works, but your's is a bit cleaner, and I think I'll transfer my stuff the way you have it. Anyway, if you could just post an entire Main and Prompter, I think we might just be able to wrap this up. Sorry about this overylong discussion, Thanks! ;(

Kevin Faust
Kevin Faust
15,353 Points

Hey Gabriel,

haha no problem. I know how challenging this is.

Here's my code:

Prompter:

package com.teamtreehouse;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


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

    public Prompter() {
        mReader = new BufferedReader(new InputStreamReader(System.in));
        loadCensoredWords();
    }

    public String promptForStory() throws IOException {
        return mReader.readLine();
    }

    private void loadCensoredWords() {
        mCensoredWords = new HashSet<>();
        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 void 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();
            System.exit(0);
        }
        // Print out the results that were gathered here by rendering the template
        System.out.println(tmpl.render(results));
    }


    public List<String> promptForWords(Template tmpl) throws IOException {
        List<String> words = new ArrayList<>();
        for (String phrase : tmpl.getPlaceHolders()) {
            String word = promptForWord(phrase);
            words.add(word);
        }
        return words;
    }


    public String promptForWord(String phrase) throws IOException {
        System.out.printf("Please enter your word for %s: %n", phrase);
        String entryWord = mReader.readLine();

        while (mCensoredWords.contains(entryWord.toLowerCase().trim())) {
            System.out.printf("Be nice, please try another word for %s. %n", phrase);
            entryWord = mReader.readLine();
        }

        return entryWord.trim();
    }
}

Main:

package com.teamtreehouse;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) {
        BufferedReader mReader = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("Make a story! Write a fill in the blank story with an underscore on each side of the variable like _noun/adjective/etc_");
        Prompter prompter = new Prompter();
        String story = null;
        try {
            story = prompter.promptForStory();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        Template tmpl = new Template(story);
        prompter.run(tmpl);
    }
}

Hope you get it working now :)

Hey Kev, So this line is not letting me type anything in: System.out.println("Make a story! Write a fill in the blank story with an underscore on each side of the variable like noun/adjective/etc");

I copied your code in, but this was the only thing that appeared in the console. Nothing about entering a name or noun.
Kevin Faust
Kevin Faust
15,353 Points

Hey Gabriel,

I think I understand your question. Correct me if im wrong. what's happening for you is that only this line is appearing for you:

Make a story! Write a fill in the blank story with an underscore on each side of the variable like _noun/adjective/etc_

and im guessing your confused as to why it's not prompting for any variables.

The reason is because we are prompting for a story. Not the variable. You have to write a sentence for example like this:

Hello __ noun ___ i am feeling __ adjective __ today

Once you type in a sentence like this, it will then proceed to prompt you for those variables you put in. those variable placeholder texts must have a double underscore on each side. Remember, we removed this line:

String story = "Thanks __name__ for helping me out.  You are really a __adjective__ __noun__ and I owe you a __noun__.";

When we had that line, it would automatically prompt us for name, adjective, noun, etc because we already had our story string. But now we are prompting the user for one. as a result we are writing our own "story"

If this was indeed your question, everything should be working now. Keep me informed whether or not you get it working!

Kevin

Hey Kev, so I add this line: String story = "Thanks name for helping me out. You are really a adjective noun and I owe you a noun.";

But then this line has a red squiggly under it saying it's already defined in the scope: String story = null;
????????

Hey Kevin, So let me reword this comment, I added this line with double underscores String story = "Thanks name for helping me out. You are really a adjective noun and I owe you a noun.";

But it doesn't like that. It says there's an error here on this line:   String story = null;
Not sure
Kevin Faust
Kevin Faust
15,353 Points

Hey Gabe,

Ah you misread what I wrote. I didn't mean for you to add that line. I was simple referring to it when we used to have it *Remember, we removed this line: String story = "Thanks __ name __ for helping me out. You are really a __ adjective __ __ noun __ and I owe you a __ noun __."; *

you can try rereading what i wrote

This is how your main file should look like:

    public static void main(String[] args) {
        BufferedReader mReader = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("Make a story! Write a fill in the blank story with an underscore on each side of the variable like _noun/adjective/etc_");
        Prompter prompter = new Prompter();
        String story = null;
        try {
            story = prompter.promptForStory();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        Template tmpl = new Template(story);
        prompter.run(tmpl);
    }

Our story string should be null in our main file. It should not have any text. When we run the program, you will input your own story. You can type in something like this:

Hello __ noun ___ i am feeling __ adjective __ today

and what this will do is then prompt you for those doubleunderscore variables.

Ok im doing that right now. So I physically have to type in the console Hello __ noun ___ i am feeling __ adjective __ today or something like it then it will prompt me for a noun?

Kevin Faust
Kevin Faust
15,353 Points

Yep. it will prompt you for whatever is in between those double underscores

OMG My IDE loved it and better yet....So did the Challenge! All i can say is thanks so very ever so much, and that was easily the hardest challenge ever!

Kevin Faust
Kevin Faust
15,353 Points

Yay glad we got it working :)

From the new code that we saw to the wording of the questions, I agree that this was the hardest challenge in the track.

Happy coding and best of luck as you continue through the track,

Kevin