#!/usr/bin/env python
#-*- coding: UTF-8 -*-
#
# Aufgabe 9: N‐Gramm Modellkonstruktion (+10Pkt Zusatz für den Einsatz eines Glättungsverfahrens)
# Author: Matthias Rebel, 731220

from aufgabe_X_ngramclass import NGrams
import getopt, sys
import aufgabe_X_ngramclass


#   FUNKTIONEN ______________________________________________________________________________________

def prettyprint(satz, satzNGramme, nSize, finalResult):
    " druckt das Ergebnis in gewünschter Form "
    print satz, ' => ',
    if nSize > 1:
        for x in satz.split()[nSize-1:-nSize+1]:
            ((a,b),c) = finalResult[(x,)]
            print 'P(', b[0], '|', " ".join(list(a)), ') =', '%.8f' % c ,
    else:
        for x in satz.split():#[nSize-1:-nSize]:
            print 'P(',x,') =','%.8f' % finalResult[(x,)],



def createNgramModelfromKorpus():
    " erzeugt die nSize Gramme des Korpus "
    nGrams = NGrams()
    nGramsModel = nGrams.createAndCountNgramsA(nSize, tokens)
    return nGramsModel

def createUniGramme():
    " erzeugt die Unigramme des Korpus "
    uniGrams = NGrams()
    uniGramme = uniGrams.createAndCountNgramsA(1, tokens)
    return uniGramme

def createNgrammeSatz():
    " erzeugt die nSize Gramme des Satzes"
    satzNGrams = NGrams()
    satzNGramme = satzNGrams.createAndCountNgramsA(nSize, satz.split())
    return satzNGramme


def calculatePropabilityForInput(nGramsModel, satzNGrams, uniGramme, nSize):
    """ berechnet die Probability für den Eingabesatz 
        für nSize > 1 mit folgender Formel:     
        P(word|context) = count(context,word) + 1 / count(word) + vokabSizeV
        Add-One Laplace Glättung                ^                    ^

        für UniGramme: 
        P(Word) = (countContWord + 1) / (countWord + vokabSizeV )
        Add-One Laplace Glättung   ^                    ^ """

    multiPropDict = {}

    if nSize > 1:
    # P(word|context) = count(context,word) + 1 / count(word) + vokabSizeV

        for ((context, word), count) in satzNGrams.items():
            #print nGramsModel
            #print ((context, word), count) 

            # count of Word in Context >>> in nGramsModel
            try:
                countContWord = nGramsModel[(context, word)]
            except:
                countContWord = 0

            # count of Word in unigrams, alle Vorkommen von Word 
            try:
                countWord = uniGramme[((),word)]
            except:
                countWord = 0     ### Add-One-Glättung (Laplace)  
                                  ###      v                    v                          
            probability = (countContWord + 1) / (countWord + vokabSizeV )
            multiPropDict[word] = ((context, word), probability )
            #prozent = ((countContWord + 1) / (countWord + vokabSizeV )) * len(nGramsModel) / 100 # in prozent  
            #print '%.2f' % prozent

    else:
        for ((context,word),count) in satzNGrams.items():
            try:
                countWord = uniGramme[((),word)]
            except:
                countWord = 0     ### Add-One-Glättung (Laplace)  
                                  ###      v                    v                          
            probability = (countWord + 1) / (korpuSizeN + vokabSizeV)
            multiPropDict[word] = probability

    return multiPropDict




# Defaultwert für nSize
nSize = 2


opts = []; #args = []

try:                                       # shortOptions, longOptions
    opts, args = getopt.getopt(sys.argv[1:], 'h:n:', ["help=","nSize="])
except getopt.GetoptError:
    print "ERR: Mindestens eine der Optionen ist nicht verfuegbar";# usage(); sys.exit()

for o, a in opts:
    if o == "--help" or o == "-h":
        print "Sorry, no help! watch the code."; #usage()
    elif o == "--nSize" or o == "-n":
        nSize = int(a)



filename = 'korpus/text-8kb.txt'
satz = '<s> Der Mann ist ein Gummibärchen </s>'

#   HAUPTTEIL ______________________________________________________________________________________

filename = 'korpus/ep-self-2000kb.txt'
satz = '<s> Darüber hinaus müssen sehr spezifische Maßnahmen ergriffen werden </s>'




if __name__ == "__main__":

    try:
        datei = file(filename,"r")
        tokens = datei.read().split()
        datei.close()
    except IOError:
        print "Cannot read from file", filename


    vokabSizeV = len(set(tokens))
    korpuSizeN = len(tokens)


    ### NGRAM-MODELL    
    ##  Erzeugen der nGramme des Korpus mit Hilfe der XGram_Klasse
    nGramsModel = createNgramModelfromKorpus()

    if nSize == 1:
        uniGramme = nGramsModel
    else:
        uniGramme = createUniGramme()

    ##  Erzeugen der nGramme des Satzes
    satzNGramme = createNgrammeSatz()

    # Berechnung für den Satz
    finalResult = calculatePropabilityForInput(nGramsModel, satzNGramme, uniGramme, nSize)

    prettyprint(satz, satzNGramme, nSize, finalResult)



#_______________________________________________________________________________________________ EOF