#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# ND july 2011 
# convert TDB to nice pdf via LaTeX
# for a system up to 5 elements

import subprocess
from string import lower
from string import upper
from string import ascii_letters

def chiffre(s):
# 1 if s est un nombre, 0 sinon
    test=1
    try:
        float(s)
    except ValueError:
        test=0
    return test

def lettre(a):
# 1 if a est une lettre, 0 sinon
    test=0
    if a in ascii_letters:
        test=1
    return test

def check_ord(ph):
# le rang de ph dans tab_ord si elle a une contribution ordonnee, -1 sinon
    test=-1
    for i in range(len(tab_ord)):
        if ph==tab_ord[i][0]:
            test=i
    return test

# renvoie le nom d'une phase dans un format adapté à Latex
def nom_ph(phase):
    for i in range(len(tab_ph)):
        if phase==tab_ph[i][0]:
            nom=tab_ph[i][1].replace('\rm','\\rm')
    return nom

# renvoie le nom d'une espèce dans un format adapté à Latex
def nom_sp(species):
    nom='{\Box}'
# change nom si l'espèce est *
    if species=='*':
       nom='*' 
# change nom si l'espèce est un element
    for i in range(len(tab_elt)):
        if species==tab_elt[i][0]:
            nom=tab_elt[i][1]
# change nom si l'espèce est une espèce plus complexe
    for i in range(len(tab_sp)):
        if species==tab_sp[i][0]:
            nom=tab_sp[i][1]
    nom=nom.replace('\rm','\\rm')
    return nom

# renvoie le nom d'une constitution dans un format adapté à Latex
def nom_cst(txt):
#    print txt
    a=txt.replace(',',' , ').replace(':',' : ')
    a=a.split()
#    print a
    nom=''
    lim=[',',':']
    for i in range(len(a)):
        if a[i] in lim:
            nom=nom+a[i]
        else:
            nom=nom+nom_sp(a[i])
#    print nom
    return nom

# renvoie une jolie fonction dans un format adapté à Latex
def nice_fun(fun):
    fun=fun.replace('#','')
    for i in range(9):
        fun=fun.replace('**(-'+str(i)+')','^{-'+str(i)+'}')
        fun=fun.replace('**'+str(i),'^{'+str(i)+'}')
    fun=fun.replace('RTLNP','\,R\,T\,\ln (10^{-5}\,.\,P)')
    fun=fun.replace('*LN','\,\ln')
    fun=fun.replace('(1E-05','(10^{-5}')
    fun=fun.replace('+','\,+\,')
    fun=fun.replace('-','\,-\,')    
    for i in range(10):
        fun=fun.replace('E\,-\,0'+str(i)+'*T','.10^{-'+str(i)+'}\,T')
        fun=fun.replace('E\,+\,0'+str(i)+'*T','.10^{'+str(i)+'}\,T')
    for i in range(10,32):
        fun=fun.replace('E\,-\,'+str(i)+'*T','.10^{-'+str(i)+'}\,T')
        fun=fun.replace('E\,+\,'+str(i)+'*T','.10^{'+str(i)+'}\,T')
    fun=fun.replace('*','\ ')
    fun=fun.replace('\,-\,.','\,-\,0.')
    fun=fun.replace('\,+\,.','\,+\,0.')
    return fun

# renvoie une jolie fonction, 
# sur plusieurs intervalles si nécessaire
# dans un format adapté à Latex
def joli_fun(txt):
    tmin=str(298.15)
    tmax=''
    ttfun=[]
    tint=''
    a=txt.split()
    ay=-1
    for n in range(len(a)):
        if a[n]=='Y':
            tmax=str(float(a[n-1]))
            ttfun=ttfun+[[tmin,tmax]]
            tmin=tmax
            ay=n
    if tmax=='':
        tint=nice_fun(a[1][:a[1].find(';')])
        tint='$'+tint+'$'
        if a[-1]!='N':
            tint=tint+' \dotfill  '+a[-1]
    else:
        for n in range(len(ttfun)):
            tmin=ttfun[n][0]
            tmax=ttfun[n][1]
            tint=tint+'\n\n$'+nice_fun(a[1+3*n][:a[1+3*n].find(';')])+'$ \mbox{ } \dotfill \mbox{\ for '+tmin+'$<T<$'+tmax+'}\n\n'
        if a[-1]=='N':
            tint=tint+'$'+nice_fun(a[ay+1][:a[ay+1].find(';')])+'$ \mbox{ } \dotfill \mbox{\ for $T>$'+tmax+'}\n'
        else:
            tint=tint+'$'+nice_fun(a[ay+1][:a[ay+1].find(';')])+'$ \mbox{ } \dotfill \mbox{\ for $T>$'+tmax+'}\n\n \ \dotfill \ '+a[-1]+'\n'
    return tint

def format_ref(txt):
    txt=txt.replace('REF','\item[REF')
    txt=txt.replace(" '","]")
    txt=txt.replace("'","\n")
    txt=txt.replace("_","\_")
    txt=txt.replace("<","$<$")
    txt=txt.replace(">","$>$")
    txt=txt.replace("!","")
    txt='\\begin{description}\n'+txt+'\end{description}'
    return txt

def nelt(ph,cst,elt):
# Retourne le nombre de mole de l'element elt 
# dans la constitution cst de la phase ph
#
    n='0'
# Si elt n'apparait pas dans la constitution
    if cst.count(elt)==0:
        n='0'
# Sinon
    else:
# identification de la phase
        for i in range(len(tab_ph)):
            if tab_ph[i][0]==ph:
# Un seul sous-réseau
                if tab_ph[i][2]=='1':
#     Si la constitution = l'element recherche
                    if cst==elt:
                        n='1'
#     Sinon il faut compter le nombre de elt dans la cst
                    else:
#     identification de l'espece
                        for j in range(len(tab_sp)):
                            if tab_sp[j][0]==cst:
#     attribution du nombre de elt dans l'espece
                                for k in range(len(tab_sp[j][2])):
#                                    print cst,elt,tab_sp[j][2]
                                    if tab_sp[j][2][k]==elt:
                                        n=tab_sp[j][2][k+1]
# Liquide ionique
                elif ph=='IONIC_LIQUID':
                    a=cst.split(':')
#                    print 'a',a,'elt',elt
#         espece neutre
                    if len(a)==1 and cst.count(elt)>0:
#         element
                        if a[0]==elt:
                            n='1'
                        else:
                            for j in range(len(tab_sp)):
                                if a[0]==tab_sp[j][0]:
                                    for k in range(len(tab_sp[j][2])):
                                        if tab_sp[j][2][k]==elt:
                                            n=tab_sp[j][2][k+1]
#         espece
                    elif cst.count(elt)>0:
                        if a[1]=='VA':
                            for j in range(len(tab_sp)):
                                if a[0]==tab_sp[j][0]:
                                    if len(tab_sp[j][2][1])>2:
                                        n=tab_sp[j][2][1]
                                    else:
                                        n='1'
                        else:
                            if a[0].count(elt)>0:
                                for k in range(len(tab_sp)):
                                    if a[1]==tab_sp[k][0]:
                                        q=int(tab_sp[k][2][-1][1:])
                                for k in range(len(tab_sp)):
                                    if a[0]==tab_sp[k][0]:
                                        for l in range(len(tab_sp[k][2])):
                                            if tab_sp[k][2][l]==elt:
                                                n=str(int(n)+q*int(tab_sp[k][2][l+1]))
                            if a[1].count(elt)>0:
                                for k in range(len(tab_sp)):
                                    if a[0]==tab_sp[k][0]:
                                        p=int(tab_sp[k][2][-1][1:])
                                for k in range(len(tab_sp)):
                                    if a[1]==tab_sp[k][0]:
                                        for l in range(len(tab_sp[k][2])):
                                            if tab_sp[k][2][l]==elt:
                                                n=str(int(n)+p*int(tab_sp[k][2][l+1]))
                else:
                    a=cst.split(':')
#                    print a,elt,tab_ph[i],tab_ph[i][2],range(len(tab_ph[i][2]))
                    for j in range(int(tab_ph[i][2])):
#                        print tab_ph[i],"j",a[j]
                        if a[j]==elt:
                            n=str(float(n)+float(tab_ph[i][4+2*j]))
                        else:
                            for k in range(len(tab_sp)):
                                if a[j]==tab_sp[k][0]:
                                    for l in range(len(tab_sp[k][2])):
                                        if tab_sp[k][2][l]==elt:
                                            n=str(float(n)+float(tab_sp[k][2][l+1])*float((tab_ph[i][4+2*j])))
        if n[-1]=='0':
            n=n[:-2]
    return n


def gref(phase,cst):
    text='-HSER^{'+phase+'}_{'+cst+'}'
    for i in range(len(tab_ph)):
        if tab_ph[i][0]==phase:
            if tab_ph[i][2]=='1':
                text=''
                for j in range(len(tab_elt)):
                    if str(nelt(phase,cst,tab_elt[j][0]))!='0':
                        text=text+'- '
                        if nelt(phase,cst,tab_elt[j][0])!='1':
                            text=text+nelt(phase,cst,tab_elt[j][0])+'\ '
                        text=text+' H^{SER}_{'+nom_sp(tab_elt[j][0])+'}'
#                    print "test",tab_elt[j],text
            elif phase=='IONIC_LIQUID':
                text=''
                for j in range(len(tab_elt)):
                    if str(nelt(phase,cst,tab_elt[j][0]))!='0':
                        text=text+'- '
                        if nelt(phase,cst,tab_elt[j][0])!='1':
                            text=text+nelt(phase,cst,tab_elt[j][0])+'\ '
                        text=text+' H^{SER}_{'+nom_sp(tab_elt[j][0])+'}'
#                    print nelt(phase,cst,tab_elt[j][0])
            elif check_ord(phase)>-1:
                dis_ph=tab_ord[check_ord(phase)][1]
                text=''
                for j in range(len(tab_elt)):
#                    print cst,tab_elt[j][0],nelt(phase,cst,tab_elt[j][0])
                    if str(nelt(phase,cst,tab_elt[j][0]))!='0':
                        text=text+'- '
                        if nelt(phase,cst,tab_elt[j][0])!='1':
                            text=text+nelt(phase,cst,tab_elt[j][0])+'\ '
                        text=text+' G^{'+nom_ph(dis_ph)+'}_{'+nom_sp(tab_elt[j][0])+'}'
            else:
                text=''
                for j in range(len(tab_elt)):
#                    print cst,tab_elt[j][0],nelt(phase,cst,tab_elt[j][0])
                    if str(nelt(phase,cst,tab_elt[j][0]))!='0':
                        text=text+'- '
                        if nelt(phase,cst,tab_elt[j][0])!='1':
                            text=text+nelt(phase,cst,tab_elt[j][0])+'\ '
                        text=text+' H^{SER}_{'+nom_sp(tab_elt[j][0])+'}'
    return text

# entrée des éléments du système
# demander le nom des éléments, maximum 5
check=0
syst=''
elt=raw_input("Enter the elements / A B or A B C / :")
telt=elt.split()
while check==0:
    if len(telt)==2:
        syst='bin'
        check=1
    elif len(telt)==3:
        syst='ter'
        check=1
    elif len(telt)==4:
        syst='qua'
        check=1
    elif len(telt)==5:
        syst='qui'
        check=1
    elif len(telt)==1:
        elt=raw_input('Enter at least another element : ')
        telt=telt+elt.split()
    elif len(telt)>5:
#        print "Trop d'éléments, seuls les cinq premiers seront considérés"
        telt=telt[:5]
        syst='qui'
        check=1

# éléments rangés par ordre alphabétique
#telt=sorted(telt)
# Formatter le nom des éléments selon convention
for i in range(len(telt)):
    telt[i]=telt[i].replace(telt[i][0],telt[i][0].upper())
    if len(telt[i])==2:
        telt[i]=telt[i].replace(telt[i][1],telt[i][1].lower())
# entrée du nom du TDB principal
nomtdb=raw_input("Enter the TDB name / FUEL-12 / :")
if nomtdb=='':
    nomtdb="FUEL-12"
# création d'un TCM pour générer le TDB du sous-système
nomtcm='syst.TCM'
tcmf=open(nomtcm,'w')
# écriture du TCM
tcmf.write("go da \n")
tcmf.write("sw u "+nomtdb+"\n")
tcmf.write("def_sy")
for i in telt:
    tcmf.write(" "+i)
tcmf.write("\nget \ngo g \n")
tcmf.write("l_d syst N \ngo sy \nex\n")
# fermeture du TCM
tcmf.close()
# création du TDB avec tcs et le TCM
iii=raw_input('Continuing')
subprocess.Popen(['tcs',nomtcm])
iii=raw_input('Continuing')
# ouverture du fichier TDB en mode lecture
tdbf=open('syst.TDB','r')
# t=tableau des lignes du fichier TDB
t=tdbf.readlines()
# fermeture du fichier TDB
tdbf.close()
# extraction des données du tableau t
# supression des lignes vides et 
# regroupement des lignes jusqu'à rencontrer '!'
ttt=[]
l=''
for i in range(len(t)):
    ligne=t[i]
    if len(ligne.split())!=0 and ligne[0]!='$':
        if ligne.count('!')==0:
            l=l+ligne
        else:
            l=l+ligne
            ttt=ttt+[l]
            l=''
#   extraction des éléments
tab_elt=[]
for ligne in ttt:
    if ligne.split()[0]=='ELEMENT':
        if ligne.split()[4][0]!='0':
            e=[ligne.split()[1]]
            if len(ligne.split()[1])==1:
               e=e+['{\rm '+e[0][0]+'}']
            else:
               n='{\rm '+e[0][0]+e[0][1].lower()+'}'
               e=e+[n]
            tab_elt=tab_elt+[e]
#   extraction des espèces chimiques
tab_sp=[]
for ligne in ttt:
    if ligne.split()[0]=='SPECIES':
        s=[ligne.split()[1]]
        st=ligne.split()[2].replace('!','').replace('/',' ')
# formate le nom pour LaTeX
        name=ligne.split()[1]
        for i in range(len(tab_elt)):
            if name.count(tab_elt[i][0])>0:
                name=name.replace(tab_elt[i][0],' '+tab_elt[i][1]+' ')
#        name=name.replace('VA','\Box ')
        name=name.replace('4/3','_{4/3}')
        for i in range(10,20):
            name=name.replace(' '+str(i),'_{'+str(i)+'}')
        for i in range(10):
            name=name.replace(' '+str(i),'_'+str(i))
        for i in range(10):
            name=name.replace('-'+str(i),'^{'+str(i)+'-}')
            name=name.replace('+'+str(i),'^{'+str(i)+'+}')
        s=s+[name]
# extrait informations sur la composition de l'espece
        check=0
        while check==0:
            for i in range(len(st)-1):
                if chiffre(st[i])==1 and lettre(st[i+1])==1 or lettre(st[i])==1 and chiffre(st[i+1])==1:
                    st=st[:i+1]+' '+st[i+1:]
                    check=1
            for i in range(len(st)-1):
                if chiffre(st[i])==1 and lettre(st[i+1])==1 or lettre(st[i])==1 and chiffre(st[i+1])==1:
                    check=0
        st=st.split()
        s=s+[st]
        tab_sp=tab_sp+[s]
#   extraction des functions
tab_fun=[]
for ligne in ttt:
    if ligne.split()[0]=='FUNCTION':
        fun=[]
        a=ligne.split()
        n=a[1]
        f=ligne[ligne.find(a[2])-1:].replace('\n     ','').replace('!\n','')
        fun=[n,f]
        tab_fun=tab_fun+[fun]
#   extraction des phases et de leur modele
tab_ph=[]
for i in range(len(ttt)):
    ligne=ttt[i]
    if ligne.split()[0]=='PHASE':
        ph=[]
        nph=ttt[i].split()[1]
        if nph.count(':')>0:
            nph=nph[:nph.find(':')]
        ph=[nph]
        ph=ph+['{\rm '+nph.replace('_','\_')+'}']
        ph=ph+[ttt[i].split()[3]]
        print ligne,ph
        cst=ttt[i+1][ttt[i+1].find(' :')+2:]
        cst=cst.replace('\n    ','')
        print cst
        if ttt[i].split()[1].count(':Y')==0:
            for j in range(int(ttt[i].split()[3])):
                ph=ph+[cst.split()[2*j].replace('%',''),ttt[i].split()[j+4]]
        else:
            ph=ph+[cst.split()[0],'P']
            ph=ph+[cst.split()[2],'Q']
        tab_ph=tab_ph+[ph]
#   extraction des phases possédant une contribution desordonnee
tab_ord=[]
ord=''
for i in range(len(ttt)):
    ligne=ttt[i]
    if ligne.count('DIS_PART')>0:
        a=ligne.split()
        for j in range(len(a)):
            if a[j]=='DIS_PART':
                ord=[a[j-1],a[j+1].replace(',,,!','')]
                tab_ord=tab_ord+[ord]
#print tab_ord
#   extraction de leurs paramètres 
tab_par=[]
for i in range(len(ttt)):
    ligne=ttt[i]
    if ligne.split()[0]=='PARAMETER':
        par=[]
        line=ligne.replace(' PARAMETER ','')
        id=line[:line.find('(')]
        ph=line[line.find('(')+1:line.find(',')]
        cst=line[line.find(',')+1:line.find(';')]
        if id.count('G')>0 and cst.count(',')>0:
            id='L'
        ord=line[line.find(';')+1:line.find(')')]
        fun=line[line.find(')')+1:line.find('!')].replace('\n  ','')
        par=[id,ph,cst,ord,fun]
#        print par
        tab_par=tab_par+[par]
    if ligne.split()[0]=='PARA':
        par=[]
        line=ligne.replace(' PARA ','')
        id=line[:line.find('(')]
        ph=line[line.find('(')+1:line.find(',')]
        cst=line[line.find(',')+1:line.find(';')]
        if id.count('G')>0 and cst.count(',')>0:
            id='L'
        ord=line[line.find(';')+1:line.find(')')]
        fun=line[line.find(')')+1:line.find('!')].replace('\n  ','')
        par=[id,ph,cst,ord,fun]
        tab_par=tab_par+[par]
#   extraction des références
tab_ref=[]
for i in range(len(ttt)):
    ligne=ttt[i]
    if ligne.split()[0]=='LIST_OF_REFERENCES':
        ref=ligne[ligne.find('SOURCE')+6:]
        tab_ref=tab_ref+[ref]
# demande si toutes les phases doivent être 
rep=raw_input("Do you want to list all the phases / Y/N / :")
if rep=='N':
    for i in range(len(tab_ph)):
        print i,' ',tab_ph[i][0]
    rep=raw_input("Enter the numbers of the phases to reject, each separated by space :")
    rej=rep.split()
    tab_ent=range(len(tab_ph))
    print tab_ent
    print rej
    for i in range(len(rej)):
        rej[i]=int(rej[i])
    print rej
    for i in range(len(rej)):
#        tab_ent=tab_ent.remove(rej[i])
        tab_ent=tab_ent[:tab_ent.index(rej[i])]+tab_ent[tab_ent.index(rej[i])+1:]
        print tab_ent
else:
    tab_ent=range(len(tab_ph))
print "Phases taken into account :"
for i in tab_ent:
    print i,tab_ph[int(i)][0]
# création d'un fichier tex
nom='syst'
texnom=nom+'.tex'
texf = open(texnom,'w')
# écriture du fichier tex
texf.write("""
\documentclass[preprint,fleqn,a4]{elsarticle}
\usepackage{amssymb}
\\textwidth 15.7cm
\\textheight 21.5cm
\oddsidemargin  0.cm
\evensidemargin  0.cm
\\topmargin -25pt
\pagestyle{empty}\n""")
#texf.write('\\begin{document}\n\n\sloppy \n\n \parindent1cm \n\n')
texf.write('\\begin{document}\n\n \parindent1cm \n\n')
# titre nom du système
if syst=='bin':
    texf.write('{\\begin{center}\huge '+telt[0]+' -- '+telt[1]+'\end{center}}')
if syst=='ter':
    texf.write('{\\begin{center}\huge '+telt[0]+' -- '+telt[1]+' -- '+telt[2]+'\end{center}}')
if syst=='qua':
    texf.write('{\\begin{center}\huge '+telt[0]+' -- '+telt[1]+' -- '+telt[2]+' -- '+telt[3]+'\end{center}}')
texf.write('\n\n')
if syst=='qui':
    texf.write('{\\begin{center}\huge '+telt[0]+' -- '+telt[1]+' -- '+telt[2]+' -- '+telt[3]+' -- '+telt[4]+'\end{center}}')
texf.write('\n\n')
# nom de la phase
# for n in range(len(tab_ph)):
for n in tab_ent:
    n=int(n)
    print tab_ph[n]
    texf.write('\section*{Phase '+nom_ph(tab_ph[n][0])+'\n')
# modele
    for i in range(int(tab_ph[n][2])):
        texf.write('($'+nom_cst(tab_ph[n][3+2*i])+'$)')
        if chiffre(tab_ph[n][4+2*i])==1:
            if float(tab_ph[n][4+2*i])!=1:
                texf.write('$_{'+tab_ph[n][4+2*i]+'}$')
        else:
            texf.write('$_{'+tab_ph[n][4+2*i]+'}$')
    texf.write('}\n\n\\begin{description}')
# parametres
    for i in range(len(tab_par)):
        if tab_par[i][1]==tab_ph[n][0]:
            texf.write('\item[\hspace{1cm}$\,')
            if tab_par[i][2].count(',')>0:
                texf.write('^'+tab_par[i][3])
#            print tab_par[i][0]
            if tab_par[i][0]=='  TC':
                texf.write('{T_C}')
            elif tab_par[i][0]=='  BMAGN':
                texf.write('{\\beta}')
            else:
                texf.write(tab_par[i][0])
            texf.write('^{'+nom_ph(tab_par[i][1])+'}_{'+nom_cst(tab_par[i][2])+'}')
            if tab_par[i][2].count(',')==0 and tab_par[i][0]=='  G':
                texf.write(gref(tab_par[i][1],tab_par[i][2]))
            texf.write('$]=\ ')
#            if len(joli_fun(tab_par[i][4]))>66:
#                if joli_fun(tab_par[i][4]).count(' for $')==0:
#                    texf.write('\n\n\parindent1.0cm')
#                    texf.write(joli_fun(tab_par[i][4])+'\n\n')
#                else:
#                    texf.write('\n\n\hspace{1cm}\\begin{minipage}[t]{13.8cm} \parindent0cm ')
#                    texf.write(joli_fun(tab_par[i][4])+'\end{minipage}\n\n')
            if len(joli_fun(tab_par[i][4]))+len(tab_par[i][2])>72:
                texf.write('\n\n\hspace{1cm}\\begin{minipage}[t]{13.8cm} \parindent0cm ')
                texf.write(joli_fun(tab_par[i][4])+'\end{minipage}\n\n')
            else:
                texf.write(joli_fun(tab_par[i][4])+'\n\n')
    texf.write('\end{description}')
# fonctions
texf.write('\section*{Functions} \sloppy\n\n')
texf.write('\\begin{description}')
for i in range(len(tab_fun)):
    if tab_fun[i][0]!='UN_ASS':
        texf.write('\item[$\,')
        texf.write(tab_fun[i][0]+'$]=')
        texf.write(joli_fun(tab_fun[i][1])+'\n\n')
texf.write('\end{description}')
# references
texf.write('\section*{References}')
#texf.write('\\begin{description}')
for i in range(len(tab_ref)):
#    texf.write('\item[$\,')
#    texf.write(tab_fun[i][0]+'$]=')
    texf.write(format_ref(tab_ref[i]))
#    texf.write(joli_fun(tab_fun[i][1])+'\n\n')
#texf.write('\end{description}')
texf.write("\end{document}")
# fermeture du fichier tex
texf.close()
# compilation du fichier tex avec pdflatex
iii=raw_input('Continuing')
subprocess.Popen(['pdflatex',nom])
iii=raw_input('Continuing')
# ouverture du fichier pdf avec foxit
pdfnom=nom+'.pdf'
subprocess.Popen(['foxit',pdfnom])

