/*
 * Copyright 1999-2004 Carnegie Mellon University.
 * Portions Copyright 2004 Sun Microsystems, Inc.
 * Portions Copyright 2004 Mitsubishi Electric Research Laboratories.
 * All Rights Reserved.  Use is subject to license terms.
 *
 * See the file "license.terms" for information on usage and
 * redistribution of this file, and for a DISCLAIMER OF ALL
 * WARRANTIES.
 *
 */
package edu.cmu.sphinx.result;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;

/**
 * A confusion set is a set of words with their associated posteriors.
 * In Java terms it's a SortedMap from posteriors to sets of WordResults, but
 * the class is called a set because that's what this beast is known as
 * in the literature.
 * 
 * @author pgorniak
 */ 
public class ConfusionSet extends TreeMap {
    
    /**
     * Add a word hypothesis to this confusion set.
     * 
     * @param word the hypothesis to add
     */
    public void addWordHypothesis(WordResult word) {
        Set wordSet = getWordSet(word.getConfidence());
        if (wordSet == null) {
            wordSet = new HashSet();
            put(new Double(word.getConfidence()),wordSet);
        }
        wordSet.add(word);
    }
    
    /**
     * Get the word set with this confidence.
     * 
     * @param posterior the confidence (posterior)
     * @return a set of hypotheses with this confidence, null if no such hypotheses
     * 
     */
    public Set getWordSet(double posterior) {
        return (Set)get(new Double(posterior)); 
    }
    
    /**
     * Return the set of best hypothesis. This will usually contain one
     * hypothesis, but might contain more case there are some that have
     * exactly equal confidences.
     * 
     * @return a set of best hypotheses
     * 
     */
    public Set getBestHypothesisSet() {
        return (Set)get(lastKey()); 
    }
    
    /**
     * Return the single best hypothesis. Breaks ties arbitrarily.
     * 
     * @return the best hypothesis stored in this confusion set (by confidence)
     */
    public WordResult getBestHypothesis() {
        Set s = getBestHypothesisSet();
        return (WordResult)s.iterator().next();
    }
    
    /**
     * Get the highest posterior (confidence) stored in this set.
     *
     * @return the highes posterior
     */
    public double getBestPosterior() {
        return ((Double)lastKey()).doubleValue();
    }

    /**
     * Returns the WordResult in this ConfusionSet for the given word.
     *
     * @param word the word to look for
     *
     * @return the WordResult for the given word, or null if no WordResult
     *     for the given word is found
     */
    public WordResult getWordResult(String word) {
        for (Iterator i = values().iterator(); i.hasNext(); ) {
            Set wordSet = (Set) i.next();
            for (Iterator r = wordSet.iterator(); r.hasNext(); ) {
                WordResult wordResult = (WordResult) r.next();
                String resultSpelling 
                    = wordResult.getPronunciation().getWord().getSpelling();
                if (resultSpelling.equals(word)) {
                    return wordResult;
                }
            }
        }
        return null;
    }

    /**
     * Dumps out the contents of this ConfusionSet.
     *
     * @param name the name of the confusion set
     */
    public void dump(String name) {
        System.out.print(name + " :");
        for (Iterator i = values().iterator(); i.hasNext(); ) {
            Set wordSet = (Set) i.next();
            for (Iterator r = wordSet.iterator(); r.hasNext();) {
                WordResult wordResult = (WordResult) r.next();
                System.out.print
                    (" " + 
                     wordResult.getPronunciation().getWord().getSpelling());
            }
        }
        System.out.println();
    }
}

@@ -2415,32 +2415,843 @@
 Value();%0A    %7D%0A%0A
+    /**%0A     * Check whether this confusion set contains the given word%0A     * @param word the word to look for%0A     * @return true if word is in this set%0A     */%0A    public boolean containsWord(String word) %7B%0A        return getWordResult(word) != null;%0A    %7D%0A    %0A    /**%0A     * Check whether this confusion set contains any fillers.%0A     * @return whether fillers are found%0A     */%0A    public boolean containsFiller() %7B%0A        for (Iterator i = values().iterator(); i.hasNext(); ) %7B%0A            Set wordSet = (Set) i.next();%0A            for (Iterator r = wordSet.iterator(); r.hasNext(); ) %7B%0A                WordResult wordResult = (WordResult) r.next();%0A                if (wordResult.isFiller()) %7B%0A                    return true;%0A                %7D%0A            %7D%0A        %7D%0A        return false;%0A    %7D%0A    %0A
     /**%0A     * R
@@ -3313,16 +3313,16 @@
 n word.%0A
-
      *%0A 
@@ -3814,16 +3814,41 @@
 pelling 
+= wordResult.toString(); 
 %0A       
@@ -3860,16 +3860,18 @@
         
+//
 = wordRe
@@ -4667,32 +4667,32 @@
     %7D%0A        %7D%0A
-
         System.o
@@ -4711,10 +4711,549 @@
 ;%0A    %7D%0A
+    %0A    public String toString() %7B%0A        StringBuffer b = new StringBuffer();%0A        Iterator i = keySet().iterator();%0A        while (i.hasNext()) %7B%0A            Double p = (Double)i.next();%0A            Set words = (Set)get(p);%0A            b.append(p.toString()).append(%22:%22);%0A            Iterator j = words.iterator();%0A            while (j.hasNext()) %7B%0A                b.append(j.next());%0A                if (j.hasNext()) %7B%0A                    b.append(%22,%22);%0A                %7D%0A            %7D%0A        %7D%0A        return b.toString();%0A    %7D%0A
 %7D%0A

add methods to check for a specific word, all fillers also changing the find word methods to use word.toString instead of going through the pronunciation this might break something in MAPConfidence - need to check