import datetime
import logging
import os
import re
import xmltodict
import unicodedata

import pyudev
import requests
import requests_cache

from .utils import is_dvd, is_blu_ray

requests_cache.install_cache(backend='memory')
logger = logging.getLogger(__name__)

def search_tmdb(movie):
    logger.info("Searching TMDB for the movie release year")

    session = requests.session()
    session.params.update({
        'api_key': os.environ['TMDB_API_KEY'],
        'query': movie
    })
    session.headers.update({
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    })

    resp = session.get('https://api.themoviedb.org/3/search/movie')
    if resp.status_code != 200:
        logger.error(f"TMDB query failed with response\n"
                     f"{resp.status_code}: {resp.reason}")
    return resp.json()

def get_tmdb_year(movie):
    results = search_tmdb(movie)
    if results['total_results'] == 0:
        logger.info("Did not find any results.")
        year = ""
    elif results['total_results'] > 1:
        logger.info("Found multiple results.")
        year = ""
    else:
        logger.info("Found exactly 1 result.")
        movie = results['results'][0]
        release_date = movie['release_date']
        year = datetime.datetime.strptime(release_date, '%Y-%m-%d').year

    return year

def get_movie_year(movie):
    year = get_tmdb_year(movie)
    if not year:
        year = get_omdb_year(movie)
    return year

def clean_blu_ray_title(title):
    title = (unicodedata.normalize('NFKD', title)
             .encode('ascii', 'ignore')
             .decode())
    tm = chr(8482)
    title = re.sub(r" - (Blu\-rayTM|BLU\-RAYTM|BLU\-RAY|Blu\-ray)", "", title)
    title = re.sub(tm, "", title)
    return title

def clean_title_for_search(title):
    return re.sub("_", " ", title)

def get_blu_ray_title(path):
    fname = f'{path}/BDMV/META/DL/bdmt_eng.xml'
    if not os.path.exists(fname):
        logger.info("Metadata XML not in expected location.")
        return ''

    with open(fname, 'rb') as xml_file:
        doc = xmltodict.parse(xml_file.read())

    title = doc['disclib']['di:discinfo']['di:title']['di:name']
    # TODO: Test a unicode title
    title = clean_blu_ray_title(title)

    return title

def _fetch_omdb(params):
    session = requests.session()
    session.params.update({
        'apikey': os.environ['OMDB_API_KEY'],
        'plot': 'short',
        'r': 'json',
        **params
    })
    logger.info("Querying OMDB.")
    resp = session.get('https://www.omdbapi.com/')

    if resp.status_code != 200:
        logger.error(f"OMDB query failed with response\n"
                     "{resp.status_code}: {resp.reason}")
        resp.raise_for_status()

    return resp.json()

def search_omdb(title):
    return _fetch_omdb({
        's': title
    })

def get_omdb(title, year):
    return _fetch_omdb({
        't': title,
        'y': year
    })

def get_omdb_year(title):
    logger.info("Attempting to get year from OMDB.")
    result = get_omdb(title, '')
    if result['Response'] == 'True':
        logger.info("Found exact title.")
        return result['Year']

    logger.info("Searching OMDB.")
    result = search_omdb(title)
    if result['Response'] == 'True':
        if result['totalResults'] == '1':
            logger.info("Found exactly 1 result.")
            return result['Search'][0]['Year']
        else:
            logger.info("Found multiple results.")
            return ''
    else:
        logger.info("Found no search results.")

def get_media_type(title, year=''):
    results = get_omdb(title, year)
    response = results['Response']
    if response == 'False' and year:
        error = results['Error']
        logger.info(f'Title {title} and year {year} not found.\n'
                    f'Error: {error}\nRetrying without year')
        return get_media_type(title, '')
    elif response == 'False':
        logger.info(f"Title {title} not found.")
    elif response == 'True':
        return results['Type']
    else:
        logger.error(f"Unhandled response\n{results}")

def get_title(path):
    if is_dvd(path):
        logger.info("Found DVD")
        logger.info("No reliable way to find DVD title")
        logger.info("Consider using libdvdnav")
        title = ''
    elif is_blu_ray(path):
        logger.info("Found Blu-Ray")
        title = get_blu_ray_title(path)
        if not title:
            logger.info("Failed to get Blu-Ray title from disc")
    else:
        msg = "Did not find a video on the device"
        logger.error(msg)
        raise ValueError(msg)

    return title

def identify(device_name, mount_point):
    assert 'TMDB_API_KEY' in os.environ
    assert 'OMDB_API_KEY' in os.environ

    logger.info("Identifying disk")
    context = pyudev.Context()

    # this is probably /dev/sr0 or something. Don't need the 'dev'
    device = pyudev.Devices.from_name(
        context,
        'block',
        device_name.split('/')[-1]
    )
    id_fs_type = device.get('ID_FS_TYPE')

    if id_fs_type != 'udf':
        # if it's 'iso9660, then a data rip might work.
        raise ValueError(f"Expected 'udf' for FS type. Got {id_fs_type}")

    title = get_title(mount_point)
    if not title:
        logger.info("Getting title from ID_FS_LABEL")
        title = device.get('ID_FS_LABEL')
        logger.info(f"ID_FS_LABEL: {title}")

    title = clean_title_for_search(title)
    year = get_movie_year(title)

    logger.info(f"Title: '{title}'; Year: {year}")

    # TODO: it's possible that this could find a new year for the title
    video_type = get_media_type(title, year)

    logger.info("Done with identification.")
    logger.info(f"Title: '{title}'; Year: {year}; Video Type: {video_type}")
    return title, year, video_type


from datetime import date

# print(date.today())

print("Today's date is:" + str(date.today()))

# cambiar a años luz

parsecs = 11
lightyears = parsecs * 3.26
print(str(parsecs) + " parsecs is " + str(lightyears) + " lightyears")


import numpy as np
import pandas as pd
from scipy.interpolate import interp1d
from scipy.interpolate import interp2d
from scipy.misc import derivative
import astropy.units as u
import astropy.constants as c
from astropy.cosmology import FlatLambdaCDM, z_at_value
from tqdm import *
from astropy.cosmology import Planck13 as cosmo
from astropy import constants as const
import sys
import matplotlib.pyplot as plt
import matplotlib.pylab as pylab
import tools
from scipy.integrate import quad
from scipy.integrate import fixed_quad
from scipy.integrate import romberg
import PS
import tools

zzmin = 0.001
zzmax = 30.001
zzbins = 301

def read_ps(filename):
    h = cosmo.h
    tbl = np.loadtxt(filename)
    z_vect = np.linspace(zzmin, zzmax, zzbins)
    k_vect = tbl[:,0]
    matrix = tbl[:,1:]
    return z_vect, k_vect*h, matrix/(h**3)

def ps_interp(z,k,matrix,z_vect,k_vect):
    if (z < np.min(z_vect) or (z > np.max(z_vect)) or (k < np.min(k_vect)) or (k > np.max(k_vect)) ):
        return 0.
    ind_z_low, ind_z_up = tools.find_nearest(z_vect,z)
    ind_k_low, ind_k_up = tools.find_nearest(k_vect,k)
    z_low = z_vect[ind_z_low]
    z_up = z_vect[ind_z_up]
    k_low = k_vect[ind_k_low]
    k_up = k_vect[ind_k_up]
    if ((matrix[ind_k_low, ind_z_low] <= 0.) or (matrix[ind_k_up, ind_z_low] <=0 ) or (matrix[ind_k_low, ind_z_up] <=0) or (matrix[ind_k_up, ind_z_up] <=0)):
        return 0.
    else:
        ps_z_low = 10.**tools.lininterp(k, k_low, k_up, np.log10(matrix[ind_k_low, ind_z_low]), np.log10(matrix[ind_k_up,ind_z_low]))
        ps_z_up = 10.**tools.lininterp(k, k_low, k_up,np.log10(matrix[ind_k_low, ind_z_up]), np.log10(matrix[ind_k_up,ind_z_up]))
    return tools.lininterp(z,z_low,z_up,ps_z_low,ps_z_up)

NIRB_ps_path = "./NIRB_PS/"
ps1h=read_ps(NIRB_ps_path + "PS_GALl_1h.dat")
ps2h=read_ps(NIRB_ps_path + "PS_GALl_2h.dat")

def PS2(z, k):
    return ps_interp(z ,k , ps1h[2] + ps2h[2], ps1h[0], ps1h[1])

class LowGal:
    def __init__(self):
        """
        Container class to compute various quantities for low-z Galaxy as studied here --> https://arxiv.org/pdf/1201.4398.pdf

        """

        # Set constants
        self.fromHztoeV = 6.58e-16
        self.gramstoeV = 1 / ( 1.78 * 1e-33)
        self.mtoev = 1/(1.97 * 1e-7)
        self.H0 = cosmo.H(0).value * 1e3 / (1e3 * const.kpc.value) #expressed in 1/s
        self.rhocritical = cosmo.critical_density(0).value * self.gramstoeV /(1e-2)**3 # eV/m**3
        self.Om0 = cosmo.Om0 #total matter
        self.OLambda0 = cosmo.Ode0  # cosmological constant
        self.DM0 = self.Om0 - cosmo.Ob0 # dark matter
        self.evtonJoule = 1.60218 * 1e-10 # from eV to nJ
        self.evtoJoule = 1.60218 * 1e-19 # from eV to J
        self.h  = 0.6766
        self.Mpc = 1e3 * const.kpc.value
        self.zmin = 0.001
        self.zmax = 30.001
        self.zbins = 301
        self.h = cosmo.h
        self.lambda_eff = np.array([0.15,0.36,0.45,0.55,0.65,0.79,0.91,1.27,1.63,2.20,3.60,4.50])
        self.Mstar0_vect = np.array([-19.62,-20.20,-21.35,-22.13,-22.40,-22.80,-22.86,-23.04,-23.41,-22.97,-22.40,-21.84])
        self.q_vect = np.array([1.1,1.0,0.6,0.5,0.5,0.4,0.4,0.4,0.5,0.4,0.2,0.3])
        self.phistar0_vect = np.array([2.43,5.46,3.41,2.42,2.25,2.05,2.55,2.21,1.91,2.74,3.29,3.29])
        self.p_vect = np.array([0.2,0.5,0.4,0.5,0.5,0.4,0.4,0.6,0.8,0.8,0.8,0.8])
        self.alpha0_vect = np.array([-1.,-1.,-1.,-1.,-1.,-1.,-1.,-1.,-1.,-1.,-1.,-1.])
        self.r_vect = np.array([0.086,0.076,0.055,0.060,0.070,0.070,0.060,0.035,0.035,0.035,0.035,0.035])
        self.zmax_vect = np.array([8.0,4.5,4.5,3.6,3.0,3.0,2.9,3.2,3.2,3.8,0.7,0.7])

    def fnu(self, m):
        """
        Specific flux in micro Jansky, as in Eq.2 of --> 1201.4398. Function of the magnitude m
        """
        return 10**(-0.4*(m -23.9))

    def Absolute(self, m,z):
        # Pass from apparent to absolute magnitude, as in Eq. 8. Achtung, the log needs to be in basis 10
        return m - cosmo.distmod(z).value + 2.5 * np.log10(1+z)

    def Ms(self,z,q,Mstarz0):
        return Mstarz0 - 2.5*np.log10((1+(z-0.8))**q) #Eq.3

    def phis(self,z,p,phistar0):
        return phistar0*np.exp(-p*(z-0.8))*1e-3 # Eq.4

    def alphaMe(self,z,r,alpha0):
        return alpha0*(z/0.01)**r # Eq. 5

    def phi_star_highz(self,z):
        return 1.e-3*1.14*10.**(0.003*(z-3.8))

    def Mshighz(self,z):

        return self.Ms(3.8,self.q_vect[0],self.Mstar0_vect[0]) + 0.33*(z-3.8) # modified to match

    def MsUV(self, z,q,Mstarz0):
        if z > 3.8:
            return self.Mshighz(z)
        else:
            return self.Ms(z,q,Mstarz0)

    def alphahighz(self, z):
        """
        function that computes alpha at high redshift (z>3.8), defined as in Section 7.5 of Bowens et al. 2003, ApJ 737
        """
        return self.alphaMe(3.8,self.r_vect[0],self.alpha0_vect[0]) - 0.018*(z-3.8)

    def Msobs(self, lobs,z):
        lambdaemission = lobs / (1 + z)
        indice = np.argmin(np.abs(lambdaemission - self.lambda_eff))
        if indice==0 and z > 3.8:
            return self.Mshighz(z)
        else:
            return self.Ms(z,q_vect[indice],Mstar0_vect[indice])

    def PhiObs(self, lobs, m , z):
        M = self.Absolute(m,z)
        exponent = 0.4 * (self.Msobs(lobs,z) - M )
        return 0.4 * np.log(10) * self.phisobs(lobs,z) * (10**exponent) ** (self.alpha0obs(lobs,z) + 1) * np.exp(-10**exponent)

    def PhiMe(self, z,m,phistar0,p,Mstarz0,q,alpha0,r):
        M = M = self.Absolute(m,z)
        exponent = 0.4 * (self.Ms(z,q,Mstarz0) - M )
        return 0.4*np.log(10)*self.phis(z,p,phistar0)* (10**exponent) ** (self.alphaMe(z,r,alpha0) + 1) * np.exp(-10**exponent)

    def PhiMeHigh(self, z,m):
        M = self.Absolute(m,z)
        exponent = 0.4 * (self.Mshighz(z) - M )
        return 0.4*np.log(10)*self.phi_star_highz(z)* (10**exponent) ** (self.alphahighz(z) + 1) * np.exp(-10**exponent)

    # Now we define the functions with input the observed wavelength (to be passed in micron)

    def phisobs(self,lobs,z):

        lambdaemission = lobs / (1 + z)
        indice = np.argmin(np.abs(lambdaemission - self.lambda_eff))

        if indice ==0 and z > 3.8:

            return self.phi_star_highz(z)

        else:
            return self.phis(z,self.p_vect[indice],self.phistar0_vect[indice])

    def PhiObsMe2(self, lambda_obs,m,z):

        z_vect = lambda_obs/self.lambda_eff - 1.
        phi_vect = np.zeros(len(z_vect)) + 1.e-30
        ind_gt0 = np.where(z_vect > 0)[0]
        ind_eq0 = np.where(z_vect == 0)[0]
        phi_vect[ind_gt0] = np.array([self.PhiMe(z_vect[i],m,self.phistar0_vect[i],self.p_vect[i],self.Mstar0_vect[i],self.q_vect[i],self.alpha0_vect[i],self.r_vect[i]) for i in ind_gt0])
        phi_vect[ind_eq0] = self.PhiMe(0.01,m,self.phistar0_vect[ind_eq0],self.p_vect[ind_eq0],self.Mstar0_vect[ind_eq0],self.q_vect[ind_eq0],self.alpha0_vect[ind_eq0],self.r_vect[ind_eq0])
        if (z_vect[0] >= 4.):
            phi_vect[0] = self.PhiMeHigh(z_vect[0],m)
        if ((z > z_vect[0]) or (z < z_vect[-1])):
            return 1.e-30
        else:
            ind_low,ind_high = tools.find_nearest(z,z_vect)
        #if ((z_vect[ind_low] <= 0) or (z_vect[ind_high] <=0)) :
        #    return 0.
        #else:
        return tools.lininterp(z,z_vect[ind_low],z_vect[ind_high],phi_vect[ind_low],phi_vect[ind_high])

    def alpha0obs(self,lobs,z):

        lambdaemission = lobs / (1 + z)
        indice = np.argmin(np.abs(lambdaemission - self.lambda_eff))

        if indice==0 and z > 3.8:
            return self.alpha_highz(z)
        else:
            return self.alphaMe(z,self.r_vect[indice],self.alpha0_vect[indice])

    def Msobs(self, lobs,z):
        lambdaemission = lobs / (1 + z)
        indice = np.argmin(np.abs(lambdaemission - self.lambda_eff))
        if indice==0 and z > 3.8:
            return self.MsUV(z,self.q_vect[0],self.Mstar0_vect[0])
        else:
            return self.Ms(z,self.q_vect[indice],self.Mstar0_vect[indice])

    def LF(self, lobs, m , z): # Luminosity function as in Eq. 6 of the paper
        M = self.Absolute(m,z)
        exponent = 0.4 * (self.Msobs(lobs,z) - M )
        return 0.4 * np.log(10) * self.phisobs(lobs,z) * (10**exponent) ** (self.alpha0obs(lobs,z) + 1) * np.exp(-10**exponent)

    def E(self, z):
        return cosmo.H(z).value/cosmo.H(0).value

    def dVdz(self, z):
        dH0 = (1e-3 * const.c.value/cosmo.H(0).value)
        return cosmo.comoving_distance(z).value**2 * dH0/self.E(z)

    def Nuz(self, lambdaobs, m, z):
        return self.PhiObsMe2(lambdaobs, m , z) * self.dVdz(z)

    def dFdz(self, lobs, mlim, z): # Returned in nW/m^2/sr, the 10^-32 comes from the micro-Jansky, the 1e-9 from the nano-Watt
        if z > 8:
            return 0
        else:
            def integrand(m):

                return const.c.value / (lobs * 1e-6) * self.Nuz(lobs,m, z) * self.fnu(m) * 1e-32 / 1e-9

        return quad(integrand,mlim,65)[0]

    def WindowGal(self, lobs,mlim,z): # nW/m^2/sr/Mpc ---> H/c dF/dz
        c_km = 1e-3 * const.c.value
        return cosmo.H(z).value/c_km * self.dFdz(lobs, mlim, z)

    def IntermediatePsNoise(self,lobs, mlim, z):
        marray = np.arange(mlim,60,0.5)
        integrand_array= np.array([self.Nuz(lobs, m, z) * (const.c.value / (lobs * 1e-6) * self.fnu(m) * 1e-32 / 1e-9)**2 for m in marray])
        return np.trapz(integrand_array,marray)

    def PSnoise(self, lobs, mlim):

        #z_vec = np.logspace(-3, 0.7, 30)
        z_vec = np.logspace(np.log10(0.001), np.log10(7), 60)
        array_dNf = np.array([self.IntermediatePsNoise(lobs, mlim, z) for z in z_vec])

        return np.trapz(array_dNf,z_vec)

class Cllow:
    def __init__(self):
        """
        Container class to compute the Power spectrum and the Cl

        """
        # Set constants
        self.fromHztoeV = 6.58e-16
        self.gramstoeV = 1 / ( 1.78 * 1e-33)
        self.mtoev = 1/(1.97 * 1e-7)
        self.H0 = cosmo.H(0).value * 1e3 / (1e3 * const.kpc.value) #expressed in 1/s
        self.rhocritical = cosmo.critical_density(0).value * self.gramstoeV /(1e-2)**3 # eV/m**3
        self.Om0 = cosmo.Om0 #total matter
        self.OLambda0 = cosmo.Ode0  # cosmological constant
        self.DM0 = self.Om0 - cosmo.Ob0 # dark matter
        self.evtonJoule = 1.60218 * 1e-10 # from eV to nJ
        self.evtoJoule = 1.60218 * 1e-19 # from eV to J
        PSgal1h = np.loadtxt("/Users/andreacaputo/Desktop/Phd/AxionDecayCrossCorr/Codes/NIRB_PS/PS_GALl_1h.dat")
        PSgal2h = np.loadtxt("/Users/andreacaputo/Desktop/Phd/AxionDecayCrossCorr/Codes/NIRB_PS/PS_GALl_2h.dat")
        self.Mpc = 1e3 * const.kpc.value
        self.zmin = 0.001
        self.zmax = 30.001
        self.zbins = 301
        self.h = cosmo.h
        self.z_vect = np.linspace(self.zmin, self.zmax, self.zbins)
        self.k_vect = PSgal1h[:,0]* self.h
        self.Power1h = PSgal1h[:,1:]/(self.h**3)
        self.Power2h = PSgal2h[:,1:]/(self.h**3)
        self.Power = self.Power1h + self.Power2h
        self.Praw_prova1h = interp2d(self.k_vect, self.z_vect, np.transpose(self.Power1h))
        self.Praw_prova2h = interp2d(self.k_vect, self.z_vect, np.transpose(self.Power2h))
        self.Praw_prova = interp2d(self.k_vect, self.z_vect, np.transpose(self.Power))

    def PSgal1h(self, k, z):

        return self.Praw_prova1h(k, z)[0]

    def PSgal2h(self, k, z):
        return self.Praw_prova2h(k, z)[0]

    def PSgal(self, k, z):
        return self.Praw_prova(k, z)[0]

    def tointegrate(self, lobs,mlim,k,z):

        lowz = LowGal()
        return (1e-3*const.c.value/cosmo.H(z).value)*self.PSgal(k, z)*(lowz.WindowGal(lobs,mlim,z))**2 / (cosmo.comoving_distance(z).value)**2

    def Pqlow(self, lobs,mlim,k):
        def integrand(z):
            return self.to_integrate(lobs,mlim,k,z)
        return quad(integrand,1e-4,7)[0]

    def CllowQuad(self,lobs,mlim,l):
        def integrand(z):
            kl = l/cosmo.comoving_distance(z).value
            return self.tointegrate(lobs,mlim,kl,z)
        return quad(integrand,0.001,7)[0] # ACHTUNG: the lower bound should be consistent with the PS data, otherwise it will interpolate

    def CllowNoise(self,lobs,mlim): # Here the Cl is already given in (nW/m^2/sr)^2
        lowz = LowGal()

        return lowz.PSnoise(lobs, mlim)

    def CllowNn(self,lobs,mlim,l): # Here the Cl is already given in (nW/m^2/sr)^2, no noise
        lowz = LowGal()
        zarray = np.logspace(np.log10(0.001), np.log10(7), 60)
        kl = l/ cosmo.comoving_distance(zarray).value
        array = np.arange(0,len(zarray))
        yarray = np.array([self.tointegrate(lobs,mlim,kl[i],zarray[i]) for i in array])
        return np.trapz(yarray,zarray)

    def Cllow(self,lobs,mlim,l): # Here the Cl is already given in (nW/m^2/sr)^2
        lowz = LowGal()
        zarray = np.logspace(np.log10(0.001), np.log10(7), 60)
        kl = l/ cosmo.comoving_distance(zarray).value
        array = np.arange(0,len(zarray))
        yarray = np.array([self.tointegrate(lobs,mlim,kl[i],zarray[i]) for i in array])
        return np.trapz(yarray,zarray) + lowz.PSnoise(lobs, mlim)


import statistics as s
import greedy_solver as g
import wizard_parse as p
from random import shuffle

def randomize_test(k, wizards, constraints):
    v = []
    for _ in range(k):
        shuffle(wizards)
        v += [g.greedy_find(wizards, constraints)[1]]
    return s.mean(v)

def find_worst(path):
    files = p.get_files(path)
    worst_sample = files[0]
    most_errors = 0
    for file in files:
        v = p.parse(file)
        result = randomize_test(5, v[0], v[1])
        if result > most_errors:
            most_errors = result
            worst_sample = file
        print(worst_sample, most_errors)
    return worst_sample, most_errors


import sys
from setuptools import setup
from setuptools import find_packages

version = '3.0dev'

if sys.version_info < (2, 7):
    extra_install_requires = ['ordereddict']
else:
    extra_install_requires = []

setup(
    name='Products.UserAndGroupSelectionWidget',
    version=version,
    description='Archetypes Widget for User and Group Selection, works '
                'with many users.',
    long_description=open('README.rst').read() + open('HISTORY.txt').read() + open('LICENSE.txt').read(),
    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'Environment :: Web Environment',
        'Framework :: Zope2',
        'License :: OSI Approved :: BSD License',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
        ],
    keywords='zope zope2 plone archetypes z3cform widget user',
    author='BlueDynamics Alliance',
    author_email='dev@bluedynamics.com',
    url='https://github.com/collective/Products.UserAndGroupSelectionWidget',
    license='BSD',
    packages=find_packages('src'),
    package_dir = {'': 'src'},
    namespace_packages=['Products', ],
    include_package_data=True,
    zip_safe=False,
    install_requires=[
        'setuptools',
        'zope.interface',
        'zope.component',
        'zope.schema>=4.1.1',
        'Zope2',
        'AccessControl',
        'Products.CMFCore',
        'Products.CMFPlone',
        'Products.PlonePAS',
        'bda.cache',
        'lxml',
        'plone.dexterity',
        ] + extra_install_requires,
    extras_require = {
        'test': [
            'unittest2',
            'zope.app.testing',
            'plone.app.testing',
            ],
        },
    )


# --------------------------------  TESSERACT e Insere no excel todas as informações

import pytesseract
import cv2
from PIL import Image
import pandas as pd
from openpyxl import Workbook, load_workbook
import pyscreenshot as ImageGrab
import pyautogui
import time
import pygetwindow
import numpy as np

pyautogui.FAILSAFE= False
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract'

my_abas = ['gemchest', 'sailing', 'pets', 'mount',
           'foraging', 'mining', 'hunting', 'fishing', 'excavating', 'traderother', 'logging']
my_sections =['name', 'avgprice', 'recentprices', 'lowestprice', 'cheapestrem']
my_sectionsletters = {'A', 'B', 'C', 'D', 'E'}

wb = load_workbook('auction.xlsx')

for aba in my_abas:
    excellinhafinal = 6
    ws = wb.active
    ws.title = f'{aba}'
    at = wb[f"{aba}"]
    if aba == 'pets':
        excellinhafinal = 8
    if aba == 'mount':
        excellinhafinal = 8
    if aba == 'gemchest':
        excellinhasfinal = 4
    if aba == 'foraging':
        excellinhafinal = 8
    if aba == 'hunting':
        excellinhafinal = 8
    if aba == 'fishing':
        excellinhafinal = 8
    if aba == 'mining':
        excellinhafinal = 5
    if aba == 'logging':
        excellinhafinal = 5
    if aba == 'excavating':
        excellinhafinal = 7
    if aba == 'traderother':
        excellinhafinal = 7

    for sections in my_sections:
        for linhas in range(2, excellinhafinal):
            #tesseract the images
            typing = (pytesseract.image_to_string(f'{aba}\worked{linhas}{sections}.bmp',  config= ' --psm 6 -c tessedit_char_whitelist={0123456789}'))
            if sections == 'name':
                typing = (pytesseract.image_to_string(f'{aba}\worked{linhas}{sections}.bmp',  config= ' --psm 6'))
            #make and retyping the tab
            if typing == '':
                typing = float(0)
            if sections == 'name':
                at[f'A{linhas}'] = typing
            if sections == 'avgprice':
                at[f'B{linhas}'] = float(typing)
            if sections == 'recentprices':
                at[f'C{linhas}'] =float(typing)
            if sections == 'lowestprice':
                at[f'D{linhas}'] = float(typing)
            if sections == 'cheapestrem':
                at[f'E{linhas}'] = float(typing)
            wb.save('auction.xlsx')

pyautogui.moveTo(0, 0)


import os.path,click
from localstack_ext.bootstrap.licensingv2 import AuthToken,DevLocalstackEnvironment,LicensingError,get_credentials_from_environment,get_licensed_environment
@click.group(name='license',short_help='(Beta) Manage and verify your LocalStack license')
def license():0
@license.command('info')
def cmd_info():
	I='test'
	try:A=get_credentials_from_environment()
	except Exception as B:click.echo(f"credentials: {B}");return
	if A:
		if isinstance(A,AuthToken):
			if A.encoded()==I:E=I
			else:E='valid syntax'if A.is_valid()else'invalid'
		else:E=''
		click.echo(f"credentials: {type(A).__name__}({A.encoded()}) {E}")
	else:click.echo('credentials: none found in environment')
	D=get_licensed_environment()
	if isinstance(D,DevLocalstackEnvironment):click.echo('test credentials used, using unlicensed dev environment');return
	C=None
	for G in D.get_license_file_read_locations():
		if os.path.isfile(G):C=G;break
	F=None
	if C:
		try:
			with open(C,'rb')as J:H=J.read();F=D.parser.parse(H);click.echo(f"license location: {C}");click.echo(f"license: {H.decode('utf-8')}")
		except LicensingError as B:click.echo(f"license location: {C}");click.echo(f"license: error reading license file {B}")
	if F:
		try:D.client.validate(F);click.echo('license validity: valid')
		except LicensingError as B:click.echo(f"license validity: invalid ({B})")
@license.command('activate')
def cmd_activate():
	try:A=get_licensed_environment();A.activate();click.echo('license activation completed');click.echo(f"license: {A.serializer.serialize(A.license).decode('utf-8')}")
	except LicensingError as B:click.echo(B.get_user_friendly())


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pytest
import yaml

from App.App_2.app import App

class TestContact:
    def setup_class(self):
        self.app = App()
        self.contact = self.app.start().main().goto_contact()

    @pytest.mark.parametrize("name, gender, tel",
                             yaml.safe_load(open("../data/data.yml", encoding='utf-8'))['add_data'])
    def test_add_contact(self, name, gender, tel):
        assert "成功" in self.contact.add_member().invite_manual().input_name(name).set_gender(
            gender).input_tel(tel).click_save().get_toast()

    @pytest.mark.parametrize("name", yaml.safe_load(open("../data/data.yml", encoding='utf-8'))['del_data'])
    def test_del_member(self, name):
        assert self.contact.goto_profile(name).goto_edit().del_member().get_member(name) is False


import pytest
from pathlib import Path

from perceval import Circuit, P, BasicState, pdisplay, Matrix, BackendFactory, Processor
from perceval.rendering.pdisplay import pdisplay_circuit, pdisplay_matrix, pdisplay_analyzer
from perceval.rendering.format import Format
import perceval.algorithm as algo
import perceval.components.unitary_components as comp
import sympy as sp
import numpy as np

def strip_line_12(s: str) -> str:
    return s.strip().replace("            ", "")

def test_helloword():
    c = comp.BS()
    assert c.m == 2
    definition = c.definition()
    assert strip_line_12(pdisplay_matrix(definition)) == strip_line_12("""
            ⎡exp(I*(phi_tl + phi_tr))*cos(theta/2)    I*exp(I*(phi_bl + phi_tr))*sin(theta/2)⎤
            ⎣I*exp(I*(phi_br + phi_tl))*sin(theta/2)  exp(I*(phi_bl + phi_br))*cos(theta/2)  ⎦
    """)
    expected = [P(name='theta', value=sp.pi/2, min_v=0, max_v=4*sp.pi),
                P(name='phi_tl', value=0, min_v=0, max_v=2*sp.pi),
                P(name='phi_bl', value=0, min_v=0, max_v=2*sp.pi),
                P(name='phi_tr', value=0, min_v=0, max_v=2*sp.pi),
                P(name='phi_br', value=0, min_v=0, max_v=2*sp.pi),
                ]
    for p_res, p_exp in zip(c.get_parameters(True), expected):
        assert str(p_res) == str(p_exp)
    assert c.U.is_unitary()
    for backend_name in ["SLOS", "Naive"]:
        backend = BackendFactory.get_backend(backend_name)
        backend.set_circuit(c)
        expected_outputs = {
            BasicState("|0,1>"): 0.5,
            BasicState("|1,0>"): 0.5
        }
        input_state = BasicState("|0,1>")
        backend.set_input_state(input_state)
        bsd = backend.prob_distribution()
        for output_state, p in bsd.items():
            assert output_state in expected_outputs
            assert pytest.approx(expected_outputs[output_state]) == p
            assert pytest.approx(expected_outputs[output_state]) == backend.probability(output_state)
        assert len(bsd) == len(expected_outputs)
        p = Processor(backend_name, c)
        ca = algo.Analyzer(p,
                           [BasicState([0, 1]), BasicState([1, 0]), BasicState([1, 1])],  # the input states
                           "*"  # all possible output states that can be generated with 1 or 2 photons
                           )
        assert strip_line_12(pdisplay_analyzer(ca)) == strip_line_12("""
            +-------+-------+-------+-------+-------+-------+
            |       | |0,1> | |1,0> | |2,0> | |1,1> | |0,2> |
            +-------+-------+-------+-------+-------+-------+
            | |0,1> |  1/2  |  1/2  |   0   |   0   |   0   |
            | |1,0> |  1/2  |  1/2  |   0   |   0   |   0   |
            | |1,1> |   0   |   0   |  1/2  |   0   |  1/2  |
            +-------+-------+-------+-------+-------+-------+
        """)

def test_empty_circuit():
    c = Circuit(4)
    m = c.compute_unitary(False)
    assert m.shape == (4, 4)
    assert np.allclose(m, Matrix.eye(4))
    assert pdisplay_circuit(c).replace(" ", "") == """

0:────:0 (depth 0)

1:────:1 (depth 0)

2:────:2 (depth 0)

3:────:3 (depth 0)

""".replace(" ", "")

def test_bs_symbolic_unitary():
    phi_tl = P("phi")
    theta = P("theta")
    bs = comp.BS(theta=theta, phi_tl=phi_tl)
    assert strip_line_12(pdisplay_matrix(bs.compute_unitary(use_symbolic=True))) == strip_line_12("""
            ⎡exp(I*phi)*cos(theta/2)    I*sin(theta/2)⎤
            ⎣I*exp(I*phi)*sin(theta/2)  cos(theta/2)  ⎦""")

def test_bs_u():
    bs = comp.BS()
    assert pdisplay_matrix(bs.U) == "⎡sqrt(2)/2    sqrt(2)*I/2⎤\n⎣sqrt(2)*I/2  sqrt(2)/2  ⎦"

    bs = comp.BS(theta=comp.BS.r_to_theta(1))
    assert pdisplay_matrix(bs.U) == "⎡1  0⎤\n⎣0  1⎦"

    bs = comp.BS(theta=comp.BS.r_to_theta(0))
    assert pdisplay_matrix(bs.U) == "⎡0  I⎤\n⎣I  0⎦"

def test_parameter():
    theta = P("theta0")
    bs = comp.BS(theta=theta)
    with pytest.raises(AssertionError):  # Cannot request a numeric matrix with variable parameters
        bs.compute_unitary(use_symbolic=False)
    assert pdisplay_matrix(bs.compute_unitary(use_symbolic=True)) == strip_line_12("""
            ⎡cos(theta0/2)    I*sin(theta0/2)⎤
            ⎣I*sin(theta0/2)  cos(theta0/2)  ⎦""")

def test_double_parameter_ok():
    phi1 = P("phi")
    comp.BS(phi_tl=phi1, phi_bl=phi1)

def test_double_parameter_dup():
    phi1 = P("phi")
    phi2 = P("phi")
    with pytest.raises(RuntimeError):  # Exception should be raised for two parameters with same name
        comp.BS(phi_tr=phi1, phi_bl=phi2)

def test_double_parameter_dup_multi():
    phi1 = P("phi")
    phi2 = P("phi")
    with pytest.raises(RuntimeError):  # Exception should have been generated for two parameters with same name
        comp.BS(phi_tr=phi1) // comp.BS(phi_tl=phi2)

def test_build_composition():
    a = comp.BS()
    b = comp.BS()
    c = a // b
    assert pdisplay_matrix(c.U) == "⎡0  I⎤\n⎣I  0⎦"

def test_build_composition_2():
    c = comp.BS() // comp.PS(phi=sp.pi/2)
    assert pdisplay_matrix(c.U) == "⎡sqrt(2)*I/2  -sqrt(2)/2⎤\n⎣sqrt(2)*I/2  sqrt(2)/2 ⎦"

def test_build_composition_3():
    c = comp.BS() // (0, comp.PS(phi=sp.pi/2))
    assert pdisplay_matrix(c.U) == "⎡sqrt(2)*I/2  -sqrt(2)/2⎤\n⎣sqrt(2)*I/2  sqrt(2)/2 ⎦"

def test_build_composition_4():
    c = comp.BS() // (1, comp.PS(phi=sp.pi/2))
    assert pdisplay_matrix(c.U) == "⎡sqrt(2)/2   sqrt(2)*I/2⎤\n⎣-sqrt(2)/2  sqrt(2)*I/2⎦"

def test_invalid_ifloor():
    with pytest.raises(AssertionError):
        comp.BS() // (1, comp.BS())  # invalid ifloor should fail

def test_unitary_component():
    non_unitary_matrix = Matrix([[1, 2], [3, 4]])
    with pytest.raises(AssertionError):
        comp.Unitary(non_unitary_matrix)

    odd_size_matrix = Matrix.random_unitary(5)
    with pytest.raises(AssertionError):
        # In case the unitary component is polarized, the unitary matrix size must be even
        comp.Unitary(odd_size_matrix, use_polarization=True)

    unitary = comp.Unitary(odd_size_matrix)
    assert (unitary.U == odd_size_matrix).all()

def test_unitary_inverse():
    """
    Testing vertical inversion can be performed by applying a m:-1:0 permutation on the right and on the left of the
    inverted circuit. The resulting circuit has to be equivalent to the input circuit.
    """
    size = 4
    perm_tester = comp.PERM(list(range(size-1, -1, -1)))
    input_component = comp.Unitary(Matrix.random_unitary(size))
    inverted_component = comp.Unitary(input_component.U)
    inverted_component.inverse(v=True)
    test_circuit = Circuit(size)\
        .add(0, perm_tester)\
        .add(0, inverted_component)\
        .add(0, perm_tester)
    assert np.array_equal(input_component.U, test_circuit.U)

    # Test v and h inversion interaction (the order should have no impact on the result)
    u1 = comp.Unitary(Matrix.random_unitary(size))
    u2 = comp.Unitary(U=u1.U)
    u1.inverse(h=True)
    u1.inverse(v=True)
    u2.inverse(v=True)
    u2.inverse(h=True)
    assert np.allclose(u1.U, u2.U, atol=1e-12)

def _gen_bs(i: int):
    return comp.BS(theta=P(f"theta{i}"))

# noinspection PyTypeChecker
def test_generator():
    c = Circuit.generic_interferometer(5, _gen_bs)
    assert len(c.get_parameters()) == 5*4/2
    c = Circuit.generic_interferometer(5, _gen_bs, depth=1)
    assert len(c.get_parameters()) == 2
    c = Circuit.generic_interferometer(5, _gen_bs, depth=2)
    assert len(c.get_parameters()) == 4

def test_iterator():
    c = Circuit(3)
    comps = [(0, 1), (1, 2), (0, 1)]
    for k in range(len(comps)):
        c.add(comps[k], comp.BS(theta=1/(k+1)))

    d = Circuit(4)
    d.add((0, 1, 2), c, merge=False)
    d.add((2, 3), comp.BS(theta=1/4))
    comps.append((2, 3))

    l_comp = list(d.__iter__())

    assert len(l_comp) == 4
    for i in range(4):
        assert float(l_comp[i][1].param("theta")) == 1/(i+1) and l_comp[i][0] == comps[i]

def test_evolve():
    for backend_name in ["SLOS", "Naive", "MPS"]:
        backend = BackendFactory.get_backend(backend_name)
        backend.set_circuit(comp.BS.H())
        backend.set_input_state(BasicState("|1,0>"))
        assert str(backend.evolve()) == "sqrt(2)/2*|1,0>+sqrt(2)/2*|0,1>"

def _generate_simple_circuit():
    return (comp.Unitary(U=Matrix.random_unitary(3), name="U1")
            // (0, comp.PS(sp.pi / 2))
            // comp.Unitary(U=Matrix.random_unitary(3), name="U2"))

def test_visualization_ucircuit(capfd):
    c = _generate_simple_circuit()
    pdisplay(c, output_format=Format.TEXT)
    out, err = capfd.readouterr()
    assert out.strip() == """
    ╭─────╮╭───────────╮╭─────╮
0:──┤U1   ├┤PS phi=pi/2├┤U2   ├──:0 (depth 3)
    │     │╰───────────╯│     │
    │     │             │     │
1:──┤     ├─────────────┤     ├──:1 (depth 2)
    │     │             │     │
    │     │             │     │
2:──┤     ├─────────────┤     ├──:2 (depth 2)
    ╰─────╯             ╰─────╯
""".strip()

TEST_DATA_DIR = Path(__file__).resolve().parent / 'data'

def test_depths_ncomponents():
    assert comp.PS(0).depths() == [1]
    assert comp.PS(0).ncomponents() == 1
    c = _generate_simple_circuit()
    assert c.depths() == [3, 2, 2]
    assert c.ncomponents() == 3
    with open(TEST_DATA_DIR / 'u_random_8', "r") as f:
        m = Matrix(f)
        ub = (Circuit(2)
              // comp.BS()
              // (0, comp.PS(phi=P("φ_a")))
              // comp.BS()
              // (0, comp.PS(phi=P("φ_b"))))
        c1 = Circuit.decomposition(m, ub, shape="triangle")
        assert c1 is not None and c1.depths() == [28, 38, 32, 26, 20, 14, 8, 2]
        assert c1.ncomponents() == 112

def test_reflexivity():
    c = comp.BS(theta=comp.BS.r_to_theta(1/3), convention=comp.BSConvention.H)
    assert pytest.approx(c.compute_unitary(use_symbolic=False)[0, 0]) == np.sqrt(1/3)

def test_getitem1_index():
    c = Circuit(2) // comp.BS() // comp.PS(P("phi1")) // comp.BS() // comp.PS(P("phi2"))
    with pytest.raises(IndexError):
        _ = c[0, 5]
    with pytest.raises(ValueError):
        _ = c[-1]
    with pytest.raises(IndexError):
        _ = c[4, 0]

def test_getitem2_value():
    c = Circuit(2) // comp.BS.H() // comp.PS(P("phi1")) // comp.BS.H() // comp.PS(P("phi2"))
    assert c[0, 0].describe() == "BS(convention=BSConvention.H)"
    assert c[0, 1].describe() == "PS(phi=phi1)"

def test_getitem3_parameter():
    c = Circuit(2) // comp.BS.H() // comp.PS(P("phi1")) // comp.BS.H() // comp.PS(P("phi2"))
    assert c.getitem((0, 0), True).describe() == "PS(phi=phi1)"


import datetime as dt
import pandas as pd
pd.set_option('display.max_columns', None)
pd.set_option('display.width', None)
import datetime as dt

pd.set_option('display.float_format', lambda x: '%.3f' % x)

df_ = pd.read_csv("flo_data_20k.csv")
df = df_.copy()

df.head()
df.tail()
df.columns
df.describe().T
df.isnull().sum()
df.dtypes

df["master_id"].nunique()

df["of_on_total_ever"] = df["order_num_total_ever_online"] + df["order_num_total_ever_offline"]

df["of_on_total_price_ever"] = df["customer_value_total_ever_online"] + df["customer_value_total_ever_offline"]
df.head()

df.dtypes
[col for col in df.columns if "date" in col]

date_change = df.columns[df.columns.str.contains("date")]
df[date_change] = df[date_change].apply(pd.to_datetime)
df.dtypes

df.groupby("order_channel").agg({"of_on_total_ever": "sum",
                                 "of_on_total_price_ever": "sum"})

totalprice_top10=df.sort_values(by="of_on_total_price_ever", ascending=False).head(10)
totalprice_top10

totalorder_top10=df.sort_values(by="of_on_total_ever", ascending=False).head(10)
totalorder_top10

def func(x):
    df["of_on_total_ever"] = df["order_num_total_ever_online"] + df["order_num_total_ever_offline"]
    df["of_on_total_price_ever"] = df["customer_value_total_ever_online"] + df["customer_value_total_ever_offline"]

    df['first_order_date'] = pd.to_datetime(df['first_order_date'])
    df['last_order_date'] = pd.to_datetime(df['last_order_date'])
    df['last_order_date_online'] = pd.to_datetime(df['last_order_date_online'])
    df['last_order_date_offline'] = pd.to_datetime(df['last_order_date_offline'])

    return(df)

func(df)

df["last_order_date"].max()

today_date = dt.datetime(2021, 6, 1)
type(today_date)

df.groupby("master_id").agg({"last_order_date": lambda last_order_date: (today_date - last_order_date.max()).days,
                             "of_on_total_ever": lambda of_on_total_ever: of_on_total_ever,
                             "of_on_total_price_ever": lambda of_on_total_price_ever: of_on_total_price_ever})

rfm = df.groupby("master_id").agg({"last_order_date": lambda last_order_date: (today_date - last_order_date.max()).days,
                             "of_on_total_ever": lambda of_on_total_ever: of_on_total_ever,
                             "of_on_total_price_ever": lambda of_on_total_price_ever: of_on_total_price_ever})

rfm.columns = ['recency', 'frequency', 'monetary']

rfm["recency_score"] = pd.qcut(rfm['recency'], 5, labels=[5, 4, 3, 2, 1])

rfm["frequency_score"] = pd.qcut(rfm['frequency'].rank(method="first"), 5, labels=[1, 2, 3, 4, 5])

rfm["monetary_score"] = pd.qcut(rfm['monetary'], 5, labels=[1, 2, 3, 4, 5])

rfm["RFM_SCORE"] = (rfm['recency_score'].astype(str) + rfm['frequency_score'].astype(str))

seg_map = {
    r'[1-2][1-2]': 'hibernating',
    r'[1-2][3-4]': 'at_Risk',
    r'[1-2]5': 'cant_loose',
    r'3[1-2]': 'about_to_sleep',
    r'33': 'need_attention',
    r'[3-4][4-5]': 'loyal_customers',
    r'41': 'promising',
    r'51': 'new_customers',
    r'[4-5][2-3]': 'potential_loyalists',
    r'5[4-5]': 'champions'
}

rfm['segment'] = rfm['RFM_SCORE'].replace(seg_map, regex=True)

rfm[["segment", "recency", "frequency", "monetary"]].groupby("segment").agg(["mean"])

#WOMAN_BEST_CUSTOMERS

df["interested_in_categories_12"].value_counts()

rfm_c_lc = rfm[(rfm["segment"]=="champions") | (rfm["segment"]=="loyal_customers")]
rfm_c_lc
rfm_c_lc.shape[0]

woman = df[(df["interested_in_categories_12"]).str.contains("KADIN")]

woman_best_customers = pd.merge(rfm_c_lc, woman[["interested_in_categories_12","master_id"]], on=["master_id"])

woman_best_customers= woman_best_customers.drop(woman_best_customers.loc[:,'recency':'interested_in_categories_12'].columns,axis=1)
woman_best_customers

woman_best_customers.to_csv("woman_best_customers.csv")

#TURN_BACK_TO_COMPANY_MAN_CHILD

requested_customers = rfm[(rfm["segment"]=="cant_loose") | (rfm["segment"]=="about_to_sleep") | (rfm["segment"]=="new_customers")]

man_children = df[(df["interested_in_categories_12"]).str.contains("ERKEK|COCUK|AKTIFCOCUK")]

turn_back_to_company = pd.merge(requested_customers, man_children[["interested_in_categories_12","master_id"]],on=["master_id"])

turn_back_to_company = turn_back_to_company.drop(turn_back_to_company.loc[:,'recency':'interested_in_categories_12'].columns,axis=1)
turn_back_to_company.head()
turn_back_to_company.shape
turn_back_to_company.to_csv("turn_back_to_company.csv")


from typer.testing import CliRunner

from sim_dev import __app_name__
from sim_dev import __author__
from sim_dev import __version__
from sim_dev import cli
from sim_dev.config import AppConfiguration

runner = CliRunner()

def test_version():
    result = runner.invoke(cli.app, ["--version"])
    assert result.exit_code == 0
    assert f"{__app_name__} v{__version__} made by {__author__}\n" in result.stdout

def test_commands_args():
    conf = AppConfiguration()
    config = AppConfiguration()
    result = conf._get_args_command("change-directory")
    result1 = config._get_args_command("")
    result2 = config._get_args_command(None)

    assert not result is None
    assert conf is config
    assert not result == result1
    assert result2 is None


"""
A module for managing and solving sudokus of variable size
"""
import constraint

class Sudoku(object):

    """
    This class manages Sudoku grids of variable sizes.

    It allows for easy access to the individual rows, columns and blocks of
    the grid. Sudokus can be solved using constraint processing.
    """

    def __init__(self, grid):
        """
        The constructor expects a flat list as a grid, for example:

        >>> grid4x4 = [0, 1, 0, 0,
        ...            0, 0, 4, 0,
        ...            0, 0, 0, 0,
        ...            0, 0, 3, 0]
        >> Sudoku(grid4x4)

        Where zeros indicate an empty field.
        The grid's length must be a a square number.
        """
        self.grid = grid
        self.size = int(len(grid) ** 0.5)
        self.block_size = int(self.size ** 0.5)

        if self.size ** 2 != len(grid):
            raise ValueError('Expecting a square grid')

    @property
    def rows(self):
        """
        Generator expression for accessing the individual rows of the grid
        """
        for n in range(self.size):
            yield self.grid[n * self.size:self.size * (n + 1)]

    @property
    def columns(self):
        """
        Returns a generator for accessing the individual columns of the grid
        """
        for n in range(self.size):
            yield self.grid[n::self.size]

    @property
    def blocks(self):
        """
        Returns a generator for accessing the individual blocks of the grid
        """
        for _y in range(self.block_size):
            for _x in range(self.block_size):
                block = []
                x = _x * self.block_size
                y = _y * self.block_size * self.size
                start = x + y
                for r in range(self.block_size):
                    block += self.grid[start:start + self.block_size]
                    start += self.size
                yield block

    def solve(self):
        """
        Solves the sudoku.

        This will replace the empty cells in this sudoku with the solutions.
        """
        problem = constraint.Problem()
        all_different = constraint.AllDifferentConstraint()

        for i, n in enumerate(self.grid):
            problem.addVariable(i, range(1, self.size + 1) if n == 0 else [n])

        _s = Sudoku(range(len(self.grid)))
        for row in _s.rows:
            problem.addConstraint(all_different, row)
        for col in _s.columns:
            problem.addConstraint(all_different, col)
        for block in _s.blocks:
            problem.addConstraint(all_different, block)

        solution = problem.getSolution()
        if solution:
            self.grid = solution.values()
        else:
            raise ValueError('No solutions found')

    def __str__(self):
        """
        Shows the string representation of the sudoku grid.
        """
        result = ''
        number_width = len(str(self.size)) + 1
        block_count = int(self.size / self.block_size)
        block_width = block_count * number_width

        # Formatting has gotten bit complex because we need to handle grids of
        # variable size. As a result, numbers are often longer than one char.
        for y, row in enumerate(self.rows):
            if y % self.block_size == 0 and y > 0:
                # insert horizontal line
                result += "+-".join(["-" * block_width] * block_count) + "\n"
            for x, num in enumerate(row):
                if x % self.block_size == 0 and x > 0:
                    # insert vertical line
                    result += "| "
                # draw numbers
                result += str(num).ljust(number_width)
            result += "\n"
        return result

if __name__ == '__main__':
    small = [0, 1, 0, 0,
             0, 0, 4, 0,
             0, 0, 0, 0,
             0, 2, 3, 0]

    hardest = [8, 0, 0, 0, 0, 0, 0, 0, 0,
               0, 0, 3, 6, 0, 0, 0, 0, 0,
               0, 7, 0, 0, 9, 0, 2, 0, 0,
               0, 5, 0, 0, 0, 7, 0, 0, 0,
               0, 0, 0, 0, 4, 5, 7, 0, 0,
               0, 0, 0, 1, 0, 0, 0, 3, 0,
               0, 0, 1, 0, 0, 0, 0, 6, 8,
               0, 0, 8, 5, 0, 0, 0, 1, 0,
               0, 9, 0, 0, 0, 0, 4, 0, 0]

    empty_normal = [0] * (9 ** 2)
    empty_big = [0] * (16 ** 2)

    s = Sudoku(hardest)
    s.solve()

    print(s)


from django.urls import path
from .views import *

app_name = "news"
urlpatterns = [
    # path("news/", NewsView.as_view(), name="news"),
    path("news-detail/<int:pk>/", NewsDetailView.as_view(), name="news-detail"),
    path("news/list/", NewsView.as_view(), name="news"),
    path("news/all-list/", AllNewsView.as_view(), name="news-all"),
    # news crud
    path("category", CategoryView.as_view(), name="category-table"),
    path("category-create/", CategoryCreateView.as_view(), name="category-create"),
    path(
        "category-update/<int:pk>/",
        CategoryUpdateView.as_view(),
        name="category-update",
    ),
    path(
        "category-delete/<int:pk>/",
        CategoryDeleteView.as_view(),
        name="category-delete",
    ),
    path("news-table/", NewsTableView.as_view(), name="news-table"),
    # add news/notice
    path("admin/add-news/", AddAdminNewsView.as_view(), name="add-anews"),
    # update news/notice
    path("admin/edit-news/<int:pk>/", EditAdminNewsView.as_view(), name="edit-anews"),
    ##########################
    path("news-delete/<int:pk>/", NewsDeleteView.as_view(), name="news-delete"),
    path(
        "recentactivity-detail/<int:pk>/",
        RecentActivityDetailView.as_view(),
        name="recentactivity-detail",
    ),
    path("recent-activity/list/", RecentActivityView.as_view(), name="recent-activity"),
     path("recent-activity/all-list/", AllRecentActivityView.as_view(), name="all-recent-activity"),
    # recent actvities crud
    path(
        "recent-activity/table/",
        RecentActivityTableView.as_view(),
        name="recentactivity-table",
    ),
    #####################recent activity #########
     path("recent-activity/add-recent-activity/", AddAdminRecentView.as_view(), name="add-arecent-activity"),
    # update news/notice
    path("recent-activity/edit-recent-activity/<int:pk>/", EditAdminRecentView.as_view(), name="edit-arecent-activity"),
    ##########################
    path(
        "recent-activity-delete/<int:pk>/",
        RecentActivityDeleteView.as_view(),
        name="recentactivity-delete",
    ),
    # dam knowledge
    path("damknowledge-salient-features/", DamKnowledgeSalientFeaturesView.as_view(), name="damknowledge"),
    path("pipeline/", PipeLineView.as_view(), name="pipeline"),
    path("name-of-dam/", NameOfDamView.as_view(), name="name-of-dam"),
    path("lake/", LakeView.as_view(), name="lake"),
    path("literature/", LiteratureView.as_view(), name="literatures"),
    # admin dam knowledge

    # administration
    path(
        "administration/login",
        AdministrationLoginView.as_view(),
        name="administration-login",
    ),
    path(
        "administration/darta-chalani", DartaChalaniView.as_view(), name="darta-chalani"
    ),
    path("administration/darta-list", DartaListView.as_view(), name="darta-list"),
    path("administration/darta-form", DartaFormView.as_view(), name="darta-form"),
    path("administration/chalani-list", ChalaniListView.as_view(), name="chalani-list"),
    path("administration/chalani-form", ChalaniFormView.as_view(), name="chalani-form"),
    path("darta/<int:pk>", DartaDetailView.as_view(), name="darta-detail"),
    path("darta/<int:pk>/update", DartaUpdateView.as_view(), name="darta-update"),
    path("darta/<int:pk>/delete", DartaDeleteView.as_view(), name="darta-delete"),
    path("chalani/<int:pk>", ChalaniDetailView.as_view(), name="chalani-detail"),
    path("chalani/<int:pk>/update", ChalaniUpdateView.as_view(), name="chalani-update"),
    path("chalani/<int:pk>/delete", ChalaniDeleteView.as_view(), name="chalani-delete"),
    path("administration/upload-file/", CUploadFileView.as_view(), name="c-upload-file"),
    path("administration/upload-file/add", CAddUploadFileView.as_view(), name="c-add-file"),
    path("administration/upload-file/edit/<int:pk>/", CEditUploadUpdateFileView.as_view(), name="c-edit-file"),
    path("administration/upload-file/delete/<int:pk>/", CEditUploadDeleteFileView.as_view(), name="c-delete-file"),

    # ========= Notice ========
    path("notice/", NoticeView.as_view(), name="notice"),
    path("notice/create/", NoticeCreateView.as_view(), name="notice-create"),
    path("notice/update/<int:pk>/", NoticeUpdateView.as_view(), name="notice-update"),
    path("notice/delete/<int:pk>/", NoticeDeleteView.as_view(), name="notice-delete"),
    path("admin/profile/", AdminProfileView.as_view(), name="admin-profile"),
    # message
    path("admin/messages/", MessageView.as_view(), name="admin-message"),
    path("messages/create/", MessageCreateView.as_view(), name="message-create"),
    path("messages/update/<int:pk>/", MessageUpdateView.as_view(), name="messages-update"),
    path("messages/delete/<int:pk>/", MessageDeleteView.as_view(), name="message-delete"),

    path("darta/search",DartaSearch.as_view(),name="darta-search")
    # for displying pdf
    #     path("admin/message/create/", MessageCreateView.as_view(), name="message-create"),
    #     path("admin/message/update/<int:pk>/", MessageUpdateView.as_view(), name="message-update"),
    #     path("admin/message/delete/<int:pk>/", MessageDeleteView.as_view(), name="message-delete"),
]


import pytest
from brownie import network, FigaNFT
from scripts.helpful_scripts import (
    get_account,
    get_contract,
    LOCAL_BLOCKCHAIN_ENVIRONMENTS,
)

def test_can_create_figa_nft(
    get_keyhash,
    chainlink_fee,
):
    # Arrange
    if network.show_active() not in LOCAL_BLOCKCHAIN_ENVIRONMENTS:
        pytest.skip("Only for local testing")
    figa_nft = FigaNFT.deploy(
        get_contract("vrf_coordinator").address,
        get_contract("link_token").address,
        get_keyhash,
        {"from": get_account()},
    )
    get_contract("link_token").transfer(
        figa_nft.address, chainlink_fee * 3, {"from": get_account()}
    )
    # Act
    transaction_receipt = figa_nft.createCollectible(
        "None", {"from": get_account()}
    )
    requestId = transaction_receipt.events["requestedCollectible"]["requestId"]
    assert isinstance(transaction_receipt.txid, str)
    get_contract("vrf_coordinator").callBackWithRandomness(
        requestId, 777, figa_nft.address, {"from": get_account()}
    )
    # Assert
    assert figa_nft.tokenCounter() > 0
    assert isinstance(figa_nft.tokenCounter(), int)


#!/usr/bin/python3

"""Uni tests for the abc"""

import unittest
import unittest.mock
from typing import Any
from pyhp.backends import (
    SourceInfo,
    CodeSource,
    DirectCodeSource,
    TimestampedCodeSource,
    CodeSourceContainer,
    TimestampedCodeSourceContainer
)
from pyhp.compiler import Code

def context_manager_exit(self: Any, *_args: Any) -> None:
    self.close()

class TestSource(unittest.TestCase, DirectCodeSource, TimestampedCodeSource):
    """test the source abc methods"""
    def mtime(self) -> int:
        return 99

    def ctime(self) -> int:
        return 10

    def atime(self) -> int:
        return -9

    def test_info(self) -> None:
        """test TimestampedCodeSource.info"""
        self.assertEqual(
            self.info(),
            SourceInfo(
                99,
                10,
                -9
            )
        )

    def source(self) -> str:
        return "test"

    def test_size(self) -> None:
        """test DirectCodeSource.size"""
        self.assertEqual(self.size(), 4)

    def code(self) -> Code:
        raise RuntimeError

class TestSourceContainer(unittest.TestCase):
    """test the code source container abc"""
    def test_contains(self) -> None:
        """test CodeSourceContainer.__contains__"""
        source = unittest.mock.Mock(spec_set=CodeSource)
        container = unittest.mock.MagicMock(spec_set=CodeSourceContainer)
        container.__getitem__.configure_mock(side_effect=(source, KeyError))
        self.assertTrue(CodeSourceContainer.__contains__(container, "Test"))
        source.close.assert_called()
        self.assertFalse(CodeSourceContainer.__contains__(container, "Test"))
        self.assertFalse(CodeSourceContainer.__contains__(container, 1))

    def test_values(self) -> None:
        """test CodeSourceContainer.values"""
        sources = {
            "a": unittest.mock.MagicMock(spec_set=CodeSource),
            "b": unittest.mock.MagicMock(spec_set=CodeSource),
            "c": unittest.mock.MagicMock(spec_set=CodeSource)
        }
        values = CodeSourceContainer.values(sources)
        for value in sources.values():
            value.__enter__ = lambda x: x
            value.__exit__ = context_manager_exit
            self.assertIn(value, values)
            value.close.assert_called()
        self.assertNotIn(1, values)

    def test_items(self) -> None:
        """test CodeSourceContainer.items"""
        sources = {
            "a": unittest.mock.MagicMock(spec_set=CodeSource),
            "b": unittest.mock.MagicMock(spec_set=CodeSource),
            "c": unittest.mock.MagicMock(spec_set=CodeSource)
        }
        items = CodeSourceContainer.items(sources)
        for name, source in sources.items():
            source.__enter__ = lambda x: x
            source.__exit__ = context_manager_exit
            self.assertIn((name, source), items)
            source.close.assert_called()
        self.assertNotIn(("a", 1), items)
        self.assertNotIn(("abc", 1), items)
        self.assertNotIn((1, 2), items)

class TestTimestampedCodeSourceContainer(unittest.TestCase):
    """test TimestampedCodeSourceContainer"""
    def test_mtime(self) -> None:
        """test TimestampedCodeSourceContainer.mtime"""
        container = {
            "a": unittest.mock.MagicMock(spec_set=TimestampedCodeSource)
        }
        container["a"].__enter__ = lambda x: x
        container["a"].__exit__ = context_manager_exit
        container["a"].mtime.configure_mock(side_effect=(9,))
        self.assertEqual(TimestampedCodeSourceContainer.mtime(container, "a"), 9)
        container["a"].close.assert_called()
        with self.assertRaises(KeyError):
            TimestampedCodeSourceContainer.mtime(container, "b")

    def test_ctime(self) -> None:
        """test TimestampedCodeSourceContainer.ctime"""
        container = {
            "a": unittest.mock.MagicMock(spec_set=TimestampedCodeSource)
        }
        container["a"].__enter__ = lambda x: x
        container["a"].__exit__ = context_manager_exit
        container["a"].ctime.configure_mock(side_effect=(9,))
        self.assertEqual(TimestampedCodeSourceContainer.ctime(container, "a"), 9)
        container["a"].close.assert_called()
        with self.assertRaises(KeyError):
            TimestampedCodeSourceContainer.ctime(container, "b")

    def test_atime(self) -> None:
        """test TimestampedCodeSourceContainer.atime"""
        container = {
            "a": unittest.mock.MagicMock(spec_set=TimestampedCodeSource)
        }
        container["a"].__enter__ = lambda x: x
        container["a"].__exit__ = context_manager_exit
        container["a"].atime.configure_mock(side_effect=(9,))
        self.assertEqual(TimestampedCodeSourceContainer.atime(container, "a"), 9)
        container["a"].close.assert_called()
        with self.assertRaises(KeyError):
            TimestampedCodeSourceContainer.atime(container, "b")

    def test_info(self) -> None:
        """test TimestampedCodeSourceContainer.info"""
        info = SourceInfo(1, 2, 3)
        container = {
            "a": unittest.mock.MagicMock(spec_set=TimestampedCodeSource)
        }
        container["a"].__enter__ = lambda x: x
        container["a"].__exit__ = context_manager_exit
        container["a"].info.configure_mock(side_effect=(info,))
        self.assertEqual(TimestampedCodeSourceContainer.info(container, "a"), info)
        container["a"].close.assert_called()
        with self.assertRaises(KeyError):
            TimestampedCodeSourceContainer.info(container, "b")


#!/usr/bin/python3.4
# -*-coding:Utf-8 -*
'''module to manage Quality settings'''
import xml.etree.ElementTree as xmlMod
from usefullFunctions import *
from Preferences.PresetList.Preset.OSA import *
from Preferences.PresetList.Preset.ValueType.Size import *
import os

class Quality:
	'''class to manage Quality settings'''
	FORMATS = [ 'BMP', 'IRIS', 'PNG', 'JPEG', 'JPEG2000', 'TARGA', 'TARGA_RAW',\
				'CINEON', 'DPX', 'OPEN_EXR_MULTILAYER', 'OPEN_EXR', 'HDR', 'TIFF']
	COLOR_DEPTH = {
					'BMP'					:		[8],
					'IRIS'					:		[8],
					'JPEG'					:		[8],
					'TARGA'					:		[8],
					'TARGA_RAW'				:		[8],
					'CINEON'				:		[10],
					'PNG'					:		[8, 16],
					'TIFF'					:		[8, 16],
					'JPEG2000'				:		[8, 12, 16],
					'DPX'					:		[8, 10, 12, 16],
					'OPEN_EXR'				:		[16, 32],
					'OPEN_EXR_MULTILAYER'	:		[32],
					'HDR'					:		[32]
					}
	EXT = {
					'BMP'					:		'.bmp',
					'IRIS'					:		'.rgb',
					'JPEG'					:		'.jpg',
					'TARGA'					:		'.tga',
					'TARGA_RAW'				:		'.tga',
					'CINEON'				:		'.cin',
					'PNG'					:		'.png',
					'TIFF'					:		'.tif',
					'DPX'					:		'.dpx',
					'OPEN_EXR'				:		'.exr',
					'OPEN_EXR_MULTILAYER'	:		'.exr',
					'HDR'					:		'.hdr'
					}

	def __init__(self, xml= None):
		'''initialize Quality settings with default value or values extracted from an xml object'''
		if xml is None:
			self.defaultInit()
		else:
			self.fromXml(xml)

	def defaultInit(self):
		'''initialize Quality settings with default value'''
		self.pourcent = 100
		self.size = Size('1920x1080')
		self.samples = 1500
		self.simplify = None

		self.format = 'OPEN_EXR_MULTILAYER'
		self.colorDepth = 32
		self.JPEGquality = 100
		self.PNGcompression = 0

		self.JPEGcodec = 'J2K'
		self.JPEGcinema = False
		self.JPEGcinema48 = False
		self.JPEGycc = False
		self.DPXlog = False
		self.EXRcodec = 'NONE'
		self.EXRzbuffer = True
		self.EXRpreview = False

		self.OSA = OSA()

	def fromXml(self, xml):
		'''initialize Quality settings with values extracted from an xml object'''
		node = xml.find('resolution')
		self.pourcent = int(node.get('pourcent'))
		self.size = Size(xml = node)
		self.samples = int(xml.find('samples').get('value'))
		if xml.find('simplify') is not None:
			self.simplify = int(xml.find('simplify').get('value'))
		else:
			self.simplify = None
		node = xml.find('format')
		self.format = node.get('value')
		self.colorDepth = int(node.get('depth'))
		self.JPEGquality = int(node.get('quality'))
		self.PNGcompression = int(node.get('compression'))

		self.JPEGcodec = node.get('jpegCodec')
		self.EXRcodec = node.get('exrCodec')

		self.JPEGcinema = node.get('cinema', '0') == '1'
		self.JPEGcinema48 = node.get('cinema48', '0') == '1'
		self.JPEGycc = node.get('ycc', '0') == '1'
		self.DPXlog = node.get('dpxlog', '0') == '1'
		self.EXRzbuffer = node.get('zbuffer', '0') == '1'
		self.EXRpreview = node.get('previews', '0') == '1'

		self.OSA = OSA(xml.find('OSA'))

	def toXml(self):
		'''export Quality settings into xml syntaxed string'''
		txt = '<quality>\n'
		txt += '  <resolution pourcent="'+str(self.pourcent)+'" '+self.size.toXmlAttr()+' />\n'
		txt += '  <samples value="'+str(self.samples)+'" />\n'

		if self.simplify is not None:
			txt += '  <simplify value="'+str(self.simplify)+'" />\n'

		txt += '  <format value="'+self.format+'" depth="'+str(self.colorDepth)\
				+'" quality="'+str(self.JPEGquality)\
				+'" compression="'+str(self.PNGcompression)\
				+'" jpegCodec="'+self.JPEGcodec+'" exrCodec="'+self.EXRcodec+'" '

		if self.JPEGcinema:
			txt += 'cinema="1" '
		if self.JPEGcinema48:
			txt += 'cinema48="1" '
		if self.JPEGycc:
			txt += 'ycc="1" '
		if self.DPXlog:
			txt += 'dpxlog="1" '
		if self.EXRzbuffer:
			txt += 'zbuffer="1" '
		if self.EXRpreview:
			txt += 'preview="1" '

		txt += ' />\n'

		txt += self.OSA.toXml()

		txt += '</quality>\n'
		return txt

	def menu(self, log):
		'''menu to explore and edit Quality settings settings'''
		change = False
		log.menuIn('Quality')

		while True:

			log.print()

			self.print()

			print('''\n\n        Menu :
1- Edit Resolution Size
2- Edit Pourcent Setting
3- Edit Cycles Samples
4- Edit OSA settings (for Blender Render only)
5- Edit Simplify Setting
6- Edit Format''')

			if len(self.COLOR_DEPTH[self.format]) > 1:
				print('7- Change Color Depth')

			if self.format == 'PNG':
				print('8- Edit Compression Settings')
			elif self.format in ['JPEG', 'JPEG2000']:
				print('8- Edit Quality Settings')

			if self.format == 'JPEG2000':
				print('9- Edit JPEG2000 Codec Options')
			elif self.format == 'DPX':

				if self.DPXlog:
					print('9- Disable DPX Logarithmic colorspace')
				else:
					print('9- Enable DPX Logarithmic colorspace')

			elif self.format in ['OPEN_EXR', 'OPEN_EXR_MULTILAYER']:
				print('9- Edit EXR Codec Options')

			print('0- Quit\n\n')

			choice = input('Action?').strip().lower()

			if choice in ['0', 'q', 'quit', 'cancel']:
				log.menuOut()
				return change
			elif choice == '1':
				change = (self.size.edit(log, 'Resolution Size') or change)
			elif choice in ['2', '3']:
				change = (self.edit(log, int(choice)) or change)
			elif choice == '4':
				change = (self.OSA.menu(log) or change)
			elif choice == '5':
				change = (self.editSimplify(log) or change)
			elif choice == '6':
				change = (self.editFormat(log) or change)
			elif choice == '7' and len(self.COLOR_DEPTH[self.format]) > 1:
				change = (self.editColorDepth(log) or change)
			elif choice == '8' and self.format in ['PNG','JPEG', 'JPEG2000']:
				change = (self.editCompressionQuality(log) or change)
			elif choice == '9' and self.format in ['OPEN_EXR', 'OPEN_EXR_MULTILAYER', 'DPX', 'JPEG2000']:
				if self.format == 'DPX':
					self.DPXlog = not self.DPXlog
					log.write('DPX Logarithmic color space '\
							+{ True:'enabled', False:'disabled' }[self.DPXlog]+'.')
					change = True
				elif self.format == 'JPEG2000':
					change = (self.editJpeg2000(log) or change)
				elif self.format == 'OPEN_EXR':
					change = (self.editExr(log) or change)
				else:
					change = (self.editExrCodec(log) or change)
			else:
				log.error('Unvalid menu choice', False)

	def print(self):
		'''a method to print preset'''
		enable = { True:'enabled', False:'disabled' }
		print('Resolution :            '+self.size.toStr()+'@'+str(self.pourcent))
		print('Cycles Samples :        '+str(self.samples))
		print('Simplify :              '+self.getSimplify())

		if self.format in ['JPEG', 'JPEG2000']:
			print('Format :                '+self.format+' (@'\
						+str(self.JPEGquality)+'%)')
		elif self.format == 'PNG':
			print('Format :                '+self.format+' (@'\
						+str(self.PNGcompression)+'%)')
		else:
			print('Format :                '+self.format)

		print('Color Depth :           '+str(self.colorDepth))

		if self.format == 'JPEG2000':
			print('JPEG2000 Codec :        '+self.JPEGcodec)
			opt = ''
			if self.JPEGcinema:
				opt += 'cinema '
			if self.JPEGcinema48:
				opt += 'cinema48 '
			if self.JPEGycc:
				opt += 'YCC'
			print('JPEG2000 options :      '+opt)
		elif self.format == 'DPX':
			print('DPX Log :               '\
				+enable[self.DPXlog])
		elif self.format in ['OPEN_EXR', 'OPEN_EXR_MULTILAYER']:
			print('EXR codec :             '+self.EXRcodec)
			if self.format == 'OPEN_EXR':
				print('EXR zbuffer :           '+enable[self.EXRzbuffer])
				print('EXR previews :          '+enable[self.EXRpreview])

		self.OSA.print()

	def getSimplify(self):
		'''A method to get simplify setting'''
		if self.simplify is None:
			return 'Disabled'
		else:
			return str(self.simplify)+' subdiv'

	def edit(self, log, choice):
		'''A method to edit pourcent setting'''
		if choice == 2:
			log.menuIn('Edit Resolution Pourcent')
		else:
			log.menuIn('Edit Cycles Samples')

		while True:

			log.print()

			# print current setting and get new one
			if choice == 2:
				print('\n\n        Edit Pourcent :\nCurrent Pourcent : '+str(self.pourcent)+'\n')
				new = input('New pourcent setting?').strip().lower()
			else:
				print('\n\n        Edit Cycles Samples :\nCurrent Sammples : '+str(self.samples)+'\n')
				new = input('New Samples setting?').strip().lower()

			# exit menu
			if new in ['', 'q', 'quit', 'cancel']:
				log.menuOut()
				return False

			#check new setting
			try:
				new = int(new)
			except ValueError:
				log.error('New setting must be an integer.')
				continue

			if new < 0:
				log.error('New setting must be a positive integer.')
				continue

			# apply new setting and exit
			if choice == 2:
				self.pourcent = new
				log.write('Resolution pourcent setting is set to : '\
							+str(self.pourcent)+'%')
			else:
				self.samples = new
				log.write('Cycles samples set to : '+str(self.samples)+'%')
			log.menuOut()
			return True

	def editSimplify(self, log):
		'''A method to Edit Simplify settings'''
		log.menuIn('Edit Simplify settings')

		while True:

			log.print()

			# print current setting and get new one
			print('\n\n        Edit Simplify Settings :\nCurrent settings : '+self.getSimplify()+'\n')
			choice = input('New setting?').strip().lower()

			# exit menu
			if choice in ['', 'q', 'quit', 'cancel']:
				log.menuOut()
				return False

			#check new setting
			try:
				choice = int(choice)
			except ValueError:
				log.error('New setting must be an integer.')
				continue

			if choice < 0:
				log.error('New setting must be a positive integer.')
				continue

			if choice < 11:
				self.simplify = choice
			else:
				self.simplify = None
			log.write('Simplify set to : '+self.getSimplify())
			log.menuOut()
			return True

	def editFormat(self, log):
		'''A method to edit format settings'''

		log.menuIn('Choose Output Format')

		while True:

			log.print()

			print('\n\n        Edit Output Format :\n\nCurrent format : '+self.format)

			indexPrintList(self.FORMATS)

			choice = input('new format?').strip()

			if choice.lower() in ['', 'q', 'quit', 'cancel']:
				log.menuOut()
				return False

			try:
				choice = int(choice)
			except ValueError:
				log.error('An integer is expected!')
				continue

			if choice < 0 or choice >= len(self.FORMATS):
				log.error('Out of choice range!')
				continue

			self.format = self.FORMATS[choice]
			self.checkDepth(log)
			self.checkEXRcodec(log)
			log.write('Output format is set to : '+self.format)
			log.menuOut()
			return True

	def checkDepth(self, log):
		'''a method to check if current color depth is coherent with new set format'''
		depths = self.COLOR_DEPTH[self.format]

		if len(depths) == 1:
			self.colorDepth = depths[0]
		elif self.colorDepth not in depths:
			if self.colorDepth == 32:
				self.colorDepth = depths[-1]
			else:
				self.colorDepth = 16
		log.write('Color depth automatically set to '+str(self.colorDepth))

	def checkEXRcodec(self, log):
		'''check that EXR 16bit don't use B44 or B44A codec'''
		if self.format in ['OPEN_EXR', 'OPEN_EXR_MULTILAYER']\
			and self.colorDepth == 32 and self.EXRcodec in ['B44', 'B44A']:
			self.EXRcodec = 'NONE'
			log.write('EXR codec automatically set to none')

	def editColorDepth(self, log):
		'''a method to change color depth setting'''
		log.menuIn('Change Color Depth')
		depths = self.COLOR_DEPTH[self.format]
		while True:
			log.print()
			choice = input('\n\ncurrent settings : '+str(self.colorDepth)+' bits\n\navailable depth :['+ (','.join(str(x) for x in depths)) +'].\nwhat\'s the new depth (\'q\' to quit) :').lower().strip()

			if choice in ['0', 'q', 'quit', 'cancel']:
				log.menuOut()
				return False

			try:
				choice = int(choice)
			except ValueError:
				log.error('error, integer value expected!')
				continue

			if choice in depths:
				self.colorDepth = choice
				log.write('Color depth set to '+str(self.colorDepth))
				self.checkEXRcodec(log)
				log.menuOut()
				return True
			else:
				log.error('error, unvalid value! excpeted value are:'+(','.join(str(x) for x in depths)))

	def editCompressionQuality(self, log):
		'''a method to edit output compression (png) or quality (jpg)'''
		png = (self.format == 'PNG')
		if png:
			log.menuIn('Edit Compression')
			current = self.PNGcompression
		else:
			log.menuIn('Edit Quality')
			current = self.JPEGquality

		while True:
			log.print()

			choice = input('\n\nCurrent setting : '+str(current)\
					+'%\n\nNew settings (integer between 0 and 100 or "q" to quit) : ').strip().lower()

			if choice in ['q', 'quit', 'cancel']:
				log.menuOut()
				return False

			try:
				choice = int(choice)
			except ValueError:
				log.error('error, integer value expected!')
				continue

			if choice >= 0 and choice <= 100:
				if png:
					self.PNGcompression = choice
					log.write('PNG compression set to '+str(self.PNGcompression)+'.')
				else:
					self.JPEGquality = choice
					log.write('JPEG quality set to '+str(self.JPEGquality)+'.')

				log.menuOut()
				return True
			else:
				log.error('error, expect a value between 0 and 100, not «'+str(choice)+'»!')

	def editJpeg2000(self, log):
		'''a method to edit JPEG2000 codec specific settings'''
		enable = {True:'enabled', False: 'disabled'}
		action = {True:'Disable', False: 'Enable'}
		change = False
		log.menuIn('Edit JPEG2000 Settings')
		while True:
			log.print()

			self.print()

			print('\n\n        Menu:')

			if self.JPEGcodec == 'J2K':
				print('1- switch to JP2 codec')
			else:
				print('1- switch to J2K codec')

			print('2- '+action[self.JPEGcinema]+' cinema Option')
			print('3- '+action[self.JPEGcinema48]+' cinema48 Option')
			print('4- '+action[self.JPEGycc]+' YCC Option')

			menu = input('0- Quit\n\nMenu choice :').strip().lower()

			if menu in ['0', 'q', 'quit', 'cancel']:
				log.menuOut()
				return change

			if menu == '1':
				if self.JPEGcodec == 'J2K':
					self.JPEGcodec = 'JP2'
				else:
					self.JPEGcodec = 'J2K'
				change = True
				log.write('JPEG2000 codec set to '+self.JPEGcodec)
			elif menu == '2':
				self.JPEGcinema = not self.JPEGcinema
				change = True
				log.write ('JPEG2000 cinema option '+enable[self.JPEGcinema])
			elif menu == '3':
				self.JPEGcinema48 = not self.JPEGcinema48
				change = True
				log.write ('JPEG2000 cinema48 option '+enable[self.JPEGcinema48])
			elif menu == '4':
				self.JPEGycc = not self.JPEGycc
				change = True
				log.write ('JPEG2000 YCC option '+enable[self.JPEGycc])
			else:
				log.error('Unvalid choice, expect an integer value between 0 and 4')

	def editExr(self, log):
		'''a method to edit EXR codec specific settings'''
		enable = {True:'enabled', False: 'disabled'}
		action = {True:'Disable', False: 'Enable'}
		change = False
		log.menuIn('Edit EXR Settings')
		while True:
			log.print()

			self.print()

			print('\n\n        Menu:\n1- Choose EXR Codec')
			print('2- '+action[self.EXRzbuffer]+' zbuffer Option')
			print('3- '+action[self.EXRpreview]+' previews Option')

			menu = input('0- Quit\n\nMenu choice :').strip().lower()

			if menu in ['0', 'q', 'quit', 'cancel']:
				log.menuOut()
				return change

			if menu == '1':
				change = (self.editExrCodec(log) or change)
			elif menu == '2':
				self.EXRzbuffer = not self.EXRzbuffer
				change = True
				log.write ('EXR Z buffer '+enable[self.EXRzbuffer])
			elif menu == '3':
				self.EXRpreview = not self.EXRpreview
				change = True
				log.write ('EXR previews '+enable[self.EXRpreview])
			else:
				log.error('Unvalid choice, expect an integer value between 0 and 3')

	def editExrCodec(self, log):
		'''a method to choose EXR codec'''
		log.menuIn('Choose EXR Codec')

		codecs = ['quit', 'NONE', 'PXR24', 'ZIP', 'PIZ', 'RLE', 'ZIPS', 'DWAA', 'DWAB']

		if self.colorDepth == 16:
			codecs.append('B44')
			codecs.append('B44A')

		while True:
			log.print()

			self.print()

			print('\n\nCurrent EXR Codec : '+self.EXRcodec+'\n')

			indexPrintList(codecs)

			menu = input('\n\nMenu choice :').strip().lower()

			if menu in ['0', 'q', 'quit', 'cancel']:
				log.menuOut()
				return False

			try:
				menu = int(menu)
			except ValueError:
				log.error('integer value expected')
				continue

			if menu > 0 and menu < len(codecs):
				self.EXRcodec = codecs[menu]
				log.write('EXR codec set to '+self.EXRcodec)
				log.menuOut()
				return True
			else:
				log.error('unvalid choice, expect a value between 0 and '+str(len(codecs)-1)+'!')

	def apply(self, scene):
		'''apply settings to a blender scene object'''
		scene.render.resolution_percentage = self.pourcent
		scene.render.resolution_x = self.size.X
		scene.render.resolution_y = self.size.Y

		scene.cycles.use_square_samples = False
		scene.cycles.samples = self.samples

		if self.simplify is None:
			scene.render.use_simplify = False
		else:
			scene.render.use_simplify = True
			scene.render.simplify_subdivision_render

		scene.render.image_settings.file_format = self.format
		scene.render.image_settings.color_depth = str(self.colorDepth)
		scene.render.image_settings.quality = self.JPEGquality
		scene.render.image_settings.compression = self.PNGcompression

		scene.render.image_settings.use_cineon_log = self.DPXlog

		scene.render.image_settings.jpeg2k_codec = self.JPEGcodec
		scene.render.image_settings.use_jpeg2k_cinema_preset = self.JPEGcinema
		scene.render.image_settings.use_jpeg2k_cinema_48 = self.JPEGcinema48
		scene.render.image_settings.use_jpeg2k_ycc = self.JPEGycc

		scene.render.image_settings.exr_codec = self.EXRcodec
		scene.render.image_settings.use_zbuffer = self.EXRzbuffer
		scene.render.image_settings.use_preview = self.EXRpreview

		self.OSA.apply(scene)

	def getExtension(self):
		'''return file extension'''
		if self.format == 'JPEG2000':
			if self.JPEGcodec == 'J2K':
				return '.j2c'
			else:
				return '.jp2'

		return self.EXT[self.format]


import os

import azure.functions as func
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from utilities.exceptions import ApiException

from . import routes

if os.getenv("FUNCTIONS_WORKER_RUNTIME"):
    app = FastAPI(
        version="0.0.1",
        servers=[{"url": "/api", "description": "Azure Functions as a FastAPI server"}],
        root_path="/public",
        root_path_in_servers=False,
    )
else:
    app = FastAPI()

app.include_router(routes.router)

@app.exception_handler(ApiException)
async def generic_api_exception_handler(request: Request, error: ApiException):
    """
    Generic API exception handler.
    Ensures that all thrown exceptions of the custom type API Excpetion are
    returned in a unified format.
    Args:
        request (Request): HTTP Request
        error (ApiException): Thrown exception

    Returns:
        JSONResponse: Returns the exception in JSON format
    """
    return JSONResponse(
        status_code=error.status_code,
        content={"code": error.code, "description": error.description},
    )

async def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
    """
    Azure function entry point. All web requests are handled by FastAPI.
    Args:
        req (func.HttpRequest): Request
        context (func.Context): Azure Function Context

    Returns:
        func.HttpResponse: HTTP Response
    """
    return await func.AsgiMiddleware(app).handle_async(req, context)


import os
import subprocess
import textwrap

import pytest
from click_odoo import odoo, odoo_bin

# This hack is necessary because the way CliRunner patches
# stdout is not compatible with the Odoo logging initialization
# mechanism. Logging is therefore tested with subprocesses.
odoo.netsvc._logger_init = True

def _init_odoo_db(dbname, test_addons_dir=None):
    subprocess.check_call(["createdb", dbname])
    cmd = [odoo_bin, "-d", dbname, "-i", "base", "--stop-after-init"]
    if test_addons_dir:
        addons_path = [
            os.path.join(odoo.__path__[0], "addons"),
            os.path.join(odoo.__path__[0], "..", "addons"),
            test_addons_dir,
        ]
        cmd.append("--addons-path")
        cmd.append(",".join(addons_path))
    subprocess.check_call(cmd)

def _drop_db(dbname):
    subprocess.check_call(["dropdb", dbname])

@pytest.fixture(scope="module")
def odoodb(request):
    dbname = "click-odoo-contrib-test-{}".format(odoo.release.version_info[0])
    test_addons_dir = getattr(request.module, "test_addons_dir", "")
    _init_odoo_db(dbname, test_addons_dir)
    try:
        yield dbname
    finally:
        _drop_db(dbname)

@pytest.fixture(scope="function")
def odoocfg(request, tmpdir):
    addons_path = [
        os.path.join(odoo.__path__[0], "addons"),
        os.path.join(odoo.__path__[0], "..", "addons"),
    ]
    test_addons_dir = getattr(request.module, "test_addons_dir", "")
    if test_addons_dir:
        addons_path.append(test_addons_dir)
    odoo_cfg = tmpdir / "odoo.cfg"
    odoo_cfg.write(
        textwrap.dedent(
            f"""\
            [options]
            addons_path = {",".join(addons_path)}
            """
        )
    )
    yield odoo_cfg


from flask import Flask, render_template, request
import requests

app = Flask(__name__)

@app.route('/', methods=['GET'])

def home():
    return render_template('home.html')

@app.route('/pokeapi', methods=['GET', 'POST'])
def pokeapi():
    print(request.method)
    if request.method == 'POST':
        pokemon_name = request.form.get('pokemon_name')
        print(pokemon_name)
        url = f'https://pokeapi.co/api/v2/pokemon/{pokemon_name}'
        response = requests.get(url)
        if response.ok:
            pokemon_data = response.json()
            pokemon_list = []
            for pokemon in pokemon_data:
                get_pokemon_info = {
                    "Name": pokemon["name"],
                    "Abilities": pokemon["abilities"][0]['ability']['name'],
                    "BaseExperience": pokemon["base_experience"],
                    "FrontShinyURL": pokemon["sprites"]["front_shiny"],
                    "AttackBaseStat": pokemon["stats"][0]["base_stat"],
                    "HPBaseStat": pokemon["stats"][0]["base_stat"],
                    "DefenseBaseStat": pokemon["stats"][0]["base_stat"],
                }
                pokemon_list.append(get_pokemon_info)
            return render_template('pokeapi.html', pokemon_list=pokemon_list)
        else:
            "This pokemon does not exist"
    return render_template('pokeapi.html')

Documents/Coding Temple/Week 5 and 6 - Flask/Homework/app.py


from operator import attrgetter
from typing import Tuple

class Elf:
    def __init__(self) -> None:
        self._calories = []

    def add_calories(self, calories: int) -> None:
        self._calories.append(calories)

    @property
    def total_calories(self) -> int:
        return sum(self._calories)

def parse(file):
    elves = []
    with open(file, 'r') as f:
        elf = Elf()
        for line in (l.strip() for l in f):
            if line == '':
                elves.append(elf)
                elf = Elf()
            else:
                elf.add_calories(int(line))
        elves.append(elf)
    return elves

def calculate(elves: list[Elf]) -> Tuple[int, int]:
    getter = attrgetter('total_calories')
    sorted_list = sorted(elves, key=getter, reverse=True)
    return (sorted_list[0].total_calories, sum(map(getter, sorted_list[:3])))

def main():
    elves = parse('test.txt')
    result = calculate(elves)
    assert result[0] == 24000
    assert result[1] == 45000

    elves = parse('input.txt')
    result = calculate(elves)

    print(f'Pt1: {result[0]}')
    print(f'Pt2: {result[1]}')

if __name__ == '__main__':
    main()


# List where we store all the letters of the alphabet twice, so the list can loop.
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

# Defines our caesar function
def caesar(text, shift, direction):
  # Empty variable where we will store the ciphered text
  cipher_text = ""
  # For each character in text that cannot be found in the alphabet, we will keep in the same position.
  for char in text:
    if char not in alphabet:
      cipher_text += char
  # We will loop each letter in the text the user inputted. Each letter will get a new position depending on the shift setting and if the user chose to encode or decode.
  for letter in text:
    position = alphabet.index(letter)
    if direction == "encode":
      new_position = position + shift
    elif direction == "decode":
      new_position = position - shift
    cipher_text += alphabet[new_position]
  print(f"The {direction}d text is {cipher_text}")

#Imports and prints ASCII art logo.
import art
print(art.logo)
# Variable which we use to check if program should continue running or not. If user does not want to continue loop, they will write 'no' and the value will be changed to 'False'
should_continue = True

# While loop checks variable above and will loop as long as that value is True.
while should_continue == True:
  direction = input("Type 'encode' to encrypt, type 'decode' to decrypt:\n").lower()
  # If user inputs another statement other than encode or decode, while loop will break.
  if direction != "encode" and direction != "decode":
    print("Please type encode or decode")
    break

  text = input("Type your message:\n").lower()
  shift = int(input("Type the shift number:\n"))

  # If the shift input is greater than 26 (the no of characters of the alphabet) we will use the modulo function to calculate which position that character would have if the alphabet would loop. EX 45 would be 19.
  if shift > 26:
    shift = shift % 26
  # Run the caesar function
  caesar(text, shift, direction)

  # User input if they would like to run the program again. If no the should_continue will be changed to false and the while loop ends.
  user_input = input("Do you want to go again? Type 'yes' to continue or 'no' to exit: \n").lower()
  if user_input == "no":
    should_continue = False
    print("Goodbye")


import logging
import tkinter as tk
from typing import Callable, List

from pdf2reader.gui.pdf_page_grid_display import PdfPageGridDisplay
from pdf2reader.gui.tooltip import create_tooltip
from pdf2reader.pdf_file import PdfFile, SectionGroup

logger = logging.getLogger(__name__)

class SelectPagesToActionWindow:
    def __init__(self, title: str, pdf_file: PdfFile, save_callback: Callable[[List[int]], None],
                 checkbox_text: str = "", preselected_pages: List[int] = None,
                 enabled_pages: List[int] = None, show_crop: bool = True, custom_crop: List[int] = None,
                 show_sections: bool = False, show_sections_only_from_group: SectionGroup = None):
        self.pdf_file = pdf_file
        self.checkbox_text = checkbox_text
        self.save_callback = save_callback
        self._preselected_pages = preselected_pages
        self._enabled_pages = enabled_pages
        self._show_crop = show_crop
        self._custom_crop = custom_crop
        self._show_sections = show_sections
        self._show_section_only_from_group = show_sections_only_from_group

        self.window = tk.Toplevel()
        try:
            self.window.grab_set()  # Fails on some platforms (works on Windows)
        except:
            pass
        self.window.title(title)
        self.window.geometry("900x600")
        self.window.protocol("WM_DELETE_WINDOW", self._close_callback)

        self.page_checkboxes = {}

        self._setup_variables()
        self._setup_layout()

        for page_number in self._preselected_pages:
            self.page_checkboxes[page_number].select()

    def _setup_variables(self):
        self.is_pdf_opened = tk.BooleanVar()

        self.is_pdf_opened.set(True)

    def _setup_layout(self):
        self.controls = ControlsMenu(self.window, self.pdf_file, select_callback=self._select_callback_1_indexed,
                                     unselect_callback=self._unselect_callback_1_indexed,
                                     save_callback=self._save_callback)
        self.pages_view = PdfPageGridDisplay(self.window, is_pdf_opened=self.is_pdf_opened, pdf_file=self.pdf_file,
                                             create_page_additional_info=self._create_page_additional_info,
                                             show_crop=self._show_crop, custom_crop=self._custom_crop,
                                             show_sections=self._show_sections,
                                             show_sections_only_from_group=self._show_section_only_from_group,
                                             enabled_pages=self._enabled_pages)

        self.controls.pack(fill=tk.X, side=tk.TOP, expand=False)
        self.pages_view.pack(fill=tk.BOTH, side=tk.TOP, expand=True)

    def _save_callback(self):
        selected_pages = []
        for page_number, checkbox in self.page_checkboxes.items():
            checked_status = int(checkbox.getvar(checkbox.cget('variable')))
            if checked_status:
                selected_pages.append(page_number)
        self.save_callback(selected_pages)
        self.close()

    def _select_callback_1_indexed(self, page_numbers: List[int]):
        invalid_page_indexes = []
        for page_number in page_numbers:
            checkbox = self.page_checkboxes.get(page_number - 1)
            if checkbox:
                checkbox.select()
            else:
                if page_number < 1 or page_number > self.pdf_file.page_count:
                    invalid_page_indexes.append(page_number)
        if invalid_page_indexes:
            if len(invalid_page_indexes) > 20:
                invalid_page_indexes = invalid_page_indexes[:20] + ["..."]
            tk.messagebox.showerror("Invalid page indexes", f"Invalid page indexes: {invalid_page_indexes}. "
                                                            f"Ignoring them and selecting the rest.")

    def _unselect_callback_1_indexed(self, page_numbers: List[int]):
        invalid_page_indexes = []
        for page_number in page_numbers:
            checkbox = self.page_checkboxes.get(page_number - 1)
            if checkbox:
                checkbox.deselect()
            else:
                if page_number < 1 or page_number > self.pdf_file.page_count:
                    invalid_page_indexes.append(page_number)
        if invalid_page_indexes:
            if len(invalid_page_indexes) > 20:
                invalid_page_indexes = invalid_page_indexes[:20] + ["..."]
            tk.messagebox.showerror("Invalid page indexes", f"Invalid page indexes: {invalid_page_indexes}. "
                                                            f"Ignoring them and selecting the rest.")

    def _create_page_additional_info(self, master, page, page_number):
        frame = tk.Frame(master, padx=5)
        frame.pack(fill=tk.NONE, side=tk.TOP, expand=False)

        label = tk.Label(frame, text=f"page {page_number + 1} • ")
        label.pack(side=tk.LEFT, padx=0)

        checkbox = tk.Checkbutton(frame, text=self.checkbox_text, command=lambda: self._checkbox_callback(page_number))
        checkbox.pack(side=tk.LEFT, padx=0)

        self.page_checkboxes[page_number] = checkbox

        return frame

    def _checkbox_callback(self, page_number):
        checkbox = self.page_checkboxes[page_number]
        checked_status = checkbox.getvar(checkbox.cget('variable'))
        logger.debug(f"checkbox callback: {page_number}, status: {checked_status}")

    def _close_callback(self):
        self.close()

    def __del__(self):
        self.close()

    def close(self):
        try:
            self.window.grab_release()
        except:
            pass
        self.window.destroy()

class ControlsMenu(tk.Frame):
    def __init__(self, parent, pdf_file: PdfFile, select_callback: Callable[[List[int]], None],
                 unselect_callback: Callable[[List[int]], None], save_callback: Callable, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.pdf_file = pdf_file

        self.parent = parent
        self.select_callback = select_callback
        self.unselect_callback = unselect_callback
        self.save_callback = save_callback

        self._setup_layout()

    def _setup_layout(self):
        self.range_label = tk.Label(self, text="Range: ")
        self.tooltip_label = tk.Label(self, text="?")
        create_tooltip(self.tooltip_label, "Select pages for cropping. "
                                           "Use comma to separate page numbers. "
                                           "Use dash to specify a range (inclusive). "
                                           "Use ':' to specify a step. "
                                           "Use '*' to select all pages. "
                                           "For example '1,3,5-9:2' will select pages 1, 3, 5, 7, 9.")

        self.inputfield = tk.Entry(self)

        self.crop_button = tk.Button(self, text="Select range", command=self._select_button_callback)
        self.uncrop_button = tk.Button(self, text="Unselect range", command=self._unselect_button_callback)
        self.splitter = tk.Label(self, text=" | ")
        self.save_button = tk.Button(self, text="Save", command=self._save_button_callback)

        self.range_label.pack(side=tk.LEFT, padx=5)
        self.tooltip_label.pack(side=tk.LEFT, padx=5)
        self.inputfield.pack(side=tk.LEFT, padx=5)
        self.crop_button.pack(side=tk.LEFT, padx=5)
        self.uncrop_button.pack(side=tk.LEFT, padx=5)
        self.splitter.pack(side=tk.LEFT, padx=5)
        self.save_button.pack(side=tk.LEFT, padx=5)

    def _parse_select_text(self, select_text: str) -> List[int]:
        page_numbers = []
        if "*" in select_text:
            return list(range(1, 1 + self.pdf_file.page_count))
        for part in select_text.split(","):
            if "-" in part:
                start, end = part.split("-")
                if ":" in end:
                    end, step = end.split(":")
                else:
                    step = 1
                page_numbers.extend(range(int(start), int(end) + 1, int(step)))
            else:
                page_numbers.append(int(part))
        return page_numbers

    def _select_button_callback(self):
        select_text = self.inputfield.get()
        logger.debug(f"Select button callback text: {select_text}")
        try:
            # Parse select text to list of page numbers
            page_numbers = self._parse_select_text(select_text)
            logger.debug(f"Select button callback parsed page numbers (1-indexed): {page_numbers}")
            self.select_callback(page_numbers)
        except Exception as e:
            logger.error(f"Select button callback error: {e}")
            tk.messagebox.showerror("Invalid range", f"Invalid range: '{select_text}', error: {str(e)}")

    def _unselect_button_callback(self):
        select_text = self.inputfield.get()
        logger.debug(f"Unselect button callback text: {select_text}")
        try:
            # Parse select text to list of page numbers
            page_numbers = self._parse_select_text(select_text)
            logger.debug(f"Unselect button callback parsed page numbers (1-indexed): {page_numbers}")
            self.unselect_callback(page_numbers)
        except Exception as e:
            logger.error(f"Unselect button callback error: {e}")
            tk.messagebox.showerror("Invalid range", f"Invalid range: '{select_text}', error: {str(e)}")

    def _save_button_callback(self):
        self.save_callback()


import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.utils.rnn import pad_packed_sequence as unpack
from torch.nn.utils.rnn import pack_padded_sequence as pack

class SDEN(nn.Module):
    def __init__(self,vocab_size,embed_size,hidden_size,slot_size,intent_size,dropout=0.3,pad_idx=0):
        super(SDEN,self).__init__()

        self.pad_idx = 0
        self.embed = nn.Embedding(vocab_size,embed_size,padding_idx=self.pad_idx)
        self.bigru_m = nn.GRU(embed_size,hidden_size,batch_first=True,bidirectional=True)
        self.bigru_c = nn.GRU(embed_size,hidden_size,batch_first=True,bidirectional=True)
        self.context_encoder = nn.Sequential(nn.Linear(hidden_size*4,hidden_size*2),
                                                               nn.Sigmoid())
        self.session_encoder = nn.GRU(hidden_size*2,hidden_size*2,batch_first=True,bidirectional=True)

        self.decoder_1 = nn.GRU(embed_size,hidden_size*2,batch_first=True,bidirectional=True)
        self.decoder_2 = nn.LSTM(hidden_size*4,hidden_size*2,batch_first=True,bidirectional=True)

        self.intent_linear = nn.Linear(hidden_size*4,intent_size)
        self.slot_linear = nn.Linear(hidden_size*4,slot_size)
        self.dropout = nn.Dropout(dropout)

        for param in self.parameters():
            if len(param.size())>1:
                nn.init.xavier_uniform_(param)
            else:
                param.data.zero_()

    def forward(self,history,current):
        batch_size = len(history)
        H= [] # encoded history
        for h in history:
            mask = (h!=self.pad_idx)
            length = mask.sum(1).long()
            embeds = self.embed(h)
            embeds = self.dropout(embeds)
            lens, indices = torch.sort(length, 0, True)
            lens = [l if l>0 else 1 for l in lens.tolist()] # all zero-input
            packed_h = pack(embeds[indices], lens, batch_first=True)
            outputs, hidden = self.bigru_m(packed_h)
            _, _indices = torch.sort(indices, 0)
            hidden = torch.cat([hh for hh in hidden],-1)
            hidden = hidden[_indices].unsqueeze(0)
            H.append(hidden)

        M = torch.cat(H) # B,T_C,2H
        M = self.dropout(M)

        embeds = self.embed(current)
        embeds = self.dropout(embeds)
        mask = (current!=self.pad_idx)
        length = mask.sum(1).long()
        lens, indices = torch.sort(length, 0, True)
        packed_h = pack(embeds[indices], lens.tolist(), batch_first=True)
        outputs, hidden = self.bigru_c(packed_h)
        _, _indices = torch.sort(indices, 0)
        hidden = torch.cat([hh for hh in hidden],-1)
        C = hidden[_indices].unsqueeze(1) # B,1,2H
        C = self.dropout(C)

        C = C.repeat(1,M.size(1),1)
        CONCAT = torch.cat([M,C],-1) # B,T_c,4H

        G = self.context_encoder(CONCAT)

        _,H = self.session_encoder(G) # 2,B,2H
        weight = next(self.parameters())
        cell_state = weight.new_zeros(H.size())
        O_1,_ = self.decoder_1(embeds)
        O_1 = self.dropout(O_1)

        O_2,(S_2,_) = self.decoder_2(O_1,(H,cell_state))
        O_2 = self.dropout(O_2)
        S = torch.cat([s for s in S_2],1)

        intent_prob = self.intent_linear(S)
        slot_prob = self.slot_linear(O_2.contiguous().view(O_2.size(0)*O_2.size(1),-1))

        return slot_prob, intent_prob


import argparse
import chess
import chess.pgn

MAX_VISIT_GAMES = 100000

parser = argparse.ArgumentParser(description='Filter PGN file')
parser.add_argument('--inf', help="Specify input file")
parser.add_argument('--outf', help="Specify output file")
parser.add_argument('--minrtg', help="Specify minimum rating")

args = parser.parse_args()

print(args)

MIN_RTG = 1500

if args.minrtg:
	MIN_RTG = int(args.minrtg)

pgn = open(args.inf)

cnt=0

found=0

pgns = []

class HeaderVisitor(chess.pgn.BaseVisitor):
	def __init__(self):
		self.game = chess.pgn.Game()

		self.variation_stack = [self.game]
		self.starting_comment = ""
		self.in_variation = False

	def visit_header(self, tagname, tagvalue):
		self.game.headers[tagname] = tagvalue

	def result(self):
		return self.game

while cnt<MAX_VISIT_GAMES:
	rawgame = chess.pgn.read_game(pgn)
	if rawgame==None:
		break
	white_elo = 1500
	black_elo = 1500

	try:
		white_elo = int(rawgame.headers["WhiteElo"])
		black_elo = int(rawgame.headers["BlackElo"])
	except:
		pass

	cnt+=1

	if white_elo >= MIN_RTG and black_elo >= MIN_RTG:
		found+=1
		print("{:5d} {:5d}".format(cnt,found))

		exporter = chess.pgn.StringExporter(headers=True, variations=True, comments=True)
		pgn_string = rawgame.accept(exporter)

		pgns.append(pgn_string)

with open(args.outf,"w") as outfile:
	outfile.write("\n\n\n".join(pgns)+"\n\n\n")