 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Aug 31 23:00:20 2019

@author: alizz
"""
import os
import csv
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit as fit
from scipy import stats

# %% Input
# Directory:
class cDir:
    dataDir     = '/Users/alizz/Google Drive (alireza.meghdadi@gmail.com)/Southampton - GoogleDrive/'
    dataDir     += 'Experiments/Pipe Viscometry/Data/'
    prepDir     = 'Preprocessed Results/'
    full        = dataDir + prepDir

SaveFigures     = False
SavePoLaw       = False
quality         = 450

pipes       = ['2.48 mm PTFE','4.48 mm PTFE']
techniques  = ['DSS','TSS']
lgRatios    = ['1-3','1-4','1-5']

diameters = {'4.48 mm PTFE':4.48e-3,'2.48 mm PTFE':2.48e-3}
lengths = {'4.48 mm PTFE':15e-2,'2.48 mm PTFE':34e-2}

# %% Functions
def plotCurves (graph,x,y, heading, xlimit, ylimit, xlab, ylab,datalab):
    graph.plot(x,y,marker = 's', markersize = 6, linestyle = 'None', color='k', label = datalab)
    if pipe == '2.48 mm PTFE':
        graph.xaxis.set_major_locator(plt.MultipleLocator(50))
    else:
        graph.xaxis.set_major_locator(plt.MultipleLocator(10))
    graph.minorticks_on()
    graph.grid(True, which='both')
    graph.grid(linestyle=':',linewidth=0.5,which='minor')
    # graph.xaxis.set_minor_locator(plt.MultipleLocator(5))
    graph.set_ylim(ylimit)
    graph.set_xlim(xlimit)
    graph.tick_params(axis='both', labelsize=14)
    graph.set_xlabel(xlab, fontsize = 18, labelpad = 20)
    graph.set_ylabel(ylab, fontsize = 18, labelpad = 15)
    graph.title.set_text(heading)
    graph.title.set_position(titlepos)
    graph.title.set_fontsize(18)

def pLaw(shearRate, k, n):
    tw = (k*(shearRate**n))
    return tw

def polyFit(x,p):
    y = (p[0]*x**2)+(p[1]*x)+p[2]
    return y

def apparentVisc(shearRate, k, n):
    vis = (k*(shearRate**(n-1)))
    return vis

def flowToShear (x,d):
    return ((x*32)/(60000000*np.pi*d**3))

def shearToFlow (x,d):
    return ((x*60000000*np.pi*d**3)/32)

def keyGen(p,t,r):
    return p + " | " + t + " | " + r

def calctw(dp,d,L):
    tw = [100*x*d/(4*L) for x in dp]
    return tw

# %% Read End-Effect Corrections
correctedCsvs = []
bagelyCorrections = {}

directory = os.fsencode(cDir.dataDir+'End-Effects/')
directory_files = sorted(os.listdir(directory))
for file in directory_files:
    filename = os.fsdecode(file)
    if filename.endswith(".csv"):          # Open CSV file
        correctedCsvs.append(filename)
        with open(cDir.dataDir+'End-Effects/'+filename) as csvFile:
            reader = csv.reader(csvFile)
            yint = []
            for row in reader:
                yint.append(row[1])
        bagelyCorrections[filename[:-4]]  = list(map(float,yint[1:]))

# %% Read CSV
csvs        = []
params      = []
polyParams  = []
paramMins   = []
paramMaxs   = []
perrs       = []
perrMins    = []
perrMaxs    = []
chi         = []
ks          = []
pearson     = []
dps         = {}
figs        = []

directory = os.fsencode(cDir.full)
directory_files = sorted(os.listdir(directory))
for file in directory_files:
    filename = os.fsdecode(file)
    if filename.endswith(".csv"):          # Open CSV file
        csvs.append(filename)
        with open(cDir.full + filename) as csvFile:
            reader = csv.reader(csvFile)

            flowRateMl, flowRateM3, viscPoiseuille,viscPoiseuilleStd = [],[],[],[]
            obsShear, tw, twStd = [],[],[]
            viscPoiseuilleMin, viscPoiseuilleMax = [], []
            viscPoiseuilleSemMin, viscPoiseuilleSemMax = [], []
            twMin, twMax, twSemMin, twSemMax, dpAveRep, dpAveStd = [], [], [], [], [], []

            for row in reader:
                flowRateMl.append(row[0])
                flowRateM3.append(row[1])
                dpAveRep.append(row[2])
                dpAveStd.append(row[3])
                viscPoiseuille.append(row[4])
                viscPoiseuilleMin.append(row[5])
                viscPoiseuilleMax.append(row[6])
                viscPoiseuilleStd.append(row[7])
                viscPoiseuilleSemMin.append(row[8])
                viscPoiseuilleSemMax.append(row[9])
                obsShear.append(row[10])
                tw.append(row[11])
                twMin.append(row[12])
                twMax.append(row[13])
                twStd.append(row[14])
                twSemMin.append(row[15])
                twSemMax.append(row[16])

        flowRateMl                      = list(map(float,flowRateMl[1:]))
        flowRateM3                      = list(map(float,flowRateM3[1:]))
        dpAveRep                        = list(map(float,dpAveRep[1:]))
        dpAveStd                        = list(map(float,dpAveStd[1:]))
        viscPoiseuille                  = list(map(float,viscPoiseuille[1:]))
        viscPoiseuilleMin               = list(map(float,viscPoiseuilleMin[1:]))
        viscPoiseuilleMax               = list(map(float,viscPoiseuilleMax[1:]))
        viscPoiseuilleStd               = list(map(float,viscPoiseuilleStd[1:]))
        viscPoiseuilleSemMin            = list(map(float,viscPoiseuilleSemMin[1:]))
        viscPoiseuilleSemMax            = list(map(float,viscPoiseuilleSemMax[1:]))
        obsShear                        = list(map(float,obsShear[1:]))
        tw                              = list(map(float,tw[1:]))
        twMin                           = list(map(float,twMin[1:]))
        twMax                           = list(map(float,twMax[1:]))
        twStd                           = list(map(float,twStd[1:]))
        twSemMin                        = list(map(float,twSemMin[1:]))
        twSemMax                        = list(map(float,twSemMax[1:]))

        pipe        = filename[:12]
        diameter    = float(filename[:4])/1000
        technique   = filename[15:18]
        lgRatio     = filename[21:24]

        key = keyGen(pipe,technique,lgRatio)
        dps[key] = dpAveRep
        correctedDp     = np.subtract(dpAveRep,bagelyCorrections[technique + ' | '+ lgRatio])
        correctedTw     = calctw(correctedDp, diameters[pipe], lengths[pipe])
        twOffset        = np.subtract(tw,correctedTw)
        correctedTwMin  = np.subtract(twMin,twOffset)
        correctedTwMax  = np.subtract(twMax,twOffset)

# %% Power-Law Fitting

        # twStd was halved bcause preprocessing-V5 stores 2*standard deviations in twStd
        param, cov = fit(pLaw,obsShear,correctedTw,bounds=(0,[np.inf,1]),
                         sigma=[(x/2) for x in twStd], absolute_sigma=True)
        paramMin, covMin = fit(pLaw,obsShear,correctedTwMin,bounds=(0,[np.inf,1]),
                               sigma=twSemMin,absolute_sigma=True)
        paramMax, covMax = fit(pLaw,obsShear,correctedTwMax,bounds=(0,[np.inf,1]),
                               sigma=twSemMax,absolute_sigma=True)

        perr = np.sqrt(np.diag(cov))
        up = param + 2*perr # upper limit power law paramers
        down = param - 2*perr # lower limit power law paramers

        perrMin = np.sqrt(np.diag(covMin))
        perrMax = np.sqrt(np.diag(covMax))

        params.append(param)
        paramMins.append(paramMin)
        paramMaxs.append(paramMax)
        perrs.append(perr)
        perrMins.append(perrMin)
        perrMaxs.append(perrMax)

# %% Polynomial Fitting
        polyParam = np.polyfit(correctedTw,obsShear,2)
        polyParams.append(polyParam)

# %% Rheograms

        maxQRange       = np.round(max(flowRateMl),-1)
        xextra          = {'2.48 mm PTFE':30,'4.48 mm PTFE':10}
        maxShearRange   = np.round(max(obsShear)+xextra[pipe],-1)
        maxtw           = {'2.48 mm PTFE':40,'4.48 mm PTFE':80}
        xQlimit         = [0,maxQRange]
        xShearlimit     = [0,maxShearRange]
        ytwlimit        = [0,maxtw[pipe]]
        yViscPoislimit  = {'2.48 mm PTFE':[0,0.4],'4.48 mm PTFE':[0,4]}
        yDplimit        = {'2.48 mm PTFE':[0,160],'4.48 mm PTFE':[0,100]}
        xdata           = np.linspace(obsShear[0],obsShear[-1],500)
        titlepos        = [0.5,1.1]

        twFitData   = pLaw(xdata, *param)
        twup        = pLaw(xdata, *up)
        twdown      = pLaw(xdata, *down)
        twFitMin    = pLaw(xdata, *paramMin)
        twFitMax    = pLaw(xdata, *paramMax)
        appVisc     = apparentVisc(xdata, *param)
        appViscMin  = apparentVisc(xdata, *paramMin)
        appViscMax  = apparentVisc(xdata, *paramMax)

        title       = pipe + ' - ' + technique + ' Foam; Liquid to Gas Ratio = ' + lgRatio[0]
        title       += ':' + lgRatio[-1]

        ymod = [x for x in pLaw(obsShear, *param)]
        var = [(x/2)**2 for x in twStd]
        # varNorm = [abs((x-max(var))/(max(var)-min(var))) for x in var]

        chi.append(stats.chisquare(correctedTw, f_exp=ymod,ddof = 7))
        ks.append(stats.ks_2samp(correctedTw,ymod))              # Kolmogorov - Smirnoff test
        pearson.append(stats.pearsonr(np.log(obsShear),np.log(correctedTw))) #Pearson Test

        figs.append(plt.figure(figsize=[24, 24]))
        figs[-1].subplots_adjust(wspace=0.25, hspace=0.5)
        figs[-1].suptitle(title,weight='bold',fontsize=30)
        plt.style.use('ggplot')

        # g1.grid(False, which='both')
        g1 = figs[-1].add_subplot(221)

        g2 = figs[-1].add_subplot(222)
        g2title = 'Pressure Difference Averages'
        plotCurves(g2, flowRateMl, dpAveRep, g2title, xQlimit, yDplimit[pipe],
                   'Q ($\mathregular{mL.min^{-1}}$)', '$\mathregular{\Delta}$P (mBar)',
                   'Original Data')
        g2.plot(flowRateMl,correctedDp, marker = 'o', markersize = 6, linestyle = 'None',
                color='g', label = 'Corrected Data')
        g2.errorbar(flowRateMl,dpAveRep,yerr=dpAveStd,fmt='None',ecolor='black',elinewidth=1,
                    capsize=4,zorder=6)
        g2.errorbar(flowRateMl,correctedDp,yerr=dpAveStd,fmt='None',ecolor='green',elinewidth=1,
                    capsize=4,zorder=6)
        g2.xaxis.set_major_locator(plt.MultipleLocator(4))
        g2.legend(fontsize=12)

        g3 = figs[-1].add_subplot(223)
        g3title = 'Rheogram'
        plotCurves (g3,obsShear,tw, g3title, xShearlimit, ytwlimit,
                    '$\mathcal{\.\gamma}_{obs}$ ($\mathregular{s^{-1}}$)',
                    r'$\mathregular{\tau}_w$ (Pa)',r'$\mathregular{\tau}_{w_{ave}}$')
        g3.plot(obsShear,correctedTw,marker = 'o',markersize = 6, linestyle = 'None', color='g',
                label = r'Corrected $\mathregular{\tau}_{w_{ave}}$')
        g3.errorbar(obsShear,tw,yerr=twStd,fmt='None',ecolor='black',elinewidth=1,capsize=4)
        g3.errorbar(obsShear,correctedTw,yerr=twStd,fmt='None',ecolor='green',elinewidth=1,capsize=4)
        g3.plot(xdata, twFitData, 'k--',label='Power-Law Fit, ' +
                '$\mathregular{R^2}$ = %.3f' % pearson[-1][0])
        # ydata = np.linspace(correctedTw[0],correctedTw[-1],500)
        # g3.plot(polyFit(ydata,polyParam),ydata, '-r')
        g3.fill_between(xdata,twdown,twup, alpha=0.1, color='m',label='95% Confidence Interval')
        g3.legend(fontsize=12)

        g4 = figs[-1].add_subplot(224)
        g4title     = 'Power-Law Fit, ' + '$\mathregular{R^2}$ = %.3f' % pearson[-1][0]
        g4.grid(True, which='both')
        g4.grid(linestyle=':',linewidth=0.5,which='minor')
        yax2        = g4.twinx()
        yax2.grid(False, which='both')
        twFitLine   = g4.plot(xdata, twFitData, 'g--',label=g4title)
        twDot       = g4.plot(obsShear,correctedTw,marker = 's', markersize = 4, linestyle = 'None',
                              color='k', label = r'$\mathregular{\tau}_{w_{ave}}$')
        twMaxDot    = g4.plot(obsShear,correctedTwMax,marker = '^', markersize = 4,
                              linestyle = 'None', color='red',
                              label = r'$\mathregular{\tau}_{w_{max}}$')
        twMinDot    = g4.plot(obsShear,correctedTwMin,marker = 'v', markersize = 4,
                              linestyle = 'None', color='blue',
                              label = r'$\mathregular{\tau}_{w_{min}}$')
        viscLine    = yax2.plot(xdata, appVisc,'r--', label='Apparent Viscosity')
        region      = g4.fill_between(xdata,twFitMin,twFitMax, alpha=0.2, color='g',
                                      label='Shear Stress Min-Max Region')
        regionVisc  = yax2.fill_between(xdata,appViscMax,appViscMin, alpha=0.2, color='r',
                                        label='Viscosity Min-Max Region')
        yax2.set_ylabel('$\mathregular{\mu}_{app}$ (Pa.s)',fontsize = 18, labelpad = 15)
        yax2.tick_params(axis='both', labelsize=14)
        yax2.set_ylim(yViscPoislimit[pipe])
        xax2Ticks   = np.round([shearToFlow(x,diameter) for x in g4.axes.get_xticks()],1)
        xax2        = g4.twiny()
        xax2.set_xticks(xax2Ticks)
        xax2.axes.set_xlim([shearToFlow(x,diameter) for x in xShearlimit])
        xax2.set_xlabel('Q ($\mathregular{mL.min^{-1}}$)', fontsize = 18, labelpad = 20)
        xax2.tick_params(axis='both', labelsize=14)
        xax2.grid(False, which='both')

        if pipe == '2.48 mm PTFE':
            g4.xaxis.set_major_locator(plt.MultipleLocator(50))
        else:
            g4.xaxis.set_major_locator(plt.MultipleLocator(10))
        g4.minorticks_on()
        g4.set_ylim([0,20])
        g4.set_xlim(xShearlimit)
        g4.tick_params(axis='both', labelsize=14)
        g4.set_xlabel('$\mathcal{\.\gamma}_{obs}$ ($\mathregular{s^{-1}}$)', fontsize = 18,
                      labelpad = 20)
        g4.set_ylabel(r'$\mathregular{\tau}_w$ (Pa)', fontsize = 18, labelpad = 15)
        lns = twFitLine + viscLine
        lns.append(region)
        lns.append(regionVisc)
        lns += twDot + twMinDot + twMaxDot
        labs = [l.get_label() for l in lns]
        g4.legend(lns, labs, fontsize=12, ncol=2)

        if SaveFigures == True:
            folder = 'Rheograms/'
            if os.path.exists(cDir.dataDir+folder) == False:
                    os.mkdir(cDir.dataDir+folder)

            nameEnd = 'Pressure-Corrected Power Law Curve - ' + filename[:-4]
            figs[-1].savefig((cDir.dataDir+folder + '/' + nameEnd + '.png'),dpi=quality,
                             transparent = False)

# %% Save PowerLaw Indices
if SavePoLaw == True:
    # Corrected data:

    # Uncorrected data
    resultsFile = 'Corrected Power Law Indices.csv'
    with open((cDir.dataDir + 'Processed Results/' + resultsFile),'w',newline='') as csvfile:
        fields = ['pipe'                        ,
                  'technique'                   ,
                  'l:g ratio'                   ,
                  'n (flow index)'              ,
                  'n error'                     ,
                  'min n (flow index)'          ,
                  'min n error'                 ,
                  'max n (flow index)'          ,
                  'max n error'                 ,
                  'k (consistency index)'       ,
                  'k error'                     ,
                  'min k (consistency index)'   ,
                  'min k error'                 ,
                  'max k (consistency index)'   ,
                  'max k error'                 ,
                  'polynomial a'                ,
                  'polynomial b'                ,
                  'polynomial c'                ,
                  'chisquared'                  ,
                  'chi-p-value'                 ,
                  'KS D stats'                  ,
                  'KS p-value'                  ,
                  'pearson-p'                   ,
                  'r2'                          ]

        writer = csv.DictWriter(csvfile, fieldnames = fields)
        writer.writeheader()
        for i in range(len(csvs)):
            writer.writerow({
                      'pipe'                        :   csvs[i][:12]        ,
                      'technique'                   :   csvs[i][15:18]      ,
                      'l:g ratio'                   :   csvs[i][21:24]      ,
                      'n (flow index)'              :   params[i][1]        ,
                      'n error'                     :   perrs[i][1]         ,
                      'min n (flow index)'          :   paramMins[i][1]     ,
                      'min n error'                 :   perrMins[i][1]      ,
                      'max n (flow index)'          :   paramMaxs[i][1]     ,
                      'max n error'                 :   perrMaxs[i][1]      ,
                      'k (consistency index)'       :   params[i][0]        ,
                      'k error'                     :   perrs[i][0]         ,
                      'min k (consistency index)'   :   paramMins[i][0]     ,
                      'min k error'                 :   perrMins[i][0]      ,
                      'max k (consistency index)'   :   paramMaxs[i][0]     ,
                      'max k error'                 :   perrMaxs[i][0]      ,
                      'polynomial a'                :   polyParams[i][0]    ,
                      'polynomial b'                :   polyParams[i][1]    ,
                      'polynomial c'                :   polyParams[i][2]    ,
                      'chisquared'                  :   chi[i][0]           ,
                      'chi-p-value'                 :   chi[i][1]           ,
                      'KS D stats'                  :   ks[i][0]            ,
                      'KS p-value'                  :   ks[i][1]            ,
                      'pearson-p'                   :   pearson[i][1]       ,
                      'r2'                          :   pearson[i][0]       })


import sys
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from time import sleep
import sqlite3
import sys
import pandas

driver_service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=driver_service)

# Options for running headless (No GUI). Can be commented out to run with GUI.
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--disable-gpu")
# options.add_argument("--disable-software-rasterizer")
options.add_argument("--ignore-certificate-errors-spki-list")
options.add_argument("--ignore-ssl-errors")
options.add_argument('--no-sandbox')
options.add_argument("--start-maximized")
options.add_argument("--window-size=1920x1080")
driver = webdriver.Chrome(options=options)

# ARGUMENTS
link = "https://www.wunderground.com"

def weather_scraper(start_idx, end_idx, out_file):
    '''
    Wunderground gives two slightly different interfaces depending on the type of station that is selected. This scraper deals with "PWS"
    stations. leftover_stations.py then finds leftover "general" stations for weather_scraper_general(1).py to scrape.
    Written to be parallelized.

    start_idx, end_idx: The respective indices of stations in all_stations.txt to scrape.
    out_file: The output file to write scraped station info to.
    '''

    station_list = []

    with open("all_stations.txt") as f:
        stations = f.readlines()

        for i in range(len(stations)):
            if stations[i] != "\n":
                if i != len(stations) - 1:
                    station_list.append(stations[i][:len(stations[i]) - 1])
                else:
                    station_list.append(stations[i][:len(stations[i])])

        station_list = station_list[start_idx:end_idx]
        print(station_list)

    station_indices = station_list.copy()
    weather_stations_list = []
    for station in station_list:
        success = False
        for i in range(3):
            try:
                driver.get(link)
                driver.implicitly_wait(5)

                input_field = driver.find_element(By.XPATH, '//*[@id="wuSearch"]').send_keys(station)
                sleep(3)

                first_option = driver.find_element(By.XPATH, '//*[@id="wuForm"]/search-autocomplete/ul/li[2]/a/span[1]')
                sleep(3)
                print(first_option.text)

                first_option.click()
                sleep(3)

                sleep(10)
                success = True
                break
            except Exception as exc:
                sleep(10)
                print(exc)
                driver.refresh()
                sleep(20)

        if success != True:
            station_indices.remove(station)
            continue

        if len(driver.find_elements(By.XPATH, '//*[@id="inner-content"]/div[2]/lib-city-header/div[2]/lib-subnav/div/div[3]/ul/li[5]/a')) > 0:
            station_indices.remove(station)
            continue
        else:
            success = False
            for attempt in range(3):
                try:
                    monthly_mode = driver.find_element(By.XPATH, '//*[@id="modeSelect"]/option[3]').click()
                    sleep(5)

                    weather_dict = {}
                    for i in range(4):
                        year_select = driver.find_element(By.XPATH, '//*[@id="yearSelect"]')
                        years = year_select.find_elements(By.TAG_NAME, 'option')
                        year_str = years[i + 1].text

                        year_select.click()
                        years[i + 1].click()
                        print(years[i + 1].text)
                        sleep(1)

                        for j in range(12):
                            month_select = driver.find_element(By.XPATH, '//*[@id="monthSelect"]')
                            months = month_select.find_elements(By.TAG_NAME, 'option')
                            month_str = months[j].text
                            months[j].click()
                            print(month_str)
                            sleep(1)

                            view_btn = driver.find_element(By.XPATH, '//*[@id="main-page-content"]/div/div/div/lib-history/div[1]/div[2]/button').click()
                            sleep(6)

                            table_btn = driver.find_element(By.XPATH, '//*[@id="history-tab-group"]/li[2]/a').click()
                            sleep(3)

                            weather_table = driver.find_element(By.XPATH, '//*[@id="main-page-content"]/div/div/div/lib-history/div[2]/lib-history-table/div/div/div/table/tbody')
                            rows = weather_table.find_elements(By.TAG_NAME, 'tr')

                            for row in rows:
                                weather_values = row.find_elements(By.TAG_NAME, 'td')
                                date = weather_values[0].text

                                value = ""
                                for idx in range(1, len(weather_values)):
                                    if idx == len(weather_values) - 1:
                                        value += weather_values[idx].text
                                    elif idx % 3 == 0:
                                        value += weather_values[idx].text + "/"
                                    else:
                                        value += weather_values[idx].text + "-"
                                weather_dict[date] = value

                            # print(weather_dict)
                    weather_stations_list.append(weather_dict)
                    success = True
                    break
                except Exception as exc:
                    print(exc)
                    sleep(10)
                    driver.refresh()
                    sleep(30)

            if success != True:
                station_indices.remove(station)
                continue

    df = pandas.DataFrame(weather_stations_list, index=station_indices)
    df = df.to_csv(out_file, index = True)

weather_scraper(int(sys.argv[1]), int(sys.argv[2]), sys.argv[3])


#Created By Satrio Bintang (Alt5chm3rz)
#https://github.com/satriobintang
#March 2023

import string

class CaesarCipher:
    def __init__(self, shift):
        self.shift = shift
        self.alphabet_lower = string.ascii_lowercase
        self.alphabet_upper = string.ascii_uppercase
        self.alphabet = self.alphabet_lower + self.alphabet_upper

    def encrypt(self, text):
        encrypted_text = ''
        for char in text:
            if char in self.alphabet:
                char_index = self.alphabet.index(char)
                encrypted_index = (char_index + self.shift) % 26
                encrypted_char = self.alphabet[encrypted_index]
                encrypted_text += encrypted_char
            else:
                encrypted_text += char
        return encrypted_text

    def decrypt(self, text):
        decrypted_text = ''
        for char in text:
            if char in self.alphabet:
                char_index = self.alphabet.index(char)
                decrypted_index = (char_index - self.shift) % 26
                decrypted_char = self.alphabet[decrypted_index]
                decrypted_text += decrypted_char
            else:
                decrypted_text += char
        return decrypted_text

while True:
    try:
        shift = int(input('Enter the shift value (1-25): '))
        if not 1 <= shift <= 25:
            raise ValueError('Shift value must be between 1 and 25.')

        text = input('Enter the text to encrypt/decrypt: ')
        cipher = CaesarCipher(shift)
        encrypted_text = cipher.encrypt(text)
        decrypted_text = cipher.decrypt(encrypted_text)

        print(f'Original text: {text}')
        print(f'Encrypted text: {encrypted_text}')
        print(f'Decrypted text: {decrypted_text}')
        break
    except ValueError as e:
        print(e)

Encryption and Decryption Algorithms/Classic Algorithm/Algorithm_Classic_Caesar_Cipher.py


import abc
from dataclasses import dataclass
from pathlib import Path
import random
import re
import logging
from typing import Any, Callable, Dict, List, Optional, Tuple, Union

import numpy as np
import PIL.Image
import torch
import torchvision.transforms.functional as TF

from common_fate_object_learning import io_utils

LOGGER = logging.getLogger(__name__)

BACKGROUND = 0
OCCLUSION = 1
FOREGROUND = 2

class _SampleFrame(abc.ABC):
    @abc.abstractstaticmethod
    def from_path(path: Path, name: str) -> Any:
        raise NotImplementedError

    @abc.abstractmethod
    def is_valid(self) -> bool:
        raise NotImplementedError

    @abc.abstractmethod
    def load(self, size: int) -> Any:
        raise NotImplementedError

    def _get_padding(self, image_size: Tuple[int], target_size: int):
        width, height = image_size

        target_width = max(height*2, width + width % 2)
        target_height = target_width // 2
        assert target_height * 2 == target_width

        top_pad    = (target_height - height) // 2
        bottom_pad = target_height - height - top_pad
        left_pad   = (target_width - width) // 2
        right_pad  = target_width - width - left_pad

        return left_pad, top_pad, right_pad, bottom_pad

@dataclass
class _SampleFrameTraining(_SampleFrame):
    image_path: Path
    mask_path: Path

    @staticmethod
    def from_path(path: Path, name: str):
        return _SampleFrameTraining(
            path / f"{name}.image.png",
            path / f"{name}.mask.png"
        )

    def is_valid(self) -> bool:
        return self.image_path.is_file() and self.mask_path.is_file()

    def load(self, size: int = 32):
        image = io_utils.pil_loader(self.image_path, mode="RGB")
        mask = io_utils.pil_loader(self.mask_path, mode="L")

        padding = self._get_padding(image.size, size)

        image = TF.pad(image, padding=padding, padding_mode='edge')
        mask = TF.pad(mask, padding=padding, padding_mode='constant', fill=0)

        image = TF.to_tensor(TF.resize(image, size, PIL.Image.NEAREST))
        mask = torch.from_numpy(np.asarray(TF.resize(mask, size, PIL.Image.NEAREST))).long()

        return image, mask

@dataclass
class _SampleFrameValidation(_SampleFrame):
    sample_id: int
    object_id: int
    frame_id: int
    image_path: Path
    mask_path: Path
    target_image_path: Path
    target_mask_path: Path

    @staticmethod
    def from_path(path: Path, name: str):
        match = re.match(r".*sample(\d+)_object(\d+)/frame(\d+).*", str(path / name))
        if not match:
            LOGGER.warning("Warning: Unable to parse sample path: {}", path / name)
            sample_id = None
            object_id = None
            frame_id = None
        else:
            sample_id = int(match.group(1))
            object_id = int(match.group(2))
            frame_id = int(match.group(3))

        return _SampleFrameValidation(
            sample_id,
            object_id,
            frame_id,
            path / f"{name}.image.png",
            path / f"{name}.mask.png",
            path / f"{name}.image-full.png",
            path / f"{name}.mask-full.png",
        )

    def is_valid(self):
        return self.image_path.is_file() and \
               self.mask_path.is_file() and \
               self.target_image_path.is_file() and \
               self.target_mask_path.is_file()

    def load(self, size: int = 32):
        image = io_utils.pil_loader(self.image_path, mode="RGB")
        mask = io_utils.pil_loader(self.mask_path, mode="L")
        target_image = io_utils.pil_loader(self.target_image_path, mode="RGB")
        target_mask = io_utils.pil_loader(self.target_mask_path, mode="L")

        padding = self._get_padding(image.size, size)

        image = TF.pad(image, padding=padding, padding_mode='edge')
        image = TF.to_tensor(TF.resize(image, size, PIL.Image.NEAREST))

        mask = TF.pad(mask, padding=padding, padding_mode='constant', fill=0)
        mask = torch.from_numpy(np.asarray(TF.resize(mask, size, PIL.Image.NEAREST))).long()

        target_image = TF.pad(target_image, padding=padding, padding_mode='edge')
        target_image = TF.to_tensor(TF.resize(target_image, size, PIL.Image.NEAREST))

        target_mask = TF.pad(target_mask, padding=padding, padding_mode='constant', fill=0)
        target_mask = torch.from_numpy(np.asarray(TF.resize(target_mask, size, PIL.Image.NEAREST))).long()

        return {
            "sample_id": self.sample_id,
            "object_id": self.object_id,
            "frame_id": self.frame_id,
            "image": image,
            "mask": mask,
            "target_image": target_image,
            "target_mask": target_mask
        }

class ObjectDataset(torch.utils.data.Dataset):
    """Loads object crops with segmentation masks.

    This assumes the following file structure:
    ```
    dataset/sample<sample_id>_object<object_id>/frame<frame_id>.image.png
    dataset/sample<sample_id>_object<object_id>/frame<frame_id>.mask.png
    ```

    The `*.image.png` files are the cropped objects as RGB images, the
    `*.masks.png` are grayscale images defining the object masks using the
    following code:
    - 0 = background
    - 1 = other object
    - 2 = object of interest

    The length of this dataset is the number of objects. When retrieving an
    object, this will randomly sample the given number of frames for this object.
    """

    def __init__(self,
                 path: str,
                 num_frames_per_object: int = 1,
                 size: int = 32,
                 transform: Optional[Callable] = None,
                 load_evaluation_data: bool = False,
                 old_format: bool = False) -> None:
        """Initializes the data laoder

        Args:
            path: Path to the dataset.
            num_frames_per_object: Number of frames to load per object.
            size: Return samples resized and cropped to (size, size*2).
            transform: Optional transform to apply to images and masks.
            old_format: If set to true, the old data format is used
                without folders per object. Every (image,mask) pair is then
                interpreted as individual objects.
        """
        self._path = Path(path)
        self._num_frames_per_object = num_frames_per_object
        self.size = size
        self.transform = transform
        self._load_evaluation_data = load_evaluation_data
        self._old_format = old_format

        self._load_samples()

    def _load_samples(self) -> None:
        self._samples = []

        if self._old_format:
            # Old format = No subfolder per object
            # This will interprete every image pair as individual object
            if self._num_frames_per_object <= 1:
                self._samples = self._load_sample_frames(path)
                self._samples = [List[frame] for frame in self._samples]
            return

        for sample_path in self._path.iterdir():
            if sample_path.is_dir():
                frames = self._load_sample_frames(sample_path)

                if len(frames) > self._num_frames_per_object:
                    self._samples.append(frames)

    def _load_sample_frames(self, path: Path) -> List[_SampleFrame]:
        frames = []

        for image_path in path.glob("*.image.png"):
            name = image_path.name[:-len(".image.png")]

            if not self._load_evaluation_data:
                frame = _SampleFrameTraining.from_path(image_path.parent, name)
            else:
                frame = _SampleFrameValidation.from_path(image_path.parent, name)

            if frame.is_valid():
                frames.append(frame)

        return frames

    def __len__(self):
        """Returns the number of samples in this dataset."""
        return len(self._samples)

    def __getitem__(self, index):
        """Returns the sample with the given index."""
        frames = random.sample(self._samples[index], self._num_frames_per_object)
        frames = [frame.load(self.size) for frame in frames]

        if not self._load_evaluation_data:
            images = torch.stack([image for image, _ in frames])
            masks = torch.stack([mask for _, mask in frames])

            if self.transform is not None:
                return self.transform(images, masks)

            return images, masks

        else:
            stacked_frames = {}

            for key in frames[0].keys():
                stacked_frames[key] = torch.stack([
                    frame[key] if isinstance(frame[key], torch.Tensor) else torch.tensor(frame[key])
                    for frame in frames
                ])

            if self.transform is not None:
                stacked_frames["image"], stacked_frames["mask"] = \
                    self.transform(stacked_frames["image"], stacked_frames["mask"])

                stacked_frames["target_image"], stacked_frames["target_mask"] = \
                    self.transform(stacked_frames["target_image"], stacked_frames["target_mask"])

            return stacked_frames

class ObjectDatasetValidation(torch.utils.data.Dataset):
    def __init__(self,
                 path: Union[str, Path],
                 sample_size: int = 32,
                 transform: Optional[Callable] = None):
        self._path = Path(path)
        self.sample_size = sample_size
        self.transform = transform

        self._load_index()

    def _load_index(self) -> None:
        self._samples = []

        for sample_path in self._path.iterdir():
            if sample_path.is_dir():
                self._samples += self._load_sample_frames(sample_path)

    def _load_sample_frames(self, path: Path) -> List[_SampleFrameValidation]:
        frames = []

        for image_path in path.glob("*.image.png"):
            name = image_path.name[:-len(".image.png")]
            frame = _SampleFrameValidation.from_path(image_path.parent, name)

            if frame.is_valid():
                frames.append(frame)

        return frames

    def __len__(self) -> int:
        return len(self._samples)

    def __getitem__(self, index: int) -> Dict:
        frame = self._samples[index].load(self.sample_size)

        frame["image"] = frame["image"].unsqueeze(0)
        frame["mask"] = frame["mask"].unsqueeze(0)
        frame["target_image"] = frame["target_image"].unsqueeze(0)
        frame["target_mask"] = frame["target_mask"].unsqueeze(0)

        if self.transform is not None:
            frame["image"], frame["mask"] = \
                self.transform(frame["image"], frame["mask"])

            frame["target_image"], frame["target_mask"] = \
                self.transform(frame["target_image"], frame["target_mask"])

        return frame


#!/usr/bin/env python

import os.path as osp
import random

import cv2
import matplotlib.pyplot as plt
import pandas as pd

from src.mask_utils import rle2mask

class DataVisualizer(object):
    """This is data visualizer"""

    def __init__(self):
        self.root = './dataset/'
        self.df_path = osp.join(self.root, 'train.csv')
        self.train_path = osp.join(self.root, 'train_images/')
        self.df = pd.read_csv(self.df_path)
        self.columns = 1
        self.rows = 4

    def datasize(self):
        print('NUM DATA: {}'.format(self.df.shape[0]))

    def display(self):
        fig = plt.figure(figsize=(20, 20))
        df = self.df[self.df['EncodedPixels'].notnull()]
        df = df.pivot(index='ImageId',
                      columns='ClassId',
                      values='EncodedPixels')
        for i in range(1, self.columns * self.rows + 1):
            idx = random.randint(0, len(self.df) - 1)
            fig.add_subplot(self.rows, self.columns, i)

            image_id, mask = rle2mask(idx, df)
            img_path = osp.join(self.train_path, image_id)
            img = cv2.imread(img_path)
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            for ch in range(mask.shape[-1]):
                if mask[:, :, ch].any():
                    idx = ch
            mask = mask[:, :, idx]
            img[mask == 1, 0] = 255
            plt.imshow(img)
            plt.axis('off')
        plt.show()
        plt.close()

def main():
    visualizer = DataVisualizer()
    visualizer.datasize()
    visualizer.display()

if __name__ == '__main__':
    main()


import hashlib
from aiogram import types, Dispatcher
from create_connection_file import dp, bot
from aiogram.types import InputTextMessageContent, InlineQueryResultArticle

# @dp.inline_handler()
async def inline_handler(query: types.InlineQuery):
    text = query.query or "echo"
    link = 'https://en.wikipedia.org/wiki/' + text
    result_id: str = hashlib.md5(text.encode()).hexdigest()

    articles = [
        types.InlineQueryResultArticle(
            id=result_id,
            title='Page of Wikipedia',
            url=link,
            input_message_content=types.InputTextMessageContent(message_text=link))]
    await query.answer(articles, cache_time=1, is_personal=True)

def register_inline_handler(dp: Dispatcher):
    dp.register_inline_handler(inline_handler)


size1 = int(input())
students1 = input().split()
size2 = int(input())
students2 = input().split()
missed = []
notingroup = []

check1 = False

for i in students1:
    for j in students2:
        if i == j:
            check1 = True
    if check1 == False:
        missed.append(i)
    check1 = False

check2 = False
for i in students2:
    for j in students1:
        if i == j:
            check2 = True
    if check2 == False:
        notingroup.append(i)
    check2 = False

print("Missed students:")
for i in missed:
    print('- '+i)
print("Not in the group:")
for i in notingroup:
    print('- '+i)


import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px

token = open(".mapbox_token").read() # you will need your own token

df = px.data.election()
geojson = px.data.election_geojson()
candidates = df.winner.unique()

app = dash.Dash(__name__)

app.layout = html.Div([
    html.P("Candidate:"),
    dcc.RadioItems(
        id='candidate',
        options=[{'value': x, 'label': x}
                 for x in candidates],
        value=candidates[0],
        labelStyle={'display': 'inline-block'}
    ),
    dcc.Graph(id="choropleth"),
])

@app.callback(
    Output("choropleth", "figure"),
    [Input("candidate", "value")])
def display_choropleth(candidate):
    fig = px.choropleth_mapbox(
        df, geojson=geojson, color=candidate,
        locations="district", featureidkey="properties.district",
        center={"lat": 45.5517, "lon": -73.7073}, zoom=9,
        range_color=[0, 6500])
    fig.update_layout(
        margin={"r":0,"t":0,"l":0,"b":0},
        mapbox_accesstoken=token)

    return fig

if __name__ == "__main__":
    app.run_server(debug=True)


'''
'http://www.buscacep.correios.com.br/sistemas/buscacep/resultadoBuscaCepEndereco.cfm'
sistemas/buscacep/resultadoBuscaCepEndereco.cfm
'''

from urllib.parse import urlencode
from urllib.request import Request, urlopen

def semEspacoXml(s):
    s = s.replace('&lt', '<')
    s = s.replace('&gt', '>')
    s = s.replace('&amp', '&')
    s = s.replace('&nbsp', ' ')
    return s

def semCaracteresEsp(s):
    s = s.replace('\\r', '')
    s = s.replace('\\t', '')
    s = s.replace('\\n', '')
    return s

def mostraCEP(dic,chave):
    if chave in dic:
        return dic[chave]
    else:
        return False

url = 'http://www.buscacep.correios.com.br/sistemas/buscacep/resultadoBuscaCepEndereco.cfm'
postFields = {'relaxation': '70040010', 'tipoCEP': 'ALL', 'semelhante': 'N'}
request = Request(url, urlencode(postFields).encode())
result = urlopen(request).read()
result = str(result)

#   retira caracteres 'estranhos' e corrige acentuação:
result = semCaracteresEsp(result)
result = bytes(result, 'iso-8859-1').decode('unicode_escape')
result = semEspacoXml(result)

#   busca a primeira posição requisitada e 'limpa' o código
busca = 'CEP:	'
pos = int(result.index(busca) + len(busca))
result = result[pos: pos + 200]

#   separa a Rua
buscaInicio = ''
buscaFinal = ';	<td width='
posInicio = int(result.index(buscaInicio) + len(buscaFinal))
posFinal = int(result.index(buscaFinal))
resultRua = result[posInicio: posFinal]

#   separa o Bairro
buscaInicio = ''
buscaFinal = ''
posInicio = int(result.index(buscaInicio) + len(buscaFinal))
posFinal = int(result.index(buscaFinal))
resultBairro = result[posInicio: posFinal - 6]

#   separa a Cidade
buscaInicio = ''
buscaFinal = ''
posInicio = int(result.index(buscaInicio) + len(buscaFinal))
posFinal = int(result.index(buscaFinal))
resultCidade = result[posInicio: posFinal - 5]

#   resultado da busca por CEP:
print('-+'*25)
print('Informações sobre o CEP:', mostraCEP(postFields,'relaxation'))
print('Logradouro:', resultRua)
print('Bairro:', resultBairro)
print('Cidade/Estado:', resultCidade)


from odoo import api, fields, models
from odoo.exceptions import UserError
import logging
_logger = logging.getLogger(__name__)

class MrpProduction(models.Model):
    _inherit = 'mrp.production'

    flsp_qty_backflushed = fields.Float(string="Qty Backflushed")

    def open_produce_product(self):
        self.ensure_one()
        self.action_assign()
        res = super(MrpProduction, self).open_produce_product()
        #if self.product_id.tracking in ['none', 'lot']:
            # needs the total quantity
        raw_moves = self.env['stock.move'].search([('raw_material_production_id', '=', self.id)])
        for move in raw_moves:
            if move.flsp_backflush:
                qtt_to_wip = move.product_uom_qty - move.reserved_availability
                if qtt_to_wip > 0:
                    self.create_wip_qty(move.product_id, qtt_to_wip)
                    self.action_assign()
#        else:
#            # needs only qty to produce 1
            #            raw_moves = self.env['stock.move'].search([('raw_material_production_id', '=', self.id)])
            #for move in raw_moves:
                    #                if move.flsp_backflush:
                    #qtt_to_wip = move.product_uom_qty - move.reserved_availability
                    #if qtt_to_wip > 0:
                        #                        self.create_wip_qty(move.product_id, 1)
                        #self.action_assign()
        return res

    def button_mark_done(self):
        self.ensure_one()
        self.action_assign()
        backflush_qty = self.product_qty - self.flsp_qty_backflushed
        self.new_backflush_flsp(backflush_qty)
        self.flsp_qty_backflushed = self.product_qty
        res = super(MrpProduction, self).button_mark_done()
        return res

    def post_inventory(self):
        self.ensure_one()
        self.action_assign()
        self.backflush_partials_flsp()
        res = super(MrpProduction, self).post_inventory()
        return res

    def backflush_partials_flsp(self):

        stock_move_done = self.env['stock.move'].search(
        ['&', '&', '&', ('product_id', '=', self.product_id.id),
                        ('production_id', '=', self.id),
                        ('is_done', '=', True),
                        ('scrapped', '=', False)])
        total_backflushable = 0
        for move in stock_move_done:
            total_backflushable += move.product_qty

        if self.flsp_qty_backflushed:
            total_to_backflush = total_backflushable - self.flsp_qty_backflushed
        else:
            total_to_backflush = total_backflushable

        self.new_backflush_flsp(total_to_backflush)
        if self.flsp_qty_backflushed:
            self.flsp_qty_backflushed += total_to_backflush
        else:
            self.flsp_qty_backflushed = total_to_backflush

    def new_backflush_flsp(self, backflush_qty=0):

        wip_location = self.env['stock.location'].search([('complete_name', '=', 'WH/PA/WIP')])
        stock_virtual_location = self.env['stock.location'].search([('complete_name', '=', 'Virtual Locations/My Company: Inventory adjustment')])
        virtual_production_location = self.env['stock.location'].search([('complete_name', '=', 'Virtual Locations/My Company: Production')])
        stock_picking_type = self.env['stock.picking.type'].search([('sequence_code', '=', 'INT')])
        pa_location = self.env['stock.location'].search([('complete_name', '=', 'WH/PA')]).parent_path
        pa_wip_locations = self.env['stock.location'].search([('parent_path', 'like', pa_location+'%')]).ids
        if not stock_picking_type:
            raise UserError('Picking type Internal is missing')
        if not stock_virtual_location:
            raise UserError('Stock Virtual Location is missing')
        if not virtual_production_location:
            raise UserError('Stock Virtual Production is missing')
        if not wip_location:
            raise UserError('WIP Stock Location is missing')
        if not pa_location:
            raise UserError('WIP Stock Location is missing')
        if not pa_wip_locations:
            raise UserError('WIP Stock Location is missing')

        ## Check if backflush is already done
        if backflush_qty <= 0:
            backflush_qty = self.product_qty - self.flsp_qty_backflushed
        if backflush_qty <= 0:
            return

        ## Verifing quantities of components in PA/WIP if available move the quantity needed on MO to virtual production:
        bom_components = self._get_flattened_totals(self.bom_id, backflush_qty)
        stock_picking = False
        for prod in bom_components:
            if bom_components[prod]['level'] == 1:
                continue
            if prod.type in ['service', 'consu']:
                continue
            if bom_components[prod]['total'] <= 0:
                continue

            if not stock_picking:
                create_val = {
                    'origin': self.name + ' FLSP-Backflush',
                    'picking_type_id': stock_picking_type.id,
                    'location_id': wip_location.id,
                    'location_dest_id': virtual_production_location.id,
                    'state': 'assigned',
                }
                stock_picking = self.env['stock.picking'].create(create_val)
            tracking = False
            wip_lot = {}
            if prod.tracking != 'none':
                tracking = prod.tracking
                ## Need to check if the quantity is available in WIP, if it is not do not transfer.
                stock_wip = self.env['stock.quant'].search(['&', ('product_id', '=', prod.id), ('location_id', 'in', pa_wip_locations)])
                qty_needed = bom_components[prod]['total']
                pa_wip_qty = 0
                for stock_lin in stock_wip:
                    pa_wip_qty += stock_lin.quantity
                qty_needed = bom_components[prod]['total']
                if qty_needed > pa_wip_qty:
                    qtt = qty_needed - pa_wip_qty
                    self.create_wip_qty(prod, qtt)
                    stock_wip = self.env['stock.quant'].search(['&', ('product_id', '=', prod.id), ('location_id', 'in', pa_wip_locations)])

                for lot in stock_wip:
                    if lot.quantity > 0:
                        if lot.quantity - qty_needed >= 0:
                            wip_lot[lot.lot_id] = {'qty': qty_needed, 'location': lot.location_id}
                            qty_needed = 0
                            break
                        else:
                            wip_lot[lot.lot_id] = {'qty': lot.quantity, 'location': lot.location_id}
                            qty_needed -= lot.quantity
                # In case we don't have the total quantity available will create a lot 999999_000000
                if qty_needed > 0:
                    if prod.tracking == 'lot':
                        new_lot = self.create_lot(prod, 1)
                        if new_lot:
                            wip_lot[new_lot[0]] = {'qty': qty_needed, 'location': wip_location}
                    else:
                        new_lot = self.create_lot(prod, int(qty_needed))
                        for lot in new_lot:
                            wip_lot[lot] = {'qty': 1, 'location': wip_location}
            else:
                qty_needed = bom_components[prod]['total']
                pa_wip_qty = 0
                stock_wip = self.env['stock.quant'].search(['&', ('product_id', '=', prod.id), ('location_id', 'in', pa_wip_locations)])
                for stock_lin in stock_wip:
                    pa_wip_qty += stock_lin.quantity
                qty_needed = bom_components[prod]['total']

                if qty_needed > pa_wip_qty:
                    qtt = qty_needed - pa_wip_qty
                    self.create_wip_qty(prod, qtt)
                    stock_wip = self.env['stock.quant'].search(['&', ('product_id', '=', prod.id), ('location_id', 'in', pa_wip_locations)])

            stock_move = self.env['stock.move'].create({
                'name': prod.name,
                'product_id': prod.id,
                'product_uom': prod.uom_id.id,
                'product_uom_qty': bom_components[prod]['total'],
                'picking_id': stock_picking.id,
                'location_id': wip_location.id,
                'location_dest_id': virtual_production_location.id
            })
            if tracking:
                for lot in wip_lot:
                    move_line = self.env['stock.move.line'].create({
                        'product_id': prod.id,
                        'product_uom_id': prod.uom_id.id,
                        'qty_done': wip_lot[lot]['qty'],
                        'lot_id': lot.id,
                        'picking_id': stock_picking.id,
                        'move_id': stock_move.id,
                        'location_id': wip_lot[lot]['location'].id,
                        'location_dest_id': virtual_production_location.id,
                        'state': 'assigned',
                        'done_move': True,
                    })
            else:
                move_line = self.env['stock.move.line'].create({
                    'product_id': prod.id,
                    'product_uom_id': prod.uom_id.id,
                    'qty_done': bom_components[prod]['total'],
                    #'lot_id': line.lot_id.id,
                    'picking_id': stock_picking.id,
                    'move_id': stock_move.id,
                    'location_id': wip_location.id,
                    'location_dest_id': virtual_production_location.id,
                    'state': 'assigned',
                    'done_move': True,
                })
        if stock_picking:
            stock_picking.button_validate()

    def _get_flattened_totals(self, bom, factor=1, totals=None, level=None):
        """Calculate the **unitary** product requirements of flattened BOM.
        *Unit* means that the requirements are computed for one unit of the
        default UoM of the product.
        :returns: dict: keys are components and values are aggregated quantity
        in the product default UoM.
        """
        if level is None:
            level = 1
        if totals is None:
            totals = {}
        factor /= bom.product_uom_id._compute_quantity(
            bom.product_qty, bom.product_tmpl_id.uom_id, round=False
        )
        for line in bom.bom_line_ids:
            # check if the product is consumable and backflushed, skip breaking it down in backflush if it is
            if line.product_id and line.product_id.type == 'consu' and line.product_id.flsp_backflush:
                continue

            sub_bom = bom._bom_find(product=line.product_id)
            if sub_bom:
                if not line.product_tmpl_id.flsp_backflush:
                    if totals.get(line.product_id):
                        totals[line.product_id]['total'] += (
                            factor
                            * line.product_uom_id._compute_quantity(
                                line.product_qty, line.product_id.uom_id, round=False
                            )
                        )
                    else:
                        totals[line.product_id] = {'total':(
                            factor
                            * line.product_uom_id._compute_quantity(
                                line.product_qty, line.product_id.uom_id, round=False
                            )
                        ), 'level': level, 'bom': sub_bom.code}
                    continue
                else:
                    new_factor = factor * line.product_uom_id._compute_quantity(
                        line.product_qty, line.product_id.uom_id, round=False
                    )

                level += 1
                self._get_flattened_totals(sub_bom, new_factor, totals, level)
                level -= 1
            else:
                if totals.get(line.product_id):
                    totals[line.product_id]['total'] += (
                        factor
                        * line.product_uom_id._compute_quantity(
                            line.product_qty, line.product_id.uom_id, round=False
                        )
                    )
                else:
                    totals[line.product_id] = {'total':(
                        factor
                        * line.product_uom_id._compute_quantity(
                            line.product_qty, line.product_id.uom_id, round=False
                        )
                    ), 'level': level, 'bom': ''}
        return totals

    def create_lot(self, prod, qty):
        ret = []
        company_id = self.env.company.id
        self._cr.execute("select max(name) as code from stock_production_lot where name like '999999%' ")
        retvalue = self._cr.fetchall()
        returned_registre = retvalue[0]
        latest_lot = returned_registre[0]
        if latest_lot:
            next_lot = ('00000'+str(int(latest_lot[-5:])+1))[-5:]
        else:
            next_lot = '00001'
        for x in range(0,qty):
            lot = self.env['stock.production.lot'].create({
                'name': '999999_'+next_lot,
                'product_id': prod.id,
                'ref': 'Backflush Adjust',
                'company_id': company_id,
            })
            next_lot = ('00000' + str(int(next_lot[1:6]) + 1))[-5:]
            ret.append(lot)
        return ret

    def create_wip_qty(self, prod, qty):
        wip_location = self.env['stock.location'].search([('complete_name', '=', 'WH/PA/WIP')])
        stock_virtual_location = self.env['stock.location'].search([('complete_name', '=', 'Virtual Locations/My Company: Inventory adjustment')])
        stock_picking_type = self.env['stock.picking.type'].search([('sequence_code', '=', 'INT')])
        if qty <= 0:
            return
        prod.flsp_bf_check = True
        if prod.tracking == 'none':
            create_val = {
                 'origin': self.name + ' FLSP-BF-ADJUST',
                 'picking_type_id': stock_picking_type.id,
                 'location_id': stock_virtual_location.id,
                 'location_dest_id': wip_location.id,
                 'state': 'assigned',}
            stock_picking = self.env['stock.picking'].create(create_val)
            stock_move = self.env['stock.move'].create({
                     'name': prod.name,
                     'product_id': prod.id,
                     'product_uom': prod.uom_id.id,
                     'product_uom_qty': qty,
                     'picking_id': stock_picking.id,
                     'location_id': stock_virtual_location.id,
                     'location_dest_id': wip_location.id,
                     'state': 'assigned',
                 })
            move_line = self.env['stock.move.line'].create({
                     'product_id': prod.id,
                     'product_uom_id': prod.uom_id.id,
                     'qty_done': qty,
                     'picking_id': stock_picking.id,
                     'move_id' : stock_move.id,
                     'location_id': stock_virtual_location.id,
                     'location_dest_id': wip_location.id,
                     'state': 'assigned',
                     'done_move': True,
                 })
            stock_picking.button_validate()
        elif prod.tracking == 'lot':
            new_lot = self.create_lot(prod, 1)
            create_val = {
                 'origin': self.name + ' FLSP-BF-ADJUST',
                 'picking_type_id': stock_picking_type.id,
                 'location_id': stock_virtual_location.id,
                 'location_dest_id': wip_location.id,
                 'state': 'assigned',}
            stock_picking = self.env['stock.picking'].create(create_val)
            stock_move = self.env['stock.move'].create({
                     'name': prod.name,
                     'product_id': prod.id,
                     'product_uom': prod.uom_id.id,
                     'product_uom_qty': qty,
                     'picking_id': stock_picking.id,
                     'location_id': stock_virtual_location.id,
                     'location_dest_id': wip_location.id,
                     'state': 'assigned',
                 })
            move_line = self.env['stock.move.line'].create({
                     'product_id': prod.id,
                     'product_uom_id': prod.uom_id.id,
                     'qty_done': qty,
                     'picking_id': stock_picking.id,
                     'move_id' : stock_move.id,
                     'lot_id': new_lot[0].id,
                     'location_id': stock_virtual_location.id,
                     'location_dest_id': wip_location.id,
                     'state': 'assigned',
                     'done_move': True,
                 })
            stock_picking.button_validate()
        else:
            new_lot = self.create_lot(prod, int(qty))
            create_val = {
                 'origin': self.name + ' FLSP-BF-ADJUST',
                 'picking_type_id': stock_picking_type.id,
                 'location_id': stock_virtual_location.id,
                 'location_dest_id': wip_location.id,
                 'state': 'assigned',}
            stock_picking = self.env['stock.picking'].create(create_val)
            stock_move = self.env['stock.move'].create({
                     'name': prod.name,
                     'product_id': prod.id,
                     'product_uom': prod.uom_id.id,
                     'product_uom_qty': qty,
                     'picking_id': stock_picking.id,
                     'location_id': stock_virtual_location.id,
                     'location_dest_id': wip_location.id,
                     'state': 'assigned',
                 })
            for lot in new_lot:
                move_line = self.env['stock.move.line'].create({
                         'product_id': prod.id,
                         'product_uom_id': prod.uom_id.id,
                         'qty_done': 1,
                         'picking_id': stock_picking.id,
                         'move_id': stock_move.id,
                         'lot_id': lot.id,
                         'location_id': stock_virtual_location.id,
                         'location_dest_id': wip_location.id,
                         'state': 'assigned',
                         'done_move': True,
                     })
            stock_picking.button_validate()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Mar 10 17:29:54 2023

@author: johnmorgan
"""

class UnionFind:
    def __init__(self, grid):
        self.parent = []
        self.rank = []
        self.count = 0
        row_ct = len(grid)
        col_ct = len(grid[0])
        for i in range(row_ct):
            for j in range(col_ct):
                if grid[i][j] == 1:
                    self.parent.append(i * row_ct + j)
                    self.count += 1
                else:
                    self.parent.append(-1)
                self.rank.append(0)

    def find(self, i):
        if self.parent[i] != i:
            self.parent[i] = self.find(self.parent[i])
        return self.parent[i]

    def union(self, x, y):
        root_x = self.find(x)
        root_y = self.find(y)
        if root_x != root_y:
            if self.rank[root_x] > self.rank[root_y]:
                self.parent[root_y] = root_x
            elif self.rank[root_x] < self.rank[root_y]:
                self.parent[root_x] = root_y
            else:
                self.parent[root_y] = root_x
                self.rank[root_x] += 1
            self.count -= 1

    def get_count(self):
        return self.count

uf = UnionFind([[1, 0], [0, 1]])


# coding=utf-8
import os
import json
import logging
import subprocess

from ajenti.api import *
from ajenti.plugins.main.api import SectionPlugin
from ajenti.ui import on
from ajenti.ui.binder import Binder

from templates import config_templates

config_dirs = {
    'main': '/etc/fail2ban/',
    'jails': '/etc/fail2ban/jail.d/',
    'actions': '/etc/fail2ban/action.d/',
    'filters': '/etc/fail2ban/filter.d/',
    'extra': '/etc/fail2ban/fail2ban.d/'
}

config_file_types = ('.conf', '.local')

# fail2ban:
#     configurations=
#             [
#                 f2b_configs:
#                     name=
#                     path=
#                     confillist=
#                         f2b_list:
#                             path=
#                             type=
#                             __list__=
#                                     f2b_config:
#                                         name=
#                                         configfile=
#                                         config=
#
#             ]

class f2b_Config(object):
    def __init__(self, name, path):
        self.name = name
        self.path = path
        self.configfile = os.path.join(path, name)
        self.config = ''

    def __repr__(self):
        return json.dumps({'name': self.name, 'configfile': self.configfile, 'config': self.config})

    def save(self):
        self.configfile = os.path.join(self.path, self.name)
        try:
            open(self.configfile, 'w').write(self.config)
            return self
        except IOError as e:
            logging.error(e.message)

    def update(self):
        self.configfile = os.path.join(self.path, self.name)
        self.config = ''.join((open(self.configfile).readlines()))
        return self

class f2b_Configs(object):
    def __init__(self, name, path):
        self.name = name
        self.path = path
        self.configlist = f2b_list(path=path, type=name)
        self.configlist.path = self.path

    def update(self):
        for filename in os.listdir(self.path):
            try:
                cf = os.path.join(self.path, filename)
                if os.path.isfile(cf) and (os.path.splitext(filename)[-1] in config_file_types):
                    self.configlist.append(f2b_Config(filename, self.path).update())
            except IOError as e:
                logging.error('Error reading file {0} in {1}.'.format(filename, self.path))
        self.configlist.sort(key=lambda k: k.name)
        return self

class f2b_list(list):
    def __init__(self, path='', type=''):
        self.path = path
        self.type = type

@plugin
class fail2ban(SectionPlugin):
    def init(self):
        self.title = 'fail2ban'
        self.icon = 'shield'
        self.category = _('Software')
        self.f2b_v = subprocess.check_output(['fail2ban-client', '--version']).splitlines()[0]
        self.append(self.ui.inflate('fail2ban:main'))
        self.binder = Binder(self, self)
        self.update_status = True

        def on_config_update(o, c, config, u):
            if config.__old_name != config.name:
                if os.path.exists(os.path.join(c.path, config.name)):
                    self.context.notify('error', _(
                        'File with name {0} already exists in {1}.').format(config.name, c.path))
                    self.update_status = False
                    config.name = config.__old_name
                    return
                logging.debug('renamed config file %s to %s' % (config.__old_name, config.name))
                os.unlink(config.configfile)
            config.save()
            self.update_status = True

        def on_config_bind(o, c, config, u):
            config.__old_name = config.name

        def new_config(c):
            new_fn = 'untitled{0}.conf'
            s_fn = new_fn.format('')
            filename = os.path.join(c.path, s_fn)
            i = 1
            while os.path.exists(filename):
                s_fn = new_fn.format('_' + str(i))
                filename = os.path.join(c.path, s_fn)
                i += 1
            try:
                logging.debug('add config %s' % filename)
                conf = f2b_Config(s_fn, c.path)
                conf.config = config_templates[c.type]
                return conf.save()
            except IOError as e:
                print('Error writing file {0} in {1}'.format(filename, c.path))

        def delete_config(config, c):
            filename = config.configfile
            logging.debug('removed config %s' % config.configfile)
            c.remove(config)
            os.unlink(filename)

        self.find('configlist').post_item_update = on_config_update
        self.find('configlist').post_item_bind = on_config_bind
        self.find('configlist').new_item = new_config
        self.find('configlist').delete_item = delete_config

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.configurations = [
            f2b_Configs(k, d).update()
            for k, d in config_dirs.iteritems()
            if os.path.isdir(d)
        ]
        self.binder.setup(self).populate()

    @on('save-button', 'click')
    def save(self):
        self.binder.update()
        if self.update_status:
            self.context.notify('info', _('Saved'))
        self.update_status = True
        self.binder.setup(self).populate()

    @on('check-regex', 'click')
    def check_regex(self):
        self.find('check-status').text = ''
        log_fname = self.find('log-filename').value
        filter_fname = self.find('filter-filename').value
        log_as_text = self.find('log-file').value
        filter_as_text = self.find('filter-file').value
        if not (log_fname or log_as_text) or not (filter_fname or filter_as_text):
            logging.debug('Filter checker. Some parameters are empty.')
            self.context.notify('error', _('Some parameters are empty.'))
            return

        with open(filter_fname + '.tmp', 'w') as rt:
            rt.write(self.find('filter-file').value)
            rt_name = rt.name
            rt.close()

        p = subprocess.Popen(['fail2ban-regex', '--full-traceback', log_fname, rt_name], stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT)
        out, err = p.communicate()
        self.find('check-status').text = out

        os.unlink(rt_name)

    @on('open-filter-button', 'click')
    def open_filter(self):
        self.find('openfilterdialog').show()

    @on('openfilterdialog', 'button')
    def on_open_filter_dialog(self, button):
        self.find('openfilterdialog').visible = False

    @on('openfilterdialog', 'select')
    def on_filter_file_select(self, path=None):
        if not path:
            return
        self.find('openfilterdialog').visible = False
        self.find('filter-filename').value = path
        self.find('filter-file').value = ''.join(open(path).readlines())

    @on('open-log-button', 'click')
    def open_log(self):
        self.find('openlogdialog').show()

    @on('openlogdialog', 'button')
    def on_open_log_dialog(self, button):
        self.find('openlogdialog').visible = False

    @on('openlogdialog', 'select')
    def on_log_file_select(self, path=None):
        if not path:
            return
        self.find('openlogdialog').visible = False
        self.find('log-filename').value = path
        self.find('log-file').value = ''.join(open(path).readlines())

    @on('save-filter-button', 'click')
    def save_filter(self):
        try:
            open(self.find('filter-filename').value, 'w').write(self.find('filter-file').value)
        except IOError as e:
            self.context.notify('error', _('Could not save config file. %s') % str(e))
            logging.error(e.message)


k = int(input())
length = []
total_width = 0
total_height = 0

for i in range(6):
    a, b = map(int, input().split())
    length.append((a,b))

while True:
    if length[0][0] == length[2][0] and length[1][0] == length[3][0]:
        length = length[0:4]
        break
    else:
        length.append(length.pop(0))

for i in range(4):
    if length[i][0] == 1 or length[i][0] == 2:
        total_width += length[i][1]
    elif length[i][0] == 3 or length[i][0] == 4:
        total_height += length[i][1]

area = total_width * total_height - length[1][1] * length[2][1]
total = k * area

print(total)


"""Tests for precision control.
"""

import unittest
import pytest

import numpy as np
from pyscf import gto, scf

from ebcc import REBCC, UEBCC, GEBCC, NullLogger

@pytest.mark.regression
class REBCC_Precision_Tests(unittest.TestCase):
    """Test single-precision REBCC against double-precision results.
    """

    basis = "cc-pvdz"
    EBCC = REBCC

    @classmethod
    def setUpClass(cls):
        mol = gto.Mole()
        mol.atom = "Li 0 0 0; H 0 0 1.64"
        mol.basis = cls.basis
        mol.verbose = 0
        mol.build()

        mf = scf.RHF(mol)
        mf.conv_tol = 1e-12
        mf.kernel()

        cls.mol, cls.mf = mol, mf

    @classmethod
    def tearDownClass(cls):
        del cls.mol, cls.mf

    def test_ansatzes(self):
        for ansatz in [
            "CC2",
            "CCSD",
            "CC3",
            "QCISD",
        ]:
            sp = self.EBCC(self.mf, ansatz=ansatz, log=NullLogger())
            sp.e_tol = 1e-7
            sp.t_tol = 1e-4
            sp.kernel()

            dp = self.EBCC(self.mf, ansatz=ansatz, log=NullLogger())
            dp.e_tol = 1e-8
            dp.t_tol = 1e-5
            dp.kernel()

            self.assertAlmostEqual(sp.e_tot, dp.e_tot, 6)

@pytest.mark.regression
class UEBCC_Precision_Tests(REBCC_Precision_Tests):
    """Test single-precision UEBCC against double-precision results.
    """

    basis = "cc-pvdz"
    EBCC = UEBCC

@pytest.mark.regression
class GEBCC_Precision_Tests(REBCC_Precision_Tests):
    """Test single-precision GEBCC against double-precision results.
    """

    basis = "sto3g"
    EBCC = GEBCC

if __name__ == "__main__":
    print("Tests for precision")
    unittest.main()


import keras
from keras import Sequential
from keras.layers import Embedding,LSTM,Dense,Dropout,SimpleRNN,TimeDistributed,InputLayer,Activation
from tensorflow.python.keras.preprocessing.sequence import pad_sequences
import sys
import numpy as np
from sklearn.metrics import confusion_matrix
# Data Paths
trainFile = '../output/aspectTrain.txt'
testFile = '../output/aspectTest.txt'
goldFile = '../data/aspectTerm.txt'
devFile = '../output/aspectDev'

outPath = "../output/"
trainPath = outPath+"parseProcessedTrain.txt"
testPath = outPath+"parseProcessedTestLabel.txt"

# Hyperparameters
windowSize = 20

# Function for reading a file
def readFile(filPath):
    fil = open(filPath)
    vec = fil.readlines()
    fil.close()
    return vec

def extractWindow(aspectTerm,wordList):
    aspectTermWords = aspectTerm.split(' ')
    aspectSize = len(aspectTermWords)
    remWindowSize = windowSize-aspectSize

    startIndex = 0
    for idx,word in enumerate(wordList):
        if aspectTermWords[0] in word:
            startIndex = idx
            break

    windowStart = max(0,startIndex - int(remWindowSize/2))
    windowEnd = min(startIndex+aspectSize+int(remWindowSize/2),len(wordList))
    window = wordList[windowStart:windowEnd]

    return ' '.join(window)

def createMapping():
    vec = readFile(goldFile)
    mapper = {}
    invmapper = {}
    vec = [ele.strip().split('#')[1] for ele in vec]
    vec = [ele.split(' ') for ele in vec]
    counter = 0
    for sent in vec:
        for word in sent:
            if word not in mapper:
                mapper[word] = counter
                invmapper[counter] = word
                counter+=1

    return mapper,invmapper

# Function to read gold labels
def extractGoldLabels():
    vec1 = readFile(goldFile)
    vec1 = [ele.strip().split('#') for ele in vec1]
    labelDict = {}
    for ele in vec1:
        if ele[-1] == '':
            continue
        labelList = ele[-2].split('&')
        labelDict[ele[0]] = labelList
    return labelDict

def extractData(filPath,mapper,train=True):
    vec1 = readFile(filPath)
    vec1 = [ele.strip().split('#') for ele in vec1]

    Data = []
    Labels = []
    if not train:
        labelDict = extractGoldLabels()
    for ele in vec1:
        if ele[-1] == '':
            continue
        aspectTermList = ele[-1].split('&')
        if train:
            labelList = ele[-2].split('&')
        wordList = ele[1].split(' ')
        for aspectIdx,aspectTerm in enumerate(aspectTermList):
            window = extractWindow(aspectTerm,wordList)
            # print(window)
            indices = []
            for curElement in window.split(" "):
                if curElement in mapper:
                    indices.append(mapper[curElement])
                else:
                    indices.append(0)
                    print(curElement)
                    print(window)
                    sys.exit()
            # indices = [mapper[ele] for ele in window]
            Data.append(indices)
            if train:
                label = labelList[aspectIdx]
            else:
                label = labelDict[ele[0]][aspectIdx]

            if label == 'pos':
                Labels.append(np.array([1,0,0]))
            elif label == 'neg':
                Labels.append(np.array([0,1,0]))
            else:
                Labels.append(np.array([0,0,1]))

    if train:
        return Data,np.array(Labels)
    else:
        return Data,np.array(Labels)

def readData(dataPath,mapper):
    vec = readFile(dataPath)
    data = []
    point = []
    labelpoint = []
    labels = []

    for ele in vec:
        if (ele=='\n'):
            data.append(point)
            labels.append(np.array(labelpoint))
            point = []
            labelpoint = []
            continue
        curPoint = ele.strip().split("\t")
        if curPoint[1] in mapper:
            point.append(mapper[curPoint[1]])
        else:
            point.append(0)
        if curPoint[-1] == 'TRUE':
            labelpoint.append([1,0])
        else:
            labelpoint.append([0,1])

    return data,np.array(labels)

def runSent():
    mapper,invmapper = createMapping()
    num_words = len([ele for ele in mapper])

    #model
    model = Sequential()
    model.add(Embedding(num_words, 100, input_length=20))
    model.add(LSTM(50))
    model.add(Dropout(0.5))
    model.add(Dense(3, activation='softmax'))
    model.compile(loss='categorical_crossentropy',optimizer='adam', metrics=['categorical_accuracy'])
    print(model.summary())

    trainData,trainLabels = extractData(trainFile,mapper,True)
    testData,goldLabels = extractData(testFile,mapper,False)

    trainPad = pad_sequences(trainData,maxlen=20,padding='post')
    testPad = pad_sequences(testData,maxlen=20,padding='post')

    model.fit(trainPad,trainLabels,batch_size=32,epochs=10,validation_data=(testPad,goldLabels),verbose=2)

def runATE():
    mapper,invmapper = createMapping()
    num_words = len([ele for ele in mapper])

    trainData,trainLabels = readData(trainPath,mapper)
    testData,testLabels = readData(testPath,mapper)

    # print(trainData)
    # print(testData)

    MAX_LENGTH = len(max(trainData, key=len))

    #model
    model = Sequential()
    # model.add(InputLayer(input_shape=(MAX_LENGTH, )))
    model.add(Embedding(num_words, 10))
    model.add(LSTM(16,input_shape=(MAX_LENGTH, 10),return_sequences=True))
    # model.add(Dropout(0.5))
    model.add(TimeDistributed(Dense(2)))
    model.add(Activation('softmax'))
    # model.add(Dense(3, activation='softmax'))
    model.compile(loss='categorical_crossentropy',optimizer='adam')
    print(model.summary())

    trainPad = pad_sequences(trainData,maxlen=MAX_LENGTH,padding='post')
    testPad = pad_sequences(testData,maxlen=MAX_LENGTH,padding='post')
    trainLabelsPad = pad_sequences(trainLabels,maxlen=MAX_LENGTH,padding='post')
    testLabelsPad = pad_sequences(testLabels,maxlen=MAX_LENGTH,padding='post')

    model.fit(trainPad,trainLabelsPad,batch_size=32,epochs=20,validation_data=(testPad,testLabelsPad),verbose=2)
    predictions = model.predict(testPad)
    TP,FP,FN,TN = 0,0,0,0
    for idx,predict in enumerate(predictions):
        gold = testLabelsPad[idx]
        for jdx,goldTag in enumerate(gold):
            if (goldTag[0] == 0) and (goldTag[1] == 0):
                break
            if goldTag[0] == 1:
                if predict[jdx][0]>=predict[jdx][1]:
                    TP+=1
                else:
                    FN+=1
            else:
                if predict[jdx][0]>=predict[jdx][1]:
                    FP+=1
                else:
                    TN+=1
    print(TP,FP,TN,FN)
    print("Recall",TP/(TP+FN))
    print("Precision",TP/(TP+FP))
    print("Accuracy",(TP+TN)/(TP+TN+FP+FN))
    # print(confusion_matrix(predictions.argmax(axis=1),testPad.argmax(axis=1)))

runSent()


#!/usr/bin/python3
"""
This module provides a function to indent text based on punctuation marks.

The `text_indentation` function takes a string `text` as input and splits it into lines, indenting each line after a question mark, exclamation mark, or period.

Args:
    text (str): The text to be indented.

Raises:
    TypeError: If `text` is not a string.
"""

def text_indentation(text):
    """splits a text into lines along "?", ":", "." followed by 2 new lines"""
    if type(text) is not str:
        raise TypeError("text must be a string")
    flag = 0
    for a in text:
        if flag == 0:
            if a == ' ':
                continue
            else:
                flag = 1
        if flag == 1:
            if a == '?' or a == '.' or a == ':':
                print(a)
                print()
                flag = 0
            else:
                print(a, end="")


# 18 - Faça um programa que peça o tamanho de um arquivo para download (em MB) e a velocidade de um link de Internet
#     (em Mbps), calcule e informe o tempo aproximado de download do arquivo usando este link (em minutos).

arquivo = float(input("Informe o tamanho do arquivo (em MB): "))
internet = float(input("Informe a velocidade da internet (em Mbps): "))

tempoSeg = arquivo / (internet / 8)
tempoMin = tempoSeg / 60

print("O tempo aproximado de download é de ", tempoMin, "minutos")


import networkx as nx
import matplotlib.pyplot as plt
from art import text2art

print("========================================================================")
print(text2art("Grafo Boys", font="small"))
print("                                    2023 Grafoboys™. All rights reserved")
print("========================================================================")

# Pergunta se o grafo é direcionado
is_dirigido = input("O grafo é direcionado? (s/n): ").lower() == 's'

# Pergunta se o grafo é valorado
is_valorado = input("O grafo é valorado? (s/n): ").lower() == 's'

# Cria o grafo correspondente ao tipo
if is_dirigido:
    grafo = nx.DiGraph()
else:
    grafo = nx.Graph()

# Solicita a entrada de vértices
print("\nDigite os vertices do grafo: ")
while(True):
    v = input()
    if not v:
        break
    grafo.add_node(v)

# Solicita a entrada de arestas
print("\nDigite as arestas do grafo(x y peso): ")
while(True):
    a = input()
    if not a:
        break

    a1, a2, *peso = a.split()
    peso = float(peso[0]) if peso else 1.0

    if is_valorado:
        grafo.add_edge(a1, a2, weight=peso)
    else:
        grafo.add_edge(a1, a2)

# Imprime o grafo
pos = nx.spring_layout(grafo)
labels = nx.get_edge_attributes(grafo, 'weight')
nx.draw_networkx_nodes(grafo, pos, node_color='r', node_size=500)
nx.draw_networkx_edges(grafo, pos, edge_color='b', arrows=True)
nx.draw_networkx_labels(grafo, pos, font_size=20, font_family='sans-serif')
nx.draw_networkx_edge_labels(grafo, pos, edge_labels=labels, font_size=16)
plt.axis('off')
plt.show()

# Imprime ordem e tamanho do grafo
print("Ordem do grafo:", grafo.order())
print("Tamanho do grafo:", grafo.size())

# Imprime os vértices adjacentes a cada vértice
for v in grafo.nodes():
    print("Vértices adjacentes a", v, ":", list(grafo.neighbors(v)))

# Solicita a entrada de um vértice para imprimir o grau
print("\nDigite um vertice: ")
while(True):
    v = input()
    if not v:
        break
    print("Grau do vértice ", v,": ", grafo.degree(v))
    print("Lista de vértices adjacentes a", v, ": ")
    if is_dirigido:
        print("Entrada:", list(grafo.predecessors(v)))
        print("Saída:", list(grafo.successors(v)))
    else:
        print(list(grafo.neighbors(v)))
    print("\nDigite um vertice: ")

# Solicita a entrada de um par de vértices para imprimir se eles são adjacentes, menor caminho e custo do menor caminho
while(True):
    print("\nDigite um par vertices(x y): ")
    print("(Ou digite 'finalizar' para ver o raio e diâmetro):")

    v = input()
    if v.lower() == "finalizar":
        break

    v1, v2 = v.split()

    # Verifica se são adjacentes
    if grafo.has_edge(v1, v2):
        print("O vértice", v1, "é adjacente ao vértice", v2)
    else:
        print("O vértice", v1, "não é adjacente ao vértice", v2)
    if not is_dirigido:
        if nx.has_path(grafo, v1, v2):
            menor_caminho = nx.shortest_path(grafo, source=v1, target=v2, weight='weight') if is_valorado else nx.shortest_path(grafo, source=v1, target=v2)
            print("Menor caminho entre os vértices: ", str(menor_caminho))

            custo_menor_caminho = nx.shortest_path_length(grafo, source=v1, target=v2, weight='weight')
            print("Peso do menor caminho entre os vértices: ", custo_menor_caminho)
        else:
            print("Não  há caminho entre os vértices!")
    else:
        if nx.has_path(grafo.reverse(), v2, v1):
            menor_caminho = nx.shortest_path(grafo, source=v1, target=v2, weight='weight') if is_valorado else nx.shortest_path(grafo, source=v1, target=v2)
            print("Menor caminho entre os vértices: ", menor_caminho)

            custo_menor_caminho = nx.shortest_path_length(grafo, source=v1, target=v2, weight='weight')
            print("Peso do menor caminho entre os vértices: ", custo_menor_caminho)
        else:
            print("Não  há caminho entre os vértices!")

    # Calcula o menor caminho e o custo do menor caminho (caso o grafo seja valorado)

# Calcula e imprime o raio e o diâmetro do grafo
try:
    raio = nx.radius(grafo)
except nx.NetworkXError:
    print ("O grafo tem raio infinito!")

try:
    diametro = nx.diameter(grafo)
except nx.NetworkXError:
        print ("O grafo tem diâmetro infinito!")


import signal
import argparse
import _thread
import azure_download
import ftp_download
from queue import Queue

import time
import os

def get_args():
	parser = argparse.ArgumentParser()
	parser.description = argparse.ArgumentParser(description='span args command:')
	parser.add_argument("--storage_name", type=str, help="my storagename")
	parser.add_argument("--storage_key", type=str, help="my storagekey")
	parser.add_argument("--span_path", type=str, help="span file path")
	parser.add_argument("--base", type=str, help="is download base data",choices=['yes','no'])
	parser.add_argument("--ephemeris", type=str, help="is download ephemeris data",choices=['yes','no'])
	return parser.parse_args()

def set_cmd_para():
    args = get_args()

    para_dict = {"storage_name": "","storage_key": "","span_path": "","base": "","ephemeris":""}
    if args.storage_name == None:
        print ("please input your storage name")
        storage_name = input()
    else:
        storage_name = args.storage_name
    para_dict["storage_name"] = storage_name
    if args.storage_key == None:
        print ("please input your storage key")
        storage_key = input()
    else:
        storage_key = args.storage_key
    para_dict["storage_key"] = storage_key
    if args.span_path == None:
        print ("please input your span path")
        span_path = input()
    else:
        span_path = args.span_path
    para_dict["span_path"] = span_path

    if args.base == None:
        print ("is download base data? yes or no")
        base_download = input()
    else:
        base_download = args.base
    para_dict["base"] = base_download

    if args.ephemeris == None:
        print ("is download ephemeris data? yes or no")
        ephemeris_download = input()
    else:
        ephemeris_download = args.ephemeris
    para_dict["ephemeris"] = ephemeris_download
    return para_dict

def kill_app(signal_int,call_back):
    print ('exit app')
    os.kill(os.getpid(),signal.SIGINT)

if __name__ == '__main__':
	signal.signal(signal.SIGINT,kill_app)
	para_dict = set_cmd_para()
	print (para_dict)
	base_run_queue = Queue(maxsize=1000)
	ephemeris_run_queue = Queue(maxsize=1000)

	if para_dict["ephemeris"] == 'yes':
		_thread.start_new_thread(ftp_download.ephemeris_download,("ephemeris_thread",para_dict["span_path"],ephemeris_run_queue))
	if para_dict["base"] == 'yes':
		_thread.start_new_thread(azure_download.base_download,("base_thread",para_dict["span_path"],para_dict["storage_name"],para_dict["storage_key"],base_run_queue))

	base_queue_mes = ''
	ephemeris_queue_mes = ''
	base_run_flag = False
	ephemeris_run_flag = False
	if para_dict["ephemeris"] == 'no':
		ephemeris_run_flag = True
	if para_dict["base"] == 'no':
		base_run_flag = True
	while True:
		try:
			base_queue_mes = base_run_queue.get_nowait()
		except:
			pass
		try:
			ephemeris_queue_mes = ephemeris_run_queue.get_nowait()
		except:
			pass
		if(ephemeris_queue_mes == 'ftp_end'):
			ephemeris_run_flag = True
			print(ephemeris_queue_mes)
		if(base_queue_mes == 'azure_end'):
			base_run_flag = True
			print(base_queue_mes)
		if(ephemeris_run_flag == True) and (base_run_flag == True):
			print("exit")
			exit()
		time.sleep(5)


#! /usr/bin/python2.7
# -*- coding: utf-8 -*-

import numpy as np

np.set_printoptions(formatter={'int': lambda x: "0x{:02X}".format(x)},
                    linewidth=84)

if __name__ == "__main__":
    rnd_data_8bit = np.random.randint(0, 256, (24, )).astype(np.uint8)
    print("rnd_data_8bit:\n{}".format(rnd_data_8bit))

    with open("some_random_data.hex", "wb") as fout:
        rnd_data_8bit.tofile(fout)

    with open("some_random_data.hex", "rb") as fin:
        read_data = np.fromfile(fin, dtype=np.uint8, count=24)

    print("read_data:\n{}".format(read_data))


from selenium.webdriver.support.wait import WebDriverWait
from AppiumFramework.base.BasePage import BasePage
import AppiumFramework.utilities.CustomLogger as CL

"""
This page contains locators and methods related to Contact Us Form
such as enter text, click on submit buttons and validate entered text
"""

class EnterSomeValuePage(BasePage):

    _enterSomeValueField = '//android.widget.EditText[@resource-id="com.code2lead.kwad:id/Et1"]'
    _submitBtn = '//android.widget.Button[@resource-id="com.code2lead.kwad:id/Btn1"]'

    def __init__(self, driver):
        super().__init__(driver)
        self.driver = driver
        self.wait = WebDriverWait(self.driver, 15, poll_frequency=.5)

    def validateContactUsFormLandingPage(self):
        assert True == self.isDisplayed(self._enterSomeValueField)
        CL.allureLogs("Contact Us Form Page Reached Successfully")
        self.takeScreenshot(ssSection="EnterSomeValueLandingPage")

    def enterSomeValueText(self, textToEnter):
        self.sendKeys(textToEnter, self._enterSomeValueField)
        self.log(f"{textToEnter}, entered correclty on field", True)
        # CL.allureLogs(f"{textToEnter} entered Successfully on enter some value field")
        self.takeScreenshot(ssSection="EnterSomeValueData")

    def clickSubmitBtn(self):
        self.clickElement(self._submitBtn)
        CL.allureLogs("Submit button clicked successfully on entersome value section")

    def validateSubmittedText(self, textToVAlidate):
        assert True == self.isDisplayed(textToVAlidate, "text")
        self.log(f"{textToVAlidate} has been submitted correctly", True)
        CL.allureLogs(f"{textToVAlidate} has been submitted correctly")


""" Scraping from JSM """
import csv
from bs4 import BeautifulSoup #pylint: disable=E0401
import requests #pylint: disable=E0401

source = requests.get('https://jsmliving.com/search-available-units', timeout=10).text

soup = BeautifulSoup(source, 'lxml')
AVAIL_UNITS = 0

with open('JSM_scraped_info.csv', 'w', encoding='utf8') as csv_file:
    csv_writer = csv.writer(csv_file)
    csv_writer.writerow(['Address', 'Rent', 'Bedrooms', 'Bathrooms'])

    for article in soup.find_all('article'):
        rent = article.find('div', class_ = "unit__card-rent").text
        if "No Units Available" in rent:
            break
        rent2 = rent.split(':')

        AVAIL_UNITS += 1
        # print(avail_units)
        # address = article.find('div',
        # class_= "field field--name-field-building field--type-entity-reference
        # field--label-hidden field--item").a.text
        address = article.h4.a.text
        # print(address)

        print(rent2[1].strip())

        bed = article.find('div', class_ = 'unit__card-bedrooms').p.text
        # print(bed)

        bath = article.find('div', class_ = 'unit__card-bathrooms').p.text
        # print(bath)
        # print("--------")
        csv_writer.writerow([address, rent2[1].strip(), bed, bath])


import streamlit as st
from st_clickable_images import clickable_images
import pandas as pd
from pytube import YouTube
import os
import requests
from time import sleep

upload_endpoint = "https://api.assemblyai.com/v2/upload"
transcript_endpoint = "https://api.assemblyai.com/v2/transcript"

headers = {
    "authorization": st.secrets["auth_key"],
    "content-type": "application/json"
}

@st.experimental_memo
def save_audio(url):
    yt = YouTube(url)
    video = yt.streams.filter(only_audio=True).first()
    out_file = video.download()
    base, ext = os.path.splitext(out_file)
    file_name = base + '.mp3'
    os.rename(out_file, file_name)
    print(yt.title + " has been successfully downloaded.")
    print(file_name)
    return yt.title, file_name, yt.thumbnail_url

@st.experimental_memo
def upload_to_AssemblyAI(save_location):
    CHUNK_SIZE = 5242880
    print(save_location)

    def read_file(filename):
        with open(filename, 'rb') as _file:
            while True:
                print("chunk uploaded")
                data = _file.read(CHUNK_SIZE)
                if not data:
                    break
                yield data

    upload_response = requests.post(
        upload_endpoint,
        headers=headers, data=read_file(save_location)
    )
    print(upload_response.json())

    audio_url = upload_response.json()['upload_url']
    print('Uploaded to', audio_url)

    return audio_url

@st.experimental_memo
def start_analysis(audio_url):
    print(audio_url)

    ## Start transcription job of audio file
    data = {
        'audio_url': audio_url,
        'iab_categories': True,
        'content_safety': True,
        "summarization": True,
        "summary_type": "bullets"
    }

    transcript_response = requests.post(transcript_endpoint, json=data, headers=headers)
    print(transcript_response)

    transcript_id = transcript_response.json()['id']
    polling_endpoint = transcript_endpoint + "/" + transcript_id

    print("Transcribing at", polling_endpoint)
    return polling_endpoint

@st.experimental_memo
def get_analysis_results(polling_endpoint):

    status = 'submitted'

    while True:
        print(status)
        polling_response = requests.get(polling_endpoint, headers=headers)
        status = polling_response.json()['status']
        # st.write(polling_response.json())
        # st.write(status)

        if status == 'submitted' or status == 'processing' or status == 'queued':
            print('not ready yet')
            sleep(10)

        elif status == 'completed':
            print('creating transcript')

            return polling_response

            break
        else:
            print('error')
            return False
            break

st.title("YouTube Content Analyzer")
st.markdown("With this app you can audit a Youtube channel to see if you'd like to sponsor them. All you have to do is to pass a list of links to the videos of this channel and you will get a list of thumbnails. Once you select a video by clicking its thumbnail, you can view:")
st.markdown("1. a summary of the video,")
st.markdown("2. the topics that are discussed in the video,")
st.markdown("3. whether there are any sensitive topics discussed in the video.")
st.markdown("Make sure your links are in the format: https://www.youtube.com/watch?v=HfNnuQOHAaw and not https://youtu.be/HfNnuQOHAaw")

default_bool = st.checkbox("Use a default file")

if default_bool:
    file = open("./links.txt")
else:
    file = st.file_uploader("Upload a file that includes the links (.txt)")

if file is not None:
    dataframe = pd.read_csv(file, header=None)
    dataframe.columns = ['urls']
    urls_list = dataframe['urls'].tolist()

    titles = []
    locations = []
    thumbnails = []

    for video_url in urls_list:
        # download audio
        video_title, save_location, video_thumbnail = save_audio(video_url)
        titles.append(video_title)
        locations.append(save_location)
        thumbnails.append(video_thumbnail)

    selected_video = clickable_images(thumbnails,
    titles = titles,
    div_style={"height": "400px", "display": "flex", "justify-content": "center", "flex-wrap": "wrap", "overflow-y":"auto"},
    img_style={"margin": "5px", "height": "150px"}
    )

    st.markdown(f"Thumbnail #{selected_video} clicked" if selected_video > -1 else "No image clicked")

    if selected_video > -1:
        video_url = urls_list[selected_video]
        video_title = titles[selected_video]
        save_location = locations[selected_video]

        st.header(video_title)
        st.audio(save_location)

        # upload mp3 file to AssemblyAI
        audio_url = upload_to_AssemblyAI(save_location)

        # start analysis of the file
        polling_endpoint = start_analysis(audio_url)

        # receive the results
        results = get_analysis_results(polling_endpoint)

        summary = results.json()['summary']
        topics = results.json()['iab_categories_result']['summary']
        sensitive_topics = results.json()['content_safety_labels']['summary']

        st.header("Summary of this video")
        st.write(summary)

        st.header("Sensitive content")
        if sensitive_topics != {}:
            st.subheader('ðŸš¨ Mention of the following sensitive topics detected.')
            moderation_df = pd.DataFrame(sensitive_topics.items())
            moderation_df.columns = ['topic','confidence']
            st.dataframe(moderation_df, use_container_width=True)

        else:
            st.subheader('âœ… All clear! No sensitive content detected.')

        st.header("Topics discussed")
        topics_df = pd.DataFrame(topics.items())
        topics_df.columns = ['topic','confidence']
        topics_df["topic"] = topics_df["topic"].str.split(">")
        expanded_topics = topics_df.topic.apply(pd.Series).add_prefix('topic_level_')
        topics_df = topics_df.join(expanded_topics).drop('topic', axis=1).sort_values(['confidence'], ascending=False).fillna('')

        st.dataframe(topics_df)