/*
 * $Id: SummaryEntry.java,v 1.11 2006/08/31 19:59:10 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: SummaryEntry.java,v $
 * Revision 1.11  2006/08/31 19:59:10  marbobo
 * + Refactoring
 *
 * Revision 1.10  2006/07/17 14:33:45  lawern
 * Spezialbehandlung von keyId=0 bei TFIDF-Gewichtung.
 *
 * Revision 1.9  2006/07/17 14:16:09  lawern
 * Umstellung der Schlagwort- und Summary-Extraktion auf TFIDF-Gewichtung.
 *
 * Revision 1.8  2005/09/13 09:51:44  jonyp
 * cleaning the code
 *
 * Revision 1.7  2005/04/13 06:37:26  lawern
 * Analyser mit Typografiegewichtung
 *
 * Revision 1.6  2004/06/27 17:08:22  marbobo
 * + Quellcode maintenance
 *
 * Revision 1.5  2003/12/24 10:12:04  bigmac
 * Projektweite Import-Optimierung
 *
 * Revision 1.4  2003/07/07 09:29:25  lawern
 * Keywords laufen jetzt duch einen Stemmer
 *
 * Revision 1.3  2003/04/25 17:36:28  lawern
 * Überarbeitung der Satzendeerkennung
 *
 * Revision 1.2  2003/04/23 10:46:19  koppy
 * + implements Serializable
 *
 * Revision 1.1  2003/03/07 11:56:57  lawern
 * initiale Version
 *
 */
package vkc.analyse;

import vkc.search.Search;

import java.io.Serializable;

import java.util.ArrayList;


/**
 * Satz-Objekt
 *
 * @author lawern
 */
public final class SummaryEntry implements Serializable {
    private static final boolean useMaxWeightOnly = false;
    private static final boolean prioMultipleTypos = false;
    static final double log2 = Math.log(2);
    private String text;
    private boolean weightNormalized = false;
    private double weight = -1.0;
    private ArrayList wordList;
    private double maxWeight = -1.0;
    private boolean multipleWeights = false;
    private int tf;

    /**
     * erzeugt neues Wort-Objekt
     *
     * @param text - Wort
     * @param weight - Gewicht
     */
    public SummaryEntry(String text, double weight) {
        this.text = text;

        if (useMaxWeightOnly) {
            maxWeight = weight;
            tf = 1;
        } else {
            this.weight = weight;
        }
    }

    /**
     * erzeugt neues Satz-Objekt
     *
     * @param text - Satztext
     * @param wordList - ArrayList mit SummaryEntries der Schlagwörter
     */
    public SummaryEntry(String text, ArrayList wordList) {
        this.text = text;
        this.wordList = wordList;
    }

    /**
     * liefert den zum Eintrag gehörenden Text
     *
     * @return Text des Eintrags
     */
    public String getText() {
        return text;
    }

    /**
     * setz den zum Eintrag gehörenden Text
     *
     * @param text Text des Eintrags
     */
    public void setText(String text) {
        this.text = text;
    }

    /**
     * erhöht das Gewicht des Eintrags um den übergebenen Wert
     *
     * @param relevance Betrag um den das Gewicht erhöht werden soll
     */
    public void inc(double weight) {
        if (useMaxWeightOnly) {
            tf++;

            if (weight > maxWeight) {
                maxWeight = weight;
            }

            if (weight != maxWeight) {
                multipleWeights = true;
            }
        } else {
            this.weight += weight;

            if (weight != maxWeight) {
                multipleWeights = true;
            }
        }
    }

    /**
     * Liefert das Gewicht des Eintrags normiert auf den übergebenen Wert.
     *
     * @param normFactor Wert auf den normiert werden soll
     *
     * @return Gewicht des Eintrags
     */
    public double getWeight(double normFactor) {
        if (!weightNormalized) {
            if (useMaxWeightOnly) {
                if (prioMultipleTypos) {
                    if (multipleWeights) {
                        weight = (maxWeight * tf) / normFactor;
                    } else {
                        weight = (maxWeight * tf) / (normFactor * 2.0);
                    }
                } else {
                    weight = (maxWeight * tf) / normFactor;
                }
            } else {
                if (prioMultipleTypos) {
                    if (multipleWeights) {
                        weight = weight / normFactor;
                    } else {
                        weight = weight / (normFactor * 2.0);
                    }
                } else {
                    weight = weight / normFactor;
                }
            }

            weightNormalized = true;
        }

        return weight;
    }

    /**
     * Liefert das TFIDF-Gewicht des Eintrags normiert auf den übergebenen Wert.
     * @param normFactor Wert auf den normiert werden soll
     * @param currDocLangId
     * @return
     */
    public double getIDFWeight(double normFactor, int currDocLangId,
        int probSize) {
        double weight = getWeight(normFactor);
        int keyId = Search.getKeyIndex(text, currDocLangId, false, 0);

        if (keyId != 0) {
            double df = Search.idFreqBase.get(keyId);

            return weight * (Math.log(probSize / df) / log2);
        }

        return 0f;
    }

    /**
     * liefert das Gewicht des Satzeintrags normiert auf die Satzlänge
     *
     * @param normFactor Wert auf den die Schlagwörter normiert werden sollen
     *
     * @return Gewicht des Satzeintrags
     */
    public double getSentenceWeight(double normFactor, int langPackId,
        int probSize) {
        if (!weightNormalized) {
            if (wordList.size() > 1) {
                //Ein Satz muss mehr als ein Keyword enthalten.
                double weightSum = 0;

                for (int i = wordList.size() - 1; i >= 0; i--)
                    weightSum += ((SummaryEntry) wordList.get(i)).getIDFWeight(normFactor,
                        langPackId, probSize);

                weight = weightSum / wordList.size();
            } else {
                weight = 0.0;
            }

            weightNormalized = true;
        }

        return weight;
    }

    /**
     * Liefert das Gewicht des Eintrags
     *
     * @return nicht normiertes Gewicht des Eintrags
     */
    public double getWeight() {
        if (weight >= 0) {
            return weight;
        }
        
        if (prioMultipleTypos) {
            if (multipleWeights) {
                return maxWeight * tf;
            } 

            return (maxWeight * tf) / 2.0;
        }

        return maxWeight * tf;
    }

    /**
     * Liefert das IDF-Gewicht des Eintrags
     *
     * @return nicht normiertes Gewicht des Eintrags
     */
    public double getIDFWeight(int currDocLangId, int probSize) {
        double weight = getWeight();
        int keyId = Search.getKeyIndex(text, currDocLangId, false, 0);

        if (keyId != 0) {
            double df = Search.idFreqBase.get(keyId);

            return weight * (Math.log(probSize / df) / log2);
        }

        return 0f;
    }

    /**
     * setzt das Gewicht des Eintrags auf den übergebenen Wert
     *
     * @param weight Gewicht das gesetzt werden soll
     */
    public void setWeight(double weight) {
        this.weight = weight;
    }
}
