#calculeaza greutatea Poisson pentru articolele din ultimele 7 zile
import time
import datetime
import os
import sys
import math
import marshal
from vars import SYS_PATH
os.environ["DJANGO_SETTINGS_MODULE"] = "news.settings"
sys.path.append(SYS_PATH)

#from django.conf.settings import NR_ZILE_ARTICOLE, ENGINE_ROOT
from django.conf import settings
from news.stiri.models import Articol
from functions import elimina_sufixe

class ComputePoisson(object):
    """Clasa ce obtine articolele din perioada de timp dorita, calculeaza nr. de cuvinte din fiecare articol,
       calculeaza distributia Poisson
    """

    def __init__(self):
        #hard-codate pentru moment; vor fi salvate in baza de date
        self.lista_no_words = ['and', 'billion', 'dolari', 'euro', 'for', 
                               'lei', 'miliarde', 'milioane', 'that', 'the']
        #hard-codata pentru moment; va fi salvata in baza de date
        self.limita_poisson = 1.0
        self.lista_articole = self.get_lista_articole()
        self.nr_articole = len(self.lista_articole)

    def get_lista_articole(self):
        #returneaza lista de articole
        today = datetime.date.today()
        start_date = today - datetime.timedelta(days=settings.NR_ZILE_ARTICOLE)
        lista_articole = Articol.objects.filter(data__gte=start_date)
        if not lista_articole:
            #luam ultimele 3000 de Articole daca nu am gasit nici unul
            lista_articole = Articol.objects.filter().order_by('-id')[:3000]
        return lista_articole

    def proceseaza_articole(self):
        #proceseaza fiecare articol din lista
        #converteste in litere mici, elimina spatiile, ",", ":" etc...
        #intoarce un dictionar de forma:
        #dict_return = {"iliescu": {"nr_total_aparitii": nr_aparitii, "lista_indecsi": [lista cu id-urile articolelor in care apare], }}        
        dict_return = {}
        sir_strips = ",.;\"()<>?!:"
        for articol in self.lista_articole:
            #lista de cuvinte ale caror sufixe au fost eliminate
            lista_cuvinte_clean = []
            articol_id = articol.id
            text = articol.text.lower()
            lista_cuvinte = text.split()
            for cuvant in lista_cuvinte:
                cuvant = cuvant.strip(sir_strips)
                if len(cuvant) >= 3:
                    cuvant = elimina_sufixe(cuvant)
                    if cuvant not in self.lista_no_words:
                        lista_cuvinte_clean.append(cuvant)
            for cuvant in lista_cuvinte_clean:
                #daca cuvantul nu se afla salvat ca cheie in dictionarul ce este intors ca rezultat
                if (dict_return.has_key(cuvant) != True):
                    dict_return[cuvant] = {"nr_total_aparitii": lista_cuvinte_clean.count(cuvant),
                                           "lista_indecsi": [articol_id], }
                else:
                    #updatam nr. aparitii, daca cuvantul nu a mai aparut in acest articol
                    if dict_return[cuvant]["lista_indecsi"].count(articol_id) == 0:
                        dict_return[cuvant]["nr_total_aparitii"] = dict_return[cuvant]["nr_total_aparitii"] + lista_cuvinte_clean.count(cuvant)
                        dict_return[cuvant]["lista_indecsi"].append(articol_id)
        return dict_return
                
    def compute_poisson(self, dict_indecsi):
        #calculeaza greutatea Poisson pentru fiecare element din dict_indecsi
        #dict_indecsi['iliescu'] = {'lista_indecsi': [10, 627], 'nr_total_aparitii': 44}
        dict_return = {}
        for key, values_dict in dict_indecsi.iteritems():
            lmbd = (values_dict['nr_total_aparitii'] * 1.0 / self.nr_articole)
            poisson0 = math.exp((-1) * lmbd)
            intermed = self.nr_articole * (1 - poisson0)
            overest = (intermed * 1.0 / len(values_dict['lista_indecsi']))
            if overest >= self.limita_poisson:
                dict_return[key] = {'overest': overest, 'lista_indecsi': values_dict['lista_indecsi'], 
                                    'nr_total_aparitii': values_dict['nr_total_aparitii']}
        return dict_return

class SavePoisson:
    """Salveaza rezultatele calculului de probabilitate poisson""" 
    
    def __init__(self, dict_poisson):
        self.dict_poisson = dict_poisson
        self.root = settings.ENGINE_ROOT
        try:
            self.file = open(self.root + 'files/poisson.txt', 'w+')
        except IOError:
            print 'Nu am putut deschide fisierul %sfiles/poisson.txt' %(self.root)
        else:
            self.salveaza_poisson(self.dict_poisson)
            self.file.close()
            
    def salveaza_poisson(self, dict_poisson):
        self.file.truncate(0)
        marshal.dump(dict_poisson, self.file)

class LoadPoisson:
    """Clasa ce incarca termenii pentru care am calculat greutatea Poisson"""
    
    def __init__(self):
        self.root = settings.ENGINE_ROOT
        try:
            self.file = open(self.root + 'files/poisson.txt', 'r+')
        except IOError:
            print 'Nu am putut deschide fisierul %sfiles/poisson.txt' %(self.root)
        else:
            self.dict_poisson = self.get_lista_poisson()
            self.file.close()

    def get_lista_poisson(self):
        return marshal.load(self.file)

if __name__ == "__main__":
    inceput = time.time()
    compute_obj = ComputePoisson()
    dict_cuvinte = compute_obj.proceseaza_articole()
    print len(dict_cuvinte.keys())
    """dict_poisson = compute_obj.compute_poisson(dict_cuvinte)
    save_obj = SavePoisson(dict_poisson)"""
    #loader = LoadPoisson()
    #print loader.lista_poisson
    #print dict_poisson['iliescu']    
    print 'Programul a fost executat in %s secunde' %(str(time.time() - inceput))
    """poisson_loader = LoadPoisson()
    dict_poisson = poisson_loader.dict_poisson"""
    
