import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

student_data = pd.read_csv(
    "data/HSLS_2016_v1_0_CSV_Datasets/hsls_16_student_v1_0.csv", na_values=[-9, -8, -5, -7, -4, -3])
student_data.head()

# -9 = No Unit Response
# -8 = Missing
# -5 = Supressed
# -7 = Skipped
# -4 = Question not adminstered
# -3 = Carry through missing
# Sort by the first gathered predictor variables

# Getting columns that start with certain keywords
filter_col = [col for col in student_data if col.startswith('S1') or col.startswith('X1') or col.startswith('A1') or col.startswith(
    'C1')or col.startswith('STU_ID')]
X = student_data[filter_col]

updated_predictor_col_count = X.isna().sum()
df = updated_predictor_col_count / len(X)
df.to_csv("figures/missingness_imputation_missingness_per_predictor.csv")

# Only take columns with less than 15% of the data missing
X = X[X.columns[X.isnull().mean() < 0.15]]

# Median Imputation
updated_predictor_col = X.fillna(
    X.median())
updated_predictor_col.head()

fig, ax = plt.subplots(figsize=(10, 6.7))
sns.set_style('whitegrid')
sns.countplot(x='X1SEX', data=X, palette="mako")
sns.countplot(x='X1RACE', data=X, palette="mako")

X.columns

# Export to CSV file
updated_predictor_col.to_csv("data/processed/baseline_features.csv", index=False)


class CNN():
    def __init__(self, input_shape):
        self.mInput_shape = input_shape

    def buildModel(self):
        model = Sequential()
        model.add(Conv2D(14, kernel_size=3, padding='same', activation='relu', input_shape= self.mInput_shape))
        model.add(MaxPool2D((2,2), padding='same'))
        model.add(Dropout(0.2))
        model.add(Conv2D(7, kernel_size=3, padding='same', activation='relu'))
        model.add(MaxPool2D((2,2), padding='same'))
        model.add(Dropout(0.2))
        model.add(Conv2D(7, kernel_size=3, padding='same', activation='relu'))
        model.add(UpSampling2D((2,2)))
        model.add(Dropout(0.2))
        model.add(Conv2D(14, kernel_size=3, padding='same', activation='relu'))
        model.add(UpSampling2D((2,2)))
        model.add(Dropout(0.2))
        model.add(Conv2D(1, kernel_size=3, padding='same', activation='relu'))
        return model

    def printDataSet(self, y_test, restored_testing_dataset, x_test):
        plt.figure(figsize=(20,5))
        for i in range(10):
            index = y_test.tolist().index(i)
            plt.subplot(2, 10, i+1)
            plt.imshow(x_test[index].reshape((28,28)))
            plt.gray()
            plt.subplot(2, 10, i+11)
            plt.imshow(restored_testing_dataset[index].reshape((28,28)))
            plt.gray()

# Build the autoencoder
input_shape = (28,28,1)
x_train = x_train.reshape(-1,28,28,1) / 255
x_test = x_test.reshape(-1,28,28,1) / 255
epoch = 5

cnn =  CNN(input_shape)
model = cnn.buildModel()
model.compile(optimizer='adam', loss="mse")
model.summary()
autoEncoder = model.fit(x_train, x_train, epochs=epoch, batch_size=128, validation_split=0.2, verbose=1)
restored_testing_dataset = model.predict(x_test)
print(restored_testing_dataset.shape)
cnn.printDataSet(y_test, restored_testing_dataset, x_test)
printLoss(autoEncoder, epoch)


"""Utilities for parsing isoformat strings into datetime types.
"""

from datetime import datetime, date, time

def datetimefromisoformat(s):
    """Parse an isoformat string into a datetime.datetime object.
    """
    date, time = s.split()
    year, month, day = _parsedate(date)
    hour, minute, second, microsecond = _parsetime(time)
    return datetime(year, month, day, hour, minute, second, microsecond)

def datefromisoformat(s):
    """Parse an isoformat date string into a datetime.date object.
    """
    year, month, day = _parsedate(s)
    return date(year, month, day)

def timefromisoformat(s):
    """Parse an isoformat time string into a datetime.time object.
    """
    hour, minute, second, microsecond = _parsetime(s)
    return time(hour, minute, second, microsecond)

def _parsedate(s):
    """Parse an isoformat date string into a (year, month, day) tuple.
    """
    return [int(i) for i in s.split('-')]

def _parsetime(s):
    """Parse an isoformat time string into a (hour, minute, second,
    microsecond) tuple.
    """

    # The microseond is optional
    if '.' in s:
        time, microsecond = s.split('.')
        microsecond = int(microsecond)
    else:
        time, microsecond = s, 0

    hour, minute, second = [int(i) for i in time.split(':')]

    return hour, minute, second, microsecond

if __name__ == '__main__':

    import unittest

    now = datetime.now()
    today = date.today()
    midnight = time()

    class Tests(unittest.TestCase):

        datetimeTests = [
            [str(now), str(now)],
            [str(now.replace(microsecond=0)), str(now.replace(microsecond=0))],
            [str(now.replace(second=0, microsecond=0)), str(now.replace(second=0, microsecond=0))],
            [str(now.replace(second=0)), str(now.replace(second=0))],
            ]

        dateTests = [
            [str(today), str(today)],
            ]

        timeTests = [
            [str(time(0,0,0)),'00:00:00'],
            [str(time(1,2,3)),'01:02:03'],
            [str(time(1,2,3,4)),'01:02:03.000004'],
            ]

        def test_datetime(self):
            for test,expected in self.datetimeTests:
                result = str(datetimefromisoformat(test))
                self.assertEqual(expected, result)

        def test_date(self):
            for test,expected in self.dateTests:
                result = str(datefromisoformat(test))
                self.assertEqual(expected, result)

        def test_time(self):
            for test,expected in self.timeTests:
                result = str(timefromisoformat(test))
                self.assertEqual(expected, result)

    unittest.main()


import argparse
import importlib
from collections import namedtuple
from typing import Dict

CommandInfo = namedtuple("CommandInfo", "module_path, class_name")

commands_dict: Dict[str, CommandInfo] = {
    "download": CommandInfo("gtd.cli.download", "DownloadCommand"),
    "export": CommandInfo("gtd.cli.export", "ExportCommand"),
    "ts": CommandInfo("gtd.cli.ts", "TsCommand"),
}

class Command:
    def __init__(self, name: str) -> None:
        self.name = name

    def run(self, args: argparse.Namespace) -> int:
        raise NotImplementedError

def create_command(name: str) -> Command:
    """
    Create an instance of the Command class with the given name.
    """
    module_path, class_name = commands_dict[name]
    module = importlib.import_module(module_path)
    command_class = getattr(module, class_name)
    command: Command = command_class(name=name)

    return command


#!/local/data/atorus1/dora/Compilers/epd-7.3-1-rh5-x86_64(1)/bin/python

##!/Library/Frameworks/Python.framework/Versions/Current/bin/python
##!/Users/dora/Library/Enthought/Canopy_32bit/User/bin/python

import scipy
from  numpy import ndarray, zeros, array, size, sqrt, meshgrid, flipud, floor, where, amin, argmin,int
import numpy as nm
from mpl_toolkits.mplot3d import Axes3D
from pylab import *
import pprint
import os
import glob
import time
import os
import time
import cPickle as pickle
from matplotlib import colors
import socket
from mpl_toolkits.axes_grid1 import AxesGrid, ImageGrid

from scipy import trapz
from matplotlib import pyplot as plt
from physics1 import *

import physics1 as ph

phToSHow = 1
import AthenaModel as ath

def plotFormat(ax1,ax2=None,ax3=None,im=None):
#     from mpl_toolkits.axes_grid1 import make_axes_locatable

    fontsize_bar=14
    fz = 16

#     ax1.set_ylabel('$\tau N(\tau(\theta)>1)$', fontsize = 22)
#     ax1.set_title('Obscuring models', fontsize = 19)
#
#     ax1.set_ylabel('log (Number of obscuring models)', fontsize = 19)
#     for ylabel in ax.get_yticklabels():
#         ylabel.set_fontsize(fontsize_x)
#
#     ax1.set_xlabel('Inclination angle', fontsize=fz)
    ax[0].set_ylabel('$\log(N_{col})$', fontsize=fz)
#     for xlabel in ax1.get_xticklabels():
#         xlabel.set_fontsize(fontsize_x)
#
#     ax1.set_title('Column density $(cm^{-2})$', fontsize =fz)

    fig.subplots_adjust(wspace=0.2)
#     plt.setp([a.get_yticklabels() for a in fig.axes[1:] ], visible=False)

#     ax1.set_ylabel('$log (N_{col})$', fontsize = 19)

#     for ylabel in ax.get_yticklabels():
#         ylabel.set_fontsize(fontsize_x)
#
#     ax2.set_xlabel('Inclination angle', fontsize = 19)
#     for xlabel in ax.get_xticklabels():
#         xlabel.set_fontsize(fontsize_x)

#     divider = make_axes_locatable(ax)
#     cax = divider.append_axes("right", size="5%", pad=0.05)
#
#     if (im):
#         cb =plt.colorbar(im, cax=cax)
#         for t in cb.ax.get_yticklabels():
#             t.set_fontsize(fontsize_bar)

def cellTrace(dat, th, Xsrc_x_z, phToSHow):
        tiny = 1e-18
        i_s = dat.i_s
        ie = dat.ie
        js = dat.js
        je = dat.je

        zout = dat.x[je] / nm.tan(th) + Xsrc_x_z[1]

        ic = abs(dat.z - zout).argmin()
        jc = je

#         xcur = nm.array([ dat.x[jc], dat.z[ic] ])

        xcur = nm.array([ dat.x[dat.je], zout ])

        xsrc0= Xsrc_x_z

        a = xcur - xsrc0

        norm = (xcur - xsrc0)/nm.dot( xcur - xsrc0, xcur - xsrc0)
        #crossing x_{js} plane
        xz1 =nm.array([ dat.x[js+1], norm[1]/max(norm[0], tiny)*(dat.x[js+1] - xsrc0[0]) + xsrc0[1] ])

#         i =  minloc((dat. z -xz1[1]) **2)
        i = abs(dat.z - xz1[1]).argmin()
        if i>=dat.ie or i==dat.i_s: return(0.,0.)

        j = dat.js
        xz0 = nm.array([ dat.x[j], dat.z[i] ])

        stp = 0
        dstot = 0.
        tau = 0.
        dtau = 0.
        dcol_dns = 0.
        col_dns = 0.

        dl = 0.

        while True:

                xz1 =nm.array([ dat.x[j+1], #crossing x_{j+1} plane
                    norm[1]/max(norm[0], tiny)*(dat.x[j+1] - xsrc0[0]) + xsrc0[1] ])

                Sx = sqrt(nm.dot(xz1 - xz0, xz1-xz0))

                itm = i+  nm.int( nm.sign( norm[1] ) )# crossing z_{i+-1} plane

                if (norm[1] != 0.):
                    xz2 =nm.array([ norm[0]/norm[1] *(dat.z[itm] - xsrc0[1]) + xsrc0[0],
                                dat.z[itm] ])
                else:
                    xz2 =nm.array([ norm[0]/nm.max(norm[1],tiny)*(dat.z[itm] - xsrc0[1]) + xsrc0[0],
                                dat.z[itm] ])

                Sz = sqrt(nm.dot(xz2 - xz0, xz2-xz0))

                if (Sz>Sx):
                    dl = Sx  #right
                    xz0 = xz1
                    j += 1
                else:
                    dl = Sz #up or down
                    xz0 = xz2
                    i = itm

                dstot += dl
                stp += 1
                opac = ph.KPE

#                 print "here", dat.Rsc, dat.Dsc,  dat.ro[i,phToSHow, j],  opac, dl,i,j

                dtau = dat.Rsc*dat.Dsc* dat.ro[i,phToSHow,j]* opac * dl

                dcol_dns = nm.fabs( dat.ro[i, phToSHow, j]*dat.n0* dat.Rsc*dl)

                tau += dtau
                col_dns += dcol_dns
#                 print i, j, stp

                if  ( i <= dat.i_s or i >= dat.ie or j <= dat.js or j >= dat.je-1):
                    break
                if  i==ic and j ==jc :
                    break

        return(tau, col_dns)

def transmisionFunctionsAngleGrid(dat, printResults=False):
    Nth = 100

    Xsrc = array([0, 0])

#     res = dat.x[dat.js]/dat.z[dat.ie]
#     thmax = nm.pi / 2
    thmin = nm.arctan2(dat.x[dat.js], dat.z[dat.ie]-Xsrc[0] )

    thmax =nm.arctan2(dat.x[dat.js], dat.z[dat.i_s]-Xsrc[0])

    angle = linspace(thmin, thmax, Nth)

#     print angle, range(1,Nth)
#     time.sleep(3)

    tauTheta = zeros(Nth)
    colDens = zeros(Nth)

    for k,th in zip(range(1,Nth), angle):
#         th = nm.pi/2
#         print k,th
#         time.sleep(3)
        tauTheta[k], colDens[k] = cellTrace(dat, th, Xsrc_x_z = [Xsrc[1], Xsrc[0]], phToSHow =phToSHow)
#         print("tau=", tauTheta[k], "colDens=", colDens[k], th, Nth)

#         exit(); time.sleep(3)

    if printResults:
        fig  = plt.figure()
        ax = fig.add_subplot(111)
        funcToPlot =  log10(colDens)
        funcToPlot =  tauTheta
        ax.plot(angle*180./nm.pi, funcToPlot)
        show()

    return(tauTheta,colDens, angle)

def iteratorOverDataDirectoriesOverHDfFiles(basePath, dataDir,
                                            simParamFileDir, locdirList2, funcToCalculate, fileToSavePrefix):

    mod={}
    maxNumFile = 500

    dat =ath.athDataModel()

    for dirName, i in zip(locdirList2, range(size(locdirList2))):

        mod.update({ locdirList2[i]:{'ang':[], 'tau':[], 'cdens':[] }})
        simTime = []

        nFile = 0.
        dat.loadSimulationParam(simParamFileDir + 'athinput.torus9_hydro_2D', print_res=True)

        scale = 1.
        dat.n0 /= scale
        dat.Dsc/=scale

        filelist = glob.glob(os.path.join(dataDir, 'mhdXwind*.bin') )

        for fileInDir in sorted(filelist):
               try:
                  dat.loadDataFromBinFiles(fileInDir, dat, printDetail=False)
                  print("file to open:", fileInDir)
               except:
                 print("skip file:", fileInDir)
                 break

             #  torMass = dat.torusMass(dat)

               # print(torMass/MSOL)
               # exit()

               tau, cdens, ang  = funcToCalculate(dat, printResults=False)

#                 print tau, cdens, ang

               mod[locdirList2[i]]['tau'].append(tau.tolist())
               mod[locdirList2[i]]['cdens'].append(cdens.tolist())

               if not mod[ locdirList2[i]]['ang']  :
                   mod[locdirList2[i]]['ang'].append(ang.tolist())

               simTime.append(nFile)
               nFile+=1
               if (nFile > maxNumFile):
                    print ("maxNumFile reached")
                    break

        mod[ locdirList2[i] ].update( {'par': dat.par  })

        mod[ locdirList2[i] ]['par'].update( {'dt_bin': dat.dt_bin })

    return(mod)

def plotOnePane(ax, scale,Ncol_min, Ncol_max):

    Nd = len(locdirList2)

    Na = len(mdat[locdirList2[0]] ['ang'][0])
    Ny = len(mdat[locdirList2[0]] ['tau'])

    Nm=0
    distribFun1 = zeros(Na)
    distribFun2 = zeros(Na)
    col_max=0
    col_min = 1e30

    lineType = ['-', '--', '-o', '-*']
    color = ['k', 'b', 'g', 'r']
    markerWidth = [2,2,2,2]

    for i_types in xrange(Nd):

        for j_y in  xrange(Ny):
            for k_ang in  xrange(Na):
                angl = mdat[locdirList2[i_types]] ['ang'][0][k_ang]
                tau= mdat[locdirList2[i_types]] ['tau'][j_y][k_ang]
                col= mdat[locdirList2[i_types]] ['cdens'][j_y][k_ang]

                if col > col_max:
                    col_max = col
                if col <= col_min:
                    col_min = col
                Nm +=1
                if tau>1.:
                    distribFun1[k_ang] +=1

        NBINS = 10
        colDens, dColdens = nm.linspace(col_min, col_max, NBINS, retstep=True)

        NANG = 50
        angle = nm.linspace(0., nm.pi, NANG, retstep=True)

        ang_scat = []
        Ncol_scat = []

        simTime = []

        told  = 0
        dt_bin = mdat[locdirList2[0]] ['par']['dt_bin']

        for j_y in  xrange(Ny):

            tnew = told + dt_bin
            simTime.append(tnew)
            told=tnew

            for k_ang in  xrange(Na):

                angl = mdat[locdirList2[i_types]] ['ang'][0][k_ang]
                col= mdat[locdirList2[i_types]] ['cdens'][j_y][k_ang]

                scale_m = 1.+  (col - Ncol_min)/(Ncol_max-Ncol_min)*(scale -1)
                col /= scale_m

                Ncol_scat.append(col)
                ang_scat.append(angl)

        x = nm.array(mdat[locdirList2[0]]['ang'][0])
        imax=  distribFun1.argmax()
        thmax = x[imax] - nm.pi/2.
        x=x-thmax

#         print(thmax)

        loc1='lower center'
        simTimeArr =nm.array(simTime)

        print (len(Ncol_scat))
#         eps = 1.e-2
#         Ncol_scat[Ncol_scat<eps]=eps

        if i_types==0:

#             color = [str(y/100. ) for y in simTimeArr]
#             color = matplotlib.cm.rainbow(color)
#             print color
#             color = [simTime,simTime]
#             x = np.random.rand(100)
#             y = np.random.rand(100)
#             t=x
#             print t
#             plt.scatter(x, y, c=t)
#             plt.show()

            print (nm.array(ang_scat))

            x1 =(nm.array(ang_scat))*180./nm.pi - 0

            y1= log10( Ncol_scat )

#             print  len(x),len(y), len(simTime);exit()

            cm = plt.cm.get_cmap('RdYlBu')
            ax.scatter( x1, y1, cmap=cm)

#             .xlim((0,185))

#             fig.colorbar(sc)
#             ax1.scatter( x,y, c=simTime)
# #
#         ax1 = fig.add_subplot(131)
#         ax1.plot(x*180./nm.pi, log10(distribFun1),  lineType[i_types], color=color[i_types], linewidth=markerWidth[i_types]

#         ax1.legend(('$\Gamma=0.01$', '$\Gamma=0.05$', '$\Gamma=0.1$', '$\Gamma=0.3$'),
#                         shadow = False, loc = loc1)
        if i_types==1:
            ax2 = fig.add_subplot(142,sharey=ax1)
            ax2.scatter((nm.array(ang_scat)-thmax)*180./nm.pi, log10(Ncol_scat), color=color[i_types])

#         ax2.legend(('$\Gamma=0.01$', '$\Gamma=0.05$', '$\Gamma=0.1$', '$\Gamma=0.3$'),
#                         shadow = False, loc = loc1)
        if i_types==2:
            ax3 = fig.add_subplot(143,sharey=ax1)
            ax3.scatter((nm.array(ang_scat)-thmax)*180./nm.pi, log10(Ncol_scat), color=color[i_types])
#         ax2.legend(('$\Gamma=0.01$', '$\Gamma=0.05$', '$\Gamma=0.1$', '$\Gamma=0.3$'),
#                         shadow = False, loc = loc1)
        if i_types==3:
            ax3 = fig.add_subplot(144,sharey=ax1)
            ax3.scatter((nm.array(ang_scat)-thmax)*180./nm.pi, log10(Ncol_scat), color=color[i_types])

# ----------------------------------------------------------------------------
#                                    the MAIN
# ----------------------------------------------------------------------------

whatToDo = 'calculTauAndColDens'

#whatToDo = 'processTauAndColDensFromFile'

dat =ath.athDataModel()

if socket.gethostname()=='atorus':

 #   locDirList = ['/local/data/atorus2/dora/HW_Jan201707_256x8x256_L0.5n10e8']

    locDirList = ['/local/data/atorus1/dora/PROJECTS/AthenaWind']
    basePath = locDirList[0]

    if os.path.isdir( basePath +'/bin' ):
      dataDir = basePath+'/bin/'
      locdirList2 = ['']
      simParamFileDir = basePath+'/tst/cylindrical/'
#      print(simParamFileDir); exit()

    else:
      dataDir = basePath+'/'
      locdirList2 = ['']
      simParamFileDir = basePath+'/'

    if  whatToDo == 'processTauAndColDensFromFile':

        pathToPickledFile = dataDir
        fileNameList = ['multiDat_TauColDensVsAngle.p', 'multiDat_TauColDensVsAngle.p']
        locdirList2 = ['']

    put_out= '/local/data/atorus1/dora/PROJECTS/SCRIPTS/T9'
    put_FIG= '/local/data/atorus1/dora/PROJECTS/SCRIPTS/T9'

else:
    if whatToDo == 'calculTauAndColDens' :
         locdirList = [ 'SolovievSep201615_256x8x256_L0.n10e10/']
         locdirList = [ 'runDec201608_256x8x256_L0.5n10e8/']
         put_out= '/Users/dora/WORK/ECLIPSE_SPACE/torus9'
         put_FIG = '/Users/dora/Documents/TEX/torus9/'
         locdir = locdirList[0]
         dirFileToReadBase = os.getcwd()
         dataDir = '/DATA/'
         dirFileToReadBase = os.getcwd()
         dataDir = '/DATA'
         dirToRead = dirFileToReadBase + dataDir+locdirList[0]
         dat.loadSimulationParam(dirToRead + 'athinput.torus9_hydro_2D', print_res=True)

    elif whatToDo == 'processTauAndColDensFromFile':
        pathToPickledFile = '/Users/dora/WORK/ECLIPSE_SPACE/torus9/'
        fileNameList = ['SOL_multiDat_TauColDensVsAngle.p', 'HW_multiDat_TauColDensVsAngle.p']
        locdirList2 = ['']
        put_FIG = '/Users/dora/Documents/TEX/torus9/'

if whatToDo == 'calculTauAndColDens':

        print('files =', basePath, dataDir,simParamFileDir)

        multiDat=iteratorOverDataDirectoriesOverHDfFiles(basePath, dataDir,simParamFileDir,locdirList2,
                                            transmisionFunctionsAngleGrid, fileToSavePrefix=False)

#         for i_type_mod in xrange(len(locdirList2)):

        fileToSavePrefix ='multiDat_TauColDensVsAngle.p'
        filename = dataDir + fileToSavePrefix

        pickle.dump(multiDat, open(filename, "wb"))

        # try:
        #     nm.savetxt(filename,  list(multiDat))
        #     print("saving to ",  filename)
        # except IOError:
        #     print('cannot save to', filename)

        multiDat=[]

        print("calculTauAndColDens ..done");
        exit()

if whatToDo =='processTauAndColDensFromFile':

    fileName = fileNameList[0]
    filename = pathToPickledFile + fileName

    fig, ax = plt.subplots(1, 2, sharey=True)

    for filename, np in zip(fileNameList, range(len(fileNameList))):
        mdat = pickle.load( open( filename, "rb" ) )

        Ncol_min  = 10**21
        Ncol_max  = 10**27.4

        if np==0:
            scale = 1
        else:
            scale =12

        plotOnePane(ax[np],scale, Ncol_min, Ncol_max)

    plotFormat(ax[np])
    fig.suptitle('Column density $(cm^{-2})$', y=0.95, fontsize=16)

    fig.text(0.5, 0.02, 'Inclination angle', ha='center', fontsize=16)

    put_out= '/Users/dora/Documents/TEX/torus9/'
    fileNameToSave = put_out+'colDensInclAngleAllModels'
#     fig.savefig(fileNameToSave + ".pdf", format='pdf')

    show()

print('END OF PROGRAM')

#                 idxa = (np.abs(angle-angl)).argmin()
#                 idxc = (np.abs(colDens-col)).argmin()

#     Ncol = nm.sort(distribFun2)
#     indx = nm.argsort(distribFun2)
#     for i in indx:
#     cmin = distribFun2[0]
#     cmax = distribFun2[len(distribFun2)-1]

#     for i_type_mod in xrange(len(locdirList2)):
#         print("model", i_type_mod)
#         for yin_dir, j in zip(mdat[locdirList2[i_type_mod]]['tau'], xrange(N)):
#             ax.plot(x[0], log10(yin_dir))


from aiogram import types, Dispatcher
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters import Text
from aiogram.dispatcher.filters.state import State, StatesGroup
from keyboards import admin_batton
from create_bot import bot, dp
from data_base import sqlite_db
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup

ID = None

class FSMAdmin(StatesGroup):
    photo = State()
    name = State()
    description = State()
    price = State()

# @dp.message_handler(commands=['moderator'], is_chat_admin=True)
async def make_changes_command(message: types.Message):
    global ID
    ID = message.from_user.id
    await bot.send_message(message.from_user.id, "Что нужно хозяин?", reply_markup=admin_batton.button_case_admin)

# @dp.message_handler(commands='Загрузить', state=None)
async def cm_start(message: types.Message):
    if message.from_user.id == ID:
        await FSMAdmin.photo.set()
        await message.reply("Загрузи фото")

# @dp.message_handler(state="*", commands='отмена')
# @dp.message_handler(Text(equals='отмена', ignore_case=True), state="*")
async def cansel_handler(message: types.Message, state: FSMContext):
    if message.from_user.id == ID:
        current_state = await state.get_state()
        if current_state is None:
            return
        await state.finish()
        await message.reply('OK')

# @dp.message_handler(content_types=['photo'], state=FSMAdmin.photo)
async def load_photo(message: types.Message, state: FSMContext):
    if message.from_user.id == ID:
        async with state.proxy() as data:
            data['photo'] = message.photo[0].file_id

        await FSMAdmin.next()
        await message.reply('Теперь название')

# @dp.message_handler(state=FSMAdmin.name)
async def load_name(message: types.Message, state: FSMContext):
    if message.from_user.id == ID:
        async with state.proxy() as data:
            data['name'] = message.text

        await FSMAdmin.next()
        await message.reply('Введи описание')

# @dp.message_handler(state=FSMAdmin.description)
async def load_description(message: types.Message, state: FSMContext):
    if message.from_user.id == ID:
        async with state.proxy() as data:
            data['description'] = message.text

        await FSMAdmin.next()
        await message.reply('Какова цена?')

# @dp.message_handler(state=FSMAdmin.price)
async def load_price(message: types.Message, state: FSMContext):
    if message.from_user.id == ID:
        async with state.proxy() as data:
            data['price'] = float(message.text)

        await sqlite_db.sql_add_command(state)
        await state.finish()

@dp.callback_query_handler()
async def del_callback_run(callback_query: types.CallbackQuery):
    await sqlite_db.delete_command(callback_query.data.replace('del ', ''))
    await callback_query.answer(text=f'{callback_query.data.replace("del ", "")} удалена.', show_alert=True)

@dp.message_handler(commands='Удалить')
async def delete_item(message: types.Message):
    if message.from_user.id == ID:
        read = await sqlite_db.sql_read2()
        for ret in read:
            await bot.send_photo(message.from_user.id, ret[0], f'{ret[1]}\nОписание: {ret[2]}\nЦена {ret[-1]}')
            await bot.send_message(message.from_user.id, text='^^^', reply_markup=InlineKeyboardMarkup(). \
                                   add(InlineKeyboardButton(f'Удалить {ret[1]}', callback_data=f'del {ret[1]}')))

def register_handler_admin(dp: Dispatcher):
    dp.register_message_handler(cm_start, commands=['Загрузить'], state=None)
    dp.register_message_handler(cansel_handler, state="*", commands='отмена')
    dp.register_message_handler(cansel_handler, Text(equals='отмена', ignore_case=True), state="*")
    dp.register_message_handler(load_photo, content_types=['photo'], state=FSMAdmin.photo)
    dp.register_message_handler(load_name, state=FSMAdmin.name)
    dp.register_message_handler(load_description, state=FSMAdmin.description)
    dp.register_message_handler(load_price, state=FSMAdmin.price)
    dp.register_message_handler(make_changes_command, commands=['moderator'], is_chat_admin=True)
    # dp.register_message_handler(del_callback_run, lambda x: x.data and x.data.startwith('del '))
    # dp.register_message_handler(delete_item, commands='Удалить')


#!/usr/bin/env python

import abc
import re
import os
import sys

from etl.setup import ETLEnv
from etl.tools import MetadataWriter, get_current_metadata, RhizomeField, FIELDS_TO_DEDUPE, OUTPUT_COLS

# REVIEW: Add a step to ETL process to create 1 display date and 1 searchable date, which should be a year.
# REVIEW: Add a step to ETL process to change title values of "[Unknown]" to "Unknown Title" ? (DONE for PTH)
# REVIEW: Add collection name as a field to all metadata. (DONE for all)
# REVIEW: TODO pull list of unique keywords (column M) for each provider. keep phrases in tact, get a count of # of occurrences of each and make it case-insensitive.

# REVIEW: TODO: De-dupe all subject columns, in a case-insensitive manner, and make all subjects use title case.
# REVIEW: TODO: Strip opening and closing brackets from PTH titles. (DONE for PTH)
# REVIEW: TODO: de-dupe PTH resource ids, and possibly choose one of them as *the* resource id
# (e.g., line 2073 - ark: ark:/67531/metapth279657 | info:ark/67531/metapth279657 | issn: 0495-3460 | lccn: sn 86-11780 | oclc: 4742678)
# ignore for now
# REVIEW: TODO: check if PTH has better titles? or if they can be improved somehow? e.g., "art lies" does not show up in row 2073
# REVIEW: TODO: for PTH try to figure out a way to "choose better title" (use "Main Title") (DONE for PTH)
# - see ark: ark:/67531/metapth225042 | info:ark/67531/metapth225042 | local-cont-no: 1390_VisionsWest_1986_PR1 Visions of the West: American Art from Dallas Collections | Visions of the West: American Art from Dallas Collections [Press Release]
# - possibly add a new "sub-title" or "alternate title" field?
# - check if each title is a substring of one of the other titles, and if it is then remove the substring title?
# (DONE for PTH)
# REVIEW: check why so many PTH records have no artist? (DONE for PTH)

# REVIEW DPLA (and possibley calisphere) TODO: remove ", artist" and ", creator" and ", organizer" and ", photographer" and ", painter" from end of artist field?
# REVIEW Calisphere: change "(title unknown)" to "Title Unknown" ... same for "(artist unknown)"

# REVIEW: for ICAA, try to remove trailing years from artist name. e.g., "artist name, 1932-" and "artist name, 1932-1934" (DONE for ICAA)

# REVIEW: for PTH, try to do a translation from their character entities to unicode - e.g., <dc:subject>Vela&#769;zquez, Diego, 1599-1660.</dc:subject> (FIXED for PTH)
# REVIEW: for ICAA, do a sample run removing html tags. (DONE for ICAA)
# REVIEW: for DPLA & Caliphere, for now just spit out first 4-digit year I found as searchable date.
# REVIEW: generate new csvs for DPLA and Calisphere
# REVIEW: for DPLA & Calisphere, try to use URL to de-dupe records across institutions.
# See https://dp.la/item/d0814ef8a3d58a351e32ffc183ccae49?q=Day%20of%20the%20Dead%20%2781 and
#     https://calisphere.org/item/ark:/13030/hb2290044r/
# Note: in general, DPLA is more likely to contain Calisphere records than vice-versa...

# REVIEW: for DPLA and Calisphere, remove the following from end of artist name:
# , Artist
# , Author
# , Collaborator
# , Compiler
# , Contributor
# , Creator
# , Editor
# , Interviewer
# , Occupant
# , Organizer
# , Photographer
# , Speaker
# Also try removing everything within parentheses at end of artist name.

# for ICAA, look into accented characters in description and notes, e.g., ó FIXED for ICAA
# for ICAA, look into the seemingly truncated descriptions. FIXED for ICAA

def get_searchable_date(record, date_parsers):
    "Parse the date val and extract a year from it."

    date_vals = record.get(RhizomeField.DATE.value, [])
    if type(date_vals) is not list:

        date_vals = [ date_vals ]

    searchable_date = None

    for date_val in date_vals:

        for pattern, parser in date_parsers.items():

            if re.search(pattern, date_val):

                searchable_date = parser(date_val=date_val)
                if searchable_date:

                    searchable_date = int(searchable_date)
                    if searchable_date < 1000 or searchable_date > 3000:

                        raise Exception(f"Error: invalid searchable date found: {searchable_date}")

                    return searchable_date

    # REVIEW: remove this?
    if date_vals:

        print(f"Ignoring date val '{date_vals[0]}' - could not parse searchable date", file=sys.stderr)

def clean_value(value):
    "Cleans value, including removing bad whitespace."

    if type(value) is set:

        value = list(value)

    if type(value) is str:

        return value.strip()

    elif type(value) is list:

        value.sort()
        for idx, tmp in enumerate(value):

            value[idx] = tmp.strip()

    return value

def title_value(value):
    "Make value use title case."

    return value.title()

def de_dupe_list(values):

    if type(values) is not list:

        return values

    unique_values = set()

    for value in values:

        unique_values.add(title_value(value=value))

    return list(unique_values)

class BaseETLProcess(abc.ABC):

    def __init__(self, format):

        self.format = format

        self.etl_env = ETLEnv.instance()
        self.etl_env.start()

        self.date_parsers = self.get_date_parsers()

        if self.etl_env.are_tests_running():

            self.init_testing()

    @abc.abstractmethod
    def init_testing(self):    # pragma: no cover (should never get called)

        pass

    @abc.abstractmethod
    def get_date_parsers(self):     # pragma: no cover (should never get called)

        pass

    @abc.abstractmethod
    def get_field_map(self):    # pragma: no cover (should never get called)

        pass

    @abc.abstractmethod
    def get_collection_name(self):    # pragma: no cover (should never get called)

        pass

    @abc.abstractmethod
    def extract(self):    # pragma: no cover (should never get called)

        pass

    def rectify(self, data, curr_metadata):
        # This function gives ETL classes a chance to rectify
        # metadata with any changes made via content admins.

        pass

    def transform(self, data):
        "Transform the data."

        field_map = self.get_field_map()

        # Make sure that all transforms map from a field_map key to another field_map key, not
        # from a RhizomeField directly to another.
        if field_map.keys() & RhizomeField.values():

            raise Exception(f"Invalid field map keys found: {field_map.keys() & RhizomeField.values()}")

        # De-dupe the records (make sure no record appears more than once).
        record_ids = set()
        id_key = list(field_map.keys())[0]
        for record in data:

            id_val = record[id_key]

            if type(id_val) is list:

                id_val = id_val[0]

            if id_val in record_ids:

                record["ignore"] = True

            else:

                record_ids.add(id_val)

        # Now map all the other values in the raw metadata to the correct output rhizome fields.
        for record in data:

            # Has this record been flagged to be skipped?
            if record.get("ignore", False):

                continue

            for name, rhizome_fields in field_map.items():

                if not rhizome_fields:

                    continue

                if type(name) is RhizomeField:

                    name = name.value

                if type(rhizome_fields) is not list:

                    rhizome_fields = [ rhizome_fields ]

                value = record.get(name)
                if value:

                    for rhizome_field in rhizome_fields:

                        rhizome_field = rhizome_field.value

                        if rhizome_field == name:

                            continue

                        if record.get(rhizome_field):

                            prev_vals = record[rhizome_field]
                            if type(prev_vals) is not list:

                                prev_vals = [ prev_vals ]

                            clean_vals = clean_value(value=value)
                            if type(clean_vals) is not list:

                                clean_vals = [ clean_vals ]

                            record[rhizome_field] = prev_vals + clean_vals

                        else:

                            record[rhizome_field] = clean_value(value=value)

                        del record[name]

        # Get all metadata currently loaded.
        curr_metadata = get_current_metadata()

        # Remove records that are already loaded in the rhizomes website?
        if not self.etl_env.do_rebuild_previous_items():

            for record in data:

                if record.get("ignore", False):

                    continue

                url = record[RhizomeField.URL.value]

                if type(url) is list:

                    raise Exception(f"URL for record {record[RhizomeField.ID.value]} is a list - lists of urls are not supported.")

                if url in curr_metadata:

                    record["ignore"] = True

        # Rectify metadata with any changes made by content admins.
        self.rectify(data=data, curr_metadata=curr_metadata)

        # Omit any records that do not have images (?)
        if self.etl_env.do_images_only():

            for record in data:

                if not record.get(RhizomeField.IMAGES.value):

                    record["ignore"] = True

        # Do some more tweaks to each record's data.
        for record in data:

            # Add collection name.
            record[RhizomeField.COLLECTION_NAME.value] = self.get_collection_name()

            # Replace null artist name with "Unknown"
            if not record.get(RhizomeField.AUTHOR_ARTIST.value):

                record[RhizomeField.AUTHOR_ARTIST.value] = "Unknown"

            # De-dupe individual values.
            for field in FIELDS_TO_DEDUPE:

                values = record.get(field.value)
                if values:

                    values = de_dupe_list(values=values)
                    record[field.value] = values

            # Overwrite the access-rights.
            record[RhizomeField.ACCESS_RIGHTS.value] = "Image is displayed for education and personal research only. For individual rights information about an item, please check the “Description” field, or follow the link to the digital object on the content provider’s website for more information. Reuse of copyright-protected images requires signed permission from the copyright holder. If you are the copyright holder of this item and its use online constitutes an infringement of your copyright, please contact us by email at rhizomes@umn.edu to discuss its removal from the portal."

        # Populate our Searchable Date.
        for record in data:

            if self.date_parsers:

                searchable_date = get_searchable_date(record=record, date_parsers=self.date_parsers)

            else:

                searchable_date = record.get(RhizomeField.DATE.value)

            record[RhizomeField.SEARCHABLE_DATE.value] = searchable_date

    def load(self, data):
        "Load the data (into csv, json, database, etc.)"

        writer = MetadataWriter(format=self.format)
        writer.start_collection()

        for record in data:

            if record.get("ignore", False):

                continue

            writer.start_record()

            for name in OUTPUT_COLS:

                name = name.value

                value = record.get(name)
                if value and name:

                    writer.add_value(name=name, value=value)

            writer.end_record()

        writer.end_collection()


import os
import pickle

import mediapipe as mp
import cv2
import matplotlib.pyplot as plt

mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles

hands = mp_hands.Hands(static_image_mode=True, min_detection_confidence=0.3)

DATA_DIR = './rawdata'

data = []
labels = []
def multilandmarks(results):
    x_ = []
    y_ = []
    data_list = []
    for hand_landmarks in results.multi_hand_landmarks:
        i=0
        while(i < len(hand_landmarks.landmark)):
            x = hand_landmarks.landmark[i].x
            y = hand_landmarks.landmark[i].y
            x_.append(x)
            y_.append(y)
            i=i+1

        ## Normalization of landmarks
        i=0
        while(i<len(hand_landmarks.landmark)):
            x = hand_landmarks.landmark[i].x
            y = hand_landmarks.landmark[i].y
            data_list.append(x - min(x_))
            data_list.append(y - min(y_))
            i=i+1
    return data_list

for dir_ in os.listdir(DATA_DIR):
    for img_path in os.listdir(os.path.join(DATA_DIR, dir_)):
        data_list = []

        img = cv2.imread(os.path.join(DATA_DIR, dir_, img_path))
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        results = hands.process(img_rgb)
        if results.multi_hand_landmarks:
            data_list = multilandmarks(results)

            data.append(data_list)
            labels.append(dir_)

f = open('dataset.pickle', 'wb')
pickle.dump({'data': data, 'labels': labels}, f)
f.close()


# File:    pain_job_estimator.py
# Project: Starting Out with Python
# Author:  Matthew Forbes
# History: Version 1.1 February 9, 2022

def main():
    sq_ft = float(input("Please enter the square feet of wall space to be painted: "))
    paint_price_per_gallon = float(input("Please enter the paint price per gallon: $"))

    numGallons, paintCost = calc_num_gallons_cost(sq_ft, paint_price_per_gallon)
    laborHours, laborCost = labor_hours_cost(sq_ft)

    total_cost = laborCost + paintCost

    print(f"Gallons required: {numGallons}")
    print(f"Hours of labor required: {laborHours}")
    print(f"Cost of paint: {paintCost}")
    print(f"Labor cost: {laborCost}")
    print(f"Total cost of paint job: {total_cost}")

def calc_num_gallons_cost(sqFt, pricePerGal):
    num_gallons = sqFt / 112
    paint_cost = num_gallons * pricePerGal
    return (num_gallons, paint_cost)

def labor_hours_cost(sqFt):
    FT_PAINTED_PER_HOUR = 112 / 8 # 14 feet per hour. 112 feet takes 8 hours
    HOURLY_LABOR_COST = 35.0

    job_hours = sqFt / FT_PAINTED_PER_HOUR
    labor_cost = job_hours * HOURLY_LABOR_COST

    return(job_hours, labor_cost)

main()


import sys

from loader import extract_words

if __name__ == '__main__':
    list1 = sys.argv[1]
    list2 = sys.argv[2]
    with open(list1) as f:
        l1_words = extract_words(f)
    with open(list2) as f:
        l2_words = extract_words(f)

    print(f'Words in {list1} not in {list2}:')
    print(l1_words - l2_words)
    print(len(l1_words - l2_words))
    print(f'Words in {list2} not in {list1}:')
    print(l2_words - l1_words)
    print(len(l2_words - l1_words))


from test_tools.example_stubber import ExampleStubber

class AuditManagerStubber(ExampleStubber):
    """
    A class that implements stub functions used by Audit Manager unit tests.
    """

    def __init__(self, client, use_stubs=True):
        """
        Initializes the object with a specific client and configures it for
        stubbing or AWS passthrough.

        :param client: A Boto3 Audit Manager client.
        :param use_stubs: When True, use stubs to intercept requests. Otherwise,
                          pass requests through to AWS.
        """
        super().__init__(client, use_stubs)

    def stub_get_assessment(self, assessment_id, error_code=None):
        expected_params = {"assessmentId": assessment_id}
        response = {}
        self._stub_bifurcator(
            "get_assessment", expected_params, response, error_code=error_code
        )

    def stub_get_evidence_folders_by_assessment(
        self, assessment_id, max_results, tokens, folders, error_code=None
    ):
        expected_params = {"assessmentId": assessment_id, "maxResults": max_results}
        if tokens[0] is not None:
            expected_params["nextToken"] = tokens[0]
        response = {"evidenceFolders": folders}
        if tokens[1] is not None:
            response["nextToken"] = tokens[1]
        self._stub_bifurcator(
            "get_evidence_folders_by_assessment",
            expected_params,
            response,
            error_code=error_code,
        )

    def stub_disassociate_assessment_report_evidence_folder(
        self, assessment_id, folder_id, error_code=None
    ):
        expected_params = {"assessmentId": assessment_id, "evidenceFolderId": folder_id}
        response = {}
        self._stub_bifurcator(
            "disassociate_assessment_report_evidence_folder",
            expected_params,
            response,
            error_code=error_code,
        )

    def stub_get_evidence_by_evidence_folder(
        self, assessment_id, folder_id, max_results, evidences, error_code=None
    ):
        expected_params = {
            "assessmentId": assessment_id,
            "controlSetId": folder_id,
            "evidenceFolderId": folder_id,
            "maxResults": max_results,
        }
        response = {"evidence": evidences}
        self._stub_bifurcator(
            "get_evidence_by_evidence_folder",
            expected_params,
            response,
            error_code=error_code,
        )

    def stub_batch_disassociate_assessment_report_evidence(
        self, assessment_id, folder_id, evidence_ids, error_code=None
    ):
        expected_params = {
            "assessmentId": assessment_id,
            "evidenceFolderId": folder_id,
            "evidenceIds": evidence_ids,
        }
        response = {}
        self._stub_bifurcator(
            "batch_disassociate_assessment_report_evidence",
            expected_params,
            response,
            error_code=error_code,
        )

    def stub_associate_assessment_report_evidence_folder(
        self, assessment_id, folder_id, error_code=None
    ):
        expected_params = {"assessmentId": assessment_id, "evidenceFolderId": folder_id}
        response = {}
        self._stub_bifurcator(
            "associate_assessment_report_evidence_folder",
            expected_params,
            response,
            error_code=error_code,
        )

    def stub_create_assessment_report(
        self, name, desc, assessment_id, report_id, error_code=None
    ):
        expected_params = {
            "name": name,
            "description": desc,
            "assessmentId": assessment_id,
        }
        response = {"assessmentReport": {"id": report_id}}
        self._stub_bifurcator(
            "create_assessment_report", expected_params, response, error_code=error_code
        )

    def stub_list_assessment_reports(self, report_ids, error_code=None):
        expected_params = {"maxResults": 1}
        response = {
            "assessmentReports": [
                {"id": report_id, "status": "COMPLETE"} for report_id in report_ids
            ]
        }
        self._stub_bifurcator(
            "list_assessment_reports", expected_params, response, error_code=error_code
        )

    def stub_get_assessment_report_url(
        self, report_id, assessment_id, report_url, error_code=None
    ):
        expected_params = {
            "assessmentReportId": report_id,
            "assessmentId": assessment_id,
        }
        response = {
            "preSignedUrl": {"link": report_url, "hyperlinkName": "stubbed_link"}
        }
        self._stub_bifurcator(
            "get_assessment_report_url",
            expected_params,
            response,
            error_code=error_code,
        )

    def stub_create_control(self, name, source_id, control_id, error_code=None):
        expected_params = {
            "name": name,
            "controlMappingSources": [
                {
                    "sourceName": "ConfigRule",
                    "sourceSetUpOption": "System_Controls_Mapping",
                    "sourceType": "AWS_Config",
                    "sourceKeyword": {
                        "keywordInputType": "SELECT_FROM_LIST",
                        "keywordValue": source_id,
                    },
                }
            ],
        }
        response = {"control": {"id": control_id}}
        self._stub_bifurcator(
            "create_control", expected_params, response, error_code=error_code
        )

    def stub_create_assessment_framework(
        self, name, control_sets, fw_id, error_code=None
    ):
        expected_params = {"name": name, "controlSets": control_sets}
        response = {"framework": {"name": name, "id": fw_id}}
        self._stub_bifurcator(
            "create_assessment_framework",
            expected_params,
            response,
            error_code=error_code,
        )

    def stub_list_controls(
        self, ctl_type, max_results, tokens, control_ids, error_code=None
    ):
        expected_params = {"controlType": ctl_type, "maxResults": max_results}
        if tokens[0] is not None:
            expected_params["nextToken"] = tokens[0]
        response = {"controlMetadataList": [{"id": ctl_id} for ctl_id in control_ids]}
        if tokens[1] is not None:
            response["nextToken"] = tokens[1]
        self._stub_bifurcator(
            "list_controls", expected_params, response, error_code=error_code
        )

    def stub_get_control(self, control_id, sources, error_code=None):
        expected_params = {"controlId": control_id}
        response = {"control": {"id": control_id, "controlSources": sources}}
        self._stub_bifurcator(
            "get_control", expected_params, response, error_code=error_code
        )


# coding=utf-8
from selenium import webdriver
import time
import requests
from yundama.dama import indetify
from selenium.webdriver.chrome.options import Options

chrome_options = Options()

# 设置chrome浏览器无界面模式
# 浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败
# chrome_options.add_argument('--headless')
chrome_options.add_argument('blink-settings=imagesEnabled=false')  # 不加载图片, 提升速度
# phantomjs_driver = r"E:\phantomjs-2.1.1-windows\bin\phantomjs.exe"
chrome_driver = r"E:\chromedriver.exe"
browser = webdriver.Chrome(executable_path=chrome_driver)

browser.get("https://yuese64.com/")
with open("index.html", "w", encoding="utf-8") as f:
    f.write(browser.page_source)
print(("=" * 10) + "首页保存成功")
browser.find_element_by_id("login").click()
time.sleep(3)
browser.find_element_by_id("login_username").send_keys("wzq5517992@163.com")
browser.find_element_by_id("login_pass").send_keys("wzq5517992")

# 识别验证码
captcha_image_url = browser.find_element_by_xpath(".//div[@class='image']/img").get_attribute("src")
captcha_content = requests.get(captcha_image_url).content
captcha_code = indetify(captcha_content)
print("验证码的识别结果为:", captcha_code)
time.sleep(5)

# 输入验证码
browser.find_element_by_id("login_code").send_keys(captcha_code)

browser.find_element_by_class_name("submit").click()

# 获取cookie
cookies = {i["name"]: i["value"] for i in browser.get_cookies()}
print(cookies)
browser.get("https://yuese64.com/videos/24177/55d047cd3d624316843b211e7844a845/")
time.sleep(5)
browser.get("https://yuese64.com/videos/24177/55d047cd3d624316843b211e7844a845/")
print(browser.page_source)

time.sleep(3)
# browser.quit()


import json
import urllib

from django.conf import settings

def evaluate_recaptcha(request, errors):
    # Google Recaptcha validation
    recaptcha_response = request.POST.get('g-recaptcha-response')
    url = 'https://www.google.com/recaptcha/api/siteverify'
    values = {
        'secret': settings.GOOGLE_RECAPTCHA_PRIVATE_KEY,
        'response': recaptcha_response
    }
    data = urllib.parse.urlencode(values).encode()
    req = urllib.request.Request(url, data=data)
    response = urllib.request.urlopen(req)
    result = json.loads(response.read().decode())
    if not result['success']:
        errors.append('Site access denied, Google reCaptcha authentication failed')


import random

# 5 real world lists:

favorite_foods = ['Pizza', 'Beer', 'Pineapple', 'Strawberries', 'Carrots']

favorite_movies = ['Pulp Fiction', 'Blade Runner', 'LOTR', 'Your Highness']

home_depot_list = ['Insulation', 'Garden Pots', '1x4s', 'Kid Project']

pancake_ingredients = ['Flour', 'Egg', 'Baking Powder', 'Cinnamon', 'Milk']

specialty_ingredients = ['Chocolate Chips', 'Bananas', 'Blueberries', 'Strawberries']

while len(pancake_ingredients) != 7:
	recipe = specialty_ingredients.pop(random.randrange(len(specialty_ingredients)))
	pancake_ingredients.append(recipe)
	print(f"Your new recipe is: ", " ".join(pancake_ingredients))

tea = ['Earl Gray', 'Rooibos', 'Camomile']

# Scripts for lists:

# .pop()

# .append()

# .join()


def partition(array, low, high):
    pivot = array[high]
    i = low - 1
    for j in range(low, high):
        if array[j] <= pivot:
            i = i + 1
            (array[i], array[j]) = (array[j], array[i])
    (array[i + 1], array[high]) = (array[high], array[i + 1])
    return i + 1
def quickSort(array, low, high):
    if low < high:
        pi = partition(array, low, high)
        quickSort(array, low, pi - 1)
        quickSort(array, pi + 1, high)
n = int(input())
data = list(map(int, input().split()))
size = len(data)
quickSort(data, 0, size - 1)
max_value = max(data)
count = 0
for x in data:
  if x == max_value:
    count += 1
print( count)


from odoo import models, fields, api, tools
from datetime import datetime, timedelta
import json

# ***************** CREAR CIUDADES **********************

class create_city(models.TransientModel):
    _name = 'medievol.create_city'

    def _default_player(self):
        jugador = self.env['res.partner'].browse(self._context.get('active_id'))
        print(jugador.name)
        return jugador

    player = fields.Many2one('res.partner', default=_default_player, readonly=True)
    region = fields.Many2one('medievol.region')
    state = fields.Selection([('i', "Elegir región"), ('f', "Finalizar región")], default='i')
    nombre = fields.Char()

    @api.multi
    def back(self):
        if self.state == 'f':
            self.state = 'i'

        return {
            'type': 'ir.actions.act_window',
            'name': 'Creación de ciudad',
            'res_model': self._name,
            'res_id': self.id,
            'view_mode': 'form',
            'target': 'new'
        }

    @api.multi
    def next(self):
        if self.state == 'i':
            self.state = 'f'

        return {
            'type': 'ir.actions.act_window',
            'name': 'Creación de ciudad',
            'res_model': self._name,
            'res_id': self.id,
            'view_mode': 'form',
            'target': 'new'
        }

    @api.multi
    def new(self):
        c_template = self.env.ref('medievol.city1')
        c = self.env['medievol.city'].create({
            'name': self.nombre,
            'image': c_template.image,
            'poblation': 100,
            'defense': 50,
            'quarry_id': self.env.ref('medievol.quarry1').id,
            'mine_id': self.env.ref('medievol.mine1').id,
            'farm_id': self.env.ref('medievol.farm1').id,
            'castle_id': self.env.ref('medievol.castle1').id,
            'infirmary_id': self.env.ref('medievol.infirmary0').id,
            'wall_id': self.env.ref('medievol.wall0').id,
            'barracks_id': self.env.ref('medievol.barracks0').id,
            'treasury_id': self.env.ref('medievol.treasury0').id,
            'forge_id': self.env.ref('medievol.forge0').id,
            'player_id': self.player.id,
            'region_id': self.region.id
        })
        for i in [1, 2, 3, 4]:
            if i < 4:
                p = self.env['medievol.means_city'].create({
                    'cantidad': 100,
                    'city_id': c.id,
                    'means_id': self.env.ref('medievol.means' + str(i)).id
                })
            else:
                p = self.env['medievol.means_city'].create({
                    'cantidad': 50,
                    'city_id': c.id,
                    'means_id': self.env.ref('medievol.means' + str(i)).id
                })

# ***************** CREAR GUERRAS *********************************

class type_soldiers(models.TransientModel):
    _name = 'medievol.type_soldiers'

    brujo = fields.Many2one('medievol.create_wars')
    tipo = fields.Many2one('medievol.soldiers')
    quantity = fields.Float()

class create_wars(models.TransientModel):
    _name = 'medievol.create_wars'

    def _default_city(self):
        return self.env['medievol.city'].browse(self._context.get('active_id'))

    def _default_player(self):
        player = self.env['medievol.city'].browse(self._context.get('active_id')).player_id
        return player
    def _get_date(self):
        date = datetime.now()
        return fields.Datetime.to_string(date)

    def _get_date_fin(self):
        date = datetime.now() + timedelta(hours=4)
        return fields.Datetime.to_string(date)

    city = fields.Many2one('medievol.city', default=_default_city, readonly=True)
    player = fields.Many2one('res.partner', default=_default_player, readonly=True)
    fecha_ini = fields.Datetime(default=_get_date)
    fecha_fin = fields.Datetime(default=_get_date_fin)
    soldiers_wars = fields.Many2many('medievol.soldiers_wars')

    tipo = fields.Many2one('medievol.soldiers')
    def _get_attack_domain(self):
        c = self._context.get('citys')
        if c:
          c = json.loads(c)
          return [('id','in',c)]

    city_attack = fields.Many2one('medievol.city', domain=_get_attack_domain)

    wiz_soldiers = fields.One2many('medievol.type_soldiers', 'brujo')
    quantity = fields.Float()
    state = fields.Selection([('i', "Selección Soldados"), ('c', "Ciudad a Atacar"), ('f', "Finalizar")],
                             default='i')

    @api.onchange('city')
    def _onchange_soldiers(self):
        for f in self:
            return {
                'domain': {'tipo': [('id', 'in', f.city.soldiers_city_id.soldiers_id.ids)]}
            }

    @api.multi
    def send_soldiers(self):
        for f in self:
            self.env['medievol.type_soldiers'].create({
                'brujo': f.id,
                'tipo': f.tipo.id,
                'quantity': f.quantity
            })
        return {
            'type': 'ir.actions.act_window',
            'name': 'Creación de Batallas',
            'res_model': self._name,
            'res_id': self.id,
            'view_mode': 'form',
            'target': 'new'
        }

    @api.multi
    def exit(self):
        return

    @api.multi
    def next(self):
        if self.state == 'i':
            self.state = 'c'
        elif self.state == 'c':
            self.state = 'f'

        return {
            'type': 'ir.actions.act_window',
            'name': 'Creación de Batallas',
            'res_model': self._name,
            'res_id': self.id,
            'view_mode': 'form',
            'context': {'citys': json.dumps(self.env['medievol.city'].search([]).filtered(lambda r: r.id != self.city.id).ids)},
            'target': 'new'
        }

    @api.multi
    def back(self):
        if self.state == 'f':
            self.state = 'c'
        elif self.state == 'c':
            self.state = 'i'

        return {
            'type': 'ir.actions.act_window',
            'name': 'Creación de Batallas',
            'res_model': self._name,
            'res_id': self.id,
            'view_mode': 'form',
            'target': 'new'
        }

    @api.multi
    def new_battle(self):
        for f in self:
            soldados_cantidad = f.wiz_soldiers
            for soldiers in soldados_cantidad:
                batalla = self.env['medievol.wars'].create({})

                self.env['medievol.soldiers_wars'].create({
                    'cantidad': soldiers.quantity,
                    'soldiers_id': soldiers.tipo.id,
                    'city_id': f.city.id,
                    'city_attack_id': f.city_attack.id,
                    'batalla_id': batalla.id,
                    'player_id': f.player.id
                })

# ***************** CREAR SOLDADOS **********************

class create_soldiers(models.TransientModel):
    _name = 'medievol.create_soldiers'

    def _default_city(self):
        city = self.env['medievol.city'].browse(self._context.get('city_id'))
        return city

    city = fields.Many2one('medievol.city', default=_default_city, readonly=True)
    soldiers = fields.Many2one('medievol.soldiers')
    quantity = fields.Float()
    comprobar = fields.Boolean()
    cfoodsoldier = fields.Integer(readonly=True)
    cgoldsoldier = fields.Integer(readonly=True)
    cfoodcity = fields.Float(readonly=True)
    cgoldcity = fields.Float(readonly=True)

    state = fields.Selection([('i', "Selección Soldados"), ('c', "Gastos de Producción"), ('f', "Finalizar")],
                             default='i')

    @api.multi
    def new(self):
        c = self.env['medievol.recruit_soldiers'].create({
            'cantidad': self.quantity,
            'city_id': self.city.id,
            'soldiers_id': self.soldiers.id
        })
        encontrado = False
        soldados_ciudad = self.city.soldiers_city_id.search([])
        if len(soldados_ciudad) > 0:
            for sol in soldados_ciudad:
                if c.soldiers_id == sol.soldiers_id:
                    sol.cantidad = sol.cantidad + c.cantidad
                    encontrado = True

        if encontrado == False:
            soldier_new = self.env['medievol.soldiers_city'].create({
                'cantidad': c.cantidad,
                'city_id': c.city_id.id,
                'soldiers_id': c.soldiers_id.id
            })

        granja = self.env['medievol.farm'].search([])[0]
        tesoreria = self.env['medievol.treasury'].search([])[0]
        recursos = self.city.means_city_id
        for r in recursos:
            if r.means_id == granja.means_id:
                r.cantidad = r.cantidad - self.cfoodsoldier
            elif r.means_id == tesoreria.means_id:
                r.cantidad = r.cantidad - self.cgoldsoldier

    @api.multi
    def back(self):
        if self.state == 'f':
            self.state = 'c'
        elif self.state == 'c':
            self.state = 'i'

        return {
            'type': 'ir.actions.act_window',
            'name': 'Creación de Soldados',
            'res_model': self._name,
            'res_id': self.id,
            'view_mode': 'form',
            'target': 'new'
        }

    @api.multi
    def next(self):
        if self.state == 'i':
            self.state = 'c'
            soldado = self.soldiers
            self.cfoodsoldier = soldado.food * self.quantity
            self.cgoldsoldier = soldado.gold * self.quantity
            granja = self.env['medievol.farm'].search([])[0]
            tesoreria = self.env['medievol.treasury'].search([])[0]
            recursos = self.city.means_city_id
            for r in recursos:
                if r.means_id == granja.means_id:
                    self.cfoodcity = r.cantidad
                elif r.means_id == tesoreria.means_id:
                    self.cgoldcity = r.cantidad
            cantidadfood = self.cfoodcity - self.cfoodsoldier
            cantidadgold = self.cgoldcity - self.cgoldsoldier
            if cantidadfood >= 0 and cantidadgold >= 0:
                self.comprobar = True
            else:
                self.comprobar = False

        elif self.state == 'c':
            if self.comprobar:
                self.state = 'f'

        return {
            'type': 'ir.actions.act_window',
            'name': 'Creación de Soldados',
            'res_model': self._name,
            'res_id': self.id,
            'view_mode': 'form',
            'target': 'new'
        }


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:

        q = deque()

        q.append(root)

        res = []
        while q:

            level = []
            for _ in range(len(q)):
                curr = q.popleft()
                if curr and  curr.left:
                    q.append(curr.left)
                if curr and  curr.right:
                    q.append(curr.right)

                if curr:
                    level.append(curr.val)
            if level:
                res.append(level)

        return res[::-1]


import typing as t
import os.path
import logging
import json

from yaml.error import Mark
from typing_extensions import TypedDict, Protocol, Literal

from schemalint.entity import ErrorEvent, Lookup, Context
from schemalint.errors import (
    ParseError,
    LintError,
    ResolutionError,
    ValidationError,
    MessageError,
)

logger = logging.getLogger(__name__)

StatusType = Literal["INFO", "WARNING", "ERROR"]

class PositionDict(TypedDict):
    line: int
    character: int

class OutputDict(TypedDict):
    status: str
    errortype: str
    filename: str

    start: PositionDict
    end: PositionDict

    message: str
    where: t.List[str]

class Layout(Protocol):
    def layout(self, d: OutputDict) -> str:
        ...

class LTSVLayout(Layout):
    def layout(self, d: OutputDict) -> str:
        d["start"] = f"{d['start']['line']}@{d['start']['character']}"
        d["end"] = f"{d['end']['line']}@{d['end']['character']}"
        return "\t".join(f"{k}:{v}" for k, v in d.items())

class JSONLayout(Layout):
    def layout(self, d: OutputDict) -> str:
        d["where"] = str(d["where"])
        return json.dumps(d, ensure_ascii=False)

class Detector:
    lookup: Lookup

    def __init__(self, filename: str, *, lookup: Lookup):
        self.filename = filename  # root file
        self.lookup = lookup

    def has_error_point(self, err: LintError):
        return getattr(err, "problem_mark", None) is not None

    def detect_status(self, filename):
        if self.filename == filename:
            return "ERROR"
        else:
            return "WARNING"

    def detect_loadning_start_point(self, err: LintError) -> (Mark, Mark):
        if err.data is None:
            return self.detect_error_point(err)
        map_node = self.lookup.lookup_node(err.data)
        knode, vnode = self.lookup_kvpair(map_node, err.path[-1])
        return knode.start_mark, vnode.end_mark

    def detect_error_point(self, err: LintError) -> Mark:
        mark = getattr(err.inner, "context_mark")
        import copy

        if mark is None:
            mark = getattr(err.inner, "problem_mark")
            mark.line -= 1  # xxx

        start_mark = copy.deepcopy(mark)
        start_mark.column = 0
        end_mark = copy.deepcopy(mark)
        end_mark.column = -1
        return (start_mark, end_mark)

    def lookup_kvpair(self, node, k):  # todo: rename
        for knode, vnode in node.value:
            if knode.value == k:
                return knode, vnode

class Formatter:
    detector: Detector
    layout: Layout

    def __init__(
        self, filename: str, *, detector: Detector, layout: t.Optional[Layout] = None
    ):
        self.filename = filename
        self.detector = detector
        self.layout = layout or LTSVLayout()

    def format(self, ev: ErrorEvent) -> str:
        err = ev.error
        if isinstance(err, ParseError):
            return self.format_parse_error(err)
        elif isinstance(err, ResolutionError):
            return self.format_resolution_error(err)
        elif isinstance(err, ValidationError):
            return self.format_validation_error(err)
        elif isinstance(err, MessageError):
            return self.format_message_error(err, context=ev.context)
        else:
            raise err

    def format_parse_error(self, err: ParseError) -> str:
        status = self.detector.detect_status(err.history[-1])
        if hasattr(err.inner, "problem"):
            message = f"{err.inner.problem} ({err.inner.context})"
        else:
            message = repr(err.inner)

        start_mark, end_mark = self.detector.detect_loadning_start_point(err)
        filename = os.path.relpath(start_mark.name, start=".")

        where = [os.path.relpath(name) for name in err.history]
        where[0] = f"{where[0]}:{start_mark.line+1}"
        if self.detector.has_error_point(err):
            where[-1] = f"{where[-1]}:{err.inner.problem_mark.line+1}"

        return self.layout.layout(
            OutputDict(
                status=status,
                errortype=err.__class__.__name__,
                filename=filename,
                start=PositionDict(
                    line=start_mark.line + 1, character=start_mark.column
                ),
                end=PositionDict(line=end_mark.line + 1, character=end_mark.column),
                message=message,
                where=where,
            )
        )

    def format_resolution_error(self, err: ResolutionError) -> str:
        start_mark, end_mark = self.detector.detect_loadning_start_point(err)
        filename = os.path.relpath(start_mark.name, start=".")
        status = self.detector.detect_status(err.history[-1])
        message = repr(err.inner)

        where = [os.path.relpath(name) for name in err.history]
        where[0] = f"{where[0]}:{start_mark.line+1}"
        if self.detector.has_error_point(err):
            where[-1] = f"{where[-1]}:{err.inner.problem_mark.line+1}"

        return self.layout.layout(
            OutputDict(
                status=status,
                errortype=err.__class__.__name__,
                filename=filename,
                start=PositionDict(
                    line=start_mark.line + 1, character=start_mark.column
                ),
                end=PositionDict(line=end_mark.line + 1, character=end_mark.column),
                message=message,
                where=where,
            )
        )

    def format_validation_error(self, err: ValidationError) -> str:
        status = "ERROR"
        message = f"{err.message} (validator={err.validator})"
        node = self.detector.lookup.lookup_node(err.instance)  # xxx

        start_mark, end_mark = node.start_mark, node.end_mark

        filename = os.path.relpath(start_mark.name, start=".")
        where = [os.path.relpath(filename)]
        where[0] = f"{where[0]}:{start_mark.line+1}"

        return self.layout.layout(
            OutputDict(
                status=status,
                errortype=err.__class__.__name__,
                filename=filename,
                start=PositionDict(
                    line=start_mark.line + 1, character=start_mark.column
                ),
                end=PositionDict(line=end_mark.line + 1, character=end_mark.column),
                message=message,
                where=where,
            )
        )

    def format_message_error(
        self,
        err: MessageError,
        *,
        context: t.Optional[Context],
        status: StatusType = "INFO",
    ) -> str:
        message = err.args[0]
        filename = os.path.relpath(context.filename if context else self.filename)
        where = [filename]
        return self.layout.layout(
            OutputDict(
                status=status,
                errortype=err.__class__.__name__,
                filename=filename,
                start=PositionDict(line=1, character=1),
                end=PositionDict(line=1, character=-1),
                message=message,
                where=where,
            )
        )

OutputType = Literal["ltsv", "json"]

def get_formatter(
    filename: str, *, lookup: Lookup, output_type: OutputType
) -> Formatter:
    detector = Detector(filename, lookup=lookup)
    layout = get_layout(output_type)
    return Formatter(filename, detector=detector, layout=layout)

def get_layout(output_type: OutputType) -> Layout:
    if output_type == "json":
        return JSONLayout()
    else:
        return LTSVLayout()


import pytz
import logging
from datetime import datetime, timedelta

from odoo import fields, models, api, _
from odoo.exceptions import UserError, ValidationError

_logger = logging.getLogger(__name__)

class MrpDistributeTimesheetLine(models.TransientModel):
    _name = 'mrp.distribute.timesheet.line'
    _description = 'Represents a sample of the distribution'

    project_id = fields.Many2one(
        'project.project',
        string='Project',
    )
    production_id = fields.Many2one(
        'mrp.production',
        string='Production',
    )
    start_time = fields.Datetime()
    end_time = fields.Datetime()

    def _prepare_analytic_line(self, name):
        diff = self.end_time - self.start_time
        hours = diff.total_seconds() / 3600
        vals = {
            'name': name,
            'project_id': self.project_id.id,
            'production_id': self.production_id.id,
            'date_time': self.start_time,
            'unit_amount': hours,
        }
        return vals

class MrpDistributeTimesheet(models.TransientModel):
    _name = 'mrp.distribute.timesheet'
    _description = 'Distribute working time along multiple production orders'

    @api.model
    def _default_date_time(self):
        def ceil_dt(dt, delta):
            return dt + (datetime.min - dt) % delta

        return ceil_dt(fields.Datetime.now(), timedelta(minutes=-15))

    @api.model
    def _default_reason(self):
        return self.env.ref('mrp_timesheet_distribution.layout_and_wiring')

    production_ids = fields.Many2many(
        'mrp.production',
        string='Production Orders',
        readonly=True,
    )
    reason_id = fields.Many2one(
        'mrp.distribute.timesheet.reason',
        string='Reason',
        required=True,
        default=_default_reason
    )
    custom_reason = fields.Char(string='Other Reason')
    date_time = fields.Datetime(
        default=_default_date_time,
        required=True,
    )
    unit_amount = fields.Float(
        'Quantity',
        default=0.0,
        required=True,
    )
    timesheet_line_ids = fields.Many2many(
        'mrp.distribute.timesheet.line',
        string='Timesheet Lines',
        compute="_compute_timesheet_line_ids",
    )

    exclude_time = fields.Boolean()
    excluded_start_time = fields.Datetime()
    excluded_end_time = fields.Datetime()

    @api.model
    def default_get(self, fields):
        rec = super().default_get(fields)
        active_ids = self._context.get('active_ids')
        active_model = self._context.get('active_model')

        if active_model == 'mrp.production' and active_ids:
            production_ids = self.env['mrp.production'].browse(active_ids)
            rec.update({'production_ids': production_ids.ids})
        return rec

    @api.multi
    def action_reopen(self):
        return self._reopen()

    @api.multi
    def _reopen(self, id=False):
        return {
            'type': 'ir.actions.act_window',
            'view_mode': 'form',
            'view_type': 'form',
            'res_id': id or self.id,
            'res_model': self._name,
            'target': 'new',
            'context': {
                'default_model': self._name,
            },
        }

    @api.multi
    def action_distribute(self):
        self._do_distribute()

    @api.multi
    def action_distribute_continue(self):
        self._do_distribute()
        mrp_distribute_timesheet_id = self.create(
            {
                "date_time": self.timesheet_line_ids[-1].end_time,
                "reason_id": self.reason_id.id,
                "exclude_time": self.exclude_time,
                "production_ids": [(6, 0, self.production_ids.ids)],
            }
        )
        mrp_distribute_timesheet_id.onchange_date_time()
        return self._reopen(mrp_distribute_timesheet_id.id)

    @api.onchange('date_time')
    def onchange_date_time(self):
        # Convert datetime into user timezone to manipulate hours and minutes
        tz = self.env.context.get('tz') or self.env.user.tz
        date_time_tz = pytz.timezone(tz).normalize(
            pytz.utc.localize(self.date_time)
        )

        resource_calendar_id = self.env.user.resource_calendar_id
        attendance_ids = resource_calendar_id.attendance_ids.filtered(
            lambda r: r.dayofweek == str(self.date_time.weekday())
        )

        st = et = False
        for attendance_id in attendance_ids:
            if attendance_id.day_period == 'morning':
                hour, minute = divmod(float(attendance_id.hour_to) * 60, 60)
                st = date_time_tz.replace(
                    hour=round(hour), minute=round(minute), second=0
                )
            if attendance_id.day_period == 'afternoon':
                hour, minute = divmod(float(attendance_id.hour_from) * 60, 60)
                et = date_time_tz.replace(
                    hour=round(hour), minute=round(minute), second=0
                )

        # Set start and end time in user timezone
        if not st or not et:
            st = date_time_tz.replace(hour=12, minute=0, second=0)
            et = date_time_tz.replace(hour=13, minute=30, second=0)

        # Convert back data to UTC since all datetime data must be
        # stored without timezone info (means UTC)
        self.excluded_start_time = pytz.utc.normalize(st).replace(tzinfo=None)
        self.excluded_end_time = pytz.utc.normalize(et).replace(tzinfo=None)

    @api.depends(
        'date_time', 'unit_amount', 'exclude_time', 'excluded_start_time',
        'excluded_end_time'
    )
    def _compute_timesheet_line_ids(self):
        self.timesheet_line_ids.unlink()
        if self.production_ids and self.date_time and self.unit_amount:
            start = self.date_time
            end = start + timedelta(hours=self.unit_amount)

            if self.exclude_time and self.excluded_end_time > start >= self.excluded_start_time:
                start = self.excluded_end_time
                end = start + timedelta(hours=self.unit_amount)
                self._generate_timesheet_interval(start, end)
            elif self.exclude_time and end > self.excluded_start_time and start < self.excluded_end_time:
                start_delta = self.excluded_start_time - start
                self._generate_timesheet_interval(start, start + start_delta)
                self._generate_timesheet_interval(
                    self.excluded_end_time, self.excluded_end_time +
                    timedelta(hours=self.unit_amount) - start_delta
                )
            else:
                self._generate_timesheet_interval(start, end)

    def _generate_timesheet_interval(self, start, end):
        diff = (end - start) / len(self.production_ids)
        i = 0
        line_ids = self.env['mrp.distribute.timesheet.line']
        for production_id in self.production_ids:
            vals = {
                'start_time': i * diff + start,
                'end_time': (i + 1) * diff + start,
                'project_id': production_id.project_id.id,
                'production_id': production_id.id,
            }
            line_ids += self.env['mrp.distribute.timesheet.line'].create(vals)
            i += 1
        self.timesheet_line_ids += line_ids

    @api.model
    def _get_or_create_task(self, project_id, name):
        time_tracking_type = self.env.ref(
            'project_identification.time_tracking_type'
        )
        stage_done = self.env.ref(
            'project_task_default_stage.project_tt_deployment'
        )
        task_id = self.env['project.task'].search(
            [
                ('project_id', '=', project_id.id),
                ('name', '=', name),
            ],
            limit=1
        )
        if not task_id:
            vals = {
                'project_id': project_id.id,
                'type_id': time_tracking_type.id,
                'stage_id': stage_done.id,
                'name': name,
            }
            task_id = self.env['project.task'].create(vals)
        return task_id

    def _do_distribute(self):
        if not self.timesheet_line_ids:
            raise ValidationError(
                _('The number of timesheet lines cannot be 0.')
            )

        for line_id in self.timesheet_line_ids:
            name = self.reason_id.name
            if self.reason_id == self.env.ref(
                'mrp_timesheet_distribution.other'
            ):
                name = self.custom_reason

            vals_line = line_id._prepare_analytic_line(name)
            if not 'task_id' in vals_line:
                vals_line['task_id'] = self._get_or_create_task(
                    line_id.project_id, name
                ).id

            self.env['account.analytic.line'].create(vals_line)


import numpy as np
from typing import Union, Optional, Any

from ..utils.vector import Vector

Position = Vector
Action = int
Cost = Union[int, float]
AdjList = dict[int, list[tuple[int, Cost]]]
AdjMatrix = np.ndarray
PosToIdx = dict[Position, int]
TextMaze = list[list[str]]
GameResult = dict[str, Optional[Any]]
Params = dict[str, Any]


class Node:
    def __init__(self, value):
        self.value = value
        self.right = None
        self.left = None

class BinaryTree:

    def __init__(self):
        self.root = None

    def breadth_first(self,root):
        visit=[]
        rot=[]
        if root!=None:
            current = root
            rot+=[current]

            try:
                while rot!=[]:
                    rot+=[rot[0].left]
                    rot+=[rot[0].right]
                    visit+=[rot[0].value]
                    del rot[0]
            except:

                return visit
        else:
            raise Exception("tree is empty")

class BinarySearchTree(BinaryTree):
    """
    this class is a  subclass of the BinaryTree class with Add and Contain methods
    """
    def __init__(self):
        super().__init__()
        self.root = None

    def add(self, value):
        if self.root is None:
            self.root = Node(value)
            return
        cur_node = self.root
        added_to_tree = False
        while not added_to_tree:
            if cur_node.value >= value:
                if cur_node.left is None:
                    cur_node.left = Node(value)
                    added_to_tree = True
                else:
                    cur_node = cur_node.left
            elif cur_node.value < value:
                if cur_node.right is None:
                    cur_node.right = Node(value)
                    added_to_tree = True
                else:
                    cur_node = cur_node.right

    def contains(self, value):
        bool_res = False
        cur_node = self.root
        while not bool_res:
            if cur_node.value == value:
                return True
            elif cur_node.value > value:
                if cur_node.left is None:
                    bool_res = True
                else:
                    cur_node = cur_node.left
            elif cur_node.value < value:
                if cur_node.right is None:
                    bool_res = True
                else:
                    cur_node = cur_node.right
        return False

    def maxValue(self):
        if self.root!=None:
            current = self.root

            while (current.right):
                current = current.right
            return current.value
        else:
            raise Exception("tree is empty")

trees=BinaryTree()
root = Node(1)
root.left = Node(6)
root.right = Node(3)
root.left.left = Node(7)
root.left.right = Node(5)
print(trees.breadth_first(root))


# Import keras.
import keras as kr
import tensorflow as tf
from keras.models import Sequential
from keras.datasets import mnist
from keras.models import Sequential, load_model
from keras.layers.core import Dense, Dropout, Activation
from keras.utils import np_utils
from keras.models import load_model
import sklearn.preprocessing as pre
import sys
import gzip
import numpy as np
import cv2
import matplotlib.pyplot as plt
import PIL
from PIL import Image, ImageDraw, ImageTk
import tkinter as tk
import os.path

## Function to build the model, need to have a folder called dataset on same level as the script
## .gz files must be located in here

## Canvas all taken from https://www.youtube.com/watch?v=OdDCsxfI8S0
width = 200
height = 200
center = height//2
white = (255, 255, 255)
green = (0,128,0)
ModelCreated = False

def save():
    filename = "image.png"
    image1.save(filename)

def paint(event):
    # python_green = "#476042"
    x1, y1 = (event.x - 1), (event.y - 1)
    x2, y2 = (event.x + 1), (event.y + 1)
    cv.create_oval(x1, y1, x2, y2, fill="black",width=5)
    draw.line([x1, y1, x2, y2],fill="black",width=5)

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

def buildModel():

    model = kr.models.Sequential()

    ## https://machinelearningmastery.com/handwritten-digit-recognition-using-convolutional-neural-networks-python-keras/
    ## Used this reference for dropout values as I was unsure why this was used
    model.add(Dense(512, input_shape=(784,)))
    model.add(Activation('relu'))
    model.add(Dropout(0.2))

    model.add(Dense(512))
    model.add(Activation('relu'))
    model.add(Dropout(0.2))

    model.add(Dense(10))
    model.add(Activation('softmax'))

    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

    with gzip.open('dataset/train-images-idx3-ubyte.gz', 'rb') as f:
        train_img = f.read()

    with gzip.open('dataset/train-labels-idx1-ubyte.gz', 'rb') as f:
        train_lbl = f.read()

    train_img =  np.array(list(train_img[16:])).reshape(60000, 28, 28).astype(np.uint8)/ 255.0
    train_lbl =  np.array(list(train_lbl[ 8:])).astype(np.uint8)

    encoder = pre.LabelBinarizer()
    encoder.fit(train_lbl)
    outputs = encoder.transform(train_lbl)
    inputs = train_img.reshape(60000, 784)

    # Train the model with our inputs(Images) and outputs (Labels)
    #print("Building neural network - May take a few mins!")
    model.fit(inputs, outputs, epochs=10, batch_size=128)
    model.save('Mnist')

def CompareImage(imageFile):
    with gzip.open('dataset/train-labels-idx1-ubyte.gz', 'rb') as f:
        train_lbl = f.read()
    train_lbl =  np.array(list(train_lbl[ 8:])).astype(np.uint8)

    New_model = load_model('Mnist')
    print("According to my network your number is: ")
    encoder = pre.LabelBinarizer()
    encoder.fit(train_lbl)
    print(encoder.inverse_transform(New_model.predict(imageFile)))

def convertImage(imagefile):

    ## Really good reference for this : http://www.appstate.edu/~marshallst/GLY3455/lectures/9_Image_Processing.pdf

    ## Convert to greyscale
    im = Image.open(imagefile).convert('L')

    ## Make sure image is resized
    im= im.resize((28, 28), Image.BICUBIC)

    ## Convert to list
    im = list(im.getdata())

    # Currently everything is in bytes 0 - 255 , we want to make this 0-1
    im = [(255 - x) * 1.0 / 255.0 for x in im]

    ## need to reshape for our model, expects an array of length 1-D array of size 784
    im =  np.array(list(im)).reshape(1,784)

    print("Image successfully converted! Sending To model")

    ## Send the ready array to our build model function
    CompareImage(im)

def print_menu():

    print("-" * 15 , "Welcome to Keiths Digit Recognition Script" , 15 * "-")
    print("A. Create Model (Must do this first) " + "Model Created: " + str(ModelCreated))
    print("B. Select your own image")
    print("C. Draw your digit")
    print("D. Exit")

loop=True

## Check if model is created

while loop:
         ## While loop which will keep going until loop = False
    if os.path.isfile('Mnist'):
        ModelCreated = True

    print_menu()    ## Displays menu
    choice = input("Enter your choice [A-C]: ")
    print(choice)

    if choice == 'A':
        print("Creating Model")
        buildModel()
    elif choice == 'B':
        userInput = input("Please enter file name/path: ")
        convertImage(userInput)
    elif choice=='C':
        # Canvas taken from https://www.youtube.com/watch?v=OdDCsxfI8S0
        print("Creating canvas (X canvas off when finished and select option one and enter 'image.png')")
        root = tk.Tk()

        # Tkinter create a canvas to draw on
        cv = tk.Canvas(root, width=width, height=height, bg='white')
        cv.pack()

        # PIL create an empty image and draw object to draw on
        # memory only, not visible
        image1 = PIL.Image.new("RGB", (width, height), white)
        draw = ImageDraw.Draw(image1)

        # do the Tkinter canvas drawings (visible)
        # cv.create_line([0, center, width, center], fill='green')

        cv.pack()
        cv.bind("<B1-Motion>", paint)

        # do the PIL image/draw (in memory) drawings
        # draw.line([0, center, width, center], green)

        # PIL image can be saved as .png .jpg .gif or .bmp file (among others)
        # filename = "my_drawing.png"
        # image1.save(filename)
        button=tk.Button(text="save",command=save)
        button.pack()
        root.mainloop()
    elif choice=='D':
        print("Exit")

        ## You can add your code or functions here
        loop=False # This will make the while loop to end as not value of loop is set to False
    else:
        # Any integer inputs other than values 1-5 we print an error message
        print("Wrong option selection. Enter any key to try again..")


# # -*- coding:utf-8 -*-
import time

starting_time = time.time()

import warnings

warnings.filterwarnings(action='ignore')

import math
import csv
import pandas as pd
import numpy as np

np.set_printoptions(precision=8, suppress=True)
pd.options.display.float_format = '{:.8f}'.format

from tensorflow.keras.models import load_model
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras import metrics

from Working_code import config as cf
from Working_code import tts

logger = cf.logging.getLogger("__Planning__")

def planning(row):
    # append the row to the list
    logger.info("Making raw data to list")
    cf.data_list.append(row)
    logger.info("Making raw data to list Done")
    # print(cf.data_list)
    # if the list items are 15 then execute below
    if len(cf.data_list) == 15:
        # start time recording
        start_time = time.time()

        # changing the list to dataframe format
        logger.info("Making 15 items to Dataframe")
        dataframe_list = pd.DataFrame(cf.data_list, columns=cf.columns)

        # insert 'Type', 'RowID', 'Id' to the dataframe
        dataframe_list.insert(0, 'Type', 0)
        dataframe_list.insert(0, 'RowID', 1)
        dataframe_list.insert(0, 'Id', 1)

        # cleaning the dataframe (changing string to numbers, int to float, etc
        logger.info("Transform Dataframe to wanted shape")
        data_cleaning(dataframe_list)

        # Drop the useless columns
        dataframe_list = dataframe_list.drop(columns=cf.drop_column_list, axis=1)

        print(dataframe_list)

        # make the 'RowID' column to the numpy array
        logger.info("Making data to array")
        rowID_list = np.array(dataframe_list['RowID'].drop_duplicates())

        # transform the dataframe and append it to the X (list)
        for rowID in rowID_list:
            tmp_data = dataframe_list[dataframe_list['RowID'] == rowID]
            feature = tmp_data.iloc[:, 4:].apply(pd.to_numeric)
            feature = np.array(feature)
            cf.X.append(feature)

        # changing the X to numpy array
        X_arr = np.array(cf.X)

        logger.info(f"data shape : {X_arr.shape}")

        # make prediction
        logger.info("Prediction Starts")
        prediction = cf.model.predict(X_arr, verbose=1)
        prediction_list = prediction.tolist()
        prediction_list = sum(prediction_list,[])
        for i in range(len(prediction_list)):
            prediction_list[i] = "{:.5f}".format(prediction_list[i])
        for i in range(len(prediction_list)):
            cf.prediction_result_data.append(float(prediction_list[i]))
        print(cf.prediction_result_data)

        #for i in range(len(cf.prediction_result_data)):
        #    cf.prediction_result_data[i] = format(cf.prediction_result_data[i],'f')

        # get the max value and the index of that max value (if index is 3, then category number is 3)
        value = max(cf.prediction_result_data)
        max_index = cf.prediction_result_data.index(value)
        cf.prediction_result_data.append(max_index)
        cf.prediction_result_data.append(value)

        # Type -Night:0, Resources:1, Monster:2, Build Stuff:3, Social Interaction:4, External Events:5
        # if the score is above 0.8 and index is as 0,1,2,3,4,5 then return synthesized tts
        logger.info("Prediction Result to TTS")
        if cf.prediction_result_data[6] == 0 and cf.prediction_result_data[7] > 0.8:
            tts.synthesize_utt('Night')
            cf.count += 1
        elif cf.prediction_result_data[6] == 1 and cf.prediction_result_data[7] > 0.8:
            tts.synthesize_utt('Resources')
            cf.count += 1
        elif cf.prediction_result_data[6] == 2 and cf.prediction_result_data[7] > 0.8:
            tts.synthesize_utt('Monster')
            cf.count += 1
        elif cf.prediction_result_data[6] == 3 and cf.prediction_result_data[7] > 0.8:
            tts.synthesize_utt('Build Stuff')
            cf.count += 1
        elif cf.prediction_result_data[6] == 4 and cf.prediction_result_data[7] > 0.8:
            tts.synthesize_utt('Social Interaction')
            cf.count += 1
        elif cf.prediction_result_data[6] == 5 and cf.prediction_result_data[1] > 0.8:
            tts.synthesize_utt('External Events')
            cf.count += 1

        # Append count and \n (for identifying previous result and current result at the csv) to the list
        logger.info("Prediction Result to CSV")
        cf.prediction_result_data.append(cf.count)

        # Add the time consumption to the list
        current_time = round((time.time() - start_time), 2)
        cf.total_time = cf.total_time + current_time

        cf.prediction_result_data.append(current_time)
        cf.prediction_result_data.append(cf.total_time)
        cf.prediction_result_data.append(int(time.time()))
        # cf.prediction_result_data.append('\n')

        # write all the info to the csv file
        if cf.csvcounter == 1:
            with open("multi_accuracy_result.csv", encoding="utf-8", newline='', mode="w") as f:
                writer = csv.writer(f)
                writer.writerow(['category 1 acc','category 2 acc','category 3 acc', 'category 4 acc', 'category 5 acc', 'category 6 acc','category','top acc','count','time','total time', 'posix time'])
                writer.writerow(cf.prediction_result_data)

            cf.csvcounter = cf.csvcounter + 1

        elif cf.csvcounter == 2:
            with open("multi_accuracy_result.csv", encoding="utf-8", newline='', mode="a") as f:
                writer = csv.writer(f)
                writer.writerow(cf.prediction_result_data)

        if cf.total_time >= 60:
            cf.count = 0
            cf.total_time = 0

        # print(cf.prediction_result_data)

        cf.data_list.clear()
        cf.prediction_result_data.clear()
        cf.X.clear()

def data_cleaning(dataframe_list):
    # Splitting combined columns
    dataframe_list[['Affected_Hunger', 'Affected_Health', 'Affected_Sanity']] = dataframe_list['hunger:health:sanity'].str.split(':', n=2, expand=True)
    dataframe_list[['log', 'rock', 'grass', 'twigs']] = dataframe_list['log:rock:grass:twigs'].str.split(':', n=3, expand=True)
    dataframe_list[['twigs_removed', 'flint']] = dataframe_list['twigs:flint'].str.split(':', n=1, expand=True)

    # Change several columns: String to float/int
    dataframe_list[['Affected_Hunger', 'Affected_Health', 'Affected_Sanity']] = dataframe_list[['Affected_Hunger', 'Affected_Health', 'Affected_Sanity']].astype(float)
    dataframe_list[['log', 'rock', 'grass', 'twigs', 'flint']] = dataframe_list[['log', 'rock', 'grass', 'twigs', 'flint']].astype(int)
    dataframe_list[['Player_Xloc', 'Player_Zloc']] = dataframe_list[['Player_Xloc', 'Player_Zloc']].astype(float)

    # creating ['Motion'], ['agg_Motion']
    dataframe_list[['Motion', 'agg_Motion']] = None
    for i in range(len(dataframe_list)):
        if i % 15 == 0:
            dataframe_list.loc[i, 'Motion'] = 0
            dataframe_list.loc[i, 'agg_Motion'] = 0
        else:
            # ['Motion']
            dx = dataframe_list['Player_Xloc'].iloc[i] - dataframe_list['Player_Xloc'].iloc[i - 1]
            dz = dataframe_list['Player_Zloc'].iloc[i] - dataframe_list['Player_Zloc'].iloc[i - 1]
            dist = math.sqrt((dx ** 2) + (dz ** 2))
            dataframe_list['Motion'].iloc[i] = dist

            # ['agg_Motion']
            dataframe_list['agg_Motion'].iloc[i] = dataframe_list['agg_Motion'].iloc[i - 1] + dist

    for i in range(len(dataframe_list)):
        # Type -Night:0, Resources:1, Monster:2, Build Stuff:3, Social Interaction:4, External Events:5
        # Phase -day:0, dusk:1, night:2
        if dataframe_list.loc[i, 'Phase'] == 'day':
            dataframe_list.loc[i, 'Phase'] = 0
        elif dataframe_list.loc[i, 'Phase'] == 'dusk':
            dataframe_list.loc[i, 'Phase'] = 1
        else:
            dataframe_list.loc[i, 'Phase'] = 2

        # Food -'No Food!':0, 'Less Food!':1, 'Fine!':2
        if dataframe_list.loc[i, 'Food_AVATAR'] == 'No Food!':
            dataframe_list.loc[i, 'Food_AVATAR'] = 0
        elif dataframe_list.loc[i, 'Food_AVATAR'] == 'Less Food!':
            dataframe_list.loc[i, 'Food_AVATAR'] = 1
        else:
            dataframe_list.loc[i, 'Food_AVATAR'] = 2

        # Curr_Active_Item
        if dataframe_list.loc[i, 'Curr_Active_Item_AVATAR'] == 'nil':
            dataframe_list.loc[i, 'Curr_Active_Item_AVATAR'] = 0
        else:
            dataframe_list.loc[i, 'Curr_Active_Item_AVATAR'] = 1

        # Curr_Equip_Hands
        if dataframe_list.loc[i, 'Curr_Equip_Hands_AVATAR'] == 'nil':
            dataframe_list.loc[i, 'Curr_Equip_Hands_AVATAR'] = 0
        else:
            if dataframe_list.loc[i, 'Curr_Equip_Hands_AVATAR'].rsplit('-')[1].lstrip() == 'axe(LIMBO)':
                dataframe_list.loc[i, 'Curr_Equip_Hands_AVATAR'] = 1
            elif dataframe_list.loc[i, 'Curr_Equip_Hands_AVATAR'].rsplit('-')[1].lstrip() == 'pickaxe(LIMBO)':
                dataframe_list.loc[i, 'Curr_Equip_Hands_AVATAR'] = 2
            else:
                dataframe_list.loc[i, 'Curr_Equip_Hands_AVATAR'] = 3

        # Attack_Target
        if dataframe_list.loc[i, 'Attack_Target_AVATAR'] == 'nil':
            dataframe_list.loc[i, 'Attack_Target_AVATAR'] = 0
        else:
            dataframe_list.loc[i, 'Attack_Target_AVATAR'] = 1

        # Defense_Target
        if dataframe_list.loc[i, 'Defense_Target_AVATAR'] == 'nil':
            dataframe_list.loc[i, 'Defense_Target_AVATAR'] = 0
        else:
            dataframe_list.loc[i, 'Defense_Target_AVATAR'] = 1

        # Recent_attacked
        if dataframe_list.loc[i, 'Recent_attacked_AVATAR'] == 'nil':
            dataframe_list.loc[i, 'Recent_attacked_AVATAR'] = 0
        else:
            dataframe_list.loc[i, 'Recent_attacked_AVATAR'] = 1

        # Tool -'Less resources':0, 'Only Axe', 'One of Axe and Pickaxe':1, 'Fine':2
        if dataframe_list.loc[i, 'Tool_AVATAR'] == 'Less resources':
            dataframe_list.loc[i, 'Tool_AVATAR'] = 0
        elif (dataframe_list.loc[i, 'Tool_AVATAR'] == 'Only Axe') | (dataframe_list.loc[i, 'Tool_AVATAR'] == 'One of Axe and Pickaxe'):
            dataframe_list.loc[i, 'Tool_AVATAR'] = 1
        else:
            dataframe_list.loc[i, 'Tool_AVATAR'] = 2

        # Lights -'Less resources':0, 'Only torch':1, 'It's OK', 'Fine':2
        if dataframe_list.loc[i, 'Lights_AVATAR'] == 'Less resources':
            dataframe_list.loc[i, 'Lights_AVATAR'] = 0
        elif dataframe_list.loc[i, 'Lights_AVATAR'] == 'Only torch':
            dataframe_list.loc[i, 'Lights_AVATAR'] = 1
        else:
            dataframe_list.loc[i, 'Lights_AVATAR'] = 2

        # Is_Light -'No lights!':0, 'Lights nearby':1, 'Campfire nearby':2
        if dataframe_list.loc[i, 'Is_Light_AVATAR'] == 'No lights!':
            dataframe_list.loc[i, 'Is_Light_AVATAR'] = 0
        elif dataframe_list.loc[i, 'Is_Light_AVATAR'] == 'Lights nearby':
            dataframe_list.loc[i, 'Is_Light_AVATAR'] = 1
        else:
            dataframe_list.loc[i, 'Is_Light_AVATAR'] = 2

        # Is_Monster -'No monsters nearby':0, 'I see some monsters':1, 'too many monsters':2
        if dataframe_list.loc[i, 'Is_Monster_AVATAR'] == 'No monsters nearby':
            dataframe_list.loc[i, 'Is_Monster_AVATAR'] = 0
        elif dataframe_list.loc[i, 'Is_Monster_AVATAR'] == 'I see some monsters':
            dataframe_list.loc[i, 'Is_Monster_AVATAR'] = 1
        else:
            dataframe_list.loc[i, 'Is_Monster_AVATAR'] = 2

    return dataframe_list