from gekko import GEKKO
import numpy as np
from stream import Stream
from math import sinh, cosh
from scipy.integrate import quad
import csv

m = GEKKO()

def Antoine(T, C1, C2, C3, C4, C5):

    P = m.exp(C1 + (C2 / T) + (C3 * m.log(T)) + (C4 * (T ** C5)))

    return (P / 1000) # kPa

def Antoinenp(T, C1, C2, C3, C4, C5):

    P = np.exp(C1 + (C2 / T) + (C3 * np.log(T)) + (C4 * (T ** C5)))

    return (P / 1000) # kPa

def AntoineInv(P, C1, C2, C3, C4, C5):

    m = GEKKO()
    T = m.Var(value = 298.15, lb = 100, ub = 800)
    m.Equation([(m.exp(C1 + (C2 / T) + (C3 * m.log(T)) + (C4 * (T ** C5))) / 1000) - P == 0])
    m.solve(disp=False)
    return float(T.value[0]) # K

def HeatVap(T, Tc, C1, C2, C3, C4):

    Tr = T / Tc
    Hvap = C1 * (1 - Tr) ** (C2 + C3 * Tr + C4 * Tr * Tr)
    return Hvap/1e6 # kJ / mol

def CP_L(T, C1, C2, C3, C4, C5):

    CPL = C1 +( C2 * T) +( C3 * (T ** 2)) +( C4 * (T ** 3)) + (C5 * (T ** 4))
    return CPL/1e6 # kJ / mol K

def CP_ig(T, C1, C2, C3, C4, C5):

    CPIG = C1 + C2 * pow((C3 / T) / (sinh(C3 / T)), 2) + C4 * pow((C5 / T) / (cosh(C5 / T)), 2)
    return CPIG/1e6 # kJ / mol K

def meanCP(f, T1, T2, ar):

    mcp, err = quad(f, T1, T2, args = ar, limit=1100)
    mcp = mcp / (T2 - T1)
    return mcp # kJ / mol K

def parameters(compounds):

    p = {'Antoine': {compound: compound_data[compound]['Antoine'] for compound in compounds},
         'AntoineInv' : {compound: compound_data[compound]['Antoine'] for compound in compounds},
         'Hvap' : {compound: compound_data[compound]['Hvap'] for compound in compounds},
         'CPL': {compound: compound_data[compound]['CPL'] for compound in compounds},
         'CPig': {compound: compound_data[compound]['CPIG'] for compound in compounds}}

    return p

with open('compound_data.csv', mode = 'r') as csv_f:
    reader = csv.reader(csv_f)
    compound_data = {row[0]: {'Antoine': {'C1': float(row[7]), 'C2': float(row[8]), 'C3': float(row[9]), 'C4': float(row[10]), 'C5': float(row[11])},
                                'Hvap': {'Tc': float(row[1]), 'C1': float(row[12]), 'C2': float(row[13]), 'C3': float(row[14]), 'C4': float(row[15])},
                                'CPL': {'C1': float(row[2]), 'C2': float(row[3]), 'C3': float(row[4]), 'C4': float(row[5]), 'C5': float(row[6])},
                                'CPIG': {'C1': float(row[16]), 'C2': float(row[17]), 'C3': float(row[18]), 'C4': float(row[19]), 'C5': float(row[20])}} for row in reader}
    csv_f.close()

class FlashDrum():

    def __init__(self, mode = 'Isothermal'):
        ''' The Flash Drum has one inlet stream and two outlet stream.
         The program uses the class Stream to represent the inlet and outlet process streams.
         -> feed is the inlet object from the class Stream.
         -> vapor is an outlet object from the class Stream.
         -> liquid is an outlet object from the class Stream.
         -> mode refers to calculations made by the program, default is "Isothermal", it also can work in "Adiabatic".
         -> psi is the vapor outlet / feed inlet ratio.
         -> Heat is the heat in kJ/mol that the Flash Drum requires.
         -> Temperature is the Flash Drum operating temperature in K.
         -> Pressure is the Flash Drum operating pressure kPa.
         -> Tref is the reference temperature in K for the energy balance calculations.
         This class only works with pressure in kPa and temperature in K. '''
        self.feed = Stream("FEED")
        self.vapor = Stream("VAPOR")
        self.liquid = Stream("LIQUID")
        self.mode = mode
        self.psi = 0
        self.Heat = None
        self.Temperature = None
        self.Pressure = None
        self.Tref = 298.15

    def setFeedStream(self, inletStream = Stream("FEED")):
        '''Set the feed stream properties.'''
        inletStream.normalize()
        self.feed.setT(inletStream.Temperature)
        self.feed.setP(inletStream.Pressure)
        self.feed.setmF(inletStream.molarFlow)
        self.feed.setmC(inletStream.mComposition)
        self.feed.setH(inletStream.Enthalpy)

    def Streams(self, energy = False):
        ''' Display the stream results in a table. '''

        F = str(round(self.feed.getmF(), 3))
        V = str(round(self.vapor.getmF(), 3))
        L = str(round(self.liquid.getmF(), 3))
        T_f = str(round(self.feed.getT(), 2))
        T_v = str(round(self.vapor.getT(), 2))
        T_l = str(round(self.liquid.getT(), 2))
        P_f = str(self.feed.getP())
        P_v = str(self.vapor.getP())
        P_l = str(self.liquid.getP())

        stream_table1 = ""
        stream_table1 += "-"*100
        stream_table1 += "\n\t\t\t\tF L A S H  D R U M: \t" + self.mode.upper()
        stream_table1 += "\n"+"-"*100
        stream_table1 += "\nStreams:\t\t" + "FEED" + " " * 20 + "VAPOR " + " " * 20 + "LIQUID"
        stream_table1 += "\n" + "-"*100
        stream_table1 += "\n\t\t\t" + "T_f = " + T_f + " K" + "\t\t" + "T_v = " + T_v + " K" + "\t\t  " + "T_l = " + T_l + " K"
        stream_table1 += "\n\t\t\t" + "P_f = " + P_f + " kPa" + "\t\t" + "P_v = " + P_v + " kPa" + "\t\t  " + "P_l = " + P_l + " kPa"

        if len(F) >  5:

            if len(V) > 5:

                stream_table1 += "\n\t\t\t" + "F = " + F + " mol/h" + "\t" + "V = " + V + " mol/h" + "\t  " + "L = " + L + " mol/h"

            else:

                stream_table1 += "\n\t\t\t" + "F = " + F + " mol/h" + "\t" + "V = " + V + " mol/h" + "\t\t  " + "L = " + L + " mol/h"

        elif len(F) > 2:

            if len(V) > 5:

                stream_table1 += "\n\t\t\t" + "F = " + F + " mol/h" + "\t\t" + "V = " + V + " mol/h" + "\t  " + "L = " + L + " mol/h"

            else:

                stream_table1 += "\n\t\t\t" + "F = " + F + " mol/h" + "\t\t" + "V = " + V + " mol/h" + "\t\t  " + "L = " + L + " mol/h"

        elif len(F) > 0:

            if len(V) > 0:

                stream_table1 += "\n\t\t\t" + "F = " + F + " mol/h" + "\t\t" + "V = " + V + " mol/h" + "\t\t  " + "L = " + L + " mol/h"

            else:

                stream_table1 += "\n\t\t\t" + "F = " + F + " mol/h" + "\t\t" + "V = " + V + " mol/h" + "\t\t\t  " + "L = " + L + " mol/h"

        stream_table2 = ""

        for key in self.feed.getmC().keys():

            if len(key) > 7:

                stream_table2 += "\n" + key + "\t\tz = "
            else:
                stream_table2 += "\n" + key + "\t\t\tz = "

            stream_table2 += str(round(self.feed.getmC(key), 3))

            if len(str(round(self.feed.getmC(key), 3))) > 4:

                stream_table2 += "\t\t" + "y = " + str(round(self.vapor.getmC(key), 3))

            else:

                stream_table2 += "\t\t\t" + "y = " + str(round(self.vapor.getmC(key), 3))

            if len(str(round(self.vapor.getmC(key), 3))) > 4:

                stream_table2 += "\t\t  " + "x = " + str(round(self.liquid.getmC(key),3))

            else:

                stream_table2 += "\t\t\t  " + "x = " + str(round(self.liquid.getmC(key),3))

        stream_table3 = ""

        if energy:
            stream_table3 += "\n\t\t\t" + "h_f = " + str(round(self.feed.getH(), 3)) + " kJ/mol" + \
                "\t" + "h_v = " + str(round(self.vapor.getH(), 3)) + " kJ/mol" + \
                "\t  " + "h_l = " + str(round(self.liquid.getH(), 3)) + " kJ/mol" + "\n" + "-"*100 + \
                "\n\t\t\tHEAT: Q = " + str(round(self.Heat)) + " kW"
        stream_table3 += "\n" + "-"*100
        stream_table = stream_table1 + stream_table2 + stream_table3
        return stream_table

    def saveResults(self):
        feed = {'name': self.feed.getName(),
                'Temeperature': self.feed.getT(),
                'Pressure': self.feed.getP(),
                'Molar Flow': self.feed.getmF(),
                'Molar Composition': self.feed.getmC(),
                'Enthalpy': self.feed.getH()}
        vapor = {'name': self.vapor.getName(),
                'Temeperature': self.vapor.getT(),
                'Pressure': self.vapor.getP(),
                'Molar Flow': self.vapor.getmF(),
                'Molar Composition': self.vapor.getmC(),
                'Enthalpy': self.vapor.getH()}
        liquid = {'name': self.liquid.getName(),
                'Temeperature': self.liquid.getT(),
                'Pressure': self.liquid.getP(),
                'Molar Flow': self.liquid.getmF(),
                'Molar Composition': self.liquid.getmC(),
                'Enthalpy': self.liquid.getH()}
        Q = self.Heat
        Psi = self.psi
        mode = self.mode
        results = {'Drum': {'mode': mode, 'Heat': Q, 'Psi': Psi},
                    'Feed': feed,
                    'Vapor': vapor,
                    'Liquid': liquid}
        return  results

    def idealK(self, T, P, c):
        ''' Caculates an ideal K parameter with Raoult's Law'''
        Psat = Antoine(T, **c)
        return Psat / P

    def isothermal(self, T, P, c, energy = False):
        ''' Simulates an Isothermal Flash Drum given an operating temperature and pressure.'''
        self.mode = "Isothermal"
        self.vapor.setT(T)
        self.vapor.setP(P)
        self.liquid.setT(T)
        self.liquid.setP(P)
        self.vapor.setmC(None)
        self.liquid.setmC(None)
        Tf_bubble = self.bubbleT(self.feed.getP(), c)
        Tf_dew = self.dewT(self.feed.getP(), c)
        T_bubble = self.bubbleT(P, c)
        T_dew = self.dewT(P, c)
        Tf = self.feed.getT()
        Tf_mode = None
        # Check for the feedstream condition
        if Tf <= Tf_bubble:

            Tf_mode = "liquid"

        elif Tf >= Tf_dew:

            Tf_mode = "vapor"

        else:

            Tf_mode = "mixture"

        Tref = self.Tref
        cpl = {}
        cpig = {}
        hf = {}
        hv = {}
        hl = {}
        tb = {}

        ### MATERIAL BALANCE AND ENERGY BALANCE
        # Check if the operating temperature is between the limits for the PSI calculations.

        ## BELOW BUBBLE TEMPERATURE MEANS LIQUID PHASE ONLY
        if T <= T_bubble:
            ## MATERIAL BALANCE
            #  There is no vapor phase
            self.psi = 0
            self.vapor.setmF(0)
            self.liquid.setmF(self.feed.getmF())

            for key in self.feed.getmC().keys():

                self.liquid.setmC((self.feed.getmC(key)), key)
                self.vapor.setmC(0, key)

            ## ENERGY BALANCE, if enabled ...
            if energy:

                for key in self.feed.getmC().keys():
                    # Mean heat capacity
                    cpl[key] = meanCP(CP_L, T_bubble * 0.8,  T_dew * 1.2, tuple([value for value in c['CPL'][key].values()]))
                    # Enthalply calculation.
                    if Tf_mode == "liquid":

                        hf[key] = self.feed.getmC(key) * cpl[key] * (Tf - Tref)

                    elif Tf_mode == "vapor":

                        cpig[key] = meanCP(CP_ig, T_bubble * 0.8,  T_dew * 1.2, tuple([value for value in c['CPig'][key].values()]))
                        tb[key] = AntoineInv(P, **c['AntoineInv'][key])
                        hf[key] = self.feed.getmC(key) * (cpl[key] * (tb[key] - Tref) + HeatVap(tb[key], **c['Hvap'][key]) + cpig[key] * (T - tb[key]))

                    else:

                         hf[key] = self.feed.getmC(key) * (cpl[key] * (T - Tref) + HeatVap(T, **c['Hvap'][key]))

                    hl[key] = self.liquid.getmC(key) * cpl[key] * (T - Tref)
                    hv[key] = 0.0

                self.feed.setH(sum([value for value in hf.values()]))
                self.liquid.setH( sum([value for value in hl.values()]))
                self.vapor.setH(0.0)
                # Energy balance for heat (Q) caculation.
                self.Heat = self.vapor.getmF() * self.vapor.getH() + self.liquid.getmF() * self.liquid.getH() - self.feed.getmF() * self.feed.getH()

        ## ABOVE DEW TEMPERATURE MEANS VAPOR PHASE ONLY
        elif T >= T_dew:
            ## MATERIAL BALANCE
            #  There is no vapor phase
            self.psi = 1
            self.vapor.setmF(self.feed.getmF())
            self.liquid.setmF(0)

            for key in self.feed.getmC().keys():

                self.liquid.setmC(0, key)
                self.vapor.setmC(self.feed.getmC(key), key)

            ## ENERGY BALANCE, if enabled ...
            if energy:

                for key in self.feed.getmC().keys():
                    # Mean heat capacity
                    cpl[key] = meanCP(CP_L, T_bubble * 0.8,  T_dew * 1.2, tuple([value for value in c['CPL'][key].values()]))
                    cpig[key] = meanCP(CP_ig, T_bubble * 0.8,  T_dew * 1.2, tuple([value for value in c['CPig'][key].values()]))
                    # Enthalply calculation.
                    if Tf_mode == "liquid":

                        hf[key] = self.feed.getmC(key) * cpl[key] * (Tf - Tref)

                    elif Tf_mode == "vapor":

                        tb[key] = AntoineInv(P, **c['AntoineInv'][key])
                        hf[key] = self.feed.getmC(key) * (cpl[key] * (tb[key] - Tref) + HeatVap(tb[key], **c['Hvap'][key]) + cpig[key] * (T - tb[key]))

                    else:

                         hf[key] = self.feed.getmC(key) * (cpl[key] * (T - Tref) + HeatVap(T, **c['Hvap'][key]))

                    hl[key] = 0
                    tb[key] = AntoineInv(P, **c['AntoineInv'][key])
                    hv[key] = self.vapor.getmC(key) * (cpl[key] * (tb[key] - Tref) + HeatVap(tb[key], **c['Hvap'][key]) + cpig[key] * (T - tb[key]))

                self.feed.setH(sum([value for value in hf.values()]))
                self.liquid.setH(0)
                self.vapor.setH(sum([value for value in hv.values()]))

                # Energy balance for heat (Q) caculation.
                self.Heat = self.vapor.getmF() * self.vapor.getH() + self.liquid.getmF() * self.liquid.getH() - self.feed.getmF() * self.feed.getH()

        # DRUM TEMPERATURE BETWEEN BUBBLE AND DEW TEMPERATURES
        else:
            ## MATERIAL BALANCE
            # Create a gekko model for solve the equations system
            m = GEKKO()
            # Ki calculations.
            Ki = {}

            for key in self.feed.getmC().keys():

                K = m.Intermediate(self.idealK(T,P, c['Antoine'][key]))
                Ki[key] = K

            Psi = m.Var(value=0.5, lb= 0.0, ub = 1.0)
            x = sum([((self.feed.getmC(key) * (1 - Ki[key])) / (1 + Psi * (Ki[key] - 1))) for key in Ki.keys()])
            m.Equation([x == 0])
            m.solve(disp=False)
            self.psi = float(Psi.value[0])
            # Calulate vapor and liquid molar flows.
            self.vapor.setmF(self.psi * self.feed.getmF())
            self.liquid.setmF(self.feed.getmF() - self.vapor.getmF())
            # Calculate vapor and liquid molar compositions
            for key in Ki.keys():

                self.liquid.setmC((self.feed.getmC(key)) / (1 + self.psi * (Ki[key][0] - 1)), key)
                self.vapor.setmC(self.liquid.getmC(key)  * Ki[key][0], key)

            ## ENERGY BALANCE, if enabled ...
            if energy:

                for key in self.feed.getmC().keys():
                    # Mean heat capacity
                    cpl[key] = meanCP(CP_L, T_bubble * 0.8,  T_dew * 1.2, tuple([value for value in c['CPL'][key].values()]))
                    # Enthalply calculation.
                    if Tf_mode == "liquid":

                        hf[key] = self.feed.getmC(key) * cpl[key] * (Tf - Tref)

                    elif Tf_mode == "vapor":

                        cpig[key] = meanCP(CP_ig, T_bubble * 0.8,  T_dew * 1.2, tuple([value for value in c['CPig'][key].values()]))
                        tb[key] = AntoineInv(P, **c['AntoineInv'][key])
                        hf[key] = self.feed.getmC(key) * (cpl[key] * (tb[key] - Tref) + HeatVap(tb[key], **c['Hvap'][key]) + cpig[key] * (T - tb[key]))

                    else:

                         hf[key] = self.feed.getmC(key) * (cpl[key] * (T - Tref) + HeatVap(T, **c['Hvap'][key]))

                    hl[key] = self.liquid.getmC(key) * cpl[key] * (T - Tref)
                    hv[key] = self.vapor.getmC(key) * (cpl[key] * (T - Tref) + HeatVap(T, **c['Hvap'][key]))

                self.feed.setH(sum([value for value in hf.values()]))
                self.liquid.setH( sum([value for value in hl.values()]))
                self.vapor.setH(sum([value for value in hv.values()]))

                # Energy balance for heat (Q) caculation.
                self.Heat = self.vapor.getmF() * self.vapor.getH() + self.liquid.getmF() * self.liquid.getH() - self.feed.getmF() * self.feed.getH()

    def adiabatic(self, P, c):
        ''' It makes adibatic flash caculations given an operating pressure.'''
        self.mode ="Adiabatic"
        self.Pressure = P
        self.vapor.setP(P)
        self.liquid.setP(P)
        self.vapor.setmC(None)
        self.liquid.setmC(None)
        Tf_bubble = self.bubbleT(self.feed.getP(), c)
        Tf_dew = self.dewT(self.feed.getP(), c)
        Tf = self.feed.getT()
        Tf_mode = None
        Tref = self.Tref
        cpl = {}
        cpig = {}
        hf = {}
        hg = {}
        hl = {}
        # Check for the feedstream condition
        if Tf <= Tf_bubble:

            Tf_mode = "liquid"
            T_bubble = self.bubbleT(P, c)
            T_dew = self.dewT(P, c)
            Tf = self.feed.getT()
            Tf_mode = None
            Tref = self.Tref
            cpl = {}
            cpig = {}
            hf = {}
            hg = {}
            hl = {}
            m = GEKKO()
            m.options.MAX_ITER = 1000
            Psi = m.Var(value=0.5, lb= 0.0, ub = 1.0)
            T = m.Var(value=(T_bubble + T_dew) * 0.5, lb = 200, ub = 800)
            # K's
            Ki = {}
            # Ki calculations are made.
            for key in self.feed.getmC().keys():
                K = m.Intermediate(self.idealK(T,P, c['Antoine'][key]))

                Ki[key] = K

            x = sum([((self.feed.getmC(key) * (1 - Ki[key])) / (1 + Psi * (Ki[key] - 1))) for key in Ki.keys()])
            # Intermediate equations:
            self.vapor.setmF( Psi * self.feed.getmF())
            self.liquid.setmF(self.feed.getmF() - self.vapor.getmF())

            for key in Ki.keys():
                self.liquid.setmC((self.feed.getmC(key)) / (1 + Psi * (Ki[key] - 1)), key)
                self.vapor.setmC(self.liquid.getmC(key)  * Ki[key], key)

            # Intermediate energy Balance
            for key in self.feed.getmC().keys():

                cpl[key] = meanCP(CP_L, T_bubble * 0.8,  T_dew * 1.2, tuple([value for value in c['CPL'][key].values()]))
                #cpig[key] = meanCP(CP_ig, T_bubble,  T_dew, tuple([value for value in c['CPig'][key].values()]))
                hf[key] = self.feed.getmC(key) * cpl[key] * (Tf - Tref)
                hl[key] = self.liquid.getmC(key) * cpl[key] * (T - Tref)
                hg[key] = self.vapor.getmC(key) * (cpl[key] * (T - Tref) + HeatVap(T, **c['Hvap'][key]))

            self.feed.setH( sum([value for value in hf.values()]))
            self.liquid.setH( sum([value for value in hl.values()]))
            self.vapor.setH( sum([value for value in hg.values()]))
            # Second equaion: f(T) == 0
            y = self.vapor.getmF() * self.vapor.getH() + self.liquid.getmF() * self.liquid.getH() - self.feed.getmF() * self.feed.getH()
            # Solve the equations system
            m.Equation([x == 0, y == 0])
            m.solve(disp=False)
            # Evaluate the results of T and PSI in the intermediate equations
            self.psi = float(Psi.value[0])
            self.Temperature = float(T.value[0])
            # Real Ki calculations are made.
            for key in self.feed.getmC().keys():

                Ki[key] = Ki[key][0]
            # Calulate vapor and liquid molar flows.
            self.vapor.setmF( self.psi * self.feed.getmF())
            self.liquid.setmF(self.feed.getmF() - self.vapor.getmF())
            # Calculate vapor and liquid molar compositions
            for key in Ki.keys():

                self.liquid.setmC((self.feed.getmC(key)) / (1 + self.psi * (Ki[key] - 1)), key)
                self.vapor.setmC(self.liquid.getmC(key)  * Ki[key], key)

            #Real Energy Balance
            for key in self.feed.getmC().keys():
                # Mean heat capacity
                cpl[key] = meanCP(CP_L, T_bubble * 0.8,  T_dew * 1.2, tuple([value for value in c['CPL'][key].values()]))
                #cpig[key] = meanCP(CP_ig, T_bubble,  T_dew, tuple([value for value in c['CPig'][key].values()]))
                # Enthalply calculation.
                hf[key] = self.feed.getmC(key) * cpl[key] * (Tf - Tref)
                hl[key] = self.liquid.getmC(key) * cpl[key] * (self.Temperature - Tref)
                hg[key] = self.vapor.getmC(key) * (cpl[key] * (self.Temperature - Tref) + HeatVap(self.Temperature, **c['Hvap'][key]))

            self.feed.setH( sum([value for value in hf.values()]))
            self.liquid.setH( sum([value for value in hl.values()]))
            self.vapor.setH( sum([value for value in hg.values()]))
            Q = self.vapor.getmF() * self.vapor.getH() + self.liquid.getmF() * self.liquid.getH() - self.feed.getmF() * self.feed.getH()
            self.vapor.setT(self.Temperature)
            self.liquid.setT(self.Temperature)
            self.Heat = Q

        else:

            self.mode ="Adiabatic: NO SOLVED!"
            self.vapor.setmF(0)
            self.liquid.setmF(0)
            self.vapor.setH(0)
            self.liquid.setH(0)
            self.vapor.setT(0)
            self.liquid.setT(0)
            self.vapor.setP(0)
            self.liquid.setP(0)
            self.Heat = 0

            for key in self.feed.getmC().keys():

                self.vapor.setmC(0, key)
                self.liquid.setmC(0, key)

    def bubbleT(self, P, c):
        ''' Bubble temperature calculation given an operating pressure.'''
        m = GEKKO()

        T = m.Var(value = 298.15, lb = 0.0, ub = 800.0)
        # K's
        Ki = {}

        for key in self.feed.getmC().keys():
            Ki[key] = self.idealK(T,P, c['Antoine'][key])

        x = sum([self.feed.getmC(key) * Ki[key] for key in Ki.keys()])
        m.Equation([x - 1 == 0])
        m.solve(disp=False)

        return round(T.value[0], 2)

    def dewT(self, P, c ):
        ''' Dew temperature calculation given an operating pressure.'''
        m = GEKKO()

        T = m.Var(value = 298.15, lb = 200.0, ub = 800.0)
        # K's
        Ki = {}

        for key in self.feed.getmC().keys():
            Ki[key] = self.idealK(T,P, c['Antoine'][key])

        x = sum([self.feed.getmC(key) / Ki[key] for key in Ki.keys()])
        m.Equation([x - 1 == 0])
        m.solve(disp=False)

        return round(T.value[0], 2)

    def bubbleP(self, T, c):
        ''' Bubble pressure calculation given an operating temperature.'''
        P = sum([self.feed.getmC(key) * Antoinenp(T, **c['Antoine'][key]) for key in self.feed.getmC().keys()])

        return P

    def dewP(self, T, c):
        ''' Dew pressure calculation given an operating temperature.'''
        P = sum([self.feed.getmC(key) / Antoinenp(T, **c['Antoine'][key]) for key in self.feed.getmC().keys()]) ** (-1)

        return round(P, 3)


from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render

# Create your views here.
from book.models import CommentForm, Comment

def index(request):
    text="Merhaba Django";

    return HttpResponse("Product Page")

@login_required(login_url='/login')

def addcomment(request,id):
    url = request.META.get('HTTP_REFERER')
    if request.method == 'POST':
        form= CommentForm(request.POST)
        if form.is_valid():
            current_user=request.user #login olan user den gelecek

            data=Comment() #model ile baglantı
            data.user_id = current_user.id
            data.book_id = id
            data.subject = form.cleaned_data['subject']
            data.comment = form.cleaned_data['comment']
            data.rate = form.cleaned_data['rate']
            data.ip =request.META.get('REMOTE_ADDR') #ip adresini aldık
            data.save() #veritabanına kaydet
            messages.success(request, "Yorumunuz basari ile gönderilmiştir.Teşekkür Ederiz")

            return HttpResponseRedirect(url)
    messages.error(request, "Yorumunuz gönderilememiştir.Lütfen kontrol ediniz")
    return HttpResponse("url")


from flask_app.models.model_user import User
from flask_app.models.model_post import Post

from flask_app import app
from flask import render_template, redirect, flash, session, request

@app.route('/ideas')
def list_user_posts():
    if 'user_id' not in session:
        return redirect('/login')
    # Collects all the posts from the database and their users
    posts = Post.get_all_posts()
    print(posts)
    return render_template('ideas.html', posts = posts)

@app.route('/add_blog', methods=['POST'])
def add_post():
    if 'user_id' not in session:
        return redirect('/login')
    data = {
        'title' : request.form['title'],
        'content' : request.form['content'],
        'user_id' : session['user_id']
    }

    Post.add_blog(data)
    return redirect('/ideas')

@app.route('/delete_blog/<int:blog_id>')
def delete_blog(blog_id):
    data = {
        'blog_id' : blog_id
    }

    Post.delete(data)
    return redirect('/ideas')

@app.route('/update_blog/<int:blog_id>')
def update_blog(blog_id):
    if 'user_id' not in session:
        return redirect('/login')
    data = {
        'blog_id' : blog_id
    }
    post = Post.get_post(data)
    return render_template('update_blog.html', post = post)

@app.route('/update', methods=["POST"])
def update():
    data = {
        'blog_id' : request.form['blog_id'],
        'title' : request.form['title'],
        'content' : request.form['content']
    }

    Post.update_the_blog(data)
    return redirect('/ideas')


# -*- coding: utf-8 -*-
"""
Created on Sat Nov 30 21:48:09 2019

@author: rakshith kunchum

Simple program to demonstrate Controlled-NOT gate.
Circuit:
0: ───H───@───M('q0')───
          │
1: ───────X───M('q1')───
Results:
q0=0111100111
q1=0111100111
Counter({1: 7, 0: 3})
Counter({1: 7, 0: 3})
"""
import cirq

def main():
    circuit = cirq.Circuit()
    (q0, q1) = cirq.LineQubit.range(2)
    circuit.append([cirq.H(q0), cirq.CNOT(q0, q1),
                    cirq.measure(q0, key='q0'), cirq.measure(q1, key='q1')])
    sim = cirq.Simulator()
    results = sim.run(circuit, repetitions=10)
    print("Circuit:", circuit, sep='\n')
    print("Results:", results, sep='\n')
    print(results.histogram(key='q0'))
    print(results.histogram(key='q1'))

if __name__ == '__main__':
    main()


import pint
import pytest

import eradiate
from eradiate import unit_registry as ureg
from eradiate.contexts import SpectralContext
from eradiate.radprops import AFGL1986RadProfile

@pytest.fixture
def test_ckd_spectral_ctx_1650():
    spectral_cfg = eradiate.scenes.measure._core.CKDMeasureSpectralConfig(bins="1650")
    bindex = eradiate.ckd.Bindex(bin=spectral_cfg.bins[0], index=3)
    return SpectralContext.new(bindex=bindex, bin_set="10nm")

@pytest.fixture
def test_ckd_spectral_ctx_550():
    spectral_cfg = eradiate.scenes.measure._core.CKDMeasureSpectralConfig(bins="550")
    bindex = eradiate.ckd.Bindex(bin=spectral_cfg.bins[0], index=3)
    return SpectralContext.new(bindex=bindex, bin_set="10nm")

@pytest.mark.parametrize("model_id", ["midlatitude_summer", "us_standard"])
def test_afgl_1986_rad_profile_default_ckd(mode_ckd, model_id):
    """
    Collision coefficient evaluation methods return pint.Quantity objects.
    """
    p = AFGL1986RadProfile(dict(model_id=model_id))

    spectral_ctx = SpectralContext.new(bin_set="10nm")
    for field in ["albedo", "sigma_a", "sigma_t"]:
        x = getattr(p, f"eval_{field}_ckd")(
            spectral_ctx.bindex, bin_set_id=spectral_ctx.bin_set.id
        )
        assert isinstance(x, ureg.Quantity)

    sigma_s = p.eval_sigma_s_ckd(spectral_ctx.bindex)
    assert isinstance(sigma_s, ureg.Quantity)

@pytest.mark.parametrize("model_id", ["midlatitude_summer", "us_standard"])
def test_afgl_1986_rad_profile_has_absorption_default(
    mode_ckd, test_ckd_spectral_ctx_1650, model_id
):
    """
    Default value for 'has_absorption' is True, hence the absorption
    coefficient is computed and is not zero everywhere at 1650 nm.
    """
    p = AFGL1986RadProfile(dict(model_id=model_id))
    assert p.has_absorption
    ds = p.eval_dataset(test_ckd_spectral_ctx_1650)
    assert (ds.sigma_a.values != 0.0).any()

@pytest.mark.parametrize("model_id", ["midlatitude_summer", "us_standard"])
def test_afgl_1986_rad_profile_has_absorption_true(
    mode_ckd, test_ckd_spectral_ctx_1650, model_id
):
    """
    When 'has_absorption' is True, the absorption coefficient is computed
    and is not zero everywhere at 1650 nm.
    """
    p = AFGL1986RadProfile(thermoprops=dict(model_id=model_id), has_absorption=True)
    assert p.has_absorption
    ds = p.eval_dataset(test_ckd_spectral_ctx_1650)
    assert (ds.sigma_a.values != 0.0).any()

@pytest.mark.parametrize("model_id", ["midlatitude_summer", "us_standard"])
def test_afgl_1986_rad_profile_has_absorption_false(
    mode_ckd, test_ckd_spectral_ctx_1650, model_id
):
    """
    When 'has_absorption' is False, the absorption coefficient is not
    computed and is zero everywhere.
    """
    p = AFGL1986RadProfile(thermoprops=dict(model_id=model_id), has_absorption=False)
    assert not p.has_absorption
    ds = p.eval_dataset(test_ckd_spectral_ctx_1650)
    assert (ds.sigma_a.values == 0.0).all()

def test_afgl_1986_rad_profile_has_scattering_default(
    mode_ckd, test_ckd_spectral_ctx_550
):
    """
    Default value for 'has_scattering' is True, hence the absorption
    coefficient is computed and is not zero everywhere at 550 nm.
    """
    p = AFGL1986RadProfile()
    assert p.has_scattering
    ds = p.eval_dataset(test_ckd_spectral_ctx_550)
    assert (ds.sigma_s.values != 0.0).any()

def test_afgl_1986_rad_profile_has_scattering_true(mode_ckd, test_ckd_spectral_ctx_550):
    """
    When 'has_scattering' is True, the scattering coefficient is computed
    and is not zero everywhere at 550 nm.
    """
    p = AFGL1986RadProfile(has_scattering=True)
    assert p.has_scattering
    ds = p.eval_dataset(test_ckd_spectral_ctx_550)
    assert (ds.sigma_s.values != 0.0).any()

def test_afgl_1986_rad_profile_has_scattering_false(
    mode_ckd, test_ckd_spectral_ctx_550
):
    """
    When 'has_scattering' is False, the scattering coefficient is not
    computed and is zero everywhere.
    """
    p = AFGL1986RadProfile(has_scattering=False)
    assert not p.has_scattering
    ds = p.eval_dataset(test_ckd_spectral_ctx_550)
    assert (ds.sigma_s.values == 0.0).all()

@pytest.mark.parametrize(
    "model_id",
    [
        "tropical",
        "midlatitude_summer",
        "midlatitude_winter",
        "subarctic_summer",
        "subarctic_winter",
        "us_standard",
    ],
)
def test_afgl_1986_rad_profile_model_id(mode_ckd, model_id):
    """
    All models are supported in ckd mode.
    """
    AFGL1986RadProfile(thermoprops=dict(model_id=model_id))

@pytest.mark.parametrize(
    "molecule",
    ["N2O", "CO", "CH4", "O2"],
)
def test_afgl_1986_rad_profile_concentrations_ckd_not_implemented(mode_ckd, molecule):
    """
    Concentrations rescaling is not implemented for molecules other than
    H2O and O3 in CKD mode.
    """
    with pytest.raises(NotImplementedError):
        AFGL1986RadProfile(
            thermoprops=dict(concentrations={molecule: 0.0 * ureg.dimensionless})
        )

@pytest.mark.parametrize(
    "bin", ["280", "550", "790", "1040", "1270", "1590", "2220", "2400"]
)
@pytest.mark.parametrize("model_id", ["midlatitude_summer", "us_standard"])
def test_afgl_1986_rad_profile_ckd_10nm(mode_ckd, bin, model_id):
    """
    Can evaluate absorption coefficient.
    """
    p = AFGL1986RadProfile(thermoprops=dict(model_id=model_id))
    bin = eradiate.scenes.measure._core.CKDMeasureSpectralConfig(bins=bin).bins[0]
    bindex = eradiate.ckd.Bindex(bin=bin, index=3)
    spectral_ctx = SpectralContext.new(bindex=bindex, bin_set="10nm")
    assert isinstance(p.eval_sigma_a(spectral_ctx), pint.Quantity)


import requests
import time
import pandas as pd
from pprint import pprint
from bs4 import BeautifulSoup

class NikeScrape():

    def __init__(self, browser, dbEngine) -> None:

        self.browser = browser
        self.dbEngine = dbEngine

        self.SCROLL_PAUSE_TIME = 5

        self.product_categories = []
        self.products = []
        self.product_styles = []
        self.product_images = []

    def get_categories(self):
        """method to fetch categories from nike store"""
        url = 'https://www.nike.com/in/w/sale-3yaep'

        page = requests.get(url)
        soup = BeautifulSoup(page.content, 'html.parser')

        categories = soup.find_all('div', class_='categories')
        categories = categories[0].find_all('a')

        category_id = 1

        for category in categories:
            product_category = {
                'name': category.get_text(),
                '_link': category.get('href'),
                'id': category_id
            }
            self.product_categories.append(product_category)
            print(f'---{product_category["id"]} {product_category["name"]}---')
            category_id += 1

    def get_products(self):
        """method to fetch products of each category"""
        p_count = 1

        for category in self.product_categories:
            self.browser.get(category['_link'])
            self.scroll()

            category_soup = BeautifulSoup(self.browser.page_source)
            products = category_soup.find_all('div', class_='product-card')

            for product in products:
                main_link = product.find_all(
                    'a', class_='product-card__link-overlay')
                name = product.find_all(
                    'div', class_='product-card__title')[0].get_text()
                price = product.find_all(
                    'div', class_='product-price is--current-price css-s56yt7')[0].get_text()
                price_in_number = price[1:].split(',')
                short_description = product.find_all(
                    'div', class_='product-card__subtitle')[0].get_text()
                p = {
                    'product_category_id': category['id'],
                    'name': name,
                    '_link': main_link[0].get('href'),
                    'id': p_count,
                    'price': int(''.join(price_in_number)),
                    'short_description': short_description,
                    'long_description': None
                }
                self.products.append(p)
                print(f'---{p["id"]} {p["name"]}---')
                p_count += 1

    def scroll(self):
        """function to scroll to end of the page"""

        last_height = self.browser.execute_script(
            "return document.body.scrollHeight")

        while True:
            # Scroll down to bottom
            self.browser.execute_script(
                "window.scrollTo(0, document.body.scrollHeight);")

            # Wait to load page
            time.sleep(self.SCROLL_PAUSE_TIME)

            # Calculate new scroll height and compare with last scroll height
            new_height = self.browser.execute_script(
                "return document.body.scrollHeight")
            if new_height == last_height:
                break
            last_height = new_height

    def get_product_styles(self):
        """method to fetch product styles of each products"""
        product_style_id = 1

        self.product_image_id = 1

        for product in self.products:
            # open the page of the product
            self.browser.get(product['_link'])

            product_soup = BeautifulSoup(self.browser.page_source)
            product_description = product_soup.find_all('div', class_='description-preview')
            if product_description:
                long_description = product_description[0].find_all('p')[0].get_text()
                product['long_description'] = long_description

            styles_container = product_soup.find_all('div', class_='colorway-images')
            if styles_container:
                styles = styles_container[0]
                styles = styles.find_all('a')

                for style in styles:
                    # open different styles
                    self.browser.get(style.get('href'))
                    self.scroll()

                    style_soup = BeautifulSoup(self.browser.page_source)
                    color = style_soup.find_all(
                        'li', class_='description-preview__color-description')[0].get_text()
                    color_processed = color.split(':')[1][1:]
                    style = style_soup.find_all(
                        'li', class_='description-preview__style-color')[0].get_text()
                    style_processed = style.split(':')[1][1:]
                    ps = {
                        'id': product_style_id,
                        'product_id': product['id'],
                        'colour': color_processed,
                        'style_name': style_processed
                    }
                    self.product_styles.append(ps)
                    print(f'---{ps["id"]} {ps["colour"]} {ps["style_name"]}---')

                    self.get_product_images(style_soup, product_style_id)

                    product_style_id += 1

    def get_product_images(self, style_soup, product_style_id):
        """method to fetch images of different styles"""
        product_images = style_soup.find_all('div', class_='css-du206p')

        for image in product_images:
            picture_tag = image.find_all('picture')[1]
            img_tag = picture_tag.find_all('img')[0]
            # print(img_tag)
            if img_tag.has_attr('src'):
                img_url = img_tag['src']
                product_image = {
                    'id': self.product_image_id,
                    'product_style_id': product_style_id,
                    'image_url': img_url
                }
                self.product_images.append(product_image)
                print(f'---{product_image["id"]} {product_image["image_url"]}---')
                self.product_image_id += 1

    def save_to_db(self):
        df_product_categories = pd.DataFrame(self.product_categories)
        df_product_categories.drop('_link', 1, inplace=True)
        df_product_categories.to_sql(con=self.dbEngine, name='product_categories',
                                     if_exists='append', index=False)

        df_products = pd.DataFrame(self.products)
        df_products.drop('_link', 1, inplace=True)
        df_products.to_sql(con=self.dbEngine, name='products',
                           if_exists='append', index=False)

        df_product_styles = pd.DataFrame(self.product_styles)
        df_product_styles.to_sql(con=self.dbEngine, name='product_styles',
                                 if_exists='append', index=False)

        df_product_images = pd.DataFrame(self.product_images)
        df_product_images.to_sql(con=self.dbEngine, name='product_images',
                                 if_exists='append', index=False)


# -*- coding: cp1252 -*-

import uictrl as ui
from libsimpa import *
import xml.etree.ElementTree as ET
import os

def extractReceiverPositionFromXml(xmlFilePath):
    tree = ET.parse(xmlFilePath)
    root = tree.getroot()

    receivers_data = []

    def toNum(val):
        return float(val.replace(",", "."))

    for receiver_group in root.iter('recepteursp'):
        for receiver in receiver_group.iter('recepteur_ponctuel'):
            receivers_data.append([receiver.attrib["name"], toNum(receiver.attrib["x"]), toNum(receiver.attrib["y"]),
                                   toNum(receiver.attrib["z"])])

    # sort receiver by x coordinate

    receivers_data.sort(key=lambda item: item[1])

    return receivers_data

def GetMixedLevel(folderwxid):
    """
     Retourne un tableau contenant le niveau sonore global et toute bande des récepteurs ponctuels d'un dossier
     folderwxid identifiant wxid de l'élément dossier contenant les récepteurs ponctuels.
    """
    i_cols=[]
    myfrequency_labels=[]
    #folder devient l'objet dossier
    recplist=[]
    folder=ui.element(folderwxid)
    # retrieve computation result main folder location
    folderpath = ui.e_file(folder.getinfos()["parentid"]).buildfullpath()
    recpPosition = extractReceiverPositionFromXml(os.path.join(folderpath, 'config.xml'))

    for child in folder.childs():
        if child[1]==ui.element_type.ELEMENT_TYPE_REPORT_FOLDER:
            recplist.append(child[0])
    #Pour chaque récepteur on demande a l'application les données traitées du fichier ( niveau sonore et cumuls )
    intensityElements = {}
    for idrecp in recplist:
        #recp devient l'objet ayant comme indice idrecp (entier)
        parent=ui.element(idrecp)
        #application.sendevent(pere,idevent.IDEVENT_RELOAD_FOLDER)
        receiverName=parent.getinfos()["label"]
        #on recupere les données calculées
        elid = parent.getelementbylibelle('Punctual receiver intensity')
        if elid != -1:
            intensity=ui.element(elid)
            intensityElements[receiverName] = intensity

    for receiverInfo in recpPosition:
        receiverName, rx, ry, rz = receiverInfo
        if receiverName in intensityElements:
            intensity = intensityElements[receiverName]
            #on stocke dans gridspl le tableau des niveaux de pression
            gridparam=ui.application.getdataarray(intensity)
            values=gridparam[-1][1:]
            #retrieve the last row
            if len(myfrequency_labels)==0:
                myfrequency_labels=list(gridparam[0][1:])
                myfrequency_labels.insert(0, "z")
                myfrequency_labels.insert(0, "y")
                myfrequency_labels.insert(0, "x")
                myfrequency_labels.insert(0, "")
            myReceiverRow = [receiverName,rx,ry,rz]
            for idxyz in range(len(values)):
                I=values[idxyz]*1
                myReceiverRow.append(I)
            i_cols.append(myReceiverRow)
    i_cols.insert(0,myfrequency_labels)
    return i_cols
def SaveLevel(tab,path):
    #Creation de l'objet qui lit et ecris les fichier gabe
    gabewriter=Gabe_rw(len(tab))
    labelcol=stringarray()
    for cell in tab[0][1:]:
        labelcol.append(cell.encode('cp1252'))
    gabewriter.AppendStrCol(labelcol, "label")
    for col in tab[1:]:
        datacol=floatarray()
        for cell in col[1:]:
            datacol.append(float(cell))
        gabewriter.AppendFloatCol(datacol,str(col[0]))
    gabewriter.Save(path.encode('cp1252'))

def dofusion(folderwxid, path):
    arraydata=GetMixedLevel(folderwxid)
    SaveLevel(zip(*arraydata),path)
    #raffraichie l'arbre complet
    ui.application.sendevent(ui.element(ui.element(ui.application.getrootreport()).childs()[0][0]),ui.idevent.IDEVENT_RELOAD_FOLDER)

class manager:
    def __init__(self):
        self.GetD=ui.application.register_event(self.OnDFusion)
    def getmenu(self,typeel,idel,menu):
        el=ui.element(idel)
        infos=el.getinfos()
        if infos["name"]==u"Punctual receivers":
            menu.insert(0,())
            menu.insert(0,(u"Compute Intensity all",self.GetD))
            return True
        else:
            return False
    def OnDFusion(self,idel):
        grp=ui.e_file(idel)
        dofusion(idel,grp.buildfullpath()+ui._("TousInt")+".gabe")
ui.application.register_menu_manager(ui.element_type.ELEMENT_TYPE_REPORT_FOLDER, manager())


from __future__ import print_function
from __future__ import division

import os
import sys
curdir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(curdir, os.path.pardir))

if sys.version_info[0] < 3:
    reload(sys)
    sys.setdefaultencoding("utf-8")
    # raise "Must be using Python 3"

from absl import app
from absl import flags
from absl import logging
from collections import defaultdict
import copy
import random
from ml import ml

from common import *
from common.exceptions import *
from transitionparser.configurations import *

class TransitionBasedParser:
    """
    Refactored ArcStandardParser, with a Configuration object
    """
    Configuration = None
    """
   Configuration class, defines how the parser behaves
   """

    def __init__(self, decider):
        self.d = decider
        pass

    def decide(self, conf):
        actions = self.d.next_actions(
            conf.stack, conf.deps, conf.sent, conf.i, conf)
        return actions

    def parse(self, sent):
        logging.debug("parse: %s", sent)
        sent = [ROOT] + sent
        conf = self.Configuration(sent)
        logging.debug("parse: resolve conf")
        while not conf.is_in_finish_state():
            logging.debug("parse: not finish")
            next_actions = self.decide(conf)
            for act in next_actions:
                try:
                    logging.debug("parse: next_actions [%s]", act)
                    conf.do_action(act)
                    logging.debug("parse: stack len(%s), deps(%s), buffer len(%s)", len(conf.stack), len(conf.deps), (len(conf.sent) - conf.i))
                    break
                except IllegalActionException as e:
                    logging.debug("parse: next_actions error - %s", e)
                    pass
        logging.debug("parse: finish")
        return conf.deps  # ,conf.chunks

class ArcStandardParser2(TransitionBasedParser):
    Configuration = ArcStandardConfiguration

class ArcEagerParser(TransitionBasedParser):
    Configuration = ArcEagerConfiguration

class ErrorInspectionParser(ArcStandardParser2):  # {{{
    def __init__(self, decider, oracle, confPrinter, out=sys.stdout):
        ArcStandardParser2.__init__(self, decider)
        self.oracle = oracle
        self.confPrinter = confPrinter
        self.out = out

        self.raise_on_error = False
        self.use_oracle_answer = True

    def decide(self, conf):
        action = ArcStandardParser2.decide(self, conf)
        real = self.oracle.next_action(
            conf.stack, conf.deps, conf.sent, conf.i)
        if action != real:
            self.out.write(
                "%s -> %s %s\n" %
                (real, action, self.confPrinter.format(conf)))
            if self.raise_on_error:
                raise MLTrainerWrongActionException()

        if self.use_oracle_answer:
            return real
        else:
            return action


#
# This is an example script which can be used as a template to make your own graphs which intergrate with the pigrow remote gui
#
# Copy this file, remane it something that fits the pattern  graph_[name].py and save it into the graph_modules folder
#
# All code must happen within the make_graph function,
# Save the graph using the exact path given by graph_path
#
#
#
def read_graph_options():
    '''
    Returns a dictionary of settings and their default values for use by the remote gui
    '''
    graph_module_settings_dict = {
             "title_text":"",
             "show_legend":"true"
             }
    return graph_module_settings_dict

def make_graph(list_of_datasets, graph_path, ymax="", ymin="", size_h="", size_v="", dh="", th="", tc="", dc="", extra=[]):

    import matplotlib
    matplotlib.use('agg')
    import matplotlib.pyplot as plt

    if extra == {}:
        extra = read_graph_options()
    # set variables to settings from dictionary converting to the appropriate type
    title_text        = extra['title_text']
    show_legend       = extra['show_legend']

    def directionless_timedelta(time1, time2):
        if time1 > time2:
            return time1 - time2
        else:
            return time2 - time1

    if len(list_of_datasets) < 2:
        print("!!! You need two logs loaded to run this script ")
        return None

    # This compares onyl the first two datasets
    log_1_date_list = list_of_datasets[0][0]
    log_1_value_list = list_of_datasets[0][1]
    key_list_1 = list_of_datasets[0][2]
    log_2_date_list = list_of_datasets[1][0]
    log_2_value_list = list_of_datasets[1][1]
    key_list_2 = list_of_datasets[1][2]

    print("First log;", len(log_1_date_list), " Second log;", len(log_2_date_list))
    print("Want's to create a compare graph using the compare module")
    # group two lists so can calculate differences and etc

    matched_list_a_v = []
    matched_list_a_d = []
    matched_list_b_v = []
    matched_list_b_d = []
    time_diffs = []
    value_diffs = []
    # cycle through first set finding matching data
    log_2_counter = 0
    for x in range(0, len(log_1_date_list)):
        log_1_item_date =  log_1_date_list[x]
        first_log_after = 'None'
        #print(log_2_counter, len(log_2_date_list))
        if not log_2_counter > len(log_2_date_list) - 2:
            while first_log_after == 'None':
                log_2_item_date = log_2_date_list[log_2_counter]
                date_diff = log_1_item_date - log_2_item_date
                #print(x, log_1_item_date, log_2_counter, log_2_item_date)
                if log_1_item_date < log_2_item_date:
                    first_log_after = log_2_counter
                else:
                    log_2_counter += 1
                if log_2_counter > len(log_2_date_list):
                    first_log_after = None

            if log_2_counter > 0:

                time_diff_forward = directionless_timedelta(log_2_date_list[log_2_counter], log_1_date_list[x]).total_seconds()
                time_diff_back = directionless_timedelta(log_1_date_list[x], log_2_date_list[log_2_counter - 1]).total_seconds()
                if time_diff_forward < time_diff_back:
                    #print(" forward dif; ", time_diff_forward, " backward dif: ", time_diff_back)
                    #print("using forward")
                    matched_list_a_v.append(log_1_value_list[x])
                    matched_list_a_d.append(log_1_date_list[x])
                    matched_list_b_v.append(log_2_value_list[log_2_counter])
                    matched_list_b_d.append(log_2_date_list[log_2_counter])
                    time_diffs.append(time_diff_forward)
                    value_diff = log_1_value_list[x] - log_2_value_list[log_2_counter]
                    value_diffs.append(value_diff)
                else:
                    #print("using back")
                    matched_list_a_v.append(log_1_value_list[x])
                    matched_list_a_d.append(log_1_date_list[x])
                    matched_list_b_v.append(log_2_value_list[log_2_counter - 1])
                    matched_list_b_d.append(log_2_date_list[log_2_counter - 1])
                    time_diff_back = time_diff_back - time_diff_back - time_diff_back
                    time_diffs.append(time_diff_back)
                    value_diff = log_1_value_list[x] - log_2_value_list[log_2_counter - 1]
                    value_diffs.append(value_diff)

    # start making the graph
    fig, ax = plt.subplots(figsize=(size_h, size_v))
    # Top graph, the two data sets overlaid
    ax1 = plt.subplot(311)
    ax1.plot(log_1_date_list, log_1_value_list, color='blue', label=key_list_1[0], lw=1)
    ax1.plot(log_2_date_list, log_2_value_list, color='green', label=key_list_2[0], lw=1)
    #ax1.plot(matched_list_a_d, matched_list_a_v, color='blue', lw=1)
    #ax1.plot(matched_list_b_d, matched_list_b_v, color='black', lw=1)
    plt.title(title_text + "\nBoth Logs Overlaid")
    plt.grid(True)
    if key_list_1[0] == key_list_2[0]:
        plt.ylabel(key_list_1[0])
    else:
        if show_legend == "true":
            ax1.legend()
    ax1.xaxis_date()
    # Second graph, the value difference
    ax2 = plt.subplot(312, sharex=ax1)
    ax2.plot(matched_list_a_d, value_diffs, color='black', lw=1)
    plt.title("Difference between closest log values")
    plt.ylabel("Difference")
    plt.grid(True)
    # Third graph, the time difference
    ax3 = plt.subplot(313, sharex=ax1)
    ax3.plot(matched_list_a_d, time_diffs, color='black', lw=1)
    plt.title("Time Difference between closest log values")
    plt.ylabel("Time Difference in Seconds")
    plt.grid(True)

    # Set y axis min and max range
    if not ymax == "":
        plt.ylim(ymax=int(ymax))
    if not ymin == "":
        plt.ylim(ymin=int(ymin))
    # format x axis to date
    fig.autofmt_xdate()
    # save the graph
    plt.savefig(graph_path)
    # tidying up after ourselves
    plt.close(fig)
    print("compare graph created and saved to " + graph_path)


import torch
from delineation.utils import *

import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt

from torch import nn

def soft_skeletonize(x, thresh_width=1):
    '''
    Differenciable aproximation of morphological skelitonization operaton
    thresh_width - maximal expected width of vessel
    '''
    for i in range(thresh_width):
        min_pool_x = torch.nn.functional.max_pool2d(x*-1, (3, 3), 1, 1)*-1
        contour = torch.nn.functional.relu(torch.nn.functional.max_pool2d(min_pool_x, (3, 3), 1, 1) - min_pool_x)
        x = torch.nn.functional.relu(x - contour)
    return x

def norm_intersection(center_line, vessel):
    '''
    inputs shape  (batch, channel, height, width)
    intersection formalized by first ares
    x - suppose to be centerline of vessel (pred or gt) and y - is vessel (pred or gt)
    '''
    smooth = 1.
    clf = center_line.view(*center_line.shape[:2], -1)
    vf = vessel.view(*vessel.shape[:2], -1)
    intersection = (clf * vf).sum(-1)
    return (intersection + smooth) / (clf.sum(-1) + smooth)

def soft_cldice_loss(pred, target, target_skeleton=None):
    '''
    inputs shape  (batch, channel, height, width).
    calculate clDice loss
    Because pred and target at moment of loss calculation will be a torch tensors
    it is preferable to calculate target_skeleton on the step of batch forming,
    when it will be in numpy array format by means of opencv
    '''
    pred = pred.sigmoid()
    cl_pred = soft_skeletonize(pred)
    if target_skeleton is None:
        target_skeleton = soft_skeletonize(target)
    iflat = norm_intersection(cl_pred, target)
    tflat = norm_intersection(target_skeleton, pred)
    intersection = iflat * tflat
    return 1 -((2. * intersection) /
              (iflat + tflat))

def bce_segmentation_loss(projection, gt):
    criterion = torch.nn.BCEWithLogitsLoss()
    loss = criterion(projection, gt)
    return loss

def initia_loss_func(seg_l, lgt, seg_r, rgt):

    loss = 0.5 * bce_segmentation_loss(seg_l, lgt) \
           + 0.5 * bce_segmentation_loss(seg_r, rgt)

    return loss

class dice_cl_loss(torch.nn.Module):
    def __init__(self, ignore_index=250):

        super().__init__()

    def forward(self, seg_l, lgt, seg_r, rgt):

        _loss = 0.5 * soft_cldice_loss(seg_l, lgt).mean() + 0.5 * soft_cldice_loss(seg_r, rgt).mean()

        return _loss

class binary_cross_entropy_one(torch.nn.Module):
    def __init__(self, ignore_index=250):

        super().__init__()

        self.left_bce_logits = torch.nn.BCEWithLogitsLoss()

    def forward(self, seg_l, lgt):
        _loss = self.left_bce_logits(seg_l, lgt)
        return _loss

class binary_cross_entropy(torch.nn.Module):
    def __init__(self, ignore_index=250):

        super().__init__()

        self.left_bce_logits = torch.nn.BCEWithLogitsLoss()
        self.right_bce_logits = torch.nn.BCEWithLogitsLoss()

    def forward(self, seg_l, lgt, seg_r, rgt):

        _loss = 0.5 * self.left_bce_logits(seg_l, lgt) + 0.5 * self.right_bce_logits(seg_r, rgt)

        return _loss

class smooth_l1_masked_disparity(torch.nn.Module):
    def __init__(self):

        super().__init__()

    def forward(self, dl, seg_r, dlgt, lgt):

        mask = lgt > 0
        print('Max: {} Min: {}'.format(dlgt.unsqueeze(1)[mask].max(),
                                       dlgt.unsqueeze(1)[mask].min()))

        print('Predicted Max: {} Min: {}'.format(dl[mask].max(),
                                       dl[mask].min()))

        print(dl[mask].squeeze()[0:10])
        print(dlgt.unsqueeze(1)[mask].squeeze()[0:10])

        _loss = F.smooth_l1_loss(dl[mask], dlgt.unsqueeze(1)[mask], reduction='mean')

        return _loss

class warp_only(torch.nn.Module):
    def __init__(self):

        super().__init__()

        self.bce_logits = torch.nn.BCEWithLogitsLoss()

    def forward(self, dl, seg_r, dlgt, lgt):

        mask = lgt > 0
        recon_l =  F.sigmoid(warp(seg_r, dl))

        recon_l = recon_l*mask

        _loss_recon = F.smooth_l1_loss(recon_l[mask], lgt[mask], reduction='mean')

        return _loss_recon

class warp_only_joint(torch.nn.Module):
    def __init__(self):

        super().__init__()

        self.bce_logits = torch.nn.BCEWithLogitsLoss()

    def forward(self, l_aug, r_aug, l_gt_aug, r_gt_aug, dl, seg_r, seg_l, dlgt, lgt, rgt):

        loss_seg1 = 0.5 * bce_segmentation_loss(l_aug, l_gt_aug) \
               + 0.5 * bce_segmentation_loss(r_aug, l_gt_aug)

        recon_l =  warp(seg_r, dl)*seg_l
        _loss_recon = F.smooth_l1_loss(recon_l, lgt, reduction='mean')

        return 0.5*loss_seg1 + _loss_recon

class smooth_l1_masked_disparity_joint(torch.nn.Module):
    def __init__(self):

        super().__init__()

    def forward(self, l_aug, r_aug, l_gt_aug, r_gt_aug, dl, seg_r, seg_l, dlgt, lgt, rgt):

        loss_seg1 = 0.5 * bce_segmentation_loss(l_aug, l_gt_aug) \
               + 0.5 * bce_segmentation_loss(r_aug, l_gt_aug)

        mask = lgt > 0
        print('Max: {} Min: {}'.format(dlgt.unsqueeze(1)[mask].max(),
                                       dlgt.unsqueeze(1)[mask].min()))

        print('Predicted Max: {} Min: {}'.format(dl[mask].max(),
                                       dl[mask].min()))

        print(dl[mask].squeeze()[0:10])
        print(dlgt.unsqueeze(1)[mask].squeeze()[0:10])

        _loss = F.smooth_l1_loss(dl[mask], dlgt.unsqueeze(1)[mask], reduction='mean')
        _loss[torch.isnan(_loss)] = 0

        return 0.5*loss_seg1+ _loss

class smooth_l1_disparity_and_edge_warp_joint(torch.nn.Module):

    def __init__(self):

        super().__init__()

        self.bce_logits = torch.nn.BCEWithLogitsLoss()

    def forward(self, l_aug, r_aug, l_gt_aug, r_gt_aug, dl, seg_r, seg_l, dlgt, lgt, rgt):

        loss_seg1 = 0.5 * bce_segmentation_loss(l_aug, l_gt_aug) \
               + 0.5 * bce_segmentation_loss(r_aug, l_gt_aug)

        mask = lgt > 0

        recon_l =  warp(F.sigmoid(seg_r), dl)*seg_l

        _loss_recon = F.smooth_l1_loss(recon_l, lgt, reduction='mean')

        _loss = F.smooth_l1_loss(dl[mask], dlgt.unsqueeze(1)[mask], reduction='mean')
        _loss[torch.isnan(_loss)] = 0

        return 0.5*loss_seg1+_loss+ 0.5*_loss_recon

class smooth_l1_disparity_and_edge_warp(torch.nn.Module):
    def __init__(self):

        super().__init__()

        self.bce_logits = torch.nn.BCEWithLogitsLoss()

    def forward(self, dl, seg_r, dlgt, lgt):

        mask = lgt > 0
        recon_l =  F.sigmoid(warp(seg_r, dl))
     #   recon_l_gt = F.sigmoid(warp(seg_r, dlgt.unsqueeze(1)))

        # recon_l_gt = recon_l_gt*mask
        recon_l = recon_l*mask
        _loss_recon = F.smooth_l1_loss(recon_l[mask], lgt[mask], reduction='mean')

        _loss = F.smooth_l1_loss(dl[mask], dlgt.unsqueeze(1)[mask], reduction='mean')
        _loss[torch.isnan(_loss)] = 0

        return _loss+ 0.5*_loss_recon

class smooth_l1_disparity(torch.nn.Module):
    def __init__(self):

        super().__init__()

        self.bce_logits = torch.nn.BCEWithLogitsLoss()

    def forward(self, dl, seg_r, dlgt, lgt):

        mask = lgt > 0
        recon_l =  F.sigmoid(warp(seg_r, dl))

        # recon_l_gt = recon_l_gt*mask
        recon_l = recon_l*mask

        _loss_recon = F.smooth_l1_loss(recon_l[mask], lgt[mask], reduction='mean')

        _loss = F.smooth_l1_loss(dl[mask], dlgt.unsqueeze(1)[mask], reduction='mean')
        _loss[torch.isnan(_loss)] = 0

        return _loss

class smooth_l1_disparity_and_bce(torch.nn.Module):
    def __init__(self):
        super().__init__()

        self.bce_logits = torch.nn.BCEWithLogitsLoss()

    def forward(self, dl, dlgt, sl, lgt):
        mask = lgt > 0

        _loss_seg = self.bce_logits(sl, lgt)
        _loss_seg[torch.isnan(_loss_seg)] = 0

        _loss_disp = F.smooth_l1_loss(dl[mask], dlgt.unsqueeze(1)[mask], reduction='mean')
        _loss_disp[torch.isnan(_loss_disp)] = 0

        _loss = _loss_disp + 2 * _loss_seg
        return _loss, _loss_disp, _loss_seg


# This script detects for the presence of either a BME680 sensor on the I2C bus or a Sense HAT
# The BME680 includes sensors for temperature, humidity, pressure and gas content
# The Sense HAT does not have a gas sensor, and so air quality is approximated using temperature and humidity only.

import sys
import time
import smbus
import os
import json

from bme680 import BME680
from bme280 import BME280       # import the class object for our BME280 sensor
from w1therm import W1THERM
from enviroplushat import ENVIROPLUS
from http.server import HTTPServer, BaseHTTPRequestHandler

class balenaSense():
    readfrom = 'unset'
    bus = smbus.SMBus(1)

    def __init__(self):
        # First, check for enviro plus hat (since it also has BME on 0x76)
        # try:
        #     self.bus.write_byte(0x23, 0) # test if we can connect to ADS1015
        # except IOError:
        #     print('Enviro Plus hat not found')
        # else:
        #     self.readfrom = 'enviroplus'
        #     self.sensor = ENVIROPLUS()
        #     print('Found Enviro+ Hat')

        # Next, check to see if there is a BME680 on the I2C bus
        if self.readfrom == 'unset':
            try:
                self.bus.write_byte(0x76, 0)
            except IOError:
                print('BME280 not found on 0x76, trying 0x77')
            else:
                print('BME280 found on 0x76')
                self.readfrom = 'bme680secondary'
                # self.sensor = BME680(self.readfrom)
                self.sensor = BME280(self.readfrom)  # Make the class' sensor BME280

        # If we didn't find it on 0x76, look on 0x77
        if self.readfrom == 'unset':
            try:
                self.bus.write_byte(0x77, 0)
            except IOError:
                print('BME280 not found on 0x77')
            else:
                print('BME280 found on 0x77')
                self.readfrom = 'bme680primary'
                # self.sensor = BME680(self.readfrom)   <---- OLD; working
                self.sensor = BME280(self.readfrom)     # Make the class' sensor BME280

        # If no BME680, is there a Sense HAT?
        # if self.readfrom == 'unset':
        #     try:
        #         self.bus.write_byte(0x5F, 0)
        #     except:
        #         print('Sense HAT not found')
        #     else:
        #         self.readfrom = 'sense-hat'
        #         print('Using Sense HAT for readings (no gas measurements)')
        #
        #         # Import the sense hat methods
        #         import sense_hat_air_quality
        #         from hts221 import HTS221
        #         self.sense_hat_reading = lambda: sense_hat_air_quality.get_readings(HTS221())

        # Next, check if there is a 1-wire temperature sensor (e.g. DS18B20)
        # if self.readfrom == 'unset':
        #     if os.environ.get('BALENASENSE_1WIRE_SENSOR_ID') != None:
        #         sensor_id = os.environ['BALENASENSE_1WIRE_SENSOR_ID']
        #     else:
        #         sensor_id = None
        #
        #     try:
        #         self.sensor = W1THERM(sensor_id)
        #     except:
        #         print('1-wire sensor not found')
        #     else:
        #         self.readfrom = '1-wire'
        #         print('Using 1-wire for readings (temperature only)')

        # If this is still unset, no sensors were found; quit!
        if self.readfrom == 'unset':
            print('No suitable sensors found! Exiting.')
            sys.exit()

    def sample(self):
        if self.readfrom == 'sense-hat':
            return self.apply_offsets(self.sense_hat_reading())
        else:
            return self.apply_offsets(self.sensor.get_readings(self.sensor))

    def apply_offsets(self, measurements):
        # Apply any offsets to the measurements before storing them in the database
        # if os.environ.get('BALENASENSE_TEMP_OFFSET') != None:
        #     measurements[0]['fields']['temperature'] = measurements[0]['fields']['temperature'] + float(os.environ['BALENASENSE_TEMP_OFFSET'])
        #
        # if os.environ.get('BALENASENSE_HUM_OFFSET') != None:
        #     measurements[0]['fields']['humidity'] = measurements[0]['fields']['humidity'] + float(os.environ['BALENASENSE_HUM_OFFSET'])
        #
        # if os.environ.get('BALENASENSE_ALTITUDE') != None:
        #     # if there's an altitude set (in meters), then apply a barometric pressure offset
        #     altitude = float(os.environ['BALENASENSE_ALTITUDE'])
        #     measurements[0]['fields']['pressure'] = measurements[0]['fields']['pressure'] * (1-((0.0065 * altitude) / (measurements[0]['fields']['temperature'] + (0.0065 * altitude) + 273.15))) ** -5.257

        return measurements

class balenaSenseHTTP(BaseHTTPRequestHandler):
    def _set_headers(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_GET(self):
        self._set_headers()
        measurements = balenasense.sample()
        # print("##############\tHERE ARE THE MEASUREMENTS MAN\t##############")
        # print(measurements)
        # print("##############\t############################\t##############")
        print("Sending measurements in JSON")
        self.wfile.write(json.dumps(measurements[0]['fields']).encode('UTF-8'))

    def do_HEAD(self):
        self._set_headers()

# Start the server to answer requests for readings
balenasense = balenaSense()

while True:
    server_address = ('', 80)
    httpd = HTTPServer(server_address, balenaSenseHTTP)
    print('Sensor HTTP server running')
    httpd.serve_forever()


if __name__ == '__main__' and  __package__ is None:
    import sys
    from os import path
    sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )

from sklearn.model_selection import train_test_split
from models import ImageModel
from dataset_generators import ImageDataset
import utils as ut
import os
import numpy as np
from torch.utils.data import Subset, DataLoader
from torchviz import make_dot
import torch
import torch.nn as nn

MODEL_NAME = "IMAGES_MODEL"
IMAGE_SHAPE = 224
IMAGE_COL = "local_path"
LABEL_COL = "label"
LR = 0.001
DEVICE = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
BATCH_SIZE = 228
EPOCHS = 20
NUM_CLASSES = 3

data = ImageDataset(IMAGE_SHAPE, IMAGE_COL, LABEL_COL)
indices = np.arange(len(data))

train_indices, test_indices = train_test_split(indices, test_size=0.2, random_state=42)

train_data = Subset(data, train_indices)
test_data = Subset(data, test_indices)

train_loader = DataLoader(train_data, batch_size=BATCH_SIZE, shuffle=True, pin_memory=True)
test_loader = DataLoader(test_data, batch_size=BATCH_SIZE, shuffle=False, pin_memory=True)

model = ImageModel(NUM_CLASSES, IMAGE_SHAPE).to(DEVICE)

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=LR)

print()
print(" ############# MODEL SUMMARY ############# ")
print()
print(model)
print()
print(" ############ ############# ############ ")
print()

ut.train(model, train_loader, test_loader, EPOCHS, MODEL_NAME, optimizer, criterion, DEVICE, False)

# text, _ = next(iter(train_loader))
# output = model(text.to(DEVICE))

# archi = make_dot(output, params=dict(model.named_parameters()))

# archi.save("images_model_archi", "C:/Users/MourtadaHouari/Desktop/sentiment-analysis/src/images")
# archi.render('C:/Users/MourtadaHouari/Desktop/sentiment-analysis/src/images/images_model_archi', format='png')


from django.shortcuts import render
from django.http import HttpResponse
from django.http import JsonResponse
import blog.models
import json

from django.views.decorators.gzip import gzip_page

# Create your views here.

def index(request):
    articles=blog.models.Article.objects.all()
    return render(request,'blog/index.html',{'articles':articles})

def article_page(request,article_id):
    article = blog.models.Article.objects.get(pk=article_id)
    return render(request,'blog/article_page.html',{'article':article})

def edit_page(request,article_id):
    if str(article_id)=='0':
        return render(request,'blog/edit_page.html')
    article = blog.models.Article.objects.get(pk=article_id)
    return render(request,'blog/edit_page.html',{'article':article})

def edit_action(request,article_id,title,content):
    #title = request.POST.get('title','TITLE')
    #content = request.POST.get('content','CONTENT')
    #article_id=request.POST.get('article_id',0)
    if article_id=='0':
        blog.models.Article.objects.create(title=title,content=content)
        articles = blog.models.Article.objects.all()
        #return render(request,'blog/index.html',{'articles':articles})
        return HttpResponse(json.dumps({"status":0,"msg":"success"}))
    article=blog.models.Article.objects.get(pk=article_id)
    article.title=title
    article.content=content
    article.save()
    #return render(request,'blog/article_page.html',{'article':article})
    return HttpResponse(json.dumps({"status":0,"msg":"success"}))

def get_article(request,article_id):
    if article_id=='-1':
        articles=blog.models.Article.objects.all()
        data=[]
        for a in articles:
            article={"id":a.id,"title":a.title,"content":a.content}
            data.append(article)
        return HttpResponse(json.dumps({"code":0,"data":data}))
    article=blog.models.Article.objects.get(pk=article_id)
    data = {"code":0,"data":[{'id': article.id, 'title': article.title,'content':article.content},{'id': article.id, 'title': article.title,'content':article.content}]}
    return HttpResponse(json.dumps(data))
    #return JsonResponse({'id': article.id, 'title': article.title,'content':article.content})

def formattingData(code,data):
    return json.dumps(
        {
            "status": code,
            "content": data
        }
    )


#! /usr/bin/env python
import csv
import itertools
from collections import defaultdict

with open("airbnb.csv", newline="") as fid:
    reader = csv.DictReader(
        itertools.islice(fid, 1, None),
        delimiter=";",
        fieldnames=(
            "ID",
            "Listing Url",
            "Scrape ID",
            "Last Scraped",
            "Name",
            "Summary",
            "Space",
            "Description",
            "Experiences Offered",
            "Neighborhood Overview",
            "Notes",
            "Transit",
            "Access",
            "Interaction",
            "House Rules",
            "Thumbnail Url",
            "Medium Url",
            "Picture Url",
            "XL Picture Url",
            "Host ID",
            "Host URL",
            "Host Name",
            "Host Since",
            "Host Location",
            "Host About",
            "Host Response Time",
            "Host Response Rate",
            "Host Acceptance Rate",
            "Host Thumbnail Url",
            "Host Picture Url",
            "Host Neighbourhood",
            "Host Listings Count",
            "Host Total Listings Count",
            "Host Verifications",
            "Street",
            "Neighbourhood",
            "Neighbourhood Cleansed",
            "Neighbourhood Group Cleansed",
            "City",
            "State",
            "Zipcode",
            "Market",
            "Smart Location",
            "Country Code",
            "Country",
            "Latitude",
            "Longitude",
            "Property Type",
            "Room Type",
            "Accommodates",
            "Bathrooms",
            "Bedrooms",
            "Beds",
            "Bed Type",
            "Amenities",
            "Square Feet",
            "Price",
            "Weekly Price",
            "Monthly Price",
            "Security Deposit",
            "Cleaning Fee",
            "Guests Included",
            "Extra People",
            "Minimum Nights",
            "Maximum Nights",
            "Calendar Updated",
            "Has Availability",
            "Availability 30",
            "Availability 60",
            "Availability 90",
            "Availability 365",
            "Calendar last Scraped",
            "Number of Reviews",
            "First Review",
            "Last Review",
            "Review Scores Rating",
            "Review Scores Accuracy",
            "Review Scores Cleanliness",
            "Review Scores Checkin",
            "Review Scores Communication",
            "Review Scores Location",
            "Review Scores Value",
            "License",
            "Jurisdiction Names",
            "Cancellation Policy",
            "Calculated host listings count",
            "Reviews per Month",
            "Geolocation",
            "Features",
        ),
    )

    listings = defaultdict(list)

    # import ipdb

    # ipdb.set_trace()
    for row in reader:
        listings[row["Country"]].append(row["ID"])

for country, ids in listings.items():
    with open(f"{country}.txt", "w") as fid:
        fid.write("\n".join(ids))


import helper
import gold

def parse_content(content):
    """ Parse the content of the file """
    words = dict()
    for line in content.split('\n'):
        word, frequency = line.split()
        words[word] = int(frequency)

    return words

def make_tree(words):
    trie_structure = dict()
    for key, value in words.items():
        current_loc = trie_structure
        for character in key:
            if character not in current_loc.keys():
                current_loc[character] = dict()

            current_loc = current_loc[character]
        current_loc["$" + key] = value

    return trie_structure

def get_leaves(node):
    """ Get the leaves from a given tree """
    leaf_nodes = list()
    search_list = [node]

    while search_list:
        search_node = search_list.pop()
        for key in search_node.keys():
            if key.startswith("$"):
                leaf_nodes.append((key.replace("$", ""), search_node[key]))
            else:
                search_list.append(search_node[key])

    return leaf_nodes

def predict(tree, numbers):
    """ Predict the value from the input numbers """
    output_predictions = list()
    search_list = [tree]
    t9 = {"2": "abc", "3": "def", "4": "ghi", "5": "jkl", "6": "mno", "7": "pqrs", "8": "tuv", "9": "wxyz"}

    for number in numbers:
        length = len(search_list)

        for _ in range(length):
            node = search_list.pop(0)
            for key in node.keys():
                if key in t9[number]:
                    search_list.append(node[key])

    for node in search_list:
        output_predictions.extend(get_leaves(node))

    output_predictions.sort(key=lambda x: x[1], reverse=True)
    return output_predictions

if __name__ == '__main__':
    content = helper.read_content(filename='ngrams-10k.txt')

    # When you've finished implementing a part, remove the `gold.` prefix to check your own code.

    # PART 1: Parsing a string into a dictionary.
    words = parse_content(content)

    # PART 2: Building a trie from a collection of words.
    tree = make_tree(words)

    while True:
        # PART 3: Predict words that could follow
        numbers = helper.ask_for_numbers()
        predictions = predict(tree, numbers)

        if not predictions:
            print('No words were found that match those numbers. :(')
        else:
            for prediction, frequency in predictions[:10]:
                print(prediction, frequency)

        response = input('Want to go again? [y/N] ')
        again = response and response[0] in ('y', 'Y')
        if not again:
            break

Lessons Exercises/T9 Predictive Text/T9.py


from flask_mail import Message
from flask import current_app, render_template
from WateringSite import mail
from threading import Thread

def send_async_email(app, msg):
    with app.app_context():
        mail.send(msg)

def send_email(subject, sender, recipients, text_body, html_body):
    msg = Message(subject, sender=sender, recipients=recipients)
    msg.body = text_body
    msg.html = html_body
    Thread(target=send_async_email,
           args=(current_app._get_current_object(), msg)).start()

def send_guest_access_email(device, sender, recipient):
    token = device.get_guest_access_token((72*60*60))
    send_email('Invitation to a [Plant Party]',
               sender=("{} at HannahsPlants.party".format(sender.username), current_app.config['ADMINS'][0]),
               recipients=[recipient["Email"]],
               text_body=render_template('email/guest_access.txt',
                                         sender=sender, recipient=recipient, token=token),
               html_body=render_template('email/guest_access.html',
                                         sender=sender, recipient=recipient, token=token))


from tkinter import *
from tkinter.ttk import *
import sqlite3

class Win_Infrastructure:
    def __init__(self, driver):
        self.driver = driver

    # Function to manage infrastructure
    def open_inf(self, root):
        # Create infrastructure window
        win = Toplevel(root)
        win.title("Infrastructure")
        # Rezise patient window
        win.geometry("1600x900")

        #======================================================================================================
        #============================================= Rooms =================================================
        #======================================================================================================
        # Databases
        # Create a database or connect to one
        conn = sqlite3.connect("hospital.db")

        # Create cursor
        c = conn.cursor()

        # Create Treeview Frame
        tree1_frame = Frame(win)
        tree1_frame.pack()

        # Add some style
        style2 = Style()
        style2.configure("Treeview",
                rowheight = 15)

        # Treeview scrollbar
        tree1_scroll = Scrollbar(tree1_frame)
        tree1_scroll.pack(side=RIGHT, fill= Y)

        # Create Treeview
        my_tree1 = Treeview(tree1_frame, yscrollcommand= tree1_scroll.set, selectmode='extended')

        # Pack to the screen
        my_tree1.pack()

        # Configure the scrollbar
        tree1_scroll.config(command=my_tree1.yview)

        # Define our columns
        my_tree1['columns'] = ("ID", "Name")

        # Formate our columns
        my_tree1.column("#0", width = 0, stretch = NO)
        my_tree1.column("ID", anchor = W, width =100)
        my_tree1.column("Name", anchor = CENTER, width = 200)

        # Create Headings
        my_tree1.heading("#0", text = "", anchor = CENTER)
        my_tree1.heading("ID", text = "ID", anchor=CENTER)
        my_tree1.heading("Name", text = "Name", anchor=CENTER)

        # Create striped row tags
        my_tree1.tag_configure("oddrow", background= "white")
        my_tree1.tag_configure("evenrow", background= "lightblue")

        # Room Record Frame
        add_frame = LabelFrame(win, text = "Room Record")
        add_frame.pack(fill="x", expand="yes", padx= 20)

        id1 = Label(add_frame, text="ID")
        id1.grid(row=0, column=0, padx= 10, pady= 5)

        name1 = Label(add_frame, text="Name")
        name1.grid(row=0, column = 1, padx= 10, pady= 5)

        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        #~~~~~~~~~~~~~~~~~~~ Entry ~~~~~~~~~~~~~~~~~~~~~~~~~
        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        # Room ID
        id1_box = Entry(add_frame)
        id1_box.grid(row=1, column=0, padx= 10, pady= 5)

        # Room Name
        name1_box = Entry(add_frame)
        name1_box.grid(row=1, column=1, padx= 10, pady= 5)

        # Select Record
        def select_record1(e):
            # Clear boxes
            id1_box.delete(0, END)
            name1_box.delete(0, END)

            # Grab record Number
            selected = my_tree1.focus()

            # Grab record values
            values = my_tree1.item(selected, 'values')

            # Output to entry boxes
            id1_box.insert(0, values[0])
            name1_box.insert(0, values[1])

        # Update Record
        def update_record1():

            #Grab the record Number
            selected = my_tree1.focus()

            # Update record
            my_tree1.item(selected, text='', values=(id1_box.get(),name1_box.get()))

            # Create a database or connect to one
            conn = sqlite3.connect("hospital.db")

            # Create cursor
            c = conn.cursor()

            c.execute("""UPDATE rooms SET
                    r_id = :r_id,
                    r_name = :r_name

                    WHERE r_id = :r_id""",
                    {
                        'r_id' : id1_box.get(),
                        'r_name': name1_box.get()

                    }
                    )

            # Commit Changes
            conn.commit()

            # Close Connection
            conn.close()

            # Pull data before running program
            query_database1()

        # Add record
        def add_record1():
            # Create a database or connect to one
            conn = sqlite3.connect("hospital.db")

            # Create cursor
            c = conn.cursor()

            # Add New Record
            c.execute("INSERT INTO rooms (r_id, r_name) Values (:r_id, :r_name)",
            {
                'r_id' : id1_box.get(),
                'r_name' : name1_box.get()
            }
            )

            # Commit Changes
            conn.commit()

            # Close Connection
            conn.close()

            # Clear boxes
            id1_box.delete(0, END)
            name1_box.delete(0, END)

            # Clear The Treeview Table
            my_tree1.delete(*my_tree1.get_children())

            # Run to pull data from database on start
            query_database1()

        # Show records upon running program
        def query_database1():
            # Create a database or connect to one
            conn = sqlite3.connect("hospital.db")

            # Create cursor
            c = conn.cursor()

            # Query the database
            c.execute("SELECT * FROM rooms")
            records = c.fetchall()

            # Loop Thru Results
            global count
            count = 0
            for record in records:
                if count % 2 == 0:
                    my_tree1.insert(parent='', index='end', iid= count , text=f'count', values=(record[0], record[1]) , tags= ("evenrow",))
                else:
                    my_tree1.insert(parent='', index='end', iid= count , text=f'count', values=(record[0], record[1]) , tags= ("oddrow",))
                count += 1

            # Commit Changes
            conn.commit()

            # Close Connection
            conn.close()

        # Remove all
        def remove_all1():
            # Create a database or connect to one
            conn = sqlite3.connect("hospital.db")

            # Create cursor
            c = conn.cursor()

            for record in my_tree1.get_children():
                my_tree1.delete(record)

            c.execute("DELETE from rooms")
            # Remove data away from database here

            # Commit Changes
            conn.commit()

            # Close Connection
            conn.close()

            # Clear The Treeview Table
            my_tree1.delete(*my_tree1.get_children())

            # Run to pull data from database on start
            query_database1()

        # Remove one selected
        def remove_one1():
            x = my_tree1.selection()[0]
            my_tree1.delete(x)

            # Create a database or connect to one
            conn = sqlite3.connect("hospital.db")

            # Create cursor
            c = conn.cursor()

            c.execute("DELETE from rooms WHERE r_id=" + room_id_box.get())

            # Clear boxes
            id1_box.delete(0, END)
            name1_box.delete(0, END)

            # Commit Changes
            conn.commit()

            # Close Connection
            conn.close()

            # Clear The Treeview Table
            my_tree1.delete(*my_tree1.get_children())

            # Run to pull data from database on start
            query_database1()

        # Remove many selected
        def remove_many1():
            # Create a database or connect to one
            conn = sqlite3.connect("hospital.db")

            # Create cursor
            c = conn.cursor()

            x = my_tree1.selection()
            for record in x:
                my_tree1.delete(record)
                c.execute("DELETE from rooms WHERE r_id=" + record[0])

            # Commit Changes
            conn.commit()

            # Close Connection
            conn.close()

            # Clear The Treeview Table
            my_tree1.delete(*my_tree1.get_children())

            # Run to pull data from database on start
            query_database1()

        btn_frame1 = LabelFrame(win, text= "Room Command")
        btn_frame1.pack(fill ="x", expand="yes", padx=20)

        # Buttons
        add_record1 = Button(btn_frame1, text="Add Record", command= add_record1)
        add_record1.grid(row= 0 , column= 0, padx= 10, pady= 5)

        # Update Records
        update_record = Button(btn_frame1, text = "Update Record", command= update_record1)
        update_record.grid(row = 0, column= 1, padx= 10, pady= 5)

        # Remove all
        remove_all1 = Button(btn_frame1, text = "Remove All Record", command = remove_all1)
        remove_all1.grid(row = 0, column= 2, padx= 10, pady= 5)

        # Remove one
        remove_one1 = Button(btn_frame1, text= "Remove One Selected", command=remove_one1)
        remove_one1.grid(row= 0, column= 3, padx= 10, pady= 5)

        # Remove many selected
        remove_many1 = Button(btn_frame1, text = "Remove Many Selected", command= remove_many1)
        remove_many1.grid(row = 0, column= 4, padx= 10, pady= 5)

        # Bind the treeview
        my_tree1.bind("<ButtonRelease-1>", select_record1)

        # Pull data before running program
        query_database1()

        #======================================================================================================
        #============================================= Beds =================================================
        #======================================================================================================

        # Create Treeview Frame
        tree2_frame = Frame(win)
        tree2_frame.pack()

        # Treeview scrollbar
        tree2_scroll = Scrollbar(tree2_frame)
        tree2_scroll.pack(side=RIGHT, fill= Y)

        # Create Treeview
        my_tree2 = Treeview(tree2_frame, yscrollcommand= tree2_scroll.set, selectmode='extended')

        # Pack to the screen
        my_tree2.pack()

        # Configure the scrollbar
        tree2_scroll.config(command=my_tree2.yview)

        # Define our columns
        my_tree2['columns'] = ("Bed ID", "Room Name", "Room ID", "Patient ID")

        # Formate our columns
        my_tree2.column("#0", width = 0, stretch = NO)
        my_tree2.column("Bed ID", anchor = W, width =100)
        my_tree2.column("Room Name", anchor = CENTER, width = 200)
        my_tree2.column("Room ID", anchor = W, width = 200)
        my_tree2.column("Patient ID", anchor = W, width = 100)

        # Create Headings
        my_tree2.heading("#0", text = "", anchor = CENTER)
        my_tree2.heading("Bed ID", text = "Bed ID", anchor=CENTER)
        my_tree2.heading("Room Name", text = "Room Name", anchor=CENTER)
        my_tree2.heading("Room ID", text = "Room ID", anchor=CENTER)
        my_tree2.heading("Patient ID", text = "Patient ID", anchor=CENTER)

        # Create striped row tags
        my_tree2.tag_configure("oddrow", background= "white")
        my_tree2.tag_configure("evenrow", background= "lightblue")

        my_tree2.pack(pady= 10)

        add_frame2 = LabelFrame(win, text= "Bed Record")
        add_frame2.pack(fill="x", expand="yes", padx= 20)

        bed_id = Label(add_frame2, text="Bed ID")
        bed_id.grid(row=0, column=0)

        room_name = Label(add_frame2, text="Room Name")
        room_name.grid(row=0, column = 1)

        room_id = Label(add_frame2, text="Room ID")
        room_id.grid(row=0, column = 2)

        patient_id = Label(add_frame2, text = "Patient ID")
        patient_id.grid(row=0, column = 3)

        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        #~~~~~~~~~~~~~~~~~~~ Entry ~~~~~~~~~~~~~~~~~~~~~~~~~
        #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        # ID
        bed_id_box = Entry(add_frame2)
        bed_id_box.grid(row=1, column=0, padx= 10, pady= 5)

        # Room Name
        room_name_box = Entry(add_frame2)
        room_name_box.grid(row=1, column=1, padx= 10, pady= 5)

        # Room ID
        room_id_box = Entry(add_frame2)
        room_id_box.grid(row=1, column=2, padx= 10, pady= 5)

        # Patient ID
        patient_id_box = Entry(add_frame2)
        patient_id_box.grid(row=1, column=3, padx= 10, pady= 5)

        # Select Record
        def select_record2(e):
            # Clear boxes
            bed_id_box.delete(0, END)
            room_name_box.delete(0, END)
            room_id_box.delete(0, END)
            patient_id_box.delete(0, END)

            # Grab record Number
            selected = my_tree2.focus()

            # Grab record values
            values = my_tree2.item(selected, 'values')

            # Output to entry boxes
            bed_id_box.insert(0, values[0])
            room_name_box.insert(0, values[1])
            room_id_box.insert(0, values[2])
            patient_id_box.insert(0, values[3])

        # Update Record
        def update_record2():

            #Grab the record Number
            selected = my_tree2.focus()

            # Update record
            my_tree2.item(selected, text='', values=(bed_id_box.get(),room_name_box.get(), room_id_box.get(), patient_id_box.get()))

            # Create a database or connect to one
            conn = sqlite3.connect("hospital.db")

            # Create cursor
            c = conn.cursor()

            # Still lack of foreign key!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            c.execute("""UPDATE beds SET
                    bed_id = :bed_id,
                    bed_r_name = :bed_r_name,
                    bed_r_id = :bed_r_id,
                    bed_p_id = :bed_p_id,

                    WHERE bed_id = :bed_id""",
                    {
                        'bed_id' : bed_id_box.get(),
                        'bed_r_name': room_name_box.get(),
                        'bed_r_id' : room_id_box.get(),
                        'bed_p_id' : patient_id_box.get(),

                    }
                    )

            # Commit Changes
            conn.commit()

            # Close Connection
            conn.close()

            # Pull data before running program
            query_database2()

        # Add record
        def add_record2():
            # Create a database or connect to one
            conn = sqlite3.connect("hospital.db")

            # Create cursor
            c = conn.cursor()

            # Add New Record
            c.execute("INSERT INTO beds (bed_r_name, bed_r_id, bed_p_id) Values (:bed_r_name, :bed_r_id, :bed_p_id)",
            {
                'bed_r_name' : room_name_box.get(),
                'bed_r_id' : room_id_box.get(),
                'bed_p_id' : patient_id_box.get(),
            }
            )

            # Commit Changes
            conn.commit()

            # Close Connection
            conn.close()

            # Clear boxes
            room_name_box.delete(0, END)
            room_id_box.delete(0, END)
            patient_id_box.delete(0, END)

            # Clear The Treeview Table
            my_tree2.delete(*my_tree2.get_children())

            # Run to pull data from database on start
            query_database2()

        # Show records upon running program
        def query_database2():
            # Create a database or connect to one
            conn = sqlite3.connect("hospital.db")

            # Create cursor
            c = conn.cursor()

            # Query the database
            c.execute("SELECT * FROM beds")
            records = c.fetchall()

            # Loop Thru Results
            global count
            count = 0
            for record in records:
                if count % 2 == 0:
                    my_tree2.insert(parent='', index='end', iid= count , text=f'count', values=(record[0], record[1], record[2], record[3]) , tags= ("evenrow",))
                else:
                    my_tree2.insert(parent='', index='end', iid= count , text=f'count', values=(record[0], record[1], record[2], record[3]) , tags= ("oddrow",))
                count += 1

            # Commit Changes
            conn.commit()

            # Close Connection
            conn.close()

        # Remove all
        def remove_all2():
            # Create a database or connect to one
            conn = sqlite3.connect("hospital.db")

            # Create cursor
            c = conn.cursor()

            for record in my_tree2.get_children():
                my_tree2.delete(record)

            c.execute("DELETE from beds")

            # Commit Changes
            conn.commit()

            # Close Connection
            conn.close()

            # Clear The Treeview Table
            my_tree2.delete(*my_tree2.get_children())

            # Run to pull data from database on start
            query_database2()

        # Remove one selected
        def remove_one2():
            # Create a database or connect to one
            conn = sqlite3.connect("hospital.db")

            # Create cursor
            c = conn.cursor()

            x = my_tree2.selection()[0]
            my_tree2.delete(x)

            c.execute("DELETE from nurses WHERE nur_id=" + bed_id_box.get())

            # Clear boxes
            bed_id_box.delete(0, END)
            room_name_box.delete(0, END)
            room_id_box.delete(0, END)
            patient_id_box.delete(0, END)

            # Commit Changes
            conn.commit()

            # Close Connection
            conn.close()

            # Clear The Treeview Table
            my_tree2.delete(*my_tree2.get_children())

            # Run to pull data from database on start
            query_database2()

        # Remove many selected
        def remove_many2():
            # Create a database or connect to one
            conn = sqlite3.connect("hospital.db")

            # Create cursor
            c = conn.cursor()

            x = my_tree2.selection()
            for record in x:
                my_tree2.delete(record)
                c.execute("DELETE from beds WHERE bed_id=" + record[0])

            # Commit Changes
            conn.commit()

            # Close Connection
            conn.close()

            # Clear The Treeview Table
            my_tree2.delete(*my_tree2.get_children())

            # Run to pull data from database on start
            query_database2()

        # Buttons frame
        btn_frame2 = LabelFrame(win, text= "Bed Command")
        btn_frame2.pack(fill ="x", expand="yes", padx=20)

        # Buttons
        add_recordx2 = Button(btn_frame2, text="Add Record", command= add_record2)
        add_recordx2.grid(row= 0 , column= 0, padx= 10, pady= 5)

        # Show Records
        update_record2 = Button(btn_frame2, text = "Update Record", command= update_record2)
        update_record2.grid(row = 0, column= 1, padx= 10, pady= 5)

        # Remove all
        remove_allx2 = Button(btn_frame2, text = "Remove All Record", command = remove_all2)
        remove_allx2.grid(row = 0, column= 2, padx= 10, pady= 5)

        # Remove one
        remove_onex2 = Button(btn_frame2, text= "Remove One Selected", command=remove_one2)
        remove_onex2.grid(row= 0, column= 3, padx= 10, pady= 5)

        # Remove many selected
        remove_manyx2 = Button(btn_frame2, text = "Remove Many Selected", command= remove_many2)
        remove_manyx2.grid(row = 0, column= 4, padx= 10, pady= 5)

        # Bind the treeview
        my_tree2.bind("<ButtonRelease-1>", select_record2)

        # Pull data before running program
        query_database2()

        # Win loop
        win.mainloop()