from gurobipy import GRB, Model, quicksum

m = Model('Optimizacion de recursos hospitalarios')

#max 108.750.000

#=====CONJUNTOS=====
i_personal = ['enf', 'sec', 'doc', 'cirj', 'ten']
f_rubros = ['adm', 'urg', 'clin', 'pab']
c_contratos = ['c1', 'c2', 'c3']
n_insumos = ['bisturi', 'pinzas', 'papel']
d_medicamentos = ['parac', 'ibup', 'queti', 'vit']
b_infraestructuras = ['box1', 'box2', 'box3', 'box4']
l_laboratorios = ['lab1', 'lab2', 'lab3']
v_bodegas = ['bod1', 'bod2']
t_periodo = ['ene', 'feb', 'mar', 'abr', 'may']

#=====PARAMETROS=====
personal_H = {
    'enf' : {
        ('ene', 'c1') : 500000, ('feb', 'c1') : 500000, ('mar', 'c1') : 500000, ('abr', 'c1') : 500000, ('may', 'c1') : 500000,
        ('ene', 'c2') : 600000, ('feb', 'c2') : 600000, ('mar', 'c2') : 600000, ('abr', 'c2') : 600000, ('may', 'c2') : 600000,
        ('ene', 'c3') : 700000, ('feb', 'c3') : 700000, ('mar', 'c3') : 700000, ('abr', 'c3') : 700000, ('may', 'c3') : 700000,
        },
    'sec' : {
        ('ene', 'c1') : 350000, ('feb', 'c1') : 350000, ('mar', 'c1') : 350000, ('abr', 'c1') : 350000, ('may', 'c1') : 350000,
        ('ene', 'c2') : 350000, ('feb', 'c2') : 350000, ('mar', 'c2') : 350000, ('abr', 'c2') : 350000, ('may', 'c2') : 350000,
        ('ene', 'c3') : 350000, ('feb', 'c3') : 350000, ('mar', 'c3') : 350000, ('abr', 'c3') : 350000, ('may', 'c3') : 350000,
        },
    'doc' : {
        ('ene', 'c1') : 800000, ('feb', 'c1') : 800000, ('mar', 'c1') : 800000, ('abr', 'c1') : 800000, ('may', 'c1') : 800000,
        ('ene', 'c2') : 850000, ('feb', 'c2') : 850000, ('mar', 'c2') : 850000, ('abr', 'c2') : 850000, ('may', 'c2') : 850000,
        ('ene', 'c3') : 900000, ('feb', 'c3') : 900000, ('mar', 'c3') : 900000, ('abr', 'c3') : 900000, ('may', 'c3') : 900000,
        },
    'cirj' : {
        ('ene', 'c1') : 1000000, ('feb', 'c1') : 1000000, ('mar', 'c1') : 1000000, ('abr', 'c1') : 1000000, ('may', 'c1') : 1000000,
        ('ene', 'c2') : 1250000, ('feb', 'c2') : 1250000, ('mar', 'c2') : 1250000, ('abr', 'c2') : 1250000, ('may', 'c2') : 1250000,
        ('ene', 'c3') : 1500000, ('feb', 'c3') : 1500000, ('mar', 'c3') : 1500000, ('abr', 'c3') : 1500000, ('may', 'c3') : 1500000,
        },
    'ten' : {
        ('ene', 'c1') : 350000, ('feb', 'c1') : 350000, ('mar', 'c1') : 350000, ('abr', 'c1') : 450000, ('may', 'c1') : 550000,
        ('ene', 'c2') : 350000, ('feb', 'c2') : 350000, ('mar', 'c2') : 350000, ('abr', 'c2') : 450000, ('may', 'c2') : 550000,
        ('ene', 'c3') : 350000, ('feb', 'c3') : 350000, ('mar', 'c3') : 350000, ('abr', 'c3') : 450000, ('may', 'c3') : 550000,
        }
}
personal_V = {
    'adm' : {'ene' : 12, 'feb' : 12, 'mar' : 12, 'abr' : 12, 'may' : 12},
    'urg' : {'ene' : 50, 'feb' : 50, 'mar' : 50, 'abr' : 75, 'may' : 75},
    'clin' : {'ene' : 50, 'feb' : 50, 'mar' : 50, 'abr' : 70, 'may' : 70},
    'pab' : {'ene' : 15, 'feb' : 15, 'mar' : 15, 'abr' : 5, 'may' : 5},
}
personal_A = {
    'adm' : {'ene' : 108750000, 'feb' : 108750000, 'mar' : 108750000, 'abr' : 108750000, 'may' : 108750000},
    'urg' : {'ene' : 108750000, 'feb' : 108750000, 'mar' : 108750000, 'abr' : 108750000, 'may' : 108750000},
    'clin' : {'ene' : 108750000, 'feb' : 108750000, 'mar' : 108750000, 'abr' : 108750000, 'may' : 108750000},
    'pab' : {'ene' : 108750000, 'feb' : 108750000, 'mar' : 108750000, 'abr' : 108750000, 'may' : 108750000},
}
insumos_G = {
    'bisturi' : {'ene' : 50, 'feb' : 50, 'mar' : 50, 'abr' : 50, 'may' : 50},
    'pinzas' : {'ene' : 60, 'feb' : 60, 'mar' : 60, 'abr' : 60, 'may' : 60},
    'papel' : {'ene' : 100, 'feb' : 100, 'mar' : 100, 'abr' : 100, 'may' : 100}
}
insumos_E = {
    'bisturi' : {
        ('ene', 'bod1') : 325, ('feb', 'bod1') : 325, ('mar', 'bod1') : 325, ('abr', 'bod1') : 325, ('may', 'bod1') : 325,
        ('ene', 'bod2') : 225, ('feb', 'bod2') : 225, ('mar', 'bod2') : 225, ('abr', 'bod2') : 225, ('may', 'bod2') : 225,
        },
    'pinzas' : {
        ('ene', 'bod1') : 325, ('feb', 'bod1') : 325, ('mar', 'bod1') : 325, ('abr', 'bod1') : 325, ('may', 'bod1') : 325,
        ('ene', 'bod2') : 325, ('feb', 'bod2') : 325, ('mar', 'bod2') : 325, ('abr', 'bod2') : 325, ('may', 'bod2') : 325,
        },
    'papel' : {
        ('ene', 'bod1') : 300, ('feb', 'bod1') : 300, ('mar', 'bod1') : 300, ('abr', 'bod1') : 300, ('may', 'bod1') : 300,
        ('ene', 'bod2') : 200, ('feb', 'bod2') : 200, ('mar', 'bod2') : 200, ('abr', 'bod2') : 200, ('may', 'bod2') : 200,
        }
}
insumos_L = {
    'ene' : 1000000, 'feb' : 1000000, 'mar' : 1000000, 'abr' : 1000000, 'may' : 1000000
}
insumos_Ii = {
    'bisturi' : {'ene' : 0, 'feb' : 20, 'mar' : 20, 'abr' : 20, 'may' : 20},
    'pinzas' : {'ene' : 0, 'feb' : 20, 'mar' : 20, 'abr' : 20, 'may' : 20},
    'papel' : {'ene' : 0, 'feb' : 20, 'mar' : 20, 'abr' : 20, 'may' : 20}
}
insumos_Ai = {
    'bisturi' : {'ene' : 100, 'feb' : 100, 'mar' : 100, 'abr' : 100, 'may' : 100},
    'pinzas' : {'ene' : 100, 'feb' : 100, 'mar' : 100, 'abr' : 100, 'may' : 100},
    'papel' : {'ene' : 100, 'feb' : 100, 'mar' : 100, 'abr' : 100, 'may' : 100}
}
insumos_CFi = {
    'bisturi' : {
        ('ene', 'bod1') : 100, ('feb', 'bod1') : 100, ('mar', 'bod1') : 100, ('abr', 'bod1') : 100, ('may', 'bod1') : 100,
        ('ene', 'bod2') : 100, ('feb', 'bod2') : 100, ('mar', 'bod2') : 100, ('abr', 'bod2') : 100, ('may', 'bod2') : 100,
        },
    'pinzas' : {
        ('ene', 'bod1') : 100, ('feb', 'bod1') : 100, ('mar', 'bod1') : 100, ('abr', 'bod1') : 100, ('may', 'bod1') : 100,
        ('ene', 'bod2') : 100, ('feb', 'bod2') : 100, ('mar', 'bod2') : 100, ('abr', 'bod2') : 100, ('may', 'bod2') : 100,
        },
    'papel' : {
        ('ene', 'bod1') : 100, ('feb', 'bod1') : 100, ('mar', 'bod1') : 100, ('abr', 'bod1') : 100, ('may', 'bod1') : 100,
        ('ene', 'bod2') : 100, ('feb', 'bod2') : 100, ('mar', 'bod2') : 100, ('abr', 'bod2') : 100, ('may', 'bod2') : 100,
        }
}
medicamentos_Q = {
    'parac' : {
        ('ene', 'lab1') : 750, ('feb', 'lab1') : 750, ('mar', 'lab1') : 750, ('abr', 'lab1') : 750, ('may', 'lab1') : 750,
        ('ene', 'lab2') : 800, ('feb', 'lab2') : 800, ('mar', 'lab2') : 800, ('abr', 'lab2') : 800, ('may', 'lab2') : 800,
        ('ene', 'lab3') : 800, ('feb', 'lab3') : 800, ('mar', 'lab3') : 800, ('abr', 'lab3') : 800, ('may', 'lab3') : 800
        },
    'ibup' : {
        ('ene', 'lab1') : 800, ('feb', 'lab1') : 800, ('mar', 'lab1') : 800, ('abr', 'lab1') : 800, ('may', 'lab1') : 800,
        ('ene', 'lab2') : 750, ('feb', 'lab2') : 750, ('mar', 'lab2') : 750, ('abr', 'lab2') : 750, ('may', 'lab2') : 750,
        ('ene', 'lab3') : 700, ('feb', 'lab3') : 700, ('mar', 'lab3') : 700, ('abr', 'lab3') : 700, ('may', 'lab3') : 700
        },
    'queti' : {
        ('ene', 'lab1') : 1950, ('feb', 'lab1') : 1950, ('mar', 'lab1') : 1950, ('abr', 'lab1') : 1950, ('may', 'lab1') : 1950,
        ('ene', 'lab2') : 1950, ('feb', 'lab2') : 1950, ('mar', 'lab2') : 1950, ('abr', 'lab2') : 1950, ('may', 'lab2') : 1950,
        ('ene', 'lab3') : 1500, ('feb', 'lab3') : 1500, ('mar', 'lab3') : 1500, ('abr', 'lab3') : 1500, ('may', 'lab3') : 1500
        },
    'vit' : {
        ('ene', 'lab1') : 750, ('feb', 'lab1') : 750, ('mar', 'lab1') : 750, ('abr', 'lab1') : 750, ('may', 'lab1') : 750,
        ('ene', 'lab2') : 500, ('feb', 'lab2') : 500, ('mar', 'lab2') : 500, ('abr', 'lab2') : 500, ('may', 'lab2') : 500,
        ('ene', 'lab3') : 650, ('feb', 'lab3') : 650, ('mar', 'lab3') : 650, ('abr', 'lab3') : 650, ('may', 'lab3') : 650
        }
}
medicamentos_O = {
    'parac' : {'ene' : 50, 'feb' : 50, 'mar' : 50, 'abr' : 50, 'may' : 50},
    'ibup' : {'ene' : 60, 'feb' : 60, 'mar' : 60, 'abr' : 60, 'may' : 60},
    'queti' : {'ene' : 50, 'feb' : 50, 'mar' : 50, 'abr' : 50, 'may' : 50},
    'vit' : {'ene' : 100, 'feb' : 100, 'mar' : 100, 'abr' : 100, 'may' : 100}
}
medicamentos_Z = {
    'ene' : 1000000, 'feb' : 1000000, 'mar' : 1000000, 'abr' : 1000000, 'may' : 1000000
}
medicamentos_Im = {
    'parac' : {'ene' : 0, 'feb' : 0, 'mar' : 0, 'abr' : 0, 'may' : 0},
    'ibup' : {'ene' : 0, 'feb' : 0, 'mar' : 0, 'abr' : 0, 'may' : 0},
    'queti' : {'ene' : 0, 'feb' : 0, 'mar' : 0, 'abr' : 0, 'may' : 0},
    'vit' : {'ene' : 0, 'feb' : 0, 'mar' : 0, 'abr' : 0, 'may' : 0}
}
medicamentos_Am = {
    'parac' : {'ene' : 100, 'feb' : 100, 'mar' : 100, 'abr' : 100, 'may' : 100},
    'ibup' : {'ene' : 100, 'feb' : 100, 'mar' : 100, 'abr' : 100, 'may' : 100},
    'queti' : {'ene' : 100, 'feb' : 100, 'mar' : 100, 'abr' : 100, 'may' : 100},
    'vit' : {'ene' : 100, 'feb' : 100, 'mar' : 100, 'abr' : 100, 'may' : 100}
}
medicamentos_CFm = {
    'parac' : {
        ('ene', 'lab1') : 100, ('feb', 'lab1') : 100, ('mar', 'lab1') : 100, ('abr', 'lab1') : 100, ('may', 'lab1') : 100,
        ('ene', 'lab2') : 100, ('feb', 'lab2') : 100, ('mar', 'lab2') : 100, ('abr', 'lab2') : 100, ('may', 'lab2') : 100,
        ('ene', 'lab3') : 100, ('feb', 'lab3') : 100, ('mar', 'lab3') : 100, ('abr', 'lab3') : 100, ('may', 'lab3') : 100
        },
    'ibup' : {
        ('ene', 'lab1') : 100, ('feb', 'lab1') : 100, ('mar', 'lab1') : 100, ('abr', 'lab1') : 100, ('may', 'lab1') : 100,
        ('ene', 'lab2') : 100, ('feb', 'lab2') : 100, ('mar', 'lab2') : 100, ('abr', 'lab2') : 100, ('may', 'lab2') : 100,
        ('ene', 'lab3') : 100, ('feb', 'lab3') : 100, ('mar', 'lab3') : 100, ('abr', 'lab3') : 100, ('may', 'lab3') : 100
        },
    'queti' : {
        ('ene', 'lab1') : 100, ('feb', 'lab1') : 100, ('mar', 'lab1') : 100, ('abr', 'lab1') : 100, ('may', 'lab1') : 100,
        ('ene', 'lab2') : 100, ('feb', 'lab2') : 100, ('mar', 'lab2') : 100, ('abr', 'lab2') : 100, ('may', 'lab2') : 100,
        ('ene', 'lab3') : 100, ('feb', 'lab3') : 100, ('mar', 'lab3') : 100, ('abr', 'lab3') : 100, ('may', 'lab3') : 100
        },
    'vit' : {
        ('ene', 'lab1') : 100, ('feb', 'lab1') : 100, ('mar', 'lab1') : 100, ('abr', 'lab1') : 100, ('may', 'lab1') : 100,
        ('ene', 'lab2') : 100, ('feb', 'lab2') : 100, ('mar', 'lab2') : 100, ('abr', 'lab2') : 100, ('may', 'lab2') : 100,
        ('ene', 'lab3') : 100, ('feb', 'lab3') : 100, ('mar', 'lab3') : 100, ('abr', 'lab3') : 100, ('may', 'lab3') : 100
        }
}

#=====PARAMETROS CONSTANTES=====

#=====VARIABLES DE DECISION=====
varA = {}
varG = {}
varS = {}
varM = {}
varQ = {}
varSn = {}
varSd = {}

for periodo in t_periodo:
    for personal in i_personal:
        for contrato in c_contratos:
            varA[personal, contrato, periodo] = m.addVar(vtype=GRB.INTEGER, name="varA_{}_{}_{}".format(personal, contrato, periodo))
    for insumo in n_insumos:
        varS[insumo, periodo] = m.addVar(vtype=GRB.INTEGER, name="varS_{}_{}".format(insumo, periodo))
        for bodega in v_bodegas:
            varG[insumo, bodega, periodo] = m.addVar(vtype=GRB.INTEGER, name="varG_{}_{}_{}".format(insumo, bodega, periodo))
            varSn[insumo, bodega, periodo] = m.addVar(lb=0, ub=1, vtype=GRB.BINARY, name="varSn_{}_{}_{}".format(insumo, bodega, periodo))
    for medicamento in d_medicamentos:
        varQ[medicamento, periodo] = m.addVar(vtype=GRB.INTEGER, name="varQ_{}_{}".format(medicamento, periodo))
        for laboratorio in l_laboratorios:
            varM[medicamento, laboratorio, periodo] = m.addVar(vtype=GRB.INTEGER, name="varM_{}_{}_{}".format(medicamento, laboratorio, periodo))
            varSd[medicamento, laboratorio, periodo] = m.addVar(lb=0, ub=1, vtype=GRB.BINARY, name="varSd_{}_{}_{}".format(medicamento, laboratorio, periodo))

m.update()

#=====RESTRICCIONES=====

#A: Presupuesto funcionarios:
for periodo in t_periodo:
    for personal in i_personal:
        for rubro in f_rubros:
            m.addConstr(quicksum(personal_H[personal][(periodo, contrato)] * varA[personal, contrato, periodo] for contrato in c_contratos) \
                <= personal_A[rubro][periodo], 'presuFunc_{}_{}_{}'.format(personal, rubro, periodo))

#C: Minimo de funcionarios:
for periodo in t_periodo:
    for personal in i_personal:
        for rubro in f_rubros:
            m.addConstr(personal_V[rubro][periodo] <= quicksum(varA[personal, contrato, periodo] \
                for contrato in c_contratos), 'minFunRub_{}_{}_{}'.format(personal, rubro, periodo))

#D: Presupuesto insumos:
for periodo in t_periodo:
    m.addConstr(quicksum(insumos_Ii[insumo][periodo] * insumos_Ai[insumo][periodo] + quicksum( \
        varG[insumo, bodega, periodo] * insumos_E[insumo][(periodo, bodega)] for bodega in v_bodegas) \
        for insumo in n_insumos) <= insumos_L[periodo], 'presuInsu_{}'.format(periodo))

#E: Minimo insumos:
for periodo in t_periodo:
    for insumo in n_insumos:
        m.addConstr(insumos_G[insumo][periodo] <= quicksum(varG[insumo, bodega, periodo] \
            for bogeda in v_bodegas), 'minimInsu_{}_{}'.format(insumo, periodo))

#F: Binaria insumos:
for periodo in t_periodo:
    for insumo in n_insumos:
        for bodega in v_bodegas:
            m.addConstr(varG[insumo, bodega, periodo] <= GRB.INFINITY * varSn[insumo, bodega, periodo], \
                'binarInsu_{}_{}_{}'.format(periodo, insumo, bodega))

#G: Presupuesto medicamentos:
for periodo in t_periodo:
    m.addConstr(quicksum(medicamentos_Im[medicamento][periodo] * medicamentos_Am[medicamento][periodo] + quicksum( \
        varM[medicamento, laboratorio, periodo] * medicamentos_Q[medicamento][(periodo, laboratorio)] \
        for laboratorio in l_laboratorios) for medicamento in d_medicamentos) <= medicamentos_Z[periodo], \
        'presMedic_{}'.format(periodo))

#H: Minimo medicamentos:
for periodo in t_periodo:
    for medicamento in d_medicamentos:
        m.addConstr(medicamentos_O[medicamento][periodo] <= quicksum(varM[medicamento, laboratorio, periodo] \
            for laboratorio in l_laboratorios), 'minimInsu_{}_{}'.format(medicamento, periodo))

#F: Binaria medicamentos:
for periodo in t_periodo:
    for medicamento in d_medicamentos:
        for laboratorio in l_laboratorios:
            m.addConstr(varM[medicamento, laboratorio, periodo] <= GRB.INFINITY * varSd[medicamento, laboratorio, periodo], \
                'binarInsu_{}_{}_{}'.format(periodo, insumo, bodega))

#J-K: Inv medicamentos:
for periodo_index, periodo in enumerate(t_periodo):
    for medicamento in d_medicamentos:
        if periodo_index == 0:
            m.addConstr(medicamentos_Im[medicamento][periodo] + quicksum(varM[medicamento, laboratorio, t_periodo[periodo_index + 1]] for laboratorio in l_laboratorios) \
                == varQ[medicamento, t_periodo[periodo_index + 1]] + medicamentos_Im[medicamento][t_periodo[periodo_index + 1]], 'invMedIni_{}_{}'.format(medicamento, periodo))
        else:
            m.addConstr(medicamentos_Im[medicamento][t_periodo[periodo_index - 1]] + quicksum(varM[medicamento, laboratorio, periodo] for laboratorio in l_laboratorios) \
                == varQ[medicamento, periodo] + medicamentos_Im[medicamento][periodo], 'invMedicm_{}_{}'.format(medicamento, periodo))

#L-M: Inv insumos:
for periodo_index, periodo in enumerate(t_periodo):
    for insumo in n_insumos:
        if periodo_index == 0:
            m.addConstr(insumos_Ii[insumo][periodo] + quicksum(varG[insumo, bodega, t_periodo[periodo_index + 1]] for bodega in v_bodegas) \
                == varS[insumo, t_periodo[periodo_index + 1]] + insumos_Ii[insumo][t_periodo[periodo_index + 1]], 'invInsIni_{}_{}'.format(insumo, periodo))
        else:
            m.addConstr(insumos_Ii[insumo][t_periodo[periodo_index - 1]] + quicksum(varG[insumo, bodega, periodo] for bodega in v_bodegas) \
                == varS[insumo, periodo] + insumos_Ii[insumo][periodo], 'invInsumo_{}_{}'.format(insumo, periodo))

#=====FUNCION OBJETIVO=====
sum_personal = quicksum(quicksum(personal_H[personal][(periodo, contrato)] * varA[personal, contrato, periodo] \
                for contrato in c_contratos) for rubro in f_rubros)
sum_insumos = quicksum(insumos_Ai[insumo][periodo] * insumos_Ii[insumo][periodo] + quicksum( \
                insumos_E[insumo][(periodo, bodega)] * varG[insumo, bodega, periodo] + \
                insumos_CFi[insumo][(periodo, bodega)] * varSn[insumo, bodega, periodo] \
                for bodega in v_bodegas) for insumo in n_insumos)
sum_medicamentos = quicksum(medicamentos_Am[medicamento][periodo] * medicamentos_Im[medicamento][periodo] + quicksum( \
                    medicamentos_Q[medicamento][(periodo, laboratorio)] * varM[medicamento, laboratorio, periodo] + \
                    medicamentos_CFm[medicamento][(periodo, laboratorio)] * varSd[medicamento, laboratorio, periodo] \
                    for laboratorio in l_laboratorios) for medicamento in d_medicamentos)

objetivo = quicksum(sum_personal + sum_insumos + sum_medicamentos for periodo in t_periodo)

m.setObjective(objetivo, GRB.MINIMIZE)

#OPTIMIZACION
m.optimize()

m.printAttr("X")
print("\n-------------\n")
for constr in m.getConstrs():
    print(constr, constr.getAttr("slack"))


import pefile as pe
import os
import numpy as np
import pandas as pd

benign_l = os.listdir("malware_dataset/benignware") #label : 0
malware_l = os.listdir("malware_dataset/malware") #label : 1
test_l = os.listdir("malware_dataset/testdata")
benign_path = "malware_dataset/benignware/"
malware_path = "malware_dataset/malware/"
test_path = "malware_dataset/testdata/"

no_of_sections = []
no_of_symbols = []
timestamp = []
characteristics = []
addr_of_entry_pt = []
size_of_init_data = []
size_of_uninit_data = []
checksum = []
dll_char = []
has_relocs_ = []
verify_checksum_ = []
is_dll_ = []
magic_value = []
directory_entry_imports_len = []
imports_len = []
imports_len = []
label = []

def create_df(directory,path):

    print(directory)
    count = 0
    for i in directory:
        print(count)
        count = count + 1

        try:
            filename = path+str(i)
#            print(filename)
            p = pe.PE(name=filename)
            print("Hash Value : ",p.get_imphash())

            print("e_magic_value : ", hex(p.DOS_HEADER.e_magic))
            magic = p.DOS_HEADER.e_magic
            magic_value.append(magic)

            print("signature : ", hex(p.NT_HEADERS.Signature))

            for section in p.sections:
            #    print(section.Name.decode('utf-8'))
#                print("\t Virtual Address :", section.VirtualAddress)
#               print("\t Misc_Physical Address : ", section.Misc_PhysicalAddress)
#               print("\t Pointer to raw data : ", section.PointerToRawData)
#               print("\t Pointer to relocations : ", section.PointerToRelocations)
#               print("\t Pointer to line numbers : ",section.PointerToLinenumbers)
#               print("\t Number of Relocations", section.NumberOfLinenumbers)
                pass

            has_relocs_.append(p.has_relocs())
            verify_checksum_.append(p.verify_checksum())
            is_dll_.append(p.is_dll())

            no_of_sections.append(p.FILE_HEADER.NumberOfSections)

            no_of_symbols.append(p.FILE_HEADER.NumberOfSymbols)

            timestamp.append(p.FILE_HEADER.TimeDateStamp)

            characteristics.append(p.FILE_HEADER.Characteristics)

            addr_of_entry_pt.append(p.OPTIONAL_HEADER.AddressOfEntryPoint)

            size_of_init_data.append(p.OPTIONAL_HEADER.SizeOfInitializedData)

            size_of_uninit_data.append(p.OPTIONAL_HEADER.SizeOfUninitializedData)

            checksum.append(p.OPTIONAL_HEADER.DllCharacteristics)

            #directory_entry_imports_len.append(len(p.DIRECTORY_ENTRY_IMPORT))

            #imports = [x.imports for x in p.DIRECTORY_ENTRY_IMPORT]
            #imports_len.append(len(imports))

#            label.append(1)
#            label.append(0)
        except OSError as e:
            pass
        except pe.PEFormatError as e:
            pass

#create_df(malware_l,malware_path)
#create_df(benign_l,benign_path)
create_df(test_l,test_path)

df = pd.DataFrame()
df['Magic Number'] = magic_value
df['Number of Sections'] = no_of_sections
df['number of symbols'] = no_of_symbols
df['has relocs'] = has_relocs_
df['is dll'] = is_dll_
df['verify checksum'] = verify_checksum_
df['time stamp'] = timestamp
df['characteristics'] = characteristics
df['address of entry point'] = addr_of_entry_pt
df['size of init data'] = size_of_init_data
df['size of uninit data'] = size_of_uninit_data
df['checksum'] = checksum
#df['label'] = label
df.to_csv(r"malware_dataset/benignware_output/data_frame_benign.csv")
#df.to_csv(r"malware_dataset/benignware_output/data_frame_mal.csv")
df.to_csv(r"malware_dataset/data_frame_test.csv")


import time
import torch
import numpy as np
import random
from longformer.sliding_chunks import sliding_chunks_matmul_pv, sliding_chunks_matmul_qk

def same_storage(x, y):
    '''Tests if two tensors share the same underlying storage (for memory optimizations)'''
    return x.storage().data_ptr() == y.storage().data_ptr()

if __name__ == '__main__':
    np.random.seed(3)
    random.seed(3)
    torch.manual_seed(3)
    torch.cuda.manual_seed(3)
    torch.cuda.manual_seed_all(3)

    torch.set_printoptions(sci_mode=False)
    N = 4096  # * 16
    M = 64  # hidden size
    W = 256  # one sided. Actual window size = 2w+1
    B = 3
    D = 1  # no dilation
    H = 12  # number of heads
    autoregressive = False  # not autoregressive
    device = 'cuda'
    dtype = torch.float32

    query = torch.randn(B * N * H * M, requires_grad=True, device=device, dtype=dtype).view(B, N, H, M)
    key = torch.randn(B * N * H * M, requires_grad=True, device=device, dtype=dtype).flip(dims=(0,)).view(B, N, H, M)
    value = torch.randn(B * N * H * M, requires_grad=True, device=device, dtype=dtype).view(B, N, H, M)

    # query = query.half()  # uncomment to profile the fp16 performance
    # key = key.half()
    # value = value.half()
    attention = sliding_chunks_matmul_qk(query, key, W, float('-inf'))
    attention_probs = torch.nn.functional.softmax(attention, dim=-1)
    context2 = sliding_chunks_matmul_pv(attention_probs, value, W)


#!/usr/bin/python3

from bs4 import BeautifulSoup
from bs4 import BeautifulSoup
import requests as req

resp = req.get("https://jetlend.ru")
soup = BeautifulSoup(resp.text, 'lxml')

count_teg = 0
count_attr = 0
# count_attr2 = 0
for child in soup.recursiveChildGenerator():
    # if child.attrs:
    #     count_attr2 += len(child.attrs)
    if child.name:
        count_teg += 1
        count_attr += len(child.attrs)
        print(child.name)

print(f'Если не считать (<!DOCTYPE>, <!--...-->,...), количество тэгов:{count_teg}\nКоличество атрибутов: {count_attr} и {count_attr2}')


import json
from flask import jsonify, request
from herovii.libs.bpbase import ApiBlueprint, auth
from herovii.models.org.feedback import Feedback
from herovii.models.base import db
from herovii.models.org.lowprice_feedback import LowPriceFeedback
from herovii.validator.forms import FeedbackForm, LowPriceFeedbackForm

__author__ = 'shaolei'

api = ApiBlueprint('org')

@api.route('/feedback/advice', methods=['POST'])
@auth.login_required
def create_feedback():
    form = FeedbackForm.create_api_form()
    with db.auto_commit():
        feedback = Feedback()
        feedback.organization_id = form.organization_id.data
        feedback.qq = form.qq.data
        feedback.content = form.content.data
        db.session.add(feedback)
    return jsonify(feedback), 201

@api.route('/feedback/lowprice', methods=['POST'])
#@auth.login_required
def create_lowprice_feedback():
    form = LowPriceFeedbackForm.create_api_form()
    with db.auto_commit():
        lowprice_feedback = LowPriceFeedback()
        lowprice_feedback.organization_id = form.organization_id.data
        lowprice_feedback.organization_name = form.organization_name.data
        lowprice_feedback.course_name = form.course_name.data
        lowprice_feedback.name = form.name.data
        lowprice_feedback.phone_num = form.phone_num.data
        db.session.add(lowprice_feedback)
    return jsonify(lowprice_feedback), 201


from django.urls.conf import path
from .views import 세일_지우기, 세일_업데이트, 세일_입력, 세일목록, 세일상세

app_name = '세일목록1' # namespace과 이름 지정이 달라도 상관 없음

urlpatterns = [
    path('', 세일목록, name='목록'),
    path('<int:pk>/', 세일상세, name='상세'),
    path('make/', 세일_입력, name='생성'),
    path('<int:pk>/update/', 세일_업데이트, name='업뎃'),
    path('<int:pk>/delete/', 세일_지우기, name='지우기'),
]


"""
Module works with Twitter api and creates a map with friends' locations.
"""
import requests
import certifi

import ssl

import geopy.geocoders

from geopy.geocoders import Nominatim

ctx = ssl.create_default_context(cafile=certifi.where())
geopy.geocoders.options.default_ssl_context = ctx
geolocator = Nominatim(user_agent="twitter friends", scheme='http')
from geopy.exc import GeocoderUnavailable
from geopy.exc import GeocoderTimedOut
from flask import Flask, render_template, request

import folium
app = Flask(__name__)

def get_info(bearer_token, screen_name):
  """
  Sends request to Twitter with the help of bearer token.
  Returns json with the information about first 50 friends of user with given username.
  """
  base_url = 'https://api.twitter.com/'
  search_headers = {
    'Authorization': 'Bearer {}'.format(bearer_token)
    }
  search_params = {
    'screen_name': '{}'.format(screen_name),
    'count': 50
  }
  search_url = '{}1.1/friends/list.json'.format(base_url)

  response = requests.get(search_url, headers=search_headers, params=search_params)
  json_response = response.json()
  return json_response

def get_friends_coordinates(json_response):
  """
  Function gets a dictionary and returns a list
  of tuples with each friend's coordinates.
  """
  friends_list = []
  for user in json_response['users']:
    location = user['location']
    nickname = user['screen_name']
    friends_list.append([nickname, location])

  new_friends_list = []
  for friend in friends_list:
    try:
      location = geolocator.geocode(friend[1])
      new_friends_list.append([friend[0], location.latitude, location.longitude])
    except AttributeError:
      continue
    except GeocoderTimedOut:
      continue
    except GeocoderUnavailable:
      continue
  return new_friends_list

def create_map(new_friends_list):
  """
  Function creates an html map with markers as friends' locations.
  """
  mapp = folium.Map(tiles='CartoDB dark_matter')
  folium.TileLayer('OpenStreetMap').add_to(mapp)
  folium.TileLayer('CartoDB positron').add_to(mapp)
  folium.TileLayer('Stamen Terrain').add_to(mapp)
  fig = folium.FeatureGroup(name = 'Twitter Friends')
  for friend in new_friends_list:
    fig.add_child(folium.Marker(location=[friend[1], friend[2]],
                                popup=friend[0],
                                icon=folium.Icon(color='blue', icon='user', prefix='fa')))

  mapp.add_child(fig)
  mapp.add_child(folium.LayerControl())
  mapp.save('templates/Twitter_Friends.html')

@app.route("/")
def index():
  """
  Function creates the main page of the app.
  """
  return render_template("index.html")

@app.route("/map", methods=["POST"])
def final_map():
  """
  Function creates a final map about friends.
  """
  try:
    nickname = request.form.get("screen_name")
    request_token = request.form.get("bearer_token")
    if not nickname or not request_token:
      return render_template("failure.html")
    json_response = get_info(request_token, nickname)
    create_map(get_friends_coordinates(json_response))

    return render_template("Twitter_Friends.html")
  except KeyError:
    return render_template("failure.html")

if __name__ == "__main__":
  app.run(debug=False)


import tqdm as tqdm
from xlingcorrelation import Segmented
from collections import defaultdict, Counter

path = '/Users/gladysbaudet//Desktop/PFE/'
cds = 'CDS/'
results = 'Results/'
# corpora = ['french/Lyon/', 'danish/Plunkett/', 'swedish/Lund/', 'spanish/OreaPine/']
corpora = ['french/lyon-50k/', 'swedish/lund-50k/']
# algos = ['ag/', 'dibs/', 'puddle/', 'tp/relativeforward/', 'tp/absoluteforward/', 'tp/relativebackward/', 'tp/absolutebackward/', 'baseline0/', 'baseline1/']
algos = ['baseline0/', 'baseline1/']
units = ['syllable/', 'phoneme/']

# for corpus in tqdm.tqdm(corpora) :
#     ortho=open(path+cds+corpus+"ortholines.txt",'r').read()
#     seg_ortho=Counter(ortho.lower().split())
#     f = open(path+results+corpus+"gold_freq_words.csv", 'w')
#     for double in seg_ortho.most_common() :
#         f.write(str(double[1])+" "+ str(double[0])+'\n')
#     f.close()
#
# ortho=open(path+cds+"english/Brent/full_corpus/"+"ortholines.txt",'r').read()
# seg_ortho=Counter(ortho.lower().split())
# f = open(path+results+"English/Brent/"+"gold_freq_words.csv", 'w')
# for double in seg_ortho.most_common() :
#     f.write(str(double[1])+" "+ str(double[0])+'\n')
# f.close()

ortho=open(path+cds+"english/Brent/50K0/"+"ortholines.txt",'r').read()
seg_ortho=Counter(ortho.lower().split())
f = open(path+results+"English/Brent/50k/"+"gold_freq_words.csv", 'w')
for double in seg_ortho.most_common() :
    f.write(str(double[1])+" "+ str(double[0])+'\n')
f.close()

# for corpus in tqdm.tqdm(corpora) :
#     for unit in units :
#         listsegfull = [Segmented(path+results+corpus+algo+unit+'segmented.txt', \
#         path+cds+corpus+'gold.txt', path+cds+corpus+'ortholines.txt', \
#         unit, algo, cds) for algo in algos]
#
#         for seg in listsegfull :
#             seg.write_freq_words(path+results+corpus+seg._algo+seg._unit+"freq_words.csv")

# for unit in units :
#     listsegfull = [Segmented(path+results+"English/Brent/50K0/"+algo+unit+'segmented.txt', \
#     path+"CDS/"+"english/Brent/50K0/"+'gold.txt', path+"CDS/"+"english/Brent/50K0/"+'ortholines.txt', \
#     unit, algo, cds) for algo in algos]
#
#     for seg in listsegfull :
#         seg.write_freq_words(path+results+"English/Brent/50K0/"+seg._algo+seg._unit+"freq-words.txt")


from datetime import datetime, timedelta

# returns the earliest following date, based on a day (1=monday, 7=sunday)
# offset of 1 day, because saving 0 is hard for Odoo
def _get_next_date_for_day(dt, day):
    #day = 1 (monday), dt.weekday() = 1 (tuesday), days ahead = -1, return 6
    days_ahead = day - dt.weekday() - 1 # difference in count weekday days ahead = 0
    if days_ahead < 1: # Target day already happened this week
        days_ahead += 7 # days ahead = 8
    return dt + timedelta(days_ahead)

# same as _get_next_date_for_day, but always returns a date in the future
def _get_future_next_date_for_day(olddt, day): #olddt = datetime.datetime(2015, 11, 23, 13, 32, 47), day = 4
    now = datetime.utcnow()
    if now >= olddt:
        while(now >= olddt):
            olddt = _get_next_date_for_day(olddt, day)
        return olddt
    return _get_next_date_for_day(olddt, day)


from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
from .models import Bookings

from datetime import datetime
from json import loads

@csrf_exempt
def get_bookings_overview(request):
    data = loads(request.body)
    room_num_with_self_booking_arr = []
    MatchingBookings = Bookings.objects.filter(net_id=data["NetID"])
    for Booking in MatchingBookings:
        room_num_with_self_booking_arr.append(Booking.room_num)
    return JsonResponse({
        "RoomNumsWithSelfBookings": room_num_with_self_booking_arr,
        "BookingsLeft": 2 - len(MatchingBookings)
    })

@csrf_exempt
def get_room_bookings(request):
    data = loads(request.body)
    time_arr = []
    for Booking in Bookings.objects.filter(room_num=data["RoomNum"]):
        time_arr.append(Booking.start_time)
    return JsonResponse({"BookingTimeArr": time_arr})

@csrf_exempt
def create_room_bookings(request):
    data = loads(request.body)
    if data["Cancel"]:
        Bookings.objects.filter(
            net_id=data["NetID"],
            room_num=data["RoomNum"],
            start_time=data["StartTime"]
        ).delete()
    else:
        MatchingBookings = Bookings.objects.filter(net_id=data["NetID"])

        if len(MatchingBookings) < 2:
            member = Bookings(
                date=datetime.today(),
                net_id=data["NetID"],
                room_num=data["RoomNum"],
                start_time=data["StartTime"]
            )
            member.save()
        else:
            return JsonResponse({"Successful": False})

    return JsonResponse({"Successful": True})


import json
from flask import render_template
from flask_login import login_required
from . import main
from .. import mqtt, socketio
from ..models import BaseControl, Panel, topic_control_map, MQTTMessage, \
    create_mqttmessage

@main.route('/')
@login_required
def index():
    panels = Panel.objects
    return render_template('index.html', panels=panels)

@mqtt.on_message()
def handle_messages(client, userdata, message):

    MQTTMessage.remove_old()
    mqtt_msg = create_mqttmessage(client, userdata, message,
                                  MQTTMessage.DIRECTION_IN)

    mqtt_msg.save()

    control_ids = topic_control_map.get(message.topic)
    if control_ids is None:
        return

    controls = BaseControl.objects(id__in=control_ids)
    for control in controls:
        control.handle_mqtt_message(client, userdata, message)

@socketio.on('control clicked')
def handle_control_clicked(json_str):
    data = json.loads(json_str)
    control = BaseControl.objects(id=data['control_id']).first()

    if control is not None:
        control.handle_event(data)


#!/usr/bin/env python
import logging

import numpy as np
import torch
import torch.nn as nn
from torchvision.models.segmentation import deeplabv3_resnet101

class NoiseModule:
    def __init__(self, cfg):
        """
        Noise Module implements the noise mdoel from the paper.
        It maintains a variance for each pixel of each image.
        sd = sqrt(var), we store the variances for each of the prior distributions
        Sampling is done using var * N(0, 1)
        It is responsible for sampling from the noise distribution, loss calculation and updating the variance.
        Args
        ---
        cfg: (yacs.CfgNode) base configuration for the experiment.
        """
        super(NoiseModule, self).__init__()
        self.logger = logging.getLogger(str(cfg.SYSTEM.EXP_NAME) + ".noise_module")
        self.num_imgs = cfg.SOLVER.NUM_IMG
        self.num_maps = cfg.SOLVER.NUM_MAPS
        self.h, self.w = cfg.SOLVER.IMG_SIZE
        self.num_pixels = self.h * self.w
        self.alpha = cfg.NOISE.ALPHA
        self.device = cfg.SYSTEM.DEVICE
        # prior variance of the noise distribution, Initalized with zeros(!section 3.2 last para)
        self.noise_variance = torch.zeros(self.num_imgs * self.num_pixels)
        # emperical variance, observed variance between prediction and unsup labels
        self.emp_var = torch.zeros(self.num_imgs * self.num_pixels)

    def get_index(self, arr=None, img_idx=None):
        """
        Function for fetching indexes of pixels for img_idx
        Args
        ---
        img_idx: (int) index of image
        arr: (list) value array to fetch values from
        Returns
        ---
        values, idxs
        values: arr[idxs]
        idxs: starting and ending of pixels for the image
        """
        if arr is None:
            arr = self.noise_variance
        idx = img_idx * self.num_pixels
        return arr[idx:idx+self.num_pixels], np.arange(idx, idx+self.num_pixels)

    def get_index_multiple(self, arr=None, img_idxs=None):
        """
        Function for fetching indexes of pixels for img_idx
        Args
        ---
        img_idx: (list[int]) indexs of image
        arr: (list) value array to fetch values from
        Returns
        --- values: np.array, (len(img_idxs), num_pixels) idxs: starting and ending of pixels for the image
        """
        if arr is None:
            arr = self.noise_variance
        noise = np.zeros((len(img_idxs), self.num_pixels), dtype=np.float)
        noise_idx = np.zeros((len(img_idxs), self.num_pixels), dtype=np.float)
        for key, img_idx in enumerate(img_idxs):
            idx = img_idx * self.num_pixels
            noise[key] = arr[idx:idx+self.num_pixels]
            noise_idx[key] = np.arange(idx, idx+self.num_pixels)
        return noise, noise_idx

    def loss_fast(self, var1, var2):
        """
        Computes the loss using Eq 6
        Args
        ----
        var1: variance of q distribution, prior variance
        var2: variance of p distribution, predictive variance
        Returns
        ---
        noise loss:  float noise loss per image Note! different from paper which uses sum of noise
        """
        noise_loss = 0
        for idx in range(var1.shape[0]):
            covar1 = var1[idx].to(self.device) + 1e-6
            covar2 = var2[idx].to(self.device) + 1e-6
            ratio = 1. * (covar1 / covar2)
            loss = -0.5 * (torch.log(ratio) - ratio + 1).to(self.device)
            loss = abs(loss)
            # See Eq 6 from paper and https://github.com/pytorch/pytorch/blob/master/torch/distributions/kl.py#L394
            noise_loss += torch.sum(loss) / var1.shape[1]
        return noise_loss / var1.shape[0]

    def sample_noise(self, idxs):
        """
        Samples noise from Normal distribution with prior variance.
        Args
        ---
        idxs: List[int]
        sample from standard normal and transform using var for idxs
        Returns
        ---
        samples: np.array, noise samples of shape (len(idxs), NUM_MAPS, 128, 128)
        """
        samples = torch.zeros(len(idxs), self.num_maps, self.h, self.w)
        for idx, img_idx in enumerate(idxs):
            var, var_idx = self.get_index(self.noise_variance, img_idx)
            var = var.view(self.h, self.w).to(self.device)
            for map_idx in range(self.num_maps):
                # elementwise mutliplication with prior variance for each image of samples from N(0, 1)
                sample = var * torch.zeros(self.h, self.w).normal_().to(self.device)
                samples[idx][map_idx] = sample
        return samples

    def update(self):
        """
        Updates the prior variance for each pixel of each image by emp variance
        !Note: Emp variance needs to be updated before calling this.
        """
        print("Updating Noise")
        print("----------------------------------------")
        # import ipdb; ipdb.set_trace()
        # See equation 7, !Note: we have saved the variances and not sd, hence no need for squaring
        self.noise_variance = self.noise_variance + self.alpha * (self.emp_var - self.noise_variance)
        print(f'Max: {torch.max(self.noise_variance)}, Min :{torch.min(self.noise_variance)}')
        self.logger.info(f"Noise Variance: {self.noise_variance}")
        print("----------------------------------------")

def BaseModule(cfg):
    model = deeplabv3_resnet101(pretrained=True)
    model.classifier[4] = nn.Conv2d(256, 1, kernel_size=(1, 1), stride=(1, 1))
    model.aux_classifier[4] = nn.Conv2d(256, 1, kernel_size=(1, 1), stride=(1, 1))
    return model


import sys
sys.dont_write_bytecode = True

import os
import shutil
import time
import stat
import json
import math
import hashlib
import pdb

import gradio as gr
import modules.extras
import modules.ui
import modules.scripts as scripts
import modules.prompt_parser as prompt_parser
import pprint
import piexif
import piexif.helper

from functools import partial
from PIL import Image
from copy import copy
from modules.shared import opts, cmd_opts
from modules.processing import process_images, Processed
from modules.images import FilenameGenerator
from modules import shared, images, scripts, script_callbacks
from pathlib import Path
from typing import List, Tuple

##########################################################################################

PROMPTBOOK_VERSION = "1.0"

refresh_symbol = '\U0001f504'  # 🔄

def sanitize_prompt(prompt):
    return prompt.strip().strip(',').strip()

class Recipe:
    def __init__(self, parts):
        self.parts = parts

    def serialize(self):
        return {
            "version": PROMPTBOOK_VERSION,
            "parts": [part.serialize() if part else None for part in self.parts]
        }

    def deserialize(data):
        parts = [RecipePart.deserialize(part_json) if part_json else None for part_json in data["parts"]]

        return Recipe(parts)

    def to_json(self):
        return json.dumps(self.serialize())

    def from_json(jsdata):
        data = json.loads(jsdata)
        assert isinstance(data, dict)
        return Recipe.deserialize(data)

    def from_json_array(jsdata):
        data = json.loads(jsdata)
        assert isinstance(data, list)
        return [Recipe.deserialize(entry) for entry in data]

    def evaluate(self, p=None, existing_prompt_action=None):
        prompt_parts = []
        negative_prompt_parts = []

        for part in self.parts:
            if part is None:
                continue

            prompt = part.prompt

            positive = apply_prompt_strength(prompt.positive, part.strength)
            negative = apply_prompt_strength(prompt.negative, part.strength)

            if positive.strip():
                prompt_parts.append(positive)
            if negative.strip():
                negative_prompt_parts.append(negative)

        if p:
            if p.prompt.strip():
                if existing_prompt_action == "Append":
                    prompt_parts.append(p.prompt)
                elif existing_prompt_action == "Prepend":
                    prompt_parts = [p.prompt] + prompt_parts

            if p.negative_prompt.strip():
                if existing_prompt_action == "Append":
                    negative_prompt_parts.append(p.negative_prompt)
                elif existing_prompt_action == "Prepend":
                    negative_prompt_parts = [p.negative_prompt] + negative_prompt_parts

        return join_prompts(prompt_parts), join_prompts(negative_prompt_parts)

class RecipePart:
    def __init__(self, prompt, strength):
        self.prompt: Prompt = prompt
        self.strength = strength

    def serialize(self):
        return {
            "prompt": self.prompt.serialize(slim=True),
            "strength": self.strength
        }

    def deserialize(data):
        prompt = Prompt.deserialize(data["prompt"])
        strength = data["strength"]

        return RecipePart(prompt, strength)

    def to_json(self):
        return json.dumps(self.serialize())

    def from_json(jsdata):
        data = json.loads(jsdata)
        return Recipe.deserialize(data)

class Prompt:
    def __init__(self, name, description, positive, negative, tags=[], sha256=None):
        self.name = name
        self.description = description
        self.positive = sanitize_prompt(positive)
        self.negative = sanitize_prompt(negative)
        self.tags = tags

        if name == "(Custom)":
            self.sha256 = ""
        elif sha256 is None:
            m = hashlib.sha256()
            m.update(self.positive.encode())
            m.update(self.negative.encode())
            self.sha256 = m.hexdigest()
        else:
            self.sha256 = sha256

    def load_from_file(png_filepath):
        image = Image.open(png_filepath)
        return Prompt.load_from_image(image)

    def load_from_image(image):
        _, info = images.read_info_from_image(image)
        return Prompt.from_json(info["promptbook_prompt"])

    def serialize(self, slim=False):
        data = {
            "name": self.name,
            "description": self.description,
            "positive": self.positive,
            "negative": self.negative,
            "sha256": self.sha256,
        }

        if not slim:
            data["version"] = PROMPTBOOK_VERSION
            data["tags"] = self.tags

        return data

    def deserialize(data):
        name = data["name"]
        description = data["description"]
        positive = data["positive"]
        negative = data["negative"]
        tags = data.get("tags", [])
        sha256 = data.get("sha256", None)

        return Prompt(name, description, positive, negative, tags, sha256)

    def to_json(self):
        return json.dumps(self.serialize())

    def from_json(jsdata):
        data = json.loads(jsdata)
        return Prompt.deserialize(data)

####################################################################################################

SPECIAL_PROMPTS = ["(None)", "(Custom)"]

def get_prompt_path(prompt_name):
    return os.path.join(opts.promptbook_prompts_path, f"{prompt_name}.png")

class UiPromptMerge:
    def __init__(self, rows):
        self.rows = rows

    def prompt_choices_outputs(self):
        return [row.dropdown_prompt for row in self.rows]

    def add_prompt_outputs(self):
        return list(sum([(row.dropdown_prompt, row.slider_strength) for row in self.rows], ()))

    def select_button_outputs(self):
        return [row.select_button for row in self.rows]

    def output_prompt_outputs(self):
        return list(sum([(row.dropdown_prompt, row.slider_strength, row.custom_prompt, row.custom_negative_prompt) for row in self.rows], ()))

    @staticmethod
    def load_recipe(recipe_json):
        recipe = Recipe.from_json(recipe_json)
        results = ["(None)", 1.0, "", ""] * int(opts.promptbook_merge_max_rows)

        for index, part in enumerate(recipe.parts):
            if part is None:
                continue
            elif part.prompt.name == "(Custom)":
                results[index * 4] = part.prompt.name
                results[index * 4 + 1] = part.strength
                results[index * 4 + 2] = part.prompt.positive
                results[index * 4 + 3] = part.prompt.negative
            else:
                prompt_path = get_prompt_path(part.prompt.name)
                if os.path.isfile(prompt_path):
                    loaded = Prompt.load_from_file(prompt_path)
                    if loaded.sha256 == part.prompt.sha256:
                        results[index * 4] = part.prompt.name
                        results[index * 4 + 1] = part.strength

        return results

    @staticmethod
    def output_recipe(*rest):
        recipe = UiPromptMerge.make_recipe(rest)
        return recipe.to_json()

    @staticmethod
    def clear_recipe():
        return ["(None)", 1.0, "", ""] * int(opts.promptbook_merge_max_rows)

    @staticmethod
    def evaluate_recipe(*rest):
        recipe = UiPromptMerge.make_recipe(rest)
        prompt, negative_prompt = recipe.evaluate()
        return f"{prompt}\nNegative prompt: {negative_prompt}".strip()

    @staticmethod
    def make_recipe(allvars):
        pairwise = list(zip(allvars[::4], allvars[1::4], allvars[2::4], allvars[3::4]))
        parts = []
        for pair in pairwise:
            prompt_name, strength, custom_prompt, custom_negative_prompt = pair
            if prompt_name != "" and prompt_name != "(None)":
                parts.append(UiPromptMergeRow.make_recipe_part(prompt_name, strength, custom_prompt, custom_negative_prompt))
            else:
                parts.append(None)

        while parts and parts[-1] is None:
            parts.pop()

        return Recipe(parts)

class UiPromptMergeRow:
    def __init__(self, index, row, delete_button, select_button, image_preview, dropdown_prompt, slider_strength, custom_prompt, custom_negative_prompt):
        self.index = index
        self.row = row
        self.delete_button = delete_button
        self.select_button = select_button
        self.image_preview = image_preview
        self.dropdown_prompt = dropdown_prompt
        self.slider_strength = slider_strength
        self.custom_prompt = custom_prompt
        self.custom_negative_prompt = custom_negative_prompt

    @staticmethod
    def make_recipe_part(prompt_name, strength, custom_prompt, custom_negative_prompt):
        if prompt_name == "(Custom)":
            prompt = Prompt("(Custom)", "", custom_prompt, custom_negative_prompt)
        else:
            prompt = Prompt.load_from_file(get_prompt_path(prompt_name))
        return RecipePart(prompt, strength)

def update_row(prompt_name):
    image_file = os.path.join(opts.promptbook_prompts_path, f"{prompt_name}.png")
    if prompt_name in SPECIAL_PROMPTS or not os.path.isfile(image_file):
        image_file = None

    is_custom = prompt_name == "(Custom)"
    return image_file, gr.Row.update(visible=is_custom)

def ui_prompt_merge():
    all_prompt_choices = SPECIAL_PROMPTS
    all_rows = []

    with gr.Row():
        with gr.Column():
            for i in range(0, int(opts.promptbook_merge_max_rows)):
                with gr.Row():
                    with gr.Column():
                        with gr.Row(variant="panel") as row:
                            with gr.Column(scale=1):
                                with gr.Row():
                                    delete_button = gr.Button("❌", elem_id=f"promptbook_prompt_delete_button_{i}")
                                    select_button = gr.Button(f"{i}", elem_id=f"promptbook_prompt_select_button_{i}", variant="primary" if i == 0 else "secondary")
                            with gr.Column(scale=19):
                                with gr.Row():
                                    image_preview = gr.Image(elem_id=f"promptbook_prompt_preview_{i}", type="pil", show_label=False, interactive=False).style(width=64, height=64)
                                    dropdown_prompt = gr.Dropdown(choices=all_prompt_choices, interactive=True, label="Prompt")
                                    slider_strength = gr.Slider(minimum=0.0, maximum=2.0, step=0.05, value=1.0, label="Strength", interactive=True)
                                with gr.Row(visible=False) as custom_row:
                                    custom_prompt = gr.components.Textbox(label="Custom prompt", lines=2)
                                    custom_negative_prompt = gr.components.Textbox(label="Custom negative prompt", lines=2)

                            all_rows.append(UiPromptMergeRow(i, row, delete_button, select_button, image_preview, dropdown_prompt, slider_strength, custom_prompt, custom_negative_prompt))

                dropdown_prompt.change(fn=update_row, inputs=[dropdown_prompt], outputs=[image_preview, custom_row])
                delete_button.click(fn=lambda: ("(None)", 1.0), inputs=None, outputs=[dropdown_prompt, slider_strength])
    with gr.Row():
        create_recipe_button = gr.Button("Generate Recipe", variant="primary")
        load_recipe_button = gr.Button("Load Recipe")
        clear_recipe_button = gr.Button("Clear Recipe")
        evaluate_recipe_button = gr.Button("Evaluate Recipe")
    with gr.Row():
        recipe_json = gr.Textbox(label="Recipe Output")

    prompt_merge_ui = UiPromptMerge(all_rows)
    create_recipe_button.click(fn=UiPromptMerge.output_recipe, inputs=prompt_merge_ui.output_prompt_outputs(), outputs=[recipe_json])
    load_recipe_button.click(fn=UiPromptMerge.load_recipe, inputs=[recipe_json], outputs=prompt_merge_ui.output_prompt_outputs())
    clear_recipe_button.click(fn=UiPromptMerge.clear_recipe, inputs=None, outputs=prompt_merge_ui.output_prompt_outputs())
    evaluate_recipe_button.click(fn=UiPromptMerge.evaluate_recipe, inputs=prompt_merge_ui.output_prompt_outputs(), outputs=[recipe_json])

    return prompt_merge_ui

####################################################################################################

tabs_list = ["promptbook", "generated"]
num_of_prompts_per_page = 0
PROMPTS_PATH = os.path.join(scripts.basedir(), "promptbook/prompts")
GENERATED_PATH = os.path.join(scripts.basedir(), "promptbook/generated")
ICON_PATH = os.path.join(scripts.basedir(), "static/promptbook_icon.png")

def traverse_all_files(curr_path, prompt_list) -> List[Tuple[str, os.stat_result]]:
    f_list = [(os.path.join(curr_path, entry.name), entry.stat()) for entry in os.scandir(curr_path)]
    for f_info in f_list:
        fname, fstat = f_info
        if os.path.splitext(fname)[1] == ".png":
            prompt_list.append(f_info)
        elif stat.S_ISDIR(fstat.st_mode):
            prompt_list = traverse_all_files(fname, prompt_list)
    return prompt_list

def get_all_prompts(sort_by, keyword):
    fileinfos = traverse_all_files(shared.opts.promptbook_prompts_path, [])
    keyword = keyword.strip(" ")
    if len(keyword) != 0:
        fileinfos = [x for x in fileinfos if keyword.lower() in x[0].lower()]
    if sort_by == "date":
        fileinfos = sorted(fileinfos, key=lambda x: -x[1].st_mtime)
    elif sort_by == "path name":
        fileinfos = sorted(fileinfos)

    filenames = [finfo[0] for finfo in fileinfos]
    return filenames

def get_prompt_page(page_index, filenames, keyword, sort_by):
    if page_index == 1 or page_index == 0 or len(filenames) == 0:
        filenames = get_all_prompts(sort_by, keyword)
    page_index = int(page_index)
    length = len(filenames)
    max_page_index = length // num_of_prompts_per_page + 1
    page_index = max_page_index if page_index == -1 else page_index
    page_index = 1 if page_index < 1 else page_index
    page_index = max_page_index if page_index > max_page_index else page_index
    idx_frm = (page_index - 1) * num_of_prompts_per_page
    prompt_list = filenames[idx_frm:idx_frm + num_of_prompts_per_page]

    visible_num = num_of_prompts_per_page if idx_frm + num_of_prompts_per_page < length else length % num_of_prompts_per_page
    visible_num = num_of_prompts_per_page if visible_num == 0 else visible_num

    load_info = "
"
    load_info += f"{length} images in this directory, divided into {int((length + 1) // num_of_prompts_per_page  + 1)} pages"
    load_info += "
"
    return filenames, page_index, prompt_list, visible_num, ""

def show_prompt_info(tabname_box, num, page_index, filenames):
    file = filenames[int(num) + int((page_index - 1) * num_of_prompts_per_page)]
    tm = "
" + time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(os.path.getmtime(file))) + "
"
    return file, tm, num, file, ""

def populate_prompt_info(image):
    prompt = Prompt.load_from_image(image)
    return prompt.name, prompt.description, prompt.positive, prompt.negative, "", "", ','.join(prompt.tags)

def open_promptbook():
    tabname = "promptbook"
    with gr.Tab(tabname):
        with gr.Blocks(analytics_enabled=False):
            with gr.Row():
                first_page = gr.Button('First Page')
                prev_page = gr.Button('Prev Page')
                page_index = gr.Number(value=1, label="Page Index")
                next_page = gr.Button('Next Page')
                end_page = gr.Button('Last Page')
            with gr.Row(elem_id=tabname+'_promptbook'):
                with gr.Row():
                    with gr.Column(scale=3):
                        prompt_gallery = gr.Gallery(show_label=False, elem_id=tabname + "_promptbook_gallery").style(grid=6)
                        with gr.Row():
                            add_prompt_button = gr.Button("Add Prompt", elem_id=tabname + "_promptbook_add_prompt_btn")
                            add_prompt_index = gr.Number(label="Prompt Index", value=0)
                        prompt_merge_ui = ui_prompt_merge()
                    with gr.Column():
                        with gr.Row():
                            sort_by = gr.Radio(value="date", choices=["path name", "date"], label="sort by")
                            keyword = gr.Textbox(value="", label="keyword")
                        with gr.Row():
                            with gr.Column():
                                prompt_name = gr.Textbox(value="", label="Prompt Name", interactive=False)
                                prompt_description = gr.Textbox(value="", label="Prompt Description", interactive=False)
                                prompt_positive = gr.Textbox(label="Positive Prompt", interactive=False, lines=6)
                                prompt_negative = gr.Textbox(label="Negative Prompt", interactive=False, lines=6)
                                prompt_tags = gr.Textbox(value="", label="Prompt Tags", interactive=False)
                                prompt_file_name = gr.Textbox(value="", label="File Name", interactive=False)
                                prompt_file_time = gr.HTML()
                            with gr.Row():
                                try:
                                    send_to_buttons = modules.generation_parameters_copypaste.create_buttons(["txt2img", "img2img", "inpaint", "extras"])
                                except:
                                    pass

                    # hiden items
                    with gr.Row(visible=False):
                        renew_page = gr.Button("Renew Page", elem_id=tabname+"_promptbook_renew_page")
                        visible_img_num = gr.Number()
                        tabname_box = gr.Textbox(tabname)
                        prompt_index = gr.Textbox(value=-1)
                        set_index = gr.Button('set_index', elem_id=tabname+"_promptbook_set_index")
                        filenames = gr.State([])
                        prompt_info_switch = gr.Image(type="pil")
                        info1 = gr.Textbox()
                        info2 = gr.Textbox()
                        load_switch = gr.Textbox(value="load_switch", label="load_switch")
                        turn_page_switch = gr.Number(value=1, label="turn_page_switch")
                        prompt_file_info_raw = gr.Textbox(label="Generate Info", interactive=False, lines=6)

    #turn page
    first_page.click(lambda s:(1, -s) , inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
    next_page.click(lambda p, s: (p + 1, -s), inputs=[page_index, turn_page_switch], outputs=[page_index, turn_page_switch])
    prev_page.click(lambda p, s: (p - 1, -s), inputs=[page_index, turn_page_switch], outputs=[page_index, turn_page_switch])
    end_page.click(lambda s: (-1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
    load_switch.change(lambda s:(1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
    keyword.submit(lambda s:(1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
    sort_by.change(lambda s:(1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
    page_index.submit(lambda s: -s, inputs=[turn_page_switch], outputs=[turn_page_switch])
    renew_page.click(lambda s: -s, inputs=[turn_page_switch], outputs=[turn_page_switch])

    turn_page_switch.change(
        fn=get_prompt_page,
        inputs=[page_index, filenames, keyword, sort_by],
        outputs=[filenames, page_index, prompt_gallery, visible_img_num, prompt_file_info_raw]
    )
    turn_page_switch.change(fn=None, inputs=[tabname_box], outputs=None, _js="promptbook_turnpage")

    def reload_prompts():
        prompts = get_all_prompts("", "")
        choices = SPECIAL_PROMPTS + [os.path.splitext(os.path.basename(prompt))[0] for prompt in prompts]
        return [gr.update(choices=choices) for i in range(len(prompt_merge_ui.prompt_choices_outputs()))]
    turn_page_switch.change(fn=reload_prompts, inputs=[], outputs=prompt_merge_ui.prompt_choices_outputs())

    set_index.click(show_prompt_info,
                    _js="promptbook_get_current_img",
                    inputs=[
                        tabname_box,
                        prompt_index,
                        page_index,
                        filenames
                    ],
                    outputs=[
                        prompt_file_name,
                        prompt_file_time,
                        prompt_index,
                        prompt_info_switch,
                        prompt_file_info_raw
                    ])
    prompt_info_switch.change(fn=populate_prompt_info, inputs=[prompt_info_switch], outputs=[prompt_name, prompt_description, prompt_positive, prompt_negative, prompt_tags])
    prompt_info_switch.change(fn=modules.extras.run_pnginfo, inputs=[prompt_info_switch], outputs=[info1, prompt_file_info_raw, info2])

    try:
        modules.generation_parameters_copypaste.bind_buttons(send_to_buttons, prompt_file_name, prompt_file_info_raw)
    except:
        pass

    def add_prompt(add_prompt_name, add_index, *rest):
        pairwise = list(zip(rest[::2], rest[1::2]))
        result = []

        for index, pair in enumerate(pairwise):
            prompt_name, strength = pair
            if index == add_index:
                print("Add " + add_prompt_name)
                prompt_name = add_prompt_name
                strength = 1.0
            result += [prompt_name, strength]

        add_index += 1
        if add_index >= len(pairwise):
            add_index = 0

        return [add_index] + result

    add_prompt_vars = prompt_merge_ui.add_prompt_outputs()
    add_prompt_button.click(fn=add_prompt, inputs=[prompt_name, add_prompt_index] + add_prompt_vars, outputs=[add_prompt_index] + add_prompt_vars)

    def update_select_buttons(selected_index):
        return [gr.Button.update(variant="primary" if selected_index == i else "secondary") for i in range(0, int(opts.promptbook_merge_max_rows))]
    add_prompt_index.change(fn=update_select_buttons, inputs=[add_prompt_index], outputs=prompt_merge_ui.select_button_outputs())

    for row in prompt_merge_ui.rows:
        row.select_button.click(fn=lambda i=row.index: i, inputs=None, outputs=[add_prompt_index])
        row.delete_button.click(fn=lambda i=row.index: i, inputs=None, outputs=[add_prompt_index])

def get_all_generated(prompt_name, sort_by, keyword):
    path = os.path.join(opts.promptbook_generated_path, prompt_name + ".json")
    if not os.path.isfile(path):
        return []

    with open(path, "r") as file:
        jsdata = json.load(file)

    # TODO use correct sha256sum
    results = []
    for files in jsdata["files"].values():
        for entry in files:
            if os.path.isfile(entry["filename"]):
                results.append(entry["filename"])

    return results

def get_generated_page(prompt_name, page_index, filenames, keyword, sort_by):
    if page_index == 1 or page_index == 0 or len(filenames) == 0:
        filenames = get_all_generated(prompt_name, sort_by, keyword)
    page_index = int(page_index)
    length = len(filenames)
    max_page_index = length // num_of_prompts_per_page + 1
    page_index = max_page_index if page_index == -1 else page_index
    page_index = 1 if page_index < 1 else page_index
    page_index = max_page_index if page_index > max_page_index else page_index
    idx_frm = (page_index - 1) * num_of_prompts_per_page
    prompt_list = filenames[idx_frm:idx_frm + num_of_prompts_per_page]

    visible_num = num_of_prompts_per_page if idx_frm + num_of_prompts_per_page < length else length % num_of_prompts_per_page
    visible_num = num_of_prompts_per_page if visible_num == 0 else visible_num

    load_info = "
"
    load_info += f"{length} images in this directory, divided into {int((length + 1) // num_of_prompts_per_page  + 1)} pages"
    load_info += "
"
    return filenames, page_index, prompt_list, visible_num, ""

def show_generated_info(tabname_box, num, page_index, filenames):
    file = filenames[int(num) + int((page_index - 1) * num_of_prompts_per_page)]
    tm = "
" + time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(os.path.getmtime(file))) + "
"
    return file, tm, num, file, ""

all_prompts = []

def reload_prompts():
    global all_prompts
    filenames = get_all_prompts("", "")
    all_prompts = [os.path.splitext(os.path.basename(filename))[0] for filename in filenames]

def open_generated():
    tabname = "generated"
    with gr.Tab(tabname):
        with gr.Blocks(analytics_enabled=False):
            with gr.Row():
                first_page = gr.Button('First Page')
                prev_page = gr.Button('Prev Page')
                page_index = gr.Number(value=1, label="Page Index")
                next_page = gr.Button('Next Page')
                end_page = gr.Button('Last Page')
            with gr.Row(elem_id=tabname+'_promptbook'):
                with gr.Row():
                    with gr.Column(scale=3):
                        with gr.Row():
                            prompt_name = gr.Dropdown(label='Prompt', elem_id="promptbook_prompt_name", choices=[])
                            modules.ui.create_refresh_button(prompt_name, reload_prompts, lambda: {"choices": sorted([x for x in all_prompts])}, "refresh_prompts")
                        seed_gallery = gr.Gallery(show_label=False, elem_id=tabname + "_promptbook_gallery").style(grid=6)

                    with gr.Column():
                        with gr.Row():
                            sort_by = gr.Radio(value="date", choices=["path name", "date"], label="sort by")
                            keyword = gr.Textbox(value="", label="keyword")
                        with gr.Row():
                            with gr.Column():
                                generated_file_info = gr.Textbox(label="Generate Info", interactive=False, lines=6)
                                generated_file_name = gr.Textbox(value="", label="File Name", interactive=False)
                                generated_file_time = gr.HTML()
                        with gr.Row(elem_id=tabname + "_promptbook_button_panel"):
                            try:
                                send_to_buttons = modules.generation_parameters_copypaste.create_buttons(["txt2img", "img2img", "inpaint", "extras"])
                            except:
                                pass

                    # hiden items
                    with gr.Row(visible=False):
                        renew_page = gr.Button("Renew Page", elem_id=tabname+"_promptbook_renew_page")
                        visible_img_num = gr.Number()
                        tabname_box = gr.Textbox(tabname)
                        generated_index = gr.Textbox(value=-1)
                        set_index = gr.Button('set_index', elem_id=tabname+"_promptbook_set_index")
                        filenames = gr.State([])
                        generated_info_switch = gr.Image(type="pil")
                        info1 = gr.Textbox()
                        info2 = gr.Textbox()
                        load_switch = gr.Textbox(value="load_switch", label="load_switch")
                        turn_page_switch = gr.Number(value=1, label="turn_page_switch")

    #turn page
    first_page.click(lambda s:(1, -s) , inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
    next_page.click(lambda p, s: (p + 1, -s), inputs=[page_index, turn_page_switch], outputs=[page_index, turn_page_switch])
    prev_page.click(lambda p, s: (p - 1, -s), inputs=[page_index, turn_page_switch], outputs=[page_index, turn_page_switch])
    end_page.click(lambda s: (-1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
    load_switch.change(lambda s:(1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
    keyword.submit(lambda s:(1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
    sort_by.change(lambda s:(1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
    page_index.submit(lambda s: -s, inputs=[turn_page_switch], outputs=[turn_page_switch])
    renew_page.click(lambda s: -s, inputs=[turn_page_switch], outputs=[turn_page_switch])
    prompt_name.change(lambda s: -s, inputs=[turn_page_switch], outputs=[turn_page_switch])

    turn_page_switch.change(
        fn=get_generated_page,
        inputs=[prompt_name, page_index, filenames, keyword, sort_by],
        outputs=[filenames, page_index, seed_gallery, visible_img_num, generated_file_info]
    )
    turn_page_switch.change(fn=None, inputs=[tabname_box], outputs=None, _js="promptbook_turnpage")

    set_index.click(show_generated_info,
                    _js="promptbook_get_current_img",
                    inputs=[
                        tabname_box,
                        generated_index,
                        page_index,
                        filenames
                    ],
                    outputs=[
                        generated_file_name,
                        generated_file_time,
                        generated_index,
                        generated_info_switch,
                        generated_file_info
                    ])
    generated_info_switch.change(fn=modules.extras.run_pnginfo, inputs=[generated_info_switch], outputs=[info1, generated_file_info, info2])

    try:
        modules.generation_parameters_copypaste.bind_buttons(send_to_buttons, generated_file_name, generated_file_info)
    except:
        pass

TAB_INDEX_GENERATE = 0
TAB_INDEX_SAVE_PROMPT = 1

def merge_processed(processed_list, include_lone_images=True, rows=None, make_grid=True) -> Processed:
    # Temporary list of all the images that are generated to be populated into the grid.
    # Will be filled with empty images for any individual step that fails to process properly
    image_cache = []

    processed_result = None
    for processed in processed_list:
        try:
            for processed_image in processed.images:
                if processed_result is None:
                    # Use our first valid processed result as a template container to hold our full results
                    processed_result = copy(processed)
                    cell_mode = processed_image.mode
                    cell_size = processed_image.size
                    processed_result.images = []
                    if make_grid:
                        processed_result.images.append(Image.new(cell_mode, cell_size))

                image_cache.append(processed_image)
                if include_lone_images:
                    processed_result.images.append(processed_image)
                    processed_result.all_prompts.append(processed.prompt)
                    processed_result.all_seeds.append(processed.seed)
                    processed_result.infotexts.append(processed.infotexts[0])
        except Exception:
            image_cache.append(Image.new(cell_mode, cell_size))

    if not processed_result:
        raise RuntimeError("Unexpected error: draw_xy_grid failed to return even a single processed image")

    if make_grid:
        if rows is None:
            rows = math.ceil(math.sqrt(len(image_cache)))

        # TODO: layout vertically depending on image size
        grid = images.image_grid(image_cache, rows=rows)

        processed_result.images[0] = grid

    return processed_result

####################################################################################################

def join_prompts(p):
    return sanitize_prompt(", ".join([sanitize_prompt(prompt) for prompt in p]))

def apply_prompt_strength(prompt, strength):
    if strength == 1.0 or not prompt.strip():
        return prompt

    parsed = prompt_parser.parse_prompt_attention(prompt)
    for pair in parsed:
        pair[1] *= strength

    return "".join(["(" + pair[0] + ":" + ("%0.3f" % pair[1]) + ")" for pair in parsed])

def apply_recipe(p, recipe, existing_prompt_action):
    prompt, negative_prompt = recipe.evaluate(p, existing_prompt_action)

    p.prompt = prompt
    p.negative_prompt = negative_prompt

    return process_images(p)

# HACK: Better way of getting result filename from a Processed (before script returns)?
def get_resulting_sample_filename(p, processed, seed, prompt, image, image_count, index):
    # Copied from modules/images.py
    namegen = FilenameGenerator(p, seed, prompt, image)
    basename = ""
    extension = opts.samples_format
    path = p.outpath_samples

    save_to_dirs = opts.save_to_dirs

    if save_to_dirs:
        dirname = namegen.apply(opts.directories_filename_pattern or "[prompt_words]").lstrip(' ').rstrip('\\ /')
        path = os.path.join(path, dirname)

    os.makedirs(path, exist_ok=True)

    if seed is None:
        file_decoration = ""
    elif opts.save_to_dirs:
        file_decoration = opts.samples_filename_pattern or "[seed]"
    else:
        file_decoration = opts.samples_filename_pattern or "[seed]-[prompt_spaces]"

    add_number = opts.save_images_add_number or file_decoration == ''

    if file_decoration != "" and add_number:
        file_decoration = "-" + file_decoration

    file_decoration = namegen.apply(file_decoration)

    if add_number:
        basecount = images.get_next_sequence_number(path, basename) - image_count
        fn = f"{basecount + index:05}"
        fullfn = os.path.join(path, f"{fn}{file_decoration}.{extension}")
    else:
        fullfn = os.path.join(path, f"{file_decoration}.{extension}")

    return fullfn

def append_generated(prompt, strength, output_img_filename):
    if prompt.name == "(Custom)" or prompt.sha256 == "":
        return

    path = os.path.join(opts.promptbook_generated_path, prompt.name + ".json")
    if os.path.isfile(path):
        with open(path, "r") as file:
            jsdata = json.load(file)
    else:
        jsdata = {
            "version": PROMPTBOOK_VERSION,
            "files": {}
        }

    if prompt.sha256 not in jsdata["files"]:
        jsdata["files"][prompt.sha256] = []

    jsdata["files"][prompt.sha256].append({"filename": output_img_filename, "strength": strength})

    with open(path, "w+") as file:
        json.dump(jsdata, file)

import base64
import json
import zlib
from PIL import Image, PngImagePlugin, ImageDraw, ImageFont
from fonts.ttf import Roboto

def caption_image_overlay(srcimage, title, textfont=None):
    from math import sin

    title = (title[:30] + '...') if len(title) > 30 else title

    image = srcimage.copy()
    fontsize = 32
    if textfont is None:
        try:
            textfont = ImageFont.truetype(None or Roboto, fontsize)
            textfont = None or Roboto
        except Exception:
            textfont = Roboto

    factor = 4.0
    gradient = Image.new('RGBA', (1, image.size[1]), color=(0, 0, 0, 0))
    for y in range(math.ceil(image.size[1]/3)):
        mag = sin(y/image.size[1]*factor)
        gradient.putpixel((0, y+math.floor(image.size[1]/3*2)), (0, 0, 0, int(mag*255)))
    image = Image.alpha_composite(image.convert('RGBA'), gradient.resize(image.size))

    draw = ImageDraw.Draw(image)

    font = ImageFont.truetype(textfont, fontsize)
    padding = 10

    _, _, w, h = draw.textbbox((0, 0), title, font=font)
    fontsize = min(int(fontsize * (((image.size[0]*0.95)-(padding*4))/w)), 72)
    font = ImageFont.truetype(textfont, fontsize)
    _, _, w, h = draw.textbbox((0, 0), title, font=font)
    draw.text((padding, image.size[1]-(padding*1.5)), title, anchor='ls', font=font, fill=(255, 255, 255, 230))

    icon_size = int(min(image.size[0], image.size[1]) * 0.2)
    icon = Image.open(ICON_PATH).resize((icon_size, icon_size))
    image.paste(icon, (padding, padding), icon)

    return image

class Script(scripts.Script):
    def title(self):
        return "Promptbook Generation"

    def show(self, is_img2img):
        return True

    def ui(self, is_img2img):
        with gr.Tabs():
            with gr.TabItem('Generate') as tab_generate:
                recipe_json = gr.Textbox(label="Recipe JSON")
                dropdown_txt2img_prompt = gr.Dropdown(choices=["Ignore", "Prepend", "Append"], value="Ignore", label="txt2img prompt")
                checkbox_save_grid = gr.Checkbox(label="Save grid", value=True)

            with gr.TabItem('Save Prompt') as tab_save:
                prompt_name = gr.Textbox(label="Prompt name (Leave blank to use positive prompt as name)", value="")
                prompt_description = gr.Textbox(label="Prompt description", value="")
                prompt_tags = gr.Textbox(label="Prompt tags", value="")
                save_prompt_card = gr.Checkbox(label="Save prompt card", value=True)
                with gr.Row():
                    overwrite_existing = gr.Checkbox(label="Overwrite existing", value=False)
                    generate_comparison = gr.Checkbox(label="Generate comparison", value=False)
                example_prompt = gr.Textbox(label="Example prompt", value="", lines=2)
                example_negative_prompt = gr.Textbox(label="Example negative prompt", value="", lines=2)
                append_example_prompts = gr.Checkbox(label="Append example prompts", value=False)
                batch_filename = gr.Textbox(label="Batch file (one positive prompt per line)", value="")
                batch_reset_seed = gr.Checkbox(label="Randomize seed each batch iteration", value=False)

        with gr.Row(visible=False):
            tab_index = gr.Number(value=0)

        tab_generate.select(lambda: (TAB_INDEX_GENERATE), inputs=None, outputs=[tab_index])
        tab_save.select(
            lambda p, pn: (
                TAB_INDEX_SAVE_PROMPT,
                shared.opts.promptbook_default_prompt if not p.strip() else p,
                shared.opts.promptbook_default_negative_prompt if not pn.strip() else pn),
            inputs=[example_prompt, example_negative_prompt],
            outputs=[tab_index, example_prompt, example_negative_prompt])

        return [
            tab_index,
            recipe_json,
            dropdown_txt2img_prompt,
            checkbox_save_grid,
            prompt_name,
            prompt_description,
            prompt_tags,
            overwrite_existing,
            generate_comparison,
            save_prompt_card,
            example_prompt,
            example_negative_prompt,
            append_example_prompts,
            batch_filename,
            batch_reset_seed
        ]

    def run(self,
            p,
            tab_index,
            gen_recipe_json,
            gen_txt2img_prompt,
            gen_save_grid,
            save_prompt_name,
            save_prompt_description,
            save_prompt_tags,
            save_overwrite_existing,
            save_generate_comparison,
            save_prompt_card,
            save_example_prompt,
            save_example_negative_prompt,
            save_append_example_prompts,
            save_batch_filename,
            save_batch_reset_seed):
        modules.processing.fix_seed(p)

        os.makedirs(opts.promptbook_generated_path, exist_ok=True)

        if tab_index == TAB_INDEX_GENERATE:
            return self.generate(p, gen_recipe_json, gen_txt2img_prompt, gen_save_grid)
        elif tab_index == TAB_INDEX_SAVE_PROMPT:
            return self.save_prompt(
                p,
                save_prompt_name,
                save_prompt_description,
                save_prompt_tags,
                save_overwrite_existing,
                save_generate_comparison,
                save_prompt_card,
                save_example_prompt,
                save_example_negative_prompt,
                save_append_example_prompts,
                save_batch_filename,
                save_batch_reset_seed
            )

    def generate(self, p, recipe_json, txt2img_prompt, save_grid):
        if recipe_json.strip().startswith("["):
            recipes = Recipe.from_json_array(recipe_json)
        else:
            recipes = [Recipe.from_json(recipe_json)]

        results = []

        for recipe in recipes:
            processed = apply_recipe(p, recipe, txt2img_prompt)
            results.append(processed)

            unwanted_grid_because_of_img_count = len(processed.images) < 2 and opts.grid_only_if_multiple
            has_grid = (opts.return_grid or opts.grid_save) and not p.do_not_save_grid and not unwanted_grid_because_of_img_count

            for i in range(0, len(processed.all_seeds)):
                filename = get_resulting_sample_filename(p,
                                                         processed,
                                                         processed.all_seeds[i],
                                                         processed.all_prompts[i],
                                                         # ignore grid image
                                                         processed.images[i + 1 if has_grid else 0],
                                                         len(processed.all_seeds),
                                                         i)
                for part in recipe.parts:
                    if part is None:
                        continue
                    append_generated(part.prompt, part.strength, filename)

            if save_grid:
                images.save_image(processed.images[0], p.outpath_grids, "promptbook", prompt=p.prompt, seed=processed.seed, grid=True, p=p)

        if not results:
            raise Exception("No recipes succesfully generated images.")

        merged = merge_processed(results, include_lone_images=True, make_grid=False)

        return merged

    def generate_cover_with_comparison(self, p, i, filename, prompt_description, pos, neg, example_prompt, example_negative_prompt, append_example_prompts):
        p1 = copy(p)
        p1.prompt = example_prompt
        p1.negative_prompt = example_negative_prompt
        before: Processed = process_images(p1)

        p2 = copy(p)
        if append_example_prompts:
            p2.prompt = join_prompts([pos, example_prompt])
            p2.negative_prompt = join_prompts([neg, example_negative_prompt])
        else:
            p2.prompt = join_prompts([example_prompt, pos])
            p2.negative_prompt = join_prompts([example_negative_prompt, neg])
        after: Processed = process_images(p2)

        original_prompt = after.infotexts[0]

        return merge_processed([before, after], include_lone_images=True, rows=1), original_prompt, p2

    def generate_cover(self, p, i, filename, prompt_description, pos, neg, example_prompt, example_negative_prompt, append_example_prompts):
        p1 = copy(p)
        if append_example_prompts:
            p1.prompt = join_prompts([pos, example_prompt])
            p1.negative_prompt = join_prompts([neg, example_negative_prompt])
        else:
            p1.prompt = join_prompts([example_prompt, pos])
            p1.negative_prompt = join_prompts([example_negative_prompt, neg])
        after: Processed = process_images(p1)

        return after, after.infotexts[0], p1

    def save_prompt(self,
                    p,
                    prompt_name,
                    prompt_description,
                    prompt_tags,
                    overwrite_existing,
                    generate_comparison,
                    save_prompt_card,
                    example_prompt,
                    example_negative_prompt,
                    append_example_prompts,
                    batch_filename,
                    batch_reset_seed):
        if prompt_name == "":
            prompt_name = p.prompt
        sanitized_name = images.sanitize_filename_part(prompt_name, replace_spaces=False)
        if batch_filename == "" and not sanitized_name.strip():
            raise RuntimeError("Prompt name was blank.")

        p.batch_count = 1
        # p.batch_size = 1

        if batch_filename != "":
            with open(batch_filename, "r", encoding="utf-8") as file:
                ext = os.path.splitext(batch_filename)
                if ext == ".json":
                    prompts_json = json.load(file)
                    prompts = [(p.get("prompt", ""), p.get("negative_prompt", ""), p.get("tags", [])) for p in prompts_json]
                else:
                    prompts = [(line.strip(), "", []) for line in file]
        else:
            tags = [tag.strip() for tag in prompt_tags.split(',')]
            prompts = [(p.prompt, p.negative_prompt, tags)]

        steps_per_run = 2 if generate_comparison else 1

        shared.total_tqdm.updateTotal(p.steps * p.n_iter * steps_per_run * len(prompts))
        shared.state.job_count = p.n_iter * steps_per_run * len(prompts)

        results = []

        for i, prompt in enumerate(prompts):
            if batch_reset_seed:
                p.seed = -1
                p.subseed = -1
                modules.processing.fix_seed(p)

            pos, neg, tags = prompt

            filename = sanitized_name
            if batch_filename != "":
                filename = images.sanitize_filename_part(pos, replace_spaces=False)

            outpath = os.path.join(opts.promptbook_prompts_path, f"{filename}.png")
            if os.path.exists(outpath) and not overwrite_existing:
                print("File already exists, skipping: " + filename)
                continue

            print(f"Generating prompt card '{filename}'")
            print(f"Positive:{pos}")
            if neg != "":
                print(f"Negative:{neg}")
            if tags:
                print(f"Tags: {', '.join(tags)}")

            if generate_comparison:
                processed, original_prompt, p2 = self.generate_cover_with_comparison(p, i, filename, prompt_description, pos, neg, example_prompt, example_negative_prompt, append_example_prompts)
            else:
                processed, original_prompt, p2 = self.generate_cover(p, i, filename, prompt_description, pos, neg, example_prompt, example_negative_prompt, append_example_prompts)

            if save_prompt_card:
                prompt = Prompt(filename, prompt_description, pos, neg, tags)
                cover = caption_image_overlay(processed.images[0], filename)
                grid_outpath = images.save_image(
                    cover,
                    opts.promptbook_prompts_path,
                    basename="",
                    prompt=p2.prompt,
                    seed=processed.seed,
                    grid=True,
                    p=p2,
                    forced_filename=filename,
                    # don't save the info .txt alongside like if info=<...> were passed
                    # these images are mostly for comparison instead of generating something pretty
                    existing_info={"promptbook_prompt": prompt.to_json(), "parameters": original_prompt},
                    pnginfo_section_name=""
                )

            results.append(processed)

        if not results:
            raise Exception("No promptcards generated! Do all the files in the batch exist already?")

        return merge_processed(results, include_lone_images=True, make_grid=False)

def create_promptbook(pb):
    with gr.Tabs(elem_id="promptbook_tab"):
        open_promptbook()
        open_generated()

def on_ui_tabs():
    global num_of_prompts_per_page
    num_of_prompts_per_page = int(opts.promptbook_page_columns * opts.promptbook_page_rows)
    with gr.Blocks(analytics_enabled=False) as pb:
        create_promptbook(pb)
        gr.Checkbox(opts.promptbook_preload, elem_id="promptbook_preload", visible=False)
        gr.Textbox(",".join(tabs_list), elem_id="promptbook_tabnames_list", visible=False)
    return (pb, "Promptbook", "promptbook"),

DEFAULT_PROMPT = """masterpiece, high quality, highres, 1girl"""
DEFAULT_NEGATIVE_PROMPT = ""
DEFAULT_MAX_ROWS = 15

def on_ui_settings():
    section = ('promptbook', "Promptbook")
    shared.opts.add_option("promptbook_preload", shared.OptionInfo(False, "Preload images at startup", section=section))
    shared.opts.add_option("promptbook_page_columns", shared.OptionInfo(6, "Number of columns on the page", section=section))
    shared.opts.add_option("promptbook_page_rows", shared.OptionInfo(6, "Number of rows on the page", section=section))
    shared.opts.add_option("promptbook_default_prompt", shared.OptionInfo(DEFAULT_PROMPT, "Default prompt to use when generating prompt covers", section=section))
    shared.opts.add_option("promptbook_default_negative_prompt", shared.OptionInfo(DEFAULT_NEGATIVE_PROMPT, "Default negative prompt to use when generating prompt covers", section=section))
    shared.opts.add_option("promptbook_prompts_path", shared.OptionInfo(PROMPTS_PATH, "Path containing prompt .png files", section=section))
    shared.opts.add_option("promptbook_generated_path", shared.OptionInfo(GENERATED_PATH, "Path containing files for generation stats", section=section))
    shared.opts.add_option("promptbook_merge_max_rows", shared.OptionInfo(DEFAULT_MAX_ROWS, "Maximum prompt count for the prompt merger", section=section))

script_callbacks.on_ui_settings(on_ui_settings)
script_callbacks.on_ui_tabs(on_ui_tabs)


"""
SVM dla klasyfikacji
Program, który za pomocą SVM klasyfikuje dane

## Autorzy
-Paweł Szyszkowski s18184
-Braian Kreft s16723

## Instalacja

pip install -r requirements.txt

## Uruchomienie
python SVM_happy.py

## Instrukcja użycia
Po uruchomieniu programu zostaną nam przewidywane wyniki
"""
import numpy as np
from sklearn import svm
from numpy import random

"""
Ładowanie danych z pliku tekstowego z odzieleniem po przecinku
"""

input_file = 'data_happy.txt'
data = np.loadtxt(input_file, delimiter=',')

"""
Przypisanie do zmiennych kolumn z danymi i kolumn z wynikami
"""

X, y = data[:, 1:], data[:, 0]
"""
Zasilenie danymi testowymi funkcjonalności SVM

"""
svc = svm.SVC(kernel='linear', C=1, gamma=100).fit(X, y)

"""
Generowanie losowych danych do predykcji

"""
XX = random.randint(1,6, size=(100, 6))
XX = np.asarray(XX)

"""
Generowanie predykcji
"""
Z = svc.predict(np.c_[XX])

for i in range(Z.size):
    print('Dane:', XX[i, :], ' wskazują na opinię ', 'pozytywną' if Z[i] == 1 else 'negatywną' )


from fastapi import APIRouter

from eco_challenge.auth.dependencies import CurrentAdmin
from eco_challenge.core.models.role_model import RoleCreate, RoleGet

from eco_challenge.core.storages.role_storage import RoleStorageDepends
router = APIRouter(prefix='/role', tags=['Role'])

@router.post('/')
async def create_role(role_create: RoleCreate, storage: RoleStorageDepends, _: CurrentAdmin) -> RoleGet:
    return await storage.save_object(role_create)

@router.get('/')
async def get_roles(storage: RoleStorageDepends, _: CurrentAdmin) -> list[RoleGet]:
    return await storage.get_objects()

@router.delete('/{role_id}')
async def delete_role(role_id: int, storage: RoleStorageDepends, _: CurrentAdmin):
    await storage.delete_object(role_id)


import re

from django.conf import settings
from rest_framework import serializers

from api.utils.help_text import make_comma_separated_help_text

class SchemableHyperlinkedIdentityField(serializers.HyperlinkedIdentityField):
    """
    This field returns the link but allows the option to replace the URL scheme.

    This is useful when the API runs on ``http`` behind a proxy that serves ``https``.
    In these cases, the scheme in hyperlinks must be forced to ``https``.
    """

    def __init__(self, scheme=settings.API_LINK_SCHEME, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.scheme = scheme

    def get_url(self, *args, **kwargs):
        url = super().get_url(*args, **kwargs)

        # Only rewrite URLs if a fixed scheme is provided
        if self.scheme is not None:
            url = re.sub(r"^\w+://", f"{self.scheme}://", url, 1)

        return url

class EnumCharField(serializers.CharField):
    """This field extends the ``CharField`` to add enum validation."""

    default_error_messages = serializers.CharField.default_error_messages | {
        "outside_enum": "Invalid value: {given}. Allowed values: {allowed}"
    }

    def __init__(self, plural: str, enum_class: set[str], **kwargs):
        kwargs["help_text"] = make_comma_separated_help_text(enum_class, plural)
        super().__init__(**kwargs)

        self.enum_class = enum_class

    def _validate_enum(self, given_value: str):
        """
        Validate whether the given values are all members of the given enum.

        :param given_value: the comma separated list received in the input
        :return: the lower cased form of the input, if the input is valid
        :raise: ``ValidationError``, if the input is invalid
        """

        lower = given_value.lower()
        input_values = lower.split(",")
        for value in input_values:
            if value not in self.enum_class:
                self.fail("outside_enum", given=value, allowed=self.enum_class)
        return lower

    def to_internal_value(self, data):
        data = super().to_internal_value(data)
        self._validate_enum(data)
        return data


import collections
import json
import re
from functools import lru_cache
from typing import Dict, List
import pandas as pd
import numpy as np
import os
import math

from config import delimiters, debug, stemmer, stop_words

@lru_cache(maxsize=10000000)
def stem(string: str):
    s = string.encode("ascii", "ignore").decode()
    return stemmer.stem(s)

def splitter(text, raw=False):
    word_tokens = re.split(delimiters, text)
    if raw:
        return [word.lower() for word in word_tokens if word not in stop_words]
    words_taken = []

    # words_taken = [stem(word.lower()) for word in word_tokens if word not in stop_words]

    for word in word_tokens:
        word = word.lower()
        if word not in stop_words:
            word = stem(word)
            words_taken.append(word)
    return words_taken

def tokenize_and_store(texts: str or List[str], dictionary: Dict[str, int], frequency=True, raw=False):
    if isinstance(texts, str):
        texts = [texts]
    for text in texts:
        word_tokens = splitter(text, raw)
        for w in word_tokens:
            if frequency:
                dictionary[w] += 1
            else:
                dictionary[w] = 1
    if '' in dictionary:
        dictionary.pop('')

def tokenize_fill_TF(texts: str or List[str], TF: np.ndarray, vocabulary: Dict[str, int]):
    if debug:
        assert TF.size == len(vocabulary)
    if isinstance(texts, str):
        texts = [texts]
    for text in texts:
        word_tokens = splitter(text)
        for w in word_tokens:
            if w in vocabulary:
                TF[vocabulary[w]] += 1
            else:
                if debug:
                    assert w == ''