# -*- coding:latin-1 -*-
import random
import codecs

from Traducir import tr
from Constantes import *

import Partida
import ControlPosicion

# ---------------------------------------------------------------------------------------------
class RespuestaMotor :
    def __init__( self, nombre ) :
        self.nombre = nombre
        self.sinInicializar = True
        self.mate = 0
        self.puntos = 0
        self.sinMovimientos = False # o por jaquemate o por ahogado
        self.pv = "a1a1"
        self.desde = ""
        self.hasta = ""
        self.coronacion = ""
        self.depth = 0

        self.tiempo = 0

        self.maxTiempo = 0

    # -----------------------------------------------------------------------------------------
    def __str__( self ) :
        resp = ""
        for x in [ "sinInicializar", "mate", "puntos", "sinMovimientos", "pv", "desde", "hasta", "coronacion", "depth"] :
            resp += x + " : " + str( eval("self.%s"%x) ) + "  "
        return resp

    # -----------------------------------------------------------------------------------------
    def movimiento( self ) :
        return self.desde + self.hasta + self.coronacion

    # -----------------------------------------------------------------------------------------
    def cambiaColor( self, posicionAnterior=None ) :
        # Se usa en tutor para analizar las jugadas siguientes a la del usuario
        # Si no encuentra ninguna jugada y la jugada previa es jaque, pasa a mate en 1
        if posicionAnterior and self.sinMovimientos :
            if posicionAnterior.siJaque() :
                self.mate = 1
                return
        self.puntos = -self.puntos
        if self.mate :
            self.mate = -self.mate
            if self.mate > 0 :
                self.mate += 1

    # -----------------------------------------------------------------------------------------
    def siMejorQue( self, otra, difpts=0, difporc=0 ) :
        if self.mate :
            if otra.mate < 0 :
                if self.mate < 0 :
                    return self.mate < otra.mate
                else :
                    return True
            elif otra.mate > 0 :
                if self.mate < 0 :
                    return False
                else :
                    return self.mate < otra.mate
            else :
                return self.mate > 0
        elif otra.mate :
            return otra.mate < 0
        dif = self.puntos - otra.puntos
        if dif <= 0 :
            return False
        adif = abs(dif)
        if difpts :
            if adif <= difpts :
                return False
        if difporc :
            porc = int(abs(self.puntos)*difporc/100)
            if adif < porc :
                return False
        return True

    # -----------------------------------------------------------------------------------------
    def puntosABS( self ) :
        if self.mate :
            if self.mate < 0 :
                puntos = -10000 - (self.mate+1)*10
            else :
                puntos = +10000 - (self.mate-1)*10
        else :
            puntos = self.puntos

        return puntos

    # -----------------------------------------------------------------------------------------
    def texto( self ) :
        if self.mate > 0 :
            if self.mate == 1 :
                return tr( "MATE" )
            else :
                return tr( "MATE_EN", str(self.mate) )
        elif self.mate < 0 :
            if self.mate == -1 :
                return tr( "NOS_HACEN_MATE" )
            else :
                return tr( "NOS_HACEN_MATE_EN", str(-self.mate) )
        else :
            return "%d %s"%(self.puntos,tr( "PUNTOS" ) )

    # -----------------------------------------------------------------------------------------
    def base2texto( self ) :
        txt = ""
        for clave, texto in (   ( "NOMBRE", self.nombre ), \
                                ( "SININICIALIZAR", "S" if self.sinInicializar else "N" ), \
                                ( "MATE", str(self.mate) ), \
                                ( "PUNTOS", str(self.puntos) ), \
                                ( "SINMOVIMIENTOS", "S" if self.sinInicializar else "N" ), \
                                ( "PV", self.pv ), \
                                ( "DESDE", self.desde ), \
                                ( "HASTA", self.hasta ), \
                                ( "CORONACION", self.coronacion ), \
                                ( "DEPTH", str(self.depth) ) ) :
            txt += "%s=%s\n"%(clave, texto)
        return txt

    # -----------------------------------------------------------------------------------------
    def texto2base( self, texto ) :

        for linea in texto.split( "\n" ) :
            pos = linea.find( "=" )
            if pos > 0 :
                clave = linea[:pos]
                eti = linea[pos+1:].strip()
                if clave == "NOMBRE" :
                    self.nombre = eti
                elif clave == "SININICIALIZAR" :
                    self.sinInicializar = eti == "S"
                elif clave == "MATE" :
                    self.mate = int(eti)
                elif clave == "PUNTOS" :
                    self.puntos = int(eti)
                elif clave == "SINMOVIMIENTOS" :
                    self.sinMovimientos = eti == "S"
                elif clave == "PV" :
                    self.pv = eti
                elif clave == "DESDE" :
                    self.desde = eti
                elif clave == "HASTA" :
                    self.hasta = eti
                elif clave == "CORONACION" :
                    self.coronacion = eti
                elif clave == "DEPTH" :
                    self.depth = int(eti)

# ---------------------------------------------------------------------------------------------
class MRespuestaMotor :
    def __init__( self, nombre ) :
        self.nombre = nombre
        self.tiempo = 0

        self.depth = 0

        self.maxTiempo = 0
        self.maxProfundidad = 0

        self.dicMultiPV = {}
        self.liMultiPV = [] # Ordenados de mejor a peor, se hace tras dispatch

    # -----------------------------------------------------------------------------------------
    def mejorRMQue( self, rm, difpts, difporc ) :
        if self.liMultiPV :
            return self.liMultiPV[0].siMejorQue( rm, difpts, difporc )
        else :
            return False

    # -----------------------------------------------------------------------------------------
    def buscaRM( self, movimiento ) :
        movimiento = movimiento.lower()
        for n, rm in enumerate(self.liMultiPV) :
            if rm.movimiento() == movimiento :
                return rm, n
        return None, -1

    # -----------------------------------------------------------------------------------------
    def mejorMovQue( self, movimiento ) :
        if self.liMultiPV :
            rm, n = self.buscaRM( movimiento )
            if rm is None :
                return True
            if n == 0 :
                return False
            return self.liMultiPV[0].siMejorQue( rm, 0, 0 )
        return False

    # -----------------------------------------------------------------------------------------
    def mejorMov( self ) :
        if self.liMultiPV :
            return self.liMultiPV[0]
        return RespuestaMotor( self.nombre )

    # -----------------------------------------------------------------------------------------
    def mejorMovDetectaBlunders( self, fdbg, mindifpuntos, maxmate ) :
        rm0 = self.liMultiPV[0]
        if maxmate :
            if 0 < rm0.mate <= maxmate :
                if fdbg :
                    fdbg.write( "1. %s : %s %d <= %d\n"%(rm0.pv,tr("MATE"),rm0.mate, maxmate) )
                return True
        if mindifpuntos :
            partidaBase = self.partida # asignada por el gestorMotor
            numJugadas = partidaBase.numJugadas()
            puntosPrevios = 0
            if numJugadas >= 3 :
                jg = partidaBase.liJugadas[numJugadas-3]
                if hasattr( jg, "puntosABS_3" ) : # se graban en mejormovajustado
                    puntosPrevios = jg.puntosABS_3
            difpuntos = rm0.puntosABS() - puntosPrevios # son puntos ganados por el motor y perdidos por el jugador
            if difpuntos >  mindifpuntos :
                if fdbg :
                    fdbg.write( "1. %s : %s %d > %d\n"%(rm0.pv,tr("PUNTOS_PERDIDOS"),difpuntos, mindifpuntos) )
                return True
        return False

    # -----------------------------------------------------------------------------------------
    def ajustaPersonalidad( self, una ) :
        def x( clave ) :
            return una.get(clave,0)

        cp = ControlPosicion.ControlPosicion()
        cp.leeFen( self.fenBase )

        dbg = x( "DEBUG" )
        if dbg :
            fdbg = codecs.open(dbg, "ab", 'utf-8')
            fdbg.write( "\n%s\n"%cp.muestra() )
            dpr = tr( "PERSON_PREVISTO" )
        else :
            fdbg = None

        # Aterrizaje
        aterrizaje = una.get( "ATERRIZAJE", 50 )

        # Blunders
        mindifpuntos = x( "MINDIFPUNTOS" )
        maxmate = x( "MAXMATE" )
        if self.mejorMovDetectaBlunders( fdbg, mindifpuntos, maxmate ) :
            if fdbg :
                fdbg.close()
            return kAjustarMejor, mindifpuntos, maxmate, dbg, aterrizaje

        # Comprobamos donde estamos, si medio o final
        tipo = "F" if cp.totalPiezas() <= x( "MAXPIEZASFINAL" ) else ""

        # Variable a analizar
        xMpn = x("MOVERPEON"+tipo)
        xApz = x("AVANZARPIEZA"+tipo)
        xJ = x("JAQUE"+tipo)
        xC = x("CAPTURAR"+tipo)

        x2B = x("2BPR"+tipo)
        xAvPR = x("AVANZARPR"+tipo)
        xJPR = x( "JAQUEPR"+tipo )
        xCPR = x( "CAPTURARPR"+tipo )

        # Miramos todas las propuestas
        for num,rm in enumerate(self.liMultiPV) :
            partida = Partida.Partida(cp).leerPV(rm.pv)
            jg0 = partida.liJugadas[0]
            ps0 = partida.iniPosicion
            psZ = partida.ultPosicion

            if dbg :
                pgn = ""
                si = False
                for jg in partida.liJugadas :
                    pgn += jg.pgnEN() + " "
                    if si :
                        pgn += "- "
                    si = not si
                pgn = pgn.strip("- ")

                if rm.mate :
                    fdbg.write( "%2d. %s : %d %s\n"%(num+1,pgn, rm.mate,tr("MATE")) )
                else :
                    fdbg.write( "%2d. %s : %d\n"%(num+1,pgn,rm.puntos) )

            if rm.mate :
                continue

            if xMpn :
                if ps0.casillas[jg0.desde].lower() == "p" :
                    rm.puntos += xMpn
                    if dbg :
                        fdbg.write( "    %s : %d -> %d\n"%(tr("PERSON_MOVERPEON"), xMpn,rm.puntos) )

            if xApz :
                if ps0.casillas[jg0.desde].lower() != "p" :
                    if tipo == "F" :
                        dif = ps0.distanciaPiezaKenemigo( jg0.desde )-ps0.distanciaPiezaKenemigo( jg0.hasta )
                    else :
                        nd = int(jg0.desde[1])
                        nh = int(jg0.hasta[1])
                        dif = nh-nd
                        if not ps0.siBlancas :
                            dif = -dif
                    if dif > 0 :
                        rm.puntos += xApz
                        if dbg :
                            fdbg.write( "    %s : %d -> %d\n"%(tr("PERSON_AVANZARPIEZA"), xApz,rm.puntos) )

            if xJ :
                if jg0.siJaque :
                    rm.puntos += xJ
                    if dbg :
                        fdbg.write( "    %s : %d -> %d\n"%(tr("PERSON_JAQUE"), xJ, rm.puntos) )

            if xC :
                if jg0.siCaptura() :
                    rm.puntos += xC
                    if dbg :
                        fdbg.write( "    %s : %d -> %d\n"%(tr("PERSON_CAPTURAR"), xJ, rm.puntos) )

            if x2B :
                if psZ.numPiezas( "B" ) == 2 :
                    rm.puntos += x2B
                    if dbg :
                        fdbg.write( "    %s : %d -> %d \n"%(tr("PERSON_2B"), x2B, rm.puntos) )

            if xAvPR :
                pZ = psZ.pesoWB()
                p0 = ps0.pesoWB()
                valorWB =  pZ - p0
                if not cp.siBlancas :
                    valorWB = -valorWB
                if valorWB > 0 :
                    rm.puntos += xAvPR
                    if dbg :
                        if not cp.siBlancas :
                            p0 = -p0
                            pZ = -pZ
                        fdbg.write( "    %s (%s) : %d -> %d [%d => %d]\n"%(tr("PERSON_AVANZAR"), dpr, xAvPR, rm.puntos,p0,pZ) )

            if xJPR :
                n = True
                for jg in partida.liJugadas :
                    if n and jg.siJaque :
                        rm.puntos += xJPR
                        if dbg :
                            fdbg.write( "    %s (%s) : %d -> %d\n"%(tr("PERSON_JAQUE"), dpr, xJPR, rm.puntos) )
                        break
                    n = not n

            if xCPR :
                n = True
                for jg in partida.liJugadas :
                    if n and jg.siCaptura() :
                        rm.puntos += xCPR
                        if dbg :
                            fdbg.write( "    %s (%s) : %d -> %d\n"%(tr("PERSON_CAPTURAR"), dpr, xCPR, rm.puntos) )
                        break
                    n = not n

        # Ordenamos
        li = []
        for rm in self.liMultiPV :
            elpeor = True
            for n, rm1 in enumerate(li) :
                if rm.siMejorQue( rm1, 0, 0 ) :
                    li.insert( n, rm )
                    elpeor = False
                    break
            if elpeor :
                li.append( rm )
        self.liMultiPV = li

        if dbg :
            fdbg.write( "Result :\n" )
            for num, rm in enumerate(self.liMultiPV) :
                partida = Partida.Partida(cp).leerPV(rm.pv)

                pgn = ""
                si = False
                for jg in partida.liJugadas :
                    pgn += jg.pgnEN() + " "
                    if si :
                        pgn += "- "
                    si = not si
                pgn = pgn.strip("- ")

                if rm.mate :
                    fdbg.write( "%d. %s : %d %s\n"%(num+1,pgn, rm.mate,tr("MATE")) )
                else :
                    fdbg.write( "%d. %s : %d\n"%(num+1,pgn,rm.puntos) )

            fdbg.write( "\n" )
            fdbg.close()

        return una.get( "AJUSTARFINAL" if tipo == "F" else "AJUSTAR", kAjustarMejor ), mindifpuntos, maxmate, dbg, aterrizaje

    # -----------------------------------------------------------------------------------------
    def mejorMovAjustadoNivel( self, nTipo ) :
        if nTipo == kAjustarNivelAlto :
            dic = { kAjustarMejor:60, kAjustarSuperiorMM:30, kAjustarSuperiorM:15, kAjustarSuperior:10, kAjustarSimilar:5 }
        elif nTipo == kAjustarNivelMedio :
            dic = { kAjustarSuperiorMM:5, kAjustarSuperiorM:10, kAjustarSuperior:25, kAjustarSimilar:60, kAjustarInferior:25, kAjustarInferiorM:10, kAjustarInferiorMM:5 }
        elif nTipo == kAjustarNivelBajo :
            dic = { kAjustarSimilar:25, kAjustarInferior:60, kAjustarInferiorM:25, kAjustarInferior:10 }
        tp = 0
        for k, v in dic.iteritems() :
            tp += v
        sel = random.randint(1,tp)
        t = 0
        for k, v in dic.iteritems() :
            t += v
            if sel <= t :
                return k
    # -----------------------------------------------------------------------------------------
    def mejorMovAjustadoSuperior( self, nivel, mindifpuntos, maxmate, aterrizaje ) :

        if self.mejorMovDetectaBlunders( None, mindifpuntos, maxmate ) :
            return self.liMultiPV[0]

        # Buscamos una jugada positiva que no sea de mate
        # Si no la hay, cogemos el último
        rmIni = None
        for rm in self.liMultiPV :
            if rm.mate == 0 :
                rmIni = rm
                break
        if rmIni is None :
            return self.liMultiPV[-1] # Mandamos el mate peor

        ptsIni = rmIni.puntosABS()
        if ptsIni > aterrizaje :
            minimo = ptsIni - aterrizaje
        else :
            minimo = 0

        li = []
        for rm in self.liMultiPV :
            pts = rm.puntosABS()
            if pts < minimo :
                break
            li.append( rm )

        if not li :
            return self.liMultiPV[0]
        nLi = len(li)

        return li[0] if nLi < nivel else li[-nivel]

    # -----------------------------------------------------------------------------------------
    def mejorMovAjustadoInferior( self, nivel, mindifpuntos, maxmate, aterrizaje ) :

        if self.mejorMovDetectaBlunders( None, mindifpuntos, maxmate ) :
            return self.liMultiPV[0]

        # Buscamos una jugada positiva que no sea de mate
        # Si no la hay, cogemos el último
        rmIni = None
        for rm in self.liMultiPV :
            if rm.mate == 0 :
                rmIni = rm
                break
        if rmIni is None :
            return self.liMultiPV[-1] # Mandamos el mate peor

        ptsIni = rmIni.puntosABS()
        if ptsIni > aterrizaje : # el motor hace una jugada bastante peor, pero no malísima
            minimo = ptsIni - aterrizaje
        else :
            minimo = 0

        li = []
        for rmSel in self.liMultiPV :
            pts = rmSel.puntosABS()
            if pts < minimo :
                li.append(rmSel)
        if not li :
            return self.liMultiPV[-1] # Mandamos la jugada peor
        nLi = len(li)

        return li[-1] if nLi < nivel else li[nivel-1]

    # -----------------------------------------------------------------------------------------
    def mejorMovAjustadoSimilar( self, mindifpuntos, maxmate, aterrizaje ) :

        if self.mejorMovDetectaBlunders( None, mindifpuntos, maxmate ) :
            return self.liMultiPV[0]

        # Buscamos una jugada positiva que no sea de mate
        # Si no la hay, cogemos el último
        rmIni = None
        for rm in self.liMultiPV :
            if rm.mate == 0 :
                rmIni = rm
                break
        if rmIni is None :
            return self.liMultiPV[-1] # Mandamos el mate peor

        ptsIni = rmIni.puntosABS()
        if ptsIni > aterrizaje : # el motor hace una jugada peor, pero no malísima
            minimo = ptsIni - aterrizaje
        else :
            minimo = 0

        rmAnt = self.liMultiPV[0]
        rmSel = rmAnt
        ptsAnt = rmAnt.puntosABS()
        for rm in self.liMultiPV :
            pts = rm.puntosABS()
            if pts < minimo :
                rmSel = rm if abs(ptsAnt) > abs(pts) else rmAnt
                break
            rmAnt = rm
            ptsAnt = pts
        return rmSel

    # -----------------------------------------------------------------------------------------
    def mejorMovAjustado( self, nTipo ) :
        if self.liMultiPV :

            rmSel =  None
            aterrizaje = 50
            siPersonalidad = nTipo >= 1000 # Necesario para grabar los puntos
            dbg = None

            if siPersonalidad :
                nTipo, mindifpuntos, maxmate, dbg, aterrizaje = self.ajustaPersonalidad( self.liPersonalidades[nTipo-1000] )

            if nTipo == kAjustarMejor :
                rmSel = self.liMultiPV[0]
            elif nTipo == kAjustarPeor :
                rmSel = self.liMultiPV[-1]
            elif nTipo in ( kAjustarNivelAlto, kAjustarNivelBajo, kAjustarNivelMedio ) :
                nTipo = self.mejorMovAjustadoNivel( nTipo ) # Se corta el if para que se calcule el nTipo

            if nTipo in ( kAjustarSuperior, kAjustarSuperiorM, kAjustarSuperiorMM ) :
                nivel = { kAjustarSuperior:1, kAjustarSuperiorM:2, kAjustarSuperiorMM:3 }
                if not siPersonalidad :
                    mindifpuntos, maxmate = 200, 2
                rmSel = self.mejorMovAjustadoSuperior( nivel[nTipo], mindifpuntos, maxmate, aterrizaje )

            elif nTipo == kAjustarSimilar :
                if not siPersonalidad :
                    mindifpuntos, maxmate = 300, 1
                rmSel = self.mejorMovAjustadoSimilar( mindifpuntos, maxmate, aterrizaje )

            elif nTipo in ( kAjustarInferior, kAjustarInferiorM, kAjustarInferiorMM ) :
                nivel = { kAjustarInferior:1, kAjustarInferiorM:2, kAjustarInferiorMM:3 }
                if not siPersonalidad :
                    mindifpuntos, maxmate = 400, 1
                rmSel = self.mejorMovAjustadoInferior( nivel[nTipo], mindifpuntos, maxmate, aterrizaje )

            if rmSel is None :
                rmSel = self.liMultiPV[0]

            # Para comprobar pérdida de puntos
            if self.partida.numJugadas() :
                self.partida.liJugadas[-1].puntosABS_3 = rmSel.puntosABS()

            return rmSel
        return RespuestaMotor( self.nombre )

    # -----------------------------------------------------------------------------------------
    def rmMultiPV( self, movim ) :
        movim = movim.lower()
        for k, rm in self.dicMultiPV.iteritems() :
            if rm.pv.split(" ")[0] == movim :
                return rm, k
        return None, None

    # -----------------------------------------------------------------------------------------
    def dispatch( self, mensaje, maxTiempo, maxProfundidad ) :
        self.maxTiempo = maxTiempo
        self.maxProfundidad = maxProfundidad
        for linea in mensaje.split("\n") :
            if linea.startswith( "info " ) and " pv " in linea:
                self.miraPV( linea[5:] )

            elif linea.startswith( "bestmove" ) :
                self.miraBestMove( linea )

        # Ordenamos
        self.liMultiPV = []
        for k, rm in self.dicMultiPV.iteritems() :
            elpeor = True
            for n, rm1 in enumerate(self.liMultiPV) :
                if rm.siMejorQue( rm1, 0, 0 ) :
                    self.liMultiPV.insert( n, rm )
                    elpeor = False
                    break
            if elpeor :
                self.liMultiPV.append( rm )

    # -----------------------------------------------------------------------------------------
    def miraPV( self, pvBase ) :
        dClaves = self.miraClaves( pvBase, ( "multipv", "depth", "seldepth", "score", "time", "nodes", "pv", "hashfull", "tbhits", "nps" ) )

        if "pv" in dClaves :
            pv = dClaves["pv"].strip()
            if not pv :
                return
        else :
            return

        if "nodes" in dClaves : # Toga en multipv, envia 0 si no tiene nada que contar
            if (dClaves["nodes"] == "0") and ("mate" not in pvBase) :
                return

        if ("multipv" in dClaves) :
            kMulti = dClaves["multipv"]
            if kMulti not in self.dicMultiPV :
                self.dicMultiPV[kMulti]= RespuestaMotor( self.nombre )
        else:
            if len( self.dicMultiPV ) == 0 :
                kMulti = "1"
                self.dicMultiPV[kMulti]= RespuestaMotor( self.nombre )
            else:
                kMulti = self.dicMultiPV.keys()[0]

        rm = self.dicMultiPV[kMulti]
        rm.sinInicializar = False

        if "depth" in dClaves :
            depth = int(dClaves["depth"].strip())
            if self.maxProfundidad :
                if rm.desde : # Es decir que ya tenemos datos (rm.pv al principio = a1a1
                    if (depth > self.maxProfundidad) and (depth > rm.depth ) :
                        return
            rm.depth = depth

        if "score" in dClaves :
            score = dClaves["score"].strip()
            if score.startswith( "cp " ) :
                rm.puntos = int( score.split(" ")[1] )
                rm.mate = 0
                rm.sinMovimientos = False
            elif score.startswith( "mate " ) :
                rm.puntos = 0
                rm.mate = int( score.split( " " )[1] )

        if "pv" in dClaves :
            pv = dClaves["pv"].strip()
            x = pv.find( " " )
            pv1 = pv[:x] if x >= 0 else pv
            rm.pv = pv
            rm.desde = pv1[:2]
            rm.hasta = pv1[2:4]
            rm.coronacion = pv1[4] if len(pv1)==5 else ""

    # -----------------------------------------------------------------------------------------
    def miraBestMove( self, bestmove ) :
        if len( self.dicMultiPV ) >= 1 :
            return
        if "1" not in self.dicMultiPV :
            self.dicMultiPV["1"] = RespuestaMotor( self.nombre )
        rm = self.dicMultiPV["1"]

        rm.sinInicializar = False
        dClaves = self.miraClaves( bestmove, ( "bestmove", "ponder" ) )
        rm.desde = ""
        rm.hasta = ""
        rm.coronacion = ""
        rm.sinMovimientos = False
        if "bestmove" in dClaves :
            bestmove = dClaves["bestmove"].strip()
            rm.sinMovimientos = True
            if bestmove :
                if len(bestmove) >= 4 :
                    def bien( a8 ) :
                        return a8[0] in "abcdefgh" and a8[1] in "12345678"
                    d = bestmove[:2]
                    h = bestmove[2:4]

                    if bien( d ) and bien( h ) :
                        rm.sinMovimientos = d == h
                        rm.desde = d
                        rm.hasta = h
                        if len(bestmove) == 5 and bestmove[4].lower() in "qbrn" :
                            rm.coronacion = bestmove[4]
                        if rm.pv == "a1a1" : # No muestra pvs solo directamente
                            rm.pv = bestmove

        else :
            rm.sinMovimientos = True

    # -----------------------------------------------------------------------------------------
    def miraClaves( self, mensaje, liClaves ) :
        dClaves = {}
        clave = ""
        dato = ""
        for palabra in mensaje.split( " " ) :
            if palabra in liClaves :
                if clave :
                    dClaves[clave] = dato.strip()
                clave = palabra
                dato = ""
            else :
                dato += " " + palabra
        if clave :
            dClaves[clave] = dato.strip()
        return dClaves

