"""
-*- coding: utf-8 -*-
@author : mhebding
Simulations autour du pH
"""

import math
import matplotlib.pyplot as plt

"""Partie 1 - Calcul du pH d'un Af ou d'une base Bf par input"""
def pHAF(C): #calcul du pH d'une solution dans laquelle on a introduit un AF
    pH = round(-math.log10(C),2)
    return pH

def pHBF(C): #calcul du pH d'une solution dans laquelle on a introduit une BF
    pH = round(14+math.log10(C),2)
    return pH

def pHAf(pKa, C): #calcul du pH d'une solution où l'on a introduit Af à C
    Ka = 10**-pKa
    K = Ka
    delta = K**2+4*K*C
    h = (-K+delta**0.5)/2
    pH = round(-math.log10(h),2)
    return pH

def pHBf(pKa, C): #calcul du pH d'une solution où l'on a introduit Bf à C
    Ka = 10**-pKa
    Ke = 10**-14
    K = Ke/Ka
    delta = K**2+4*K*C
    HO = (-K+delta**0.5)/2
    h = Ke/HO
    pH = round(-math.log10(h),2)
    return pH

def part1():
    print("Qu'avez-vous introduit dans la solution ?")
    cas = input("AF, Af, BF ou Bf ?")
    C = float(input("Concentration introduite ?"))
    if cas == 'Af' or cas == 'Bf':
        pKa = float(input("Valeur du pKa du couple ?"))
        if cas == 'Af':
            pH = pHAf(pKa, C)
            print("Le pH de la solution est {}.".format(pH))
        else:
            pH = pHBf(pKa, C)
            print("Le pH de la solution est {}.".format(pH))
    elif cas == 'AF':
        pH = pHAF(C)
        print("Le pH de la solution est {}.".format(pH))
    else:
        pH = 14+round(math.log10(C),2)
        print("Le pH de la solution est {}.".format(pH))

"""Partie 2 - Titrage BF par AF pour différents C initials"""
def part2():
    #HO- + H3O+ = 2H2O K = 10**14
    #OK une réaction de titrage doit être totale K>10**4 (et rapide et unique)

    #echantillon à analyser (Na+ + HO-)
    listeC0 = [10**-i for i in range(1,5)]
    for concentration in listeC0:
        C0 = concentration
        V0 = 10
        #solution titrante (HCl)
        Ca = C0 #solution titrante à la même concentration
        Veq = float(C0*V0/Ca) #détermination du volume équivalent

        N = 100 #nombre de points

        listeV = [V/N for V in range(0,int(N*2*Veq),1)]
        listepH = []

        for V in listeV:
            if V < Veq:
                n0 = C0*V0-Ca*V
                pH = pHBF(n0/(V0+V))
                listepH.append(pH)
            if V == Veq:
                pH = 7
                listepH.append(pH)
            if V > Veq:
                na = Ca*V-C0*V0
                pH = pHAF(na/(V0+V))
                listepH.append(pH)

        plt.plot(listeV, listepH, label='C0 = '+str(C0))
        plt.xlabel('V')
        plt.ylabel('pH')
        plt.legend()
        plt.xlim(0, 2*Veq)
        plt.ylim(0, 14)
        plt.plot([0,Veq],[7, 7], color='red')
        plt.plot([Veq,Veq],[0, 7], color='red')
    decalage = 0.2
    plt.annotate(7, xy = (0+decalage, 7+decalage), color='red')
    plt.annotate('Veq = '+str(Veq), xy = (Veq+decalage, 0+decalage), color='red')
    plt.plot(Veq, 7, marker='o', color='red')
    plt.annotate('point invariant', xy = (Veq+0.5, 7), color='red')
    plt.savefig('titrage BF par AF') #enregistrement
    plt.show()

"""Partie 3 - Titrage Af par BF avec pourcentages"""
def part3():
    #Af + HO- = A- + H2O K = Ka/Ke

    #echantillon à analyser (Af=CH3COOH)
    pKa = 4.8
    C0 = 0.01
    V0 = 10
    #solution titrante (Na+ + HO-)
    Cb = C0
    Veq = float(C0*V0/Cb)

    N = 50 #nombre de points

    listeV = [V/N for V in range(0,int(N*2*Veq),1)]
    listepH = []
    listeAf = []
    listeA = []

    for V in listeV:
        CentAf = 100*(C0*V0-Cb*V)/(C0*V0)
        CentA = 100*(Cb*V)/(C0*V0)
        if V == 0:
            pH = pHAf(pKa, C0)
            listepH.append(pH)
            listeAf.append(CentAf)
            listeA.append(CentA)
        elif V < Veq:
            n0 = C0*V0-Cb*V
            pH = pKa + math.log10((Cb*V)/n0)
            listepH.append(pH)
            listeAf.append(CentAf)
            listeA.append(CentA)
        elif V == Veq:
            n = C0*V0
            pH = pHBf(pKa, n/(V0+V))
            listepH.append(pH)
            listeAf.append(CentAf)
            listeA.append(CentA)
        elif V > Veq:
            nb = Cb*V-C0*V0
            pH = pHBF(nb/(V0+V))
            listepH.append(pH)
            listeAf.append(0)
            listeA.append(100)

    plt.subplot(211)
    plt.plot(listeV, listepH, label='Titrage Af par HO-. C0 = '+str(C0))
    plt.xlabel('V')
    plt.ylabel('pH')
    plt.legend()
    plt.plot([0,Veq/2],[pKa, pKa], color='red')
    plt.plot([Veq/2,Veq/2],[0, pKa], color='red')
    plt.plot(Veq/2, pKa, marker='o', color='red')
    decalage = 0.2
    plt.annotate('pKa = '+str(pKa), xy = (0+decalage, pKa+decalage), color='red')
    plt.annotate('Veq/2 = ' + str(Veq/2), xy = (Veq/2+decalage, 0+decalage), color='red')
    plt.xlim(0, 2*Veq)
    plt.ylim(0, 14)
    plt.subplot(212)
    plt.plot(listeV, listeAf, label='%Af')
    plt.plot(listeV, listeA, label='%A')
    plt.xlabel('V')
    plt.xlim(0, 2*Veq)
    plt.ylim(0, 100)
    plt.legend()
    plt.savefig('titrage Af par BF') #enregistrement
    plt.show()