import torch
import torch.nn as nn
import torch.nn.functional as F
import os
import os.path as osp
import sys
path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(path)

import clip
from tools.configer import Configer
from lib.get_dataloader import get_data_loader
import cv2
import numpy as np
import matplotlib.pyplot as plt
import clip
from PIL import Image
import lib.transform_cv2 as T
import torch.nn.functional as F
import random
import pickle

def get_img_for_everyclass(configer, dataset_id=None):
    n_datasets = configer.get("n_datasets")

    num_classes = []
    for i in range(1, n_datasets + 1):
        num_classes.append(configer.get("dataset" + str(i), "n_cats"))

    dls = get_data_loader(configer, aux_mode='ret_path', distributed=False)

    img_lists = []
    lb_lists  = []
    lb_info_list = []
    for i in range(0, n_datasets):
        this_img_lists = []
        this_lb_lists = []
        lb_info_list.append(dls[i].dataset.lb_map)

        if dataset_id != None and i != dataset_id:
            img_lists.append(this_img_lists)
            lb_lists.append(this_lb_lists)
            continue
        # print("cur dataset id： ", i)

        for label_id in range(0, num_classes[i]):
            this_img_lists.append([])
            this_lb_lists.append([])

        for im, lb, lbpth in dls[i]:
            im = im[0]
            lb = lb.squeeze()
            for label_id in range(0, num_classes[i]):
                if len(this_img_lists[label_id]) < 100 and (lb == label_id).any():
                    this_img_lists[label_id].append(im)
                    this_lb_lists[label_id].append(lbpth)

        for j, lb in enumerate(this_lb_lists):
            if len(lb) == 0:
                print("the number {} class has no image".format(j))

        img_lists.append(this_img_lists)
        lb_lists.append(this_lb_lists)

    return img_lists, lb_lists, lb_info_list

def get_img_for_everyclass_single(configer, dls):
    n_datasets = configer.get("n_datasets")

    num_classes = []
    for i in range(1, n_datasets + 1):
        num_classes.append(configer.get("dataset" + str(i), "n_cats"))

    # dls = get_data_loader(configer, aux_mode='ret_path', distributed=False)
    dl_iters = [iter(dl) for dl in dls]

    img_lists = []
    lb_lists  = []
    for i in range(0, n_datasets):
        # print("cur dataset id： ", i)
        this_img_lists = []
        this_lb_lists = []
        for label_id in range(0, num_classes[i]):
            this_img_lists.append([])
            this_lb_lists.append([])

        cur_num = 0
        while True:
            try:
                im, lb, lbpth = next(dl_iters[i])
                while torch.min(lb) == 255:
                    im, lb, lbpth = next(dl_iters[i])

                if not len(im) == 1:
                    raise StopIteration
            except StopIteration:
                break

            im = im[0]
            lb = lb.squeeze()
            for label_id in range(0, num_classes[i]):
                if (lb == label_id).any():
                    this_img_lists[label_id].append(im)
                    this_lb_lists[label_id].append(lbpth)

            # print('cur_num: ', cur_num)
            # print('num_classes: ', num_classes[i])
            # print(lbpth)
            # if cur_num == num_classes[i]:
            #     break

        for j, lb in enumerate(this_lb_lists):
            if len(lb) == 0:
                print("the number {} class has no image".format(j))

        img_lists.append(this_img_lists)
        lb_lists.append(this_lb_lists)

    return img_lists, lb_lists

def crop_image_by_label_value(img, label, label_value):
    # 将标签二值化
    binary = np.zeros_like(label, dtype=np.uint8)
    binary[label == label_value] = 255

    binary = cv2.convertScaleAbs(binary)

    # 执行闭运算操作
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    closed = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)

    # 计算轮廓
    contours, _ = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

#     # 找到覆盖所有轮廓的最小矩形
#     max_rect = cv2.minAreaRect(np.concatenate(contours))

#     # 获取最大包围盒的坐标
#     x, y, w, h = cv2.boundingRect(np.int0(cv2.boxPoints(max_rect)))
#     print(x, y, w, h)

    # 计算每个包围盒的面积并找到面积最大的包围盒
    max_area = 0
    max_bbox = None
    for contour in contours:
        bbox = cv2.boundingRect(contour)
        area = bbox[2] * bbox[3]
        if area > max_area:
            max_area = area
            max_bbox = bbox

    # 如果没有找到任何包围盒，返回空图像
    if max_bbox is None:
        return np.zeros_like(img)

    # 裁剪图像
    x, y, w, h = max_bbox

#     # 获取包围盒
#     x, y, w, h = cv2.boundingRect(contours[4])
#     print(x, y, w, h)

    # 裁剪图像
    # print(img.shape)
    cropped = img[y:y+h, x:x+w, :]

    # 将不属于该标签的像素点替换为指定的值
    label_roi = binary[y:y+h, x:x+w]

    k = np.ones((5, 5), np.uint8)
    dilated = cv2.dilate(label_roi, kernel=k)

    mask = np.ones_like(cropped, dtype=bool)
    mask[dilated != 255] = False
    cropped[~mask] = 128

    h, w, _ = cropped.shape
    if h < w:
        top_padding = (w - h) // 2
        bottom_padding = w - h - top_padding
        cropped = cv2.copyMakeBorder(cropped, top_padding, bottom_padding, 0, 0, cv2.BORDER_CONSTANT, value=[128, 128, 128])
    elif h > w:
        left_padding = (h - w) // 2
        right_padding = h - w - left_padding
        cropped = cv2.copyMakeBorder(cropped, 0, 0, left_padding, right_padding, cv2.BORDER_CONSTANT, value=[128, 128, 128])

    # 返回裁剪后的图像
    return cropped

def gen_image_features(configer, dataset_id=None):
    img_lists, lb_lists, lb_info_list = get_img_for_everyclass(configer, dataset_id)

    n_datasets = configer.get('n_datasets')
    to_tensor = T.ToTensor(
                mean=(0.48145466, 0.4578275, 0.40821073), # clip , rgb
                std=(0.26862954, 0.26130258, 0.27577711),
            )
    device = "cuda" if torch.cuda.is_available() else "cpu"
    model, _ = clip.load("ViT-B/32", device=device)
    with torch.no_grad():
        out_features = []
        for idx in range(0, n_datasets):
            this_label_info = lb_info_list[idx]
            if dataset_id != None and idx != dataset_id:
                continue
            print("dataset_id: ", idx)
            for i, im_lb_list in enumerate(zip(img_lists[idx], lb_lists[idx])):
                im_list, lb_list = im_lb_list
                if len(im_list) == 0:
                    print("why dataset_id: ", idx)
                    continue
                image_features_list = []
                for im_path, lb_path in zip(im_list, lb_list):
                    image = cv2.imread(im_path)
                    # print(lb_path[0])
                    lb = cv2.imread(lb_path[0], 0)
                    lb = this_label_info[lb]
                    if image is None:
                        print(im_path)
                        continue
                    # lb = lb.numpy()
                    cropped_img = crop_image_by_label_value(image, lb, i)

                    im_lb = dict(im=cropped_img, lb=lb)
                    im_lb = to_tensor(im_lb)
                    img = im_lb['im'].cuda()
                    img = F.interpolate(img.unsqueeze(0), size=(224, 224))
                    image_features = model.encode_image(img).type(torch.float32)
                    image_features_list.append(image_features)

                # print("im_lb_list: ", im_lb_list)
                img_feat = torch.cat(image_features_list, dim=0)
                mean_feats = torch.mean(img_feat, dim=0, keepdim=True)
                # print(mean_feats.shape)
                out_features.append(mean_feats)

    return out_features

def gen_image_features_single(configer, dls, gen_feature=False):
    if gen_feature is False:
        img_lists, lb_lists = get_img_for_everyclass_single(configer, dls)
    else:
        img_lists, lb_lists = dls

    n_datasets = configer.get('n_datasets')
    to_tensor = T.ToTensor(
                mean=(0.48145466, 0.4578275, 0.40821073), # clip , rgb
                std=(0.26862954, 0.26130258, 0.27577711),
            )
    device = "cuda" if torch.cuda.is_available() else "cpu"
    model, _ = clip.load("ViT-B/32", device=device)
    with torch.no_grad():
        out_features = []
        for dataset_id in range(0, n_datasets):
            print("dataset_id: ", dataset_id)
            for i, im_lb_list in enumerate(zip(img_lists[dataset_id], lb_lists[dataset_id])):
                im_list, lb_list = im_lb_list
                im_lb_zip_list = list(zip(im_list, lb_list))
                if len(im_list) == 0:
                    print("why dataset_id: ", dataset_id)
                    continue
                image_features_list = []
                im_path, lb_path = random.choice(im_lb_zip_list)
                image = cv2.imread(im_path)
                # print(lb_path[0])
                lb = cv2.imread(lb_path[0], 0)
                if image is None:
                    print(im_path)
                    continue
                # lb = lb.numpy()
                cropped_img = crop_image_by_label_value(image, lb, i)

                im_lb = dict(im=cropped_img, lb=lb)
                im_lb = to_tensor(im_lb)
                img = im_lb['im'].cuda()
                img = F.interpolate(img.unsqueeze(0), size=(224, 224))
                image_features = model.encode_image(img).type(torch.float32)
                image_features_list.append(image_features)

                # print("im_lb_list: ", im_lb_list)
                img_feat = torch.cat(image_features_list, dim=0)
                mean_feats = torch.mean(img_feat, dim=0, keepdim=True)
                # print(mean_feats.shape)
                out_features.append(mean_feats)

    return out_features, [img_lists, lb_lists]

def gen_image_features_storage(configer, dataset_id):
    img_lists, lb_lists = get_img_for_everyclass(configer, dataset_id)

    n_datasets = configer.get('n_datasets')
    to_tensor = T.ToTensor(
                mean=(0.48145466, 0.4578275, 0.40821073), # clip , rgb
                std=(0.26862954, 0.26130258, 0.27577711),
            )
    device = "cuda" if torch.cuda.is_available() else "cpu"
    model, _ = clip.load("ViT-B/32", device=device)
    with torch.no_grad():
        this_datasets_feats = []
        print("dataset_id: ", dataset_id)
        for i, im_lb_list in enumerate(zip(img_lists[dataset_id], lb_lists[dataset_id])):
            im_list, lb_list = im_lb_list
            if len(im_list) == 0:
                print("why dataset_id: ", dataset_id)
                continue
            image_features_list = []
            for im_path, lb_path in zip(im_list, lb_list):
                image = cv2.imread(im_path)
                # print(lb_path[0])
                lb = cv2.imread(lb_path[0], 0)
                if image is None:
                    print(im_path)
                    continue
                # lb = lb.numpy()
                cropped_img = crop_image_by_label_value(image, lb, i)

                im_lb = dict(im=cropped_img, lb=lb)
                im_lb = to_tensor(im_lb)
                img = im_lb['im'].cuda()
                img = F.interpolate(img.unsqueeze(0), size=(224, 224))
                image_features = model.encode_image(img).type(torch.float32)
                image_features_list.append(image_features)

            # print("im_lb_list: ", im_lb_list)
            img_feat = torch.cat(image_features_list, dim=0)
            # mean_feats = torch.mean(img_feat, dim=0, keepdim=True)
            # print(mean_feats.shape)
            this_datasets_feats.append(img_feat)
    # out_features = torch.cat(out_features, dim=0)
    return this_datasets_feats

def get_encode_lb_vec(configer, datasets_id=None):
    n_datasets = configer.get('n_datasets')
    text_feature_vecs = []
    with torch.no_grad():
        clip_model, _ = clip.load("ViT-B/32", device="cuda")
        for i in range(0, n_datasets):
            if datasets_id != None and i != datasets_id:
                continue
            lb_name = configer.get("dataset"+str(i+1), "label_names")
            lb_name = ["a photo of " + name + "." for name in lb_name]
            text = clip.tokenize(lb_name).cuda()
            text_features = clip_model.encode_text(text).type(torch.float32)
            text_feature_vecs.append(text_features)

    return text_feature_vecs

def gen_graph_node_feature(configer):
    n_datasets = configer.get("n_datasets")

    if not osp.exists(configer.get('res_save_pth')): os.makedirs(configer.get('res_save_pth'))

    file_name = configer.get('res_save_pth') + 'graph_node_features'
    dataset_names = []
    for i in range(0, configer.get('n_datasets')):
        # file_name += '_'+str(configer.get('dataset'+str(i+1), 'data_reader'))
        dataset_names.append(str(configer.get('dataset'+str(i+1), 'data_reader')))

    # file_name += '.pt'
    out_features = []
    for i in range(0, n_datasets):
        this_file_name = file_name + f'_{dataset_names[i]}.pt'
        if osp.exists(this_file_name):
            this_graph_node_features = torch.load(this_file_name, map_location='cpu')

            out_features.append(this_graph_node_features)
        else:
            print(f'gen_graph_node_featuer: {i}')
            img_feature_vecs = gen_image_features(configer, i)
            img_feat_tensor = torch.cat(img_feature_vecs, dim=0)

            text_feature_vecs = get_encode_lb_vec(configer, i)[0]
            this_graph_node_features = torch.cat([text_feature_vecs, img_feat_tensor], dim=1)

            print("gen finished")
            torch.save(this_graph_node_features.clone(), this_file_name)

            out_features.append(this_graph_node_features)

    out_features = torch.cat(out_features, dim=0)
    print(out_features.shape)
    return out_features

    # if not osp.exists(configer.get('res_save_pth')): os.makedirs(configer.get('res_save_pth'))

    # file_name = configer.get('res_save_pth') + 'graph_node_features'+str(configer.get('n_datasets'))
    # for i in range(0, configer.get('n_datasets')):
    #     file_name += '_'+str(configer.get('dataset'+str(i+1), 'data_reader'))

    # file_name += '.pt'

    # if osp.exists(file_name):
    #     graph_node_features = torch.load(file_name)
    # else:
    #     print("gen_graph_node_feature")
    #     text_feature_vecs = get_encode_lb_vec(configer)
    #     text_feat_tensor = torch.cat(text_feature_vecs, dim=0)
    #     print(text_feat_tensor.shape)
    #     print("gen_text_feature_vecs")
    #     img_feature_vecs = gen_image_features(configer)
    #     img_feat_tensor = torch.cat(img_feature_vecs, dim=0)
    #     print(img_feat_tensor.shape)
    #     print("gen_img_features")
    #     graph_node_features = torch.cat([text_feat_tensor, img_feat_tensor], dim=1)
    #     # graph_node_features = (text_feat_tensor+img_feat_tensor)/2
    #     print(graph_node_features.shape)
    #     torch.save(graph_node_features.clone(), file_name)

    # return graph_node_features

def gen_graph_node_feature_single(configer, img_feature_vecs, text_feat_tensor=None):
    if text_feat_tensor is None:
        text_feature_vecs = get_encode_lb_vec(configer)
        text_feat_tensor = torch.cat(text_feature_vecs, dim=0)

    # img_feature_vecs, lbpth_list = gen_image_features_single(configer, dls, gen_feature)
    n_datasets = configer.get("n_datasets")
    img_feat_tensor = []
    for i in range(0, n_datasets):
        n_cats = configer.get(f'dataset{i+1}', 'n_cats')
        for j in range(0, n_cats):
            num_samples, dim = img_feature_vecs[i][j].shape
            if num_samples == 1:
                img_feat_tensor.append(img_feature_vecs[i][j])
                continue

            choice_samples = int(num_samples/2)

            # print(f'the shape of dataset{i}: ', img_feature_vecs[i][j].shape)
            random_img_sample = random.sample(list(img_feature_vecs[i][j]), choice_samples)
            avg_img_feat = torch.mean(torch.cat(random_img_sample).view(-1, dim), dim=0)
            img_feat_tensor.append(avg_img_feat[None])

    img_feat_tensor = torch.cat(img_feat_tensor, dim=0)

    # graph_node_features = torch.cat([text_feat_tensor, img_feat_tensor], dim=1)
    graph_node_features = (text_feat_tensor+img_feat_tensor)/2

    return graph_node_features, text_feat_tensor

def gen_graph_node_feature_storage(configer):

    # text_feature_vecs = get_encode_lb_vec(configer)
    # text_feat_tensor = torch.cat(text_feature_vecs, dim=0)
    n_datasets = configer.get("n_datasets")

    if not osp.exists(configer.get('res_save_pth')): os.makedirs(configer.get('res_save_pth'))

    file_name = configer.get('res_save_pth') + 'img_feature_vecs'+str(configer.get('n_datasets'))
    dataset_names = []
    for i in range(0, configer.get('n_datasets')):
        # file_name += '_'+str(configer.get('dataset'+str(i+1), 'data_reader'))
        dataset_names.append(str(configer.get('dataset'+str(i+1), 'data_reader')))

    # file_name += '.pt'
    out_features = []
    for i in range(0, n_datasets):
        this_file_name = file_name + f'_{dataset_names[i]}.pkl'
        if osp.exists(this_file_name):
            # img_feature_vecs = torch.load(this_file_name)
            with open(this_file_name, 'rb') as file:
                img_feature_vecs = pickle.load(file)

            out_features.append(img_feature_vecs)
        else:
            print("gen_img_feature_vecs")
            img_feature_vecs = gen_image_features_storage(configer, i)
            print("gen finished")
            with open(this_file_name, 'wb') as file:
                pickle.dump(img_feature_vecs, file)
            # _ = [torch.save(img_feature_vecs.clone(), file_name + f'_dataset{idx}.pt' ) for idx, img_feature_vecs in enumerate(out_features)]
            out_features.append(img_feature_vecs)

    return out_features

if __name__ == "__main__":
    configer = Configer(configs="configs/ltbgnn_5_datasets.json")
    img_feature_vecs = gen_graph_node_feature_storage(configer)
    # print(img_feature_vecs[0][0])
    # print(img_feature_vecs)

    # print(graph_node_features.shape)
    # norm_adj_feat = F.normalize(graph_node_features, p=2, dim=1)
    # similar_matrix = torch.einsum('nc, mc -> nm', norm_adj_feat, norm_adj_feat)
    # print("similar_matrix_max:", torch.max(similar_matrix))
    # print("similar_matrix_min:", torch.min(similar_matrix))
    # torch.set_printoptions(profile="full")
    # print(similar_matrix)


#importing the libraries
import requests
from bs4 import BeautifulSoup
import csv

#assigning the main url to scrape to find sub-urls which starts with #StopRansomware
url = 'https://www.cisa.gov/uscert/ncas/alerts?page=0'

#sending the get request to the url
response = requests.get(url)

#parsing the html content with BeautifulSoup Library
soup  = BeautifulSoup(response.content, 'html.parser')

#Creating two empty lists to append the data
technical_title = []
Use = []
urls = []

#finding the links using the html parser which has a class of 'views-field views-field-title'
alerts = soup.findAll('div', {'class': 'views-field views-field-title'})

#Opened the csv file
with open('research.csv', 'w', newline = '') as file:
    #creating the csv writer object
    writer = csv.writer(file)
    #writitng the header row to the csv file
    writer.writerow(['Techniqual_title', 'Use'])

#iterating over the urls under the main url
for alert in alerts:
    #striping and changing into text to remove all the space beforew and after
    alert_text = alert.text.strip()
    #slicing the texts with ':' to make it into list and to identify if the folllowing text has #StopRansomware or not
    parts = alert_text.split(':')
    #Checking if the text has #StopRansomware or not
    if parts[1].strip().startswith('#StopRansomware'):
        #extracting the link of the texts which has #StopRansomware in it
        link = alert.find('a')['href']
        #creating the list of new urls taht has #StopRansomware in it
        new_url = 'https://cisa.gov/uscert'+link
        #appending it to the new_url list
        urls.append(new_url)

#iterating over the url/pages that has #StopRansomware in it
for x in urls:
    #sending the get request to the url
    r = requests.get(x)
    #parsing the html content with BeautifulSoup Library
    soup = BeautifulSoup(r.content, 'html.parser')
    #finding the links using the html parser which has a class of 'Table'
    table = soup.findAll('table', {'class': 'Table'})
    #iterating over the each lines in table
    for name in table:
        Techniqual_title = name.tr.td.p.span.text
        Use = name.tr.td.p.span.text
        technical_title.append(Techniqual_title)
        writer.writerow([technical_title, Use])
        pass


import paddle
import paddle.nn as nn
from loss_fn import HingeEmbeddingLoss
from model import Discriminator, Generator

import sys
sys.path.append(r"D:\code_sources\from_github\paddlepaddle\14s\DiscoGAN-Paddle\pipeline")
from utils import gen_fake_data, torch2paddle, torch2paddle_gether
from reprod_log import ReprodLogger

recon_criterion = nn.MSELoss()
gan_criterion = nn.BCELoss()
feat_criterion = HingeEmbeddingLoss()

# def logger
reprod_logger = ReprodLogger()

def get_fm_loss(real_feats, fake_feats, criterion):
    losses = 0
    for real_feat, fake_feat in zip(real_feats, fake_feats):
        l2 = (real_feat.mean(0) - fake_feat.mean(0)) * (real_feat.mean(0) - fake_feat.mean(0))
        loss = criterion(l2, paddle.ones(l2.shape))
        losses += loss

    return losses

def get_gan_loss(dis_real, dis_fake, criterion):
    labels_dis_real = paddle.ones([dis_real.shape[0], 1])
    labels_dis_fake = paddle.zeros([dis_fake.shape[0], 1])
    labels_gen = paddle.ones([dis_fake.shape[0], 1])

    dis_real = dis_real.reshape([dis_real.shape[0], 1])
    dis_fake = dis_fake.reshape([dis_fake.shape[0], 1])
    dis_loss = criterion(dis_real, labels_dis_real) * 0.5 + criterion(dis_fake, labels_dis_fake) * 0.5
    gen_loss = criterion(dis_fake, labels_gen)

    return dis_loss, gen_loss

generator_A = Generator()
generator_B = Generator()
discriminator_A = Discriminator()
discriminator_B = Discriminator()

# 加载预训练模型

discoGAN_ckpt = torch2paddle_gether("./discoGAN.pth")
generator_A.set_state_dict(discoGAN_ckpt['generator_A'])
generator_B.set_state_dict(discoGAN_ckpt['generator_B'])
discriminator_A.set_state_dict(discoGAN_ckpt['discriminator_B'])
discriminator_B.set_state_dict(discoGAN_ckpt['discriminator_B'])

generator_A.eval()
generator_B.eval()
discriminator_A.eval()
discriminator_B.eval()

A, _ = gen_fake_data(seed=42, shape=[4, 3, 64, 64])
B, _ = gen_fake_data(seed=100, shape=[4, 3, 64, 64])

with paddle.no_grad():

    AB = generator_B(B)
    BA = generator_A(A)

    ABA = generator_A(AB)
    BAB = generator_B(BA)

    # Reconstruction Loss
    recon_loss_A = recon_criterion(ABA, A)
    recon_loss_B = recon_criterion(BAB, B)

    # Real/Fake GAN Loss (A)
    A_dis_real, A_feats_real = discriminator_A(A)
    A_dis_fake, A_feats_fake = discriminator_A(BA)

    dis_loss_A, gen_loss_A = get_gan_loss(A_dis_real, A_dis_fake, gan_criterion)
    fm_loss_A = get_fm_loss(A_feats_real, A_feats_fake, feat_criterion)

    # Real/Fake GAN Loss (B)
    B_dis_real, B_feats_real = discriminator_B(B)
    B_dis_fake, B_feats_fake = discriminator_B(AB)

    dis_loss_B, gen_loss_B = get_gan_loss(B_dis_real, B_dis_fake, gan_criterion)
    fm_loss_B = get_fm_loss(B_feats_real, B_feats_fake, feat_criterion)

    rate = 0.01

    gen_loss_A_total = (gen_loss_B * 0.1 + fm_loss_B * 0.9) * (1. - rate) + recon_loss_A * rate
    gen_loss_B_total = (gen_loss_A * 0.1 + fm_loss_A * 0.9) * (1. - rate) + recon_loss_B * rate

    gen_loss = gen_loss_A_total + gen_loss_B_total
    dis_loss = dis_loss_A + dis_loss_B

reprod_logger.add("gen_loss", gen_loss.cpu().detach().numpy())
reprod_logger.add("dis_loss", dis_loss.cpu().detach().numpy())
reprod_logger.save("loss_paddle.npy")


import logging
from dataclasses import dataclass

from sklearn.datasets import fetch_20newsgroups_vectorized
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier

import curifactory as cf
from curifactory.caching import PickleCacher
from curifactory.reporting import JsonReporter, LinePlotReporter

@dataclass
class Params(cf.ExperimentParameters):
    layers: tuple = (100,)
    seed: int = 42
    activation: str = "relu"
    sample_count: int = 9000
    dimesionality: int = 500

@cf.stage(
    inputs=None, outputs=["training_data", "testing_data"], cachers=[PickleCacher] * 2
)
def load_data(record):
    params: Params = record.params

    data = fetch_20newsgroups_vectorized()
    x_train, x_test, y_train, y_test = train_test_split(
        data.data[: params.sample_count, : params.dimesionality],
        data.target[: params.sample_count],
        test_size=0.75,
        random_state=params.seed,
    )
    logging.info(x_train.shape)

    return (x_train, y_train), (x_test, y_test)

@cf.stage(inputs=["training_data"], outputs=["model"], cachers=[PickleCacher])
def train_model(record, training_data):
    params: Params = record.params

    clf = MLPClassifier(params.layers, activation=params.activation).fit(
        training_data[0], training_data[1]
    )

    record.report(LinePlotReporter(clf.loss_curve_, name="loss"))
    return clf

@cf.aggregate(
    inputs=["model", "testing_data"], outputs=["scores"], cachers=[PickleCacher]
)
def test_models(
    record: cf.Record,
    records: list[cf.Record],
    model: dict[cf.Record, any],
    testing_data: dict[cf.Record, any],
):
    scores = {}

    # iterate through every record and score its associated model
    lines = {}
    for r, r_model in model.items():
        score = r_model.score(testing_data[r][0], testing_data[r][1])

        # store the result keyed to the argument set name
        scores[r.params.name] = score
        lines[r.params.name] = r_model.loss_curve_

    record.report(LinePlotReporter(lines))
    record.report(JsonReporter(scores))
    return scores

def get_params():
    params = []
    layer_sizes = [1, 10, 20, 50, 100]
    for size in layer_sizes:
        params.append(Params(name=f"{size}", layers=(size,)))
    return params

def run(param_sets, manager):
    for param_set in param_sets:
        record = cf.Record(manager, param_set)
        train_model(load_data(record))

    test_models(cf.Record(manager, None))


#!/usr/bin/python3
"""
Module: Unit Testing for City class
"""
import unittest
from models.city import City

class TestCity(unittest.TestCase):
    """TestCity class"""
    def setUp(self):
        """ instantiate class"""
        self.city = City()

    def testattr(self):
        """ testing attributes"""
        self.assertTrue(hasattr(self.city, "created_at"))
        self.assertTrue(hasattr(self.city, "id"))
        self.assertFalse(hasattr(self.city, "updated_at"))
        self.assertFalse(hasattr(self.city, "random_attr"))
        self.assertTrue(hasattr(self.city, "name"))
        self.assertEqual(self.city.__class__.__name__, "City")
        self.assertEqual(self.city.name, "")
        self.assertEqual(self.city.state_id, "")
        self.city.name = "San Francisco"
        self.state_id = "343r387"
        self.assertEqual(self.city.name, "San Francisco")

    def test_method(self):
        """testing Amenity methods"""
        self.city.save()
        self.assertTrue(hasattr(self.city, "updated_at"))

    def test_string_format(self):
        """testing string formatting"""
        expected = "[{}] ({}) {}".format(
            self.city.__class__.__name__, str(
                self.city.id), self.city.__dict__)
        got = str(self.city)
        self.assertEqual(expected, got)

    def test_module_doc(self):
        """ module documentation """
        expected = True
        got = len(self.city.__doc__) > 0
        self.assertEqual(expected, got)

    def test_class_doc(self):
        """class documentation"""
        expected = True
        got = len(City.__doc__) > 0
        self.assertEqual(expected, got)

    def test_init_doc(self):
        """__init__() documentation"""
        expected = True
        got = len(City.__init__.__doc__) > 0
        self.assertEqual(expected, got)

    def test_str_doc(self):
        """__str__() documentation"""
        expected = True
        got = len(City.__str__.__doc__) > 0
        self.assertEqual(expected, got)

    def test_to_json(self):
        """to_json() documentation"""
        expected = True
        got = len(City.to_json.__doc__) > 0
        self.assertEqual(expected, got)


from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.urls import reverse
from django.shortcuts import render, HttpResponseRedirect, get_object_or_404

from basketapp.models import Basket
from products.models import Product

from geekshop.utils import is_ajax, get_price_format

@login_required
def basket(request):
    title = 'корзина'
    basket_items = request.user.basket.order_by('product__category')

    content = {
        'title': title,
        'basket_items': basket_items,
        'total': get_total(request)
    }

    return render(request, 'basketapp/basket.html', content)

@login_required
def add(request, pk=None):
    if 'login' in request.META.get('HTTP_REFERER'):
        return HttpResponseRedirect(reverse('products:product', args=[pk]))

    product = get_object_or_404(Product, pk=pk)

    basket = Basket.objects.filter(user=request.user, product=product).first()

    if not basket:
        basket = Basket(user=request.user, product=product)

    if product.quantity > 0:
        basket.quantity += 1
        basket.save()

    return HttpResponseRedirect(request.META.get('HTTP_REFERER'))

@login_required
def remove(request, pk):
    if 'login' in request.META.get('HTTP_REFERER'):
        return HttpResponseRedirect(reverse('basket:view'))

    basket_record = get_object_or_404(Basket, pk=pk)
    basket_record.delete()

    return HttpResponseRedirect(request.META.get('HTTP_REFERER'))

def get_total(request):
    basket = []
    qty = 0
    sum = 0
    if request.user.is_authenticated:
        basket = request.user.basket.all()

    for item in basket:
        qty += item.quantity
        sum += item.get_item_total()

    return {
        'qty': qty,
        'sum': get_price_format(int(sum))
    }

@login_required
def edit(request, pk, quantity):
    # request.is_ajax()
    if is_ajax(request):
        quantity = int(quantity)
        basket_item = Basket.objects.filter(pk=int(pk)).first()
        cost = 0

        result = {
            'status': 'error',
            'basket_item': {
                'id': int(pk),
                'cost': 0,
                'qty': quantity
            },
            'itog': {},
        }

        if basket_item is None:
            result['basket_item']['qty'] = 0
            return JsonResponse(result)

        if quantity > 0:
            if basket_item.quantity + basket_item.product.quantity >= quantity:
                basket_item.quantity = quantity
            else:
                result['basket_item']['qty'] = basket_item.quantity
            basket_item.save()

            cost = int(basket_item.get_item_total())
            result['basket_item']['cost'] = get_price_format(cost)
        else:
            basket_item.delete()

        result['itog'] = get_total(request)
        result['status'] = 'success'

        # result = render_to_string('basketapp/includes/inc_basket_list.html', content)

        return JsonResponse(result)


from src.extraction import extract_data
from src.processing import process_data
from src.loading import Database
from logsetup import log_setup

logger = log_setup.logging.getLogger(__name__)

if __name__ == '__main__':

    logger.info('Initializing process... ')

    # Download the information
    file_path = extract_data()

    # Extracts part of the data
    medals_filtered_df = process_data(file_path)

    # Operations with database
    db_access = Database()
    db_access.create_table()
    db_access.save_data(medals_filtered_df)
    db_access.fetch_info()

    logger.info('Process finished')


from tensorflow.keras.applications import EfficientNetB3
from tensorflow.keras import layers,optimizers
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras.models import Sequential
import tensorflow as tf
from tensorflow.keras.layers.experimental import preprocessing
from tensorflow.keras.optimizers.schedules import ExponentialDecay
import os
from sklearn.model_selection import train_test_split
import cv2
import sys
import numpy as np
import matplotlib.pyplot as plt

sys.path.append('..')
cd = os.getcwd()

size = 300

def load_img(dir1):
    face = []
    label = []
    X = []
    Y = []
    for subdir in os.listdir(dir1):
        path = dir1 + subdir
        for img in os.listdir(path + '/'):
            nm = os.path.splitext(os.path.basename(subdir))[0]
            imgfile = cv2.imread(path + '/' + img)
            s = cv2.resize(imgfile, (size, size))
            im = np.array(s)
            im = im.astype('float32')
            face.append(im)
            label.append(nm)
            print(nm)
    X.extend(face)
    Y.extend(label)
    return np.asarray(X),np.asarray(Y)

def encode(y):
    lab = []
    for label in y:
        if label == "safe":
            x = [1, 0]
        else:
            x = [0, 1]
        lab.append(x)
    return np.asarray(lab)

x,y = load_img("worker/")
trainx, testx, trainy, testy = train_test_split(x,y,test_size=0.2,random_state=0)
labtrny = encode(trainy)
labtesy = encode(testy)

img_augmentation = Sequential(
    [
        preprocessing.RandomRotation(factor=0.15),
        preprocessing.RandomTranslation(height_factor=0.1, width_factor=0.1),
        preprocessing.RandomFlip(),
        preprocessing.RandomContrast(factor=0.1),
    ],
    name="img_augmentation",
)

lr_schedule = ExponentialDecay(initial_learning_rate=0.001,
                               decay_steps=10000,
                               decay_rate=0.9)

inputs = layers.Input(shape=(size, size, 3))
x = img_augmentation(inputs)
baseModel = EfficientNetB3(include_top=True, classes=2, weights=None)(inputs)
model = tf.keras.Model(inputs,baseModel)
print(model.summary())
sgd = optimizers.Adam(learning_rate=lr_schedule)
model.compile(optimizer=sgd, loss="categorical_crossentropy", metrics=['accuracy'])
Monitor = EarlyStopping(monitor='val_loss', patience=30, min_delta=0.01, verbose=1, restore_best_weights=True)
hist = model.fit(x=trainx,y=labtrny,batch_size=16,epochs=200,validation_data=(testx,labtesy),callbacks=[Monitor],
                 verbose=2)

model.save("enetapd.h5")
newfit = min(hist.history['val_loss'])
newacc = max(hist.history['val_accuracy'])
print('New Model Validation Fitness: ', newfit)
plt.plot(hist.history["accuracy"])
plt.plot(hist.history['val_accuracy'])
plt.plot(hist.history['loss'])
plt.plot(hist.history['val_loss'])
plt.title("model accuracy")
plt.ylabel("Accuracy")
plt.xlabel("Epoch")
plt.legend(["Accuracy", "Validation Accuracy", "loss", "Validation Loss"])
plt.show()


#!/usr/bin/python
# -*- coding:utf-8 -*-

import cx_Oracle
from conf import Config as Config

def connect_db():
    # 连接数据库
    db_user = Config().getconf("db").ttw
    # 这里的顺序是用户名 / 密码 @ oracleserver的ip地址 / 数据库名字
    conn = cx_Oracle.connect(db_user)
    # 使用cursor()方法获取操作游标
    get_redis_ares = conn.cursor()
    get_redis_ares.execute("SELECT ra.id,ra.fullname FROM REDIS_AREA ra ")
    redis_ares = get_redis_ares.fetchall()
    get_job_class = conn.cursor()
    get_job_class.execut
    a = len(redis_ares)
    print(a)
    get_redis_ares .close()
    # conn.commit()
    conn.close()

if __name__ == '__main__':
    connect_db()


# -*- coding: utf-8 -*-
# @Time    : 2022/01/05
# @Author  : ForestNeo
# @Software: PyCharm
# @Function:

"""
给你一个仅包含小写英文字母和 '?' 字符的字符串 s，请你将所有的 '?' 转换为若干小写字母，使最终的字符串不包含任何 连续重复 的字符。
注意：你 不能 修改非 '?' 字符。
题目测试用例保证 除 '?' 字符 之外，不存在连续重复的字符。
在完成所有转换（可能无需转换）后返回最终的字符串。如果有多个解决方案，请返回其中任何一个。可以证明，在给定的约束条件下，答案总是存在的。

示例 1：
输入：s = "?zs"
输出："azs"
解释：该示例共有 25 种解决方案，从 "azs" 到 "yzs" 都是符合题目要求的。只有 "z" 是无效的修改，因为字符串 "zzs" 中有连续重复的两个 'z' 。

示例 2：
输入：s = "ubv?w"
输出："ubvaw"
解释：该示例共有 24 种解决方案，只有替换成 "v" 和 "w" 不符合题目要求。因为 "ubvvw" 和 "ubvww" 都包含连续重复的字符。

示例 3：
输入：s = "j?qg??b"
输出："jaqgacb"

示例 4：
输入：s = "??yw?ipkj?"
输出："acywaipkja"

提示：
1 <= s.length<= 100
s 仅包含小写英文字母和 '?' 字符
"""

def modifyString(s: str) -> str:
    chars = ['a', 'b', 'c']
    input_arr = [c for c in '1' + s + '1']
    for i in range(1, len(input_arr) - 1):
        if input_arr[i] == '?':
            before, after = input_arr[i-1], input_arr[i+1]
            for j in range(len(chars)):
                if chars[j] != before and chars[j] != after:
                    input_arr[i] = chars[j]
                    break
    return "".join(c for c in input_arr[1:-1])

if __name__ == '__main__':
    a = "??abc"
    print(modifyString(a))


import PyInquirer
import tabulate
import os

from typing import Callable, Dict, List

from backend import Field, Table, Type
from backend.constraints import *

types = {'integer': Integer, 'character': Char, 'real': Real, 'text': Text}
cons = [{'name': 'not null'}, {'name': 'auto increment'}, {'name': 'unique'}, {'name': 'primary key'},
        {'name': 'foreign key'}]  # more constraints TO DO
cons_to_class = {'not null': NotNull, 'auto increment': AutoIncrement, 'unique': Unique, 'primary key': PrimaryKey,
                 'foreign key': ForeignKey}

def __choice_to_function(message: str, choices: Dict[str, Callable[[str], bool]], buffer: Dict[str, Table],
                         root_path: str) -> bool:
    return choices[
        PyInquirer.prompt([{
            'type': 'list', 'name': 'op', 'message': message, 'choices': list(choices.keys())
        }])['op']](buffer, root_path)

def __choice_to_function2(message: str, choices: Dict[str, Callable[[str], bool]], table: Table,
                          root_path: str) -> bool:
    return choices[
        PyInquirer.prompt([{
            'type': 'list', 'name': 'op', 'message': message, 'choices': list(choices.keys())
        }])['op']](table, root_path)

def exit(buffer: Dict[str, Table], root_path) -> bool:
    print('Bye!')
    print()
    return False

def __not_null(v: str):
    return len(v) != 0

__create_table = [{
    'type': 'input', 'name': 'name', 'message': 'Please Enter a New Table Name:', 'validate': __not_null
}, {
    'type': 'input', 'name': 'desc', 'message': 'Please Describe This Table:', 'validate': __not_null
}]

__enter_table = [{
    'type': 'input', 'name': 'name', 'message': 'Please Enter The Table Name:', 'validate': __not_null
}]

__enter_field = [{
    'type': 'input', 'name': 'name', 'message': 'Please Enter The Field Name:', 'validate': __not_null
}, {
    'type': 'input', 'name': 'desc', 'message': 'Please Describe This Field:', 'validate': __not_null
}, {
    'type': 'list', 'name': 'type', 'message': 'Please Choose The Field Type:', 'choices': list(types.keys())
}, {
    'type': 'checkbox', 'name': 'other_cons', 'message': 'Please Choose Other Constraints:', 'choices': cons
}]

__enter_desc = [{
    'type': 'input', 'name': 'desc', 'message': 'Please Enter The Description:', 'validate': __not_null
}]

def show_tables(buffer: Dict[str, Table], root_path) -> bool:
    headers = ['TableName', 'Description']
    data = []
    for table in buffer:
        name = table
        desc = buffer[table].desc
        row = [name, desc]
        data.append(row)
    print()
    print(tabulate.tabulate(data, headers, tablefmt='pretty'))
    print()

    return True

def show_table(buffer: Dict[str, Table], root_path) -> bool:
    name = PyInquirer.prompt(__enter_table)['name']
    # print(name)
    __show_table(buffer, name)

    return True

def __show_table(buffer: Dict[str, Table], name: str):
    headers = ['FieldName', 'Description']
    data = []
    if (buffer.__contains__(name)):
        table = buffer[name]
        for field in table.fields:
            row = [field.name, field.desc]
            data.append(row)
        print()
        print(tabulate.tabulate(data, headers, tablefmt='pretty'))
        print()
    else:
        print('No Table Named ' + name + ' Exists!')

def enter_table(buffer: Dict[str, Table], root_path) -> bool:
    name = PyInquirer.prompt(__enter_table)['name']
    __show_table(buffer, name)
    table = buffer[name]
    while __choice_to_function2('Select Your Option: ', {
        'Add New Field': add_field,
        'Remove Old Field': remove_field,
        'Edit Description': edit_desc,
        'Back': back
    }, table, root_path):
        pass
    return True

def back(table: Table, root_path):
    return False

def add_field(table: Table, root_path) -> bool:
    info = PyInquirer.prompt(__enter_field)
    name = info['name']
    desc = info['desc']

    # TO DO
    if (info['type'] == 'character'):
        length = input('Enter The Char Length: ')
        type = types[info['type']](length)
    else:
        type = types[info['type']]()

    other_cons = []
    for c in info['other_cons']:
        if c == 'foreign key':
            ref = input('Enter The Reference Table Name: ')
            temp_cons = cons_to_class[c](ref)
        else:
            temp_cons = cons_to_class[c]()
        other_cons.append(temp_cons)
    other_cons = set(other_cons)
    constraints = {type} | other_cons

    field = Field(name, desc, constraints)
    # Need a check funct here -- to make sure no duplications occur
    table.fields.append(field)
    table.save(table)
    return True

def remove_field(table: Table, root_path) -> bool:
    target = input('Please Input The Field Name: ')
    for field in table.fields:
        if field.name == target:
            table.fields.remove(field)
            break
    table.save(table)
    return True

def edit_desc(table: Table, root_path) -> bool:
    desc = PyInquirer.prompt(__enter_desc)['desc']
    table.desc = desc
    table.save(table)
    return True

def create_table(buffer: Dict[str, Table], root_path) -> bool:
    info = PyInquirer.prompt(__create_table)
    name = info['name']
    desc = info['desc']
    fields = []
    file = os.path.join(root_path, name + '.json')
    table = Table(file, name, desc, fields)
    table.save(table)
    buffer.setdefault(name, table)
    return True

def drop_table(buffer: Dict[str, Table], root_path) -> bool:
    name = PyInquirer.prompt(__enter_table)['name']
    __show_table(buffer, name)
    table = buffer[name]

    if PyInquirer.prompt(
            {
                'type': 'confirm',
                'name': 'confirm',
                'message': 'This Table is About to Be Removed, Continue?',
                'default': False
            })['confirm']:
        path = table._file
        if os.path.exists(path):
            os.remove(path)
            print('Local Has Been Deleted Successfully!')
        else:
            raise Exception('No Such File: ' + path)
        buffer.pop(name)
    else:
        print('Aborted.')
    return True


#Import urllib and BS
from urllib.request import urlopen
from bs4 import BeautifulSoup
import ssl

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

#Set inputs
url = input('Enter URL - ')

count = input('Enter count - ')
count = int(count)

position = input('Enter position - ')
position = int(position)

#print(range(count))
#counting loop
for num in range(count + 1) :
    print(num)
    print('Retrieving:', url)
    html = urlopen(url, context=ctx).read()
    soup = BeautifulSoup(html, 'html.parser')
    tags = soup('a')
    for tag in tags:
        link = tag.get()
        print(link[position - 1])


import sgtk
from sgtk.platform.qt import QtCore, QtGui

views = sgtk.platform.current_bundle().import_module("views")

shotgun_globals = sgtk.platform.import_framework(
    "tk-framework-shotgunutils", "shotgun_globals"
)

shotgun_model = sgtk.platform.import_framework(
    "tk-framework-shotgunutils", "shotgun_model"
)

class ShotgunFieldDelegateGeneric(views.WidgetDelegate):
    """
    A generic, model-agnostic, shotgun field widget delegate.

    This class is designed to be used with any model that represents data that
    can be stored in Shotgun fields.

    The included subclass, ``ShotgunFieldDelegate``, is designed to work
    specifically with ``ShotgunModel`` instances. For other model types use this
    class and supply a ``field_data_role`` to this class constructor. The
    default is ``QtCore.Qt.EditRole``.
    """

    def __init__(
        self,
        sg_entity_type,
        field_name,
        display_class,
        editor_class,
        view,
        bg_task_manager=None,
        field_data_role=QtCore.Qt.EditRole,
    ):
        """
        Constructor

        :param sg_entity_type: Shotgun entity type
        :type sg_entity_type: String

        :param field_name: Shotgun field name
        :type field_name: String

        :param display_class: A shotgun field :class:`~PySide.QtGui.QWidget` to
            display the field info

        :param editor_class: A shotgun field :class:`~PySide.QtGui.QWidget` to
            edit the field info

        :param view: The parent view for this delegate
        :type view:  :class:`~PySide.QtGui.QWidget`

        :param bg_task_manager: Optional Task manager.  If this is not passed in
            one will be created when the delegate widget is created.
        :type bg_task_manager: :class:`~task_manager.BackgroundTaskManager`

        :param int field_data_role: The data role that stores SG field data in
            the model where this delegate is to be used.
        """
        views.WidgetDelegate.__init__(self, view)

        # The model role used to get/set values for editing the field widget
        self._field_data_role = field_data_role

        self._entity_type = sg_entity_type
        self._field_name = field_name
        self._display_class = display_class
        self._editor_class = editor_class
        self._bg_task_manager = bg_task_manager

    @property
    def field_data_role(self):
        """
        The item role used to get and set data associated with the fields being
        represented by this delegate.
        """
        return self._field_data_role

    def paint(self, painter, style_options, model_index):
        """
        Paint method to handle all cells that are not being currently edited.

        :param painter: The painter instance to use when painting
        :param style_options: The style options to use when painting
        :param model_index: The index in the data model that needs to be painted
        """

        # let the base class do all the heavy lifting
        super(ShotgunFieldDelegateGeneric, self).paint(
            painter, style_options, model_index
        )

        # clear out the paint widget's contents to prevent it from showing in
        # other places in the view (since the widget is shared)
        widget = self._get_painter_widget(model_index, self.view)
        widget.set_value(None)

    def _create_widget(self, parent):
        """
        Creates a widget to use for the delegate.

        :param parent: QWidget to parent the widget to
        :type parent: :class:`~PySide.QtGui.QWidget`

        :returns: QWidget that will be used to paint grid cells in the view.
        :rtype: :class:`~PySide.QtGui.QWidget`
        """
        widget = self._display_class(
            parent=parent,
            entity_type=self._entity_type,
            field_name=self._field_name,
            bg_task_manager=self._bg_task_manager,
            delegate=True,
        )

        if self._display_class == self._editor_class:
            # display and edit classes are the same. we need to make sure
            # we disable the editing so that the delegate isn't drawn in its
            # edit state.
            widget.enable_editing(False)

        return widget

    def sizeHint(self, style_options, model_index):
        """
        Returns the size needed by the delegate to display the item specified by
        ``model_index``, taking into account the style information provided by
        ``style_options``.

        Reimplemented from ``QStyledItemDelegate.sizeHint``

        :param style_options: Style information for the item.
        :type style_options: :class:`~PySide.QtGui.QStyleOptionViewItem`
        :param model_index: The index of the item to return the size of.
        :type model_index: :class:`~PySide.QtCore.QModelIndex`

        :returns: size required by the delegate
        :rtype: :class:`~PySide.QtCore.QSize`
        """

        if not model_index.isValid():
            return QtCore.QSize()

        size_hint = QtCore.QSize()
        painter_widget = self._get_painter_widget(model_index, self.view)
        if painter_widget:
            size_hint = painter_widget.size()

        return size_hint

    def _create_editor_widget(self, model_index, style_options, parent):
        """
        Create an editor widget for the supplied model index.

        :param model_index: The index of the item in the model to return a
            widget for
        :type model_index: :class:`~PySide.QtCore.QModelIndex`

        :param style_options: Specifies the current Qt style options for this
            index
        :type style_options: :class:`~PySide.QtGui.QStyleOptionViewItem`

        :param parent: The parent view that the widget should be parented to
        :type parent: :class:`~PySide.QtGui.QWidget`

        :returns: A QWidget to be used for editing the current index
        :rtype: :class:`~PySide.QtGui.QWidget`
        """
        # ensure the field is editable
        if not shotgun_globals.field_is_editable(self._entity_type, self._field_name):
            return None

        if not model_index.isValid():
            return None

        if not self._editor_class:
            return None

        widget = self._editor_class(
            parent=parent,
            entity_type=self._entity_type,
            field_name=self._field_name,
            bg_task_manager=self._bg_task_manager,
            delegate=True,
        )

        if self._display_class == self._editor_class:
            # display and edit classes are the same. we need to make sure
            # we enable the editing
            widget.enable_editing(True)

        # auto fill the background color so that the display widget doesn't show
        # behind.
        widget.setAutoFillBackground(True)

        return widget

    def _on_before_paint(self, widget, model_index, style_options):
        """
        Update the display widget with the value stored in the supplied model
        index. The value is retrieved for the role supplied to the
        ``field_data_role`` argument supplied to the constructor.

        :param widget: The QWidget (constructed in _create_widget()) which will
            be used to paint the cell.

        :param model_index: object representing the data of the object that is
            about to be drawn.
        :type model_index: :class:`~PySide.QtCore.QModelIndex`

        :param style_options: Object containing specifics about the
            view related state of the cell.
        :type style_options: :class:`~PySide.QtGui.QStyleOptionViewItem`
        """

        # make sure the display widget is populated with the correct data
        self._set_widget_value(widget, model_index)

    def setEditorData(self, editor, model_index):
        """
        Sets the data to be displayed and edited by the editor from the data
        model item specified by the model index.

        :param editor: The editor widget.
        :type editor: :class:`~PySide.QtGui.QWidget`
        :param model_index: The index of the model to be edited.
        :type model_index: :class:`~PySide.QtCore.QModelIndex`
        """

        # make sure the editor widget is populated with the correct data
        self._set_widget_value(editor, model_index)

    def setModelData(self, editor, model, index):
        """
        Gets data from the editor widget and stores it in the specified model at
        the item index.

        :param editor: The editor widget.
        :type editor: :class:`~PySide.QtGui.QWidget`
        :param model: The SG model where the data lives.
        :type model: :class:`~PySide.QtCore.QAbstractItemModel`
        :param index: The index of the model to be edited.
        :type index: :class:`~PySide.QtCore.QModelIndex`
        """
        src_index = _map_to_source(index)
        if not src_index or not src_index.isValid():
            # invalid index, do nothing
            return

        # compare the new/old values to see if there is a change
        new_value = editor.get_value()
        cur_value = src_index.data(self.field_data_role)
        if cur_value == new_value:
            # value didn't change. nothing to do here.
            return

        # attempt to set the new value in the model
        successful = src_index.model().setData(
            src_index, new_value, self.field_data_role
        )

        if not successful:
            bundle = sgtk.platform.current_bundle()
            bundle.log_error(
                "Unable to set model data for widget delegate: %s, %s"
                % (self._entity_type, self._field_name)
            )

    def editorEvent(self, event, model, option, index):
        """
        Handles mouse events on the editor.

        :param event: The event that occurred.
        :type event: :class:`~PySide.QtCore.QEvent`

        :param model: The SG model where the data lives.
        :type model: :class:`~PySide.QtCore.QAbstractItemModel`

        :param option: Options for rendering the item.
        :type option: :class:`~PySide.QtQui.QStyleOptionViewItem`

        :param index: The index of the model to be edited.
        :type index: :class:`~PySide.QtCore.QModelIndex`

        :return: ``True``, if the event was handled, ``False`` otherwise.
        :rtype: ``bool``
        """

        # The primary use for this is labels displaying clickable links (entity,
        # multi-entity, etc). By default, they're painted into the view via the
        # delegate, so you can't interact with them. There were some suggestions
        # online how to work around this that seemed really complex. This is a
        # solution rob suggested which I tried and it seems to work... and is
        # much simpler! Basically, detect a mouse click (release is all we have
        # really) in the delegate, populate the underlying widget with the data
        # from the index, then forward the event to the widget. The result is a
        # simulation of clicking on the actual widget.

        # Forward mouse clicks to the underlying display widget. This only kicks
        # in if the editor widget isn't displayed or doesn't process a mouse
        # event for some reason. If you're having trouble with editors
        # disappearing, it may be because they can't receive focus or aren't
        # handling a mouse click.
        if event.type() == QtCore.QEvent.MouseButtonRelease:
            self._forward_mouse_event(event, index)
            return True

        return False

    def _forward_mouse_event(self, mouse_event, index):
        """
        Forward the mouse event to the display widget to simulate
        interacting with the widget. This is necessary since the delegate only
        paints the widget in the view rather than being an actual widget
        instance.
        :param mouse_event: The event that occured on the delegate.
        :type mouse_event: :class:`~PySide.QtCore.QEvent`
        :param index: The model index that was acted on.
        :type index: :class:`~PySide.QtCore.QModelIndex`
        """

        # get the widget used to paint this index, populate it with the
        # value for this index
        widget = self._get_painter_widget(index, self.view)
        self._set_widget_value(widget, index)

        item_rect = self.view.visualRect(index)

        # get the rect of the item in the view
        widget.resize(item_rect.size())

        # move the widget to 0, 0 so we know exactly where it is
        widget.move(0, 0)

        # map global mouse position to within item_rect
        view_pos = self.view.viewport().mapFromGlobal(QtGui.QCursor.pos())

        # calculate the offset from the item rect
        widget_x = view_pos.x() - item_rect.x()
        widget_y = view_pos.y() - item_rect.y()

        # forward the mouse event to the display widget
        forward_event = QtGui.QMouseEvent(
            mouse_event.type(),
            QtCore.QPoint(widget_x, widget_y),
            mouse_event.button(),
            mouse_event.buttons(),
            mouse_event.modifiers(),
        )
        QtGui.QApplication.sendEvent(widget, forward_event)

    def _set_widget_value(self, widget, model_index):
        """
        Updates the supplied widget with data from the supplied model index.

        :param widget: The widget to set the value for
        :param model_index: The index of the model where the data comes from
        :type model_index: :class:`~PySide.QtCore.QModelIndex`
        """

        src_index = _map_to_source(model_index)
        if not src_index or not src_index.isValid():
            # invalid index, do nothing
            return

        value = src_index.data(self.field_data_role)
        widget.set_value(shotgun_model.sanitize_qt(value))

class ShotgunFieldDelegate(ShotgunFieldDelegateGeneric):
    """
    A delegate for a given type of Shotgun field. This delegate is designed to
    work with indexes from a ``ShotgunModel`` where the value of the field is
    stored in the ``SG_ASSOCIATED_FIELD_ROLE`` role.
    """

    def __init__(
        self,
        sg_entity_type,
        field_name,
        display_class,
        editor_class,
        view,
        bg_task_manager=None,
    ):
        """
        Constructor

        :param sg_entity_type: Shotgun entity type
        :type sg_entity_type: String

        :param field_name: Shotgun field name
        :type field_name: String

        :param display_class: A shotgun field :class:`~PySide.QtGui.QWidget` to
            display the field info

        :param editor_class: A shotgun field :class:`~PySide.QtGui.QWidget` to
            edit the field info

        :param view: The parent view for this delegate
        :type view:  :class:`~PySide.QtGui.QWidget`

        :param bg_task_manager: Optional Task manager.  If this is not passed in
            one will be created when the delegate widget is created.
        :type bg_task_manager: :class:`~task_manager.BackgroundTaskManager`
        """

        field_data_role = shotgun_model.ShotgunModel.SG_ASSOCIATED_FIELD_ROLE

        super(ShotgunFieldDelegate, self).__init__(
            sg_entity_type,
            field_name,
            display_class,
            editor_class,
            view,
            bg_task_manager=bg_task_manager,
            field_data_role=field_data_role,
        )

    def setModelData(self, editor, model, index):
        """
        Gets data from the editor widget and stores it in the specified model at
        the item index.

        :param editor: The editor widget.
        :type editor: :class:`~PySide.QtGui.QWidget`
        :param model: The SG model where the data lives.
        :type model: :class:`~PySide.QtCore.QAbstractItemModel`
        :param index: The index of the model to be edited.
        :type index: :class:`~PySide.QtCore.QModelIndex`
        """
        src_index = _map_to_source(index)
        if not src_index or not src_index.isValid():
            # invalid index, do nothing
            return

        # compare the new/old values to see if there is a change
        new_value = editor.get_value()
        cur_value = src_index.data(self.field_data_role)
        if cur_value == new_value:
            # value didn't change. nothing to do here.
            return

        bundle = sgtk.platform.current_bundle()

        # special case for image fields in the ShotgunModel. The SG model stores
        # the image field in the first column. If the value has changed, set the
        # icon value there.
        if editor.get_field_name() == "image":
            primary_item = src_index.model().item(src_index.row(), 0)
            try:
                if new_value:
                    # update the value locally in the model
                    primary_item.setIcon(QtGui.QIcon(new_value))
                else:
                    primary_item.setIcon(QtGui.QIcon())
            except Exception as e:
                bundle.log_error("Unable to set icon for widget delegate: %s" % (e,))

            return

        successful = src_index.model().setData(
            src_index, new_value, self.field_data_role
        )

        if not successful:
            bundle.log_error(
                "Unable to set model data for widget delegate: %s, %s"
                % (self._entity_type, self._field_name)
            )

    def _set_widget_value(self, widget, model_index):
        """
        Updates the supplied widget with data from the supplied model index.

        :param widget: The widget to set the value for
        :param model_index: The index of the model where the data comes from
        :type model_index: :class:`~PySide.QtCore.QModelIndex`
        """

        src_index = _map_to_source(model_index)
        if not src_index or not src_index.isValid():
            # invalid index, do nothing
            return

        # special case for image fields in the ShotgunModel. The SG model has
        # the ability to pre-query thumbnails for entities for efficiency. If
        # this is the image field for an entity in the SG model, we can make use
        # of the potentially pre-queried image available in the first column.
        if widget.get_field_name() == "image":
            primary_item = src_index.model().item(src_index.row(), 0)
            icon = primary_item.icon()
            if icon:
                widget.set_value(icon.pixmap(QtCore.QSize(256, 256)))
            return

        value = src_index.data(self.field_data_role)
        widget.set_value(shotgun_model.sanitize_qt(value))

def _map_to_source(idx, recursive=True):
    """
    Map the specified index to it's source model.  This can be done recursively
    to map back through a chain of proxy models to the source model at the
    beginning of the chain

    :param idx: The index to map from
    :param recursive: If true then the function will recurse up the model chain
        until it finds an index belonging to a model that doesn't derive from
        QAbstractProxyModel. If false then it will just return the index from
        the imediate parent model.

    :returns: QModelIndex in the source model or the first model in the chain
        that isn't a proxy model if recursive is True.
    """
    src_idx = idx
    while src_idx.isValid() and isinstance(src_idx.model(), QtGui.QAbstractProxyModel):
        src_idx = src_idx.model().mapToSource(src_idx)
        if not recursive:
            break
    return src_idx


import telebot
import argparse
import os
import random

# Open cmd. Then write CD and path to bot folder.
# Run echo_bot with command 'python echo_bot.py --p "path\to\folder\"'
# Path to images folder should look like this
# "C:\photo_bot\photos\\"

parser = argparse.ArgumentParser()
parser.add_argument("--p", default=1, type=str, help="Path", required=True)
args = parser.parse_args()
path = args.p
files = os.listdir(path)

bot = telebot.TeleBot("YourBotToken")

@bot.message_handler(commands=['start'])
def send_welcome(message):
    bot.send_message(message.chat.id, "Hi, want a picture?")

@bot.message_handler(commands=['getcat'])
def send_photo(message):
    bot.send_chat_action(message.chat.id, 'upload_photo')
    random.seed()
    rand_num = random.randint(0, len(files) - 1)
    img = open(path + files[rand_num], 'rb')
    bot.send_photo(message.chat.id, img,
                   reply_to_message_id=message.message_id)
    img.close()

bot.polling()


from applications import app
from flask import Response, request, jsonify
import random

@app.route('/postMyLighteningBall', methods=['POST'])
def postMyLighteningBall():
    post = request.data.decode('utf-8')
    myLighteningBall = int(post)
    app.logger.info(myLighteningBall)
    winningLighteningBall = random.randint(1,14)

    match = False
    if myLighteningBall == winningLighteningBall:
        match = True
    else:
        match = False
    return jsonify({"winningBall":winningLighteningBall, "match":match})

@app.route('/postMyLotteryNumbers', methods=['POST'])
def postMyLotteryNumbers():
    post = request.data.decode('utf-8')
    stringNumbers = list(post.split(" "))
    myLotteryNumbers = [int(i) for i in stringNumbers]

    count = 0
    winningNumbers = []
    while count != 6:
        ball = random.randint(1,50)
        if ball not in winningNumbers:
            winningNumbers.append(ball)
            count += 1
    list_string = map(str, winningNumbers)
    winningLotteryNumbers = " ".join(list_string)

    matches = 0
    for ball in myLotteryNumbers:
        if ball in winningNumbers:
            matches = matches + 1
    return jsonify({"winningBalls":winningLotteryNumbers, "matches":matches})


"""
Decision Tree Classifier
CSCI 230 Final Project
Grace MacDonald, Warren Seeds, Carson Cooley, Petra Ilic, Sarah Martin
"""
import eda
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import GridSearchCV, validation_curve, StratifiedKFold
from sklearn.tree import DecisionTreeClassifier, export_text, plot_tree, export_graphviz, plot_tree
from sklearn.metrics import precision_score, recall_score, f1_score, accuracy_score, confusion_matrix, plot_confusion_matrix, classification_report, roc_auc_score, ConfusionMatrixDisplay
from sklearn.feature_selection import RFE

print('\n\n====================================== Beginning Decision Tree Classifier ============================================ \n\n')
df = eda.df
X_train = eda.X_train
X_test = eda.X_test
y_train = eda.y_train
y_test = eda.y_test
X_val = eda.X_val
y_val = eda.y_val

print('\n\n--------------------------- Addressing over and underfitting with validation curves ------------------------\n\n')

param_range = [1, 5, 10, 50, 100, 250, 500, 1000]
train_scores, test_scores = validation_curve(
                estimator=DecisionTreeClassifier(random_state=0),
                X=X_train,
                y=y_train,
                param_name='max_depth',
                param_range=param_range,
                cv=10)
train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
test_mean = np.mean(test_scores, axis=1)
test_std = np.std(test_scores, axis=1)
plt.plot(param_range, train_mean,
         color='blue', marker='o',
         markersize=5, label='Training accuracy')
plt.fill_between(param_range, train_mean + train_std,
                 train_mean - train_std, alpha=0.15,
                 color='blue')
plt.plot(param_range, test_mean,
         color='green', linestyle='--',
         marker='s', markersize=5,
         label='Validation accuracy')
plt.fill_between(param_range,
                 test_mean + test_std,
                 test_mean - test_std,
                 alpha=0.15, color='green')
plt.grid()
plt.xscale('log')
plt.legend(loc='lower right')
plt.xlabel('Parameter max_depth')
plt.ylabel('Accuracy')
plt.ylim([0.2, 1.03])
plt.tight_layout()
plt.show()

print('\n\n------------------------------------------- DTC Grid Search ------------------------------------------------ \n\n')

param_grid = [{'criterion': ['gini', 'entropy', 'log_loss'],
               'max_depth': [3,5,10,20,50,100,200],
               'min_samples_split': [2,6,10],
               'splitter': ['best', 'random'],
               'min_samples_leaf': [1,5,10],
               'min_weight_fraction_leaf': [0,0.2,0.35,0.5],
               'max_features': ['sqrt', 'log2']
               }]

gs = GridSearchCV(estimator=DecisionTreeClassifier(random_state=0),
                  param_grid=param_grid,
                  scoring='accuracy',
                  refit=True,
                  cv=10,
                  n_jobs=-1)

gs = gs.fit(X_val, y_val)
print(gs.best_score_)
print(gs.best_params_)
params = gs.best_params_

dtc = DecisionTreeClassifier(random_state=0, criterion=params['criterion'], max_depth=params['max_depth'],
                            max_features=params['max_features'],
                            min_samples_leaf=params['min_samples_leaf'], min_samples_split=params['min_samples_split'],
                            min_weight_fraction_leaf=params['min_weight_fraction_leaf'], splitter=params['splitter'])
dtc.fit(X_train, y_train)
y_pred = dtc.predict(X_test)

'''
print('\n\n------------------------------------------ Importance of Each Feature ----------------------------------------------- \n\n')
feature_importances = pd.DataFrame(dtc.feature_importances_,
                                index = X_train.columns)

print(feature_importances)
'''

print('\n\n------------------------------------------ Evaluating DTC ----------------------------------------------- \n\n')
k = 10
kf = StratifiedKFold(n_splits=k, shuffle=True, random_state=123)

X_kf = np.concatenate((X_train, X_test))
y_kf = np.concatenate((y_train, y_test))

predicted_targets = np.array([])
actual_targets = np.array([])

accuracies = []
precisions = []
recalls = []
f1s = []
roc_aucs = []
for train_index, test_index in kf.split(X_kf, y_kf):
    X_train_kf, X_test_kf = X_kf[train_index], X_kf[test_index]
    y_train_kf, y_test_kf = y_kf[train_index], y_kf[test_index]

    dtc.fit(X_train_kf, y_train_kf)
    y_pred_kf = dtc.predict(X_test_kf)

    predicted_targets = np.append(predicted_targets, y_pred_kf)
    actual_targets = np.append(actual_targets, y_test_kf)

    accuracies.append(dtc.score(X_test_kf, y_test_kf))
    precisions.append(precision_score(y_true=y_test_kf, y_pred=y_pred_kf))
    recalls.append(recall_score(y_true=y_test_kf, y_pred=y_pred_kf))
    f1s.append(f1_score(y_true=y_test_kf, y_pred=y_pred_kf))
    roc_aucs.append(roc_auc_score(y_test_kf, y_pred_kf))

cm_kf = confusion_matrix(y_true=actual_targets, y_pred=predicted_targets)
cm_kf_display = ConfusionMatrixDisplay(cm_kf)
cm_kf_display.from_predictions(y_true=actual_targets, y_pred=predicted_targets, cmap=plt.cm.Blues)
plt.title("10-Fold Cross Validation Confusion Matrix")
plt.show()

print('\n\n------------------------------------ 10-Fold Cross Validation Metrics ----------------------------------------- \n\n')

print("Accuracy: ", round(sum(accuracies)/k, 6))
print("Precision:", round(sum(precisions)/k, 6))
print("Recall:   ", round(sum(recalls)/k, 6))
print("F1:       ", round(sum(f1s)/k, 6))
print("ROC-AUC:  ", round(sum(roc_aucs)/k, 6))

print('\n\n')
print('Classification report:\n', classification_report(actual_targets, predicted_targets))

# print('\n\n----------------------------- Printing Graphical Representation of DTC ------------------------------------- \n\n')

# plot_tree(dtc, fontsize=5, feature_names=eda.X_train.columns)
# plt.tight_layout()
# plt.show()

# print('\n\n------------------------------------------ Feature Importance ----------------------------------------------- \n\n')

# feature_importance = pd.DataFrame(dtc.feature_importances_,
#                                 index = X_train.columns,
#                                 columns=['importance']).sort_values('importance',
#                                                                     ascending=False)

# print(feature_importance)

# feature_importance = feature_importance[feature_importance['importance'] != 0]

# ax = feature_importance.plot.bar(y='importance',rot=0)
# plt.show()

print('\n\n------------------------------------- Recursive Feature Elimination ------------------------------------- \n\n')

estimator = DecisionTreeClassifier(random_state=0, criterion=params['criterion'], max_depth=params['max_depth'],
                            max_features=params['max_features'],
                            min_samples_leaf=params['min_samples_leaf'], min_samples_split=params['min_samples_split'],
                            min_weight_fraction_leaf=params['min_weight_fraction_leaf'], splitter=params['splitter'])

selector = RFE(estimator, n_features_to_select=0.3, step=1)

predicted_targets_RFE = np.array([])
actual_targets_RFE = np.array([])

accuracies_RFE = []
precisions_RFE = []
recalls_RFE = []
f1s_RFE = []
roc_aucs_RFE = []
for train_index, test_index in kf.split(X_kf, y_kf):
    X_train_kf, X_test_kf = X_kf[train_index], X_kf[test_index]
    y_train_kf, y_test_kf = y_kf[train_index], y_kf[test_index]

    selector.fit(X_train_kf, y_train_kf)
    y_pred_kf = selector.predict(X_test_kf)

    predicted_targets_RFE = np.append(predicted_targets_RFE, y_pred_kf)
    actual_targets_RFE = np.append(actual_targets_RFE, y_test_kf)

    accuracies_RFE.append(round(accuracy_score(y_true=y_test_kf, y_pred=y_pred_kf), 6))
    precisions_RFE.append(round(precision_score(y_true=y_test_kf, y_pred=y_pred_kf), 6))
    recalls_RFE.append(round(recall_score(y_true=y_test_kf, y_pred=y_pred_kf), 6))
    f1s_RFE.append(round(f1_score(y_true=y_test_kf, y_pred=y_pred_kf), 6))
    roc_aucs_RFE.append(round(roc_auc_score(y_test_kf, y_pred_kf), 6))

cm_kf_RFE = confusion_matrix(y_true=actual_targets_RFE, y_pred=predicted_targets_RFE)
cm_kf_display_RFE = ConfusionMatrixDisplay(cm_kf_RFE)
cm_kf_display_RFE.from_predictions(y_true=actual_targets_RFE, y_pred=predicted_targets_RFE, cmap=plt.cm.Blues)
plt.title("10-Fold Cross Validation Confusion Matrix")
plt.show()

print('\n\n------------------------------------ 10-Fold Cross Validation Metrics with RFE ----------------------------------------- \n\n')

print("Accuracy: ", round(sum(accuracies_RFE)/len(accuracies_RFE), 6))
print("Precision:", round(sum(precisions_RFE)/len(precisions_RFE), 6))
print("Recall:   ", round(sum(recalls_RFE)/len(recalls_RFE), 6))
print("F1:       ", round(sum(f1s_RFE)/len(f1s_RFE), 6))
print("ROC-AUC:  ", round(sum(roc_aucs_RFE)/len(roc_aucs_RFE), 6))

print("\n\nAccuracy: ", accuracies_RFE)
print("Precision:", precisions_RFE)
print("Recall:   ", recalls_RFE)
print("F1:       ", f1s_RFE)
print("ROC-AUC:  ", roc_aucs_RFE)

print('\n\n')
print('Classification report:\n', classification_report(actual_targets_RFE, predicted_targets_RFE))