Pragram 3: A Pattern Class for a ChatBot

For this assignment you will create a class that can be used to store a pattern and an associated response. This will allow for a wide range of patterns and responses to be added to a chatbot without writing Java code for each pattern. Instead, the pattern will simply be added to a text file read by the chatbot.

A pattern is a sentence that may contain one "wild card" phrase. A wild card phrase is indicated by enclosing the phrase in angle brackets "< ... >". The associated response is likewise a sentence that may contain one wild card phrase. The actual response genereated when a pattern matches is the response sentence with the phrase matching the wild card in the pattern substituted for the wild card (if any) in the response. For example, here is a possible pattern and response:

Pattern: Why do you <verb> those shoes?
Response: Why do you <verb> that shirt?
If the sentence "Why do you wear those shoes?" was tested against this pattern, it would generate the response "Why do you wear that shirt?" Likewise, if the sentence was "Why do you like those shoes?" the response would be "Why do you like that shirt?"

The pattern doesn't actually care what comes between the angle brackets (verb in the example above). What you put between the angle brackets is like a program comment. It is only for the human's looking at the text of the pattern. Likewise, the string between the angle brackets in the pattern does not even have to be the same as the string in the response. The above pattern would behave the same if it was:

Pattern: Why do you <wear> those shoes?
Response: Why do you <like> that shirt?

The Pattern Class

Your Pattern class will have a public constructor that takes two parameters that are both instances of the class Sentence. The first parameter will be the Sentence object representing the pattern to match. The second parameter will be the Sentence object representing the response.

The Pattern class will also have a public method, getResponse() that takes one parameter that is a String. The method should return the response, as a Sentence, to the message if the message matches the pattern of this Pattern object and return null otherwise.

Here is a template of the Pattern class.

The Sentence Class

For this assignment you will also need to add a method, matchWild(), to the class Sentence. Here is a link to the complete source for Sentence except for the missing matchWild() method. The method takes a String as a parameter, call it message, and returns the part of message that matches the wild card in "this" Sentence. If the message does not match the pattern of this sentence, then return null.

For this project, all sentences will be broken into three parts, start, middle, and end, plus a punctuation symbol. To simplify the code a bit, you can assume that sentences used as patterns for matching will obey the following restriction. Failure to adhere to this restriction may result in a pattern not matching as expected.

Any blank parts of a sentence precede any non-blank parts. For example, the sentence pattern "I'm hungry." could be represented as blank start and middle parts with "I'm hungry" as the end, or with a blank start part, "I'm" as the middle, and "hungry" as the end. As another example, "I hate <noun>." could have a blank start with "I hate" as the middle, or "I" as the start and "hate" as the middle. In both cases end would be the wildcard "<noun>". It would not be ok to have start be "I hate", middle be blank, and "<noun>" be the end.

Testing Your Pattern Class

The actual program you submit for this assignment is a program that can be used to test your Pattern class and the modifications to Sentence. Your program will repeatedly read a pattern and a message to respond to. The pattern consists of 6 lines of input, 3 for the pattern sentence, and 3 for the response sentence. The 3 lines for each consist of the start, middle, and end of the sentence. The punctuation symbol for the sentence is included in the end portion of the input. After the 6 lines for the pattern will be a one line message for which a response is desired. If the message matches the pattern, the program should print the appropriate response. If they do not match, the program should print "no match". This should continue until there is no more input. You should check for the end of input using Scanner.hasNext() before reading each group of 7 lines. You can assume that the input will have a multiple of 7 lines.

Although you are strongly encouraged to test your program using file redirection (it saves a lot of time and typing), you program should print a single prompt of "ready" at the very beginning. After that, the only output should be the matched responses or "no match".

Sample Execution and Sample Solution

There is a sample solution in .../hw3Solution.jar. You run the program by typing:
java -jar hw3Solution.jar
Here is a sample execution. To help you understand the output below, I have put the computer's output in BOLD.
os-prompt% java -jar hw3Solution.jar
ready
Do you
<verb>
apples?
No. I do not
<verb>
apples.
Do you like apples?
No. I do not like apples.
Do you
like
<noun>?
Yes. I
like
<noun>.
Do you like to swim?
Yes. I like to swim.


Hello.


Hi.
Hello.
Hi.
<noun>
is
beautiful.
What about
<noun>
do you think is beautiful?
The sky is beautiful.
What about the sky do you think is beautiful?
I
like
<noun>.
<noun>
is
nice.
I like living in Santa Cruz.
Living in Santa Cruz is nice.
os-prompt%
Notice that just because there is a wild card in the pattern sentence, there does not need to be one in the response sentence.

As indicated before, I would never actually type all of the above in to test my program. I would instead put the input into (also found in hw3Test1.txt) a file and use redirection. Doing that for the above input would give the following execution:

os-prompt%java -jar hw3Solution.jar < hw3Test1.txt
ready
No. I do not like apples.
Yes. I like to swim.
Hi.
What about the sky do you think is beautiful?
Living in Santa Cruz is nice.
If your input file has any extra lines at the end you will see output like this:
ready
No. I do not like apples.
Yes. I like to swim.
Hi.
What about the sky do you think is beautiful?
Living in Santa Cruz is nice.
Exception in thread "main" java.util.NoSuchElementException: No line found
        at java.util.Scanner.nextLine(Scanner.java:1471)
        at hw3.Main.readPattern(Main.java:60)
        at hw3.Main.main(Main.java:20)
If that happens, just try deleting the blank lines from the end of the input file.

Getting Started

I recommend that you first get the program to work assuming there are no wild cards. For that you can use the already existing method Sentence.exactMatch(String) to compare input strings with the pattern. If there is an exact match, have getResponse() return the full response sentence (again assuming there is no wild card that needs replacing).

When that is working, write the matchWild() method in Sentence and TEST IT. Modify your exact match program from the first step to print just the wild card phrase or "no match".

Once you have the matchWild() working, write a private method in Pattern called buildResponse() that takes two parameters, a String, call it wild, representing the part of a sentence that matched a wild card and a Sentence, call it response, possibly containing a wild card. The method will return a new Sentence that has wild substituted for the wild part, if any, of response.

Now you only need to modify getResponse() to use the matchWild() and buildResponse() methods to test for a match and return either null (no match) or the result of buildResponse().

At this point, the Sentence and Pattern classes have all of the required functionality and you just need to once again modify your main program to loop calling getResponse() for each input line and printing the proper output ("no match" or the actual response).

Correctness Points

20 points - compiles without errors and is a serious attempt at a solution

10 points - correctly handles some wild card pattern

20 points - 4 points for each correctly handled pattern from hw3Test1.txt modified in content but not form to preclude simple string matching solutions. E.g. the first pattern might be changed to "I <verb> programming." with a response of "I <verb> programming too." and a test message of "I like programming." which generates the response "I like programming too." Notice this has the same form as the first pattern from the example run, namely a non-empty start, a wildcard middle, and a non-empty end. Make sure you also test on sample sentences that do NOT match the pattern. For example, "A nice way to make a living is programming." should not match. It would if your code failed to properly check that the starting sequences matched. An erroneous program might match and respond "I nice way to make a living is programming too."