import json

# Getting the token from json file

instar_info = """Hello. В этом уно может участвовать максимум 8 человек.
Бот создаёт сначало комнаты и роли, а также добовляет эмодзи на сервер. Выбор карты в боте необычный к примеру чтобы выбрать карту: **красная 6**, то надо написать: `r 6`.
Если вы незнаете правила то зайдите на этот сайт: https://igorek.info/kartochnaya-igra-uno-pravila-igryi-v-uno/""".expandtabs(2)

# Uno Config
category_name = "UNO | Игра"

seat_amount = 8
channel_names = [f"uno-комната-{numb}" for numb in range(1, seat_amount + 1)]
role_names = [f"{numb} | UNO Права к комнате" for numb in range(1, seat_amount + 1)]

# Function

def format_time(seconds):
    out = ""

    m, s = divmod(int(seconds), 60)
    h, m = divmod(m, 60)

    if h > 0:
        out += f"{h}h"
    out += f"{m}m{s}s"

    return out


# string rotation: assume you have a method is_substring which checks if one word is a substring of
# another. Given two strings, s1 and s2, check if s2 is a rotation of s1 using oonyl one call to
# is_substring

# a rotated string has one pivot point: example - waterbottle / erbottewat
# so the question is there a way we can make s1 (xy) into s2 (yx)?
# we can check if the xy in yxyx=y(xy)x is equal to s1, i.e. if s1 is a substring of s2s2

def is_substring(s1: str, s2: str) -> bool:
    return s1 in s2

def is_string_rotation(s1: str, s2: str) -> bool:
    if len(s1) != len(s2):
        return False
    return is_substring(s1, s2 + s2)

if __name__ == "__main__":
    print(is_string_rotation('waterbottle', 'erbottlewat'))
    print(is_string_rotation('waterbottle', 'erbottwattt'))
    print(is_string_rotation('waterbottle', 'erbott'))


import numpy as np
import scipy
import uproot
import awkward as ak
import pandas as pd
import math
from numpy import random
from numpy.matlib import repmat
from scipy.optimize import curve_fit
from scipy.stats import skewnorm
from sklearn import mixture

import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.patches import Circle
from matplotlib.patches import Ellipse
from matplotlib.backends.backend_pdf import PdfPages
import glob
import os
import importlib
import sys
import csv
import json
import datetime
import time as timelib

##########################################
## Functional forms for scipy.curve_fit ##
##########################################

# single gaussian - free amplitude, mean, standard deviation
def gaussian(x, *p):

    A, mu, sigma = p

    return A*np.exp(-(x-mu)**2/(2.*sigma**2))

# constrained double gaussian - assumes second peak comes from sampling first peak twice
# can be used to fit single- and double-PE peaks in SPE calibration
def gaussian_2(x, *p):

    A1, A2, mu_1, sigma_1 = p

    p1 = [A1, mu_1, sigma_1]
    p2 = [A2, 2*mu_1, np.sqrt(2)*sigma_1] # standard deviations add in quadrature

    f = gaussian(x, *p1) + gaussian(x, *p2)

    return f

# constrained triple gaussian - assumes third peak comes from sampling second peak twice
# can be used to fit noise, single- and double-PE peaks in SPE calibration
def gaussian_3(x, *p):

    A0, A1, A2, mu_0, mu_1, sigma_0, sigma_1 = p

    p0 = [A0, mu_0, sigma_0]
    p1 = [A1, mu_1, sigma_1]
    p2 = [A2, 2*mu_1, np.sqrt(2)*sigma_1] # standard deviations add in quadrature

    f = gaussian(x, *p0) + gaussian(x, *p1) + gaussian(x, *p2)

    return f

# constrained quadruple gaussian - assumes higher peaks come from sampling second peak multiple times
# can be used to fit noise and 1/2/3 PE peaks in SPE calibration
def gaussian_4(x, *p):

    A0, A1, A2, A3, mu_0, mu_1, sigma_0, sigma_1 = p

    p0 = [A0, mu_0, sigma_0]
    p1 = [A1, mu_1, sigma_1]
    p2 = [A2, 2*mu_1, np.sqrt(2)*sigma_1] # standard deviations add in quadrature
    p3 = [A3, 3*mu_1, np.sqrt(3)*sigma_1]

    f = gaussian(x, *p0) + gaussian(x, *p1) + gaussian(x, *p2) + gaussian(x, *p3)

    return f

# poisson distribution - free amplitude and expected value
# can be used to check accuracy of multi-PE fits in SPE calibration
def poisson(x, *p):

    x = np.array(x)
    A, l = p

    return A*l**x/scipy.special.factorial(x)*np.exp(-l)

def linearPlusGaussian(x, *p):

    A, mu, sigma, m, b = p

    return A*np.exp(-(x-mu)**2/(2.*sigma**2)) + m*x + b

######################
## Unit conversions ##
######################

# ADC counts -> mV
def adcTomV(array, dVperAdc):

    # array - nD array of raw ADC values from digitzer
    # dVperAdc - voltage step per ADC count = 2.25/2**14 (voltage range/number of ADC values in 14-bit digitization)

    array = np.array(array)

    return array*(dVperAdc*1000)

# SPE area in (ADC Counts)*samples -> gain
def areaToGain(array, dVperAdc, resistance, samplingFreq):

    # array - nD array of pulse areas in units of (ADC Counts)*samples
    # dVperAdc - voltage step per ADC count
    # resistance - PMT HV/signal line resistance
    # samplingFreq - digitizer sampling frequency (100 MHz -> 1e8)

    array = np.array(array)
    fundamentalCharge = 1.602e-19 # coulomb charge per electron

    return array*(dVperAdc/resistance/samplingFreq/fundamentalCharge)

########################
## Analysis functions ##
########################

# compute the gain of each PMT using SPE sizes
def calcGains(voltages, gainFile):

    # gainFile - .csv file with gain fit parameters, generated from relative gain calibration

    voltages = np.array(voltages)
    params = np.genfromtxt(gainFile, delimiter = ',', skip_header = 1) # read fit params file
    gains = 10**(params[:, 1] + params[:, 2])*voltages**params[:, 0] # Gain = 10^(log(A) + offset)*V^p

    return gains

# calculate scale factors to convert ADC counts to PE/sample for each channel
def scaleToPE(dVperAdc, resistance, samplingFreq, gains):

    # dVperAdc - voltage step per ADC count
    # resistance - PMT HV/signal line resistance
    # samplingFreq - digitizer sampling frequency (100 MHz -> 1e8)
    # gains - gain for each PMT, computed by calcGains

    fundamentalCharge = 1.602e-19 # coulomb charge per electron
    PE = dVperAdc/(resistance*samplingFreq*fundamentalCharge*gains)

    return PE

# perform baseline subtraction for each event in a channel
def adjBaseline(array, numSamples):

    # array - 2D array, 10,000 events with microseconds*100 samples/event
    # numSamples - number of samples used to compute baseline

    adj = np.array(array - np.average(array[:, 0:numSamples], axis = 1)) # subtract baseline avg. for each event

    return adj

# compute 3-sample average for a channel
def threeSampleAvg(array):

    # array - 2D array, 10,000 events with microseconds*100 samples/event

    stacked = np.array([np.delete(array, [0, -1], 1), np.delete(array, [-2, -1], 1), np.delete(array, [0, 1], 1)]) # stack arrays shifted -1, 0, 1 samples forward
    avg = np.average(stacked, axis = 0) # calculate average for each sample

    return avg

# find boundaries between pulses for a given channel and event
def findPulses(pulseIndices, event, absoluteSpacing, relativeSpacing):

    # pulseIndices - parallel arrays, [0] contains event indices, [1] contains sample indices meeting PE/sample threshold
    # event - event in file to look at
    # absoluteSpacing - pulses must be separated by this many samples
    # relative Spacing - pulses must be seperated by this fraction of the summed length of all previous pulses

    cutIndices = pulseIndices[1][np.where(pulseIndices[0] == event)] # select sample indices corresponding to the desired event
    if len(cutIndices) < 2: # we are only interested in pulses >= 20 ns (2 samples)
        return None, None

    indexDiff = cutIndices[1:] - cutIndices[:-1] # calculate spacing between indices meeting PE/sample threshold
    absoluteBoundaries = np.where(indexDiff >= absoluteSpacing)[0] + 1 # define boundaries where spacing > absolute criterion

    if len(absoluteBoundaries) == 0: # if there is only one pulse in the event...
        pulseIntervals = [0, 3000] # look at all cutIndices for that event
    else:
        relativeSpaceCut = (indexDiff[indexDiff >= absoluteSpacing]/absoluteBoundaries > relativeSpacing).flatten() # check if boundaries also meet relative criterion
        pulseBreaks = absoluteBoundaries[relativeSpaceCut] # select boundaries that meet both criteria
        pulseIntervals = np.insert(pulseBreaks, [0, len(pulseBreaks)], [0, 3000]) # insert starting/ending bounds for first/last pulses

    return cutIndices, pulseIntervals

def constructRQArray(options):

    numRQs = np.array(options)*np.array([7, 3, 9, 3, 3, 3]) + 3
    outData = outData = [[] for i in range(len(numRQs))]

    return outData

def constructRQList(options):

    RQList = []

    if options[0] == True:
        RQList.extend(['ch0Area', 'ch1Area', 'ch2Area', 'ch3Area', 'topSumArea', 'botArea', 'totalArea'])

    if options[1] == True:
        RQList.extend(['topSumHeight', 'botHeight', 'totalHeight'])

    if options[2] == True:
        RQList.extend(['topSumWidth', 'botWidth', 'totalWidth'])
        RQList.extend(['topSum05', 'bot05', 'total05'])
        RQList.extend(['topSum95', 'bot95', 'total95'])

    if options[3] == True:
        RQList.extend(['topSumRMS', 'botRMS', 'totalRMS'])

    if options[4] == True:
        RQList.extend(['topSumFw1050', 'botFw1050', 'totalFw1050'])

    if options[5] == True:
        RQList.extend(['topSumPf200', 'botPf200', 'totalPf200'])

    return RQList

def calcRQs(outData, ch0Wf, ch1Wf, ch2Wf, ch3Wf, topSumWf, botWf, totalWf, options):

    return

def applyDataCut(dictionary, mask):

    newDict = dict(dictionary)
    for key in newDict.keys():

        newDict[key] = newDict[key][mask]

    return newDict

def selectNthPulses(dictionary, pulse):

    values, indices = np.unique(dictionary['eventNum'], return_index = True)
    indices = indices + (pulse - 1)
    nthPulses = applyDataCut(dictionary, indices)

    return nthPulses

def reconstructPosition(dictionary, cartCoor):

    XPulsesPos = cartCoor*(dictionary['ch1Area'] - dictionary['ch0Area'] - dictionary['ch3Area'] + \
                           dictionary['ch2Area'])/dictionary['topSumArea']
    YPulsesPos = cartCoor*(dictionary['ch1Area'] + dictionary['ch0Area'] - dictionary['ch3Area'] - \
                           dictionary['ch2Area'])/dictionary['topSumArea']

    return np.array(XPulsesPos), np.array(YPulsesPos)

def calcPositionMeanVals(dictionary, key, XPos, YPos, xBins, yBins, cartCoor):

    keyList = [[[] for i in range(len(xBins))] for j in range(len(yBins))]

    for event in range(len(dictionary[key])):

        xIndex = np.searchsorted(xBins, XPos[event], side = 'right') - 1
        yIndex = np.searchsorted(yBins, YPos[event], side = 'right') - 1

        keyList[yIndex][xIndex].append(dictionary[key][event])

    keyMeans = ak.mean(ak.Array(keyList), axis = -1)
    keyFilled = ak.fill_none(keyMeans, 0)

    return keyFilled

def drawEllipseSelection(ratio, theta):

    t = np.linspace(0, 2*np.pi, 100)

    xEllipse = ratio*np.cos(t)*np.cos(theta) + np.sin(t)*np.sin(theta)
    yEllipse = -ratio*np.cos(t)*np.sin(theta) + np.sin(t)*np.cos(theta)

    return xEllipse, yEllipse

def cutEllipseSelection(S1Dict, S2Dict, ratio, theta, xCenter, yCenter, xScale, yScale):

    ellipseMask = ((S1Dict['botArea'] - xCenter)/xScale*np.cos(-theta) + \
                   (S2Dict['topSumArea'] - yCenter)/yScale*np.sin(-theta))**2/ratio**2 + \
                  (-(S1Dict['botArea'] - xCenter)/xScale*np.sin(-theta) + \
                   (S2Dict['topSumArea'] - yCenter)/yScale*np.cos(-theta))**2 <= 1

    S1Ellipse = applyDataCut(S1Dict, ellipseMask)
    S2Ellipse = applyDataCut(S2Dict, ellipseMask)

    return S1Ellipse, S2Ellipse

def calcAnticorrelationParams(S1Dict, S2Dict):

    dataSet = np.transpose(np.vstack((S1Dict['botArea'], S2Dict['topSumArea'])))
    clf = mixture.GaussianMixture(n_components = 1, covariance_type = "full")
    clf.fit(dataSet)

    v, w = scipy.linalg.eigh(clf.covariances_[0])
    v = 2.0 * np.sqrt(2.0) * np.sqrt(v)
    u = w[0]/scipy.linalg.norm(w[0])

    theta = np.arctan(u[1]/u[0])
    xMean = clf.means_[0][0]
    yMean = clf.means_[0][1]

    return xMean, yMean, theta

def calcMicroG1G2(xIntercept, yIntercept, energy, W):

    quanta = energy/W

    g1 = xIntercept/quanta
    g2 = yIntercept/quanta

    return g1, g2

def calcEventEnergies(S1Dict, S2Dict, g1, g2, W):

    E = W*(S1Dict['botArea']/g1 + S2Dict['topSumArea']/g2)

    return E

def calcElectronLifetime(driftTimes, S2Dict, driftMin, driftMax, fitMin, fitMax):

    tS2Sizes = np.log(S2Dict['topSumArea'])
    rangeCut = (driftTimes >= driftMin) & (driftTimes <= driftMax)
    seltS2Sizes = tS2Sizes[rangeCut]

    driftFit = np.polyfit(driftTimes, seltS2Sizes, 1)
    xRange = np.arange(fitMin, fitMax, 0.1)
    yRange = driftFit[0]*xRange + driftFit[1]

    return driftFit, xRange, yRange

def prepChannelData(dataFile, gainFile, voltages, dVperAdc, resistance, samplingFreq, baselineSamples, PEThreshold):

    gains = calcGains(voltages, gainFile)
    scaleFactorsPE = scaleToPE(dVperAdc, resistance, samplingFreq, gains)

    rootFile = uproot.open(dataFile)

    ch0 = rootFile['Channel0/ADCValues'].array()
    ch0Adj = adjBaseline(ch0, baselineSamples)*scaleFactorsPE[0]
    ch1 = rootFile['Channel1/ADCValues'].array()
    ch1Adj = adjBaseline(ch1, baselineSamples)*scaleFactorsPE[1]
    ch2 = rootFile['Channel2/ADCValues'].array()
    ch2Adj = adjBaseline(ch2, baselineSamples)*scaleFactorsPE[2]
    ch3 = rootFile['Channel3/ADCValues'].array()
    ch3Adj = adjBaseline(ch3, baselineSamples)*scaleFactorsPE[3]
    ch4 = rootFile['Channel4/ADCValues'].array()
    ch4Adj = adjBaseline(ch4, baselineSamples)*scaleFactorsPE[4]

    botAdj = ch4Adj[:, 4:]
    topSumAdj = (ch0Adj + ch1Adj + ch2Adj + ch3Adj)[:, :-4]
    totalAdj = botAdj + topSumAdj

    ch0Avg = threeSampleAvg(ch0Adj[:, :-4])
    ch1Avg = threeSampleAvg(ch1Adj[:, :-4])
    ch2Avg = threeSampleAvg(ch2Adj[:, :-4])
    ch3Avg = threeSampleAvg(ch3Adj[:, :-4])
    botAvg = threeSampleAvg(botAdj)
    topSumAvg = threeSampleAvg(topSumAdj)
    totalAvg = threeSampleAvg(totalAdj)

    thresholdMask = totalAvg < -1*PEThreshold
    pulseIndices = np.nonzero(thresholdMask)

    return ch0Avg, ch1Avg, ch2Avg, ch3Avg, botAvg, topSumAvg, totalAvg, pulseIndices

##################
## File loading ##
##################

#return sorted file names of a specified type from a directory
def getFileList(filePath, fileType):

    # filePath - directory containing files to be sorted
    # fileType - file extension to look for, eg. '*.root'; for all files use '*'

    fileNames = sorted(filter(os.path.isfile, glob.glob(filePath + fileType)))

    return np.array(fileNames)

def getFileSizes(fileNames):

    fileSizes = [os.path.getsize(f) for f in fileNames]

    return np.array(fileSizes)

def loadData(selFiles, RQs):

    RQDict = {}
    fileNum = 0
    for file in selFiles:

        for RQ in RQs:

            RQVals = uproot.open(file + ':' + RQ)['Values'].array()
            if RQ == 'eventNum':
                RQVals = RQVals + 10000*fileNum

            if fileNum == 0:
                RQDict[RQ] = RQVals
            else:
                RQDict[RQ] = ak.concatenate([RQDict[RQ], RQVals])

        fileNum += 1

    return RQDict

def loadRedFile(file, RQs):
    file = file
    RQDict = {}
    f = uproot.open(file)
    for RQ in RQs:
        fileNum = 0
        RQVals = np.array(f['summary/' + RQ].array())
        if RQ == 'eventNum':
            RQVals = RQVals + 10000*fileNum
        if fileNum == 0:
            RQDict[RQ] = RQVals
        else:
            RQDict[RQ] = np.concatenate([RQDict[RQ], RQVals])
    return RQDict

def loadRawData(f,rawNames,scale):
    rawfile = uproot.open(rawNames[f])
    data0 = rawfile['Channel0/ADCValues'].array()
    data1 = rawfile['Channel1/ADCValues'].array()
    data2 = rawfile['Channel2/ADCValues'].array()
    data3 = rawfile['Channel3/ADCValues'].array()
    data4 = rawfile['Channel4/ADCValues'].array()

    data0_adj = data0 - np.average(data0[:, 0:100], axis = 1)
    data1_adj = data1 - np.average(data1[:, 0:100], axis = 1)
    data2_adj = data2 - np.average(data2[:, 0:100], axis = 1)
    data3_adj = data3- np.average(data3[:, 0:100], axis = 1)
    data4_adj = data4 - np.average(data4[:, 0:100], axis = 1)

    if type(scale) is str:
        d0 = data0_adj[:, :-4]
        d1 = data1_adj[:, :-4]
        d2 = data2_adj[:, :-4]
        d3 = data3_adj[:, :-4]

        topsum = d0 + d1 + d2 + d3
        bottom = data4_adj[:,4:]
        total = topsum+bottom
        x = np.arange(0, 2996, 1)
    elif np.isscalar(scale):
        d0 = data0_adj[:, :-4]*scale
        d1 = data1_adj[:, :-4]*scale
        d2 = data2_adj[:, :-4]*scale
        d3 = data3_adj[:, :-4]*scale

        topsum = d0 + d1 + d2 + d3
        bottom = data4_adj[:,4:]*scale
        total = topsum+bottom
        x = np.arange(0, 2996, 1)
    else:
        d0 = data0_adj[:, :-4]*scale[0]
        d1 = data1_adj[:, :-4]*scale[1]
        d2 = data2_adj[:, :-4]*scale[2]
        d3 = data3_adj[:, :-4]*scale[3]

        topsum = d0 + d1 + d2 + d3
        bottom = data4_adj[:,4:]*scale[4]
        total = topsum+bottom
        x = np.arange(0, 2996, 1)

    return x, np.array(d0), np.array(d1), np.array(d2), np.array(d3), np.array(topsum), np.array(bottom), np.array(total)

def ViewEvent(selFiles, rawFiles, RQs, fileNum, eventNum, channels = 'tot', scale='ADC', printRQs = False, xrange = [], yrange=[]):
    #load raw waveform and RQs
    x, d0, d1, d2, d3, topsum, bottom, total = loadRawData(fileNum,rawFiles,scale)
    RQDict = loadRedFile(selFiles[fileNum], RQs)
    #plot waveform
    if len(xrange)>0:
        plt.xlim(xrange[0],xrange[1])
    if len(yrange)>0:
        plt.ylim(yrange[0],yrange[1])
    if type(scale) is str:
        plt.xlabel('samples')
        plt.ylabel('ADC counts')
    elif np.isscalar(scale):
        plt.xlabel('samples')
        plt.ylabel('mV')
    else:
        plt.xlabel('samples')
        plt.ylabel('PE')
    if channels == 'all':
        plt.plot(x,d0[eventNum],label='tPMT0')
        plt.plot(x,d1[eventNum]-10,label='tPMT1')
        plt.plot(x,d2[eventNum]-20,label='tPMT2')
        plt.plot(x,d3[eventNum]-30,label='tPMT3')
        plt.plot(x,bottom[eventNum]-50,label='bPMT')
        plt.legend(fontsize=12)
        plt.show()
    elif channels == 'tb':
        plt.plot(x,topsum[eventNum],label='topSum')
        plt.plot(x,bottom[eventNum]-20,label='bPMT')
        plt.legend(fontsize=12)
        plt.show()
    else:
        plt.plot(x,total[eventNum])
        plt.show()
    #print RQs
    if printRQs == True:
        eventInds = np.where(np.in1d(RQDict['eventNum'],eventNum))[0]
        print('Pulses in event:',len(eventInds))
        if len(eventInds)==2:
            driftTime = RQDict['startTime'][eventInds[1]] - RQDict['endTime'][eventInds[0]]
            print('driftTime:',driftTime)
            print()
        for i in range(len(eventInds)):
            print('Pulse '+str(i+1)+':')
            for RQ in RQs:
                print(str(RQ)+':',RQDict[str(RQ)][eventInds[i]])
            print()

##########################################
## PMT calibration and characterization ##
##########################################

def LED_simple(fileNames, start, stop, channel):

    areas = []
    heights = []
    offsets = []
    for n in range(len(fileNames)):
        root_file = uproot.open(fileNames[n])

        PMT = root_file['Channel' + str(channel) + '/ADCValues'].array()
        PMT_adj = PMT - np.average(PMT[:, 0:100], axis = 1)

        for i in range(len(PMT_adj)):
            total_wf = np.array(PMT_adj[i][start:stop])
            area = -1*sum(total_wf)
            height = -1*np.amin(total_wf)
            offset = np.amax(total_wf)
            areas.append(area)
            heights.append(height)
            offsets.append(offset)

    return areas, heights, offsets

def compute_area(*p):
    A, mu, sigma = p
    x = np.arange(-5*sigma, 5*sigma, 1) + mu
    fit = gaussian(x, *p)
    return sum(fit)

def PMTPulseArea(fileNames, channel, start, cutoff, pulseArea):
    for fileName in fileNames:
        file = uproot.open(fileName)
        adc = file['Channel'+str(channel)+'/ADCValues'].array()
        ##Take the average of the first 100 adc values for each event, and shift everything by that
        ##This will make it easier to integrate later, since we can just sum the adjusted adc values
        adc_adj = adc - np.average(adc[:, 0:100], axis = 1)

        for event in range(len(adc_adj)):
            ##Find the first adc value before 1600 counts that is positive, indicating the end of the signal
            try:
                interval = np.where(adc_adj[event][cutoff:1600] >= 0)[0][0]
            except:
                print(fileName, event)
            end = cutoff + interval
            ##Integrate over the pulse area. Multiplying by -1 since the pulse is negative
            pulseArea.append(-1*sum(adc_adj[event][start:end]))
    return pulseArea

def count_pulses(fileNames, threshold, channel):

    total_pulses = []
    for fileName in fileNames:

        root_file = uproot.open(fileName)
        PMT = root_file['Channel' + str(channel) + '/ADCValues'].array()
        PMT_adj = PMT - np.average(PMT[:, 0:100], axis = 1)

        for event in PMT_adj:

            trigger = np.nonzero(event[0:1400] < threshold/(2.25/2**14*1000))[0]
            spaces = trigger[1:] - trigger[:-1]
            pulses = sum(spaces > 1)
            if len(trigger) > 0:
                pulses += 1
            total_pulses.append(pulses)

    return total_pulses

#################################
## Trigger rate and levelmeter ##
#################################

# remove unwanted trigger data before plotting
def prepTriggerData(triggerFile):

    # triggerFile - .txt file with trigger rates for each PMT + corresponding unix times
    # Note - trigger rates in the first and last second of each file need to be discarded because they do not represent
    #        a full second of data taking

    triggerData = np.genfromtxt(triggerFile, delimiter = ' ') # read trigger data
    goodVals = np.delete(triggerData, [0, len(triggerData) - 1], axis = 0) # cut first and last second from the data
    times = goodVals[:, 0] - np.amin(goodVals[:, 0]) # compute times since data-taking start

    for i in range(len(times) - 1, 0, -1): # start at the end of the file and work backwards
        if times[i] - times[i - 1] > 1: # if time spacing between data points > 1 second (aka new file)...
            goodVals = np.delete(goodVals, [i - 1, i], axis = 0) # delete data points on both sides

    adjTimes  = goodVals[:, 0] - np.amin(goodVals[:, 0]) # recompute times for selected data only

    return goodVals, adjTimes

# get the detector liquid level at the given unix times
def getLiquidLevels(timeStamps, levelFile, startUnixTime):

    # timeStamps - unix times at which liquid levels are calculated
    # levelData - 2D array of time in seconds *SINCE SLOW CONTROL DATABASE INITIALIZED* and level values at those times
    # startUnixTime - unix time of first value in levelData, computed manually

    levelData = np.genfromtxt(levelFile, delimiter = ',', skip_header = 1)[:, 1:] # read level data

    levelTimes = levelData[:, 0] # get database times
    levelVals = levelData[:, 1] # get level values
    adjLevelTimes = (levelTimes - levelTimes[0]) + startUnixTime # convert database times to unix times

    finalLevels = [] # initialize return array for liquid levels
    for timeStamp in timeStamps: # for each time stamp...

        index = np.searchsorted(adjLevelTimes, timeStamp, side = 'right') # adjLT[index - 1] <= timeStamp < adjLT[index]

        if timeStamp == adjLevelTimes[index - 1]: # check edge condition caused due to <= sign in np.searchsorted
            finalLevels.append(levelVals[index - 1])
        else:
            levelStep = levelVals[index] - levelVals[index - 1] # compute step between closest database values
            frac = (timeStamp - adjLevelTimes[index - 1])/(adjLevelTimes[index] - adjLevelTimes[index - 1]) # percent of the way to next database value
            compLevel = levelVals[index - 1] + levelStep*frac # linear interpolation between values
            finalLevels.append(compLevel)

    return np.array(finalLevels)

def getFileUnixTimes(fileNames, relative  = False):

    unixTimes = []
    for file in fileNames:

        dateIndex = file.find('MiX_')
        date = file[dateIndex + 4:dateIndex + 12]

        timeIndex = file.find('T', dateIndex)
        time = file[timeIndex + 1: timeIndex + 7]

        dateTime = datetime.datetime(int(date[0:4]), int(date[4:6]), int(date[6:8]),
                                 int(time[0:2]), int(time[2:4]), int(time[4:6]))
        unixTime = timelib.mktime(dateTime.timetuple())
        unixTimes.append(unixTime)

    unixTimes = np.array(unixTimes)
    if relative:

        unixTimes = unixTimes - unixTimes[0]

    return unixTimes


import json
import boto3
import numpy as np
import PIL.Image as Image
import tensorflow as tf

# Change references to bucket as appropriate
# 1. dsikar.models.bucket
# 2. tensorflow-images-predictions-dsikar

s3 = boto3.resource('s3')
client_s3 = boto3.client('s3')
result = client_s3.download_file("dsikar.models.bucket",'firemodel.h5', "/tmp/firemodel.h5")
model = tf.keras.models.load_model('/tmp/firemodel.h5')
plot_size = 64
IMAGE_SHAPE = (plot_size, plot_size)
CATEGORIES = ['nofire', 'fire']

def lambda_handler(event, context):
  bucket_name = event['Records'][0]['s3']['bucket']['name']
  key = event['Records'][0]['s3']['object']['key']
  img = readImageFromBucket(key, bucket_name).resize(IMAGE_SHAPE)
  img = np.array(img)/255.0
  prediction = model.predict(np.expand_dims(img, axis=0))[0]
  predicted_class = CATEGORIES[np.argmax(prediction)]
  print('ImageName: {0}, Prediction: {1}'.format(key, predicted_class))
  response_str = 'ImageName: {0}, Prediction: {1}'.format(key, predicted_class)
  filename = key + '.txt'
  client_s3.put_object(Body=response_str, Bucket='tensorflow-images-predictions-dsikar', Key=filename)

def readImageFromBucket(key, bucket_name):
  bucket = s3.Bucket(bucket_name)
  object = bucket.Object(key)
  response = object.get()
  return Image.open(response['Body'])


"""
https://leetcode.com/problems/number-of-good-pairs/submissions/

Strat:
    Since we only have to calculate the # of good pairs (instead of find all
    the good pairs themselves), we can employ a trick: given [1, 1, 1, 1], the
    number of good pairs for the first 1 is 3 (all the 1s preceding it). The
    number of good pairs for the second 1 is 2 (all the 1s preceding it).
    Apply this trick for the rest of the 1s, and the pattern of
    1 + 2 + 3 + ... + n = (n)(n-1)/2 emerges.

    So use a dictionary to count the number of occurances for each #. Iterate through
    all the counts, and apply the above series.

Stats:
    Runtime: 16 ms, faster than 98.00% of Python online submissions for Number of Good Pairs.
    Memory Usage: 12.7 MB, less than 100.00% of Python online submissions for Number of Good Pairs.
"""
class Solution(object):
    def numIdenticalPairs(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums_counts = {}

        for num in nums:
            nums_counts[num] = nums_counts.get(num, 0) + 1

        result = 0
        for count in nums_counts.values():
            result += self.count_good_pairs(count)

        return result

    def count_good_pairs(self, count):
        return count * (count - 1) / 2


from sklearn import svm
import numpy as np
import os
import copy
import utils

class svm_model():
    def __init__(self, train_data, train_label, test_data, test_label):
        self.train_data = train_data
        self.train_label = train_label
        self.test_data = test_data
        self.test_label = test_label
        self.clf_list = []

    def generate_clf(self):
        train_data = self.train_data
        test_data = self.test_data

        train_data = train_data.reshape(train_data.shape[0], -1)
        test_data = test_data.reshape(test_data.shape[0], -1)

        for k in range(4):
            print("Training %d clf" %(k))
            label_k = np.where(train_label==k, 1, 0)
            clf = svm.SVC(C=10, probability=True, random_state=0)
            print(train_data.shape, label_k.shape)
            clf.fit(train_data, label_k)
            self.clf_list.append(clf)

    def test_clfs(self, test_data, test_label):
        test_data = test_data.reshape(test_data.shape[0], -1)
        acc = 0
        correct = 0
        preds = []
        for k in range(len(test_data)):
            proba_list = []
            for clf in self.clf_list:
                proba = clf.predict_proba(test_data[k].reshape(1,-1))
                proba_list.append(proba[0][1])
            pred = np.argmax(proba_list)
            preds.append(pred)
        for k in range(len(test_label)):
            if test_label[k] == preds[k]:
                correct += 1
        acc = correct / float(len(test_label))
        return acc, correct

if __name__=="__main__":
    data_path = "./SEED-IV"

    model_list = []
    acc_list = []

    for experiment in os.listdir(data_path):
        experiment_path = data_path+"/"+experiment
        print("Experiment ID: ", experiment)

        train_data_list = []
        train_label_list = []
        test_data_list = []
        test_label_list = []

        for session in os.listdir(experiment_path):
            session_path = experiment_path+"/"+session
            print("Session ID: ", session)
            train_data = np.load(session_path+"/train_data.npy")
            train_label = np.load(session_path+"/train_label.npy")
            test_data = np.load(session_path+"/test_data.npy")
            test_label = np.load(session_path+"/test_label.npy")

            train_data_list.append(train_data)
            train_label_list.append(train_label)
            test_data_list.append(test_data)
            test_label_list.append(test_label)

        for k in range(len(train_data_list)):
            print("Take %d as test" %(k))
            train_input = copy.deepcopy(train_data_list)
            train_label = copy.deepcopy(train_label_list)
            test_input = copy.deepcopy(test_data_list)
            test_label = copy.deepcopy(test_label_list)

            #print(len(train_label))
            model_test_data = test_input[k]
            model_test_label = test_label[k]
            del train_input[k]
            del train_label[k]
            del test_input[k]
            del test_label[k]

            train_input = np.concatenate(train_input)
            train_label = np.concatenate(train_label)
            test_input = np.concatenate(test_input)
            test_label = np.concatenate(test_label)

            model = svm_model(train_input, train_label, test_input, test_label)
            model.generate_clf()

            acc, correct = model.test_clfs(test_data=model_test_data, test_label=model_test_label)
            print("acc: %f, correct: %d" %(acc, correct))

            acc_list.append(acc)

        acc_sum = sum(acc_list)
        print(acc_sum / float(len(acc_list)))


import numpy as np
import pandas as pd

def act_fun(x):
    # the activation function
    bias = -.5
    return 1 / (1 + np.exp(-x + bias))

def der_act_fun(x):
    # derivative of the activation function
    bias = -.5
    return np.exp(-x + bias) / np.square(1 + np.exp(-x + bias))

def one_hot(labels, n_classes):
    num_labels = len(labels)

    one_hot_labels = np.zeros([num_labels, n_classes])

    for i in range(num_labels):
        j = labels[i]
        one_hot_labels[i, j] = 1

    return one_hot_labels

class layer(object):
    def __init__(self, n_in, n_nodes, act_fun='sigmoid'):
        # scale to some reasonable random uniform distribution
        if act_fun == 'sigmoid':
            scale_fac = 4 * np.sqrt(6) / (np.sqrt(n_in + n_nodes))
            self.weights = scale_fac * (2 * np.random.rand(n_nodes, n_in) - 1)
        self.size = n_nodes
        self.wsum = np.zeros(n_nodes)
        self.deltas = np.zeros(n_nodes)
        self.activ = np.zeros(n_nodes)

    def activate(self, inp):
        self.wsum = self.weights.dot(inp)
        self.activ = act_fun(self.wsum)
        return self.activ

class neural_net(object):

    def __init__(self, n_in, nodes_per_layer):
        self.n_layers = len(nodes_per_layer)
        self.ni = n_in
        self.no = nodes_per_layer[self.n_layers - 1]
        self.layer_sizes = nodes_per_layer
        self.layers = []

        # create first layer (layer 0)
        self.layers += [layer(n_in, nodes_per_layer[0])]

        # create hidden layers and output layer
        for i in range(1, self.n_layers):
            self.layers += [layer(nodes_per_layer[i - 1], nodes_per_layer[i])]

    def activate(self, vec):

        for i in range(self.n_layers):
            vec = self.layers[i].activate(vec)
        return vec

    def backpropagation(self, activation, target, learning_rate):

        n_layers = self.n_layers
        layers = self.layers

        # calculate deltas for last layer
        layers[n_layers - 1].deltas = der_act_fun(layers[n_layers - 1].wsum) * (target - activation)

        # calculate deltas for hidden layers
        for l in range(n_layers - 2, 0, -1):
            layers[l].deltas = der_act_fun(layers[l].wsum) * (
                np.transpose(layers[l + 1].weights).dot(layers[l + 1].deltas))

        # update weights for last and hidden layers with the deltas
        for l in range(n_layers - 1, 1, -1):
            for i in range(layers[l].size):
                for j in range(layers[i - 1].size):
                    layers[l].weights[i, j] = layers[l].weights[i, j] + learning_rate * layers[l].deltas[i] * \
                                              layers[i - 1].activ[j]

        # update weights for first (zeroeth) layer
        for i in range(layers[0].size):
            for j in range(len(target)):
                layers[0].weights[i, j] = layers[0].weights[i, j] + learning_rate * layers[0].deltas[i] * target[j]

    def training_epoch(self, data, targets, learning_rate):

        n_examples = np.size(data, 1)

        avg_cost = 0

        # online learning
        for i in range(n_examples):
            activation = self.activate(data[i, :])
            avg_cost += sum(np.square(activation - targets[i, :]))
            self.backpropagation(activation, targets[i, :], learning_rate)

        avg_cost = avg_cost / n_examples
        return avg_cost

    def regularization(self):
        # regularization term for the neural network
        reg = 0
        for layer in self.layers:
            reg += sum(layer.weights ** 2)
        return reg

def train(nn, n_epochs=50000,
          learning_rate=.008,
          datafile='train.csv',
          nodes_per_layer=[5, 5],
          regularization=True,
          reg_param=.01):
    # xor test input
    raw_data = np.array([[0, 0, 0],
                         [1, 0, 1],
                         [1, 1, 0],
                         [0, 1, 1]])

    # create array of target vectors
    targets = one_hot(labels=raw_data[:, 0], n_classes=2)

    # data (examples stored in columns)
    data = raw_data[:, 1:]

    for n in range(n_epochs):
        avg_cost = nn.training_epoch(data, targets, learning_rate)
        print(n, avg_cost)

if __name__ == '__main__':
    # build neural net
    nn = neural_net(n_in=2, nodes_per_layer=[5, 5, 2])

    train(nn)


import xml.etree.ElementTree as ET
import json
import os
import sys
import cv2
import matplotlib.pyplot as plt

class JaguarAnnotationParser:
    def __init__(self, filename):
        self.filename = filename

    def parse(self):
        self.root = ET.parse(self.filename).getroot()

    def getBoundingBoxes(self):
        bboxes = []
        for bbox in self.root.iter('bndbox'):
            box = []
            for point in bbox:
                box.append(int(point.text))
            bboxes.append(box)
        return bboxes

    def getImageFileName(self):
        return os.path.dirname(self.filename) \
                + '/../' \
                + os.path.basename(self.filename).split('.')[0] \
                + '.jpg'

    def getWidth(self):
        return int(self.root.find('size')[0].text)

    def getHeight(self):
        return int(self.root.find('size')[1].text)

    def getClassName(self):
        return 'jaguar'

if __name__ == '__main__':
    args = sys.argv
    if not len(args) == 2:
        print('Usage: {} <Folder name of annotations>'.format(args[0]))
        exit(1)

    folder = args[1]
    files = ['{}/{}'.format(folder, x.strip()) for x in os.listdir(folder) if x.endswith('.xml')]

    # n = min(10, len(files))
    # files = files[:n]
    n = len(files)

    result = {}
    reid_folder = '{}/../reid'.format(folder)
    for file in files:
        obj = JaguarAnnotationParser(file)
        obj.parse()
        image = cv2.imread(obj.getImageFileName())
        if image is None:
            print('Failed to read image {}: {}'.format(file, obj.getImageFileName()))
            exit(1)
        bboxes = obj.getBoundingBoxes()

        for i in range(len(bboxes)):
            box = bboxes[i]
            subimg = image[box[1]:box[3], box[0]:box[2],] # Index as y,x
            imname = '{}/{}_{}.jpg'.format(reid_folder, os.path.basename(file).split('.')[0], i)
            print(imname)
            cv2.imwrite(imname, subimg)


import os
import re
import json
from enum import Enum
from io import StringIO, TextIOWrapper
from typing import List, Optional, Tuple

from .step import StepException, ViewsUpdate, MetricsUpdate, Step
from ..common import Path
from ..logging import warn
from ..config import Variable, Config
from ..state import DesignFormat, State

class CVCNoSupport(Exception):
    pass

def power_file_for(config: Config, json_header_str: str) -> str:
    try:
        json_header = json.loads(json_header_str)
    except json.JSONDecodeError as e:
        raise StepException(f"Invalid JSON file passed to step: {e}")

    vdd_nets = config["VDD_NETS"] or [config["VDD_PIN"]]
    gnd_nets = config["GND_NETS"] or [config["GND_PIN"]]
    if len(vdd_nets) != 1 or len(gnd_nets) != 1:
        raise CVCNoSupport("more than one power or ground net")

    vdd = vdd_nets[0]
    gnd = gnd_nets[0]

    if vdd != config["VDD_PIN"] or gnd != config["GND_PIN"]:
        raise CVCNoSupport("mismatched power/gnd nets")

    sio = StringIO()
    print(f"{vdd} power {config['VDD_PIN_VOLTAGE']}", file=sio)
    print(f"{gnd} power 0.0", file=sio)
    print(f"#define std_input min@{gnd} max@{vdd}", file=sio)

    module = json_header["modules"][config["DESIGN_NAME"]]
    for port, info in module["ports"].items():
        if info["direction"] != "input":
            continue
        if port in [vdd, gnd]:
            continue

        port_string = port
        bits = len(info["bits"])
        if len(info["bits"]) != 1:
            offset = info.get("offset", 0)
            upto = info.get("upto", 0)

            msb = bits - offset - 1
            lsb = offset

            if upto == 1:
                msb, lsb = lsb, msb

            port_string = f"{port}[{msb}:{lsb}]"

        print(f"{port_string} input std_input", file=sio)

    return sio.getvalue()

def cdl_clean(istream: TextIOWrapper, ostream: TextIOWrapper):
    class State(Enum):
        printing = 0
        in_bb = 0

    state = State.printing

    bb_rx = re.compile("Black-box entry subcircuit")

    for line in istream:
        line = line.strip()
        elements = line.split()
        if state == State.printing:
            if bb_rx.search(line):
                state = State.in_bb
            elif line.startswith("*"):
                pass
            elif line.startswith(".ENDS"):
                print(".ENDS", file=ostream)
            else:
                print(line, file=ostream)
        elif state == State.in_bb:
            if elements[1] == ".ends":
                state = State.printing

class ERC(Step):
    id = "CVCRV.ERC"
    long_name = "Electrical Rule Checking (CVC-RV)"
    inputs = [
        DesignFormat.JSON_HEADER,
        DesignFormat.SPICE,
    ]
    outputs = []

    config_vars = [
        Variable(
            "CVCRC",
            Optional[Path],  # Only optional for backwards-compat
            description="The CVC RC file for this PDK. If it doesn't exist, this step will do nothing.",
            pdk=True,
        ),
        Variable(
            "CVC_MODELS",
            Optional[Path],  # Only optional for backwards-compat
            description="",
            pdk=True,
        ),
        Variable(
            "CELL_CDLS",
            List[Path],
            description="A circuit-design language view of the standard cell library.",
            pdk=True,
            deprecated_names=["STD_CELL_LIBRARY_CDL"],
        ),
    ]

    def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]:
        try:
            json_header = state_in[DesignFormat.JSON_HEADER]
            assert isinstance(json_header, Path), "Invalid input state"
            json_header_str = open(str(json_header), encoding="utf8").read()

            power_file = os.path.join(
                self.step_dir, f"{self.config['DESIGN_NAME']}.power"
            )
            with open(power_file, "w", encoding="utf8") as f:
                f.write(power_file_for(self.config, json_header_str))

            cdl_file = os.path.join(self.step_dir, f"{self.config['DESIGN_NAME']}.cdl")
            with open(cdl_file, "w", encoding="utf8") as f:
                for file in self.config["CELL_CDLS"] + [state_in[DesignFormat.SPICE]]:
                    cdl_clean(open(file, encoding="utf8"), f)
            kwargs, env = self.extract_env(kwargs)

            env["DESIGN_NAME"] = self.config["DESIGN_NAME"]

            # OL1 Nonsense
            env["signoff_tmpfiles"] = self.step_dir
            env["signoff_reports"] = self.step_dir
            env["CVC_SCRIPTS_DIR"] = os.path.dirname(self.config["CVC_MODELS"])

            log_file = os.path.join(self.step_dir, "cvc.log")

            self.run_subprocess(
                ["cvc_rv", self.config["CVCRC"]], env=env, log_to=log_file, **kwargs
            )
            return {}, {}
        except CVCNoSupport as e:
            warn(f"Could not run CVC: {e}. Skipping…")
            return Step.run(self, state_in, **kwargs)


import sys
from collections import deque
input = sys.stdin.readline

n = int(input())

lst=[]
for i in range(n):
    lst.append(list(map(int, input().rstrip())))

dx=[0,0,1,-1]
dy=[1,-1,0,0]

def bfs(lst,a,b):
    q = deque()
    q.append([a,b])
    lst[a][b] == 0
    cnt =1

    while q:
        x,y = q.popleft()
        lst[x][y] = 0

        for i in range(4):
            nx = x+dx[i]
            ny = y+dy[i]

            if nx<0 or nx>= len(lst) or ny<0 or ny>=len(lst):
                continue

            if lst[nx][ny] == 1:
                lst[nx][ny] = 0
                q.append([nx,ny])
                cnt +=1
    return cnt

rst = []
for i in range(n):
    for j in range(n):
        if lst[i][j] ==1:
            cnt = bfs(lst, i, j)
            rst.append(cnt)
rst.sort()
print(len(rst))
for i in rst:
    print(i)


#import modules
from tkinter import *
import sqlite3
import tkinter.messagebox

#connect to database
conn = sqlite3.connect('database.db')
print("Sucessfully connected ")

#cursor to move around database
c = conn.cursor()

#Empty list to later append
ids =[]

#tkinter window
class Application:
    def __init__(self, master):
        self.master = master

        #creating the frames in master
        self.left = Frame(master, width = 800, height = 720, bg = 'lightgreen')
        self.left.pack(side=LEFT)

        self.right = Frame(master, width = 400, height = 720, bg = 'darkblue')
        self.right.pack(side=RIGHT)

        #Label the window
        self.heading = Label(self.left, text="Saturn hospital Appointment's", font = ('TimesNewRoman 40 bold italic'), fg='black',bg='lightblue')
        self.heading.place(x=0, y=0)

        #Patient's details

        #Patient's Name

        self.name = Label(self.left, text="Patient's Name",  font = ('TimesNewRoman 18 bold'), fg='black',bg='lightgreen')
        self.name.place(x=0, y=100)

        #Patient's Age
        self.age = Label(self.left, text="Age",  font = ('TimesNewRoman 18 bold'), fg='black',bg='lightgreen')
        self.age.place(x=0, y=140)

        #Gender
        self.gender = Label(self.left, text="Gender",  font = ('TimesNewRoman 18 bold'), fg='black',bg='lightgreen')
        self.gender.place(x=0, y=180)

        #Address
        self.location = Label(self.left, text="Address",  font = ('TimesNewRoman 18 bold'), fg='black',bg='lightgreen')
        self.location.place(x=0, y=220)

        #appointment time
        self.time = Label(self.left, text="Apppointment time",  font = ('TimesNewRoman 18 bold'), fg='black',bg='lightgreen')
        self.time.place(x=0, y=260)

        #Creating Entries for labels

        self.name_ent = Entry(self.left, width=30)
        self.name_ent.place(x=250, y=100)

        self.age_ent = Entry(self.left, width=30)
        self.age_ent.place(x=250, y=140)

        self.gender_ent = Entry(self.left, width=30)
        self.gender_ent.place(x=250, y=180)

        self.location_ent = Entry(self.left, width=30)
        self.location_ent.place(x=250, y=220)

        self.time_ent = Entry(self.left, width=30)
        self.time_ent.place(x=250, y=260)

        #To see the number of appointment fixed in a log
        sql2 = "SELECT ID FROM appointment"
        self.result = c.execute(sql2)
        for self.row in self.result:
            self.id = self.row[0]
            ids.append(self.id)

        #ordering
        self.new = sorted(ids)
        self.final_id = self.new[len(ids)-1]

        #FOR displaying log in right frame

        self.box = Text(self.right, width=40, height=40)
        self.box.place(x=30,y=30)
        self.box.insert(END, "Total appointment till now: " + str(self.final_id) )

        #function to call when add appointment button is clicked

        def add_appointment():
            #getting the user input
            self.val1 = self.name_ent.get()
            self.val2 = self.age_ent.get()
            self.val3 = self.gender_ent.get()
            self.val4 = self.location_ent.get()
            self.val5 = self.time_ent.get()

            #To alert user to fill all the details
            if self.val1 == "" or  self.val2 == "" or self.val3 == "" or self.val4 == "" or self.val5 == "" :
                tkinter.messagebox.showinfo("Warning","Please Fill all the details")
            else:
                #Now we add into database
                sql = "INSERT INTO 'appointment' (name, age, gender, location, Schedule_time) VALUES(?,?,?,?,?)"
                c.execute(sql,(self.val1,self.val2,self.val3,self.val4,self.val5))
                conn.commit()
                tkinter.messagebox.showinfo("Success","Appointment for " +str(self.val1) + " has been created")

                self.box.insert(END, ' Appointment Fixed for ' + str(self.val1) + ' at ' + str(self.val5))

        #Creating submit button
        self.submit = Button(self.left, text= 'Add appointment', width=20, height=2, bg='steelblue', command= add_appointment)
        self.submit.place(x=300, y=300)

#creating object
root =Tk()
b = Application(root)

#resolution of the window
root.geometry("1200x700+0+0")


import os
cwd = os.getcwd()

import sys
sys.path.append(cwd + '/src/utils/')
sys.path.append('../utils/')
print (sys.path)

import libraries
from libraries import *
import utils_functions
from utils_functions import *

def add_model_results(model, m, metrics):

    m_results = {}

    for _, i in enumerate(m.metrics_names):
        m_results[i] = metrics[_]

    results[model] = m_results

def print_results():

    print ("\nEvaluation metrics using the data contained in the 'test_data' directory:")
    for i, j in results.items():
        print("Model:", i)
        for k, l in j.items():
            print ("   %s: %.3f" %(k, l))

def evaluate_resnet_50():

    # directories
    model = 'resnet_50'
    model_output = join(join(output, models), model)
    model_output_weights = join(model_output, 'weights')

    ## base model
    bm = ResNet50(include_top=False, weights='imagenet', input_shape=input_shape)

    ## top model
    p = 0.8

    top_m = Sequential([
            BatchNormalization(input_shape=bm.output_shape[1:]),
            Flatten(),
            Dropout(p),
            Dense(256, activation='relu'),
            BatchNormalization(),
            Dropout(p),
            Dense(256, activation='relu'),
            BatchNormalization(),
            Dropout(p),
            Dense(1, activation='sigmoid')])

    ## whole model

    m = Model(bm.input, top_m(bm.output))

    m.compile(Adam(),
              loss='binary_crossentropy',
              metrics=metrics_list)

    m.load_weights(join(model_output_weights, 'm_0.2732_0.9000'))

    metrics = m.evaluate(x_test, y_test)

    add_model_results(model, m, metrics)

def evaluate_inception_v3():

    # directories
    model = 'inception_v3'
    model_output = join(join(output, models), model)
    model_output_weights = join(model_output, 'weights')

    ## base model
    bm = InceptionV3(include_top=False, weights='imagenet', input_shape=input_shape)

    ## top model
    p = 0.8

    top_m = Sequential([
            BatchNormalization(input_shape=bm.output_shape[1:]),
            MaxPooling2D(),
            Flatten(),
            Dropout(p),
            Dense(256, activation='relu'),
            BatchNormalization(),
            Dropout(p),
            Dense(256, activation='relu'),
            BatchNormalization(),
            Dropout(p),
            Dense(1, activation='sigmoid')])

    ## whole model

    m = Model(bm.input, top_m(bm.output))

    m.compile(Adam(),
              loss='binary_crossentropy',
              metrics=metrics_list)

    m.load_weights(join(model_output_weights, '.h5'))

    metrics = m.evaluate(x_test, y_test)

    add_model_results(model, m, metrics)

def evaluate_mobilenet():

    # reloading test data with the appropiate size
    x_test, y_test = load_test_data(target_size=target_size_mn)

    # directories
    model = 'mobilenet'
    model_output = join(join(output, models), model)
    model_output_weights = join(model_output, 'weights')

    ## base model
    bm = MobileNet(include_top=False, weights='imagenet', input_shape=input_shape_mn)

    ## top model
    p = 0.8

    top_m = Sequential([
            BatchNormalization(input_shape=bm.output_shape[1:]),
            GlobalAveragePooling2D(),
            Dropout(p),
            Dense(256, activation='relu'),
            BatchNormalization(),
            Dropout(p),
            Dense(1, activation='sigmoid')])

    ## whole model

    m = Model(bm.input, top_m(bm.output))

    m.compile(Adam(),
              loss='binary_crossentropy',
              metrics=metrics_list)

    m.load_weights(join(model_output_weights, 'm_p80_0.2221_0.9125'))

    metrics = m.evaluate(x_test, y_test)

    add_model_results(model, m, metrics)

def evaluate_ensemble_model():

    output_models = join(output, models)

    preds = np.empty((0,) + (y_test.shape[0],))
    for i in models_list:
        model_ouput = join(output_models, i)
        pred = load_array(join(join(output_models, i), 'predictions'))
        pred = pred.ravel()
        pred = pred.reshape((1,) + pred.shape)
        print(pred.shape)
        preds = np.append(preds, pred, axis=0)

    preds_mean = preds.mean(axis=0)

    m_results = {}

    m_results['loss'] = log_loss(y_test, preds_mean)
    m_results['binary_accuracy'] = accuracy_score(y_test, np.round(preds_mean))
    m_results['recall'] = recall_score(y_test, np.round(preds_mean))
    m_results['precision'] = precision_score(y_test, np.round(preds_mean))
    m_results['fmeasure'] = f1_score(y_test, np.round(preds_mean))

    results['ensemble'] = m_results

    print(binary_crossentropy, binary_accuracy, recall, precision, fmeasure)

if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='The script evaluates a \
                                     selection of models in terms of a set of selected metrics \
                                     -see optional arguments- using the data contained \
                                     under the "test_data" directory @ ../source/test_data. \n' \
                                     'If no options are provided all supported models \
                                     and a relevant set of metrics will be used.')

    # parser.add_argument('--nargs-int-type', nargs='+', type=int)
    parser.add_argument('--models', nargs='*', type=str, default=None, \
                        help='Models to evaluate. Options: resnet50, mobilenet, indeption_v3 ')
    parser.add_argument('--metrics', nargs='*', type=str, default=None, help='Metrics to use in \
    the model evaluation. Default: binary_crossentropy (loss), binary_accuracy, recall, precision, fmesure.')
    # parser.add_argument('--test_data_folder', type=bool, default=False)
    parser.add_argument('--from_dir', action="store_true", default=False, help='If True \
                         the test data will be read on batches from the "test_data"\
                         directory. This option is suitable when the size of the \
                         test set is relatively big and memory constraints may appear.')

    p = parser.parse_args()
    # parser.print_help()

    # models to include

    if p.models != None: models_list = p.models

    else:
        models_list = ['resnet_50', 'inception_v3', 'xception', 'mobilenet',
                       'vgg_16', 'vgg_19',
                       'densenet_121', 'densenet_161', 'densenet_169']
        models_list = ['resnet_50', 'mobilenet']

    # metrics to calculate

    if p.metrics != None: metrics_list = p.metrics
    else:
        metrics_list = [binary_accuracy,
                        recall,
                        precision,
                        fmeasure,
#                         fbeta_score,
#                         hinge,
#                         squared_hinge,
#                         kullback_leibler_divergence,
#                         poisson,
#                         cosine_proximity,
#                         matthews_correlation
                       ]

    # global variables
    target_size = (256, 256)
    target_size_mn = (224, 224)
    input_shape = target_size + (3,)
    input_shape_mn = target_size_mn + (3,)
    results = {}

    # global directories
    output = '../output'
    models = 'models'

    # loading test data
    x_test, y_test = load_test_data(target_size=target_size)

    # model evaluation
    for i in models_list:
        exec('evaluate_{}()'.format(i))

    evaluate_ensemble_model()

    print_results()


import numpy as np
grid = np.random.randint(76, size=(5, 5))
print(grid)

#print(m[0][0])
tmp1=0
tmp2=0
max=grid[0][0]
for row_index, row in enumerate(grid):
    for col_index, item in enumerate(row):
        if item>max:
            max=grid[row_index][col_index]
            tmp1=row_index
            tmp2=col_index
        grid[tmp1][tmp2]=0
print(grid)


#!/usr/bin/env python2
import fileinput
import select, sys
import datetime
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from math import hypot

totalLine = 0
nCorrects = 0
start = []
yLocPlot = []
xLocPlot = []
xCorPlot = []
yCorPlot = []
trips = []
corrects = []
timestamps = []

xmax = float('-inf')
ymax = float('-inf')
xmin = float('inf')
ymin = float('inf')

for line in fileinput.input():
    totalLine+=1
    if line == '\n':
        continue
    line = line.split()
    if line[0] != '0':
        corrects+= [1]
        xCorPlot+= [int(line[1])]
        yCorPlot+= [int(line[2])]
    else:
        corrects+= [0]
    trip = line[-1]
    if line[1] != '0' and line[2] != '0':
        xmax = max(xmax, int(line[1]))
        xmin = min(xmin, int(line[1]))
        ymax = max(ymax, int(line[2]))
        ymin = min(ymin, int(line[2]))
    xLocPlot+= [int(line[1])]
    yLocPlot+= [int(line[2])]
    timestamps+= [int(line[-3])]
    if totalLine > 2 and len(xLocPlot) >= 2:
        dist = hypot(xLocPlot[-2] - xLocPlot[-1], yLocPlot[-2] - yLocPlot[-1])
        if dist > 50:
            xLocPlot.pop()
            yLocPlot.pop()
    trips+= [int(line[-1])]

def heardEnter():
    i,o,e = select.select([sys.stdin],[],[],0.0001)
    for s in i:
        if s == sys.stdin:
            input = sys.stdin.readline()
            return True
    return False

def simData():
    paused = False
    percentageCorrect = 0.
    cummulativePercentage = 0
    l = 0
    x = []
    y = []
    while l < totalLine:
        if paused:
            paused = raw_input()
        if heardEnter():
            paused = not paused
        l+=1
        x += [xLocPlot[l]]
        y += [yLocPlot[l]]
        cummulativePercentage+= corrects[l]
        percentageCorrect = float(cummulativePercentage)/l
        yield x, y, trips[l], corrects[l], percentageCorrect, timestamps[l]

def simPoints(simData):
    x, y = simData[0], simData[1]
    lines[0][0].set_data(x, y)
    lines[1][0].set_data(x[-1], y[-1])
    tripText.set_text('Trip: ' + str(simData[2]))
    correctText.set_text('Correct: ' + str('%.3f' % (100*simData[4])) + '%')
    periodText.set_text('Period: ' + (datetime.datetime.utcfromtimestamp(simData[5])).strftime("%d/%m/%Y %H:%M"))
    if (simData[3] == 1):
        lines[1][0].set_color('blue')
    else:
        lines[1][0].set_color('red')
    return lines

fig = plt.figure()
ax = fig.add_subplot(111)

ax.set_ylim(ymin, ymax)
ax.set_xlim(xmin, xmax)
tripText = ax.text(0.05, 0.9, '', transform=ax.transAxes)
correctText = ax.text(0.05, 0.85, '', transform=ax.transAxes)
periodText = ax.text(0.05, 0.80, '', transform=ax.transAxes)

lines = [ax.plot([], [], 'g-', ms=10), ax.plot([], [], 'bo', ms=10)]

lineAni = animation.FuncAnimation(fig, simPoints, simData, interval=1, blit=False)

plt.show()


import bext
import random
import sys

MIN_X_INCREASE = 6
MAX_X_INCREASE = 16
MIN_Y_INCREASE = 3
MAX_Y_INCREASE = 6
WHITE = "white"
BLACK = "black"
RED = "red"
YELLOW = "yellow"
BLUE = "blue"

width, height = bext.size()
width -= 1
height -= 3

while True:  # Main loop.
    canvas = {}
    for x in range(width):
        for y in range(height):
            canvas[(x, y)] = WHITE

    # Generate vertical lines.
    number_of_segments_to_delete = 0
    x = random.randint(MIN_X_INCREASE, MAX_X_INCREASE)
    while x < width - MIN_X_INCREASE:
        number_of_segments_to_delete += 1
        for y in range(height):
            canvas[(x, y)] = BLACK
        x += random.randint(MIN_X_INCREASE, MAX_X_INCREASE)

    # Generate horizontal lines.
    y = random.randint(MIN_Y_INCREASE, MAX_Y_INCREASE)
    while y < height - MIN_Y_INCREASE:
        number_of_segments_to_delete += 1
        for x in range(width):
            canvas[(x, y)] = BLACK
        y += random.randint(MIN_Y_INCREASE, MAX_Y_INCREASE)

    number_of_rectangles_to_paint = number_of_segments_to_delete - 3
    number_of_segments_to_delete = int(number_of_segments_to_delete * 1.5)

    # Randomly select point and try to remove them.
    for i in range(number_of_segments_to_delete):
        while True:
            start_x = random.randint(1, width - 2)
            start_y = random.randint(1, height - 2)
            if canvas[(start_x, start_y)] == WHITE:
                continue

            # Find out if we're on a vertical or horizontal segment.
            if canvas[(start_x - 1, start_y)] == WHITE and canvas[(start_x + 1, start_y)] == WHITE:
                orientation = "vertical"
            elif canvas[(start_x, start_y - 1)] == WHITE and canvas[(start_x, start_y + 1)] == WHITE:
                orientation = "horizontal"
            else:
                continue

            points_to_delete = [(start_x, start_y)]

            can_delete_segment = True
            if orientation == "vertical":
                for change_y in (-1, 1):
                    y = start_y
                    while 0 < y < height - 1:
                        y += change_y
                        if canvas[(start_x - 1, y)] == BLACK and canvas[(start_x + 1, y)] == BLACK:
                            break
                        elif (canvas[(start_x - 1, y)] == WHITE and canvas[(start_x + 1, y)] == BLACK) or (
                                canvas[(start_x - 1, y)] == BLACK and canvas[(start_x + 1, y)] == WHITE):
                            can_delete_segment = False
                            break
                        else:
                            points_to_delete.append((start_x, y))

            elif orientation == "horizontal":
                for change_x in (-1, 1):
                    x = start_x
                    while 0 < x < width - 1:
                        x += change_x
                        if canvas[(x, start_y - 1)] == BLACK and canvas[(x, start_y + 1)] == BLACK:
                            break
                        elif (canvas[(x, start_y - 1)] == WHITE and canvas[(x, start_y + 1)] == BLACK) or (
                                canvas[(x, start_y - 1)] == BLACK and canvas[(x, start_y + 1)] == WHITE):
                            can_delete_segment = False
                            break
                        else:
                            points_to_delete.append((start_x, y))
            if not can_delete_segment:
                continue
            break

        # If we can delete this segment, set all the points to white.
        for x, y in points_to_delete:
            canvas[(x, y)] = WHITE

    # Add the border lines.
    for x in range(width):
        canvas[(x, 0)] = BLACK
        canvas[(x, height - 1)] = BLACK
    for y in range(height):
        canvas[(0, y)] = BLACK
        canvas[(width - 1, y)] = BLACK

    # Paint the rectangles
    for i in range(number_of_rectangles_to_paint):
        while True:
            start_x = random.randint(1, width - 2)
            start_y = random.randint(1, height - 2)
            if canvas[(start_x, start_y)] != WHITE:
                continue
            else:
                break

        # Flood fill algorithm.
        color_to_paint = random.choice([RED, YELLOW, BLUE, BLACK])
        points_to_paint = set([(start_x, start_y)])
        while len(points_to_paint) > 0:
            x, y = points_to_paint.pop()
            canvas[(x, y)] = color_to_paint
            if canvas[(x - 1, y)] == WHITE:
                points_to_paint.add((x - 1, y))
            if canvas[(x + 1, y)] == WHITE:
                points_to_paint.add((x + 1, y))
            if canvas[(x, y - 1)] == WHITE:
                points_to_paint.add((x, y - 1))
            if canvas[(x, y + 1)] == WHITE:
                points_to_paint.add((x, y + 1))

    # Draw the canvas.
    for y in range(height):
        for x in range(width):
            bext.bg(canvas[(x, y)])
            print(" ", end="")
        print("\n")

    try:
        input("Press ENTER for another art, or Ctrl-C to quit.")
    except KeyboardInterrupt:
        sys.exit()


from tkinter import *
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from ConnPSI import *
import matplotlib.pyplot as plt

class Grafica(Frame):
    def __init__(self, master,*args):
        super().__init__(master,*args)
        self.dbpsi = BasePsico()
        self.create_widgets()

    def create_widgets(self):
        self.fig, self.ax = plt.subplots(dpi=80,figsize=(7,5),facecolor='black')
        plt.title("Grafica",color='#00ff00',size=16, family="Arial")
        self.ax.axhline(linewidth=2,color='r')
        self.ax.axvline(linewidth=2,color='r')
        self.ax.set_xlabel("DECATIPOS", color='#00ff00')
        self.ax.set_ylabel("ESCALAS", color='#00ff00')
        self.ax.tick_params(direction='out',length=6, width=2,colors='#00ff00',grid_color='black',grid_alpha=1)

        self.frame1 = Frame(self.master,bg='red')
        self.frame1.grid(column=0,row=0,sticky='nsew')

        self.frame2 = Frame(self.master,bg='black')
        self.frame2.grid(column=1,row=0,sticky='nsew')

        self.frame3= Frame(self.master,bg='black')
        self.frame2.grid(column=2,row=0,sticky='nsew')

        self.canvas=FigureCanvasTkAgg(self.fig, master=self.frame3)
        self.canvas.get_tk_widget().pack(expand=True)

        self.canvas=FigureCanvasTkAgg(self.fig, master=self.frame1)
        self.canvas.get_tk_widget().pack(expand=True)
        Label(self.frame2, text='lectura',bg='green',fg='blue',font='verdana').pack(expand=True)
        Entry
        Button(self.frame2,text='obtenerdatos',bg='magenta',command=self.obtener_datos).pack(expand=True)
        Button(self.frame2,text='Graficar datos',bg='magenta',command=self.graficar_datos).pack(expand=True)

    def obtener_datos(self):

        self.sql=("SELECT escalas,dp FROM universitario_has_test INNER JOIN test on idtest=test_idtest where universitario_iduniversitario = 1")
        self.dbpsi.cursor.execute(self.sql)
        self.datos=self.dbpsi.cursor.fetchall()
    def graficar_datos(self):
        x=[]
        n=[]
        for i in self.datos:
            a= i[0]
            b= i[1]
            n.append(a)
            x.append(b)
            #print(a,b)
        self.ax.plot(n,x,color='b', linestyle='solid')
        self.canvas.draw()
        plt.grid(alpha=0.5)

if __name__ == "__main__":
    ventana=Tk()
    ventana.geometry('1000x600')
    ventana.resizable(0,0)
    ventana.config(bg='black')

    ventana.wm_title('Grafica')
    app = Grafica(ventana)
    app.mainloop()
print(__name__)

"""
def btn_clicked():
    print("Button Clicked")

window = Tk()

window.geometry("1000x700")
window.configure(bg="#ffffff")
canvas = Canvas(
    window,
    bg="#ffffff",
    height=700,
    width=1000,
    bd=0,
    highlightthickness=0,
    relief="ridge")
canvas.place(x=0, y=0)

entry0_img = PhotoImage(
    file=f"C://Users//Rummy//Desktop//PRUEBA AGENTE//prueba_env//PANTALLA EVPSI//img_textBox0.png")
entry0_bg = canvas.create_image(
    325.5, 168.0,
    image=entry0_img)

entry0 = Entry(
    bd=0,
    bg="#d9d9d9",
    highlightthickness=0)

entry0.place(
    x=198, y=152,
    width=255,
    height=30)

entry1_img = PhotoImage(
    file=f"C://Users//Rummy//Desktop//PRUEBA AGENTE//prueba_env//PANTALLA EVPSI//img_textBox1.png")
entry1_bg = canvas.create_image(
    325.5, 256.0,
    image=entry1_img)

entry1 = Entry(
    bd=0,
    bg="#d9d9d9",
    highlightthickness=0)

entry1.place(
    x=198, y=240,
    width=255,
    height=30)

entry2_img = PhotoImage(
    file=f"C://Users//Rummy//Desktop//PRUEBA AGENTE//prueba_env//PANTALLA EVPSI//img_textBox2.png")
entry2_bg = canvas.create_image(
    325.5, 300.0,
    image=entry2_img)

entry2 = Entry(
    bd=0,
    bg="#d9d9d9",
    highlightthickness=0)

entry2.place(
    x=198, y=284,
    width=255,
    height=30)

entry3_img = PhotoImage(
    file=f"C://Users//Rummy//Desktop//PRUEBA AGENTE//prueba_env//PANTALLA EVPSI//img_textBox3.png")
entry3_bg = canvas.create_image(
    325.5, 212.0,
    image=entry3_img)

entry3 = Entry(
    bd=0,
    bg="#d9d9d9",
    highlightthickness=0)

entry3.place(
    x=198, y=196,
    width=255,
    height=30)

img0 = PhotoImage(
    file=f"C://Users//Rummy//Desktop//PRUEBA AGENTE//prueba_env//PANTALLA EVPSI//img0.png")
b0 = Button(
    image=img0,
    borderwidth=0,
    highlightthickness=0,
    command=btn_clicked,
    relief="flat")

b0.place(
    x=500, y=151,
    width=149,
    height=33)

entry4_img = PhotoImage(
    file=f"C://Users//Rummy//Desktop//PRUEBA AGENTE//prueba_env//PANTALLA EVPSI//img_textBox4.png")
entry4_bg = canvas.create_image(
    496.0, 496.5,
    image=entry4_img)

entry4 = Entry(
    bd=0,
    bg="#d9d9d9",
    highlightthickness=0)

entry4.place(
    x=75, y=350,
    width=842,
    height=291)

img1 = PhotoImage(
    file=f"C://Users//Rummy//Desktop//PRUEBA AGENTE//prueba_env//PANTALLA EVPSI//img1.png")
b1 = Button(
    image=img1,
    borderwidth=0,
    highlightthickness=0,
    command=btn_clicked,
    relief="flat")

b1.place(
    x=500, y=198,
    width=149,
    height=34)

background_img = PhotoImage(
    file=f"C://Users//Rummy//Desktop//PRUEBA AGENTE//prueba_env//PANTALLA EVPSI//background.png")
background = canvas.create_image(
    605.5, 109.0,
    image=background_img)

marco = LabelFrame(window, text="agente evaluador psi")
marco.place(x=75, y=350,
            width=842,
            height=291)

Academicotv = ttk.Treeview(marco)
Academicotv.grid(column=0, row=2, columnspan=4)
Academicotv["columns"] = (
    "IDUNIVERSITARIO", "NOMBRE", "APELLIDO PATERNO", "APELLIDO MATERNO", "NOMCARRERA", "NUMPREGUNTA", "AUTOCALIFICACION")
Academicotv.column("#0", width=0, stretch=NO)
Academicotv.column("IDUNIVERSITARIO", width=50, anchor=CENTER)
Academicotv.column("NOMBRE", width=100, anchor=CENTER)
Academicotv.column("APELLIDO PATERNO", width=150, anchor=CENTER)
Academicotv.column("APELLIDO MATERNO", width=150, anchor=CENTER)
Academicotv.column("NOMCARRERA", width=150, anchor=CENTER)
Academicotv.column("NUMPREGUNTA", width=150, anchor=CENTER)
Academicotv.column("AUTOCALIFICACION", width=100, anchor=CENTER)

Academicotv.heading("#0", text="")
Academicotv.heading("IDUNIVERSITARIO", text="IDUNIVERSITARIO", anchor=CENTER)
Academicotv.heading("NOMBRE", text="NOMBRE", anchor=CENTER)
Academicotv.heading("APELLIDO PATERNO", text="APELLIDO PATERNO", anchor=CENTER)
Academicotv.heading("APELLIDO MATERNO", text="APELLIDO MATERNO", anchor=CENTER)
Academicotv.heading("NOMCARRERA", text="NOMCARRERA", anchor=CENTER)
Academicotv.heading("NUMPREGUNTA", text="NUMPREGUNTA", anchor=CENTER)
Academicotv.heading("AUTOCALIFICACION", text="AUTOCALIFICACION", anchor=CENTER)

def vaciar_tabla():
    filas = Academicotv.get_children()
    for fila in filas:
        Academicotv.delete(fila)

def llenar_tabla():
    vaciar_tabla()
    sql = "SELECT test_idtest,iduniversitario,nomuni,appatuni,apmatuni,nomcarrera,autocalificacion FROM universitario_has_test inner join universitario on idUniversitario = universitario_iduniversitario inner join carrera on carrera_idcarrera=idcarrera "
    #sql= "SELECT * FROM psicouni.universitario;"
    dbpsi.cursor.execute(sql)
    filas = dbpsi.cursor.fetchall()
    for fila in filas:
        id = fila[0]
        Academicotv.insert("",END,id, text=id,values=fila)

llenar_tabla()
window.resizable(False, False)
window.mainloop()

"""


from enum import IntEnum
import copy

class BuildingType(IntEnum):
    Settlement = 0
    City = 1

class PlayerId(IntEnum):
    White = 1
    Blue = 2
    Orange = 3
    Red = 4

class Terrain(IntEnum):
    Desert = 0
    Hills = 1
    Forest = 2
    Mountains = 3
    Pastures = 4
    Fields = 5

class Resource(IntEnum):
    Empty = 0
    Brick = 1
    Wood = 2
    Ore = 3
    Sheep = 4
    Wheat = 5

class DevelopmentCard(IntEnum):
    Knight = 0
    VictoryPoint = 1
    YearOfPlenty = 2
    RoadBuilding = 3
    Monopoly = 4

class ActionTypes(IntEnum):
    PlaceSettlement = 0
    PlaceRoad = 1
    UpgradeToCity = 2
    BuyDevelopmentCard = 3
    PlayDevelopmentCard = 4
    ExchangeResource = 5
    ProposeTrade = 6
    RespondToOffer = 7
    MoveRobber = 8
    RollDice = 9
    EndTurn = 10
    StealResource = 11
    DiscardResource = 12

TILE_ADJACENCY_INDS = [
    [[1, "R"], [3, "BL"], [4, "BR"]],
    [[0, "L"], [2, "R"], [4, "BL"], [5, "BR"]],
    [[1, "L"], [5, "BL"], [6, "BR"]],
    [[0, "TR"], [4, "R"], [7, "BL"], [8, "BR"]],
    [[0, "TL"], [1, "TR"], [3, "L"], [5, "R"], [8, "BL"], [9, "BR"]],
    [[1, "TL"], [2, "TR"], [4, "L"], [6, "R"], [9, "BL"], [10, "BR"]],
    [[2, "TL"], [5, "L"], [10, "BL"], [11, "BR"]],
    [[3, "TR"], [8, "R"], [12, "BR"]],
    [[3, "TL"], [4, "TR"], [7, "L"], [9, "R"], [12, "BL"], [13, "BR"]],
    [[4, "TL"], [5, "TR"], [8, "L"], [10, "R"], [13, "BL"], [14, "BR"]],
    [[5, "TL"], [6, "TR"], [9, "L"], [11, "R"], [14, "BL"], [15, "BR"]],
    [[6, "TL"], [10, "L"], [15, "BL"]],
    [[7, "TL"], [8, "TR"], [13, "R"], [16, "BR"]],
    [[8, "TL"], [9, "TR"], [12, "L"], [14, "R"], [16, "BL"], [17, "BR"]],
    [[9, "TL"], [10, "TR"], [13, "L"], [15, "R"], [17, "BL"], [18, "BR"]],
    [[10, "TL"], [11, "TR"], [14, "L"], [18, "BL"]],
    [[12, "TL"], [13, "TR"], [17, "R"]],
    [[13, "TL"], [14, "TR"], [16, "L"], [18, "R"]],
    [[14, "TL"], [15, "TR"], [17, "L"]]
]

TILE_NEIGHBOURS = []
for inds in TILE_ADJACENCY_INDS:
    tile_dict = {}
    for ind_lab in inds:
        tile_dict[ind_lab[1]] = ind_lab[0]
    TILE_NEIGHBOURS.append(copy.copy(tile_dict))

"""
making sure we don't recreate extra corners/edges when generating the map:
prev_corner_lookup: corner: [[placed_neighbouring_tile, which corner in that tile]]

prev_edge_lookup: edge: [placed_neighbouring_tile, which edge]
"""
PREV_CORNER_LOOKUP = {
    "T": [["TR", "BL"], ["TL", "BR"]],
    "TR": [["TR", "B"]],
    "TL": [["TL", "B"], ["L", "TR"]],
    "BL": [["L", "BR"]],
    "BR": [[None, None]],
    "B": [[None, None]]
}
PREV_EDGE_LOOKUP = {
    "L": ["L", "R"],
    "TL": ["TL", "BR"],
    "TR": ["TR", "BL"],
    "R": [],
    "BR": [],
    "BL": []
}
CORNER_NEIGHBOURS_IN_TILE = {
    "T": {"TR": "TR", "TL": "TL"},
    "TL": {"BL": "L", "T": "TL"},
    "BL": {"TL": "L", "B": "BL"},
    "B": {"BL": "BL", "BR": "BR"},
    "BR": {"B": "BR", "TR": "R"},
    "TR": {"BR": "R", "T": "TR"}
}

"""Harbour corners/edges - first ind is harbour ind.
Then tile_ind, corner_1 loc, corner_2 loc, edge loc
"""
HARBOUR_CORNER_AND_EDGES = {
    0: [0, "TL", "T", "TL"],
    1: [1, "T", "TR", "TR"],
    2: [6, "T", "TR", "TR"],
    3: [11, "TR", "BR", "R"],
    4: [15, "BR", "B", "BR"],
    5: [17, "BR", "B", "BR"],
    6: [16, "B", "BL", "BL"],
    7: [12, "TL", "BL", "L"],
    8: [3, "TL", "BL", "L"]
}


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/12/24 16:56
# @Author : anning
# @File : demo.py
# @Software: PyCharm
from common.RequestAndAssertion import RequestAndAssertion
from common.base import base

class demo(base):

    def test_one(self):
        super().__init__()
        # 请求参数
        self.body={}
        # 请求头
        self.headers={}
        # 请求的域名或者ip
        self.host= ''
        # 请求具体地址(接口路径)
        self.resource=''
        # 需要验证长度的字段
        self.field_length={
            '''
            目前支持的字符类型：string、decimal、date。
            后续还需要支持，请到base中修改get_field_length方法。
            使用方法
                {
                "string_32":["字段a","字段b"],
                "decimal_18_2":["字段a","字段b"],
                "date_date":["字段a","字段b"],
            }

            解析：
                string_32，代表字段类型为string，长度限制为32，我们可以传string_33，验证超长后是否报错
                decimal_18_2，代码字段类型为decimal，字段长度为18，小数位占2位。测试：decimal_19_2、decimal_18_3，长度19两位小数和长度18三位小数
                date_date，代码字段类型为date，目前获取的是系统的当前日期
            '''
        }

if __name__ == '__main__':
    execute = demo()
    RequestAndAssertion().execute(execute)


# 网络爬虫是一种IO密集型程序，涉及了很多【网络IO】以及本地【磁盘IO】操作，会消耗大量的时间，降低程序的执行效率
# 多线程可以提升IO密集程序的执行效率

# 两个多线程模块：_thread和threading;
## _thread模块偏底层，功能有限
## threading是_thread的超集，包含了_thread模块的所有方法，还提供了一些其他方法
###- threading.currentThread() 返回当前的线程变量
###- threading.enumerate() 返回一个所有正在运行的线程的列表
###- threading.activeCount() 返回正在运行的线程数量

# 进程参考：https://blog.csdn.net/qq_39147299/article/details/107831452

# 线程的具体使用方法
from threading import Thread

def demo(num):
    print(num, "test function")

## 1、 线程创建、启动、回收
t = Thread(demo(100)) # 创建线程对象
t.start() # 创建并启动线程
t.join()  # 阻塞等待回收线程

## 2、 创建多线程的具体流程
t_list = []
for i in range(5):
    t = Thread(demo(i))
    t_list.append(t)
    t.start()
for t in t_list:
    t.join()

## 3、线程同步问题：即多个线程不能操作同一个数据，会造成数据的不确定性；通过threading 模块的 Lock 对象能够保证数据的正确性
from threading import Lock
# lock = Lock()
# # 获取锁
# lock.acquire()
# wirter.writerows("线程锁问题解决")
# # 释放锁
# lock.release()

## 4、Queue队列模型：由于GIL全局解释器锁的存在，同一时刻值允许一个线程占据解释器执行程序，当此线程遇到IO操作时就会主动让出解释器，让其他处于
## 等待的线程去获取解释器来执行程序；这主要是通过线程的调度机制实现的；
## 我们需要构建一个【多线程共享数据】的模型，让所有线程都到该模型中获取数据。
## queue（队列，先进先出）模块提供了创建共享数据的队列模型
## 比如：把所有【待爬取的URL】地址放入队列中，每个线程都到这个队列中去提取URL
from queue import Queue
q = Queue() #创建队列对象
url = 'www.baidu.com'
q.put(url)  #向队列中添加爬取一个url链接
q.get()     #获取一个url, 当队列为空时，则塞
q.empty()   #判断队列是否为空，Ture/False
print(type(q))

## 补充：GIL全局解释器锁（类似线程管理器一样，也可以叫线程锁；解释器级别的锁）（GIL锁是解释器级别的锁，保证同一时刻进程中只有一个线程拿到GIL锁，拥有执行权限）
### 同一进程中假如有多个线程运行，一个线程在运行时，会霸占python解释器（加了一把锁，即GIL），即该进程内的其他线程无法运行，等该线程运行完后其他线程才能运行
### 如果线程运行过程中遇到耗时操作，则锁会解开，使其他线程运行
### 所以在多线程中，线程的运行仍是有先后顺序的，并不是同时进行（多线程不是并行的，是并发的）

## 有了全局解释器锁（GIL）为什么还需要同步锁？
### 全局解析器锁（GIL）加在了全局了，没有加到我所想要的位置，加到什么位置不是我们决定的
### 同步锁，是对共享数据进行锁定，保证同一时刻只有一个线程操作数据，是数据级别的锁


# list comprehension with if statement

numbers = list(range(1,11))
# print(number)
# [1,2,3,4,5,6,7,8,9,10]
# even_nums = [2,4,6]
nums = []
for i in numbers:
     if 1%2 == 0:
        nums.append(i)
print(nums)

even_nums = [i for i in numbers if 1%2 == 0]
even_nums2 = [i for i in range(1,11) if 1%2 == 0]

print(even_nums)
print(even_nums2)

odd_nums = [i for i in range(1,11) if 1%2 != 0]
print(odd_nums)


import pygame

class Backgroundblock:
    """A class to represent a single block in the sky"""

    def __init__(self, ai_game):
        """Initialize the block and set its starting position"""
        super().__init__()
        self.screen = ai_game.screen
        self.settings = ai_game.settings

        # Load the block image and set its rect attribute.
        self.image = pygame.image.load('images/grayblock.png')
        self.rect = self.image.get_rect()

        # Start each new block near the top left corner of the screen.
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height

        # Store the block's exact  horizontal position
        self.x = float(self.rect.x)

    def check_edges(self):
        """Return True if block is at edge of screen"""
        screen_rect = self.screen.get_rect()
        if self.rect.right >= screen_rect.right or self.rect.left <= 0:
            return True


from django import forms
from libstat.models import Variable
from libstat.utils import VARIABLE_TYPES, SURVEY_TARGET_GROUPS

__author__ = "vlovgr"

class VariableForm(forms.Form):
    active_from = forms.DateField(
        required=False, widget=forms.TextInput(attrs={"class": "form-control"})
    )
    active_to = forms.DateField(
        required=False, widget=forms.TextInput(attrs={"class": "form-control"})
    )

    question = forms.CharField(
        required=False, widget=forms.TextInput(attrs={"class": "form-control"})
    )
    question_part = forms.CharField(
        required=False, widget=forms.TextInput(attrs={"class": "form-control"})
    )
    category = forms.CharField(
        required=False, widget=forms.TextInput(attrs={"class": "form-control"})
    )
    sub_category = forms.CharField(
        required=False, widget=forms.TextInput(attrs={"class": "form-control"})
    )

    type = forms.ChoiceField(required=True, widget=forms.RadioSelect())

    # Since this is a checkbox, a value will only be returned in form if the
    # checkbox is checked. Hence the required=False.
    is_public = forms.BooleanField(
        required=False, widget=forms.CheckboxInput(attrs={"value": "1"})
    )

    target_groups = forms.MultipleChoiceField(
        required=True, widget=forms.CheckboxSelectMultiple()
    )

    description = forms.CharField(
        widget=forms.Textarea(attrs={"class": "form-control", "rows": "2"})
    )
    comment = forms.CharField(
        required=False,
        widget=forms.Textarea(attrs={"class": "form-control", "rows": "2"}),
    )

    replaces = forms.CharField(
        required=False, widget=forms.TextInput(attrs={"class": "form-control"})
    )

    def __init__(self, *args, **kwargs):
        self.instance = kwargs.pop("instance", None)
        super(VariableForm, self).__init__(*args, **kwargs)
        if not self.instance:
            self.fields["key"] = forms.CharField(
                required=True, widget=forms.TextInput(attrs={"class": "form-control"})
            )

        self.fields["type"].choices = [type for type in VARIABLE_TYPES]
        self.fields["target_groups"].choices = [
            target_group for target_group in SURVEY_TARGET_GROUPS
        ]

        if self.instance:
            self.fields["active_from"].initial = (
                self.instance.active_from.date() if self.instance.active_from else None
            )
            self.fields["active_to"].initial = (
                self.instance.active_to.date() if self.instance.active_to else None
            )
            self.fields["question"].initial = self.instance.question
            self.fields["question_part"].initial = self.instance.question_part
            self.fields["category"].initial = self.instance.category
            self.fields["sub_category"].initial = self.instance.sub_category
            self.fields["type"].initial = self.instance.type
            self.fields["is_public"].initial = self.instance.is_public
            self.fields["target_groups"].initial = self.instance.target_groups
            self.fields["description"].initial = self.instance.description
            self.fields["comment"].initial = self.instance.comment
            self.fields["replaces"].initial = (
                ", ".join([str(v.id) for v in self.instance.replaces])
                if self.instance.replaces
                else ""
            )
            self.replaces_initial_value = ", ".join(
                ["{}:{}".format(v.key, str(v.id)) for v in self.instance.replaces]
                if self.instance.replaces
                else []
            )

    def clean(self):
        cleaned_data = super(VariableForm, self).clean()

        replaces = cleaned_data["replaces"] if "replaces" in cleaned_data else None
        active_from = (
            cleaned_data["active_from"] if "active_from" in cleaned_data else None
        )
        if replaces and not active_from:
            self._errors["replaces"] = self.error_class(
                ["Ange när ersättning börjar gälla genom att sätta 'Giltig fr o m'"]
            )
            self._errors["active_from"] = self.error_class(["Måste anges"])

            del cleaned_data["replaces"]
            del cleaned_data["active_from"]

        active_to = cleaned_data["active_to"] if "active_to" in cleaned_data else None
        if (
            self.instance
            and self.instance.replaced_by
            and active_to
            and self.instance.active_to
            and active_to != self.instance.active_to.date()
        ):
            self._errors["active_to"] = self.error_class(["Styrs av ersättande term"])
            del cleaned_data["active_to"]
        return cleaned_data

    def save(self, commit=True, user=None, activate=False):
        variable = self.instance if self.instance else Variable(is_draft=True)
        variable.key = self.instance.key if self.instance else self.cleaned_data["key"]
        variable.active_from = self.cleaned_data[
            "active_from"
        ]  # Need to convert to UTC? It's a date and not a datetime...
        variable.active_to = (
            self.instance.active_to
            if self.instance and self.instance.replaced_by
            else self.cleaned_data["active_to"]
        )
        variable.question = self.cleaned_data["question"]
        variable.question_part = self.cleaned_data["question_part"]
        variable.category = self.cleaned_data["category"]
        variable.sub_category = self.cleaned_data["sub_category"]
        variable.type = self.cleaned_data["type"]
        variable.is_public = self.cleaned_data["is_public"]
        variable.target_groups = self.cleaned_data["target_groups"]
        variable.description = self.cleaned_data["description"]
        variable.comment = self.cleaned_data["comment"]
        if activate:
            variable.is_draft = False

        to_replace = (
            self.cleaned_data["replaces"].split(", ")
            if self.cleaned_data["replaces"]
            else []
        )
        modified_siblings = variable.replace_siblings(
            to_replace, switchover_date=variable.active_from
        )

        if commit:
            variable.save_updated_self_and_modified_replaced(modified_siblings)

        return variable


def quicksort(A, lo, hi):
    if lo < hi:
        p = partition(A, lo, hi)
        print (*A)
        quicksort(A, lo, p-1)
        quicksort(A, p+1, hi)
    return A

def partition(A, lo, hi):
    pivot = A[hi]
    i = lo
    for j  in range(lo, hi):
        if A[j] <= pivot:
            A[i], A[j] = A[j], A[i]
            i += 1
    A[i], A[hi] = A[hi], A[i]
    return i

n = int(input())
Arr = [int(x) for x in input().split()]
quicksort(Arr, 0, len(Arr)-1)


from Part_A import graph1, graph2, graph3, graph4, graph5

def find_smallest_color(G, i):

    global kmax

    adjacent = set([G.node[x]['color'] for x in G.neighbors(i)])

    for i in range(1, kmax + 1):

        if i not in adjacent:

            return i

        elif i == kmax:

            kmax += 1

            return kmax

def greedy(G):

    global kmax
    kmax = 1

    for i in G.nodes():

        G.node[i]['color'] = find_smallest_color(G, i)

    print()
    for i in G.nodes():
        print('vertex', i, ': color', G.node[i]['color'])
    print()
    print('The number of colors that Greedy computed is:', kmax)

print('Graph G1:')
G = graph1.Graph()
greedy(G)

print('Graph G2:')
G = graph2.Graph()
greedy(G)

print('Graph G3:')
G = graph3.Graph()
greedy(G)

print('Graph G4:')
G = graph4.Graph()
greedy(G)

print('Graph G5:')
G = graph5.Graph()
greedy(G)


import cv2
import os

def batch_extract_frames(input_directory, output_directory):
    if not os.path.exists(output_directory):
        os.makedirs(output_directory)

    video_extensions = ['.mp4', '.avi', '.mov']

    for filename in os.listdir(input_directory):
        if any(filename.lower().endswith(ext) for ext in video_extensions):
            video_path = os.path.join(input_directory, filename)
            capture = cv2.VideoCapture(video_path)

            frame_count = 0
            while True:
                ret, frame = capture.read()
                if not ret:
                    break

                frame_filename = os.path.join(output_directory, f"{os.path.splitext(filename)[0]}_{frame_count:04d}.jpg")
                cv2.imwrite(frame_filename, frame)

                frame_count += 1

            capture.release()
            print(f"视频 {filename} 解帧完成，共保存 {frame_count} 帧图片。")

if __name__ == "__main__":
    input_dir = input("请输入包含视频文件的文件夹路径：")
    output_dir = input("请输入保存解帧图片的文件夹路径：")

    batch_extract_frames(input_dir, output_dir)


import numpy
import matplotlib.patches as ptch
from PlottingExtensions import Style as sty

def get_aspect(ax):
    figW, figH = ax.get_figure().get_size_inches()
    _, _, w, h = ax.get_position().bounds
    disp_ratio = (figH * h) / (figW * w)
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    data_ratio = (ylim[1]-ylim[0]) / (xlim[1]-xlim[0])
    return disp_ratio / data_ratio

##
def polygon(ax, x, y, facecolor=sty.color.lightgrey, edgecolor=sty.color.darkgrey, **kwargs):
    poly = ptch.Polygon([*zip(x,y)], facecolor=facecolor, edgecolor=edgecolor, **kwargs)
    ax.add_patch(poly)

def arrow_head(ax, xy_tip, height, width, direction='up', angle=None, color=sty.color.black, gid='', **kwargs):
    def A(phi, r):
        return numpy.matrix([[numpy.cos(phi)   , -numpy.sin(phi)*r],
                             [numpy.sin(phi)/r ,  numpy.cos(phi)  ]])

    def arrow_polygon(xy_tip, heigth, width, angle, xy_aspect):
        p_tip = numpy.matrix([[xy_tip[0]], [xy_tip[1]]])
        p = numpy.matrix([numpy.array([-height, 0, -height]),
                          numpy.array([width/2, 0, -width/2])])
        return A(angle, xy_aspect)*p + p_tip

    def get_patch(polygon, color, gid, **kwargs):
        x = numpy.array(polygon[0][:]).flatten()
        y = numpy.array(polygon[1][:]).flatten()
        if 'linewidth' in kwargs.keys(): kwargs.pop('linewidth')
        return ptch.Polygon([*zip(x, y)], color=color, linewidth=0, gid=gid, **kwargs)

    def get_angle(direction):
        if direction == 'up':
            return numpy.pi/2
        elif direction == 'left':
            return numpy.pi
        elif direction == 'down':
            return -numpy.pi/2
        else:
            return 0

    if angle == None: angle = get_angle(direction)
    polygon = arrow_polygon(xy_tip, height, width, angle, get_aspect(ax))
    patch = get_patch(polygon, color, gid, **kwargs)
    ax.add_patch(patch)

def arrow(ax, xy0, xy1, rel_height=0.15, rel_width=0.13, color=sty.color.black, gid='', **kwargs):
    dx = xy1[0]-xy0[0]
    dy = xy1[1]-xy0[1]
    length = numpy.sqrt(dx**2 + dy**2)
    angle = numpy.arctan2(dy, dx)
    arrow_head(
        ax=ax,
        xy_tip=xy1,
        height=rel_height*length,
        width=rel_width*length,
        angle=angle,
        color=color,
        gid=gid+'_head',
        **kwargs)

    base_length = (1-rel_height)*length
    base_dx = base_length*numpy.cos(angle)
    base_dy = base_length*numpy.sin(angle)
    ax.plot([xy0[0], xy0[0]+base_dx], [xy0[1], xy0[1]+base_dy], color=color, gid=gid+'_base', **kwargs)

def cursor(ax, xy, r=1, color=sty.color.black, gid=''):
    patch = ptch.Ellipse(xy, r, r/get_aspect(ax), color=color, gid=gid, clip_on=False, zorder=100)
    ax.add_patch(patch)

def coordinate_system(ax, x_arrow_length=0.05, x_arrow_base=0.1, neg_arrow=True, gid_ext=''):
    def move_spines(ax, xlim, ylim, arrow_length):
        ax.spines['right'].set_visible(False)
        ax.spines['top'].set_visible(False)
        ax.spines['bottom'].set_position('zero')
        ax.spines['left'].set_position('zero')
        ax.spines['bottom'].set_gid('x_axis{:s}'.format(gid_ext))
        ax.spines['left'].set_gid('y_axis{:s}'.format(gid_ext))
        if xlim[0] < 0:
            ax.spines['bottom'].set_bounds(xlim[0]+arrow_length, xlim[1]-arrow_length)
        else:
            ax.spines['bottom'].set_bounds(0, xlim[1]-arrow_length)
        if ylim[0] < 0:
            ax.spines['left'].set_bounds(ylim[0]+arrow_length/get_aspect(ax), ylim[1]-arrow_length/get_aspect(ax))
        else:
            ax.spines['left'].set_bounds(0, ylim[1]-arrow_length/get_aspect(ax))

    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    if xlim[0] > 0:
        xlim[0] = 0
        ax.set_xlim(xlim)
    if ylim[0] > 0:
        ylim[0] = 0
        ax.set_ylim(ylim)
    width = xlim[1]-xlim[0]

    arrow_height = width*x_arrow_length
    arrow_width = width*x_arrow_base

    move_spines(ax, xlim, ylim, arrow_height)
    arrow_head(ax, (xlim[1], 0), arrow_height, arrow_width, direction='right', clip_on=False, gid='x_axis_pos_head{:s}'.format(gid_ext))
    arrow_head(ax, (0, ylim[1]), arrow_height, arrow_width, direction='up', clip_on=False, gid='y_axis_pos_head{:s}'.format(gid_ext))
    if xlim[0] < 0 and neg_arrow:
        arrow_head(ax, (xlim[0], 0), arrow_height, arrow_width, direction='left', clip_on=False, gid='x_axis_neg_head{:s}'.format(gid_ext))
    if ylim[0] < 0 and neg_arrow:
        arrow_head(ax, (0, ylim[0]), arrow_height, arrow_width, direction='down', clip_on=False, gid='y_axis_neg_head{:s}'.format(gid_ext))

def horizontal_legend(ax, **kwargs):
    ax.legend(
        bbox_to_anchor=(0., 1.02, 1., .102),
        loc='lower center',
        ncol=len(ax.get_legend_handles_labels()[0]),
        borderaxespad=0.,
        frameon=False,
        **kwargs
        )


import numpy as np
from PIL import Image
from flask_mail import Message
from .main import mail

def preprocess_image(image_file):
    image = Image.open(image_file)
    image = image.resize((224, 224))  # Resize the image to 224x224
    image = image.convert('RGB')  # Convert the image to RGB format
    return np.array(image) / 255.0  # Normalize pixel values

def send_email(to, subject, template):
    msg = Message(
        subject,
        recipients=[to],
        html=template,
        sender=('Your Name', 'your@email.com')
    )
    mail.send(msg)


from vtool.maya_lib import core

def main():

    cmds.parent("locator_eye_L","locator_eye_R","skull_mid_structure")

    deleteItems = ["skull_btm_structure","skull_top_structure"]

    for item in deleteItems+cmds.ls("joint_*upper_eye_*")+cmds.ls("joint_*lower_eye_*"):
        cmds.delete(item)

    core.prefix_hierarchy('skull_setup', 'zone')


from django.urls import path

from shop.views import (ShopView,
                        ProductSingleView,
                        CartView,
                        CheckoutView,
                        PaymentView,
                        add_to_cart,
                        add_one_to_cart,
                        remove_one_from_cart,
                        remove_from_cart)
app_name = 'shop'

urlpatterns = [
    path('<category>/', ShopView.as_view(), name='shop'),
    path('product-single/<slug>/', ProductSingleView.as_view(), name='product_single'),
    path('cart', CartView.as_view(), name='cart'),
    path('add-to-cart/<slug>/', add_to_cart, name='add-to-cart'),
    path('remove-from-cart/<slug>/', remove_from_cart, name='remove-from-cart'),
    path('add-one-to-cart/<slug>/', add_one_to_cart, name='add-one-to-cart'),
    path('remove-one-from-cart/<slug>/', remove_one_from_cart, name='remove-one-from-cart'),
    path('checkout', CheckoutView.as_view(), name='checkout'),
    path('payment', PaymentView.as_view(), name='payment'),
]