from tkinter import *
from tkinter.simpledialog import askinteger
from tkinter import filedialog
from PIL import ImageTk, Image

class Bitmap:
    def __init__(self, filename):
        self.filename = filename
        self.file_header = {}
        self.dib_header = {}
        self.buffer = []
        with open(filename, "rb") as f:
            f.read(2)
            self.file_header['file_size'] = int.from_bytes(f.read(4), byteorder='little')
            self.file_header['reserved'] = int.from_bytes(f.read(4), byteorder='little')
            self.file_header['offset'] = int.from_bytes(f.read(4), byteorder='little')
            self.dib_header['size'] = int.from_bytes(f.read(4), byteorder='little')
            self.dib_header['width'] = int.from_bytes(f.read(4), byteorder='little')
            self.w = self.dib_header['width']
            self.dib_header['height'] = int.from_bytes(f.read(4), byteorder='little')
            self.h = self.dib_header['height']
            self.dib_header['plain'] = int.from_bytes(f.read(2), byteorder='little')
            self.dib_header['bits'] = int.from_bytes(f.read(2), byteorder='little')
            self.dib_header['compression'] = int.from_bytes(f.read(4), byteorder='little')
            self.dib_header['data_size'] = int.from_bytes(f.read(4), byteorder='little')
            self.dib_header['dpi_x'] = int.from_bytes(f.read(4), byteorder='little', signed=True)
            self.dib_header['dpi_y'] = int.from_bytes(f.read(4), byteorder='little', signed=True)
            self.dib_header['palette'] = int.from_bytes(f.read(4), byteorder='little')
            self.dib_header['primary_color_count'] = int.from_bytes(f.read(4), byteorder='little')
            f.seek(self.file_header['offset'])
            self.file_header['offset'] = 54
            self.buffer = f.read(self.dib_header['data_size'])
        if self.dib_header['bits'] != 24:
            raise Exception('Only 24 bits bitmaps are supported!')

    def get(self, x, y):
        if x < 0 or x >= self.w or y < 0 or y >=self.h:
            return (0, 0, 0), 0
        i = y * self.w + x
        return [self.buffer[i * 3 + 2], self.buffer[i * 3 + 1], self.buffer[i * 3]], True

    def tk_image(self):
        return ImageTk.PhotoImage(Image.frombuffer('RGB', (self.w, self.h), self.buffer, "raw", "BGR", 0, -1))

    def blur(self, lv=10):
        bf = bytearray(self.buffer)
        for x in range(self.w):
            for y in range(self.h):
                sz = 1
                cr, _ = self.get(x, y)
                for p in range(1, lv):
                    cr2, isIn = self.get(x + p, y)
                    cr = [a + b for a, b in zip(cr, cr2)]
                    sz += isIn
                    cr2, isIn = self.get(x - p, y)
                    cr = [a + b for a, b in zip(cr, cr2)]
                    sz += isIn
                    cr2, isIn = self.get(x, y + p)
                    cr = [a + b for a, b in zip(cr, cr2)]
                    sz += isIn
                    cr2, isIn = self.get(x, y - p)
                    cr = [a + b for a, b in zip(cr, cr2)]
                    sz += isIn
                cr = [int(a / sz) for a in cr]
                i = y * self.w + x
                bf[i * 3] = cr[2]
                bf[i * 3 + 1] = cr[1]
                bf[i * 3 + 2] = cr[0]
            print(x)
        self.buffer = bytes(bf)

    def save(self, filename):
        with open(filename, "wb") as f:
            f.write(bytes('BM', encoding='ascii'))
            f.write(self.file_header['file_size'].to_bytes(4, byteorder='little'))
            f.write(self.file_header['reserved'].to_bytes(4, byteorder='little'))
            f.write(self.file_header['offset'].to_bytes(4, byteorder='little'))
            f.write(self.dib_header['size'].to_bytes(4, byteorder='little'))
            f.write(self.dib_header['width'].to_bytes(4, byteorder='little'))
            f.write(self.dib_header['height'].to_bytes(4, byteorder='little'))
            f.write(self.dib_header['plain'].to_bytes(2, byteorder='little'))
            f.write(self.dib_header['bits'].to_bytes(2, byteorder='little'))
            f.write(self.dib_header['compression'].to_bytes(4, byteorder='little'))
            f.write(self.dib_header['data_size'].to_bytes(4, byteorder='little'))
            f.write(self.dib_header['dpi_x'].to_bytes(4, byteorder='little', signed=True))
            f.write(self.dib_header['dpi_y'].to_bytes(4, byteorder='little', signed=True))
            f.write(self.dib_header['palette'].to_bytes(4, byteorder='little'))
            f.write(self.dib_header['primary_color_count'].to_bytes(4, byteorder='little'))
            f.write(self.buffer)

tk = Tk()
file = filedialog.askopenfilename()
bmp = Bitmap(file)
img = bmp.tk_image()
panel = Label(tk, image=img)
panel.pack(side="bottom", fill="both", expand="yes")

def open_bmp():
    global file, bmp, img
    file = filedialog.askopenfilename()
    bmp = Bitmap(file)
    img = bmp.tk_image()
    panel.configure(image=img)

def show_blur():
    global img

    n = askinteger('平滑范围：', '输入参数', initialvalue=3)
    t = askinteger('平滑次数：', '输入参数', initialvalue=3)
    for i in range(t):
        bmp.blur(n)
    img = bmp.tk_image()
    panel.config(image=img)
    bmp.save("blur.bmp")

open_button = Button(tk, text="打开", command=open_bmp)
open_button.pack()
blur_button = Button(tk, text="空间域平滑", command=show_blur)
blur_button.pack()
tk.mainloop()


import json
from pprint import pprint
with open('swjson.json') as data_file:
    data = json.load(data_file)

contador=0
print("Ahora listará las naves que aparezcan en el episodio que quieras")
episodio=input("Introduzca el número del episodio: ")
listapelis=[]

for pelicula in data ["results"]:
	for titulo in pelicula["films"]:
		if titulo["id"] not in listapelis:
			listapelis.append(titulo["id"])

if episodio not in listapelis:
	print("Pelicula inexistente")
else:
	for nave in data["results"]:
		for pelicula in nave["films"]:
			if pelicula["id"]==episodio:
				nombre=pelicula["title"]
				contador=contador+1
				print(nave["name"])
	print("El total de naves en",nombre,"son",contador)


"""
File: shapes/examples/lunar_horizon_calculator.py
Author: Neil Bassett
Date: 20 April 2021

Description: Example showing how to use the LunarHorizonCalculator
             class.
"""
from shapes import LunarHorizonCalculator
import matplotlib.pyplot as plt

schrodinger_coordinates = (132.4, -75.0)
lunar_horizon_calculator = LunarHorizonCalculator(schrodinger_coordinates)
N_alpha = 361
N_gamma = 1000
horizon_azimuths, horizon_profile =\
    lunar_horizon_calculator.horizon_profile(N_alpha, N_gamma)

fig, ax = plt.subplots(figsize=(20, 5))
plt.plot(horizon_azimuths, horizon_profile)
plt.xlim(0, 360)
plt.xlabel('Azimuth (deg)')
plt.ylabel('Horizon Angle (deg)')
plt.show()


import logging
import sys
from clbundler.config import global_config
from clbundler.commandparser import CommandParser
from clbundler import cli
from clbundler import exceptions

def main():
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)

    ch = logging.StreamHandler(sys.stdout)
    ch.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(levelname)s: %(message)s')
    ch.setFormatter(formatter)
    logger.addHandler(ch)

    parser = CommandParser()
    cli.setup_parser(parser)

    try:
        parser.parse_args()
    except exceptions.CLbundlerError as e:
        logger.error(e)


import cv2
import numpy as np
from matplotlib import pyplot as plt

#img = cv2.imread('SimpleImageDataset/building05.jpg') #reads in an imageas BGR by default
img = cv2.imread('checkered2.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

#harris corner detection (rotation invariant)
#https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_feature2d/py_features_harris/py_features_harris.html
#https://youtu.be/WyrVzTRZuXA?t=509
gray = np.float32(gray)
cornerimg = cv2.cornerHarris(gray,2,3,0.04)

#result is dilated for marking the corners, not important
dilated = cv2.dilate(cornerimg,None)
ret, dst = cv2.threshold(dilated,0.01*dilated.max(),255,0)
dst = np.uint8(dst)

# find centroids
ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)

# define the criteria to stop and refine the corners
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001)
corners = cv2.cornerSubPix(gray,np.float32(centroids),(5,5),(-1,-1),criteria)

# Now draw them
res = np.hstack((centroids,corners))
res = np.int0(res)
img[res[:,1],res[:,0]]=[255,0,0]
img[res[:,3],res[:,2]] = [0,255,0]

#plt.subplot(131),plt.imshow(img, cmap='gray'),plt.title('Original')
#plt.subplot(132),plt.imshow(cornerimg, cmap='gray'),plt.title('Cornered1')
#plt.subplot(133),plt.imshow(dilated, cmap='gray'),plt.title('Cornered2')

# Initiate FAST object with default values
fast = cv2.FastFeatureDetector_create()
# find and draw the keypoints
kp = fast.detect(img,None)
img2 = cv2.drawKeypoints(img, kp, color=(255,0,0), outImage=gray)
# Print all default params
print("Threshold: ", fast.getThreshold())
print("nonmaxSuppression: ", fast.getNonmaxSuppression())
print("neighborhood: ", fast.getType())
print("Total Keypoints with nonmaxSuppression: ", len(kp))
plt.imshow(img2)

plt.show()

#cv2.imshow('image',img2)
#cv2.waitKey(0)
#cv2.destroyAllWindows()


from tkinter import ttk
import tkinter as tk
import customtkinter
from PIL import Image
import os
import cv2
import dlib
from moviepy.editor import VideoFileClip
from ExtractImage import extract_frames
import cv2

def getDuration(video_path):
    clip = VideoFileClip(video_path)
    duration = clip.duration
    clip.close()
    return duration

def extract_frames(videoFile, times, sequencePath, progress_var):
    if not os.path.exists(sequencePath):
        os.makedirs(sequencePath)

    clip = VideoFileClip(videoFile)
    original_filename = os.path.splitext(os.path.basename(videoFile))[0]

    total_frames = len(times)
    counter = 0

    app = tk.Tk()
    app.title("Extracting Frames")
    app.geometry("250x50")

    progress = ttk.Progressbar(
        app,
        orient="horizontal",
        length=200,
        mode="determinate",
        variable=progress_var
    )
    progress.place(relx=0.5, rely=0.8, anchor=tk.CENTER)
    progress["maximum"] = total_frames

    for i, t in enumerate(times):
        frame_path = os.path.join(sequencePath, f'{original_filename}_frame{i+1}.jpg')
        clip.save_frame(frame_path, t)

        # Increment counter for the next face
        counter += 1

        # Update the progress bar
        progress_var.set(counter)
        app.update_idletasks()

    progress.destroy()
    app.destroy()
    print("Done Extracting Frames")

def CropFaces(input_folder, output_folder, progress_var):
    # Ensure the output folder exists
    os.makedirs(output_folder, exist_ok=True)

    total_frames = 35

    app = tk.Tk()
    app.title("Cropping Frames")
    app.geometry("250x50")

    progress = ttk.Progressbar(
        app,
        orient="horizontal",
        length=200,
        mode="determinate",
        variable=progress_var
    )
    progress.place(relx=0.5, rely=0.8, anchor=tk.CENTER)
    progress["maximum"] = total_frames

    # Initialize the face detector from dlib
    face_detector = dlib.get_frontal_face_detector()

    # Iterate through all images in the input folder
    for filename in os.listdir(input_folder):
        if filename.lower().endswith((".jpg", ".png")):
            input_path = os.path.join(input_folder, filename)

            # Load the image
            img = cv2.imread(input_path)

            # Conver the image to grayscale for face detection
            gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

            # Call face detector function from dlib
            faces = face_detector(gray_img)

            # Initialize a counter for unique face identification
            counter = 0

            # Crop and save each detected face
            for i, face in enumerate(faces, start=1):
                x, y, w, h = face.left(), face.top(), face.width(), face.height()

                # Adjust the cropping region to include some margin around the face
                margin = 1
                x -= margin
                y -= margin
                w += 2 * margin
                h += 2 * margin

                # Ensure the cropping region is within the image boundaries
                x = max(x, 0)
                y = max (y, 0)
                w = min(w, img.shape[1] - x)
                h = min(h, img.shape[0] - y)

                # Crop the face
                cropped_face = img[y:y+h, x:x+w]

                # Save the cropped faces
                output_filename = f"{os.path.splitext(filename)[0]}_Cropped.jpg"
                output_filepath = os.path.join(output_folder, output_filename)
                cv2.imwrite(output_filepath, cropped_face)

                # Update the progress bar
                progress_var.set(counter)
                app.update_idletasks()
    progress.destroy()
    app.destroy()
    print("Done Cropping Extracted Frames")

def ShowImage(ImagePath):
    try:
        image = customtkinter.CTkImage(dark_image=Image.open(ImagePath), size=(200, 200))

        return image

    except Exception as e:
        print(f"Error opening image: {e}")

def ShowVideo(VideoPath):
    # Takes original filename to create a new folder every time a new file is selected
    original_filename = os.path.splitext(os.path.basename(VideoPath))[0]

    ExtractedPath = os.path.join(os.path.dirname(VideoPath), f'{original_filename}_Extracted')
    os.makedirs(ExtractedPath, exist_ok=True)

    clip = VideoFileClip(VideoPath)
    times = [i/clip.fps for i in range(int(clip.fps * clip.duration))]
    progress_var = tk.DoubleVar()
    extract_frames(VideoPath, times, ExtractedPath, progress_var)

    croppedPath = os.path.join(os.path.dirname(VideoPath), f'{original_filename}_Cropped')
    CropFaces(ExtractedPath, croppedPath, progress_var)

    # Takes original filename and appends what frame it is to the end
    frame_path = os.path.join(croppedPath, f'{os.path.splitext(os.path.basename(VideoPath))[0]}_frame1_Cropped.jpg')
    # ShowImage(frame_path)
    return frame_path


import numpy as np
import time
import logging
from preprocess import *
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV, KFold
from tensorflow.keras.layers import Dense, SimpleRNN, LSTM, Dropout, Input
from tensorflow.keras.models import Sequential
from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.optimizers import Adam
from kerastuner import HyperModel
from kerastuner.tuners import Hyperband
import pickle

logger = logging.getLogger("logger")

class CustomHyperModel(HyperModel):
    def __init__(self, mode, input_shape, num_classes):
        self.mode = mode
        self.input_shape = input_shape
        self.num_classes = num_classes

    def build(self, hp):
        model = Sequential()

        model.add(Input(shape=self.input_shape))

        if self.mode == "rnn":
            for i in range(hp.Int('num_layers', 1, 3)):
                model.add(SimpleRNN(
                    units = hp.Int('units', min_value=32, max_value=256, step=16),
                    activation = hp.Choice('activation', values=['relu']),
                    return_sequences = True if i < hp.Int('num_layers', 1, 3) - 1 else False
                ))
        elif self.mode == "lstm":
            for i in range(hp.Int('num_layers', 1, 3)):
                model.add(LSTM(
                    units = hp.Int('units', min_value=32, max_value=512, step=16),
                    activation = hp.Choice('activation', values=['relu'], default='relu'),
                    return_sequences = True if i < hp.Int('num_layers', 1, 3) - 1 else False
                ))

        model.add(Dense(self.num_classes, activation='softmax'))

        model.compile(
            optimizer = Adam(
                hp.Choice('learning_rate', values=[1e-2, 1e-3, 1e-4])
            ),
            loss = 'categorical_crossentropy',
            metrics = ['accuracy']
        )

        return model

def check_single_class(y):
    if len(np.unique(y)) == 1:
        logger.info("Only 1 class in y. Skip.")
        logger.info(f"y: {y}")
        return True
    return False

def dt_run(X, y):
    logger.info("Running Decision Tree...")

    X = np.array(X)
    y = np.array(y)

    params = {
        'max_depth': [5, 10, 15, 20, 25, 30],
        'min_samples_leaf': [2, 4, 8, 12, 16, 20],
        'min_samples_split': [2, 4, 8, 12, 16, 20],
        'max_features': ['auto', 'sqrt', 'log2']
    }

    model = GridSearchCV(RandomForestClassifier(), params, cv=5, n_jobs=-1)

    if not check_single_class(y):
        model.fit(X, y)

    return model

def rf_run(X, y):
    logger.info("Running Random Forest...")

    X = np.array(X)
    y = np.array(y)

    params = {
        'n_estimators': [200, 300, 400, 500],
        'max_depth': [5, 10, 15, 20, 25, 30],
        'min_samples_leaf': [2, 4, 6, 8, 10],
        'min_samples_split': [2, 4, 6, 8, 10],
        'max_features': ['auto', 'sqrt', 'log2']
    }

    model = GridSearchCV(RandomForestClassifier(), params, cv=5, n_jobs=-1)

    # y의 클래스가 1개일 경우
    if not check_single_class(y):
        model.fit(X, y)

    return model

def rnn_lstm_generate(X, y, mode):
    if X.shape[0] != y.shape[0]:
        logger.error("X, y shape mismatch.")
        exit(1)

    logger.debug(f"X shape: {X.shape}")
    logger.debug(f"y shape: {y.shape}")

    label_to_index = {label: i for i, label in enumerate(np.unique(y))}
    index_to_label = {i: label for label, i in label_to_index.items()}

    # y를 one-hot encoding
    unique_y = np.unique(y)
    label_map = {label: i for i, label in enumerate(unique_y)}
    y = np.array([label_map[label] for label in y])

    num_classes=len(unique_y)
    input_shape=(None, 4)

    y = to_categorical(y, num_classes=num_classes)

    kfold = KFold(n_splits=5, shuffle=True, random_state=42)
    fold_num = 1

    for train, val in kfold.split(X, y):
        logger.info(f"Fold {fold_num}...")
        train_X, train_y = X[train], y[train]
        val_X, val_y = X[val], y[val]

        # hyperparameter tuning
        hypermodel = CustomHyperModel(mode, input_shape, num_classes)
        tuner = Hyperband(
            hypermodel,
            objective='val_accuracy',
            max_epochs=30,
            factor=3,
            directory='hyperband',
            project_name=f"{mode}_{time.strftime('%Y%m%d_%H%M%S')}"
        )

        tuner.search(X, y, epochs=40, validation_data=(val_X, val_y))

        best_hypers = tuner.get_best_hyperparameters(num_trials=1)[0]

        model = tuner.hypermodel.build(best_hypers)

        model.fit(
            X,
            y,
            epochs=40,
            validation_split=0.2,
            callbacks=[
                EarlyStopping(monitor='val_loss', patience=3),
                ReduceLROnPlateau(monitor='val_loss', patience=2)
            ]
        )

        fold_num += 1

    return model

def rnn_run(X, y):
    logger.info("Running RNN...")

    return rnn_lstm_generate(X, y, "rnn")

def lstm_run(X, y):
    logger.info("Running LSTM...")

    return rnn_lstm_generate(X, y, "lstm")

def learn(flows, labels, mode, model_type):
    logger.info(f"Creating {mode} {model_type} model...")

    model_func = {
        "rf": rf_run,
        "dt": dt_run,
        "rnn": rnn_run,
        "lstm": lstm_run
    }
    if model_type == "rnn" or model_type == "lstm":
        X, y = extract_features(flows, labels, mode)
    else:
        X, y = extract_features_b(flows, labels, mode)

    X = np.array(X).astype(np.float32)
    y = np.array(y).astype(np.float32)

    logger.debug(f"X shape: {X.shape}")
    logger.debug(f"y shape: {y.shape}")

    model = model_func[model_type](X, y)

    logger.info(f"Created {mode} {model_type} model.")

    # 생성 시간을 포함한 이름으로 모델 저장
    model_name = f"{mode}_{model_type}_{time.strftime('%Y%m%d_%H%M%S')}"
    with open(f"../model/{model_name}.pkl", 'wb') as f:
        pickle.dump(model, f)

    logger.info(f"Saved {mode} {model_type} model as {model_name}.pkl.")

    return model


from pygame.math import Vector2 as V2
from pygame.math import Vector3 as V3
import pygame
import pygame.gfxdraw as gfx

import thorpy
##from stlreader import Object3D
from core3d import Object3D
from light import Light
from camera import Camera

#opti: utiliser les dist au carre. Pygame vs math vs manuel
#si la technique des angles marche pas, enlever la normalisation des normales...

#comparer perfs core3d vs stlreader quand l'ordi ira mieux ==> un CHOUILLA mieux

light_pos = V3(0,0,-1000)
light_m = V3(20,20,20)
light_M = V3(200,200,200)
light = Light(light_pos, light_m, light_M)
USE_LIGHT = True

obj1 = Object3D("node_ascii.stl")
obj1.move(V3(0,0,2))
for t in obj1.triangles:
    t.color = V3(70,70,255)
    t.ecolor = t.color

obj2 = Object3D("node_ascii.stl")
obj2.move(V3(0,0,5))

from core3d import ManualObject3D, Triangle
a = 4
t1 = ManualObject3D([Triangle(a*V3(-1,0,0), a*V3(1,0,0), a*V3(0,1,0),
                                        color=V3(50,50,255)),
                        Triangle(a*V3(1,0,0), a*V3(-1,0,0), a*V3(0,-1,0),
                                        color=V3(50,50,255))])
t1.refresh_normals()
t1.move(V3(0,0,5))

##obj1.scale(0.2)

##active_obj = obj1
##objs = [obj1]

##cube = Object3D("cube_ascii.stl"); cube.refresh_normals()
##cube = Object3D("cube2.stl")
##cube.move(V3(0,0,4))
##for t in cube.triangles:
##    t.color = V3(70,70,255)
##    t.ecolor = t.color
##objs = [cube]
##cube.compute_neighbours()
##active_obj = cube
##colors = [(255,0,0),(255,0,0),
##            (0,200,0),(0,200,0),
##            (0,0,255),(0,0,255),
##            (255,255,0),(255,255,0),
##            (255,0,255),(255,0,255),
##            (255,255,255),(255,255,255)]
##colors = [V3(c) for c in colors]
##for i in range(len(cube.triangles)):
##    cube.triangles[i].color = colors[::2][i%6]

##active_obj = t1
##objs = [t1]

##fighter = Object3D("meshes/chasseur_biplace.stl")
fighter = Object3D("meshes/f4.stl")
for t in fighter.triangles:
    t.color = V3(70,70,255)
    t.ecolor = t.color
fighter.move(V3(0,0,10))

active_obj = fighter
objs = [fighter]

def func(event):
    global light_pos
    objs.sort(key=lambda x:x.from_center.length(), reverse=True)
    screen.fill((255,255,255))
    DS = 0.2
    DA = 10
    print(pygame.event.event_name(event.type))
    if event.key == pygame.K_LEFT:
        active_obj.move(V3(-DS,0,0))
    elif event.key == pygame.K_RIGHT:
        active_obj.move(V3(DS,0,0))
    elif event.key == pygame.K_DOWN:
        active_obj.move(V3(0,-DS,0))
    elif event.key == pygame.K_UP:
        active_obj.move(V3(0,DS,0))
    elif event.key == pygame.K_m:
        active_obj.move(V3(0,0,DS))
    elif event.key == pygame.K_l:
        active_obj.move(V3(0,0,-DS))
    elif event.key == pygame.K_z:
        active_obj.rotate_around_center_z(DA)
    elif event.key == pygame.K_u:
        active_obj.rotate_around_center_z(-DA)
    elif event.key == pygame.K_x:
        active_obj.rotate_around_center_x(DA)
    elif event.key == pygame.K_c:
        active_obj.rotate_around_center_x(-DA)
    elif event.key == pygame.K_y:
        active_obj.rotate_around_center_y(DA)
    elif event.key == pygame.K_a:
        active_obj.rotate_around_center_y(-DA)
    elif event.key == pygame.K_SPACE:
##        cam.move(V3(1,0,1), objs)
        cam.rotate("y",1,objs)
    for obj in objs: #pas boucler sur objs mais sur tous les triangles de la scen!!! ==> objet scene, le concept de obj est la que pour user transfos ?
        obj.refresh()
        i = 0
        for t in obj.triangles:
            if t.c.z > 0: #c denotes the center coordinate
                p = []
                for v in t.vertices():
                    x,y = cam.project(v)
                    p.append((int(x),int(y)))
                if USE_LIGHT:
                    color = light.get_color(t)
                else:
                    color = t.color
##                print(color)
##                color = t.color
##                print(p)
                gfx.filled_trigon(screen, p[0][0], p[0][1], p[1][0], p[1][1], p[2][0], p[2][1], color)
                gfx.aatrigon(screen, p[0][0], p[0][1], p[1][0], p[1][1], p[2][0], p[2][1], color)
            i+=1
    pygame.display.flip()

##thorpy.application.SHOW_FPS = True

reac = thorpy.Reaction(pygame.KEYDOWN,func)
##reac = thorpy.Reaction(thorpy.THORPY_EVENT,func,{"id":thorpy.constants.EVENT_TIME})

app = thorpy.Application((800,600))
screen = thorpy.get_screen()

cam = Camera(screen, fov=512, d=2)

g = thorpy.Ghost.make()
g.add_reaction(reac)

m = thorpy.Menu(g,fps=100)
m.play()

app.quit()


import openai

root_path = 'C:\\OpenAI\\'
key_file_path = f'{root_path}SECRET_KEY.txt'
key_file = open(key_file_path, "r", encoding='utf-8')
key = key_file.read()
print(f'key={key}')
openai.api_key = key

while True:
    completion = openai.Completion.create(
      model="text-davinci-003",
      prompt=input("You: ")
    )
    print(completion.choices[0]['text'])


__author__ = "Frédéric BISSON"
__copyright__ = "Copyright 2022, Frédéric BISSON"
__credits__ = ["Frédéric BISSON"]
__license__ = "mit"
__maintainer__ = "Frédéric BISSON"
__email__ = "zigazou@protonmail.com"

from logging import getLogger

from ..token.PDFNumber import PDFNumber
from ..token.PDFListOpen import PDFListOpen
from ..token.PDFDictOpen import PDFDictOpen
from ..token.PDFCommand import PDFCommand
from ..token.PDFListClose import PDFListClose
from ..token.PDFDictClose import PDFDictClose
from ..token.PDFComment import PDFComment

from ..item.PDFReference import PDFReference
from ..item.PDFObjectID import PDFObjectID
from ..item.PDFList import PDFList
from ..item.PDFDictionary import PDFDictionary
from ..item.PDFObject import PDFObject
from ..item.PDFTrailer import PDFTrailer
from ..item.PDFStartXref import PDFStartXref
from ..item.PDFXref import PDFXref
from ..item.PDFStream import PDFStream
from ..item.PDFXrefStream import PDFXrefStream
from ..item.PDFObjectStream import PDFObjectStream
from ..item.PDFXrefSubSection import PDFXrefSubSection

from ..pdf.PDF import PDF

from .TokenProcessor import TokenProcessor

_logger = getLogger("PDFProcessor")

class EncryptionNotImplemented(Exception):
    pass

class SignatureNotSupported(Exception):
    pass

class PDFProcessor(TokenProcessor):
    """A PDF processor

    A PDF processor is a stack machine. It recognizes some command and executes
    them, changing the stack state.
    """

    def __init__(self):
        self.tokens = PDF()

    def _generate_reference(self):
        gen_num = int(self.tokens.pop().value)
        obj_num = int(self.tokens.pop().value)
        self.tokens.push(PDFReference(obj_num, 0))

    def _generate_object_id(self):
        gen_num = int(self.tokens.pop().value)
        obj_num = int(self.tokens.pop().value)
        self.tokens.push(PDFObjectID(obj_num, 0))

    def _generate_list(self):
        items = []
        while self.tokens.stack_size() > 0:
            current = self.tokens.pop()

            if isinstance(current, PDFListOpen):
                items.reverse()
                self.tokens.push(PDFList(items))
                return

            items.append(current)

    def _generate_dict(self):
        key_values = {}

        while self.tokens.stack_size() > 0:
            value = self.tokens.pop()

            if isinstance(value, PDFDictOpen):
                self.tokens.push(PDFDictionary(key_values))
                return

            key = self.tokens.pop()
            key_values[key] = value

    def _generate_object(self):
        stream = self.tokens.pop()

        if isinstance(stream, PDFStream):
            value = self.tokens.pop()
        else:
            value = stream
            stream = None

        if type(value) == PDFDictionary:
            # Look for encryption use in the PDF
            if b"Encrypt" in value:
                raise EncryptionNotImplemented()

            # Look for signature use in the PDF
            if b"Type" in value and value[b"Type"] == b"Sig":
                raise SignatureNotSupported()

        object_id = self.tokens.pop()
        object = PDFObject(object_id.obj_num, object_id.gen_num, value, stream)

        if object.obj_num in self.tokens.objects:
            # Remove objects in the stack with the same number.
            def any_object_with_same_number(_, item):
                return (
                    type(item) == PDFObject and
                    item.obj_num == object.obj_num
                )

            for index, _ in self.tokens.find(any_object_with_same_number):
                self.tokens.pop(index)
                break

        self.tokens.push(object)

    def _convert_startxref(self):
        def any_startxref_command(_, item): return (
            type(item) == PDFCommand and
            item.command == b"startxref"
        )

        for offset, _ in self.tokens.find(any_startxref_command):
            self.tokens.pop(offset)
            self.tokens.insert(
                offset,
                PDFStartXref(self.tokens.pop(offset).value)
            )

    def _convert_xref(self):
        def any_xref_command(_, item): return (
            type(item) == PDFCommand and
            item.command == b"xref"
        )

        for offset, _ in self.tokens.find(any_xref_command):
            self.tokens.pop(offset)

            xref = PDFXref()

            while isinstance(self.tokens.stack_at(offset), PDFNumber):
                base = self.tokens.pop(offset).value
                count = self.tokens.pop(offset).value
                subsection = PDFXrefSubSection(base, count)

                for _ in range(count):
                    ref_offset = self.tokens.pop(offset).value
                    ref_new = self.tokens.pop(offset).value
                    ref_type = self.tokens.pop(offset).command.decode('ascii')

                    subsection.entries.append((ref_offset, ref_new, ref_type))

                xref.subsections.append(subsection)

            self.tokens.insert(offset, xref)

    def _convert_trailer(self):
        def any_trailer_command(_, item): return (
            type(item) == PDFCommand and
            item.command == b"trailer"
        )

        for offset, _ in self.tokens.find(any_trailer_command):
            self.tokens.pop(offset)
            self.tokens.insert(offset, PDFTrailer(self.tokens.pop(offset)))

    def end_parsing(self):
        """Converts remaining items on the stack.

        The `startxref`, `xref` and `trailer` elements of a PDF file do not
        follow a stack principle. They must therefore be recognized when all the
        parsing has been done.

        Without calling this method, the processor state is inconsistent.
        """
        self._convert_startxref()
        self._convert_xref()
        self._convert_trailer()

    def push(self, item):
        """Push an item onto the processor's stack.

        Pushing item on stack may result in their interpretation. For example,
        pushing `1` then `0` then `R` on the stack will make the processor
        replace them by a `PDFReference` object.

        Comments other than `%PDF-*` or `%%EOF` will be completely ignored.
        """
        if type(item) == PDFCommand and item.command == b"R":
            self._generate_reference()
        elif type(item) == PDFCommand and item.command == b"obj":
            self._generate_object_id()
        elif type(item) == PDFCommand and item.command == b"endobj":
            self._generate_object()
        elif type(item) == PDFListClose:
            self._generate_list()
        elif type(item) == PDFDictClose:
            self._generate_dict()
        elif type(item) == PDFComment:
            # Discard unneeded comments
            if item.content[:5] == b"%PDF-" or item.content[:5] == b"%%EOF":
                self.tokens.push(item)
        else:
            self.tokens.push(item)

    def encode(self) -> bytes:
        """Encode a PDF from the current state of the processor

        :return: A complete PDF file content ready to be written in a file
        :rtype: bytes
        """

        # Detect linearization
        def any_linearized(_, item):
            return (
                type(item) == PDFObject and
                type(item.value) == PDFDictionary and
                b"Linearized" in item
            )

        linearized = self.tokens.find_first(any_linearized)

        # Encode each object.
        def any_object(_, item):
            if type(item) != PDFObject:
                return False

            if type(item.value) == PDFDictionary:
                if b"Type" in item and item[b"Type"] == b"XRef":
                    return False

                if b"Type" in item and item[b"Type"] == b"ObjStm":
                    return False

                if b"Linearized" in item:
                    return False

            return True

        output = PDFComment(b"%PDF-1.7").encode()
        offset = len(output)

        # Write every object.
        xref_entries = {}
        for _, item in self.tokens.find(any_object):
            item.item_offset = offset
            xref_entries[item.obj_num] = (1, offset, 0)

            item_encoded = item.encode()
            offset += len(item_encoded)
            output += item_encoded

        # Write every object stream.
        def any_object_stream(_, item):
            return type(item) == PDFObjectStream

        for _, item in self.tokens.find(any_object_stream):
            index = 0
            xref_entries[item.obj_num] = (1, offset, 0)

            for object in item.objects:
                xref_entries[object.obj_num] = (2, item.obj_num, index)
                index += 1

            item_encoded = item.encode()
            offset += len(item_encoded)
            output += item_encoded

        # Retrieve trailer information.
        def any_trailer(_, item):
            return (
                type(item) == PDFTrailer or
                (
                    type(item) == PDFObject and
                    type(item.value) == PDFDictionary and
                    b"Type" in item and item[b"Type"] == b"XRef"
                )
            )

        trailers = list(self.tokens.find(any_trailer))

        if linearized:
            old_trailer = trailers[0][1]
        else:
            old_trailer = trailers[-1][1]

        if type(old_trailer) == PDFObject:
            trailer_info = old_trailer[b"Info"]
            trailer_root = old_trailer[b"Root"]
        else:
            trailer_info = old_trailer.dictionary[b"Info"]
            trailer_root = old_trailer.dictionary[b"Root"]

        # Write the XRef stream.
        max_obj_num = max(list(xref_entries.keys()))
        references = {
            index: (
                xref_entries[index] if index in xref_entries else (0, 65535, 0)
            )
            for index in range(max_obj_num + 1)
        }

        xrefstm = PDFXrefStream(max_obj_num + 1, 0, references)
        xrefstm.trailer_info = trailer_info
        xrefstm.trailer_root = trailer_root
        output += xrefstm.encode()

        # Write the startxref offset
        output += b"startxref\n%d\n" % offset

        # Write the end of file
        output += PDFComment(b"%%EOF").encode()

        return output


import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

# Datos de prueba
x = np.array([1.19, 0.33, 0.26, 0.35, 0.45, 0.85, 0.43, 1.48, 0.28, 1.12, 0.18, 1.85, 0.21, 0.17, 0.44, 0.26, 0.33, 0.18, 0.10, 0.92, 0.10, 1.06, 0.39, 0.28, 0.33])
#y = np.array([6.7, 6.1, 2.3, 5.7, 2.9, 7.5, 3.7, 5.8, 3.1, 6.8, 2.8, 7.7, 2.8, 3.8, 3.9, 3, 5.8, 2.6, 3.9, 4.8, 1.7, 6.8, 5.8, 3.5, 3.7])
y = np.array([11.8, 6, 9.2, 6.8, 7.8, 7.7, 10.3, 13.9, 8.3, 11.2, 7.9, 15.8, 8.8, 6.1, 6.2, 7.2, 5.5, 5.2, 3.9, 10.8, 3.8, 10.7, 6.5, 4.9, 7])

# Error asociado a la variable y (esto es inventado, ustedes ponen los que midieron o calcularon)
y_err =  np.full(25, 0.5)

# Definimos una ley de escala para el ajuste
def power_law(x, a, b):
    return a *pow(x, b)

# Hacemos cuadrados mínimos pesados con los errores de y usando curve_fit
popt, pcov = curve_fit(power_law, x, y, sigma=y_err, absolute_sigma=True)
a, b = popt

x_fit = np.linspace(min(x), max(x), 400)

# Graficamos con barras de error
plt.errorbar(x, y, yerr=y_err, fmt='o', label="Data")
plt.plot(x_fit, power_law(x_fit, a, b), label=f"Fit: y={a:.2f}x^{b:.2f}")

plt.xlabel("X")
plt.ylabel("Y")
plt.legend()
plt.title("Data como ley de potencias")
plt.show()

# PARTE DOS ---------------------------------

# Modelo linear con la data en log-log
def linear_model(x, m, c):
    return m * x + c

# Hacemos el logaritmo de los datos
log_x = np.log10(x)
log_y = np.log10(y)
log_y_err = y_err / (y * np.log(10))

# Para que log_y_err no tenga valores negativos, los paso como errores absolutos
popt_linear, pcov_linear = curve_fit(linear_model, log_x, log_y, sigma=log_y_err, absolute_sigma=True)
m, c = popt_linear
m_err, c_err = np.sqrt(np.diag(pcov_linear))

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 2)
plt.errorbar(log_x, log_y, yerr=log_y_err, fmt='o', label="Incerteza")
plt.plot(log_x, linear_model(log_x, m, c), label=f"Ajuste: y={m:.2f}±{m_err:.2f}x + {c:.2f}±{c_err:.2f}")
plt.xlabel("log(masa)")
plt.ylabel("log(ancho)")
plt.legend()
plt.title("Muestras en Log-Log con ajuste lineal")

"""
plt.subplot(1, 2, 1)
plt.errorbar(x, y, yerr=y_err, fmt='o', label="Data")
plt.plot(x, power_law(x, a, m), label=f"Power Law Fit: y={a:.2f}x^{b:.2f}")
plt.plot(x_fit, power_law(x_fit, a, b), label=f"Fit: y={a:.2f}x^{b:.2f}") #Lo agregue yo
plt.xlabel("X")
plt.ylabel("Y")
plt.legend()
plt.title("Data con ajuste de ley de potencias")
"""

plt.tight_layout()
plt.show()

#--------- AGREGADO POR Mí -----------------
x_fit = np.linspace(min(x), max(x), 400)
ordenada = pow(10, c)
# Graficamos con barras de error
plt.errorbar(x, y, yerr=y_err, fmt='o', label="Muestras")
plt.plot(x_fit, power_law(x_fit, ordenada, m), label=f"Ajuste: y={ordenada:.2f}x^{m:.2f}")
plt.xlabel("Masa (gr)")
plt.ylabel("Ancho (cm)")
plt.legend()
plt.title("Muestras ajustadas con la Ley de potencias")
plt.show()

y_pred = power_law(x, ordenada, m)
relative_error = np.sum((y-y_pred)**2)/np.sum(y**2)
print("Error relativo acumulado (largo vs masa): ", relative_error)

# Es importante analizar los coeficientes junto a sus incertezas asociadas
print(f"Pendiente (m): {m:.2f} ± {m_err:.2f}")
print(f"Ordenada al origen (c): {c:.2f} ± {c_err:.2f}")


import requests
import re
import time
import winsound
from bs4 import BeautifulSoup

# def main():
#     recursion(1)

with requests.Session() as s:
    root_url = "https://www.bowerypresents.com/info/events/get?scope=all&page=1&rows=99&venues=new-york-metro"

    lxml = s.get(root_url).text
    soup = BeautifulSoup(lxml, 'lxml')
    empty = ''
    event_notifier = []

    bowerybody = soup.find("body")
    boweryevent = bowerybody.find_all('div', class_='show-item')

    for event in boweryevent:
        eventdate = [a.text.strip() for a in event.select('p[class="list-date"]')]
        eventname = [a.text.strip() for a in event.select('span[itemprop="name"]') if a.text.strip() != empty]
        supporting = [a.text.strip() for a in event.select('span[itemprop="performer"]')]
        for date in eventdate:
            eventdate = date.replace('\n','')
            eventdate = re.sub(' +', ' ', eventdate)
        for opener in supporting:
            if opener == empty:
                print (eventname, eventdate)
            else:
                print(eventname, supporting, eventdate)

#
#
# def eventalert():
#     for vettix_date in vettix_dates:
#         vettix_edate = [a.text.strip() for a in vettix_date.select("p > strong")]
#         vettix_event = [a.text.strip() for a in vettix_date.select('div.date-1')]
#         for text in vettix_event:
#             if any(word in text for word in event_notifier):
#                 print(text, vettix_edate)
#                 winsound.Beep(440, 250)
#                 time.sleep(.5)
#
#
# def recursion(k):
#     if k > 0:
#         # printevent()
#         printnextpage()
#         eventalert()
#         time.sleep(600)
#         recursion(1)
#
#
# if __name__ == "__main__":
#     main()


import pandas as pd
import sys
import os
sys.path.append(os.getcwd())
import config.constants as constants
from sklearn.utils import resample

def rebalance_dataset(df, feature_col, unique_id_col):
    balanced_df = pd.DataFrame()

    max_count = df.groupby(feature_col).count()[unique_id_col].max()
    max_label = df.index[df.groupby(feature_col).count()[unique_id_col].idxmax()]

    for group, sub_df in df.groupby(feature_col):
        replace = False if group == max_label else True
        # print(f"Group: {group}, Replace: {replace}")
        temp_df = resample(sub_df, replace=replace, n_samples=max_count)
        balanced_df = pd.concat([balanced_df, temp_df])

    return balanced_df

if __name__ == "__main__":

    df = pd.read_excel(constants.rebalance_config['data_path'])
    rebal_df = rebalance_dataset(df, **constants.rebalance_config['rebal_input'])
    rebal_df.to_csv(constants.rebalance_config['out_path'])


import sqlite3 as lite

con = lite.connect('data.db')

with con:
    cur = con.cursor()
    cur.execute("CREATE TABLE categorias(id INTEGER PRIMARY KEY AUTOINCREMENT, nome TEXT)")

#Criando tabela de receitas
with con:
    cur = con.cursor()
    cur.execute("CREATE TABLE receitas(id INTEGER PRIMARY KEY AUTOINCREMENT, categoria TEXT, adicionado_em DATE, valor DECIMAL)")

#Criando tabela de gastos
with con:
    cur = con.cursor()
    cur.execute("CREATE TABLE gastos(id INTEGER PRIMARY KEY AUTOINCREMENT, categoria TEXT, retirado_em DATE, valor DECIMAL)")


import pandas as pd
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--no', type=str)
args = parser.parse_args()

output = 'test/data/output_' + args.no + '.csv'
json = 'test/data/json_' + args.no + '.csv'

df = pd.read_csv('test/data/output.csv', sep=';', header=None)
df.iloc[:, :-1].to_csv(output, index=False, header=False)
df.iloc[:, -1].to_csv(json, index=False, header=False)


from dataclasses import dataclass, field
import numpy as np
import random
from tqdm import tqdm
import torch
from typing import List, Tuple

import gzip
import pickle

from data_utils.dataset import TokenizedDataset, SentenceDropDataset
from data_utils.sentence import Sentence
from data_utils.example import ExampleWithSentences

##random.sample vs random.choice

@dataclass
class FindCatSentence(Sentence):
    pass

@dataclass
class FindCatExample(ExampleWithSentences):
    target_tokens: List[int]
    positions: List[int]
    label: int = 0

def contains_subsequence_old(target, sequence):
    if len(target) == 0:
        return True

    if target[0] not in sequence:
        return False
    else:
        for i in range(len(sequence) - len(target) + 1):
            if sequence[i] == target[0]:
                subresult = contains_subsequence(target[1:], sequence[i + 1:])
                if subresult:
                    return True
        return False

def contains_subsequence(target, sequence):
    if len(target) == 0:
        return True
    remaining = sequence
    matched = 0
    for t in target:
        idx = 0
        while idx < len(remaining) and remaining[idx] != t:
            idx += 1
        if idx >= len(remaining):
            return False
        else:
            matched += 1
            if matched == len(target):
                return True
            remaining = remaining[idx + 1:]

RESERVED_TOKENS = 10
VOCAB_SIZE = 26
PAD = 0
CLS = 1
SEP = 2
MASK = 3
VOCAB = tuple(range(RESERVED_TOKENS, RESERVED_TOKENS + VOCAB_SIZE))

def neg_example_generation(target_tokens, vocab, exam_seq_len):
    retval = random.choices(vocab, k=exam_seq_len)
    while contains_subsequence(target_tokens, retval):
        retval = random.choices(vocab, k=exam_seq_len)
    return retval

class FindCatDataset(TokenizedDataset):
    def __init__(self, tokenizer_class="bert-base-uncased",
                 total_examples=1000, seqlen=(300,), vocab=VOCAB,
                 target_tokens='cat', prob=0.5,
                 top_position=None,
                 fixed_positions=None,
                 eval=False, multi_target=True, seed=42, data_file_name=None):
        super().__init__(tokenizer_class=tokenizer_class)
        random.seed(seed)

        self.prob = prob
        self.multi_target = multi_target
        self.seqlen = seqlen
        self.vocab = vocab
        self.target_tokens = [[ord(x) - ord('a') + RESERVED_TOKENS for x in y] for y in target_tokens.split('_')]
        self.fixed_positions = fixed_positions
        self.total_examples = total_examples
        self.top_position = top_position
        if data_file_name is None:
            self.data = self.data_generation()
        else:
            self.data = self.load_data_from_file(data_file_name=data_file_name)

    def _generate_example(self):
        target = int(random.random() < self.prob)
        target_tokens = random.choice(self.target_tokens)
        # print(target_tokens)
        ##=========
        exam_seq_len = np.random.choice(self.seqlen, 1)[0]
        ##=========
        # positions = []
        retval = neg_example_generation(target_tokens=target_tokens, exam_seq_len=exam_seq_len, vocab=self.vocab)
        # if target == 1:
        #     # if self.multi_target:
        #     #     retval = random.choices(self.vocab, k=exam_seq_len)
        #     if self.fixed_positions is not None:
        #         assert len(self.fixed_positions) == len(target_tokens)
        #         positions = self.fixed_positions
        #     else:
        #         if self.top_position is None:
        #             # positions = sorted(random.choices(list(range(exam_seq_len)), k=len(target_tokens)))
        #             positions = sorted(random.sample(list(range(exam_seq_len)), k=len(target_tokens)))
        #         else:
        #             top_len = self.top_position if self.top_position < exam_seq_len else exam_seq_len
        #             # positions = sorted(random.choices(list(range(top_len)), k=len(target_tokens)))
        #             positions = sorted(random.sample(list(range(top_len)), k=len(target_tokens)))
        #
        #     for p_i, p in enumerate(positions):
        #         retval[p] = target_tokens[p_i]

        positions = []
        if target == 1:
            if self.fixed_positions is not None:
                assert len(self.fixed_positions) == len(target_tokens)
                positions = self.fixed_positions
            else:
                if self.top_position is None:
                    # positions = sorted(random.choices(list(range(exam_seq_len)), k=len(target_tokens)))
                    positions = sorted(random.sample(list(range(exam_seq_len)), k=len(target_tokens)))
                else:
                    top_len = self.top_position if self.top_position < exam_seq_len else exam_seq_len
                    # positions = sorted(random.choices(list(range(top_len)), k=len(target_tokens)))
                    positions = sorted(random.sample(list(range(top_len)), k=len(target_tokens)))

            for p_i, p in enumerate(positions):
                retval[p] = target_tokens[p_i]

        # return FindCatExample(
        #     tokenized_sentences=[FindCatSentence(sentence_idx=s_i, token_ids=[s]) for s_i, s in enumerate(retval)],
        #     target_tokens=target_tokens, positions=positions, label=target)
        return FindCatExample(
            tokenized_sentences=[FindCatSentence(sentence_idx=s_i, token_ids=[s]) for s_i, s in enumerate(retval)],
            target_tokens=target_tokens, positions=positions, label=target)

    def __len__(self):
        return len(self.data)

    def __getitem__(self, key):
        return self.data[key]

    def data_generation(self):
        data = [self._generate_example() for _ in tqdm(range(self.total_examples))]
        return data

    def save_data_into_file(self, data_file_name):
        with gzip.open(data_file_name, 'wb') as fout:
            pickle.dump(self.data, fout)
        print('save {} records into {}'.format(len(self.data), data_file_name))

    def load_data_from_file(self, data_file_name):
        with gzip.open(data_file_name, 'rb') as fin:
            data = pickle.load(fin)
        print('load {} records from {}'.format(len(data), data_file_name))
        return data

def find_cat_collate_fn(examples):
    ex_lens = [3 + len(ex.target_tokens) + len(ex.tokenized_sentences) for ex in examples]
    max_ex_len = max(ex_lens)

    batched_input = np.full((len(examples), max_ex_len), -1, dtype=np.int64)
    batched_labels = np.zeros((len(examples),), dtype=np.int64)

    for ex_i, ex in enumerate(examples):
        # print(ex.target_tokens)
        batched_input[ex_i, :ex_lens[ex_i]] = [CLS] + ex.target_tokens + [SEP] + [s.token_ids[0] for s in
                                                                                ex.tokenized_sentences] + [SEP]
        batched_labels[ex_i] = ex.label

    retval = {
        'input': batched_input,
        'labels': batched_labels
    }
    retval = {k: torch.from_numpy(retval[k]) for k in retval}
    return retval

def find_cat_probe_collate_fn(examples):
    ex_lens = [3 + len(ex.target_tokens) + len(ex.tokenized_sentences) for ex in examples]
    max_ex_len = max(ex_lens)

    batched_input = np.full((len(examples), max_ex_len), -1, dtype=np.int64)
    batched_labels = np.zeros((len(examples),), dtype=np.int64)
    batched_seq_labels = np.zeros((len(examples), max_ex_len), dtype=np.int64)
    batched_seq_mask = np.ones((len(examples), max_ex_len), dtype=np.int64)

    for ex_i, ex in enumerate(examples):
        ##++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        assert ex.label == 1
        # if ex.label == 0:
        #     positions = sorted(random.choices(list(range(len(ex.tokenized_sentences))), k=len(ex.target_tokens)))
        #     for p_i, p in enumerate(positions):
        #         ex.tokenized_sentences[p].token_ids[0] = ex.target_tokens[p_i]
        #     ex.positions = positions
        #     ex.label = 1
        ##++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        batched_input[ex_i, :ex_lens[ex_i]] = [CLS] + ex.target_tokens + [SEP] + [s.token_ids[0] for s in
                                                                                ex.tokenized_sentences] + [SEP]

        batched_labels[ex_i] = ex.label
        ex_mask_len = 2 + len(ex.target_tokens)
        mask_position = [_ for _ in range(ex_mask_len)] + [_ for _ in range(ex_mask_len + len(ex.tokenized_sentences), max_ex_len)]

        target_position = [_ + ex_mask_len for _ in ex.positions]
        batched_seq_labels[ex_i, target_position] = 1
        assert batched_seq_labels[ex_i].sum() == len(ex.target_tokens)
        batched_seq_mask[ex_i, mask_position] = 0

    retval = {
        'input': batched_input,
        'labels': batched_labels,
        'seq_labels': batched_seq_labels,
        'seq_mask': batched_seq_mask
    }
    retval = {k: torch.from_numpy(retval[k]) for k in retval}
    return retval

def find_cat_validation_fn(ex):
    return (ex.label == 0) or contains_subsequence(ex.target_tokens, [s.token_ids[0] for s in ex.tokenized_sentences])

# if __name__ == "__main__":
#
#     # dataset = FindCatDataset(total_examples=10)
#     #
#     # examples = dataset.data
#     #
#     # print(len(examples))
#     # # for x in examples:
#     # #     print(len(x.tokenized_sentences))
#     #
#     cached_examples_file = 'test.pkl.gz'
#     # # with gzip.open(cached_examples_file, 'wb') as fout:
#     # #     pickle.dump(examples, fout)
#     # # print('save {} records into {}'.format(len(examples), cached_examples_file))
#     #
#     # dataset.save_data_into_file(data_file_name=cached_examples_file)
#
#     dataset = FindCatDataset(data_file_name=cached_examples_file)
#
#
#     # true_count = 0
#     # count = 20000
#     # for _ in tqdm(range(count)):
#     #     x = random.choices(dataset.vocab, k=300)
# #         y = contains_subsequence(target=dataset.target_tokens, sequence=x)
# #         if y:
# #             true_count = true_count + 1
# #         # while y:
# #         #     x = random.choices(dataset.vocab, k=300)
# #         #     y = contains_subsequence(target=dataset.target_tokens, sequence=x)
# #         #     true_count = true_count + 1
# #     print(true_count * 1.0/count)
# #
# #     # dataset.data_generation()
# #     # sdrop_dataset = SentenceDropDataset(dataset, sent_drop_prob=.1,
# #     #                                     example_validate_fn=lambda ex: find_cat_validation_fn(ex, dataset=dataset))
# #     #
# #     # from tqdm import tqdm
# #     # from torch.utils.data import DataLoader
# #     #
# #     # dataloader = DataLoader(sdrop_dataset, batch_size=32, collate_fn=find_cat_collate_fn)
# #     #
# #     # for batch in tqdm(dataloader):
#     #     pass


from unittest import mock
from unittest.mock import MagicMock
from unittest.mock import Mock
from unittest.mock import patch

from glanceclient import exc as glance_exceptions
import jsonschema

from trove.common import clients
from trove.common import exception
from trove.configuration import models as config_models
from trove.datastore import models
from trove.extensions.mgmt.datastores.service import DatastoreVersionController
from trove.tests.unittests import trove_testtools
from trove.tests.unittests.util import util

class TestDatastoreVersionController(trove_testtools.TestCase):
    @classmethod
    def setUpClass(cls):
        util.init_db()
        cls.ds_name = cls.random_name('datastore')
        cls.ds_version_number = '5.7.30'
        models.update_datastore(name=cls.ds_name, default_version=None)

        models.update_datastore_version(
            cls.ds_name, 'test_vr1', 'mysql', cls.random_uuid(), '', 'pkg-1',
            1)
        models.update_datastore_version(
            cls.ds_name, 'test_vr2', 'mysql', cls.random_uuid(), '', 'pkg-1',
            1, version=cls.ds_version_number)

        cls.ds = models.Datastore.load(cls.ds_name)
        cls.ds_version1 = models.DatastoreVersion.load(cls.ds, 'test_vr1')
        cls.ds_version2 = models.DatastoreVersion.load(
            cls.ds, 'test_vr2', version=cls.ds_version_number)
        cls.version_controller = DatastoreVersionController()

        super(TestDatastoreVersionController, cls).setUpClass()

    @classmethod
    def tearDownClass(cls):
        util.cleanup_db()

        super(TestDatastoreVersionController, cls).tearDownClass()

    def test_create_schema(self):
        image_id = self.random_uuid()
        ver_name = self.random_name('dsversion')
        body = {
            "version": {
                "datastore_name": self.ds_name,
                "name": ver_name,
                "datastore_manager": "mysql",
                "image": image_id,
                "image_tags": [],
                "active": True,
                "default": False
            }
        }

        schema = self.version_controller.get_schema('create', body)
        validator = jsonschema.Draft4Validator(schema)

        self.assertTrue(validator.is_valid(body))

    def test_create_schema_too_many_image_tags(self):
        ver_name = self.random_name('dsversion')
        body = {
            "version": {
                "datastore_name": self.ds_name,
                "name": ver_name,
                "datastore_manager": "mysql",
                "image_tags": ['a', 'b', 'c', 'd', 'e', 'f'],
                "active": True,
                "default": False
            }
        }

        schema = self.version_controller.get_schema('create', body)
        validator = jsonschema.Draft4Validator(schema)

        self.assertFalse(validator.is_valid(body))

    def test_create_schema_emptyname(self):
        image_id = self.random_uuid()
        body = {
            "version": {
                "datastore_name": self.ds_name,
                "name": " ",
                "datastore_manager": "mysql",
                "image": image_id,
                "image_tags": [],
                "active": True,
                "default": False
            }
        }
        schema = self.version_controller.get_schema('create', body)
        validator = jsonschema.Draft4Validator(schema)

        self.assertFalse(validator.is_valid(body))

        errors = sorted(validator.iter_errors(body), key=lambda e: e.path)
        self.assertEqual(1, len(errors))
        self.assertEqual("' ' does not match '^.*[0-9a-zA-Z]+.*$'",
                         errors[0].message)

    @patch.object(clients, 'create_glance_client')
    def test_create(self, mock_glance_client):
        image_id = self.random_uuid()
        ver_name = self.random_name('dsversion')
        body = {
            "version": {
                "datastore_name": self.ds_name,
                "name": ver_name,
                "datastore_manager": "mysql",
                "image": image_id,
                "image_tags": [],
                "packages": "test-pkg",
                "active": True,
                "default": True
            }
        }
        output = self.version_controller.create(MagicMock(), body, mock.ANY)
        self.assertEqual(202, output.status)

        new_ver = models.DatastoreVersion.load(self.ds, ver_name)
        self.assertEqual(image_id, new_ver.image_id)
        self.assertEqual(ver_name, new_ver.version)

    @patch.object(clients, 'create_glance_client')
    def test_create_same_version_number(self, mock_glance_client):
        image_id = self.random_uuid()
        ver_name = self.random_name('dsversion')
        body = {
            "version": {
                "datastore_name": self.ds_name,
                "name": ver_name,
                "datastore_manager": "mysql",
                "image": image_id,
                "image_tags": [],
                "packages": "",
                "active": True,
                "default": False,
                "version": self.ds_version_number
            }
        }
        output = self.version_controller.create(MagicMock(), body, mock.ANY)
        self.assertEqual(202, output.status)

        new_ver = models.DatastoreVersion.load(self.ds, ver_name,
                                               version=self.ds_version_number)
        self.assertEqual(image_id, new_ver.image_id)
        self.assertEqual(ver_name, new_ver.name)
        self.assertEqual(self.ds_version_number, new_ver.version)
        self.assertNotEqual(self.ds_version2.id, new_ver.id)

    @patch.object(clients, 'create_glance_client')
    def test_create_by_image_tags(self, mock_create_client):
        ver_name = self.random_name('dsversion')
        body = {
            "version": {
                "datastore_name": self.ds_name,
                "name": ver_name,
                "datastore_manager": "mysql",
                "image_tags": ["trove", "mysql"],
                "active": True,
                "default": True
            }
        }
        mock_client = MagicMock()
        mock_client.images.list.return_value = [{"id": self.random_uuid()}]
        mock_create_client.return_value = mock_client

        output = self.version_controller.create(MagicMock(), body, mock.ANY)
        self.assertEqual(202, output.status)

        mock_client.images.list.assert_called_once_with(
            filters={'tag': ["trove", "mysql"], 'status': 'active'},
            sort='created_at:desc',
            limit=1
        )

        new_ver = models.DatastoreVersion.load(self.ds, ver_name)
        self.assertIsNone(new_ver.image_id)
        self.assertEqual('trove,mysql', new_ver.image_tags)

    @patch.object(clients, 'create_glance_client')
    def test_create_exist(self, mock_glance_client):
        image_id = self.random_uuid()
        ver_name = 'test_vr1'
        body = {
            "version": {
                "datastore_name": self.ds_name,
                "name": ver_name,
                "datastore_manager": "mysql",
                "image": image_id,
                "image_tags": [],
                "packages": "test-pkg",
                "active": True,
                "default": True
            }
        }
        self.assertRaises(
            exception.DatastoreVersionAlreadyExists,
            self.version_controller.create, MagicMock(), body, mock.ANY)

    def test_create_no_image(self):
        ver_name = self.random_name('dsversion')
        body = {
            "version": {
                "datastore_name": self.ds_name,
                "name": ver_name,
                "datastore_manager": "mysql",
                "active": True,
                "default": False
            }
        }
        self.assertRaises(
            exception.BadRequest,
            self.version_controller.create, MagicMock(), body, mock.ANY)

    @patch.object(clients, 'create_glance_client')
    def test_create_image_notfound(self, mock_create_client):
        image_id = self.random_uuid()
        ver_name = self.random_name('dsversion')
        body = {
            "version": {
                "datastore_name": self.ds_name,
                "name": ver_name,
                "datastore_manager": "mysql",
                "image": image_id,
                "active": True,
                "default": False
            }
        }
        mock_client = Mock()
        mock_client.images.get.side_effect = [glance_exceptions.HTTPNotFound()]
        mock_create_client.return_value = mock_client

        self.assertRaises(
            exception.ImageNotFound,
            self.version_controller.create, MagicMock(), body, mock.ANY)

    def test_update_name(self):
        new_name = self.random_name('ds-version-name')
        body = {
            "name": new_name
        }

        orig_ver = models.DatastoreVersion.load(self.ds, self.ds_version1.id)

        output = self.version_controller.edit(MagicMock(), body, mock.ANY,
                                              self.ds_version1.id)
        self.assertEqual(202, output.status)

        updated_ver = models.DatastoreVersion.load(self.ds,
                                                   self.ds_version1.id)

        self.assertEqual(new_name, updated_ver.name)
        self.assertEqual(orig_ver.image_id, updated_ver.image_id)
        self.assertEqual(orig_ver.image_tags, updated_ver.image_tags)
        self.assertEqual(orig_ver.version, updated_ver.version)

    @patch.object(clients, 'create_glance_client')
    def test_update_image(self, mock_create_client):
        new_image = self.random_uuid()
        body = {
            "image": new_image
        }

        output = self.version_controller.edit(MagicMock(), body, mock.ANY,
                                              self.ds_version1.id)
        self.assertEqual(202, output.status)

        updated_ver = models.DatastoreVersion.load(self.ds,
                                                   self.ds_version1.id)
        self.assertEqual(new_image, updated_ver.image_id)

    @patch.object(clients, 'create_glance_client')
    def test_update_image_tags(self, mock_create_client):
        name = self.random_name('dsversion')
        models.update_datastore_version(
            self.ds_name, name, 'mysql', self.random_uuid(), '', '', 1)
        ver = models.DatastoreVersion.load(self.ds, name)

        mock_client = MagicMock()
        mock_client.images.list.return_value = [{"id": self.random_uuid()}]
        mock_create_client.return_value = mock_client

        body = {
            "image_tags": ['trove', 'mysql']
        }

        output = self.version_controller.edit(MagicMock(), body, mock.ANY,
                                              ver.id)
        self.assertEqual(202, output.status)

        updated_ver = models.DatastoreVersion.load(self.ds, ver.id)
        self.assertEqual("", updated_ver.image_id)
        self.assertEqual("trove,mysql", updated_ver.image_tags)

    def test_delete(self):
        name = self.random_name('dsversion')
        models.update_datastore_version(
            self.ds_name, name, 'mysql', self.random_uuid(), '', '', 1)
        ver = models.DatastoreVersion.load(self.ds, name)

        # Add config param for the datastore version. Should be automatically
        # removed.
        param_name = self.random_name('param')
        config_models.create_or_update_datastore_configuration_parameter(
            param_name, ver.id, False, 'string', None, None)

        output = self.version_controller.delete(MagicMock(),
                                                mock.ANY,
                                                ver.id)
        self.assertEqual(202, output.status)

        self.assertRaises(
            exception.DatastoreVersionNotFound,
            models.DatastoreVersion.load_by_uuid, ver.id)

        config_params_cls = config_models.DatastoreConfigurationParameters
        self.assertRaises(
            exception.NotFound,
            config_params_cls.load_parameter_by_name,
            ver.id, param_name)

    def test_index(self):
        output = self.version_controller.index(MagicMock(), mock.ANY)
        self.assertEqual(200, output.status)

        data = output.data(None)
        self.assertGreater(len(data['versions']), 0)

    def test_show(self):
        output = self.version_controller.show(
            MagicMock(), mock.ANY, self.ds_version2.id)
        self.assertEqual(200, output.status)
        self.assertEqual(self.ds_version2.id,
                         output._data['version']['id'])
        self.assertEqual(self.ds_version2.name,
                         output._data['version']['name'])
        self.assertEqual(self.ds_version2.datastore_id,
                         output._data['version']['datastore_id'])
        self.assertEqual(self.ds_version2.datastore_name,
                         output._data['version']['datastore_name'])
        self.assertEqual(self.ds_version2.manager,
                         output._data['version']['datastore_manager'])
        self.assertEqual(self.ds_version2.image_id,
                         output._data['version']['image'])
        self.assertEqual(self.ds_version2.packages.split(','),
                         output._data['version']['packages'])
        self.assertEqual(self.ds_version2.active,
                         output._data['version']['active'])
        self.assertEqual(self.ds_version2.version,
                         output._data['version']['version'])

    def test_show_image_tags(self):
        ver_name = self.random_name('dsversion')
        tags = ['trove', 'mysql']
        models.update_datastore_version(self.ds_name, ver_name, 'mysql', '',
                                        tags, '', 1)
        ver = models.DatastoreVersion.load(self.ds, ver_name)

        output = self.version_controller.show(
            MagicMock(), mock.ANY, ver.id)
        self.assertEqual(200, output.status)

        data = output.data(None)
        self.assertEqual(tags, data['version']['image_tags'])


import json

def read(file_name):
    with open(file_name) as json_data:
        file_content = json.load(json_data)
    temporalData = []
    for r in file_content:
        rule = []
        for p in range(len(r)-1):
            rule.append(set(r[p]))
        rule.append(r[-1])
        temporalData.append(rule)
    file_content = temporalData
    return file_content

def write(file_name,data):
    temporalData = []
    for r in data:
        rule = []
        for p in range( len(r) - 1):
            rule.append(list(r[p]))
        rule.append(r[-1])
        temporalData.append(rule)
    data = temporalData
    with open (file_name, 'w') as f:
        json.dump(data,f)
#write('MEMORYRules.json',[[ {1},{2,3}, '*'], [{3}, {1}, 'A']])
#read('MEMORYRules.json')

def writePresets(file_name,data):
    with open(file_name, 'w') as f:
        json.dump(data,f)

def readPresets(file_name):
    with open(file_name) as json_data:
        file_content = json.load(json_data)
    return file_content

def clean(_files):
    if _files == all:
        files= ['MEMORYpresets.json','MEMORYRules.json']
    else:
        [files.append(f) for f in _files]
    for file in files: write(file,[])


from __future__ import division

import re
import sys

# beta library. supports more configurations that are still being tested.
from google.cloud import speech_v1p1beta1 as speech

from google.oauth2 import service_account

import pyaudio
from six.moves import queue

# read the Google_STT_File.py before. it is much more simple, but has the same idea.

# Audio recording parameters
RATE = 16000
CHUNK = int(RATE / 10)  # 100ms

# get the credentials from the creds file. it is available to download in the google cloud site.
credentials = service_account.Credentials.from_service_account_file('C:/Users/Amit/Documents/ASR_keys/Google_key.json')

class MicrophoneStream(object):
    """Opens a recording stream as a generator yielding the audio chunks."""

    def __init__(self, rate, chunk):
        self._rate = rate
        self._chunk = chunk

        # Create a thread-safe buffer of audio data
        self._buff = queue.Queue()
        self.closed = True

    def __enter__(self):
        self._audio_interface = pyaudio.PyAudio()
        self._audio_stream = self._audio_interface.open(
            format=pyaudio.paInt16,
            # The API currently only supports 1-channel (mono) audio
            # https://goo.gl/z757pE
            channels=1,
            rate=self._rate,
            input=True,
            frames_per_buffer=self._chunk,
            # Run the audio stream asynchronously to fill the buffer object.
            # This is necessary so that the input device's buffer doesn't
            # overflow while the calling thread makes network requests, etc.
            stream_callback=self._fill_buffer,
        )

        self.closed = False

        return self

    def __exit__(self, type, value, traceback):
        self._audio_stream.stop_stream()
        self._audio_stream.close()
        self.closed = True
        # Signal the generator to terminate so that the client's
        # streaming_recognize method will not block the process termination.
        self._buff.put(None)
        self._audio_interface.terminate()

    def _fill_buffer(self, in_data, frame_count, time_info, status_flags):
        """Continuously collect data from the audio stream, into the buffer."""
        self._buff.put(in_data)
        return None, pyaudio.paContinue

    def generator(self):
        while not self.closed:
            # Use a blocking get() to ensure there's at least one chunk of
            # data, and stop iteration if the chunk is None, indicating the
            # end of the audio stream.
            chunk = self._buff.get()
            if chunk is None:
                return
            data = [chunk]

            # Now consume whatever other data's still buffered.
            while True:
                try:
                    chunk = self._buff.get(block=False)
                    if chunk is None:
                        return
                    data.append(chunk)
                except queue.Empty:
                    break

            yield b"".join(data)

def listen_print_loop(responses):
    """Iterates through server responses and prints them.

    The responses passed is a generator that will block until a response
    is provided by the server.

    Each response may contain multiple results, and each result may contain
    multiple alternatives; for details, see https://goo.gl/tjCPAU.  Here we
    print only the transcription for the top alternative of the top result.

    In this case, responses are provided for interim results as well. If the
    response is an interim one, print a line feed at the end of it, to allow
    the next result to overwrite it, until the response is a final one. For the
    final one, print a newline to preserve the finalized transcription.
    """
    for response in responses:
        if not response.results:
            continue

        # The `results` list is consecutive. For streaming, we only care about
        # the first result being considered, since once it's `is_final`, it
        # moves on to considering the next utterance.
        result = response.results[0]

        print(result)

# See http://g.co/cloud/speech/docs/languages
# for a list of supported languages.
language_code = "en-US"  # a BCP-47 language tag

# get the credentials from the creds file. it is available to download in the google cloud site.
client = speech.SpeechClient(credentials=credentials)

# select the configuration.
config = speech.RecognitionConfig(
    encoding=speech.RecognitionConfig.AudioEncoding.LINEAR16,
    sample_rate_hertz=RATE,
    language_code=language_code,
    enable_word_time_offsets=True,
    enable_word_confidence=True,  # this is an example of a configuration only available at the beta library.
)

# make it a streaming config.
streaming_config = speech.StreamingRecognitionConfig(
    config=config, interim_results=True,

)

with MicrophoneStream(RATE, CHUNK) as stream:
    # instantiate the data generator.
    audio_generator = stream.generator()

    # iterate through it.
    requests = (
        speech.StreamingRecognizeRequest(audio_content=content)
        for content in audio_generator
    )

    # streaming_recognize returns a generator.
    responses = client.streaming_recognize(streaming_config, requests)

    # Now, put the responses received.
    listen_print_loop(responses)


import os
from unittest import TestCase

import numpy as num
import pymc3 as pm
import theano.tensor as tt

from beat.backend import NumpyChain, TextChain, check_multitrace, load_multitrace

class TestBackend(TestCase):
    def setUp(self):
        self.data_keys = ["Data", "A", "F", "D", "B", "Hood", "like"]
        number_of_parameters = 5
        self.like_index = self.data_keys.index("like")

        mu1 = num.ones(number_of_parameters) * (1.0 / 2)
        mu2 = -mu1

        stdev = 0.1
        sigma = num.power(stdev, 2) * num.eye(number_of_parameters)
        isigma = num.linalg.inv(sigma)
        dsigma = num.linalg.det(sigma)

        w1 = stdev
        w2 = 1 - stdev

        def two_gaussians(x):
            log_like1 = (
                -0.5 * number_of_parameters * tt.log(2 * num.pi)
                - 0.5 * tt.log(dsigma)
                - 0.5 * (x - mu1).T.dot(isigma).dot(x - mu1)
            )
            log_like2 = (
                -0.5 * number_of_parameters * tt.log(2 * num.pi)
                - 0.5 * tt.log(dsigma)
                - 0.5 * (x - mu2).T.dot(isigma).dot(x - mu2)
            )
            return tt.log(w1 * tt.exp(log_like1) + w2 * tt.exp(log_like2))

        with pm.Model() as self.PT_test:
            for data_key in self.data_keys:
                if data_key != "like":
                    uniform = pm.Uniform(
                        data_key,
                        shape=number_of_parameters,
                        lower=-2.0 * num.ones_like(mu1),
                        upper=2.0 * num.ones_like(mu1),
                        testval=-1.0 * num.ones_like(mu1),
                        transform=None,
                    )
                else:
                    like = pm.Deterministic("tmp", two_gaussians(uniform))
            pm.Potential(self.data_keys[self.like_index], like)

        # create or get test folder to write files.
        self.test_dir_path = os.path.join(os.path.dirname(__file__), "PT_TEST")
        if not os.path.exists(self.test_dir_path):
            try:
                os.mkdir(self.test_dir_path)
            except IOError as e:
                print(e)

        # create data.
        data_increment = 1
        self.lpoint = []
        for data_key in self.data_keys:
            if data_key != "like":
                chain_data = (
                    num.arange(number_of_parameters).astype(num.float) * data_increment
                )
            else:
                chain_data = num.array([10.0]).astype(num.float)
            data_increment += 1
            self.lpoint.append(chain_data)

        self.sample_size = 5
        self.data = []
        self.expected_chain_data = {}
        for i in range(self.sample_size):
            self.data.append(self.lpoint)
        for data_key, chain_data in zip(self.data_keys, self.lpoint):
            data = []
            for i in range(self.sample_size):
                data.append(chain_data)
            self.expected_chain_data[data_key] = num.array(data)

    def test_text_chain(self):

        textchain = TextChain(dir_path=self.test_dir_path, model=self.PT_test)
        textchain.setup(10, 0, overwrite=True)

        # write data to buffer
        draw = 0
        for lpoint in self.data:
            draw += 1
            textchain.write(lpoint, draw)

        textchain.record_buffer()

        for data_key in self.data_keys:
            chain_data = textchain.get_values(data_key)
            data_index = 1
            chain_at = textchain.point(data_index)
            self.assertEqual(
                chain_data.all(), self.expected_chain_data.get(data_key).all()
            )
            self.assertEqual(
                chain_at[data_key].all(),
                self.expected_chain_data.get(data_key)[data_index].all(),
            )

    def test_chain_bin(self):

        numpy_chain = NumpyChain(dir_path=self.test_dir_path, model=self.PT_test)
        numpy_chain.setup(10, 0, overwrite=True)
        print(numpy_chain)
        # write data to buffer
        draw = 0
        for lpoint in self.data:
            draw += 1
            numpy_chain.write(lpoint, draw)

        numpy_chain.record_buffer()

        # print("Var shapes: ", numpy_chain.var_shapes)
        # print("flat names: ", numpy_chain.flat_names)
        # print("Var names: ", numpy_chain.varnames)

        # print("Var shapes: ", numpy_chain.var_shapes)
        # print("flat names: ", numpy_chain.flat_names)
        # print("Var names: ", numpy_chain.varnames)

        for data_key in self.data_keys:
            chain_data = numpy_chain.get_values(data_key)
            data_index = 1
            chain_at = numpy_chain.point(data_index)
            # print(data_key + ": ", chain_data)
            self.assertEqual(
                chain_data.all(), self.expected_chain_data.get(data_key).all()
            )
            self.assertEqual(
                chain_at[data_key].all(),
                self.expected_chain_data.get(data_key)[data_index].all(),
            )

    def test_load_bin_chain(self):
        numpy_chain = NumpyChain(dir_path=self.test_dir_path, model=self.PT_test)
        numpy_chain.setup(5, 0, overwrite=False)
        # print(len(numpy_chain), numpy_chain.data_file())
        data_index = 1
        chain_at = numpy_chain.point(data_index)
        # print(chain_at)
        for data_key in self.data_keys:
            self.assertEqual(
                chain_at[data_key].all(),
                self.expected_chain_data.get(data_key)[data_index].all(),
            )

    def test_load_check_multitrace(self):
        mtrace = load_multitrace(
            self.test_dir_path, varnames=self.PT_test.vars, backend="bin"
        )
        mtrace.point(1)

        corrupted = check_multitrace(mtrace, self.sample_size, 1)
        self.assertEqual(len(corrupted), 0)

#    def tearDown(self):
#        import shutil
#        shutil.rmtree(self.test_dir_path)


from .. import om
from .default_table import DefaultTable
from PyQt5 import Qt

class PointListPickerTableModel(om.signaling_list.DragDropModelBehavior, om.signaling_list.PropertyTableModel):
    pass

class PointListPickerTable(DefaultTable):
    def __init__(self, point_list_picker, model=None, parent=None):
        super().__init__(model, parent)
        self.setWindowTitle('Point Picker')
        self.point_list_picker = point_list_picker
        if model is None:
            self.setModel(PointListPickerTableModel(('x', 'y'), self.point_list_picker.points))
        self.point_list_picker.point_list_replaced.connect(self._on_point_list_replaced)
        self.ignore_selection_change = False
        self.ignore_became_focused = False
        self.point_list_picker.point_is_selected_changed.connect(self._on_point_selection_changed)
        self.selectionModel().selectionChanged.connect(self._on_table_selection_changed)
        self.point_list_picker.point_focused.connect(self._on_point_became_focused)
        self.selectionModel().currentChanged.connect(self._on_table_focus_changed)

    def _on_point_list_replaced(self):
        self.model().signaling_list = self.point_list_picker.points

    def _on_table_selection_changed(self, selected, deselected):
        if not self.ignore_selection_change:
            self.ignore_selection_change = True
            try:
                for midx in selected.indexes():
                    if midx.isValid():
                        self.point_list_picker.point_items[self.point_list_picker.points[midx.row()]].setSelected(True)
                for midx in deselected.indexes():
                    if midx.isValid():
                        self.point_list_picker.point_items[self.point_list_picker.points[midx.row()]].setSelected(False)
            finally:
                self.ignore_selection_change = False

    def _on_point_selection_changed(self, point, isSelected):
        if not self.ignore_selection_change:
            self.ignore_selection_change = True
            try:
                m = self.model()
                sm = self.selectionModel()
                idx = self.point_list_picker.points.index(point)
                flags = Qt.QItemSelectionModel.Rows
                sm.select(m.index(idx, 0), flags | Qt.QItemSelectionModel.Select if isSelected else flags | Qt.QItemSelectionModel.Deselect)
            finally:
                self.ignore_selection_change = False

    def _on_table_focus_changed(self, focused_midx, unfocused_midx):
        if focused_midx.isValid():
            if not self.ignore_became_focused:
                self.ignore_became_focused = True
                try:
                    self.point_list_picker.point_items[self.point_list_picker.points[focused_midx.row()]].setFocus()
                finally:
                    self.ignore_became_focused = False

    def _on_point_became_focused(self, point):
        if not self.ignore_became_focused:
            self.ignore_became_focused = True
            try:
                m = self.model()
                sm = self.selectionModel()
                idx = self.point_list_picker.points.index(point)
                sm.setCurrentIndex(m.index(idx, 0), Qt.QItemSelectionModel.Current)
            finally:
                self.ignore_became_focused = False


"""fix dates

Revision ID: b73363ca9f31
Revises: 069d53cf594f
Create Date: 2020-12-13 12:53:43.610801

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'b73363ca9f31'
down_revision = '069d53cf594f'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table("booking") as batch_op:
        batch_op.alter_column(
            'final_date',
            existing_type=sa.DATETIME(),
            type_=sa.Date(),
            existing_nullable=False,
        )
        batch_op.alter_column(
            'initial_date',
            existing_type=sa.DATETIME(),
            type_=sa.Date(),
            existing_nullable=False,
        )
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table("booking") as batch_op:
        batch_op.alter_column(
            'initial_date',
            existing_type=sa.Date(),
            type_=sa.DATETIME(),
            existing_nullable=False,
        )
        batch_op.alter_column(
            'final_date',
            existing_type=sa.Date(),
            type_=sa.DATETIME(),
            existing_nullable=False,
        )
    # ### end Alembic commands ###


#! /usr/bin/env python

# Example app

import os

import dash_core_components as dcc
import dash_html_components as html

from dash import Dash
from dash.dependencies import Input, Output
from flask import Flask, session

from dash_google_auth import GoogleOAuth

# configure app
server = Flask(__name__)
app = Dash(
    __name__,
    server=server,
    url_base_pathname='/',
    auth='auth',
)
app.config['suppress_callback_exceptions']=True

# configure google oauth using environment variables
server.secret_key = os.environ.get("FLASK_SECRET_KEY", "supersekrit")
server.config["GOOGLE_OAUTH_CLIENT_ID"] = os.environ["GOOGLE_OAUTH_CLIENT_ID"]
server.config["GOOGLE_OAUTH_CLIENT_SECRET"] = os.environ["GOOGLE_OAUTH_CLIENT_SECRET"]

# allow for insecure transport for local testing (remove in prod)
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

# designate list of authorized emails
authorized_emails = [
    "lucas.chapin@gmail.com",
    "1234@example.com",
]

auth = GoogleOAuth(
    app,
    authorized_emails,
)

@server.route("/")
def MyDashApp():
    return app.index()

app.layout = html.Div(children=[
    html.H1(children="Private Dash App"),

    html.Div(id='placeholder', style={'display':'none'}),
    html.Div(id='welcome'),

    dcc.Graph(
        id='example-graph',
        figure={
            'data': [
                {'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
                {'x': [1, 2, 3], 'y': [2, 4, 6], 'type': 'bar', 'name': 'Montreal'},
            ],
            'layout': {
                'title': 'Dash Data Visualization'
            }
        }
    )
])

@app.callback(
    Output('welcome', 'children'),
    [Input('placeholder', 'value')]
)
def on_load(value):
    return "Welcome, {}!".format(session['email'])

if __name__ == '__main__':
    app.run_server(host='localhost')


# -*- coding: utf-8 -*-
"""
Created on Tue Jan 14 15:56:57 2020

@author: AdminIT
"""

from sklearn.ensemble import RandomForestClassifier

clf = RandomForestClassifier(random_state=0)
X = [[ 1,  2,  3],[11, 12, 13]]
y = [0, 1]  # classes of each sample
clf.fit(X, y)


import pandas as pd
from typing import NamedTuple, Union, Dict, Tuple, List
from rich.table import Table

def current_cluster_names(cluster_names: Dict[int, str]) -> List[str]:
    return list(sorted(cluster_names.values()))

def get_sorted_cluster_ids(df: pd.DataFrame, cluster_column: str) -> List[str]:
    return sorted(
        df[cluster_column].astype(str).unique(),
        key=lambda d: str(d).zfill(5),
    )

def cluster_counts(df: pd.DataFrame, cluster_column: str) -> pd.DataFrame:
    counts = df[cluster_column].value_counts().rename("Count")
    pcts = df[cluster_column].value_counts(normalize=True).rename("Pct")
    pcts_cumulative = pcts.cumsum().rename("Cumulative Pct")
    result = (
        pd.concat(
            (
                counts,
                pcts,
                pcts_cumulative,
            ),
            axis=1,
        )
        .reset_index()
        .rename(columns={"index": "Cluster ID"})
    )
    return result

def build_summary_df(
    df: pd.DataFrame, cluster_column: str, cluster_names: Dict[int, str]
) -> pd.DataFrame:
    summary_df = cluster_counts(df, cluster_column)
    summary_df["Label"] = summary_df["Cluster ID"].map(cluster_names).fillna("")
    return summary_df

def table_str_fmt(n: Union[float, int]) -> str:
    return f"{n*100:.1f}" if isinstance(n, float) else str(n)

class LabelingSummaryStats(NamedTuple):
    cluster_count_labeled: int
    cluster_pct_labeled: float
    examples_count_labeled: int
    examples_pct_labeled: float

    def strfmt(self, attr: str) -> str:
        n = getattr(self, attr)
        return table_str_fmt(n)

def get_labeling_summary_stats(summary_df: pd.DataFrame) -> LabelingSummaryStats:
    labeled_summary_df = summary_df.query("Label != ''")
    summary_stats = labeled_summary_df[["Pct", "Count"]].sum()
    cluster_count_labeled = len(labeled_summary_df)
    cluster_pct_labeled = cluster_count_labeled / len(summary_df)
    examples_count_labeled = int(summary_stats["Count"])
    examples_pct_labeled = summary_stats["Pct"]
    return LabelingSummaryStats(
        cluster_count_labeled,
        cluster_pct_labeled,
        examples_count_labeled,
        examples_pct_labeled,
    )

def build_rich_cluster_summary_table(summary_df: pd.DataFrame) -> Table:
    cluster_table = Table(title="Cluster Label Summary")
    for column in summary_df.columns:
        cluster_table.add_column(column)
    for row in summary_df.itertuples():
        cluster_table.add_row(*[table_str_fmt(i) for i in row[1:]])
    return cluster_table

def build_rich_stats_table(summary_stats: LabelingSummaryStats) -> Table:
    summary_table = Table(title="Overall Labeling Statistics")
    summary_table.add_column("Element")
    summary_table.add_column("Count")
    summary_table.add_column("Percent")
    summary_table.add_row(
        "Clusters",
        summary_stats.strfmt("cluster_count_labeled"),
        summary_stats.strfmt("cluster_pct_labeled"),
    )
    summary_table.add_row(
        "Rows",
        summary_stats.strfmt("examples_count_labeled"),
        summary_stats.strfmt("examples_pct_labeled"),
    )
    return summary_table

def overview(
    df: pd.DataFrame, cluster_column: str, cluster_names: Dict[int, str]
) -> Tuple[Table, Table]:
    summary_df = build_summary_df(df, cluster_column, cluster_names)
    summary_stats = get_labeling_summary_stats(summary_df)
    cluster_table = build_rich_cluster_summary_table(summary_df)
    summary_table = build_rich_stats_table(summary_stats)
    return (cluster_table, summary_table)