Package standup.joke

This package provides joke generation functionality and all its related data structures.

See:
          Description

Interface Summary
InstantiationConstraint An InstantiationConstraint represents a constraint on the keyword instantiations of a JokeStructure.
JokeConstraint A JokeConstraint represents a constraint on a particular aspect of a JokeStructure.
 

Class Summary
Backend The main class through which joke generation and related functionality should be accessed.
BackendJokeSetOnly A subclass of Backend that "generates" jokes purely by retrieving pre-generated jokes found in the 'joke cache'.
BackendJokeSetSQL A subclass of Backend that fulfills joke generation requests either by genuinely creating a new joke or by retrieving pre-generated jokes found in a 'joke cache' -- this value is determined by the current user profile's JokeCacheBehaviour.
BackendSQL A subclass of Backend that always genuinely generates new jokes.
ChooserJokeType A JDialog that allows the user to choose a JokeType.
Clause An output specification function clause.
FLevel Abstractly, an FLevel defines a subset of all jokes possibly generated by the STANDUP joke generated based on a threshold of familiarity scores.
Generator The main class that handles joke generation.
InstantiationConstraintAmbiguity An InstantiationConstraint that constrains the level of ambiguity found in the keyword instantiations of a joke.
InstantiationConstraintFamiliarityScore An InstantiationConstraint that constrains the minimum familiarity scores found in the keyword instantiations of a joke.
InstantiationConstraintFLevel An InstantiationConstraint that constrains the minimum FLevels of a joke.
InstantiationConstraintLexeme An InstantiationConstraint that constrains a joke to make use of a specific Lexeme.
InstantiationConstraintLexemeClause An InstantiationConstraint that constrains a joke to make use of a specific Lexeme in its question.
InstantiationConstraintLexemeSchema An InstantiationConstraint that constrains a joke to make use of a specific Lexeme in its answer.
InstantiationConstraintLexicon An InstantiationConstraint that constrains a joke to make use of at least one Lexeme in a given LexemeSet.
InstantiationConstraintLexiconAll An InstantiationConstraint that constrains a joke to use only Lexemes from a given LexemeSet as instantiations.
InstantiationConstraintLexiconAllClause An InstantiationConstraint that constrains a joke to use only Lexemes from a given LexemeSet as question instantiations.
InstantiationConstraintLexiconAllSchema An InstantiationConstraint that constrains a joke to use only Lexemes from a given LexemeSet as answer instantiations.
InstantiationConstraintLexiconClause An InstantiationConstraint that constrains a joke to make use of at least one Lexeme from a given LexemeSet in its question.
InstantiationConstraintLexiconNone An InstantiationConstraintLexicon that constrains a joke to NOT use ANY Lexemes from a given LexemeSet as instantiations.
InstantiationConstraintLexiconSchema An InstantiationConstraint that constrains a joke to make use of at least one Lexeme from a given LexemeSet in its answer.
InstantiationConstraintNovelty An InstantiationConstraint that constrains the Backend to only generate/retrieve a joke that does not appear in the current user's generated joke log.
InstantiationConstraintPhoneticSimilarity An InstantiationConstraint that constrains the minimum phonetic similarity ratings found in the preconditions of instantiations of a joke.
JokeConstraintAllowedSchemas A JokeConstraint that constrains a joke to use one from a given set of Schemas.
JokeConstraints  
JokeConstraintType A JokeConstraint that constrains a joke to be of a given JokeType.
JokeConstraintTypes A JokeConstraint that constrains a joke to be of one of a given set of JokeTypes.
JokeGraph A JokeGraph records all the internal structure of a JokeStructure, allowing us to inspect all the choices made by the Generator during the various stages of joke generation, i.e.
JokeGraphEdge An edge in a JokeGraph.
JokeGraphNode A node in a JokeGraph.
JokeGraphNodeKeyword A node in a JokeGraph.
JokeGraphNodeTemplate A node in a JokeGraph that represents a span of 'canned' text that arose during template filling.
JokeSet This class represents a set of JokeStructures.
JokeStructure A generated joke, with all its underlying data structures.
JokeType A type of joke as defined in the technical specification document.
JokeTypeSet A set of JokeTypes.
OptionsGUIJokeGeneration A Swing-based GUI for editing the various joke generation options.
OptionsJokeGeneration A Options representing the various settings relating to joke generation.
Precondition A Precondition represents a lexical precondition as used to define Schemas and output specification function Clauses.
ProfileJokeGeneration A Profile relating to joke generation.
Schema This class implements a schema as defined in the technical specification.
SchemaTemplatePair Defines a combination of suitable schemas and templates for joke generation.
SQLQuerySchema Represents a query on a schema instantiation table.
Template A Template is a structure used in 'surface generation', i.e.
 

Enum Summary
AllowableAmbiguity Possible values for InstantiationConstraintAmbiguity.
JokeCacheBehaviour Possible values for JokeCacheBehaviour.
SourceProcess An object indicating when an element in a JokeGraph arose, i.e.
 

Exception Summary
GeneratorException A very simple subclass of Exception that is specifically for Exceptions arising from within the standup.joke package.
 

Package standup.joke Description

This package provides joke generation functionality and all its related data structures.

The main class to use is the Backend, which handles requests for joke generation and records a user's log of generated jokes in a ProfileJokeGeneration. Actual joke generation is handled by the Generator class, which implements the joke generation and surface generation processes described in chapters ? and ? of the STANDUP backend technical specification document.

An arbitrary number of JokeConstraints can be imposed to control specific aspects of the jokes that are to be generated or retrieved, e.g. ensuring jokes use specific keywords, or use a particular type of question form, or satisfy a minimum threshold of phonetic similarity, etc.

A joke is represented as an instance of a JokeStructure, which contains a JokeGraph, a graph data structure that records all choices made by the Generator during the joke generation process.

Quick usage guide

This section provides a very quick introduction to using the standup.joke package. More details are provided in the subsequent sections.

  1. Instantiate a subclass of Backend (note that the Backend class itself is abstract). If you have installed the PostgreSQL-based lexical database, you can choose to instantiate a BackendSQL or BackendJokeSetSQL. Otherwise, instantiate a BackendJokeSetOnly -- which we use in the following example:
    import standup.joke.*;
    import standup.profiling.ProfileManager;
    
    Backend myBackend = new BackendJokeSetOnly();
    
  2. Create a user profile and use it. The Backend class provides functionality of saving user-specific option settings and personal history. Creation and manipulation of these profiles is handled through the ProfileManager class (see the standup.profiling package documentation for more details).
    ProfileManager.initialize();
    ProfileManager.createUser("username",myBackend);
    ProfileManager.useProfile("username",myBackend);
    
  3. Generate a joke. Use one of the various getNewJoke methods provided by the Backend class. Here we use the default Backend.getNewJoke() and print the question and answer to the console, before finally adding it to the user profile's favourite jokes collection:
    JokeStructure myJoke = myBackend.getNewJoke();
    System.out.println(myJoke.getQuestion());
    System.out.println(myJoke.getAnswer());
    myBackend.addToFavourites(myJoke);
    

The Backend class

The Backend class performs joke generation in a manner that is aware of a user's profile in two ways:

It implements the Profileable interface, which provides the user profiling functionality. The user profile related to joke generation is implemented in the ProfileJokeGeneration and OptionsJokeGeneration classes.

The Backend class itself is abstract, so when instantiating it, one of the following must be chosen:

Generating jokes

The recommended way to generate jokes is to use one of the various Backend.getNewJoke methods, for reasons described above.
MethodDescription
Backend.getNewJoke()Generates a random joke
Backend.getNewJoke(JokeType)Generates a random joke of a given JokeType.
Backend.getNewJoke(Lexeme)Generates a random joke that uses a particular Lexeme in its answer.
Backend.getNewJoke(LexemeSet)Generates a random joke that uses at least one Lexeme from a given LexemeSet in its answer.
Backend.getNewJoke(Topic)Generates a random joke that uses at least one Lexeme about a given Topic in its answer.

The above methods are all 'syntactic sugar' methods which actually call the standup.joke.#getNewJoke(JokeConstraints) method. Using this method directly allows the specification of much more complex combinations of constraints, e.g. generating a joke of a particular JokeType, using a particular Lexeme, and about a given Topic, etc. However, the getNewJoke(JokeConstraints) method does not automatically include the constraints imposed by the current user profile. To obtain this, use the standup.joke.#buildUserProfileConstraints() method, and add to the resulting JokeConstraints as required.

Finally, when the above methods need to generate a new joke (i.e. not simply to retrieve one from an existing 'cache' of pre-generated jokes), they all call Generator.generateJoke(String,JokeConstraints), which really performs joke generation. If you don't care about user profiling, you can bypass the Backend completely and call this method directly.

Manipulating jokes

The various joke generating methods described above all return a JokeStructure, which contains all information relating to how the joke was constructed.

The simplest way of obtaining the joke is through the JokeStructure.getQuestion() and JokeStructure.getAnswer() methods, which return String representations of the question and answer of the joke respectively.

To obtain a more detailed view of the joke, use the JokeStructure.getQuestionStruct() and JokeStructure.getAnswerStruct() methods, which return WordStruct representations of the question and answer of the joke respectively. A WordStruct allows one to distinguish between the 'canned' text of a joke and the Keywords of a joke, i.e. lexical elements that instantiate Schemas and Clauses (see below for details).

A JokeStructure also provides various boolean-returning methods for testing various aspects, e.g.:

MethodDescription
JokeStructure.ofType(JokeType)Test whether a joke is of a given type.
JokeStructure.satisfies(JokeConstraints)Test whether a joke satisfies an arbitrary collection of constraints.
JokeStructure.uses(Lexeme)Test whether a joke uses a given lexeme.
JokeStructure.usesAny(LexemeSet)Test whether a joke uses at least one lexeme from a given set.
JokeStructure.usesAll(LexemeSet)Test whether all lexemes in a joke belong to a given set.
JokeStructure.about(Topic)Test whether a joke uses at least one lexeme about a given topic.

However, the most detailed data structure relating to a joke is the JokeGraph, which can be obtained from a JokeStructure by calling JokeStructure.getGraph(). A JokeGraph records all the internal structure of a joke, allowing us to inspect all the choices made by the Generator during the various stages of joke generation, i.e. schema instantiation, output specification function clause instantiation, and template filling (see the STANDUP backend technical specification for details).

A JokeGraph consists of a set of JokeGraphNodes, which may be connected through (directed) JokeGraphEdges. A node can either correspond to a keyword, in which case it will be a standup.joke.JokeGraphNodeLex, or to a piece of 'canned' text from a template, in which case it will be a JokeGraphNodeTemplate. Where a JokeGraphNode corresponds to a span of text in either the question or answer WordStruct, they will share the same label.

Joke constraints

A JokeConstraint represents a constraint on a particular aspect of a joke.

All of them support a generate-and-test form of validation through the JokeConstraint.validate(JokeStructure) method, which returns true if a given joke satisfies that constraint, and false otherwise. Additionally, most of them provide some other way of imposing themselves on the joke generation process. An InstantiationConstraint is a JokeConstraint that can modify an SQL query when obtaining either Schema or Clause instantiations through the standup.joke.InstantiationConstraint#handleSchema(SchemaSQLQuery) or InstantiationConstraint.getSQLConstraint(Clause, List) methods, respectively.

Finally, a JokeConstraints object simply represents a collection of constraints.

The following table shows the implemented constraints:
ConstraintDescription
JokeConstraintAllowedSchemasA joke must use one of a given set of Schemas.
JokeConstraintTypeA joke must be of a given type.
InstantiationConstraintAmbiguityA joke must satisfy a minimum AllowableAmbiguity.
InstantiationConstraintFamiliarityScoreAll keywords in a joke must have an F-score equal to or above a given threshold.
InstantiationConstraintLexemeA joke must use a given keyword (variants for Schema or Clause).
InstantiationConstraintLexiconA joke must use at least one keyword from a given set (variants for Schema or Clause).
InstantiationConstraintLexiconAllAll keywords in a joke must belong to a given set (variants for Schema or Clause).
InstantiationConstraintNoveltyA joke must not have been previously generated (w.r.t user profile's history).
InstantiationConstraintPhoneticSimilarityAll homophone relations in a joke must have a phonetic similarity rating equal to or above a given threshold

Dealing with collections of jokes

A JokeSet represents a collection of jokes. It provides various methods for retrieving and manipulating jokes, e.g.:

Under the hood

The Generator class handles the actual joke generation process. It requires access to various joke resources, i.e.:

The STANDUP backend technical specification document provides more details on these objects.

When instantiating a Generator using the default Generator.Generator() constructor, it loads all necessary joke resources from definitions found within the /standup/resources/xml/ subdirectory of the STANDUP .jar file. Alternatively, the Generator.Generator(URL) constructor will instantiate a Generator using a set of joke resources defined elsewhere.

The Generator.generateJoke(String,JokeConstraints) and Generator.generateJokeStructure(String, Schema, List, List, List, double, JokeConstraints) methods implements the joke generation process (more specifically, they implement schema instantiation and clause instantiation respectively), whereas the Generator.surfaceGenerate(List, String, JokeGraph, JokeConstraints) method implements the surface generation process. All of this is described in detail in the technical specification document. All these methods gradually build up a JokeGraph and enclosing JokeStructure as they proceed.