- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Set;
- import java.util.Collections;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.Random;
- /**
- * The responder class represents a response generator object.
- * It is used to generate an automatic response, based on specified input.
- * Input is presented to the responder as a set of words, and based on those
- * words the responder will generate a String that represents the response.
- *
- * Internally, the reponder uses a HashMap to associate words with response
- * strings and a list of default responses. If any of the input words is found
- * in the HashMap, the corresponding response is returned. If none of the input
- * words is recognized, one of the default responses is randomly chosen.
- *
- * @version 1.0
- * @author Michael Kolling and David J. Barnes
- */
- public class Responder
- {
- // Used to map key words to responses.
- private HashMap<String, String> responseMap;
- // Default responses to use if we don't recognise a word.
- private ArrayList<String> defaultResponses;
- private HashMap<String, String> questionWordResponses;
- private Random randomGenerator;
- private HashSet<String> comboKeys;
- /**
- * Construct a Responder
- */
- public Responder()
- {
- responseMap = new HashMap<String, String>();
- defaultResponses = new ArrayList<String>();
- comboKeys = new HashSet<String>(); //Here we make a new HashSet to contain the *single* words which are also included in *combinations*
- questionWordResponses = new HashMap<String, String>(); //here we make a new HashMap to contain the responses to the question words (who, what, why, etc)
- fillResponseMaps();//we fill all of them in the same method
- fillDefaultResponses();
- randomGenerator = new Random();
- }
- /**
- * Generate a response from a given set of input words.
- *
- * @param words A set of words entered by the user
- * @return A string that should be displayed as the response
- */
- public String generateResponse(ArrayList<String> words, String trueInput)
- {
- /* THIS IS THE "ARE YOU A PERSON" SECTION*/
- String response = null;
- String personquery = trueInput;
- if (personquery.contains("are you a person?"))
- {
- response = "Of course I am a person.";
- return response;
- }
- /* THIS IS THE SINGLE-WORD RESPONSE SECTION, WITH A LITTLE CODE FOR COMBINATION OF TWO WORDS*/
- //first we check for specific responses
- Iterator<String> it = words.iterator();
- Set<String> keys = responseMap.keySet();
- ArrayList<String> hits = new ArrayList<String>();//"hits" is a list of all the words which match our keys
- while(it.hasNext()) {
- String word = it.next();
- for(String s : keys){
- if(word.contains(s)){
- //if the word is one of our key words, then we check to see if it's one of our combo-keywords too
- //we do this by checking to see if it's in the comboKeys set.
- if(comboKeys.contains(s)){
- hits.add(s); //if so we add it to the Hits list
- }
- response = responseMap.get(s);//we go ahead and set response to the single-word response
- }
- }
- }
- /* THIS SECTION DEALS WITH COMBINATIONS OF 2 WORDS */
- //if hits has more than one entry, we have a candidate for a
- //combination response
- String combo = "";
- if(hits.size() > 1){
- Collections.sort(hits);//this alphabetizes the hits list.
- for(String s : hits){
- //since the list is alphabetized, we can be certain that the combo words will be added in alphabetical order
- combo += s;
- }
- if(keys.contains(combo)){//now we check to see if the combination of the two words is contained in the keys
- response = responseMap.get(combo);//if so, we CHANGE the response to the combo response
- }
- }
- //if we've managed to get a response by now, return it.
- if(response != null) {
- return response;
- }
- /* THIS IS THE WHO, WHAT, WHY, ETC. SECTION*/
- //if we haven't returned a response yet, try the question words
- Set<String> qKeys = questionWordResponses.keySet();//make a key set
- //for each word in the ArrayList words
- for(String word : words){
- //if the Set qKeys contains the word
- if(qKeys.contains(word)){
- //set the response equal to the string from the questionWordResponses map
- response = questionWordResponses.get(word);
- }
- }
- //if we've managed to get a response, return it
- if(response != null) {
- return response;
- }
- /* IF ALL ELSE FAILS, SEND A DEFAULT RESPONSE */
- return pickDefaultResponse();
- /*
- * Suggested test phrases:
- * "Your software is buggy."
- * "I have a very expensive macintosh!"
- * "Why is the sky blue?"
- * "Are you a person?"
- * "something you won't recognize"
- * "bye"
- */
- }
- /**
- /**
- * Enter all the known keywords and their associated responses
- * into our response map.
- */
- private void fillResponseMaps()
- {
- responseMap.put("crash",
- "Well, it never crashes on our system. It must have something\n" +
- "to do with your system. Tell me more about your configuration.");
- responseMap.put("crashes",
- "Well, it never crashes on our system. It must have something\n" +
- "to do with your system. Tell me more about your configuration.");
- responseMap.put("slow",
- "I think this has to do with your hardware. Upgrading your processor\n" +
- "should solve all performance problems. Have you got a problem with\n" +
- "our software?");
- responseMap.put("performance",
- "Performance was quite adequate in all our tests. Are you running\n" +
- "any other processes in the background?");
- responseMap.put("bug",
- "Well, you know, all software has some bugs. But our software engineers\n" +
- "are working very hard to fix them. Can you describe the problem a bit\n" +
- "further?");
- responseMap.put("buggy",
- "Well, you know, all software has some bugs. But our software engineers\n" +
- "are working very hard to fix them. Can you describe the problem a bit\n" +
- "further?");
- responseMap.put("windows",
- "This is a known bug to do with the Windows operating system. Please\n" +
- "report it to Microsoft. There is nothing we can do about this.");
- responseMap.put("macintosh",
- "This is a known bug to do with the Mac operating system. Please\n" +
- "report it to Apple. There is nothing we can do about this.");
- responseMap.put("expensive",
- "The cost of our product is quite competitive. Have you looked around\n" +
- "and really compared our features?");
- responseMap.put("installation",
- "The installation is really quite straight forward. We have tons of\n" +
- "wizards that do all the work for you. Have you read the installation\n" +
- "instructions?");
- responseMap.put("memory",
- "If you read the system requirements carefully, you will see that the\n" +
- "specified memory requirements are 1.5 giga byte. You really should\n" +
- "upgrade your memory. Anything else you want to know?");
- responseMap.put("linux",
- "We take Linux support very seriously. But there are some problems.\n" +
- "Most have to do with incompatible glibc versions. Can you be a bit\n" +
- "more precise?");
- responseMap.put("bluej",
- "Ahhh, BlueJ, yes. We tried to buy out those guys long ago, but\n" +
- "they simply won't sell... Stubborn people they are. Nothing we can\n" +
- "do about it, I'm afraid.");
- responseMap.put("drepper",
- "Ulrich Drepper is an embarassment to free software.");
- responseMap.put("glibc",
- "Oh, glibc is one of the key components of Linux.");
- responseMap.put("drepperglibc",
- "Asking Drepper about anything is like talking to a very large brick \n" +
- "wall that would be terribly pleased to fall on you.");
- responseMap.put("expensivemacintosh",
- "You do generally get your money's worth when you buy a Mac. \n" +
- "Still, that doesn't mean they're completely problem-free.");
- comboKeys.add("macintosh");
- comboKeys.add("expensive");
- comboKeys.add("drepper");
- comboKeys.add("glibc");
- questionWordResponses.put("who",
- "Its probably Bill Gates' fault.");
- questionWordResponses.put("how",
- "I believe you'll find instructions for how to do that \n" +
- "in our instruction manual.");
- questionWordResponses.put("why",
- "Hey, in my line of work, you don't worry about 'why'.");
- }
- /**
- * Build up a list of default responses from which we can pick one
- * if we don't know what else to say.
- */
- private void fillDefaultResponses()
- {
- defaultResponses.add("That sounds odd. Could you describe that problem in more detail?");
- defaultResponses.add("No other customer has ever complained about this before. \n" +
- "What is your system configuration?");
- defaultResponses.add("That sounds interesting. Tell me more...");
- defaultResponses.add("I need a bit more information on that.");
- defaultResponses.add("Have you checked that you do not have a dll conflict?");
- defaultResponses.add("That is explained in the manual. Have you read the manual?");
- defaultResponses.add("Your description is a bit wishy-washy. Have you got an expert\n" +
- "there with you who could describe this more precisely?");
- defaultResponses.add("That's not a bug, it's a feature!");
- defaultResponses.add("Could you elaborate on that?");
- }
- /**
- * Randomly select and return one of the default responses.
- * @return A random default response
- */
- private String pickDefaultResponse()
- {
- // Pick a random number for the index in the default response list.
- // The number will be between 0 (inclusive) and the size of the list (exclusive).
- int index = randomGenerator.nextInt(defaultResponses.size());
- return defaultResponses.get(index);
- }
- }