IndexStoryTemplate.java
/*
* "Net Libs" by Copyright (C) Michael Benson - 7/27/97
*
* Loosely based on "Mac Libs" which is loosely based on the old
* "Mad Libs" books for creating stories from forms.
*
* "StoryTemplate" contains the story templates.
*/
package NetLibs;
import java.awt.*;
import java.applet.Applet;
import java.util.*;
import java.io.*;
import java.net.*;
import COM.bensoft.base.*;
import COM.bensoft.widgets.*;
/**
* StoryTemplate implements the class which handles reading the story
* template text, getting the prompts, reading the dictionaries, and
* choosing random words.
*
* @author Michael Benson
*/
public class StoryTemplate implements NetLibsConst
{
private static final String _templateDir = "templates/";
private static final String _wordDir = "words/";
private static final String _numberString = "number";
private Random _rand;
private Vector _wordList;
private Vector _wordCat;
/**
* StoryTemplate constructor.
*/
public StoryTemplate()
{
_rand = new Random();
_wordList = new Vector();
_wordCat = new Vector();
}
/**
* Reads in a story template.
*
* @param applet the parent applet (used for code base).
* @param storyName the name of the story template.
* @exception IOException if error reading template file.
* @return string containing the story template.
*/
public String getTemplate (Applet applet, String storyName) throws IOException
{
// Create a URL for the template file name:
URL templateURL = new URL(applet.getCodeBase().toString() +
_templateDir + storyName + ".txt");
// Read in the raw story template:
InputStream in = templateURL.openStream();
byte[] data = new byte[MAXFILESIZE];
int bytes_read = in.read(data);
in.close();
// Return the template as a string:
return new String(data, 0);
}
/**
* Reads in a prompt file and separates the prompts. Creates a
* vector in which each element is a prompt string.
*
* @param applet the parent applet (used for code base).
* @param storyName the name of the story template.
* @exception IOException if error reading prompt file.
* @exception MalformedURLException if error finding prompt file.
* @return vector containing each prompt string.
*/
public Vector getPrompts (Applet applet, String storyName)
throws IOException, MalformedURLException
{
Vector prompts = new Vector();
String str;
// Create a URL for the prompt file name:
URL promptURL = new URL(applet.getCodeBase().toString() +
_templateDir + storyName + ".prompts");
// Read in the whole prompt file:
InputStream in = promptURL.openStream();
byte[] data = new byte[MAXFILESIZE];
int bytes_read = in.read(data);
in.close();
// Look through the buffer for the carriage returns and
// separate the prompts:
StringBuffer buf = new StringBuffer();
for (int i = 0; i < bytes_read; i++) {
if ((char)(data[i]) == '\n') {
str = buf.toString();
prompts.addElement(str);
buf = new StringBuffer();
} else {
buf.append((char)(data[i]));
}
}
return prompts;
}
/**
* Gets a random word of type prompt. If number prompt
* is found, it will generate a random number. Also, if the prompt
* is capitalized, the chosen word will be capitalized.
*
* @param applet the parent applet (used for code base).
* @exception IOException if error reading prompt file.
* @exception MalformedURLException if error finding prompt file.
* @return the word chosen at random.
*/
public String getRandomWord (Applet applet, String prompt)
throws IOException, MalformedURLException
{
Vector words;
String str, numstr;
Integer lower = null;
Integer upper = null;
float lo, up;
if (prompt.startsWith(_numberString)) {
// Generate a random number and convert to a string.
// Find the limits in the prompt ("number from xxx to yyy"):
StringTokenizer st = new StringTokenizer(prompt);
int n = 0;
while (st.hasMoreTokens()) {
numstr = st.nextToken();
if (n == 2) {
// Lower limit:
lower = new Integer(numstr);
} else if (n == 4) {
// Upper limit:
upper = new Integer(numstr);
}
n++;
}
if (lower == null || upper == null) {
lo = (float)1.0;
up = (float)100.0;
} else {
lo = lower.floatValue();
up = upper.floatValue() - lo + (float)1.0;
}
int m = (int)(_rand.nextFloat() * up + lo);
Integer i = new Integer(m);
str = i.toString();
}
else {
// Determine if the prompt is capitalized:
boolean isCapital = Character.isUpperCase(prompt.charAt(0));
// Get the list of words either from the cache or the file:
words = _getWordList(applet, prompt);
// Get the nth word:
float f = words.size();
int n = (int)(_rand.nextFloat() * f);
if (n >= words.size()) {
// There is a tiny probability of generating a number
// that's 1 too big, so let's insure against that:
n = words.size() - 1;
}
str = (String)(words.elementAt(n));
if (isCapital) {
str = BensUtils.capitalizePhrase(str);
}
}
return str;
}
/**
* Reads in a dictionary file and separates the words. Creates
* a vector in which each element is a word string. Caches dictionaries
* so the next time a particular word category is used, it will just
* use the cached version rather than re-reading the file.
*
* @param applet the parent applet (used for code base).
* @param prompt the word category (noun, verb, etc.)
* @exception IOException if error reading prompt file.
* @exception MalformedURLException if error finding prompt file.
* @return vector containing the list of words.
*/
private Vector _getWordList (Applet applet, String prompt)
throws IOException, MalformedURLException
{
String cprompt = prompt.toLowerCase();
String str;
// First determine if this word category has already been cached:
for (int i = 0; i < _wordCat.size(); i++) {
if (((String)(_wordCat.elementAt(i))).equals(cprompt)) {
// Return the cached word list:
return (Vector)(_wordList.elementAt(i));
}
}
// Read in the word file.
// Create a URL for the word file name:
URL wordURL = new URL(applet.getCodeBase().toString() +
_wordDir + cprompt + ".words");
// Read in the whole word file:
InputStream in = wordURL.openStream();
byte[] data = new byte[MAXFILESIZE];
int bytes_read = in.read(data);
in.close();
// Look through the buffer for the carriage returns and
// separate the words:
Vector words = new Vector();
StringBuffer buf = new StringBuffer();
for (int i = 0; i < bytes_read; i++) {
if ((char)(data[i]) == '\n') {
str = buf.toString();
words.addElement(str);
buf = new StringBuffer();
} else {
buf.append((char)(data[i]));
}
}
// Add the word list to the cached lists and return it:
_wordCat.addElement(new String(cprompt));
_wordList.addElement(words);
return words;
}
}