class Systeme:
    """permet d'executer un probleme
    - pb : attribut du probleme"""

    def __init__(self,pb):
        """construit un systeme a partir d'un probleme"""
        self.pb=pb

    def execute(self,s,a):
        #print ("etat depart: ",s)
        #print ("action: ",a)
        sArriv = self.pb.transition(s,a)
        #print ("etat arrivee: ",sArriv)
        #print ("recompense: ",self.pb.recompense(s,a,sArriv))
        #print("********")
        return(sArriv)

    def valueIteration(self,nb,gamma):
        Q=self.initialiserQ()
        #nb iteration iteration
        for i in range(0,nb):
            Q=self.executerUneIteration(Q,gamma)
        return(Q)

    def initialiserQ(self):
        Q={}
        for s in self.pb.etats():
            for a in self.pb.actions():
                Q[(s,a)]=0
        return Q

    def executerUneIteration(self,Q,gamma):
        Q2={}
        #pour chaque etat,action
        for etat in self.pb.etats():
            for action in self.pb.actions():
                #calculer arrivee
                sArriv=self.pb.transition(etat,action)
                r=self.pb.recompense(etat,action,sArriv)
                # cherche max arrivee
                max=self.calculerMax(Q,sArriv)
                #mise à jour
                Q2[(etat,action)]=r+gamma*max
        return(Q2)

    def calculerMax(self,Q,sArriv):
        max=-100000
        for actionMax in self.pb.actions():
            if (Q[(sArriv,actionMax)]>max):
                max=Q[(sArriv,actionMax)]
        return(max)
                 
                    
    def executerPi(self,pi,depart,nb):
        s=depart
        for i in range(nb):
            action=pi[s]
            sFin=self.execute(s,action)
            r=self.pb.recompense(s,action,sFin)
            print(s," -> ",action," : ",sFin,"<",r,">")
            s=sFin
                    

    def afficherQ(self,Q):
        for etat in self.pb.etats():
            chaine = ""+str(etat)+" - "
            for action in self.pb.actions():
                chaine+=action+" -> "+str(Q[(etat,action)])+", "
            print(chaine)

    def afficherQS(self,Q,etat):
        chaine = ""+str(etat)+" - "
        for action in self.pb.actions():
            chaine+=action+" -> "+str(Q[(etat,action)])+", "
        print(chaine)
            

    def politiqueFromQ(self,Q):
        pi={}
        for etat in self.pb.etats():
            # cherche max arrivee
            max=-100000
            amax=-1;
            for actionMax in self.pb.actions():
                if (Q[(etat,actionMax)]>max):
                    max=Q[(etat,actionMax)]
                    amax=actionMax
            pi[etat]=amax
        return(pi)

    def apprentissage(self,Sdep):
        print("")
        

    



