/**
* (c) 2000-2011 Carlos G�mez Rodr�guez, todos los derechos reservados / all rights reserved.
* Licencia en license.txt / License in license.txt
* File created: 20/03/2011 13:15:41
*/
package eu.irreality.age.spell;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import eu.irreality.age.EntityList;
import eu.irreality.age.Item;
import eu.irreality.age.Mobile;
import eu.irreality.age.Path;
import eu.irreality.age.Room;
import eu.irreality.age.Spell;
import eu.irreality.age.World;
/**
* @author carlos
*
* Decorator of a SpellingCorrector to correct using a dictionary extracted from the reference
* names in a given world.
*/
public class ReferenceNameCorrector implements SpellingCorrector
{
private SpellingCorrector theCorrector;
/**
* Words with length smaller than this are not included in the corrector, and corrections are not attempted for them. This is to prevent AGE from trying to correct
* things like articles, prepositions, etc. to their closest name.
*/
private static int MINLENGTH = 4;
/**
* Extracts a set of words for corrections from a list of reference names.
* Words are extracted if their length is at least MINLENGTH.
*/
private Set extractRelevantWords ( List names )
{
Set s = new LinkedHashSet();
for ( int i = 0 ; i < names.size() ; i++ )
{
String name = (String)names.get(i);
StringTokenizer st = new StringTokenizer(name);
while ( st.hasMoreTokens() )
{
String word = st.nextToken();
if ( word.length() >= MINLENGTH ) s.add(word);
}
}
return s;
}
/**
* Builds a corrector that uses a dictionary extracted from the reference names of the given
* world, using the given corrector as the base.
*/
public ReferenceNameCorrector ( World w , SpellingCorrector c )
{
theCorrector = c;
EntityList items = w.getAllItems();
EntityList mobiles = w.getAllMobiles();
EntityList rooms = w.getAllRooms();
EntityList spells = w.getAllSpells();
Set words = new LinkedHashSet();
//add item reference names
for ( int i = 0 ; i < items.size() ; i++ )
{
Item it = (Item) items.get(i);
words.addAll( extractRelevantWords(it.getSingularReferenceNames()));
words.addAll( extractRelevantWords(it.getPluralReferenceNames()));
words.addAll( extractRelevantWords(it.getExtraDescriptionNames()));
}
//add mobile reference names
for ( int i = 0 ; i < mobiles.size() ; i++ )
{
Mobile mob = (Mobile) mobiles.get(i);
words.addAll( extractRelevantWords(mob.getSingularReferenceNames()));
words.addAll( extractRelevantWords(mob.getPluralReferenceNames()));
words.addAll( extractRelevantWords(mob.getExtraDescriptionNames()));
}
//add spell reference names
for ( int i = 0 ; i < spells.size() ; i++ )
{
Spell spell = (Spell) spells.get(i);
words.addAll( extractRelevantWords(spell.getSingularReferenceNames()));
words.addAll( extractRelevantWords(spell.getPluralReferenceNames()));
}
//add words coming from names of exits/paths
for ( int i = 0 ; i < rooms.size() ; i++ )
{
Room r = (Room) rooms.get(i);
words.addAll( extractRelevantWords(r.getExtraDescriptionNames()));
Path[] exits = r.getNonStandardExits();
for ( int j = 0 ; j < exits.length ; j++ )
{
List names = r.getExitNames(exits[j]);
words.addAll( extractRelevantWords(names) );
}
exits = r.getStandardExits();
for ( int j = 0 ; j < exits.length ; j++ )
{
if ( r.isValidExit(true,j))
{
List names = r.getExitNames(exits[j]);
words.addAll( extractRelevantWords(names) );
}
}
}
//add common words for the language (which don't refer to anything in the world but are expected to appear, e.g. this, another, some, etc.)
List commonWords = w.getLanguage().getCommonWordsList();
words.addAll( extractRelevantWords(commonWords) );
init(words);
}
public void init(Collection words)
{
theCorrector.init(words);
}
public void addDictionaryWord(String word) throws UnsupportedOperationException
{
theCorrector.addDictionaryWord(word);
}
/**
* Adds a new reference name (single-word or multiword) to the corrector.
* This can be used by games that dynamically add reference names to entities.
* @param name
*/
public void addReferenceName(String name)
{
List singleElementList = new ArrayList();
singleElementList.add(name);
Set relevantWords = extractRelevantWords(singleElementList);
for ( Iterator it = relevantWords.iterator() ; it.hasNext(); )
{
String word = (String) it.next();
addDictionaryWord(word);
}
}
public Correction getBestCorrection(String word)
{
if ( word.length() < MINLENGTH ) return new Correction(word,0.0); //don't attempt to correct short words like articles, prepositions, etc.
return theCorrector.getBestCorrection(word);
}
}