"""
Auteur : Stéphane Pasquet
Date : 2021 / 05 / 24
Site : https://mathweb.fr
"""

"""
python.exe -m pip install wheel
python.exe -m pip install giacpy
"""

from giacpy import latex, solve, simplifier, evalf, factoriser
from matplotlib.pyplot import plot, show, savefig, grid
from numpy import linspace
from os import system

class Trinome:
    def __init__(self,a,b,c):
        self.a = a
        self.b = b
        self.c = c
        self.delta = self.b**2 - 4*self.a*self.c
        self.giac_equation = '{}*x*x+{}*x+{}=0'.format(a,b,c)
        self.giac_trinome = '{}*x*x+{}*x+{}'.format(a,b,c)
        
    def __str__(self , tex = False):
        r = self.giac_trinome
        if tex == False:
            r = self.giac_trinome
            r = r.replace('1*' , '')
            r = r.replace('x*x' , 'x²')
            r = r.replace('*' , '')
            r = r.replace('+-' , '-')
            return r
        else:
            r = latex(r).__str__()
            r = r.replace('x\\,x','x^2')
            r = r.replace('\\,' , '')
            return r
        
    # Racines éventuelles
    
    def racines(self , tex = False , approx = False):
        L = simplifier( solve( self.giac_equation ) )
        if approx == False:
            if tex == False:
                if len(L) == 0:
                    return None
                elif len(L) == 1:
                    return L[0].__str__()
                else:
                    return L[0].__str__(), L[1].__str__()
            else:
                if len(L) == 0:
                    return "\\text{Pas de racines réelles}"
                elif len(L) == 1:
                    return latex(L[0].__str__())
                else:
                    return latex(L[0].__str__()), latex(L[1].__str__())
        else:
            if len(L) == 2:
                x1 = evalf('{}'.format(L[0]))
                x2 = evalf('{}'.format(L[1]))
                return x1, x2
            elif len(L) == 1:
                x0 = evalf('{}'.format(L[0]))
                return x0
            else:
                return None
    # Factorisation
    
    def factorise(self , tex = False):
        r = factoriser( self.giac_trinome ).__str__()
        if tex == False:
            return r
        else:
            return latex( r )
        
    # Forme canonique
    
    def canonique(self , tex = False):
        alpha = simplifier('{}/(2*{})'.format(-self.b,self.a))
        beta = simplifier('-{}/(4*{})'.format(self.delta,self.a))
        r = '{}*(x-{})^2 + {}'.format(self.a,alpha,beta)
        if tex == False:
            r = r.replace('1*' , '')
            r = r.replace('^2' , '²')
            r = r.replace('*' , '')
            r = r.replace('+-' , '-')
            return r
        else:
            r = latex(r).__str__()
            return r
        
    # Tableau de signes
    
    def signe(self , tex = False):
        if tex == False:
            ligne = [ ['','',''] , ['','',''] , ['','',''] ]
            # delta > 0
            ligne[0][0] = '|  x   |-∞     x₁     x₂     +∞|'
            ligne[0][1] = '| P(x) |    +   0  -   0  +    |' # a > 0
            ligne[0][2] = '| P(x) |    -   0  +   0  -    |' # a < 0
            #
            ligne[1][0] = '|  x   |-∞     x₁     +∞|'
            ligne[1][1] = '| P(x) |    +  0   +    |'
            ligne[1][2] = '| P(x) |    -  0   -    |'
            #
            ligne[2][0] = '|  x   |-∞          +∞|'
            ligne[2][1] = '| P(x) |       +      |'
            ligne[2][2] = '| P(x) |       -      |'
            
            if self.delta > 0:
                if self.a > 0:
                    result = '-'*len(ligne[0][0]) + '\n' + ligne[0][0] + '\n' +\
                             '-'*len(ligne[0][0]) + '\n' + ligne[0][1] + '\n' + '-'*len(ligne[0][0])
                else:
                    result = '-'*len(ligne[0][0]) + '\n' + ligne[0][0] + '\n' +\
                             '-'*len(ligne[0][0]) + '\n' + ligne[0][2] + '\n' + '-'*len(ligne[0][2])
            elif self.delta == 0:
                if self.a > 0:
                    result = '-'*len(ligne[1][0]) + '\n' + ligne[1][0] + '\n' +\
                             '-'*len(ligne[1][0]) + '\n' + ligne[1][1] + '\n' + '-'*len(ligne[1][0])
                else:
                    result = '-'*len(ligne[1][0]) + '\n' + ligne[1][0] + '\n' +\
                             '-'*len(ligne[1][0]) + '\n' + ligne[1][2] + '\n' + '-'*len(ligne[1][0])
            else:
                if self.a > 0:
                    result = '-'*len(ligne[2][0]) + '\n' + ligne[2][0] + '\n' +\
                             '-'*len(ligne[2][0]) + '\n' + ligne[2][1] + '\n' + '-'*len(ligne[2][0])
                else:
                    result = '-'*len(ligne[2][0]) + '\n' + ligne[2][0] + '\n' +\
                             '-'*len(ligne[2][0]) + '\n' + ligne[2][2] + '\n' + '-'*len(ligne[2][0])
                    
            return result
        else:
            r = "\\begin{tikzpicture}\n"
            r += "\\tkzTabInit[lgt=1.2,color,colorV=gray!20,colorL=gray!20,colorC=gray!20]{$x$/0.75,$P(x)$/0.75}{$-\\infty$,"
            if self.delta < 0:
                r += "$+\\infty$"
            elif self.delta == 0:
                x0 = self.racines(tex = True)
                r += "$" + x0.__str__().replace('"','') + "$ , $+\\infty$"
            else:
                x1, x2 = self.racines(tex = True)
                r += "$" + x1.__str__().replace('"','') + "$ , $" + x2.__str__().replace('"','') + "$ , $+\\infty$"
            r += "}\n"
            r += "\\tkzTabLine{,"
            if self.delta < 0:
                if self.a < 0:
                    r += "-"
                else:
                    r += "+"
            elif self.delta == 0:
                if self.a < 0:
                    r += "-,z,-"
                else:
                    r += "+,z,+"
            else:
                if self.a < 0:
                    r += "-,z,+,z,+"
                else:
                    r += "+,z,-,z,+"
            r += "}\n"
            r += "\\end{tikzpicture}\n"
            
            return r
        
    # Dessine la parabole
    
    def draw(self , tex = False , e = 5, namepic = 'parabole.png'):
        x = linspace(-self.b/(2*self.a)-e,-self.b/(2*self.a)+e,100)
        y = self.a * x**2 + self.b*x + self.c
        plot(x,y)
        grid()
        if tex == True:
            savefig( namepic , bbox_inches='tight' , dpi = 300)
        else:
            show()
            
    # Exportation en LaTeX
    
    def export_latex(self , filename = 'trinome.tex'):            
        doc = "\\documentclass[a4paper]{article}\n"
        doc += "\\usepackage[T1]{fontenc}\n"
        doc += "\\usepackage{tkz-tab}\n"
        doc += "\\usepackage{amsmath}\n"
        doc += "\\usepackage[margin=2cm]{geometry}\n"
        doc += "\\setlength{\\parindent}{0pt}\n"
        doc += "\\begin{document}\n"
        doc += "\\begin{center}\n"
        doc += "\\Huge\\bfseries\\boldmath Polynôme  $" + self.__str__(tex = True).replace('"','') + "$\n"
        doc += "\\end{center}\n\\bigskip\n"
        doc += "\\begin{itemize}\n"
        
        # Discriminant
        doc += "\\item[\\textbullet] Discriminant: \\[ \\Delta = {} \\]".format(self.delta)
        
        # Racines exactes
        if self.delta > 0:
            x1, x2 = self.racines( tex = True )
            doc += "\\item[\\textbullet] Valeur exacte des racines: \\[ {} \\qquad ; \\qquad {} \\]".format( x1.__str__().replace('"','') , x2.__str__().replace('"','') )
        elif self.delta == 0:
            x0 = self.racines( tex = True )
            doc += "\\item[\\textbullet] Valeur exacte de la racine double: \\[ {} \\]".format( x0.__str__().replace('"','') )

        # Racines en valeurs approchées
        if self.delta > 0:
            x1, x2 = self.racines( tex = True , approx = True)
            doc += "\\item[\\textbullet] Valeurs approchées des racines: \\[ {} \\qquad ; \\qquad {} \\]".format( x1.__str__().replace('"','') , x2.__str__().replace('"','') )
        elif self.delta == 0:
            x0 = self.racines( tex = True , approx = True)
            doc += "\\item[\\textbullet] Valeur exacte de la racine double: \\[ {} \\]".format( x0.__str__().replace('"','') )

        # Factorisation
        doc += "\\item[\\textbullet] Factorisation éventuelle: \\[ {} \\]".format( self.factorise( tex = True ).__str__().replace('"','') )
        
        # Forme canonique
        doc += "\\item[\\textbullet] Forme canonique: \\[ {} \\]".format( self.canonique( tex = True ).__str__().replace('"','') )
        
        # Tableau de signes
        doc += "\\item[\\textbullet] Tableau de signes:\n\\begin{center}\n" + self.signe(tex = True) + "\n\\end{center}\n"
        
        # Parabole
        self.draw(tex = True , namepic = filename[:-3]+"png")
        doc += "\\item[\\textbullet] Parabole:\n\\begin{center}\n\\includegraphics{" + filename[:-3] + "png}\n\\end{center}"

        doc += "\n\\end{itemize}\n"
        doc += "\\end{document}"
        
        Fichier = open(filename , 'w' , encoding = 'utf8')
        Fichier.write( doc )
        Fichier.close()
        
        system('pdflatex '+filename)
        system('start '+filename[:-3] + 'pdf')

"""
Fin de la classe
"""

P = Trinome(-2,3,4) # 2 racines
#P = Trinome(1,-2,1) # 1 racine
#P = Trinome(-1,-1,-1) # 0 racine
#P = Trinome(1,0,-1)

#print( P.racines(tex = False|True , approx=False|True) )
#print ( P.factorise(tex = True|False) )
#print( P.__str__(tex = True|False) )
#print( P.canonique(tex = True|False) )
#print( P.signe(tex = True|False) )
#P.draw(e = 5<par defaut>, tex = False|True , namepic = 'nom image.jpg|png')

#P.export_latex(filename='nom fichier.tex')
