import itertools
import math
from functools import partial

import matplotlib.pyplot as plt
import numpy as np
import torch

#---------------------------------------------------------#
#   将图像转换成RGB图像，防止灰度图在预测时报错。
#   代码仅仅支持RGB图像的预测，所有其它类型的图像都会转化成RGB
#---------------------------------------------------------#
def cvtColor(image):
    if len(np.shape(image)) == 3 and np.shape(image)[2] == 3:
        return image
    else:
        image = image.convert('RGB')
        return image

#----------------------------------------#
#   预处理训练图片
#----------------------------------------#
def preprocess_input(x):
    x /= 255
    x -= 0.5
    x /= 0.5
    return x

def postprocess_output(x):
    x *= 0.5
    x += 0.5
    x *= 255
    return x

def show_result(num_epoch, net, device):
    test_images = net.sample(4, device)

    size_figure_grid = 2
    fig, ax = plt.subplots(size_figure_grid, size_figure_grid, figsize=(5, 5))
    for i, j in itertools.product(range(size_figure_grid), range(size_figure_grid)):
        ax[i, j].get_xaxis().set_visible(False)
        ax[i, j].get_yaxis().set_visible(False)
    for k in range(2 * 2):
        i = k // 2
        j = k % 2
        ax[i, j].cla()
        ax[i, j].imshow(np.uint8(postprocess_output(test_images[k].cpu().data.numpy().transpose(1, 2, 0))))

    label = 'Epoch {0}'.format(num_epoch)
    fig.text(0.5, 0.04, label, ha='center')
    plt.savefig("results/train_out/epoch_" + str(num_epoch) + "_results.png")
    plt.close('all')  #避免内存泄漏

def show_config(**kwargs):
    print('Configurations:')
    print('-' * 70)
    print('|%25s | %40s|' % ('keys', 'values'))
    print('-' * 70)
    for key, value in kwargs.items():
        print('|%25s | %40s|' % (str(key), str(value)))
    print('-' * 70)

#---------------------------------------------------#
#   获得学习率
#---------------------------------------------------#
def get_lr(optimizer):
    for param_group in optimizer.param_groups:
        return param_group['lr']

def get_lr_scheduler(lr_decay_type, lr, min_lr, total_iters, warmup_iters_ratio = 0.05, warmup_lr_ratio = 0.1, no_aug_iter_ratio = 0.05, step_num = 10):
    def yolox_warm_cos_lr(lr, min_lr, total_iters, warmup_total_iters, warmup_lr_start, no_aug_iter, iters):
        if iters <= warmup_total_iters:
            # lr = (lr - warmup_lr_start) * iters / float(warmup_total_iters) + warmup_lr_start
            lr = (lr - warmup_lr_start) * pow(iters / float(warmup_total_iters), 2) + warmup_lr_start
        elif iters >= total_iters - no_aug_iter:
            lr = min_lr
        else:
            lr = min_lr + 0.5 * (lr - min_lr) * (
                1.0 + math.cos(math.pi* (iters - warmup_total_iters) / (total_iters - warmup_total_iters - no_aug_iter))
            )
        return lr

    def step_lr(lr, decay_rate, step_size, iters):
        if step_size < 1:
            raise ValueError("step_size must above 1.")
        n       = iters // step_size
        out_lr  = lr * decay_rate ** n
        return out_lr

    if lr_decay_type == "cos":
        warmup_total_iters  = min(max(warmup_iters_ratio * total_iters, 1), 3)
        warmup_lr_start     = max(warmup_lr_ratio * lr, 1e-6)
        no_aug_iter         = min(max(no_aug_iter_ratio * total_iters, 1), 15)
        func = partial(yolox_warm_cos_lr ,lr, min_lr, total_iters, warmup_total_iters, warmup_lr_start, no_aug_iter)
    else:
        decay_rate  = (min_lr / lr) ** (1 / (step_num - 1))
        step_size   = total_iters / step_num
        func = partial(step_lr, lr, decay_rate, step_size)

    return func

def set_optimizer_lr(optimizer, lr_scheduler_func, epoch):
    lr = lr_scheduler_func(epoch)
    for param_group in optimizer.param_groups:
        param_group['lr'] = lr


from typing import List
import pygame
from random import seed, randint

from .point import Point
from .helpclass import Settings
from .room import Room
from .helpclass import Colors as C
from .helpclass import Cell

class Map:
    # RGBA
    BACKGROUND_COLOR = (200, 50, 10)
    VOID = (150, 150, 150)
    PATH = (20, 150, 30)
    BORDER = (200, 200, 200)

    def __init__(self, columns: int, rows: int):
        seed()
        self._columns = columns
        self._rows = rows
        self._surf = pygame.Surface((columns * Cell.WIDTH, rows * Cell.HEIGHT))
        self._surf.fill(self.BACKGROUND_COLOR)
        self._rect = self._surf.get_rect()
        self._map = {}
        self._rooms = []
        self.clear()

    def add_room(self, room: Room):
        self._rooms.append(room)

    def change_cell(self, point: Point, status: int):
        if not self.in_range(point):
            raise IndexError
        self._map[point.x, point.y] = status

    def clear(self, status=0):
        self._map = {}
        for x in range(self._columns):
            for y in range(self._rows):
                self._map[x, y] = status

    def draw(self):
        self._surf.fill(C.DARK)
        self.draw_grid()
        for room in self._rooms:
            self._surf.blit(room.surface, room.rect)
        pygame.draw.rect(self._surf, 'white', (0, 0, self._columns * Cell.WIDTH-2, self._rows * Cell.HEIGHT-2), 1)
        return self._surf

    def draw_grid(self):
        void = pygame.Surface((Cell.WIDTH, Cell.HEIGHT))
        path = pygame.Surface((Cell.WIDTH, Cell.HEIGHT))
        void.fill(self.VOID)
        path.fill(self.PATH)
        pygame.draw.rect(void, self.BORDER, void.get_rect(), 1)
        pygame.draw.rect(path, self.BORDER, path.get_rect(), 1)
        self._surf.fill(self.BACKGROUND_COLOR)
        for cell in self._map:
            x, y = cell
            x1 = x * Cell.WIDTH
            x2 = Cell.WIDTH
            y1 = y * Cell.HEIGHT
            y2 = Cell.HEIGHT
            if self._map[cell] == 0:
                self._surf.blit(void, ((x1, y1), (x2, y2)))
            else:
                self._surf.blit(path, ((x1, y1), (x2, y2)))
        return self._surf

    @property
    def rect(self):
        return self._rect

    @property
    def surf(self):
        return self._surf

    @property
    def map(self):
        return self._map

    def in_range(self, point: Point):
        height = self._rows
        width = self._columns
        return point.x in range(width) and point.y in range(height)

    def __init_surf(self):
        width = self._columns * Cell.WIDTH
        height = self._rows * Cell.HEIGHT
        self._surf = pygame.Surface((width, height))
        self._surf.fill((200, 50, 10))
        self._rect = self._surf.get_rect()


# This file evaluates different models on test dataset
import pandas as pd
import numpy as np
from sklearn import svm
from sklearn.metrics import roc_curve
from sklearn.metrics import confusion_matrix

from matplotlib import pyplot as plt

def roc_drawer(features=None, normalized_mode="thigh_len"):
    """
    this function generates the plot for roc curve, models are svm based on different normalized data
    :param features: features chosen to train the model
    :param normalized_mode: how the data is normalized, e.g. "thigh_len"
    :return: plot TP rate, FP rate, confusion matrix
    """
    if features is None:
        features = ['0x', '0y', '1x', '1y', '2x', '2y', '3x', '3y', '5x', '5y', '6x', '6y', '8x', '8y', '9x', '9y',
                    '11x', '11y', '12x', '12y']

    # read set
    if normalized_mode == "thigh_len":
        ADL_train = pd.read_csv("../data/normalized/ADLNormThigh.csv", index_col=0)
        Fall_train = pd.read_csv("../data/normalized/FallNormThigh.csv", index_col=0)
        ADL_test = pd.read_csv("../data/normalized/ADLNormThighTest.csv", index_col=0)
        Fall_test = pd.read_csv("../data/normalized/FallNormThighTest.csv", index_col=0)
    elif normalized_mode == "torso_box":
        ADL_train = pd.read_csv("../data/normalized/ADLNormTorso.csv", index_col=0)
        Fall_train = pd.read_csv("../data/normalized/FallNormTorso.csv", index_col=0)
        ADL_test = pd.read_csv("../data/normalized/ADLNormTorsoTest.csv", index_col=0)
        Fall_test = pd.read_csv("../data/normalized/FallNormTorsoTest.csv", index_col=0)
    else:
        ADL_train = pd.read_csv("../data/normalized/ADLNormNone.csv", index_col=0)
        Fall_train = pd.read_csv("../data/normalized/FallNormNone.csv", index_col=0)
        ADL_test = pd.read_csv("../data/normalized/ADLNormNoneTest.csv", index_col=0)
        Fall_test = pd.read_csv("../data/normalized/FallNormNoneTest.csv", index_col=0)

    # generate the training set
    ADL_train = ADL_train[features]
    ADL_train = np.array(ADL_train).tolist()
    false_num = len(ADL_train)

    Fall_train = Fall_train[features]
    Fall_train = np.array(Fall_train).tolist()
    true_num = len(Fall_train)

    training_set = ADL_train + Fall_train
    training_label = []

    for i in range(false_num):
        training_label.append(0)
    for i in range(true_num):
        training_label.append(1)

    # generate test set
    ADL_test = ADL_test[features]
    ADL_test = np.array(ADL_test).tolist()
    false_num = len(ADL_test)

    Fall_test = Fall_test[features]
    Fall_test = np.array(Fall_test).tolist()
    true_num = len(Fall_test)

    test_set = ADL_test + Fall_test
    test_label = []

    for i in range(false_num):
        test_label.append(0)
    for i in range(true_num):
        test_label.append(1)

    svc = svm.SVC()
    svc.fit(training_set, training_label)
    scores = svc.decision_function(test_set)
    fpr, tpr, thresholds = roc_curve(test_label, scores)

    label_pred = svc.predict(test_set)
    metric = confusion_matrix(test_label, label_pred)

    return fpr, tpr, metric

def confusion_metric_drawer(metric_array, plt_name):
    TP = metric_array[1][1]
    FP = metric_array[0][1]
    FN = metric_array[1][0]
    TN = metric_array[0][0]

    accuracy = (TP + TN) / (TP + TN + FP + FN)
    precision = TP / (TP + FP)
    recall = TP / (TP + FN)

    fig, ax = plt.subplots(figsize=(3.5, 6))
    ax.matshow(metric_array, cmap=plt.cm.Blues, alpha=0.3)
    for i in range(metric_array.shape[0]):
        for j in range(metric_array.shape[1]):
            ax.text(x=j, y=i, s=metric_array[i, j], va='center', ha='center')
    plt.xlabel('predicted label')
    plt.ylabel('true label')
    font = {'color': 'red',
            'size': 10,
            'family': 'Times New Roman', }
    plt.text(-0.5, -1.5, 'Precision: '+str(precision), fontdict=font)
    plt.text(-0.5, -1, 'Recall: '+str(recall), fontdict=font)

    plt.savefig(plt_name)
    plt.show()
    plt.cla()

fpr_thigh, tpr_thigh, metric_thigh = roc_drawer(normalized_mode="thigh_len")
fpr_torso, tpr_torso, metric_torso = roc_drawer(normalized_mode="torso_box")
fpr_none, tpr_none, metric_none = roc_drawer(normalized_mode="none")

# draw roc curve
plt.plot(fpr_thigh, tpr_thigh, color='cyan', label='thigh')
plt.plot(fpr_torso, tpr_torso, color='red', label='torso')
plt.plot(fpr_none, tpr_none, color='magenta', label='none')
plt.legend()
plt.xlim([0.0, 1.05])
plt.ylim([0.0, 1.05])
plt.title('ROC curves for fall detection classifier')
plt.xlabel('False Positive Rate (1 - Specificity)')
plt.ylabel('True Positive Rate (Sensitivity)')
plt.grid(True)
plt.savefig("../output/roc_curves.png")
plt.show()
plt.cla()

# draw confusion matrix
confusion_metric_drawer(metric_thigh, "../output/metric_thigh.png")
confusion_metric_drawer(metric_torso, "../output/metric_torso.png")
confusion_metric_drawer(metric_none, "../output/metric_none.png")


#!/usr/bin/env python3

from time import sleep
import rospy
from std_msgs.msg import String
import json
import tf
from lib.src.transformation_t import TransformationT
import time

# ARM global states-------------------
arm_initial_pose = 0
arm_pose_goal = 0
arm_joints_goal = 0

# GRIPPER global states------------------------
gripper_closed = 0
have_object = 0
gripper_active = 0

def gripper_response_callback(data):
    global arm_initial_pose
    global have_object
    global gripper_closed
    global gripper_active

    if data.data == "No object detected.":
        have_object = 0
        gripper_closed = not gripper_closed
    elif data.data == "Object detected.":
        have_object = 1
        gripper_closed = not gripper_closed
    elif data.data == "Gripper is now active! Ready to receive commands.":
        gripper_active = 1

def arm_response_callback(data):
    global arm_initial_pose
    global arm_pose_goal
    global arm_joints_goal
    global gripper_active

    if data.data == "Arm is now at initial pose.":
        arm_initial_pose = 1

        if gripper_active == 0:
            # -----------------GRIPPER ACTIVATION------------------------------
            my_dict_ = {'action': 'init'}
            encoded_data_string_ = json.dumps(my_dict_)
            rospy.loginfo(encoded_data_string_)
            pub_gripper.publish(encoded_data_string_)
            # ----------------------------------------------------------------------

    elif data.data == "Arm is now at requested pose goal.":
        arm_pose_goal = 1
    elif data.data == "Arm is now at requested joints state goal.":
        arm_joints_goal = 1

def wait_for_action_to_end(state):
    while state == 0:
        time.sleep(0.1)

def gripper_open_fast():
    # values = [position, speed, force]
    my_dict = {'action': 'move', 'values': [0, 255, 0]}
    encoded_data_string = json.dumps(my_dict)
    # rospy.loginfo(encoded_data_string)
    pub_gripper.publish(encoded_data_string)

def gripper_close_fast():
    # values = [position, speed, force]
    my_dict = {'action': 'move', 'values': [255, 255, 0]}
    encoded_data_string = json.dumps(my_dict)
    # rospy.loginfo(encoded_data_string)
    pub_gripper.publish(encoded_data_string)

def move_arm_to_initial_pose():
    global arm_initial_pose
    arm_initial_pose = 0

    # -----------------ARM INITIAL POSE------------------------------
    arm_initial_pose_dict = {'action': 'move_to_initial_pose'}
    encoded_data_string_initial_pose = json.dumps(arm_initial_pose_dict)
    pub_arm.publish(encoded_data_string_initial_pose)
    # -------------------------------------------------------------------

def move_arm_to_pose_goal(x, y, z, q1, q2, q3, q4):
    global arm_pose_goal
    arm_pose_goal = 0

    _arm_dict = {'action': 'move_to_pose_goal', 'trans': [x, y, z],
                'quat': [q1, q2, q3, q4]}
    _encoded_data_string = json.dumps(_arm_dict)
    pub_arm.publish(_encoded_data_string)

def move_arm_to_joints_state(j1, j2, j3, j4, j5, j6):
    global arm_joints_goal
    arm_joints_goal = 0

    _arm_dict_ = {'action': 'move_to_joints_state',
                'joints': [j1, j2, j3, j4, j5, j6]}
    _encoded_data_string_ = json.dumps(_arm_dict_)
    pub_arm.publish(_encoded_data_string_)

if __name__ == '__main__':
    rospy.init_node('test_sequence', anonymous=True)

    rospy.Subscriber("gripper_response", String, gripper_response_callback)
    pub_gripper = rospy.Publisher('gripper_request', String, queue_size=10)

    rospy.Subscriber("arm_response", String, arm_response_callback)
    pub_arm = rospy.Publisher('arm_request', String, queue_size=10)

    rate = rospy.Rate(10.0)  # 10hz

    sleep(2)

    move_arm_to_initial_pose()

    while arm_initial_pose == 0:
        time.sleep(0.1)

    print("Now Im at initial pose!")

    while gripper_active == 0:
        time.sleep(0.1)

    print("Now the gripper is activated!")

    # data: "{\"action\": \"move_to_pose_goal\", \"trans\": [0.6692778572599781, -0.44860797032168986,\
    #   \ 0.49245419163280646], \"quat\": [-0.6795354166577906, 0.7324247360486474, -0.03131992696621351,\
    #   \ 0.02836698268450892]}"

    # -----------------ARM MOVE TO WOOD-BLOCK------------------------------
    # sleep(5)
    arm_dict = {'action': 'move_to_pose_goal', 'trans': [0.6692778572599781, -0.44860797032168986, 0.49245419163280646],
                'quat': [-0.6795354166577906, 0.7324247360486474, -0.03131992696621351, 0.02836698268450892]}
    encoded_data_string = json.dumps(arm_dict)
    pub_arm.publish(encoded_data_string)
    # ----------------------------------------------------------------------

    while arm_pose_goal == 0:
        time.sleep(0.1)

    print ("Moved to Wood Block")

    # -----------------ARM MOVE DOWN TO WOOD-BLOCK------------------------------
    move_arm_to_pose_goal(0.6692778572599781, -0.44860797032168986, 0.49245419163280646 - 0.2, -0.6795354166577906, 0.7324247360486474,
                          -0.03131992696621351,
                          0.02836698268450892)
    # ----------------------------------------------------------------------

    while arm_pose_goal == 0:
        time.sleep(0.1)

    print("Moved DOWN to Wood Block")

    gripper_close_fast()

    while gripper_closed == 0:
        time.sleep(0.1)

    print("gripper is closed!")
    #
    # # -----------------ARM MOVE ABOVE THE FINAL BOX------------------------------
    # # arm_joints_goal = 0
    # move_arm_to_joints_state(0.33516550064086914, -1.163656548862793, 1.3741701284991663,
    #                                        -1.8040539226927699, -1.5384181181537073, 0.3482170104980469)
    # # ----------------------------------------------------------------------
    #
    # while arm_joints_goal == 0:
    #     time.sleep(0.1)
    #
    # print("Now I arrived!")
    #
    #

    rospy.spin()


"""
========================================================================================
So sánh các thuật toán phát hiện dị thường để phát hiện ngoại lệ trên bộ dữ liệu đồ chơi
========================================================================================
Ví dụ này cho thấy các đặc điểm của các thuật toán phát hiện dị thường khác nhau trên
các bộ dữ liệu 2D. Các bộ dữ liệu chứa một hoặc hai chế độ (vùng có mật độ cao) để
minh họa khả năng của thuật toán đối phó với dữ liệu đa phương thức.
"""
# Đối với mỗi tập dữ liệu, 15% mẫu được tạo ra dưới dạng nhiễu đồng nhất ngẫu nhiên.
# Tỷ lệ này là giá trị được cung cấp cho tham số nu của OneClassSVM và tham số ô nhiễm
# của các thuật toán phát hiện ngoại lệ khác. Ranh giới quyết định giữa các ngoại lệ
# và ngoại lệ được hiển thị màu đen ngoại trừ Yếu tố ngoại lệ cục bộ (LOF) vì nó không
# có phương pháp dự đoán nào được áp dụng trên dữ liệu mới khi được sử dụng để phát hiện
# ngoại lệ.
#
# Sklearn.svm.OneClassSVM được biết là nhạy cảm với các ngoại lệ và do đó không hoạt động tốt
# để phát hiện ngoại lệ. Công cụ ước tính này phù hợp nhất để phát hiện tính mới khi tập huấn
# luyện không bị ô nhiễm bởi các ngoại lệ. Điều đó nói rằng, phát hiện ngoại lệ ở chiều cao
# hoặc không có bất kỳ giả định nào về phân phối dữ liệu bên trong là rất khó khăn và một SVM
# một lớp có thể cho kết quả hữu ích trong các tình huống này tùy thuộc vào giá trị của siêu
# đường kính của nó.
#
# sklearn.covariance.EllipticEnvel giả sử dữ liệu là Gaussian và học một hình elip. Do đó, nó
# xuống cấp khi dữ liệu không phải là không chính thống. Tuy nhiên, lưu ý rằng công cụ ước tính
# này là mạnh mẽ đối với các ngoại lệ.
#
# sklearn.ensemble.IsolationForest và sklearn.neighbor.LocalOutlierFactor dường như hoạt động khá
# tốt đối với các tập dữ liệu đa phương thức. Ưu điểm của sklearn.neighbor.LocalOutlierFactor so
# với các công cụ ước tính khác được hiển thị cho tập dữ liệu thứ ba, trong đó hai chế độ có mật
# độ khác nhau. Ưu điểm này được giải thích bởi khía cạnh cục bộ của LOF, có nghĩa là nó chỉ so sánh
# điểm bất thường của một mẫu với điểm của các nước láng giềng.
#
# Cuối cùng, đối với tập dữ liệu cuối cùng, thật khó để nói rằng một mẫu bất thường hơn một mẫu
# khác vì chúng được phân phối đồng đều trong một hypercube. Ngoại trừ sklearn.svm.OneClassSVM
# mặc trang phục một chút, tất cả các công cụ ước tính đều đưa ra các giải pháp hợp lý cho tình
# huống này. Trong trường hợp như vậy, sẽ là khôn ngoan nếu nhìn kỹ hơn vào điểm bất thường của
# các mẫu vì một người ước lượng tốt sẽ chỉ định điểm tương tự cho tất cả các mẫu.
#
# Mặc dù các ví dụ này cung cấp một số trực giác về các thuật toán, trực giác này có thể không
# áp dụng cho dữ liệu chiều rất cao.
#
# Cuối cùng, lưu ý rằng các tham số của các mô hình đã ở đây được lựa chọn cẩn thận nhưng trong
# thực tế, chúng cần phải được điều chỉnh. Trong trường hợp không có dữ liệu được dán nhãn, vấn đề
# hoàn toàn không được giám sát nên việc lựa chọn mô hình có thể là một thách thức.
import time

import numpy as np
import matplotlib
import matplotlib.pyplot as plt

from sklearn import svm
from sklearn.datasets import make_moons, make_blobs
from sklearn.covariance import EllipticEnvelope
from sklearn.ensemble import IsolationForest
from sklearn.neighbors import LocalOutlierFactor

print(__doc__)

matplotlib.rcParams['contour.negative_linestyle'] = 'solid'

# Cài đặt ví dụ
n_samples = 300
outliers_fraction = 0.15
n_outliers = int(outliers_fraction * n_samples)
n_inliers = n_samples - n_outliers

# định nghĩa các phương pháp phát hiện ngoại lệ / dị thường được so sánh
anomaly_algorithms = [
    ("Robust covariance", EllipticEnvelope(contamination=outliers_fraction)),
    ("One-Class SVM", svm.OneClassSVM(nu=outliers_fraction, kernel="rbf",
                                      gamma=0.1)),
    ("Isolation Forest", IsolationForest(contamination=outliers_fraction,
                                         random_state=42)),
    ("Local Outlier Factor", LocalOutlierFactor(
        n_neighbors=35, contamination=outliers_fraction))]

# Định nghĩa bộ dữ liệu
blobs_params = dict(random_state=0, n_samples=n_inliers, n_features=2)
datasets = [
    make_blobs(centers=[[0, 0], [0, 0]], cluster_std=0.5,
               **blobs_params)[0],
    make_blobs(centers=[[2, 2], [-2, -2]], cluster_std=[0.5, 0.5],
               **blobs_params)[0],
    make_blobs(centers=[[2, 2], [-2, -2]], cluster_std=[1.5, .3],
               **blobs_params)[0],
    4. * (make_moons(n_samples=n_samples, noise=.05, random_state=0)[0] -
          np.array([0.5, 0.25])),
    14. * (np.random.RandomState(42).rand(n_samples, 2) - 0.5)]

# So sánh các phân loại nhất định trong các cài đặt đã cho
xx, yy = np.meshgrid(np.linspace(-7, 7, 150),
                     np.linspace(-7, 7, 150))

plt.figure(figsize=(len(anomaly_algorithms) * 2 + 3, 12.5))
plt.subplots_adjust(left=.02, right=.98, bottom=.001, top=.96, wspace=.05,
                    hspace=.01)

plot_num = 1
rng = np.random.RandomState(42)

for i_dataset, X in enumerate(datasets):
    # Thêm các ngoại lệ
    X = np.concatenate([X, rng.uniform(low=-6, high=6,
                                       size=(n_outliers, 2))], axis=0)

    for name, algorithm in anomaly_algorithms:
        t0 = time.time()
        algorithm.fit(X)
        t1 = time.time()
        plt.subplot(len(datasets), len(anomaly_algorithms), plot_num)
        if i_dataset == 0:
            plt.title(name, size=18)

        # phù hợp với dữ liệu và thẻ ngoại lệ
        if name == "Local Outlier Factor":
            y_pred = algorithm.fit_predict(X)
        else:
            y_pred = algorithm.fit(X).predict(X)

        # vẽ các đường mức và điểm
        if name != "Local Outlier Factor":  # LOF does not implement predict
            Z = algorithm.predict(np.c_[xx.ravel(), yy.ravel()])
            Z = Z.reshape(xx.shape)
            plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors='black')

        colors = np.array(['#377eb8', '#ff7f00'])
        plt.scatter(X[:, 0], X[:, 1], s=10, color=colors[(y_pred + 1) // 2])

        plt.xlim(-7, 7)
        plt.ylim(-7, 7)
        plt.xticks(())
        plt.yticks(())
        plt.text(.99, .01, ('%.2fs' % (t1 - t0)).lstrip('0'),
                 transform=plt.gca().transAxes, size=15,
                 horizontalalignment='right')
        plot_num += 1

plt.show()


# -*- coding: utf-8 -*-
"""
Created on Mon Nov 16 14:20:05 2020

@author: Cian
"""

import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import metrics
from sklearn import model_selection
from sklearn import linear_model
from sklearn import svm

# Task 1
def preprocess():
    print("======================Task1======================")

    product_df = pd.read_csv("product_images.csv")
    # take a look at the dataset
    # print(product_df.head())
    # Take a look at the columns
    # print(product_df.columns)
    # Take a look at the labels
    # print(product_df['label'].head())

    # print(product_df.columns)

    # Adding .values at the end as it then returns a numpy array
    feature_vectors = product_df.loc[:, product_df.columns != 'label'].values
    labels = product_df['label'].values

    # Print the number of sneakers
    print("The number of sneakers:", len(labels[labels == 0]))
    # Print the number of ankle boots
    print("The number of ankle boot:", len(labels[labels == 1]))

    # Example Sneaker
    plt.figure(1, figsize=(3, 3))
    plt.imshow(np.reshape(feature_vectors[3], (28, 28)), cmap='gray', interpolation='nearest')
    plt.show()

    # Example Ankle Boot
    plt.figure(1, figsize=(3, 3))
    plt.imshow(np.reshape(feature_vectors[0], (28, 28)), cmap='gray', interpolation='nearest')
    plt.show()

    # Sample variable for the amount of samples form the feature vector to use
    # no_samples = 0.02
    # no_samples = 0.2
    # no_samples = 0.05
    # no_samples = 0.5
    no_samples = 0.08
    # no_samples = 0.7
    # no_samples = 0.8

    # Starting off with reducted amount
    train_data = feature_vectors[0:int(no_samples*len(feature_vectors))]
    train_target = labels[0:int(no_samples*len(labels))]
    test_data = feature_vectors[int(no_samples*len(feature_vectors)):len(feature_vectors)]
    test_target = labels[int(no_samples*len(labels)):len(labels)]

    # Returns train and test vars and the number of samples
    return train_data, train_target, test_data, test_target, no_samples*len(feature_vectors)

# Task 2
def perceptron(train_data, train_target, test_data, test_target, no_samples):

    # Through testing it was found that 4 was the found to be the optimal
    # amount of splits with 32 being second.
    kf = model_selection.KFold(n_splits=4, shuffle=True)

    training_times = []
    prediction_times = []

    best_score = 1e-10

    print("======================Task2======================")

     # Create a k-fold cross validation procedure to split the data into training and evaluation subsets [1 point].
    for train_index,test_index in kf.split(train_data):
        print("====================Split====================")

        perceptron = linear_model.Perceptron()

        # Measure the processing time required for training [1 point],
        # This will create a time variable from this point
        start = time.time()

        # Train a perceptron classifier on the training subsets [1 point]
        perceptron.fit(train_data[train_index], train_target[train_index])

        # This will stop counting time
        stop = time.time()

        # Absolute means that it will always be printed positively
        print("Training time:", abs(stop - start), "secs")
        # Calculate the minimum, the maximum, and the average of the training time per training sample [1 point]
        training_times.append(abs(stop - start))

        # the processing time required for prediction [1 point],
        start = time.time()

        # and predict labels for the evaluation subsets [1 point].
        prediction = perceptron.predict(train_data[test_index])

        # This will stop counting time
        stop = time.time()

        print("Prediction time:", abs(stop - start), "secs")
        # Calculate the minimum, the maximum, and the average of the training time per training sample [1 point]
        prediction_times.append(abs(stop - start))

         # and determine the accuracy score of the classification [1 point]
        score = metrics.accuracy_score(train_target[test_index], prediction)

        # and the confusion matrix [1 point]
        C = metrics.confusion_matrix(train_target[test_index], prediction)

        # Setting these to varaibles makes them easeir to read i think
        true_sneakers = C[0,0]
        true_ankleboots = C[1,1]
        false_sneakers = C[1,0]
        false_ankleboots = C[0,1]

        # for each split.
        print("Accuracy Score: ", score)
        print("True sneakers:", np.sum(true_sneakers))
        print("True ankle boots:", np.sum(true_ankleboots))
        print("False sneakers:", np.sum(false_sneakers))
        print("False ankle boots:", np.sum(false_ankleboots))

        # Whichever kfold split has the best accuracy save it
        if  best_score < score:
            best_perceptron = perceptron

    # Break up the results from each split
    print("="*50)

    # Test the model on unseen data and get a score
    test_prediction = best_perceptron.predict(test_data)

    # and the prediction accuracy [1 point].
    print("Prediciton accuracy score:", metrics.accuracy_score(test_target, test_prediction))

    # Calculate the minimum, the maximum, and the average of the training time per training sample [1 point],
    # the prediction time per evaluation sample [1 point]
    print("Minimum training time per training sample:", min(training_times)/no_samples, "secs")
    print("Maximum training time per training sample:", max(training_times)/no_samples, "secs")
    print("Average training time per training sample:", (sum(training_times)/len(training_times))/no_samples, "secs")
    print("Minimum predicition time per evaulation sample:", min(prediction_times)/no_samples, "secs")
    print("Maximum predicition time per evaulation sample:", max(prediction_times)/no_samples, "secs")
    print("Average predicition time per evaulation sample:", (sum(prediction_times)/len(prediction_times))/no_samples, "secs")

# Task 3
def svm_func(train_data, train_target, test_data, test_target, no_samples):

    # ================ Currently Tested Gamma and Ksplits and accuracies: ================
    # Tests where no_samples was 0.08:
    # Ksplits:  Tested Gamma:   RBF Acc:                Linear Acc
    # 2         1e-4            0.49906832298136644     0.9427018633540373
    # 3         1e-4            0.49906832298136644     0.9427018633540373
    # 6         1e-4            0.49906832298136644     0.943944099378882
    # 2         1e-5            0.5001552795031056      0.9411490683229814
    # 2         1e-9            0.9059006211180124      0.940527950310559

    # Tests where no_samples was 0.8:
    # Ksplits:  Tested Gamma:   RBF Acc:                Linear Acc
    # 2         1e-9            0.9239285714285714      0.935

    # A         A               A                       A

    # Create a k-fold cross validation procedure to split the data into training and evaluation subsets [1 point].
    # A split value of 4 was found again to be a sufficiant number of splits
    kf = model_selection.KFold(n_splits=4, shuffle=True)

    linear_training_times = []
    linear_prediction_times = []

    rbf_training_times = []
    rbf_prediction_times = []
    rbf_accuracies = []

    best_score_linear = 1e-10
    best_score_rbf = 1e-10

    print("======================Task3======================")

    for train_index,test_index in kf.split(train_data):
        print("====================Split====================")

        # Linear SVM information will  go from below
        print("====================Linear Kernal====================")

        # Train a support vector machine classifier on the training subsets. Try a linear kernel [1 point]
        linear = svm.SVC(kernel="linear")

        # Measure the time required for training [1 point],
        # Start Training Time
        start = time.time()

        linear.fit(train_data[train_index], train_target[train_index])

        # Stop Training Time
        stop = time.time()

        print("Training time:", abs(stop - start), "secs")
        linear_training_times.append(abs(stop - start))

        # the time required for prediction [1 point], and
        # Start Prediciton Time
        start = time.time()

        predictionLinear = linear.predict(train_data[test_index])

        # Stop Prediciton Time
        stop = time.time()

        print("Prediction time:", abs(stop - start), "secs")
        linear_prediction_times.append(abs(stop - start))

        # determine the accuracy score of the classification [1 point]
        linear_score = metrics.accuracy_score(train_target[test_index], predictionLinear)
        print("Linear Accuracy Score: ", linear_score)

        # and the confusion matrix [1 point]
        cLinear = metrics.confusion_matrix(train_target[test_index], predictionLinear)

        # Setting these to varaibles makes them easeir to read i think
        true_sneakers = cLinear[0,0]
        true_ankleboots = cLinear[1,1]
        false_sneakers = cLinear[1,0]
        false_ankleboots = cLinear[0,1]

        # Confusion matrix for linear.
        print("Linear True sneakers:", np.sum(true_sneakers))
        print("Linear True ankle boots:", np.sum(true_ankleboots))
        print("Linear False sneakers:", np.sum(false_sneakers))
        print("Linear False ankle boots:", np.sum(false_ankleboots))

        #==============================================================

        # Linear SVM information will  go from below
        print("====================RBF Kernal====================")

        # and a radial basis function kernel for different choices of the parameter ð�›¾ [2 points].
        rbf = svm.SVC(kernel="rbf", gamma=1e-6)

        # Measure the time required for training [1 point],
        # Start Training Time
        start = time.time()

        rbf.fit(train_data[train_index], train_target[train_index])

        # Stop Training Time
        stop = time.time()

        print("Training time:", abs(stop - start), "secs")
        rbf_training_times.append(abs(stop - start))

        # the time required for prediction [1 point], and
        # Start Prediciton Time
        start = time.time()

        predictionRBF = rbf.predict(train_data[test_index])

         # Stop Prediciton Time
        stop = time.time()

        print("Prediction time:", abs(stop - start), "secs")
        rbf_prediction_times.append(abs(stop - start))

        # determine the accuracy score of the classification [1 point]
        rbf_score = metrics.accuracy_score(train_target[test_index], predictionRBF)
        print("RBF Accuracy Score: ", rbf_score)
        rbf_accuracies.append(rbf_score)

        # and the confusion matrix [1 point]
        cRBF = metrics.confusion_matrix(train_target[test_index], predictionRBF)

        # Setting these to varaibles makes them easeir to read i think
        true_sneakers = cRBF[0,0]
        true_ankleboots = cRBF[1,1]
        false_sneakers = cRBF[1,0]
        false_ankleboots = cRBF[0,1]

        # Confusion matrix for rbf.
        print("RBF True sneakers:", np.sum(true_sneakers))
        print("RBF True ankle boots:", np.sum(true_ankleboots))
        print("RBF False sneakers:", np.sum(false_sneakers))
        print("RBF False ankle boots:", np.sum(false_ankleboots))

        # Break up Results from each split
        # print("="*100)

        # Whichever kfold split has the best accuracy save it
        if  best_score_linear < linear_score :
            best_linear = linear

        if  best_score_rbf < rbf_score:
            best_rbf = rbf

    # and the prediction accuracy [1 point].
    print("="*50)

    print("Prediciton accuracy score for Linear:", metrics.accuracy_score(test_target, best_linear.predict(test_data)))

    # Calculate the minimum, the maximum, and the average of the training time per training sample [1 point],
    # the prediction time per evaluation sample [1 point]
    print("Minimum Linear training time per training sample:", min(linear_training_times)/no_samples, "secs")
    print("Maximum Linear training time per training sample:", max(linear_training_times)/no_samples, "secs")
    print("Average Linear training time per training sample:", (sum(linear_training_times)/len(linear_training_times))/no_samples, "secs")
    print("Minimum Linear predicition time per evaulation sample:", min(linear_prediction_times)/no_samples, "secs")
    print("Maximum Linear predicition time per evaulation sample:", max(linear_prediction_times)/no_samples, "secs")
    print("Average Linear predicition time per evaulation sample:", (sum(linear_prediction_times)/len(linear_prediction_times))/no_samples, "secs")

    print("="*50)

    print("Prediciton accuracy score for rbf:", metrics.accuracy_score(test_target, best_rbf.predict(test_data)))
    print("Mean Accuarcy of rbf accross splits:", sum(rbf_accuracies)/len(rbf_accuracies))

    # Calculate the minimum, the maximum, and the average of the training time per training sample [1 point],
    # the prediction time per evaluation sample [1 point]
    print("Minimum rbf training time per training sample:", min(rbf_training_times)/no_samples, "secs")
    print("Maximum rbf training time per training sample:", max(rbf_training_times)/no_samples, "secs")
    print("Average rbf training time per training sample:", (sum(rbf_training_times)/len(rbf_training_times))/no_samples, "secs")
    print("Minimum rbf predicition time per evaulation sample:", min(rbf_prediction_times)/no_samples, "secs")
    print("Maximum rbf predicition time per evaulation sample:", max(rbf_prediction_times)/no_samples, "secs")
    print("Average rbf predicition time per evaulation sample:", (sum(rbf_prediction_times)/len(rbf_prediction_times))/no_samples, "secs")

def main():
    train_data, train_target, test_data, test_target, no_samples = preprocess()

    perceptron(train_data, train_target, test_data, test_target, no_samples)

    svm_func(train_data, train_target, test_data, test_target, no_samples)

main()


"""
Typing Practice Program v1

指定されたキーボードの文字をいかに早く打てるかを計測するプログラム
文字の場所を覚えるときに使えます。

1. 母音モード
    母音のみ出題

2. 子音モード
    子音のみ出題

3. 全複合モード
    母音、子音、感嘆符と数字も含んで出題

4. 日本語かなモード
    日本語かな一文字を出題

5. 英文入力モード
    簡単な英文で練習

6. 日本語文入力モード [[[未実装]]]
    簡単な日本語文で練習
"""

import time,random

#一文字のときのワードチェッカー
def check_letter_match(desired_letter, input_letter):
    # 入力文字と求める文字を大文字に変換して比較
    desired_letter = desired_letter.lower()
    input_letter = input_letter.lower()

    if desired_letter == input_letter:
        return True
    else:
        return False

bvowels = [97,105,117,101,111]
bconsonant = [x for x in range(97,123)]
alphabet = list(map(chr,bconsonant+bvowels))
for i in bvowels:
    bconsonant.pop(bconsonant.index(i))
vowels = list(map(chr,bvowels))
consonant = list(map(chr,bconsonant))
alphabet.append('!')
alphabet.append('?')

#日本語
# 「あ」から「ん」までのひらがなのUnicodeコードポイント範囲
hiragana_start = ord("あ")
hiragana_end = ord("ん")

hiragana_list = [chr(code) for code in range(hiragana_start, hiragana_end + 1)]

# 濁点のひらがなを追加
dakuten_hiragana = [
    "が", "ぎ", "ぐ", "げ", "ご",
    "ざ", "じ", "ず", "ぜ", "ぞ",
    "だ", "ぢ", "づ", "で", "ど",
    "ば", "び", "ぶ", "べ", "ぼ",
    "ぱ", "ぴ", "ぷ", "ぺ", "ぽ"
]

# ひらがなリストに濁点のひらがなを追加
hiragana_list.extend(dakuten_hiragana)
#簡単に打てないひらがなリスト
non_lists = ['ゐ','ゑ','ぃ','ぅ','ぇ','ぉ','っ','ゃ','ゅ','ょ']
for i in non_lists:
    hiragana_list.pop(hiragana_list.index(i))

#設定 [問題数=30]
setting = [30]

def mode1():
    #母音モード
    print("\n\n")
    print("母音モード：\n始めるにはエンターキーを押す...")
    inp = input()
    ans_word = ""
    ans_sum = 0
    #開始
    print()
    t_start = time.time()
    for i in range(setting[0]):
        ans_word = vowels[random.randint(0,4)]
        print("\r "+ans_word,end=' ')
        inp = input(">> ")
        ans_sum += 1 if check_letter_match(ans_word,inp) else 0
    t_end = time.time()
    print("--終了!!-\n")
    print(f'time: %3ds\n正解数: %3d/%3d\n' % (t_end - t_start,ans_sum,setting[0]))
    print()
    return 0
def mode2():
    #子音モード
    print("\n\n")
    print("子音モード：\n始めるにはエンターキーを押す...")
    inp = input()
    ans_word = ""
    ans_sum = 0
    #開始
    print()
    t_start = time.time()
    for i in range(setting[0]):
        ans_word = consonant[random.randint(0,20)]
        print("\r "+ans_word,end=' ')
        inp = input(">> ")
        ans_sum += 1 if check_letter_match(ans_word,inp) else 0
    t_end = time.time()
    print("--終了!!-\n")
    print(f'time: %3ds\n正解数: %3d/%3d\n' % (t_end - t_start,ans_sum,setting[0]))
    print()
    return 0
def mode3():
    #複合モード
    print("\n\n")
    print("複合モード：\n始めるにはエンターキーを押す...")
    inp = input()
    ans_word = ""
    ans_sum = 0
    #開始
    print()
    t_start = time.time()
    for i in range(setting[0]):
        ans_word = alphabet[random.randint(0,27)]
        print("\r "+ans_word,end=' ')
        inp = input(">> ")
        ans_sum += 1 if check_letter_match(ans_word,inp) else 0
    t_end = time.time()
    print("--終了!!-\n")
    print(f'time: %3ds\n正解数: %3d/%3d\n' % (t_end - t_start,ans_sum,setting[0]))
    print()
    return 0
def mode4():
    #日本語モード
    print("\n\n")
    print("日本語モード：\n始めるにはエンターキーを押す...")
    inp = input()
    ans_word = ""
    ans_sum = 0
    #開始
    print()
    t_start = time.time()
    for i in range(setting[0]):
        ans_word = hiragana_list[random.randint(0,96)]
        print("\r "+ans_word,end=' ')
        inp = input(">> ")
        ans_sum += 1 if check_letter_match(ans_word,inp) else 0
    t_end = time.time()
    print("--終了!!-\n")
    print(f'time: %3ds\n正解数: %3d/%3d\n' % (t_end - t_start,ans_sum,setting[0]))
    print()
    return 0
def mode5():
    #英文入力モード

    #英文セット
    english_sentences = [
        "Hello, how are you?",
        "I love programming.",
        "This is a test sentence.",
        "Python is a versatile language.",
        "The quick brown fox jumps over the lazy dog.",
        "Learning new things is always exciting.",
        "I enjoy listening to music in my free time.",
        "Coding is a valuable skill in today's world.",
        "She plays the piano beautifully.",
        "Reading books is a great way to relax.",
        "The sun is shining brightly today.",
        "I need to buy groceries after work.",
        "He is a talented artist.",
        "Do you want to go for a walk?",
        "She has a beautiful smile.",
        "We're going on a vacation next week.",
        "It's important to stay hydrated.",
        "The conference is scheduled for tomorrow.",
        "He won the first prize in the competition.",
        "I have a lot of work to do.",
        "She's a great cook.",
        "I can't believe it's already December.",
        "He always tells funny jokes.",
        "She's a dedicated teacher.",
        "Let's meet at the coffee shop.",
        "The movie starts at 7 PM.",
        "I like to go for a run in the morning.",
        "This restaurant serves delicious food.",
        "They have a lovely garden.",
        "She's a talented singer.",
        "I'm looking forward to the weekend.",
        "The book was so interesting that I couldn't put it down.",
        "He's a reliable friend.",
        "The weather is perfect for a picnic.",
        "She's a successful entrepreneur.",
        "I'm feeling a bit tired today.",
        "The museum is closed on Mondays.",
        "He's a passionate photographer.",
        "Let's make a plan for the future.",
        "I'll be there in 10 minutes.",
        "The city is known for its cultural diversity.",
        "I have a busy day ahead of me.",
        "She's a talented dancer.",
        "I enjoy spending time with my family.",
        "The concert was amazing.",
        "I have to finish this report by tomorrow.",
        "She's an excellent student.",
        "I like to watch the sunset.",
        "He's a skilled carpenter.",
        "I'll call you later.",
        "The restaurant is fully booked tonight.",
        "I have a lot of hobbies.",
        "She's a kind-hearted person.",
        "I'll be right back.",
        "The mountain is covered in snow.",
        "I have a sweet tooth.",
        "She's a fashion designer.",
        "I need to clean my room.",
        "He's a great basketball player.",
        "I'm excited about the upcoming trip.",
        "She's a wonderful actress.",
        "I like to read science fiction novels.",
        "The dog is barking loudly.",
        "I have a craving for pizza.",
        "She's an adventurous traveler.",
        "I'll take a break now.",
        "The cat is sleeping on the couch.",
        "I have a lot of responsibilities at work.",
        "She's a skilled writer.",
        "I'll see you tomorrow.",
        "The beach is so peaceful.",
        "I enjoy watching documentaries.",
        "He's a computer programmer.",
        "I need to do the laundry.",
        "She's a caring nurse.",
        "I'm running out of time.",
        "The garden is full of colorful flowers.",
        "I have a good sense of humor.",
        "She's a talented pianist.",
        "I'll be careful.",
        "The car is parked in the garage.",
        "I have a lot of dreams and goals.",
        "She's a dedicated volunteer.",
        "I'll do my best.",
        "The river flows gently.",
        "I have a busy schedule this week.",
        "She's a creative artist.",
        "I like to cook homemade meals.",
        "The movie theater is crowded.",
        "I have a passion for photography.",
        "She's a strong leader.",
        "I'll see you soon.",
        "The forest is full of wildlife.",
        "I enjoy listening to classical music.",
        "He's a talented chef.",
        "I need to finish this project.",
        "She's a reliable colleague.",
        "I'm feeling inspired today.",
    ]
    print("\n\n")
    print("英文モード：\n始めるにはエンターキーを押す...")
    inp = input()
    ans_sentence = ""
    ans_sum = 0
    #開始
    print()
    t_start = time.time()
    for i in range(setting[0]):
        ans_sentence = english_sentences[random.randint(0,97)]
        print("\r "+ans_sentence,end=' ')
        inp = input(">> ")
        ans_sum += 1 if check_letter_match(ans_sentence,inp) else 0
    t_end = time.time()
    print("--終了!!-\n")
    print(f'time: %3ds\n正解数: %3d/%3d\n' % (t_end - t_start,ans_sum,setting[0]))
    print()
    return 0
def mode6():
    #日本語文入力モード
    pass

while True:
    print("タイピング練習プログラム")
    inp = input("モード選択 >> ")
    if inp == "exit":
        break
    elif inp == "1":
        mode1()
    elif inp == "2":
        mode2()
    elif inp == "3":
        mode3()
    elif inp == "4":
        mode4()
    elif inp == "5":
        mode5()
    elif inp == "6":
        mode6()
    elif inp == "setting":
        inp = input(f"回数を指定：現在は%3d回です。\n>>>" % setting[0])
        try:
            inp = int(inp)
            setting[0] = inp
            print(f'回数を%3d回に変更しました。\n' % setting[0])
            continue
        except:
            print("有効な数字(整数)を入力してください")
            continue


from flask import Blueprint, jsonify, request

from ..models.card import Card
from ..models.card_list import CardList
from ..models.deck import Deck
from ..models.pile import Pile

deck_api_blueprint = Blueprint('deck_api', __name__)

@deck_api_blueprint.route('/', methods=["GET"])
def read_all():
    decks = Deck.query.all()
    return jsonify([deck.serial for deck in decks])

@deck_api_blueprint.route('/<id>', methods=["GET"])
def read_one(id):
    deck = Deck.query.get(id)
    if not deck:
        return f"No deck {id}", 404
    return jsonify(deck.serial)

@deck_api_blueprint.route('/<id>/piles/', methods=["GET"])
def read_piles_from(id):
    deck = Deck.query.get(id)
    if not deck:
        return f"No deck {id}", 404
    piles = Pile.query.filter(Pile.id.in_(deck.piles)).all()
    return jsonify([pile.serial for pile in piles])

@deck_api_blueprint.route('/<id>/cards/', methods=["GET"])
def read_cards_from(id):
    deck = Deck.query.get(id)
    if not deck:
        return f"No deck {id}", 404
    piles = Pile.query.filter(Pile.id.in_(deck.piles)).all()
    cards = []
    for pile in piles:
        cards.extend(Card.query.filter(Card.id.in_(pile.cards)).all())
    return jsonify([card.serial for card in cards])

@deck_api_blueprint.route('/', methods=["POST"])
def create():
    deck = Deck(piles=request.json['piles'])
    deck.save()
    return jsonify(deck.serial)

@deck_api_blueprint.route('/<id>', methods=["PUT"])
def update(id):
    deck = CardList.query.get(id)
    if not deck:
        return f"No deck {id}", 404
    deck.update(request.json)
    deck.save()
    return jsonify(deck.serial)

@deck_api_blueprint.route('/<id>', methods=["DELETE"])
def delete(id):
    deck = CardList.query.get(id)
    if not deck:
        return f"No deck {id}", 404
    deck.delete()
    return "Deleted"


import cv2 as cv
import numpy as np

#手动实现高斯滤波核(所要处理的图像:img,高斯滤波核大小:K_size*K_size 和 标准差:sigma)
def gaussian_filter(img,K_size,sigma):
    #1.获取图像的shape(确保为三维)
    #(H,W,C)其中H和W表示高度方向和宽度方向的像素点个数，C代表颜色通道数
    #image.shape返回的是图像的(H,W,C)，一个元组
    #元组的len表示元组内元素的个数
    if len(img.shape)==3:
        (H,W,C)=img.shape
    #如果不是彩色图像，即灰度图像，有可能len(img.shape)=2,则需要元组维度扩展
    #np.expand_dims(img,axis=i)表示在i位置添加数据,i=-1表示img.shape最后加上一个数1,即将元组扩展维度
    else:
        img=np.expand_dims(img,axis=-1)
        (H,W,C)=img.shape

    #2.进行原图像的zero padding(由于需要将图像的边缘也进行高斯滤波,所以将图像边缘加上一圈宽度为pad的像素点,因此需要在图像的边缘补0)
    pad=K_size//2
    #np.zeros((2,5),dtype=np.int) 两行五列的整型矩阵
    out=np.zeros((H+pad*2,W+pad*2,C),dtype=np.float64)
    #利用python的切片操作
    out[pad:pad+H,pad:pad+W]=img.copy().astype(np.float64)

    #3.实现高斯滤波核
    K=np.zeros((K_size,K_size),dtype=np.float64)
    for x in range(-pad,-pad+K_size):
        for y in range(-pad,-pad+K_size):
            K[y+pad,x+pad]=np.exp(-(x**2+y**2)/(2*(sigma**2)))
    K/=2*np.pi*sigma*sigma
    #确保高斯滤波核的所有值加起来为1
    K/=K.sum()

    #4.用手动实现的高斯滤波核进行滤波
    tmp=out.copy()
    for y in range(H):
        for x in range(W):
            for c in range(C):
                #实现互相关操作
                out[pad+y,pad+x,c]=np.sum(K*tmp[y:y+K_size,x:x+K_size,c])
    #将out中大于255的数全赋值为255,小于0的数全赋值为0,确保三通道的像素值在0-255之间
    out=np.clip(out,0,255)
    #再次使用python的切片操作,np.unit8类型可以为图像创建一个容器，使得图像能够正确显示
    out=out[pad:pad+H,pad:pad+W].astype(np.uint8)
    return out

if __name__ == '__main__':
    #读取图像
    image=cv.imread('1.Gaussian_Filtering_Kernel/original image.jpg')
    #手动高斯滤波(可以自己选择高斯滤波核的大小和标准差,修改对应的值,不过滤波核的边长得取奇数)
    out=gaussian_filter(image,K_size=5,sigma=2.0)
    #储存结果并自动显示处理过的图像
    cv.imwrite('1.Gaussian_Filtering_Kernel/out image.jpg',out)
    cv.imshow('result',out)
    #cv.waitKey()能控制cv.imshow()所显示图像的时间
    '''
    cv2.waitKey()是一个键盘绑定函数。它的时间量度是毫秒ms。
    函数会等待(n)里面的n毫秒,看是否有键盘输入。
    若有键盘输入,则返回按键的ASCII值。没有键盘输入,则返回-1.一般设置为0,他将无限等待键盘的输入。
    cv2.destroyAllWindows() 用来删除窗口的,()里不指定任何参数,则删除所有窗口,删除特定的窗口,往()输入特定的窗口值。
    '''
    cv.waitKey(0)
    cv.destroyAllWindows()


# -*- coding: utf-8 -*-
# First things, first. Import the wxPython package.

import os
import os.path
#join, getsize, isfile, getatime, getctime, getmtime, exists, isdir
import shutil
import time
from ctypes import windll
from threading import Thread
from win32api import GetModuleFileName, GetModuleHandle

try:
	import wx
	import wx.lib.mixins.listctrl  as  listmix
except ImportError:
	"""
	try:
		os.system('python3 -m pip install --proxy 172.31.0.14:6588 wxPython')
	except:
		pass
	try:
		os.system('python -m pip install --proxy 172.31.0.14:6588 wxPython')
	except:
		pass

	import wx
	import wx.lib.mixins.listctrl  as  listmix
	"""
	print('Fail with import, exit')
	exit()

class ProListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ColumnSorterMixin): #listmix.ListRowHighlighter
	"""
		Lista ordenable
	"""
	def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.LC_REPORT|wx.BORDER_SUNKEN, columnas = 2):
		wx.ListCtrl.__init__(self, parent, id, pos, size, style)
		listmix.ListCtrlAutoWidthMixin.__init__(self)
		listmix.ColumnSorterMixin.__init__(self, columnas)
		#listmix.ListRowHighlighter.__init__(self, color=None, mode=listmix.HIGHLIGHT_EVEN)
		self.itemDataMap = {}
	def GetListCtrl(self):
		return self

class EditableListCtrl(wx.ListCtrl, listmix.TextEditMixin, listmix.ListCtrlAutoWidthMixin, listmix.ColumnSorterMixin): #listmix.ListRowHighlighter
	"""
		Lista editable
	"""
	def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.LC_REPORT|wx.BORDER_SUNKEN, columnas = 2):
		"""Constructor"""
		wx.ListCtrl.__init__(self, parent, id, pos, size, style)
		listmix.TextEditMixin.__init__(self)
		listmix.ListCtrlAutoWidthMixin.__init__(self)
		listmix.ColumnSorterMixin.__init__(self, columnas)
		#listmix.ListRowHighlighter.__init__(self, color=None, mode=listmix.HIGHLIGHT_EVEN)
		self.itemDataMap = {}
	def GetListCtrl(self):
		return self

class OtherFrame(wx.Frame):
    """
    Class used for creating frames other than the main one
    """
    def __init__(self, title, parent=None):
    	style = wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER)
    	wx.Frame.__init__(self, parent=parent, title=title, style = style)
    	self.SizerPrincipal = wx.BoxSizer(wx.VERTICAL)
    	self.Show()

class wxCommander(wx.Frame):
	def __init__(self):
		title = 'wxCommander'
		#style = wx.DEFAULT_FRAME_STYLE & ~ (wx.FRAME_NO_TASKBAR) & wx.STAY_ON_TOP & ~ (wx.RESIZE_BORDER)
		style = wx.DEFAULT_FRAME_STYLE & ~ (wx.RESIZE_BORDER)
		wx.Frame.__init__(self,parent=None, title=title, style=style, size = (1920,1080))
		self.Maximize(True)
		#self.SetSize(1920, 1080)
		self.panelHijo = MyPanel(self)
		self.frame_number = 1

		#self.Maximize(True)
		self.SizerPrincipal = wx.BoxSizer(wx.VERTICAL)
		self.SizerPrincipal.Add(self.panelHijo, 1, wx.EXPAND)
		self.Bind(wx.EVT_SIZE, self.OnResizeWindow)
		# Evento de foco
		#self.Bind(wx.EVT_SET_FOCUS, self.onFocus)
		#self.panelHijo.Bind(wx.EVT_LEFT_UP, self.OnLeftClick)
		#self.panelHijo.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
		#self.panelHijo.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)
		#self.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)
		self.SetSizer(self.SizerPrincipal)
		try:
			if os.path.isfile('icono.ico'):
				icono = wx.Icon("icono.ico")
			else:
				exeName = GetModuleFileName(GetModuleHandle(None))
				icono = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)
			self.SetIcon(icono)
		except:
			pass

		self.__barraMenus()
		self.CreateStatusBar()
		self.SetStatusText("Copyright TOI")
		#self.Fit()
		self.Show()

	def on_new_frame(self, event = None):
		if event is None:
			title = 'Busqueda'
		else:
			title = 'SubFrame {}'.format(self.frame_number)
		frame = OtherFrame(title=title, parent = self)
		self.frame_number += 1

	def __barraMenus(self):
		#Creacion de un menu / seria la plantilla del menu, posteriormente se "ubica"
		self.wdMenu = wx.Menu()

		# Añadimos objetos al menu
		# "\t..." Asigna combinacion de teclas para activar el evento del menus
		self.openFolderMenuItem1 = self.wdMenu.Append(1, 'Selecciona carpeta 1\tCtrl-1', 'Selecciona carpeta')
		self.openFolderMenuItem2 = self.wdMenu.Append(2, 'Selecciona carpeta 2\tCtrl-2', 'Selecciona carpeta')
		self.wdMenu.AppendSeparator()
		self.searchItem = self.wdMenu.Append(3, 'Buscar..\tCtrl-B')
		self.exitItem = self.wdMenu.Append(-1, '&Exit\tCtrl-Q')

		#Creacion de otro menu / seria la plantilla del menu, posteriormente se "ubica"
		self.helpMenu = wx.Menu()

		# Añadimos objeto al menu
		self.aboutItem = self.helpMenu.Append(4, 'Informacion\tF1')

		# Creamos la barra para ubicar el menu y añadimos los menus
		self.menuBar = wx.MenuBar()
		self.menuBar.Append(self.wdMenu, "&Menu")
		self.menuBar.Append(self.helpMenu, "&Ayuda")

		# Activamos/asignamos la barra de menu
		self.SetMenuBar(self.menuBar)

		#Vinculamos los menus a los metodos correspondientes en base a eventos
		self.Bind(wx.EVT_MENU, self.OnOpenFolder, self.openFolderMenuItem1)
		self.Bind(wx.EVT_MENU, self.OnOpenFolder, self.openFolderMenuItem2)
		self.Bind(wx.EVT_MENU, self.OnExit, self.exitItem)
		self.Bind(wx.EVT_MENU, self.OnBuscar, self.searchItem)
		self.Bind(wx.EVT_MENU, self.OnAbout, self.aboutItem)

	def OnOpenFolder(self, event):
		idEvento = event.GetId()
		#print('Id %d en el evneto en OnOpenFolder' % idEvento)
		rutas = ['U:\\Profile\\Mis documentos\\TOI','C:\\Users\\bvf1426\\Desktop\\TOI', 'U:\\Profile\\Mis documentos', 'C:\\Users','c:\\', 'k:\\']
		if idEvento == 1:
			if os.path.exists(rutas[0]):
				rutaDefecto = rutas[0]
			else:
				rutaDefecto = rutas[4]
		elif idEvento == 2:
			if os.path.exists(rutas[1]):
				rutaDefecto = rutas[1]
			else:
				rutaDefecto = rutas[5]

		#print(event.GetEventObject())
		#print(event.GetEventObject().GetLabel())
		#print(event.EventObject.GetLabel())
		#dlg = wx.DirDialog (self, "Choose input directory", "", wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST)
		self.dlg = wx.DirDialog(None, "Selecciona directorio para trabajar", rutaDefecto, wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST| wx.DIALOG_NO_PARENT)
		#self.dlg = wx.FileDialog(None, message="Choose a Python file", defaultDir=os.getcwd(),defaultFile="", wildcard=wildcard, style=wx.FD_OPEN)
		try:
			resultado = self.dlg.ShowModal()
			if resultado == wx.ID_OK:
				if idEvento == 1:
					self.panelHijo.path = self.dlg.GetPath()
				elif idEvento == 2:
					self.panelHijo.path2 = self.dlg.GetPath()
				else:
					print(idEvento)
					return False
			else:
				return False
		except Exception:
			wx.LogError('Failed to open directory!')
			raise
		finally:
			self.dlg.Destroy()

		self.panelHijo.refrescarLista(modo = idEvento)

	def OnResizeWindow(self, event):
		event.Skip()
		if not self.IsMaximized():
			self.Update()
		else:
			self.SizerPrincipal.Layout()

	def OnExit(self, event):
		"""Metodo asociado al evento de cierre de la ventana."""
		self.Close(True)

	def OnAbout(self, event):
		"""Metodo asociado al evento vinculado al menu aboutItem"""
		wx.MessageBox('\nAplicacion que te permite explorar dos estructuras de archivos\nseparadas y trabajar con ellas.\nFiltra para trabajar unicamente con archivos .py.\nSe pueden copiar archivos de un panel al otro con dobleclick y \nse pueden borrar  con la tecla supr.\nHay un menu contextual con mas opciones.\nEl panel izquierdo esta "protegido",\npide confirmacion para sobreescribir.',
					  "Breve ayuda",
					  wx.OK|wx.ICON_INFORMATION)

	def OnBuscar(self,event):
		#print('Buscar')
		#print(self.panelHijo.enfocado)
		if self.panelHijo.enfocado in [1,2,3,4]:
			__dicc = {1:'Panel directorio 1', 2:'Panel directorio 2', 3:'Panel archivos 1', 4:'Panel archivos 2'}
			dlg = wx.TextEntryDialog(self, 'Buscar', 'Busqueda en %s' % __dicc[self.panelHijo.enfocado] )
			dlg.ShowModal()
			resultado = ''
			resultado = dlg.GetValue()
			dlg.Destroy()
			if resultado and resultado != '':
				self.panelHijo.buscarLista(resultado)
		#self.on_new_frame()

	def onFocus(self, event):
		print('onfoco')
		print(event.GetId())

	def OnDisable(self, event):
		self.menuBar.EnableTop(0, False)

	def OnRightClick(self, event):
		print(event.GetId())
		print('OrcPapa')

	def OnLeftClick(self, event):
		print(event.GetId())
		print('OlcPapa')

class MyPanel(wx.Panel):
	def __init__(self,parent):
		wx.Panel.__init__(self,parent)
		self.__parent = parent
		# (1280, 1024)
		# (1920, 1080)
		self.resolucion = self.__resolucion()
		self.__size = (1920, 1080) if self.resolucion[1] == 1080 else (1280, 1024)
		#self.__parent.SetSize(self.__size)
		self.__parent.SetSize(self.resolucion)
		self.enfocado = 0

		#self.path = self.path2 = os.getcwd()
		#self.path = 'U:\\Profile\\Mis documentos\\TOI'
		#self.path2 = 'C:\\Users\\bvf1426\\Desktop\\TOI'
		self.path = ''
		self.path2 = ''
		self.__listaEditable = [False, False, False, False]
		self.__listaFiltrada = [False, False]
		self.__iniciarObjetos()

	def __iniciarObjetos(self):
		# Inicializmos panel y sizers para ubicacion de objetos

		self.__crearSizers()

		self.__crearEtiquetas()

		self.__crearListas()

		self.__montarPaneles()

		self.__vincularEventos()

	def __vincularEventos(self):
		# Vinculamos evento a las etiquetas
		self.st00.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)
		self.st01.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)
		self.st10.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)
		self.st11.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)

		# Vinculamos evento de las listas al metodo correspondiente
		self.list_ctrl00.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)
		self.list_ctrl01.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)
		self.list_ctrl02.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)
		self.list_ctrl03.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)

		self.list_ctrl00.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnList)
		self.list_ctrl01.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnList)
		self.list_ctrl02.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnList)
		self.list_ctrl03.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnList)

		self.list_ctrl00.Bind(wx.EVT_SET_FOCUS, self.onFocus)
		self.list_ctrl01.Bind(wx.EVT_SET_FOCUS, self.onFocus)
		self.list_ctrl02.Bind(wx.EVT_SET_FOCUS, self.onFocus)
		self.list_ctrl03.Bind(wx.EVT_SET_FOCUS, self.onFocus)

		self.list_ctrl00.Bind(wx.EVT_LIST_KEY_DOWN, self.OnPressKey)
		self.list_ctrl01.Bind(wx.EVT_LIST_KEY_DOWN, self.OnPressKey)
		self.list_ctrl02.Bind(wx.EVT_LIST_KEY_DOWN, self.OnPressKey)
		self.list_ctrl03.Bind(wx.EVT_LIST_KEY_DOWN, self.OnPressKey)

		#self.Bind(wx.EVT_KEY_UP, self.OnReleaseKey)

		self.list_ctrl00.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnMouseRight)
		self.list_ctrl01.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnMouseRight)
		self.list_ctrl02.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnMouseRight)
		self.list_ctrl03.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnMouseRight)

		self.list_ctrl00.Bind(wx.EVT_LIST_COL_RIGHT_CLICK, self.OnRightClick)
		self.list_ctrl01.Bind(wx.EVT_LIST_COL_RIGHT_CLICK, self.OnRightClick)
		self.list_ctrl02.Bind(wx.EVT_LIST_COL_RIGHT_CLICK, self.OnRightClick)
		self.list_ctrl03.Bind(wx.EVT_LIST_COL_RIGHT_CLICK, self.OnRightClick)

		#self.Bind(wx.EVT_RIGHT_UP, self.OnRightClick, self.list_ctrl01)

		self.list_ctrl00.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnUpdateItem)
		self.list_ctrl01.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnUpdateItem)
		self.list_ctrl02.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnUpdateItem)
		self.list_ctrl03.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnUpdateItem)

		self.list_ctrl00.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelected)
		self.list_ctrl01.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelected)
		self.list_ctrl02.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelected)
		self.list_ctrl03.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelected)

		if self.__listaEditable[0]:
			#print('Unbind')
			self.list_ctrl00.Unbind(wx.EVT_LIST_ITEM_SELECTED)
		if self.__listaEditable[1]:
			#print('Unbind')
			self.list_ctrl02.Unbind(wx.EVT_LIST_ITEM_SELECTED)

		if self.__listaEditable[2]:
			#print('Unbind')
			self.list_ctrl01.Unbind(wx.EVT_LIST_ITEM_SELECTED)
		if self.__listaEditable[3]:
			#print('Unbind')
			self.list_ctrl03.Unbind(wx.EVT_LIST_ITEM_SELECTED)

		#self.Bind(wx.EVT_KEY_DOWN, self.OnPressKey)
		#self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightClick)
		self.Bind(wx.EVT_LEFT_UP, self.OnSelected)
		self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick, self.list_ctrl01)
		self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick, self.list_ctrl03)

	def __crearSizers(self):
		self.sizerh00 = wx.BoxSizer(wx.HORIZONTAL)

		self.sizerv1 = wx.BoxSizer(wx.VERTICAL)
		self.sizerv2 = wx.BoxSizer(wx.VERTICAL)

		self.sizerh1 = wx.BoxSizer(wx.HORIZONTAL)
		self.sizerh2 = wx.BoxSizer(wx.HORIZONTAL)
		self.sizerh3 = wx.BoxSizer(wx.HORIZONTAL)
		self.sizerh4 = wx.BoxSizer(wx.HORIZONTAL)

	def __crearEtiquetas(self):
		# Creacion de etiquetas
		self.st00 = wx.StaticText(self, label="Selecciona ruta")
		font = self.st00.GetFont()
		font.PointSize += 2
		font = font.Bold()
		self.st00.SetFont(font)

		self.st01 = wx.StaticText(self, label='Unidad sin asignar')
		font = self.st01.GetFont()
		font.PointSize += 3
		font = font.Bold()
		self.st01.SetFont(font)

		self.st10 = wx.StaticText(self, label="Selecciona ruta")
		font = self.st10.GetFont()
		font.PointSize += 2
		font = font.Bold()
		self.st10.SetFont(font)

		self.st11 = wx.StaticText(self, label='Unidad sin asignar')
		font = self.st11.GetFont()
		font.PointSize += 3
		font = font.Bold()
		self.st11.SetFont(font)

	def __crearListas(self):
		# Creacion de listas
		self.__colors = []
		#__colorPro = (247, 248, 249)
		__colorPro = (250, 230, 222)
		__colorPro = (233, 251, 245)
		#__colorEdit = (249, 202, 130)

		__colorEdit = (236, 212, 173)
		__colorEdit = (196, 252, 233)

		__colorPro = (236, 252, 255)
		#__colorEdit = (62, 100, 255)
		__colorEdit = (138, 160, 255)

		if self.__listaEditable[0]:
			self.list_ctrl00 = EditableListCtrl(self, id = 10, style=wx.LC_REPORT | wx.BORDER_SUNKEN, columnas = 1)
			self.__colors.append(__colorEdit)
		else:
			self.list_ctrl00 = ProListCtrl(self, id = 10, style=wx.LC_REPORT | wx.BORDER_SUNKEN, columnas = 1)
			self.__colors.append(__colorPro)

		if self.__listaEditable[2]:
			self.list_ctrl01 = EditableListCtrl(self, id = 30, style=wx.LC_REPORT | wx.BORDER_SUNKEN, columnas = 2)
			self.__colors.append(__colorEdit)
		else:
			self.list_ctrl01 = ProListCtrl(self, id = 30, style=wx.LC_REPORT | wx.BORDER_SUNKEN, columnas = 2)
			self.__colors.append(__colorPro)

		if self.__listaEditable[1]:
			self.list_ctrl02 = EditableListCtrl(self, id = 20, style=wx.LC_REPORT | wx.BORDER_SUNKEN, columnas = 1)
			self.__colors.append(__colorEdit)
		else:
			self.list_ctrl02 = ProListCtrl(self, id = 20, style=wx.LC_REPORT | wx.BORDER_SUNKEN, columnas = 1)
			self.__colors.append(__colorPro)

		if self.__listaEditable[3]:
			self.list_ctrl03 = EditableListCtrl(self, id = 40, style=wx.LC_REPORT | wx.BORDER_SUNKEN, columnas = 2)
			self.__colors.append(__colorEdit)
		else:
			self.list_ctrl03 = ProListCtrl(self, id = 40, style=wx.LC_REPORT | wx.BORDER_SUNKEN, columnas = 2)
			self.__colors.append(__colorPro)

		# Color de fondo
		self.list_ctrl00.SetBackgroundColour(self.__colors[0])
		self.list_ctrl01.SetBackgroundColour(self.__colors[1])
		self.list_ctrl02.SetBackgroundColour(self.__colors[2])
		self.list_ctrl03.SetBackgroundColour(self.__colors[3])

		# Insercion de columnas
		self.list_ctrl00.InsertColumn(0, 'Directorios', width=wx.LIST_AUTOSIZE_USEHEADER)
		self.list_ctrl01.InsertColumn(0, 'Archivos', width=wx.LIST_AUTOSIZE_USEHEADER)
		self.list_ctrl02.InsertColumn(0, 'Directorios', width=wx.LIST_AUTOSIZE_USEHEADER)
		self.list_ctrl03.InsertColumn(0, 'Archivos', width=wx.LIST_AUTOSIZE_USEHEADER)

		# Modifacion de fuente
		self.list_ctrl00.SetFont(wx.Font(11, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
		self.list_ctrl01.SetFont(wx.Font(11, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
		self.list_ctrl02.SetFont(wx.Font(11, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
		self.list_ctrl03.SetFont(wx.Font(11, wx.DEFAULT, wx.NORMAL, wx.NORMAL))

	def __montarPaneles(self):
		__margen = 170 if self.resolucion[1] == 1080 else 90
		# Montamos estructura con los sizers
		self.sizerh1.Add(self.st00,1, wx.ALL, 5)
		self.sizerh1.Add(self.st01,1, wx.LEFT, __margen)
		#self.sizerh1.Add(self.st01,1, wx.ALIGN_RIGHT, 0)

		self.sizerh2.Add(self.st10, 1, wx.ALL, 5)
		self.sizerh2.Add(self.st11, 1, wx.LEFT, __margen)

		self.sizerh3.Add(self.list_ctrl00,1, wx.EXPAND, 0)
		self.sizerh3.Add(self.list_ctrl01,1, wx.EXPAND, 0)

		self.sizerh4.Add(self.list_ctrl02,1, wx.EXPAND, 0)
		self.sizerh4.Add(self.list_ctrl03,1, wx.EXPAND, 0)

		self.sizerv1.Add(self.sizerh1,0,0, 0)
		self.sizerv1.Add(self.sizerh3,1,wx.EXPAND, 0)

		self.sizerv2.Add(self.sizerh2,0,0, 0)
		self.sizerv2.Add(self.sizerh4,1,wx.EXPAND, 0)

		self.sizerh00.Add(self.sizerv1,1,wx.EXPAND, 0)
		self.sizerh00.Add(self.sizerv2,1,wx.EXPAND, 0)

		self.SetSizer(self.sizerh00)

	def __vaciarPaneles(self):
		self.sizerv1.Hide(self.sizerh3)
		self.sizerv1.Remove(self.sizerh3)
		self.sizerv1.Hide(self.sizerh1)
		self.sizerv1.Remove(self.sizerh1)
		self.__parent.SizerPrincipal.Layout()
		#self.__parent.Fit()

		self.sizerv2.Hide(self.sizerh4)
		self.sizerv2.Remove(self.sizerh4)
		self.sizerv2.Hide(self.sizerh2)
		self.sizerv2.Remove(self.sizerh2)
		self.__parent.SizerPrincipal.Layout()
		#self.__parent.Fit()

		self.sizerh00.Hide(self.sizerv1)
		self.sizerh00.Remove(self.sizerv1)

		self.sizerh00.Hide(self.sizerv2)
		self.sizerh00.Remove(self.sizerv2)
		self.__parent.SizerPrincipal.Layout()
		#self.__parent.Fit()

	def __refrescarLista(self, modo = 1, buscar = False):
		#print('Modo %d de edicion en lista' % modo)
		__buscar = False
		if self.resolucion[1] == 1080:
			__textoBase = 'Trabajando en unidad %s:\\'
			__maxC = 65
		else:
			__textoBase = 'Trabajando en %s:\\'
			__maxC = 40
		if modo == 1:
			self.list_ctrl00.ClearAll()
			self.list_ctrl01.ClearAll()

			self.list_ctrl00.SetBackgroundColour(self.__colors[0])
			self.list_ctrl01.SetBackgroundColour(self.__colors[1])

			self.list_ctrl00.InsertColumn(0, 'Directorios', width=wx.LIST_AUTOSIZE_USEHEADER)
			self.list_ctrl01.InsertColumn(0, 'Archivos', width=wx.LIST_AUTOSIZE)
			self.list_ctrl01.InsertColumn(1, 'Modificado', width=wx.LIST_AUTOSIZE)

			if self.path != '':
				aux = self.path
				contador = 1
				while len(aux) > __maxC:
					if contador == 5:
						break
					aux = aux.split('\\')
					aux[contador] = '..'
					aux = '\\'.join(aux)
					contador += 1

				self.st00.SetLabel(aux)
				if self.__listaFiltrada[0]:
					__textoBase += '    Filtro (.py)'
				self.st01.SetLabel(__textoBase % self.path[0])
			__path = self.path
			self.list_ctrl00.itemDataMap = {}
			self.list_ctrl01.itemDataMap = {}
			objetoD = self.list_ctrl00
			objetoF = self.list_ctrl01

			if buscar:
				if self.enfocado == 1:
					__buscar = 'D'
				elif self.enfocado == 3:
					__buscar = 'A'

		elif modo == 2:
			self.list_ctrl02.ClearAll()
			self.list_ctrl03.ClearAll()

			self.list_ctrl02.SetBackgroundColour(self.__colors[2])
			self.list_ctrl03.SetBackgroundColour(self.__colors[3])

			self.list_ctrl02.InsertColumn(0, 'Directorios', width=wx.LIST_AUTOSIZE_USEHEADER)
			self.list_ctrl03.InsertColumn(0, 'Archivos', width=wx.LIST_AUTOSIZE)
			self.list_ctrl03.InsertColumn(1, 'Modificado', width=wx.LIST_AUTOSIZE)

			if self.path2 != '':
				aux = self.path2
				contador = 1
				while len(aux) > __maxC:
					if contador == 5:
						break
					aux = aux.split('\\')
					aux[contador] = '..'
					aux = '\\'.join(aux)
					contador += 1

				self.st10.SetLabel(aux)
				if self.__listaFiltrada[1]:
					__textoBase += '    Filtro (.py)'
				self.st11.SetLabel(__textoBase % self.path2[0])
			__path = self.path2

			self.list_ctrl02.itemDataMap = {}
			self.list_ctrl03.itemDataMap = {}

			objetoD = self.list_ctrl02
			objetoF = self.list_ctrl03

			if buscar:
				if self.enfocado == 2:
					__buscar = 'D'
				elif self.enfocado == 4:
					__buscar = 'A'
		else:
			return False

		if __path == '':
			#print('Por que esta el path vacio?')
			return False
		walking = os.walk(__path)
		listaDir = []
		listaFiles = []
		indice = 0
		objetoD.itemDataMap = {}
		objetoF.itemDataMap = {}

		objetoD.itemDataMap[0] = '...'

		for root, dirs, files in walking:
			#print('raiz', root)
			#print(dirs)
			indice = 1
			for directorio in dirs:
				listaDir.append(directorio)
				if __buscar == 'D':
					if directorio.lower().find(buscar.lower()) > -1:
						objetoD.itemDataMap[indice] = directorio
						indice +=1
				else:
					objetoD.itemDataMap[indice] = directorio
					indice +=1
			indice = 0
			for file in files:
				#print(file)
				#print(time.gmtime(os.path.getmtime(os.path.join(__path, file))))
				#print(type(time.gmtime(os.path.getmtime(os.path.join(__path, file)))))
				#horaO = time.strftime('%H:%M %d/%m/%Y',time.gmtime(os.path.getmtime(os.path.join(__path, file))))
				#horaO = time.strftime('%H:%M %d/%m/%Y',time.localtime(os.path.getmtime(os.path.join(__path, file))))
				horaO = time.strftime('%Y/%m/%d %H:%M',time.localtime(os.path.getmtime(os.path.join(__path, file))))
				listaFiles.append((file,horaO))
				#print(type(horaO),horaO)
				if __buscar == 'A':
					if file.lower().find(buscar.lower()) > -1:
						if self.__listaFiltrada[modo - 1] and not file.endswith('.py'):
							continue
						objetoF.itemDataMap[indice] = [file,horaO]
						indice += 1
					else:
						continue
				else:
					if self.__listaFiltrada[modo - 1] and not file.endswith('.py'):
						#print(file)
						continue
					objetoF.itemDataMap[indice] = [file,horaO]
					indice += 1
			break

		#print(objetoF.itemDataMap)
		#__color = (200,200,200)
		__color = (225,225,225)
		__color2 = (95, 198, 213)

		#objetoD.InsertItem(0, '...')
		#objetoD.SetItemData(0, 0)
		#objetoD.SetItemBackgroundColour(0, __color)
		__indexD = 0
		__indexF = 0
		try:
			for key,value in objetoD.itemDataMap.items():
				objetoD.InsertItem(__indexD,value)
				objetoD.SetItemData(__indexD, key)
				__indexD +=1
			"""
			for item in listaDir:
				objetoD.InsertItem(__indexD, item)

				if __indexD % 2:
					objetoD.SetItemBackgroundColour(__indexD, __color2)
				else:
					objetoD.SetItemBackgroundColour(__indexD, __color)
			"""

			#if self.resolucion[1] != 1080:
			#	objetoD.SetColumnWidth(0,200)
			objetoD.SetColumnWidth(1,wx.LIST_AUTOSIZE_USEHEADER)
			self.__pintarFilas(modo)

			#print(objetoF.itemDataMap)
			for key,value in objetoF.itemDataMap.items():
				objetoF.InsertItem(__indexF,value[0])
				objetoF.SetItem(__indexF,1, value[1])
				objetoF.SetItemData(__indexF, key)
				"""
				if __indexF % 2:
					objetoF.SetItemBackgroundColour(__indexF, __color)
				else:
					objetoF.SetItemBackgroundColour(__indexF, __color2)
				"""
				__indexF +=1

			"""
			for item in listaFiles:
				if item[0].find('.py') > -1 and item[0].find('.pyc') == -1:
					objetoF.InsertItem(__indexF, item[0])
					objetoF.SetItem(__indexF,1, item[1])
					if __indexF % 2:
						objetoF.SetItemBackgroundColour(__indexF, __color)
					else:
						objetoF.SetItemBackgroundColour(__indexF, __color2)
					__indexF += 1
			"""
			if self.resolucion[1] == 1080:
				objetoF.SetColumnWidth(0,wx.LIST_AUTOSIZE_USEHEADER)
			else:
				objetoF.SetColumnWidth(0,150)
			objetoF.SetColumnWidth(1,wx.LIST_AUTOSIZE_USEHEADER)
			self.__pintarFilas(modo + 2)
		except Exception as e:
			print(e)
			print(__indexF)

	def __refrescar(self):
		self.__refrescarLista(1)
		self.__refrescarLista(2)

	def __alternarListas(self, modo = 'DESACTIVAR'):
		self.__vaciarPaneles()

		for child in self.GetChildren():
			#print(child)
			child.Destroy()
		if modo == 'DESACTIVAR':
			self.__listaEditable = [False, False, False, False]
		elif modo == 'ACTIVAR':
			self.__listaEditable = [True, True, True, True]
		else:
			self.__listaEditable[modo - 1] = not self.__listaEditable[modo - 1]
		self.__iniciarObjetos()
		self.__parent.SizerPrincipal.Layout()
		self.__refrescar()
		#self.__parent.SetSize(self.__size)
		#self.__parent.Maximize(True)
		#self.__parent.Update()
		#self.__parent.Layout()
		#self.__parent.Fit()
		#self.__parent.Show()
		"""
		self.__parent.SizerPrincipal.Layout()
		self.__parent.Maximize(True)
		self.__parent.Maximize(False)
		self.__parent.Maximize(True)
		self.__parent.Show()
		self.__parent.Raise()
		self.__parent.Update()
		"""
		#modo = modo if modo in [1,2] else modo - 2

	def __filtrarLista(self, id):
		if id == 'todo':
			self.__listaFiltrada = [True, True]
		elif id == 'nada':
			self.__listaFiltrada = [False, False]
		else:
			self.__listaFiltrada[id - 3] = not self.__listaFiltrada[id - 3]
		self.__refrescar()

	def __pintarFilas(self, id):
		__color = (225,225,225)
		if id == 1:
			objeto = self.list_ctrl00
			__color2 = (247,148,91)
			__color2 = (178, 252, 255)
		elif id ==2:
			objeto = self.list_ctrl02
			__color2 = (247,148,91)
			__color2 = (178, 252, 255)
		elif id == 3:
			objeto = self.list_ctrl01
			__color2 = (134,188,236)
			__color2 = (94, 223, 255)
		elif id == 4:
			objeto = self.list_ctrl03
			__color2 = (134,188,236)
			__color2 = (94, 223, 255)
		#sel = objeto.GetSelection()
		#print(sel)
		#text = objeto.GetString(sel)
		#print(text)

		#azules
		#__color2 = (175,225,236)
		#__color2 = (134,188,236)
		#naranjas
		#__color2 = (247,148,91)

		count = objeto.GetItemCount()
		#print(count)
		for i in range(count):
			#item = objeto.GetItem(i,0)
			#print(item.GetText())
			if i > 0 and i % 2:
				objeto.SetItemBackgroundColour(i, __color2)
			else:
				objeto.SetItemBackgroundColour(i, __color)

	def __desactivarEdicion(self):
		self.__alternarListas('DESACTIVAR')
		try:
			self.__parent.SetStatusText("Copyright TOI")
		except Exception as e:
			print(e)

	def __activarEdicion(self):
		self.__alternarListas('ACTIVAR')
		try:
			self.__parent.SetStatusText("Copyright TOI - //MODO EDICION ACTIVADO//")
		except Exception as e:
			print(e)

	def __cambiarDirectorio(self, modo = 1,  bajar = False):
		if modo == 1:
			__path = self.path
		elif modo == 2:
			__path = self.path2
		if not bajar:
			ubicador = __path.split('\\')
			#print(ubicador)
			if len(ubicador) > 2:
				limpia = '\\' + ubicador[-1]
				__path = __path.replace(limpia, '')
			elif len(ubicador) == 2:
				__path = __path.replace(ubicador[-1], '')
		else:
			if __path[-1] != '\\':
				__path = __path + '\\' + bajar
			else:
				__path = __path + bajar

		if modo == 1:
			self.path = __path
		elif modo == 2:
			self.path2 = __path

	def __buscarPareja(self, modo, texto):
		__color = (225,225,225)
		__color2 = (94, 223, 255)
		__color3 =  (250, 83, 83)
		if modo == 1:
			objeto = self.list_ctrl02
		elif modo == 2:
			objeto = self.list_ctrl00
		elif modo == 3:
			objeto = self.list_ctrl03
		elif modo == 4:
			objeto = self.list_ctrl01
		count = objeto.GetItemCount()
		#print(objeto.GetTopItem())
		#print(objeto.GetCountPerPage())
		for i in range(count):
			item = objeto.GetItem(i,0)
			#print(item.GetText())
			#print(item.GetState())
			if item.GetState() != 0: # == 6
				#item.SetStateMask(0)
				#item.SetState(wx.LIST_STATE_SELECTED|wx.LIST_STATE_FOCUSED)
				objeto.Select(i, False)
				#objeto.Focus(i)
				#print(item.GetState())
			if item.GetText() == texto:
				objeto.SetItemBackgroundColour(i, __color3)
				objeto.EnsureVisible(i)
			elif i > 0 and i % 2:
				objeto.SetItemBackgroundColour(i, __color2)
			else:
				objeto.SetItemBackgroundColour(i, __color)

	def __copiarArchivo(self, modo, nombre):
		if not os.path.isdir(self.path) or not os.path.isdir(self.path2):
			print('Uno de los directorios no es valido para poder copiar')
			return False
		if self.path[-1] != '\\':
			__path = self.path + '\\'
		else:
			__path = self.path

		if self.path2[-1] != '\\':
			__path2 = self.path2 + '\\'
		else:
			__path2 = self.path2

		if modo == 3:
			__origenPath = __path + nombre
			__destinoPath = __path2 + nombre
			__actualiza = 2
		elif modo == 4:
			__origenPath = __path2 + nombre
			__destinoPath = __path  + nombre
			__actualiza = 1
		else:
			print('Modo %d para carpeta %s' % (modo, nombre))
			return False

		"""
		print('Estamos en modo %d' % modo)
		print('Habria que copiar')
		print('De %s' % __origenPath)
		print('A %s' % __destinoPath)
		"""
		try:
			shutil.copy2(__origenPath, __destinoPath)
		except Exception as e:
			print(e)

		self.__refrescarLista(__actualiza)

	def __borrarArchivo(self, nombre):
		#print(nombre)
		if os.path.isfile(nombre):
			print('%s es un archivo y lo voy a borrar' % nombre)
			os.remove(nombre)
			return True
		return False

	def __moverArchivo(self, modo, nombre):
		if not os.path.isdir(self.path) or not os.path.isdir(self.path2):
			print('Uno de los directorios no es valido para poder mover')
			return False
		print('mover archivo %s' % nombre)

	def __startLanzar(self, nombre):
		#print('start "" "%s"' % nombre)
		comando = 'start "" "%s"' % nombre
		hilo = Thread(target=os.system, args=(comando,))
		hilo.start()

	def __ejecutarPython(self, nombre, modo = ''):
		comando = 'python%s "%s"' % (modo, nombre)
		#print(comando)
		hilo = Thread(target=os.system, args=(comando,))
		hilo.start()
		#os.system(comando)

	def __renombrar(self, nombreO, nombreD):
		#print('Renombrar: %s a %s' % (nombreO, nombreD))
		if nombreO == nombreD:
			return False
		if os.path.exists(nombreO):
			os.rename(nombreO, nombreD)

	def __copiarDirectorio(self, modo, texto):
		if self.path == '' or self.path2 == '':
			return False
		if modo == 1:
			__origen = self.path
			__destino = self.path2
		else:
			__origen = self.path2
			__destino = self.path

		__root = texto
		__origen = __origen + '\\' + __root
		__destino = __destino + '\\' + __root
		print('origen: %s' % __origen)
		print('destino: %s' % __destino)
		print('carpeta: %s' % __root)
		if not os.path.exists(__destino):
			print('destino no existe, se crea')
			#os.mkdir(ruta_destino)
		else:
			print('destino existe')

		i = j = z = 0
		for root, dirs, files in os.walk(__origen):
			for directorio in dirs:
				ruta_destino = os.path.join(root.replace(__origen, __destino), directorio)
				if not os.path.exists(ruta_destino):
					#os.mkdir(ruta_destino)
					#print('Aqui creo carpeta')
					i += 1
				else:
					j += 1
					#print('Ruta destino existe: %s' % ruta_destino)

			for file in files:
				if file.endswith('.py'):

					__fileO = os.path.join(root, file)
					__fileD = os.path.join(root.replace(__origen,__destino),file)

					#print('Tocaria copiar %s en %s' % (__fileO, __fileD))
					z += 1
					#shutil.copy2(__fileO, __fileD))

		resultado = 'Se han copiado %d directorios de los cuales\n%d ya existian y %d se han creado.\nSe han copiado un total de %d archivos.' % (i+j, j, i, z)
		print(resultado)
		wx.MessageBox(resultado, 'Resultado copia', wx.OK|wx.ICON_INFORMATION)

	def __moverDirectorio(self):
		pass

	def __borrarDirectorio(self):
		pass

	def __emergente(self, opciones):
		self.popup_menu = wx.Menu()
		self.opcionesPopUp = {}
		for opcion in opciones:
			#__menu.Append(wx.NewId(), opcion)
			item = self.popup_menu.Append(-1, opcion)
			#print(item)
			self.opcionesPopUp[item] = opcion
			self.Bind(wx.EVT_MENU, self.OnPopUp, item)

		self.__accionPopUp = ''
		self.PopupMenu(self.popup_menu)
		self.popup_menu.Destroy()

	def refrescarLista(self, modo = 1):
		self.__refrescarLista(modo)

	def buscarLista(self, texto):
		if self.enfocado in [1,3]:
			modo = 1
		elif self.enfocado in [2,4]:
			modo = 2
		else:
			return False
		self.__refrescarLista(modo, texto)

	def emergente(self, opciones):
		self.__emergente(opciones)
		return False if self.__accionPopUp == '' else True

	def desactivarEdicion(self):
		self.__desactivarEdicion()

	def OnList(self,event):
		#print(event.GetItem())
		#print(event.m_itemIndex)
		select = event.GetText()
		__id = int(event.GetId() / 10)

		#print('select: %s' % select)
		#print('select2: %s' % select2)
		#print('Entro aqui aunque no proceda?')
		if select == '...':
			__bajar = False
		else:
			__bajar = select

		if __id in [1,2]:
			self.__cambiarDirectorio(modo = __id, bajar = __bajar)
			self.__refrescarLista(modo = __id)
		elif __id in [3,4]:
			if __id == 4:
				opciones =['confirma copiar']
				self.__emergente(opciones)
				if self.__accionPopUp == '':
					return False
			self.__copiarArchivo(__id, __bajar)

	def OnPressKey(self, event):
		try:
			keycode = event.GetKeyCode()
			#print(keycode)
			__id = int(event.GetId() / 10)
			#print(__id)
			texto = event.GetText()
			#print(texto)
		except:
			print('return')
			return False

		if keycode == 127: # 127 -> SUPR; 27 -> ESC
			__mas = '\\'
			if __id == 3:
				__path = self.path
				opciones =['confirma borrar']
				self.__emergente(opciones)
				if self.__accionPopUp == '':
					return False
				if self.path[-1] == '\\':
					__mas = ''
			elif __id == 4:
				__path = self.path2
				if self.path2[-1] == '\\':
					__mas = ''
			else:
				return False
			self.__borrarArchivo(__path + __mas + texto)
			self.__refrescarLista(__id - 2)
		elif keycode == 341: # F2
			#print(event.GetEventObject())
			#print(keycode)
			#print(__id)
			#print(texto)
			self.__alternarListas(__id)

	def OnMouseRight(self,event):
		try:
			__id = int(event.GetId() / 10)
			#print(__id)
			texto = event.GetText()
			#print(texto)
			#print(event.GetPosition())
		except Exception as e:
			print(e)
			return False

		if __id in [1,2]:
			#opciones = ['copiar', 'mover', 'renombrar', 'borrar']
			opciones = ['copiar', 'mover', 'renombrar']
			__funciones = {'copiar':self.__copiarDirectorio, 'mover':self.__moverDirectorio, 'renombrar':self.__renombrar,'borrar':self.__borrarDirectorio, 'activar edicion':self.__alternarListas, 'desactivar edicion':self.__alternarListas}
		elif __id in [3,4]:
			opciones = ['copiar', 'mover', 'renombrar', 'borrar', 'lanzar', 'python', 'python3']
			if self.__listaFiltrada[__id - 3]:
				opciones.append('desfiltrar')
			else:
				opciones.append('filtrar')
			#opciones = ['copiar', 'mover', 'renombrar', 'lanzar']
			__funciones = {'copiar':self.__copiarArchivo, 'mover':self.__moverArchivo, 'renombrar':self.__renombrar,'borrar':self.__borrarArchivo, 'lanzar':self.__startLanzar, 'activar edicion':self.__alternarListas, 'desactivar edicion':self.__alternarListas, 'filtrar':self.__filtrarLista, 'desfiltrar':self.__filtrarLista, 'python':self.__ejecutarPython, 'python3':self.__ejecutarPython}
		else:
			return False

		if self.__listaEditable[__id - 1]:
			opciones.append('desactivar edicion')
		else:
			opciones.append('activar edicion')
			opciones.remove('renombrar')
		__mas = '\\'
		if __id in [1,3]:
			if self.path[-1] == '\\':
				__mas = ''
			__ruta = self.path + __mas + texto
			__refresh = 1

		elif __id in [2,4]:
			if self.path2[-1] == '\\':
				__mas = ''
			__ruta = self.path2 + __mas + texto
			__refresh = 2

		self.__emergente(opciones)
		#print('Tengo que %s la carpeta %s' % (self.__accionPopUp, texto))
		if self.__accionPopUp == '':
			return False
		elif self.__accionPopUp == 'borrar' and __id in [1,3]:
			opciones = ['confirma borrar']
			self.__emergente(opciones)
			if self.__accionPopUp == '':
				return False
			self.__accionPopUp = 'borrar'
		elif self.__accionPopUp == 'copiar' and __id in [2,4]:
			opciones =['confirma copiar']
			self.__emergente(opciones)
			if self.__accionPopUp == '':
				return False
			self.__accionPopUp = 'copiar'

		if self.__accionPopUp in ['borrar', 'lanzar', 'python', 'python3']:
			if self.__accionPopUp == 'python3':
				__funciones[self.__accionPopUp](__ruta, '3')
			else:
				__funciones[self.__accionPopUp](__ruta)
			if self.__accionPopUp == 'borrar':
				self.__refrescarLista(__refresh)
		elif self.__accionPopUp in ['copiar', 'mover']:
				__funciones[self.__accionPopUp](__id, texto)
		elif self.__accionPopUp in ['activar edicion', 'desactivar edicion', 'filtrar', 'desfiltrar']:
			__funciones[self.__accionPopUp](__id)

		self.__accionPopUp = ''

	def OnPopUp(self,event):
		try:
			__id = event.GetId()
			#print(__id)
			item = self.popup_menu.FindItemById(__id)
			self.__accionPopUp = self.opcionesPopUp[item]
		except Exception as e:
			print(e)
			return False

	def OnRightClick(self, event):
		#print(event.GetId())
		#print('Orc')
		opciones = ['refrescar', 'activar edicion', 'desactivar edicion']
		if not (self.__listaFiltrada[0] and self.__listaFiltrada[1]):
			opciones.append('filtrar')
		else:
			opciones.append('desfiltrar')
		self.__emergente(opciones)
		#print('Tengo que %s la carpeta %s' % (self.__accionPopUp, texto))
		if self.__accionPopUp == '':
			return False
		if self.__accionPopUp == 'refrescar':
			self.__refrescar()
		elif self.__accionPopUp == 'activar edicion':
			self.__activarEdicion()
		elif self.__accionPopUp == 'desactivar edicion':
			self.__desactivarEdicion()
		elif self.__accionPopUp == 'filtrar':
			self.__filtrarLista('todo')
			self.__refrescar()
		elif self.__accionPopUp == 'desfiltrar':
			self.__filtrarLista('nada')
			self.__refrescar()

	def OnUpdateItem(self, event):
		#event.GetEventObject()
		#__id directorios 1,2 archivos 3,4
		__id = int(event.GetId() / 10)
		#print(__id)
		__item = event.GetLabel()
		if __item == '':
			return False
		#print('Item: %s' % __item)
		__indice = event.GetIndex()
		#print('Num item: %d' % __indice)
		__columna = event.GetColumn()
		#print('Num columna: %d' % __columna)
		if __columna == 1:
			return False
		if __id == 1:
			__objeto = self.list_ctrl00
			__ruta =self.path
			modo = 1
		elif __id == 2:
			__objeto = self.list_ctrl02
			__ruta =self.path2
			modo = 2
		elif __id == 3:
			__objeto = self.list_ctrl01
			__ruta =self.path
			modo = 1
		elif __id == 4:
			__objeto = self.list_ctrl03
			__ruta =self.path2
			modo = 2

		__nombreOriginal = __ruta + '\\' + __objeto.GetItem(__indice, __columna).GetText()
		__nombreFinal = __ruta + '\\' + __item

		self.__renombrar(__nombreOriginal, __nombreFinal)
		#print(__objeto.GetItem(__indice, __columna).GetText())

	def OnColClick(self,event):
		#print('Col click')
		#print(event.GetId())
		__id = int(event.GetId() / 10)
		event.Skip()
		self.__pintarFilas(__id)

	def OnSelected(self, event):
		try:
			texto = event.GetText()
		except:
			texto = ''
		__id = int(event.GetId() / 10)
		#item = event.GetItem()
		#print(item.GetText())
		#print(item.GetState())
		#print(texto)
		#print(__id)
		if texto == '':
			self.__pintarFilas(1)
			self.__pintarFilas(2)
			self.__pintarFilas(3)
			self.__pintarFilas(4)
			return True
		elif texto == '...':
			return True

		if __id in [3,4]:
			self.__pintarFilas(1)
			self.__pintarFilas(2)
		elif __id in [1,2]:
			self.__pintarFilas(3)
			self.__pintarFilas(4)

		self.__pintarFilas(__id)
		self.__buscarPareja(__id, texto)

	def OnReleaseKey(self, event):
		keycode = event.GetKeyCode()
		print(keycode)
		__id = int(event.GetId() / 10)
		print(__id)

	def onFocus(self, event):
		#print('onfoco')
		self.enfocado = int(event.GetId() / 10)

	def __resolucion(self):
		# (1280, 1024)
		# (1920, 1080)
		user32 = windll.user32
		screensize = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)
		return screensize

if __name__ == "__main__":
	ventana = wx.App()
	frame = wxCommander()
	#frame.Show()
	ventana.MainLoop()


"""
Module that contains String related functions.
"""
def is_name(name, ignore_case=False):
    """Checks if given input contains first name and surname.
    Parameters
    ----------
    value : `name`
        The value that is used for checking if it's a valid name.
    value : `ignore_case`
        The value is used for determining whether to ignore cases from the name
    Returns
    -------
    absolute value : `boolean`
        True or False.
    """
    firstname_and_surname = name.split(" ")
    if len(firstname_and_surname) == 2:
        firstname = firstname_and_surname[0]
        surname = firstname_and_surname[1]
        if ignore_case == False:
            if firstname[0].isupper() and surname[0].isupper():
                if len(firstname) >= 2 and len(surname) >= 2:
                    return True
                else:
                    return False
            #else for isupper() check
            else:
                return False
        #else for ignore_case check
        else:
            if len(firstname) >= 2 and len(surname) >= 2:
                return True
            else:
                return False
    #else for checking if there is a first name and a surname
    else:
        return False

def get_title(title, amount, char):
    """The method is used for creating a title and a frame for it with a specified character.
    Parameters
    ----------
    value : `title`
        This is a string that contains the title.
    value : `amount`
        This specifies the length of the frame for the title.
    value : `char`
        This specifies which character is used for the frame around the title.
    Returns
    -------
    absolute value : `String`
        If the frame length is greater than title length,
        a title surrounded by a frame of specified characters is returned,
        otherwise a text explaining that creating the frame failed.
    """
    result = ""
    top_layer = ""
    middle_layer = ""
    bottom_layer = ""
    if len(title) <= amount:
        #The top layer is formed
        for x in range(amount):
            top_layer = top_layer + char

        #The middle layer is formed
        i = 0
        frame_middle_point = (int) ((amount / 2) - 1)
        title_middle_point = (int) ((len(title) / 2) - 1)
        title_starting_point = frame_middle_point - title_middle_point
        if len(title) <= amount - 3:
            while i < amount:
                if i == 0:
                    middle_layer = middle_layer + char
                    i = i + 1
                elif i == amount - 1:
                    middle_layer = middle_layer + char
                    i = i + 1
                elif i == title_starting_point:
                    j = 0
                    for x in range(len(title)):
                        middle_layer = middle_layer + title[j]
                        j = j + 1
                        i = i + 1
                else:
                    middle_layer = middle_layer + " "
                    i = i + 1
        else:
            while i < amount:
                middle_layer = middle_layer + title[i]
                i = i + 1
        # bottom layer is formed
        for x in range(amount):
            bottom_layer = bottom_layer + char

        #creating the final result by piling layers on top of each other
        #and then returning the result
        result = f"""{top_layer}
{middle_layer}
{bottom_layer}"""
        return result

    else:
        result = "invalid values, title length is > graph length"
    return result


"""
Slow Program
Henry Lei
Spring 2020
"""

def convert(a):
    a[0] = 0
    a.append(143)
    return a

def convert_string(x):
    x = "lei"
    return x

def convert_int(y):
    y = y + 1
    return y

def xmain():
    nums = [12, -4]
    s = "henry"
    y = 6
    b = convert(nums)
    c = convert_string(s)
    d = convert_int(y)

    print(b)
    print(nums)
    print(c)
    print(s)
    print(d)
    print(y)

def divide(x, y):
    print("in function...")
    # Q3
    return x / y

def main():
    a = 17
    b = 5
    print("in main...")
    result = divide(a, b)
    print(result)

if __name__ == "__main__":
    main()


# coding: latin-1

"""Module für die Anmeldung."""

import string

from ebkus.app import Request
from ebkus.app.ebapi import Akte, Fall, Anmeldung, cc
from ebkus.app.ebapih import get_codes, mksel
from ebkus.app_surface.klientenkarte_templates import detail_view_anmeldung_t
from ebkus.app_surface.standard_templates import *
from ebkus.app_surface.anmeldung_templates import *

class anmneu(Request.Request):
    """Neue Anmeldung eintragen. (Tabelle: Anmeldung)"""

    permissions = Request.UPDATE_PERM

    def processForm(self, REQUEST, RESPONSE):
        mitarbeiterliste = self.getMitarbeiterliste()
        user = self.user
        if self.form.has_key('fallid'):
            fallid = self.form.get('fallid')
        else:
            self.last_error_message = "Keine ID für den Fall erhalten"
            return self.EBKuSError(REQUEST, RESPONSE)
        fall = Fall(int(fallid))
        akte = Akte(fall['akte_id'])
        bezugspersonen = akte['bezugspersonen']
        bezugspersonen.sort('verw__sort')
        zugangsarten = get_codes('fszm')

        # Datum des Fallbeginns und Nachname der 1 Bezugspers. zur Übernahme
        # im Formular anbieten.

        anmeldung = Anmeldung()
        anmeldung['ad'] = fall['bgd']
        anmeldung['am'] = fall['bgm']
        anmeldung['ay'] = fall['bgy']
        if bezugspersonen:
            b1 = bezugspersonen[0]
            anmeldung['von'] = b1['na']
            anmeldung['mtl'] = b1['tl1']
        else:
            anmeldung['von'] = ''
            anmeldung['mtl'] = ''

            # Für FORM-HIDDEN-VALUES

        hidden ={'file': 'anmeinf'}
        anmid = Anmeldung().getNewId()
        hiddenid ={'name': 'anmid', 'value': anmid}

        # Liste der Templates als String

        res = []
        res.append(head_normal_t %("Neue Anmeldeinformation eintragen"))
        res.append(anmneuvon_t % anmeldung)
        mksel(res, codeliste_t, zugangsarten)
        res.append(anmneuempfehlung_t % anmeldung)
        res.append(formhiddenvalues_t % hidden)
        res.append(formhiddennamevalues_t % hiddenid)
        res.append(anmneuende_t % fall)
        return string.join(res, '')

class updanm(Request.Request):
    """Anmeldung ändern. (Tabelle: Anmeldung)"""

    permissions = Request.UPDATE_PERM

    def processForm(self, REQUEST, RESPONSE):
        mitarbeiterliste = self.getMitarbeiterliste()
        user = self.user
        if self.form.has_key('anmid'):
            id = self.form.get('anmid')
        else:
            self.last_error_message = "Keine ID für die Anmeldung erhalten"
            return self.EBKuSError(REQUEST, RESPONSE)
        anmeldung = Anmeldung(int(id))
        fall = Fall(anmeldung['fall_id'])
        akte = Akte(fall['akte_id'])
        zugangsarten = get_codes('fszm')

        # Für FORM-HIDDEN-VALUES

        hidden ={'file': 'updanm'}

        # Liste der Templates als String

        res = []
        res.append(head_normal_t % ("Anmeldeinformation ändern"))
        res.append(anmneuvon_t % anmeldung)
        mksel(res, codeliste_t, zugangsarten, 'id', anmeldung['zm'])
        res.append(updanmempfehlung_t % anmeldung)
        res.append(formhiddenvalues_t % hidden)
        res.append(anmupdende_t % fall)
        return string.join(res, '')

class viewanm(Request.Request):
    """Anmeldung ändern. (Tabelle: Anmeldung)"""

    permissions = Request.UPDATE_PERM

    def processForm(self, REQUEST, RESPONSE):
        mitarbeiterliste = self.getMitarbeiterliste()
        user = self.user
        if self.form.has_key('anmid'):
            id = self.form.get('anmid')
        else:
            self.last_error_message = "Keine ID für die Anmeldung erhalten"
            return self.EBKuSError(REQUEST, RESPONSE)
        anmeldung = Anmeldung(int(id))
        fall = Fall(anmeldung['fall_id'])
        akte = Akte(fall['akte_id'])
        zugangsarten = get_codes('fszm')

        hidden ={'file': 'updanm'}
        res = []
        titel = ("Detailansicht: Anmeldekontakt von " + akte['vn'] + " " + akte['na'])
        res.append(head_normal_ohne_help_t %(titel))
        res.append(detail_view_anmeldung_t % anmeldung)

        return string.join(res, '')


from flask import jsonify, request
from flask_classy import route

from .models import Lightbox
from .services import send_get

class LightBoxMixin:

    @route("/add-to-lightbox/", methods=["POST"])
    def add_img_to_lightbox(self):
        lightbox_id = request.form.get('lightbox', '')
        token = request.form.get('token', '')
        lightbox = Lightbox(lightbox_id)

        return jsonify({'status': lightbox.append_item(token)})

    @route("/create-lightbox/", methods=["POST"])
    def create_lightbox(self):
        title = request.form.get('title', '')
        lightbox = Lightbox().create(title)

        return jsonify({'title': lightbox.title,
                        'lightBoxId': lightbox.lightBoxId})

    def get_lightboxes(self):
        resp = []
        status_code, response = send_get('image/lightboxes', nocache=True)
        if status_code == 200:
            resp = response['values']
        return resp