import torch
from transformers import AutoModelWithLMHead, AutoTokenizer,AutoModelForTokenClassification, AutoModelForCausalLM
from fast_bert.prediction import BertClassificationPredictor
import argparse
import numpy as np
from fairseq.models.bart import BARTModel
from tqdm import trange
import torch.nn.functional as F
import random

class Interaction():

    def __init__(self, args):
        self.gen_model_type = args['gen_model_type']
        self.gen_model_path = args['gen_model_path'].replace('"','')
        self.conv_line_path = args['conv_line_path'].replace('"','')
        self.gen_length = args['length']
        self.temperature = args['temperature']
        self.top_k = args['top_k']
        self.top_p = args['top_p']
        self.stop_token= args['stop_token']
        self.repetition_penalty= args['repetition_penalty']
        self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
        #self.device = torch.device("cpu")
        self.gen_model_type = self.gen_model_type.lower()
        self.lookup = { '1':'Fashion','2':'Politics','3':'Books','4':'Sports','5':'General Entertainment','6':'Music','7':'Science & Technology','8':'Movie','9':'General' }
        self.topic_cls = BertClassificationPredictor(
            model_path=args['topic_cls_path'].replace('"',''),
            label_path=args['label_dir'].replace('"',''),  #sys.argv[2], # directory for labels.csv file
            multi_label=False,
            model_type='bert',
            do_lower_case=True)

        self.entity_ext_model = AutoModelForTokenClassification.from_pretrained("dbmdz/bert-large-cased-finetuned-conll03-english")
        #self.entity_ext_model.to(self.device)
        self.entity_ext_model.to('cpu')
        self.entity_ext_tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")

        if self.gen_model_type =='dialogpt':
            self.gen_tokenizer = AutoTokenizer.from_pretrained(self.gen_model_path)
            self.gen_model = AutoModelWithLMHead.from_pretrained(self.gen_model_path)
            self.gen_model.cuda()
            self.gen_model.eval()
        elif self.gen_model_type == 'bart':
            self.gen_model = BARTModel.from_pretrained(self.gen_model_path, checkpoint_file='checkpoint_best.pt', data_name_or_path=self.gen_model_path)
            self.gen_model.cuda()
            self.gen_model.eval()

        self.conv_line =  BARTModel.from_pretrained(self.conv_line_path,checkpoint_file='checkpoint_best.pt',data_name_or_path=self.conv_line_path)
        self.conv_line.cuda()
        self.conv_line.eval()
        self.baseline_tokenizer = AutoTokenizer.from_pretrained(args['baseline'])
        self.baseline_model = AutoModelForCausalLM.from_pretrained(args['baseline'])
        #self.baseline_model.to('cpu')
        self.baseline_model.cuda()
        self.baseline_model.eval()

    def baseline_decode(self, user_utt):
        print('baseline decode')
        print(user_utt)
        #new_user_input_ids = self.baseline_tokenizer.encode(
        #    user_utt + self.baseline_tokenizer.eos_token, return_tensors='pt', max_length=128).to('cpu')
        new_user_input_ids = self.baseline_tokenizer.encode(
            user_utt + self.baseline_tokenizer.eos_token, return_tensors='pt', max_length=128).cuda()
        if user_utt=="BEGIN":
            np.random.seed(random.randint(0,120))
            torch.manual_seed(random.randint(0,120))
            chat_history_ids = self.baseline_model.generate(
                new_user_input_ids, max_length=60, top_k=10, top_p=0.70, pad_token_id=self.baseline_tokenizer.eos_token_id)
            utterance = self.baseline_tokenizer.decode(chat_history_ids[0], skip_special_tokens=True)
            utterance = utterance.replace('BEGIN','').strip()
            if ' <EOT> ' in utterance:
                print('utterance', utterance)
                utterance = utterance.split(' <EOT> ')[0]
        else:
            np.random.seed(4)
            torch.manual_seed(4)
            chat_history_ids = self.baseline_model.generate(
                new_user_input_ids, max_length=60, top_k=10, top_p=0.70, pad_token_id=self.baseline_tokenizer.eos_token_id)
            utterance = self.baseline_tokenizer.decode(chat_history_ids[0], skip_special_tokens=True)
            if ' <EOT> ' in utterance:
                print('utterance', utterance)
                utterance = utterance.split(' <EOT> ')[1].strip()

        return utterance

    def get_topic(self, utterance):
        '''
        this method calls the topic cls and returns utterace's topic
        '''
        print('topic input:',utterance)
        topic = self.lookup[self.topic_cls.predict(utterance)[0][0]]
        print('predict topic:',topic)
        return topic

    def get_entities(self, utterance):
        '''
        this method calls the entity extractor model and returns utterace's entities
        '''
        entities =''

        label_list = [
        "O",       # Outside of a named entity
        "B-MISC",  # Beginning of a miscellaneous entity right after another miscellaneous entity
        "I-MISC",  # Miscellaneous entity
        "B-PER",   # Beginning of a person's name right after another person's name
        "I-PER",   # Person's name
        "B-ORG",   # Beginning of an organisation right after another organisation
        "I-ORG",   # Organisation
        "B-LOC",   # Beginning of a location right after another location
        "I-LOC"    # Location
        ]

        # Bit of a hack to get the tokens with the special tokens
        tokens = self.entity_ext_tokenizer.tokenize(self.entity_ext_tokenizer.decode(self.entity_ext_tokenizer.encode(utterance)))
        inputs = self.entity_ext_tokenizer.encode(utterance, return_tensors="pt").to('cpu')

        outputs = self.entity_ext_model(inputs)[0]
        predictions = torch.argmax(outputs, dim=2)

        entity = [(token, label_list[prediction]) for token, prediction in zip(tokens, predictions[0].tolist())]

        # delete '##' before tokens
        r = []
        r_tags = []
        for i, tpl in enumerate(entity):
            if tpl[0].startswith("##"):
                if r:
                    r[-1] += tpl[0][2:]
            else:
                r.append(tpl[0])
                r_tags.append(tpl[1])

        new_entity_token = [(i, j) for i, j in zip(r, r_tags)]

        # combine tokens into entities
        flag = False
        entities = []
        ent_tags = []
        for i, tpl in enumerate(new_entity_token):
            if tpl[1] == "O":
                flag = False
                continue
            elif tpl[1] == "I-MISC" or tpl[1] == "I-PER" or tpl[1] == "I-ORG" or tpl[1] == "I-LOC":
                if flag == False:
                    flag = True
                    entities.append(tpl[0])
                    ent_tags.append(tpl[1])
                else:
                    entities[-1] += ' '
                    entities[-1] += tpl[0]
            elif tpl[1] == "B-MISC" or tpl[1] == "B-PER" or tpl[1] == "B-ORG" or tpl[1] == "B-LOC":
                entities.append(tpl[0])
                ent_tags.append(tpl[1])

        return entities

    def get_response_keywords(self, utterance, topic, entities, randomness=False):
        '''
        this method calls the conv_line model and returns response keywords
        '''
        entities_comb = ' # '.join(entities)
        input_conv = topic + ' <EOT> '+utterance+' <A0> '+entities_comb+'<A1>'
        '''
        this method calls the conv_line model and returns response keywords
        '''
        print('input to conv_line')
        print(input_conv)
        if randomness==False:
            np.random.seed(4)
            torch.manual_seed(4)
        elif randomness==True:
            np.random.seed(random.randint(0,120))
            torch.manual_seed(random.randint(0,120))
        maxb = 30 #Can be customized
        minb = 7  #Can be customized
        response = ''
        slines = [input_conv]
        with torch.no_grad():
            #hypotheses = self.conv_line.sample(slines, beam=4, lenpen=2.0, no_repeat_ngram_size=3)
            hypotheses = self.conv_line.sample(slines, sampling=True, sampling_topk=5 ,temperature=0.7 ,lenpen=2.0, max_len_b=maxb, min_len=minb, no_repeat_ngram_size=3)
        hypotheses = hypotheses[0]
        print('keywords hypotheses:', hypotheses)
        response = hypotheses.replace('\n','')
        keywords = response.replace('<V>','').replace('<s>', '').split('#')
        print('keywords keywords:', keywords)
        k = []
        for keyword in keywords:
            keyword = keyword.strip()
            k.append(keyword)
        print('keywords k:',k)
        keywords = k

        return keywords

    def top_k_top_p_filtering(self, logits, filter_value=-float('Inf')):
        """ Filter a distribution of logits using top-k and/or nucleus (top-p) filtering
            Args:
                logits: logits distribution shape (batch size x vocabulary size)
                top_k > 0: keep only top k tokens with highest probability (top-k filtering).
                top_p > 0.0: keep the top tokens with cumulative probability >= top_p (nucleus filtering).
                    Nucleus filtering is described in Holtzman et al. (http://arxiv.org/abs/1904.09751)
            From: https://gist.github.com/thomwolf/1a5a29f6962089e871b94cbd09daf317
        """
        top_k = min(self.top_k, logits.size(-1))  # Safety check
        if top_k > 0:
            # Remove all tokens with a probability less than the last token of the top-k
            indices_to_remove = logits < torch.topk(logits, top_k)[0][..., -1, None]
            logits[indices_to_remove] = filter_value

        if self.top_p > 0.0:
            sorted_logits, sorted_indices = torch.sort(logits, descending=True)
            cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1)

            # Remove tokens with cumulative probability above the threshold
            sorted_indices_to_remove = cumulative_probs > self.top_p
            # Shift the indices to the right to keep also the first token above the threshold
            sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[..., :-1].clone()
            sorted_indices_to_remove[..., 0] = 0

            # scatter sorted tensors to original indexing
            indices_to_remove = sorted_indices_to_remove.scatter(dim=1, index=sorted_indices, src=sorted_indices_to_remove)
            logits[indices_to_remove] = filter_value
        return logits

    def sample_sequence(self, model, context):
        context = torch.tensor(context, dtype=torch.long, device=self.device)
        context = context.unsqueeze(0).repeat(1, 1)
        generated = context
        model.cuda()
        with torch.no_grad():
            for _ in trange(self.gen_length):
                inputs = {'input_ids': generated}
                outputs = model(**inputs)  # Note: we could also use 'past' with GPT-2/Transfo-XL/XLNet/CTRL (cached hidden-states)
                next_token_logits = outputs[0][:, -1, :] / (self.temperature if self.temperature > 0 else 1.)

                # repetition penalty from CTRL (https://arxiv.org/abs/1909.05858)
                for i in range(1):
                    for _ in set(generated[i].tolist()):
                        next_token_logits[i, _] /= self.repetition_penalty

                filtered_logits = self.top_k_top_p_filtering(next_token_logits)
                next_token = torch.multinomial(F.softmax(filtered_logits, dim=-1), num_samples=1)
                generated = torch.cat((generated, next_token), dim=1)
        return generated

    def get_response(self, user_utterance, user_utt_topic, res_keywords):
        '''
        this method calls the dial_gen model and returns generated utterance
        '''
        res_keywords = ' # '.join(res_keywords)
        input_dial_gen = user_utt_topic.strip() + ' <EOT> ' + user_utterance.strip() +  ' <V> ' + res_keywords.strip()
        print('input to dialog generation module')
        print(input_dial_gen)
        if self.gen_model_type =='dialogpt':
            context_tokens = self.gen_tokenizer.encode(input_dial_gen, add_special_tokens=False)
            out = self.sample_sequence(model=self.gen_model, context = context_tokens)
            out = out[:, len(context_tokens):].tolist()
            response = self.gen_tokenizer.decode(out[0], clean_up_tokenization_spaces=True)
            response = response[: response.find('\n') if self.stop_token else None]
        elif self.gen_model_type =='bart':
            np.random.seed(4)
            torch.manual_seed(4)
            maxb = 128 #Can be customized
            minb = 15  #Can be customized
            response = ''
            slines = [input_dial_gen]
            with torch.no_grad():
                hypotheses = self.gen_model.sample(slines, sampling=True, sampling_topk=self.top_k ,temperature=self.temperature ,lenpen=2.0, max_len_b=maxb, min_len=minb, no_repeat_ngram_size=3)
            hypotheses = hypotheses[0]
            response = hypotheses.replace('\n','')
        return response

if __name__=="__main__":

    parser = {}
    parser['seed'] = 1000
    parser['gen_model_type'] = "bart"
    parser['gen_model_path'] = '/nas/home/zixiliu/dialogsystem_model/bartgen/'
    parser['conv_line_path'] = '/nas/home/zixiliu/dialogsystem_model/ent_kwd/'
    parser['topic_cls_path'] = '/nas/home/zixiliu/dialogsystem_model/topic_cls/'
    parser['label_dir'] = '/nas/home/zixiliu/dialogsystem_model/topic_cls/'
    parser['length'] = 100
    parser['temperature'] = 1.0
    parser['repetition_penalty'] = 1.0
    parser['top_k'] = 15
    parser['top_p'] = 0.9
    parser['stop_token'] = '\n'

    torch.manual_seed(parser['seed'])
    if torch.cuda.is_available():
        torch.cuda.manual_seed(parser['seed'])

    interaction = Interaction(parser)
    print('Hello, Welcome! I am happy to chat with you :)' )
    prev1 = ''
    prev2 = 'Hello, Welcome! I am happy to chat with you :)'
    while True:
        user_utt = input('USER: ')
        if user_utt.lower() == 'exit':
            break
        prev_utts = '[CLS]'+prev1+'[SEP]'+prev2+'[SEP]'+user_utt+'[SEP]'
        user_utt_topic = interaction.get_topic(prev_utts)
        # print('TOPIC: {}'.format(user_utt_topic))
        user_utt_entities = interaction.get_entities(user_utt)
        # print('ENTITIES: {}'.format(user_utt_entities))
        res_utt_keywords = interaction.get_response_keywords(user_utt, user_utt_topic, user_utt_entities)
        print("Response keywords are", res_utt_keywords)
        # user_reposnse_edit = input('Edit response keywords: ')
        # res_utt_keywords = user_reposnse_edit.split(' # ')
        # print("Response keywords are", res_utt_keywords)

        # print('KEYWORDS: {}'.format(res_utt_keywords))
        sys_utt = interaction.get_response(user_utt, user_utt_topic, res_utt_keywords)
        print('CHATBOT: {}'.format(sys_utt))
        prev1 = copy.copy(user_utt)
        prev2 = copy.copy(sys_utt)


import netCDF4 as nc
import numpy as np
from skimage.io import imread
from datetime import datetime
from mjd2date import date2mjd
import time
from osgeo import gdal, osr
import glob

###  INPUT

nc_name = '/home/lauranec/Documents/Kyagar_velocities_TSX_75D.nc' #nom du fichier netcdf a creer
folder = '/home/lauranec/NAS/charriel/KyagarGlacier/orb075D_vel-128-64px-intCorr-11-110d+/EPSG32643/' #dossier contenant les geotiff a mettre sous format netcdf
geotif_ref = '/home/lauranec/NAS/charriel/KyagarGlacier/orb075D_vel-128-64px-intCorr-11-110d+/EPSG32643/velocity_grid_x_m-day2012-11-20_vs_2013-08-22_geo.tif' #geotiff de reference
sensor_name = 'TSX_orb75D'  # PAZ_asc ou PAZ_desc

### MAIN

# Creation of netcdf file
ds = nc.Dataset(nc_name, 'w', format='NETCDF4')

geotif = gdal.Open(geotif_ref, gdal.GA_ReadOnly)

# Create Title, Author, history
ds.Conventions = 'CF-1.6'
ds.title = 'Cube of Ice Velocity'
ds.author = 'S. Leinss, L. Charrier'  # a modifier
ds.history = 'Created ' + time.ctime(time.time())
ds.source = 'Intensity cross-correlation for SAR images, Normalized cross correlation of the brightness orientation for optical images'
ds.references = 'Kyagar glacier: Round, V., Leinss, S., Huss, M., Haemmig, C., & Hajnsek, I. (2017). Surge dynamics and lake outbursts of Kyagar Glacier, Karakoram. The Cryosphere, 11(2), 723‑739. https://doi.org/10.5194/tc-11-723-2017'

#Get the the x and y (in the image)
ulx, xres, xskew, uly, yskew, yres  = geotif.GetGeoTransform() #top-left x, w-e pixel resolution, 0, top left y, 0, n-s pixel resolution
lrx = ulx + (geotif.RasterXSize * xres)
lry = uly + (geotif.RasterYSize * yres)

print(geotif.RasterXSize,geotif.RasterYSize)
#Create Dimensions
ds.createDimension('x', geotif.RasterXSize)
ds.createDimension('y', geotif.RasterYSize)
ds.createDimension('z', None) #temps peut grandir infinement
ds.createDimension('nchar',9)

#Create variables

mapping = ds.createVariable('mapping', 'S1')

x = ds.createVariable('x', 'f8', ('x',))
x.units = 'm'
x.axis = "X"
x.long_name = 'Cartesian x-coordinate'
x.grid_mapping = 'UTM_projection'

y = ds.createVariable('y', 'f8', ('y',))
y.units = 'm'
y.axis = "Y"
y.long_name = 'Cartesian y-coordinate'
y.grid_mapping = 'UTM_projection'

vx = ds.createVariable('vx', 'f4', ('z', 'y', 'x',), fill_value=np.nan)
vx.units = 'm/y'
vx.long_name = 'x component of velocity vector '
vx.grid_mapping = 'UTM_projection'

vy = ds.createVariable('vy', 'f4', ('z', 'y', 'x',), fill_value=np.nan)
vy.units = 'm/y'
vy.long_name = 'y component of velocity vector '
vy.grid_mapping = 'UTM_projection'

##optionel
vv = ds.createVariable('vv', 'f4', ('z', 'y', 'x',), fill_value=np.nan)  # module
vv.units = 'm/y'
vv.long_name = 'velocity magnitude '
vv.grid_mapping = 'UTM_projection'

date1 = ds.createVariable('date1', 'i4', ('z',))
date1.units = 'day (Modified Julian Date)'
date1.content = 'Date of the first acquisition'

date2 = ds.createVariable('date2', 'i4', ('z',))
date2.units = 'day (Modified Julian Date)'
date2.content = 'Date of the second acquisition'

sensor = ds.createVariable('sensor','S1',('z','nchar'))
sensor.long_name = 'sensor used to acquire the images'

quality = ds.createVariable('quality', 'f4', ('z','y','x'),fill_value=np.nan)
quality.long_name = 'quality of vx and vy'
##a modifier
quality.content = 'A combination (average) of four different factors: 1) NCC: the normalized cross correlation value of the peak. 2) grad_quality: This is a measure which analyzes the shape of the peak. 3) 1.0 / (avg_peakdist > 1): Analyzes how broad the peak is. 4) 1.0 / (splitspec_peak_dist > 1): The peak of the cross correlation is caluclated in two separates parts of the spectrum (low and high frequency components).'
quality.grid_mapping = 'UTM_projection'

#Assign Latitude and Longitude
x[:] = np.arange(ulx, lrx, xres)
y[:] = np.arange(uly, lry, yres)

#Get projection
prj=geotif.GetProjection()
srs=osr.SpatialReference(wkt=prj)

mapping.grid_mapping_name = 'universal_transverse_mercator'
# mapping.utm_zone_number = 43
mapping.spatial_ref = srs.ExportToWkt()

#Files the variables
files = glob.glob(
    f'{folder}velocity_grid_x_m-day*')  # cherche tous les fichiers qui ont une certaine chaine de caractere
z = 0
for vx_file in files:
    print(vx_file)
    # im = imread(vx_file)
    # print(im.shape)
    #
    end_file = vx_file.split('velocity_grid_x_m-day')[-1]
    begin_file = vx_file.split('velocity_grid_x')[0]
    vy_file = f'{begin_file}velocity_grid_y_m-day{end_file}'
    vv_file = f'{begin_file}velocity_grid_abs_m-day{end_file}'
    quality_file = f'{begin_file}velocity_grid_quality_{end_file}'
    geotif = gdal.Open(vx_file)

    # on rempli chaque variable avec un tableau de valeur, qui correspond a un z donne
    vx[z, :, :] = imread(vx_file)
    vy[z, :, :] = imread(vy_file)
    vv[z, :, :] = imread(vv_file)
    quality[z, :, :] = imread(quality_file)
    # convert date to julian date, keep only the second returned number
    date1[z] = date2mjd(datetime.strptime(vx_file.split('/')[-1].split('day')[-1][:10], '%Y-%m-%d').date())
    date2[z] = date2mjd(datetime.strptime(vx_file.split('/')[-1].split('day')[-1][14:24], '%Y-%m-%d').date())
    sensor[z] = nc.stringtochar(np.array(sensor_name, 'S9'))
    z += 1

ds.nx = geotif.RasterXSize  # nombre de colonne
ds.ny = geotif.RasterYSize  # nombre de ligne
ds.nz = z  # nombre de couche
ds.i = ulx  # top-left pixel (optionnel) colonne
ds.j = uly  # top-left pixel (optionnel) ligne
ds.proj4 = srs.GetAttrValue('GEOGCS')

ds.close()  # ferme le fichier

# Merge

# import xarray as xr
#
# L8_147 = xr.open_dataset('/home/lauranec/Documents/Donnees_Sylvan/Kyagar-velocity/concate_L8.nc')
# L8_148 = xr.open_dataset('/home/lauranec/Documents/Donnees_Sylvan/Kyagar-velocity/Kyagar_velocities_S1_asc129.nc')
# xr.merge([L8_147, L8_148])
#
# ds = xr.open_mfdataset('/home/lauranec/Documents/Donnees_Sylvan/Kyagar-velocity/*L8*.nc', combine='nested',
#                        concat_dim='z')
# ds.to_netcdf('/home/lauranec/Documents/Donnees_Sylvan/Kyagar-velocity/concate_L8.nc')


import torch
import torchvision.transforms as transforms
import torchvision
import torch.optim as optim
import torch.nn as nn
import torch.nn.utils.prune as prune
import torch.nn.functional as F
import argparse
import time
import os
import path
from Model.resnet import resnet50
from pthflops import count_ops
import Model.resnet_cifar as resnet_cifar10
from utils.mask_schedule import RewarmSchedule,WarmSchedule,WarmScheduleLinear,MileStone

# cifar10 model download from
# https://github.com/chenyaofo/pytorch-cifar-models/blob/master/pytorch_cifar_models/resnet.py

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='FetalHeart')
    parser.add_argument("--lr", type=float, default=1e-3)
    parser.add_argument("--arch",type=str,default='resnet56')
    parser.add_argument("--pretrained",action='store_true')
    parser.add_argument('--train',action='store_true')
    parser.add_argument('--epoch',type=int,default=100)
    parser.add_argument('--finetune',action='store_true')
    parser.add_argument('--momentum',type=float,default=0.9)
    parser.add_argument('--weight_decay',type=float,default=0)
    parser.add_argument('--prune_rate',type=float,default=0.9)
    parser.add_argument('--mask_rate',type=float,default=0.8)
    parser.add_argument('--mask_gamma',type=float,default=0.01)
    parser.add_argument('--use_new_method',action='store_true')
    parser.add_argument('--warm_up_mask',action='store_true')
    parser.add_argument('--warm_up_gamma', action='store_true')
    parser.add_argument('--start_epoch',type=int,default=5)
    parser.add_argument('--warm_iter',type=int,default=20)
    parser.add_argument('--noise_level',type=float,default=1e-6)
    parser.add_argument('--global_topk',type=bool,default=False)

    args = parser.parse_args()
    device = 'cuda'
    if args.arch == 'resnet50':

        if args.pretrained:
            model = resnet50(pretrained=True,device=device)
        else:
            model = resnet50(device=device)

    if args.arch == 'resnet20':
        model = resnet_cifar10.cifar10_resnet20()
        if args.pretrained:
            st = torch.load('Model/state_dicts/resnet20.pt')
            model.load_state_dict(st)

    if args.arch == 'resnet56':
        model = resnet_cifar10.cifar10_resnet56()
        if args.pretrained:
            st = torch.load('Model/state_dicts/resnet56.pt')
            model.load_state_dict(st)

    model.to(device)
    if not os.path.exists("result/"):
        os.mkdir("result/")
    transform = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize(mean=(0.4914, 0.4822, 0.4465), std=(0.247, 0.2435, 0.2616))])

    trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                            download=True, transform=transform)
    trainloader = torch.utils.data.DataLoader(trainset, batch_size=256,
                                              shuffle=True, num_workers=2)

    testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                           download=True, transform=transform)
    testloader = torch.utils.data.DataLoader(testset, batch_size=256,
                                             shuffle=False, num_workers=2)

    if args.train:
        optimizer = optim.SGD(model.parameters(), momentum=args.momentum,
                              lr=args.lr, weight_decay=args.weight_decay)
        lr_schedule = torch.optim.lr_scheduler.MultiStepLR(optimizer,
                                                           milestones=[40,60],
                                                           gamma=0.1)
        g_schedule = WarmScheduleLinear(args.start_epoch,
                                   args.start_epoch + args.warm_iter,
                                    args.mask_gamma,0.5)
        noise_shedule = MileStone([20,40,60],[0,0,0,0])
        losser = nn.CrossEntropyLoss()

        @torch.no_grad()
        def set_model_grad(model:nn.Module,amount=0.95,gamma=0.1,noise_level=0,glob=False):
            if glob:
                para_container = []
                for name, m in model.named_modules():
                    if isinstance(m, nn.Linear) or isinstance(m, nn.Conv2d):
                        para_container.append(m.weight)
                vector = nn.utils.parameters_to_vector(para_container).detach().clone()
                elenum = vector.data.nelement()
                topk = torch.topk(torch.abs(vector.data).view(-1), k=int(elenum * (1-amount)), largest=True)
                indice = vector.clone()
                indice[topk.indices] = 0.0
                pointer=0
                for param in para_container:
                    num_param = param.numel()
                    # Slice the vector, reshape it, and replace the old data of the parameter
                    param.grad += gamma * indice[pointer:pointer + num_param].view_as(param).data
                    param.grad += torch.rand(param.grad.shape, device=param.device) * noise_level
                    # Increment the pointer
                    pointer += num_param
                pass

            else:
                for name, m in model.named_modules():
                    if isinstance(m, nn.Linear) or isinstance(m, nn.Conv2d):
                        elenum = m.weight.data.nelement()
                        topk = torch.topk(torch.abs(m.weight.data).view(-1), k=int(elenum * amount), largest=False)
                        m.weight.grad.view(-1)[topk.indices] += gamma * m.weight.data.view(-1)[topk.indices]
                        m.weight.grad += torch.rand(m.weight.shape, device=m.weight.device) * noise_level

        start_rate = 0
        start_gamma = args.mask_gamma
        mask_warm_up_end_ep = args.warm_iter + args.start_epoch
        start_gamma = start_gamma/float(2**mask_warm_up_end_ep)
        end_gamma = args.mask_gamma
        end_rate = args.mask_rate

        for e in range(args.epoch):
            train_loss = 0
            right_pred = 0
            all_pred = 0
            model.train()
            start = time.time()
            for i,(data,label) in enumerate(trainloader):
                data = data.to(device)
                label = label.to(device)
                output = model(data)
                optimizer.zero_grad()
                loss = losser(F.softmax(output),label)
                loss.backward()

                if args.use_new_method :
                    gm = g_schedule(e)
                    set_model_grad(model,end_rate,gm,noise_shedule(e),args.global_topk)
                optimizer.step()

                with torch.no_grad():
                    _,pred = torch.max(output,dim=1)
                    right_pred += len(torch.where(pred.view(-1)==label.view(-1))[0])
                    all_pred += len(label.view(-1))
                    train_loss += loss.item()
            end = time.time()
            print('epoch{} train_loss={:2f},train_acc={}/{}({:.2f}%)'.format(e,train_loss,
                                    right_pred,all_pred,100*right_pred/all_pred))
            print('gamma:',g_schedule(e),'time:%.2f'%(end-start))

            model.eval()

            with torch.no_grad():
                right_pred = 0
                all_pred = 0
                loss_all = 0
                for data, label in testloader:
                    data = data.to(device)
                    label = label.to(device)
                    output = model(data)
                    loss = losser(F.softmax(output), label)
                    loss_all  += loss.item()
                    _, pred = torch.max(output, dim=1)
                    right_pred += len(torch.where(pred.view(-1) == label.view(-1))[0])
                    all_pred += len(label.view(-1))

            print('epoch{} test_acc={}/{}({:.2f}%),loss:{}'.format(e,
                            right_pred, all_pred, 100*right_pred / all_pred,loss_all))
            lr_schedule.step()
    # prune step
    model.to(device)
    model.eval()
    with torch.no_grad():
        right_pred = 0
        all_pred = 0
        for data, label in testloader:
            data = data.to(device)
            label = label.to(device)
            output = model(data)
            _,pred = torch.max(output, dim=1)
            right_pred += len(torch.where(pred.view(-1) == label.view(-1))[0])
            all_pred += len(label.view(-1))
        for data,label in testloader:
            data = data.to(device)
            #count_ops(model,data)
            break
    print('test_acc_before_prune={}/{}({:.2f}%)'
          .format(right_pred, all_pred,100* right_pred / all_pred))

    for name,m in model.named_modules():
        print(name)
        if (isinstance(m,nn.Linear) or isinstance(m,nn.Conv2d)):
            print("small value in {}.weight: {:.2f}%({}/{})".format(name,
                100. * float(torch.sum(m.weight <= 1e-3))
                / float(m.weight.nelement()),torch.sum(m.weight <= 1e-3),m.weight.nelement()))

    parameters_to_prune = []
    importance_score = {}
    #print(model.state_dict().keys())
    for name,m in model.named_modules():
        if (isinstance(m,nn.Linear) or isinstance(m,nn.Conv2d)):
            parameters_to_prune.append((m,'weight'))
            # bn_name = name[:-5] + 'bn' + name[-1]
            # print(bn_name)
            # if bn_name in model.state_dict():
            #     bn:nn.BatchNorm2d = model.state_dict()[bn_name]
            #     print(bn_name, bn.weight)
            #     importance_score[(m,'weight')] = getattr(m,'weight')*bn.weight
    #print('para_to_prune',parameters_to_prune)
    prune.global_unstructured(
        parameters_to_prune,
        prune.L1Unstructured,
        importance_score,
        amount=args.prune_rate
    )

    model.eval()
    with torch.no_grad():
        right_pred = 0
        all_pred = 0
        for data, label in testloader:
            data = data.to(device)
            label = label.to(device)
            output = model(data)
            _,pred= torch.max(output, dim=1)
            right_pred += len(torch.where(pred.view(-1) == label.view(-1))[0])
            all_pred += len(label.view(-1))
        for data,label in testloader:
            data = data.to(device)
            break

    print('test_acc_after_prune={}/{}({:.2f}%)'
          .format(right_pred, all_pred, 100*right_pred / all_pred))

    for e in range(10):
        train_loss = 0
        right_pred = 0
        all_pred = 0
        model.train()
        for i, (data, label) in enumerate(trainloader):
            data = data.to(device)
            label = label.to(device)
            output = model(data)
            optimizer.zero_grad()
            loss = losser(F.softmax(output), label)
            loss.backward()
            optimizer.step()

            with torch.no_grad():
                _, pred = torch.max(output, dim=1)
                right_pred += len(torch.where(pred.view(-1) == label.view(-1))[0])
                all_pred += len(label.view(-1))
                train_loss += loss.item()

        print('epoch{} train_loss={:2f},train_acc={}/{}({:.2f}%)'.format(e, train_loss,
                                                                         right_pred, all_pred,
                                                                         100 * right_pred / all_pred))

        model.eval()
        with torch.no_grad():
            right_pred = 0
            all_pred = 0
            for data, label in testloader:
                data = data.to(device)
                label = label.to(device)
                output = model(data)
                _, pred = torch.max(output, dim=1)
                right_pred += len(torch.where(pred.view(-1) == label.view(-1))[0])
                all_pred += len(label.view(-1))

        print('epoch{} test_acc={}/{}({:.2f}%)'.format(e,
                                                       right_pred, all_pred, 100 * right_pred / all_pred))


import pytest

import random
import logging
from opencontext_py.libs.utilities import chronotiles

logger = logging.getLogger("tests-unit-logger")

TEST_ARGS = [
    (
        '5G',
        5 * pow(10, 9),
        [1,2,10,25,122,637,5000, 56.32 * pow(10, 6), 223.2 * pow(10, 6),]
    ),
    (
        '2.5G',
        2.5 * pow(10, 9),
        [1,2,10,25,432, 1252, 8.47 * pow(10, 6), 101.6 * pow(10, 6),]
    ),
    (
        '500M',
        500 * pow(10, 6),
        [1, 2, 10, 25, 897, 10256, 3.88 * pow(10, 6), 87.6 * pow(10, 6),]
    ),
    (
        '10M',
        10 * pow(10, 6),
        [1, 2, 10, 25, 751, 6752, 2.56 * pow(10, 3), 156.6 * pow(10, 3),]
    ),
    (
        '10k',
        10 * pow(10, 3),
        [1, 2, 10, 25, 121, 972, 2523, 6500,]
    ),
]

NUMBER_RANDOM_TEST_SPANS = 100

def test_encode_decode_paths():
    """Tests encoding and decoding of chronotile paths."""
    for prefix, path_max_bp, test_spans in TEST_ARGS:
        # Add NUMBER_RANDOM_TEST_SPANS more random test spans,
        # with ranges up to 95 % the total time range allowed for the path duration
        test_spans += [
            random.randrange(1, (path_max_bp * 0.95), 1)
            for i in range(NUMBER_RANDOM_TEST_SPANS)
        ]
        for test_span in test_spans:
            latest_bp = round( random.randrange(0, path_max_bp), 0)
            earliest_bp = round((latest_bp + test_span), 0)
            logger.info(
                f'Checking dates: {earliest_bp} to {latest_bp}'
            )
            if latest_bp > path_max_bp or earliest_bp > path_max_bp:
                # We expect an error to be raised in this case!
                logger.info(
                    f'Out of bound date should raise error (max bp: {path_max_bp})'
                )
                with pytest.raises(Exception):
                     path = chronotiles.encode_path(
                        earliest_bp=earliest_bp,
                        latest_bp=latest_bp,
                        new_path=(f'{prefix}{chronotiles.PREFIX_DELIM}')
                    )
                continue

            path = chronotiles.encode_path(
                earliest_bp=earliest_bp,
                latest_bp=latest_bp,
                new_path=(f'{prefix}{chronotiles.PREFIX_DELIM}')
            )
            decode_dict = chronotiles.decode_path_dates(path)
            logger.info(
                f'Checking round-trip: {path}, length: '
                f'{chronotiles.raw_path_depth(path)}'
            )
            logger.info(
                f'Parsed dict: {decode_dict}'
            )
            # Assert that the round-trip of encoding to decoding worked!
            assert latest_bp == decode_dict['latest_bp']
            assert earliest_bp == decode_dict['earliest_bp']
            # Now test that trimming the paths gives us date ranges that
            # still appropriately bound our inputs.
            act_path = path[0:-1]
            while chronotiles.raw_path_depth(act_path) > 5:
                logger.info(
                    f'Checking bounds of trimmed: {act_path}, length: '
                    f'{chronotiles.raw_path_depth(act_path)}'
                )
                decode_dict = chronotiles.decode_path_dates(act_path)
                # The input values should be within the bounds of the
                # earliest and lastest values of the input dates.
                assert latest_bp >= decode_dict['latest_bp']
                assert earliest_bp <= decode_dict['earliest_bp']
                act_path = act_path[0:-1]


import re
import os, shutil
import os.path
import urllib.request

def get_last_character(string):
	return string[len(string) - 1:]

def line_contains_the_same_conditions(line, conditions):
	for condition in conditions:
		if line.count(condition) > 1:
			return True
	return False

directory_path = "/Users/Alina/Google_Drive_BBK/Comp/Compatible/"
all_files = sorted(os.listdir(directory_path))

conditions = ["CYS L", "CYS H", "CYS A", "CYS B"]

res1 = []

for index, file in enumerate(all_files, start=1):
	if not file.endswith(".pdb"):
		continue
	my_file = open(directory_path + file)
	# read the content
	file_contents = my_file.readlines()

	for line in file_contents:
		if line.strip().startswith("SSBOND   3 "):
			if line_contains_the_same_conditions(line, conditions) == False:
				for condition in conditions:
					starts_at = line.find(condition)
					if starts_at > 0:
						stri = line[starts_at + len(condition):].strip()
						number = stri[:3]
						last = int(number) - 2
						res1.append(get_last_character(condition) + str(last) + "-" + number)
						shutil.copy(directory_path + file, "/Users/Alina/Google_Drive_BBK/Comp/Compatible_SSBOND/")
			else:
				print("Contains the same conditions, file igonred")


from django.contrib.admin import AdminSite
from django.views.decorators.cache import never_cache
from .models import Ticket
from django.shortcuts import render_to_response

class CustomAdminSite(AdminSite):

    def get_urls(self):
        urls = super(CustomAdminSite, self).get_urls()
        return urls

    @never_cache
    def index(self, request, extra_context=None):
        if extra_context is None:
            extra_context = {}

        show_all = False

        if request.GET and 'show' in request.GET:
            if request.GET['show'] == 'all':
                show_all = True

        if show_all:
            tickets = Ticket.objects.filter(
                asignee=request.user).order_by('created_date')
        else:
            tickets = Ticket.objects.filter(asignee=request.user).filter(
                status='O').order_by('created_date')

        context = {
            'tickets': tickets,
            'show_all': show_all,
        }
        context.update(extra_context or {})
        return super(CustomAdminSite, self).index(request, context)

custom_admin = CustomAdminSite()


"""Simple node holding Frame-counting values"""
from vrml import node, field
from OpenGLContext.scenegraph.text import glutfont
from OpenGL.GL import *

class FrameCounter( node.Node ):
    """Simple node holding Frame-counting values

    This node is used to hold information about the amount
    of time required to render frames for the context.
    """
    PROTO = 'FrameCounter'
    count = field.newField( 'count', 'SFInt32', 1, 0)
    totalTime = field.newField( 'totalTime', 'SFFloat', 1, 0.0)
    lastTime = field.newField( 'lastTime', 'SFFloat', 1, 0.0)
    display = field.newField( 'display', 'SFBool', 1, True)
    _font = None

    def font( self, context ):
        if not self._font:
            from OpenGLContext.scenegraph.basenodes import FontStyle
            self._font = glutfont.GLUTBitmapFont(FontStyle(
                size = 1.0
            ))
        return self._font

    def addFrame( self, duration ):
        """Add the duration of a single frame to the counter

        This method does *not* send field changed events, so
        should not trigger a refresh of the scene, which is
        important, as it will be called after *every* frame.
        """
        self.__class__.count.fset( self, self.count + 1, notify=0)
        self.__class__.totalTime.fset( self, self.totalTime + duration, notify=0)
        self.__class__.lastTime.fset( self, duration, notify=0)
        return duration
    def summary( self ):
        """Give a summary of framerates

        returns (count, average fps, last frame-time)
        """
        if self.count:
            reallySmall = 0.00000000001
            return (
                self.count,
                round(float( self.count)/(self.totalTime or reallySmall), 4),
                self.lastTime
            )
        return (0,0,0)

    def Render( self, context ):
        """Render the frame-counter to the screen"""
        margin = 30
        tx,ty = context.getViewPort()
        if tx and ty:
            glPushAttrib( GL_ALL_ATTRIB_BITS )
            try:
                glDisable( GL_DEPTH_TEST )
                glDisable( GL_LIGHTING )
                glMatrixMode( GL_PROJECTION )
                glLoadIdentity()
                glOrtho( 0, tx, 0, ty, -1, 1 )
                glMatrixMode( GL_MODELVIEW )
                glLoadIdentity()
                glColor4f( 1.0,1.0,1.0, 1.0)
                try:
                    glTranslated( 10,margin*2,0.0 )
                    count,avg,last = self.summary()
                    last *= 1000
                    self.font(context).render(
                        'fps avg:%0.1f\ncurr ms: %0.0f'%(avg,last)
                    )
                finally:
                    glEnable( GL_DEPTH_TEST )
                    glLoadIdentity()
            finally:
                glPopAttrib()


from Crous.objects import RU

from utils.data import icons
from utils.image import image

import discord

import datetime
import pytz

def get_clean_date(day, month, year):
    jours = ["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"]
    mois = ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembtre", "octobre", "novembre", "décembre"]

    date = pytz.timezone("Europe/Paris").localize(datetime.datetime(int(year), int(month), int(day)), is_dst=None)

    return f"{jours[int(date.strftime('%w'))-1]} {day} {mois[int(date.strftime('%m'))-1]}"

async def load_embed(client, data: RU):
    embeds = []
    options = []

    if len(data.dates) == 0:
        embed = discord.Embed(title=f"{data.info.nom} - Error 404", description=f"**`•` Le CROUS ne fournit pas d'information actuellement pour ce restaurant...**\n**`•` Mis à jour**: <t:{int(datetime.datetime.utcnow().timestamp())}:R> (<t:{int(datetime.datetime.utcnow().timestamp())}>)", color=client.color, url=data.info.url)
        embed.set_footer(text=client.footer_text, icon_url=client.avatar_url)
        embeds.append(embed)
        options.append(discord.SelectOption(label="Indisponible...", description=f"{data.info.nom}", value=0, default=True))
    else:
        paris_dt = pytz.timezone("Europe/Paris").localize(datetime.datetime.now(), is_dst=None)

        index = 0

        for menu in data.menus:
            pass_menu = False
            embed = None

            for i in range(1, 4): # Check Week-ends because sometimes Friday's menu is still displayeds
                new_dt = paris_dt - datetime.timedelta(days=i)
                if get_clean_date(int(new_dt.strftime("%d")), int(new_dt.strftime("%m")), int(new_dt.strftime("%Y"))) == menu.date:
                    pass_menu = True

            if not pass_menu:
                if not embed:
                    embed = discord.Embed(title=f"{data.info.nom}", description=f"**`•` Menu du `{str(menu.date).title()}`**\n**`•` Mis à jour**: <t:{int(datetime.datetime.utcnow().timestamp())}:R> (<t:{int(datetime.datetime.utcnow().timestamp())}>)\n\u2063", color=client.color, url=data.info.url)

                if isinstance(menu.midi, str):
                    embed.add_field(name=f"\u2063", value=f"**{menu.midi}**")
                else:
                    count = 0
                    msg = ""

                    for i in menu.midi:
                        w = '\n- '.join(i.data)
                        msg += f"**{i.categorie}**\n- {w}\n\n"
                        count += 1

                        if count == 3:
                            embed.add_field(name=f"\u2063", value=msg)
                            embed.add_field(name="", value="")
                            msg = ""

                    if msg != "":
                        embed.add_field(name=f"\u2063", value=msg)

                embed.set_thumbnail(url=client.avatar_url)
                embed.set_footer(text=client.footer_text, icon_url=client.avatar_url)
                embeds.append(embed)
                options.append(discord.SelectOption(label=str(menu.date).title(), description=f"{data.info.zone} - {data.info.nom}", value=index, default=True if index == 0 else False))

                index += 1

    if len(embeds) == 0:
        embed = discord.Embed(title=f"{data.info.nom} - Error 404", description=f"**`•` Le CROUS ne fournit pas d'information actuellement pour ce restaurant...**\n**`•` Mis à jour**: <t:{int(datetime.datetime.utcnow().timestamp())}:R> (<t:{int(datetime.datetime.utcnow().timestamp())}>)", color=client.color, url=data.info.url)
        embed.set_footer(text=client.footer_text, icon_url=client.avatar_url)
        embeds.append(embed)
        options.append(discord.SelectOption(label="Indisponible...", description=f"{data.info.nom}", value=0, default=True))

    ru_map = await image(
        url=f"https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/geojson(%7B%22type%22%3A%22Point%22%2C%22coordinates%22%3A%5B{data.info.coords.long}1%2C{data.info.coords.lat}%5D%7D)/{data.info.coords.long},{data.info.coords.lat},15.25,0,0/1000x400?access_token={client.mapbox}",
        session=client.session
    )

    return (embeds, options, ru_map)


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

# # 8. Optimization: Exercise Solutions

# ## 1. Try with you own function
# 1) Define a function of your interest (with two or more inputs) to be minimized or maximized.
# It can be an explicit mathematical form, or given implictly as a result of simulation.

# In[1]:

import numpy as np
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')

# In[2]:

def fun(x, a=10):
    """sine in quardatic valley"""
    x = np.array(x)
    y = (x[0]**2+x[1]**2) + a*np.sin(x[0])
    return y

def fun_grad(x, a=10):
    """gradient of dips(x)"""
    df1 = 2*x[0] + a*np.cos(x[0])
    df2 = 2*x[1]
    return np.array([df1, df2])

# 2) Visualize the function, e.g., by surface plot or contour plot.

# In[3]:

w = 5
N = 10
x = np.linspace(-w,w,N)
x1, x2 = np.meshgrid(x, x)
y = fun((x1, x2), 10)
fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(projection='3d')
ax.plot_surface(x1, x2, y, cmap='viridis')
plt.xlabel("x1"); plt.ylabel("x2");

# In[ ]:

# 3) Mixmize or minimize the function using two or more optimization algorithms, e.g.
#
# * Gradient ascent/descent
# * Newton-Raphson method
# * Evolutionary algorithm
# * scpy.optimize
#
# and compare the results with different starting points and parameters.

# ### Gradiend descent

# In[4]:

def grad_descent(f, df, x0, eta=0.01, eps=1e-6, imax=1000):
    """Gradient descent"""
    xh = np.zeros((imax+1, len(np.ravel([x0]))))  # history
    xh[0] = x0
    f0 = f(x0)  # initialtization
    for i in range(imax):
        x1 = x0 - eta*df(x0)
        f1 = f(x1)
        # print(x1, f1)
        xh[i+1] = x1
        if(f1 <= f0 and f1 > f0 - eps):  # small decrease
            return(x1, f1, xh[:i+2])
        x0 = x1
        f0 = f1
    print("Failed to converge in ", imax, " iterations.")
    return(x1, f1, xh)

# In[5]:

x0 = [1,2]
xmin, fmin, xhist = grad_descent(fun, fun_grad, x0, 0.01)
print(xmin, fmin)
plt.contour(x1, x2, y)
plt.plot(xhist[:,0], xhist[:,1], '.-');

# In[6]:

x0 = [2,2]
xmin, fmin, xhist = grad_descent(fun, fun_grad, x0, 0.01)
print(xmin, fmin)
plt.contour(x1, x2, y)
plt.plot(xhist[:,0], xhist[:,1], '.-');

# In[ ]:

# ### scipy.optimize

# In[7]:

from scipy.optimize import minimize

# In[8]:

x0 = [1,2]
result = minimize(fun, x0, jac=fun_grad, options={'disp': True})
print( result.x, result.fun)
plt.contour(x1, x2, y)
plt.plot(x0[0], x0[1], 'x', result.x[0], result.x[1], 'o');

# In[9]:

x0 = [2,2]
result = minimize(fun, x0, jac=fun_grad, options={'disp': True})
print( result.x, result.fun)
plt.contour(x1, x2, y)
plt.plot(x0[0], x0[1], 'x', result.x[0], result.x[1], 'o');

# In[ ]:

# Option) Set equality or inequality constraints and apply an algorithm for constrained optimization.

# In[10]:

# h(x) = x[0] - x[1] = 0
def h(x):
    return 2*x[0] - x[1] - 4
def h_grad(x):
    return np.array([2, -1])

# With equality constraint $h(x)=0$.

# In[11]:

x0 = [1,2]
cons = ({'type':'eq', 'fun':h, 'jac':h_grad})
result = minimize(fun, [1,-3], jac=fun_grad,
            method='SLSQP', constraints=cons, options={'disp': True})
print( result.x, result.fun)
plt.contour(x1, x2, y)
plt.plot([0,4], [-4,4])  # h(x) = 0
plt.plot(x0[0], x0[1], 'x', result.x[0], result.x[1], 'o');

# In[12]:

x0 = [1,2]
cons = ({'type':'ineq', 'fun':h, 'jac':h_grad})
result = minimize(fun, [1,-3], jac=fun_grad,
            method='SLSQP', constraints=cons, options={'disp': True})
print( result.x, result.fun)
plt.contour(x1, x2, y)
plt.plot([0,4], [-4,4])  # h(x) = 0
plt.plot(x0[0], x0[1], 'x', result.x[0], result.x[1], 'o');

# In[ ]:

# In[ ]:


from math import sqrt
MAX = 1000000.0

def dist(p1, p2):
	return sqrt((p1[0] - p2[0])*(p1[0] - p2[0]) + \
				(p1[1] - p2[1])*(p1[1] - p2[1]))

def cost(points, i, j, k):
	p1 = points[i]
	p2 = points[j]
	p3 = points[k]
	return dist(p1, p2) + dist(p2, p3) + dist(p3, p1)

def mTC(points, i, j):

	# There must be at least three points between i and j
	# (including i and j)
	if (j < i + 2):
		return 0

	# Initialize result as infinite
	res = MAX

	# Find minimum triangulation by considering all
	for k in range(i + 1, j):
		res = min(res, (mTC(points, i, k) + \
						mTC(points, k, j) + \
						cost(points, i, k, j)))

	return round(res, 4)

points = [[0, 0], [1, 0], [2, 1], [1, 2], [0, 2]]
n = len(points)
print(mTC(points, 0, n-1))


import cv2

def get_bytes(input_image, y):

    image = cv2.imread(input_image)
    height, width, _ = image.shape

    if y - 7 < 0:
        y_one = 0
    else:
        y_one = y - 7
    #
    # y_one = 0 if y - 7 < 0 else y_one = y - 7

    cropped_image = image[y_one: y + 12, 0: width]
    _, buffer = cv2.imencode('.jpg', cropped_image)
    image_bytes = buffer.tobytes()

    return image_bytes

# input_image = "after_conversion/shifted_image.png"
# y = 719   # Начальная координата Y для обрезки
# cropped_image_bytes = crop_image_a(input_image, y)
#
# output_path = "output_image.jpg"
# with open(output_path, 'wb') as file:
#     file.write(cropped_image_bytes)


import PySimpleGUI as sg

class TelaCurso():
  def __init__(self):
      self.__window = None
      self.__cursos = []

  def init_components(self):
    layout = [
      [sg.Text('Escolha sua opção:')],
      [sg.Text('1 - Cadastrar Curso', size=(15, 1))],
      [sg.Text('2 - Operações do curso', size=(20, 1))],
      [sg.Text('3 - Relatórios do curso', size=(20, 1))],
      [sg.Text('0 - Voltar', size=(20, 1))],
      [sg.Text('Escolha o desejado:', size=(15, 1)), sg.InputText()],
      [sg.Submit()]
    ]
    self.__window = sg.Window('Tela curso').Layout(layout)

  def open(self):
    self.init_components()
    values = self.__window.Read()
    return values

  def pega_dados_curso(self):
    self.close()
    layout = [
      [sg.Text('Escolha o nome do curso:')],
      [sg.Text('Nome do curso:', size=(15, 1)), sg.InputText("", key="nome")],
      [sg.Text('Nome da instituição: ', size=(15, 1)), sg.InputText("", key="instituicao")],
      [sg.Submit()]
    ]
    self.__window = sg.Window('Criar curso').Layout(layout)
    values = self.__window.Read()
    self.__window.Close()
    return values[1]

  def seleciona_curso(self, cursos):
    self.close()
    layout = [
      [sg.Text('Escolha o curso:', size=(20, 1))]
    ]
    i = 0
    for curso in cursos:
      layout.append([sg.Text(str(i) + ": " + curso.nome, size=(20, 1))])
      i +=1

    layout.extend([[sg.Text('Qual opção:', size=(15, 1)), sg.InputText(key="opcao")], [sg.Submit()]])

    self.__window = sg.Window('Tela curso').Layout(layout)
    values = self.__window.Read()
    num = values[1]
    self.__window.Close()
    self.__cursos = []
    return int(num['opcao'])

  def relatorio_curso(self, cursos):
    self.close()
    layout = [
      [sg.Text('Lista de cursos:', size=(20, 1))]
    ]
    for curso in cursos:
      layout.append([sg.Text("Curso: " + curso.nome, size=(20, 1))])
      layout.append([sg.Text("Instituição: " + curso.instituicao, size=(20, 1))])
      layout.append([sg.Text("---", size=(20, 1))])

    layout.append([sg.Cancel()])
    self.__window = sg.Window('Tela relatórios').Layout(layout)
    self.__cursos = []
    values = self.__window.Read()
    num = values[0]
    self.__window.Close()
    return num

  def opcoes_curso(self):
    layout = [
      [sg.Text('Escolha sua opção:')],
      [sg.Text('1 - Excluir curso', size=(15, 1))],
      [sg.Text('2 - Editar curso', size=(20, 1))],
      [sg.Text('Qual opção:', size=(15, 1)), sg.InputText(key="opcao")],
      [sg.Submit()]
    ]
    self.__window = sg.Window('Escolher operação').Layout(layout)
    values = self.__window.Read()
    num = values[1]
    self.__window.Close()
    return int(num['opcao'])

  def opcoes_editar(self):
    layout = [
      [sg.Text('O que deseja editar:')],
      [sg.Text('1 - Nome', size=(15, 1))],
      [sg.Text('2 - Instituição', size=(15, 1))],
      [sg.Text('Qual opção:', size=(15, 1)), sg.InputText(key="opcao")],
      [sg.Submit()]
    ]
    self.__window = sg.Window('Escolher edição').Layout(layout)
    values = self.__window.Read()
    num = values[1]
    self.__window.Close()
    return int(num['opcao'])

  def novo_campo(self, opcao):
    if (opcao == 1):
      layout = [
        [sg.Text('Qual o novo nome:', size=(15, 1)), sg.InputText(key="opcao")],
        [sg.Submit()]
      ]
      self.__window = sg.Window('Novo nome').Layout(layout)
      values = self.__window.Read()
      valor = values[1]
      self.__window.Close()
      return valor['opcao']

    if (opcao == 2):
      layout = [
        [sg.Text('Qual a nova instituição:', size=(15, 1)), sg.InputText(key="opcao")],
        [sg.Submit()]
      ]
      self.__window = sg.Window('Nova instituição').Layout(layout)
      values = self.__window.Read()
      valor = values[1]
      self.__window.Close()
      return valor['opcao']

  def lista_curso(self, dados_curso):
    self.__cursos.append(dados_curso["opcao"])

  def close(self):
    self.__window.Close()


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

import json

from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q

from rest_framework import serializers
from rest_framework.utils import model_meta

from apps.openedx_objects.models import (EdxOrg, EdxCourse, EdxCourseRun,
                                         EdxCourseEnrollment)
from .models import Permission, Role

User = get_user_model()

class BaseModelSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        self.own_objects = kwargs.pop('own_objects', None)
        super(BaseModelSerializer, self).__init__(*args, **kwargs)

class PermissionSertializer(BaseModelSerializer):
    target_name = serializers.CharField(source='get_object', read_only=True)
    target_type = serializers.CharField(read_only=True)

    class Meta:
        model = Permission
        fields = ('target_type', 'target_id', 'action_type', 'target_name')
        read_only_fields = fields

class RoleSerializer(BaseModelSerializer):
    permissions = PermissionSertializer(many=True, read_only=False)

    class Meta:
        model = Role
        fields = ('id', 'name', 'permissions')
        read_only_fields = ('id',)
        target_types = (
            EdxOrg._meta.verbose_name,
            EdxCourse._meta.verbose_name,
            EdxCourseRun._meta.verbose_name,
            EdxCourseEnrollment._meta.verbose_name,
        )

    def validate(self, value):
        ids = dict((k._meta.verbose_name, v) for k, v in self.own_objects.items())
        permissions = value.get('permissions', [])
        value['permissions'] = []

        if type(permissions) not in (list, tuple, set):
            raise serializers.ValidationError({
                    'permissions': ['This field must be a list.']
                })

        for perm in permissions:
            perm.pop('target_name', None)
            perm['target_type'] = perm['target_type'].replace(' ', '')

            if perm['action_type'] not in dict(Permission.action_choices):
                raise serializers.ValidationError({
                        'permissions': ['Unknown action type %s.' % perm['action_type']]
                    })

            if perm['target_type'] not in self.Meta.target_types:
                raise serializers.ValidationError({
                        'permissions': ['Unknown target type %s.' % perm['target_type']]
                    })

            if perm['target_id'] in ids[perm['target_type']]:
                value['permissions'].append(perm)

        if not value['permissions']:
            raise serializers.ValidationError({
                    'permissions': ['You do not have a right to this']
                })

        return value

    def to_internal_value(self, data):
        permissions = data.get('permissions', '[]')
        permissions = json.loads(permissions)

        ret = super(RoleSerializer, self).to_internal_value(data)

        ret['permissions'] = permissions

        return ret

    def update(self, instance, validated_data):
        for attr, value in validated_data.items():
            if attr == 'permissions':
                value = self._get_or_create_permissons(value)
            setattr(instance, attr, value)
        instance.save()

        return instance

    def create(self, validated_data):
        ModelClass = self.Meta.model

        # Remove many-to-many relationships from validated_data.
        # They are not valid arguments to the default `.create()` method,
        # as they require that the instance has already been saved.
        info = model_meta.get_field_info(ModelClass)
        many_to_many = {}
        for field_name, relation_info in info.relations.items():
            if relation_info.to_many and (field_name in validated_data):
                many_to_many[field_name] = validated_data.pop(field_name)

        try:
            instance = ModelClass.objects.create(**validated_data)
        except TypeError as exc:
            msg = (
                'Got a `TypeError` when calling `%s.objects.create()`. '
                'This may be because you have a writable field on the '
                'serializer class that is not a valid argument to '
                '`%s.objects.create()`. You may need to make the field '
                'read-only, or override the %s.create() method to handle '
                'this correctly.\nOriginal exception text was: %s.' %
                (
                    ModelClass.__name__,
                    ModelClass.__name__,
                    self.__class__.__name__,
                    exc
                )
            )
            raise TypeError(msg)

        # Save many-to-many relationships after the instance is created.
        if many_to_many:
            for field_name, value in many_to_many.items():
                if field_name == 'permissions':
                    value = self._get_or_create_permissons(value)
                setattr(instance, field_name, value)

        return instance

    def _get_or_create_permissons(self, permissions):
        value = []

        for perm in permissions:
            ct = ContentType.objects.get_by_natural_key(model=perm['target_type'],
                                                    app_label='openedx_objects')
            perm['target_type'] = ct
            perm_obj, created = Permission.objects.get_or_create(**perm)
            value.append(perm_obj.id)

        return value

class UserSerializer(BaseModelSerializer):
    role = RoleSerializer(many=True, read_only=False)

    class Meta:
        model = User
        fields = ('id', 'username', 'role')
        read_only_fields = ('id', 'username')

    def validate(self, value):
        role = value.get('role')

        if type(role) not in (list, tuple, set):
            raise serializers.ValidationError({
                    'role': ['This field must be a list.']
                })

        try:
            role = map(int, role)
        except ValueError:
            raise serializers.ValidationError({
                    'role': ['The list fields must be a integers.']
                })

        self_roles = self.Meta.model.objects.select_related()\
                    .filter(id=self.instance.id,
                    role__permissions__action_type='Manage(permissions)')\
                    .values_list('role__id', flat=True)

        query = None
        for model, ids in self.own_objects.iteritems():
            ct = ContentType.objects.get_for_model(model)
            if query is None:
                query = Q(permissions__target_type=ct,
                        permissions__target_id__in=ids)
            else:
                query |= Q(permissions__target_type=ct,
                        permissions__target_id__in=ids)

        self_roles = Role.objects.select_related().filter(query).values_list('id',
                                                                    flat=True)
        role = [r for r in role if r in self_roles]

        value['role'] = role

        return value

    def to_internal_value(self, data):
        role = data.get('role', '[]')
        role = json.loads(role)

        ret = super(UserSerializer, self).to_internal_value(data)

        ret['role'] = role

        return ret

    def update(self, instance, validated_data):
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()

        return instance


import bs4
import os.path
import pdfkit
import pytz
import requests
import tempfile
import urllib.parse
from bs4 import BeautifulSoup
from datetime import datetime, timezone, timedelta

from concierge.logger import get_logger
from concierge.scraper.common import Figure, template_path, template_loader, title_normalizer, render_option_us_letter

class AsahiEditorial:
    def __init__(self, url: str, article_id: str, article_date: datetime.date,
                 title: str, body: list, figure: Figure):
        self.logger = get_logger(__name__)
        self.type = 'editorial'
        self.lang = 'ja'
        self.url = url
        self.id = article_id
        self.date = article_date
        self.title = title.strip()
        self.filename = '{1}_{0}'.format(
            title_normalizer(self.title).replace('（社説）', '').replace(' ', '-').replace('　', '-'), self.date)
        self.body = body
        self.figure = figure
        self.template_path = template_path
        self.template = template_loader.get_template('asahi-editorial.html')
        self.temp_output = tempfile.NamedTemporaryFile(mode='w+b', delete=False)
        self.temp_image = tempfile.NamedTemporaryFile()
        if self.figure.image:
            self.temp_image.write(self.figure.image)
        self.temp_html = self._render_html()

    def _render_html(self):
        return self.template.render(
            template_path=self.template_path,
            lang=self.lang,
            title=self.title,
            reference_url=self.url,
            article_id=self.id,
            date=self.date,
            article=self.body,
            figure_img=self.temp_image.name,
            figure_cap=self.figure.caption
        )

    def _render_us_letter(self):
        """
        Render US Letter PDF from html
        (for Fujitsu QAUDERNO)

        :return:
        """
        self.temp_output.write(pdfkit.from_string(self.temp_html, output_path=False, options=render_option_us_letter))
        self.temp_output.close()

    def develop(self):
        self.logger.info('develop editorial...')
        self._render_us_letter()
        return {'path': self.temp_output.name, 'category': 'asahi', 'filename': self.filename, 'file_ext': '.pdf'}

    def clear(self):
        self.temp_image.close()

def _extract_article_id(url: str) -> str:
    """

    :param url:
    :return:
    """
    _path = urllib.parse.urlparse(url).path
    editorial_id, extension = os.path.splitext(os.path.basename(_path))
    return editorial_id

class AsahiScraper:
    def __init__(self, pdf_format: str):
        self.logger = get_logger(__name__)
        self.pdf_format = pdf_format
        self.timezone = pytz.timezone('Asia/Tokyo')
        self.today = datetime.now(tz=self.timezone)
        self._result = {'editorial': []}
        self._asahi_news_url = 'https://www.asahi.com'
        self.asahi_editorial_view_url = self._asahi_news_url + '/articles/{0}.html?iref=pc_rensai_long_16_article'
        self.asahi_editorials_url = 'https://www.asahicom.jp/rensai/json/da16.json'

    def _fetch_editorial_list(self) -> list:
        """
        Fetch editorial list by current date.

        :return: List of editorial article path.
        """
        editorials = []
        r = requests.get(self.asahi_editorials_url, headers={'referer': self._asahi_news_url})
        for article in r.json()['items']:
            if datetime.strptime(article['release_date'], '%Y%m%d%H%M%S').date() >= self.today.date():
                editorials.append(article['id'])
        return editorials

    def _fetch_editorial_page(self, url: str) -> bs4.element.Tag:
        """

        :param url: Url for fetch.
        :return:
        """
        r = requests.get(url)
        parse = BeautifulSoup(r.content, features='html.parser').find('main')
        return parse

    def _extract_editorial_title(self, contents: bs4.element.Tag) -> str:
        """

        :param contents:
        :return:
        """
        headers = contents.find('h1')
        return headers.text

    def _extract_editorial_figure(self, contents: bs4.element.Tag) -> Figure:
        """

        :param contents:
        :return:
        """
        image = b''
        figure = contents.find('figure')
        caption = figure.find('figcaption').text
        image_url = figure.find('img').get('src')
        if image_url.startswith('//'):
            image_url = 'https:' + image_url
        try:
            r = requests.get(image_url)
            if r.ok:
                image = r.content
        except ConnectionError:
            pass
        return Figure(image=image, caption=caption)

    def _extract_editorial_body(self, contents: bs4.element.Tag) -> list:
        """

        :param contents:
        :return:
        """
        body = []
        content = contents.find_all('p')
        for p in content:
            if p.text and not p.text.endswith('分'):
                body.append(p.text)
        return body

    def _fetch_editorial(self, page_id: str) -> AsahiEditorial:
        """

        :param url:
        :return:
        """
        self.logger.info('fetch editorial...')
        url = self.asahi_editorial_view_url.format(page_id)
        article_id = _extract_article_id(url)
        contents = self._fetch_editorial_page(url)
        title = self._extract_editorial_title(contents)
        figure = self._extract_editorial_figure(contents)
        body = self._extract_editorial_body(contents)
        return AsahiEditorial(url=url, article_id=article_id, article_date=self.today.date(),
                              title=title, body=body, figure=figure)

    def _push_to_result(self, payload) -> None:
        """

        :param payload:
        :return:
        """
        self.logger.info('push to result article {0}'.format(payload.id))
        result = payload.develop()
        if result:
            self._result[payload.type].append(result)
        payload.clear()

    def download_editorials(self) -> dict:
        """

        :return:
        """
        self.logger.info('download editorials from Asahi...')
        articles = self._fetch_editorial_list()
        if articles:
            for a in articles:
                self._push_to_result(self._fetch_editorial(a))
        return self._result


from dazzler.system import Page, BindingContext, transforms as t
from dazzler.components import core, charts

data = [
    {
        "y": i ^ 2,
        'z': i ^ 3,
        'x': i * 20,
        'name': f'named{i}',
        'u': f'under{i}',
    } for i in range(25)
]

margin = {
    'top': 10,
    'bottom': 10,
    'left': 10,
    'right': 10,
}

colors = [
    '#44bb33',
    '#003399',
    '#7d21e9',
    '#a333aa',
    '#b21199'
]

radar_data = [
    {'type': 'hockey', 'a': 100, 'b': 90, 'fill': colors[0]},
    {'type': 'baseball', 'a': 90, 'b': 60, 'fill': colors[1]},
    {'type': 'basketball', 'a': 75, 'b': 30, 'fill': colors[2]},
    {'type': 'football', 'a': 25, 'b': 100, 'fill': colors[3]},
    {'type': 'golf', 'a': 50, 'b': 10, 'fill': colors[4]},
]

treemap_data = [
  {
    "name": "axis",
    "children": [
      {
        "name": "Axis",
        "size": 24593
      },
      {
        "name": "Axes",
        "size": 1302
      },
      {
        "name": "AxisGridLine",
        "size": 652
      },
      {
        "name": "AxisLabel",
        "size": 636
      },
      {
        "name": "CartesianAxes",
        "size": 6703
      }
    ]
  },
  {
    "name": "controls",
    "children": [
      {
        "name": "TooltipControl",
        "size": 8435
      },
      {
        "name": "SelectionControl",
        "size": 7862
      },
      {
        "name": "PanZoomControl",
        "size": 5222
      },
      {
        "name": "HoverControl",
        "size": 4896
      },
      {
        "name": "ControlList",
        "size": 4665
      },
      {
        "name": "ClickControl",
        "size": 3824
      },
      {
        "name": "ExpandControl",
        "size": 2832
      },
      {
        "name": "DragControl",
        "size": 2649
      },
      {
        "name": "AnchorControl",
        "size": 2138
      },
      {
        "name": "Control",
        "size": 1353
      },
      {
        "name": "IControl",
        "size": 763
      }
    ]
  },
  {
    "name": "data",
    "children": [
      {
        "name": "Data",
        "size": 20544
      },
      {
        "name": "NodeSprite",
        "size": 19382
      },
      {
        "name": "DataList",
        "size": 19788
      },
      {
        "name": "DataSprite",
        "size": 10349
      },
      {
        "name": "EdgeSprite",
        "size": 3301
      },
      {
        "name": "render",
        "children": [
          {
            "name": "EdgeRenderer",
            "size": 5569
          },
          {
            "name": "ShapeRenderer",
            "size": 2247
          },
          {
            "name": "ArrowType",
            "size": 698
          },
          {
            "name": "IRenderer",
            "size": 353
          }
        ]
      },
      {
        "name": "ScaleBinding",
        "size": 11275
      },
      {
        "name": "TreeBuilder",
        "size": 9930
      },
      {
        "name": "Tree",
        "size": 7147
      }
    ]
  },
  {
    "name": "events",
    "children": [
      {
        "name": "DataEvent",
        "size": 7313
      },
      {
        "name": "SelectionEvent",
        "size": 6880
      },
      {
        "name": "TooltipEvent",
        "size": 3701
      },
      {
        "name": "VisualizationEvent",
        "size": 2117
      }
    ]
  },
  {
    "name": "legend",
    "children": [
      {
        "name": "Legend",
        "size": 20859
      },
      {
        "name": "LegendRange",
        "size": 10530
      },
      {
        "name": "LegendItem",
        "size": 4614
      }
    ]
  },
  {
    "name": "operator",
    "children": [
      {
        "name": "distortion",
        "children": [
          {
            "name": "Distortion",
            "size": 6314
          },
          {
            "name": "BifocalDistortion",
            "size": 4461
          },
          {
            "name": "FisheyeDistortion",
            "size": 3444
          }
        ]
      },
      {
        "name": "encoder",
        "children": [
          {
            "name": "PropertyEncoder",
            "size": 4138
          },
          {
            "name": "Encoder",
            "size": 4060
          },
          {
            "name": "ColorEncoder",
            "size": 3179
          },
          {
            "name": "SizeEncoder",
            "size": 1830
          },
          {
            "name": "ShapeEncoder",
            "size": 1690
          }
        ]
      },
      {
        "name": "filter",
        "children": [
          {
            "name": "FisheyeTreeFilter",
            "size": 5219
          },
          {
            "name": "VisibilityFilter",
            "size": 3509
          },
          {
            "name": "GraphDistanceFilter",
            "size": 3165
          }
        ]
      },
      {
        "name": "IOperator",
        "size": 1286
      },
      {
        "name": "label",
        "children": [
          {
            "name": "Labeler",
            "size": 9956
          },
          {
            "name": "RadialLabeler",
            "size": 3899
          },
          {
            "name": "StackedAreaLabeler",
            "size": 3202
          }
        ]
      },
      {
        "name": "layout",
        "children": [
          {
            "name": "RadialTreeLayout",
            "size": 12348
          },
          {
            "name": "NodeLinkTreeLayout",
            "size": 12870
          },
          {
            "name": "CirclePackingLayout",
            "size": 12003
          },
          {
            "name": "CircleLayout",
            "size": 9317
          },
          {
            "name": "TreeMapLayout",
            "size": 9191
          },
          {
            "name": "StackedAreaLayout",
            "size": 9121
          },
          {
            "name": "Layout",
            "size": 7881
          },
          {
            "name": "AxisLayout",
            "size": 6725
          },
          {
            "name": "IcicleTreeLayout",
            "size": 4864
          },
          {
            "name": "DendrogramLayout",
            "size": 4853
          },
          {
            "name": "ForceDirectedLayout",
            "size": 8411
          },
          {
            "name": "BundledEdgeRouter",
            "size": 3727
          },
          {
            "name": "IndentedTreeLayout",
            "size": 3174
          },
          {
            "name": "PieLayout",
            "size": 2728
          },
          {
            "name": "RandomLayout",
            "size": 870
          }
        ]
      },
      {
        "name": "OperatorList",
        "size": 5248
      },
      {
        "name": "OperatorSequence",
        "size": 4190
      },
      {
        "name": "OperatorSwitch",
        "size": 2581
      },
      {
        "name": "Operator",
        "size": 2490
      },
      {
        "name": "SortOperator",
        "size": 2023
      }
    ]
  }
]
sankey_data = {
  "nodes": [
    {
      "name": "Visit"
    },
    {
      "name": "Direct-Favourite"
    },
    {
      "name": "Page-Click"
    },
    {
      "name": "Detail-Favourite"
    },
    {
      "name": "Lost"
    }
  ],
  "links": [
    {
      "source": 0,
      "target": 1,
      "value": 3728.3
    },
    {
      "source": 0,
      "target": 2,
      "value": 354170
    },
    {
      "source": 2,
      "target": 3,
      "value": 62429
    },
    {
      "source": 2,
      "target": 4,
      "value": 291741
    }
  ]
}
composed_data = [
  {
    "name": "Page A",
    "uv": 4000,
    "pv": 2400,
    "amt": 2400
  },
  {
    "name": "Page B",
    "uv": 3000,
    "pv": 1398,
    "amt": 2210
  },
  {
    "name": "Page C",
    "uv": 2000,
    "pv": 9800,
    "amt": 2290
  },
  {
    "name": "Page D",
    "uv": 2780,
    "pv": 3908,
    "amt": 2000
  },
  {
    "name": "Page E",
    "uv": 1890,
    "pv": 4800,
    "amt": 2181
  },
  {
    "name": "Page F",
    "uv": 2390,
    "pv": 3800,
    "amt": 2500
  },
  {
    "name": "Page G",
    "uv": 3490,
    "pv": 4300,
    "amt": 2100
  }
]

page = Page(
    __name__,
    core.Container([
        core.Container([
            core.Box([
                charts.LineChart(
                    data=data,
                    width=500,
                    height=300,
                    identity='line-chart',
                    lines=[charts.Line(dataKey='y')],
                    cartesian_grid=charts.CartesianGrid(),
                    y_axis=[charts.YAxis()],
                    x_axis=[charts.XAxis(dataKey='x')],
                    tooltip=charts.Tooltip(),
                    legend=charts.Legend(),
                    margin=margin,
                ),
                charts.AreaChart(
                    data=data,
                    width=500,
                    height=300,
                    margin=margin,
                    identity='area-chart',
                    reference_areas=[charts.ReferenceArea(
                        x1=0, x2=180, y1=0, y2=10,
                        stroke='red', strokeOpacity=0.5
                    )],
                    areas=[
                        charts.Area(
                            dataKey='y', type='monotone', stroke="#8884d8",
                            fillOpacity=0.8, fill=colors[2],
                        ),
                    ],
                    y_axis=[charts.YAxis()],
                    x_axis=[charts.XAxis(dataKey='x')],
                    tooltip=charts.Tooltip(),
                    legend=charts.Legend(),
                    cartesian_grid=charts.CartesianGrid(strokeDasharray='2 3'),
                ),
                charts.BarChart(
                    data=data,
                    width=500,
                    height=300,
                    identity='bar-chart',
                    bars=[
                        charts.Bar(
                            dataKey='y', fill=colors[0],
                            label_lists=[
                                charts.LabelList(
                                    dataKey='u',
                                    width=500,
                                    height=300,
                                    fill='#000', position='top',
                                )
                            ]
                        ),
                        charts.Bar(dataKey='z', fill=colors[1])
                    ],
                    y_axis=[charts.YAxis()],
                    x_axis=[charts.XAxis(dataKey='x')],
                    tooltip=charts.Tooltip(),
                    legend=charts.Legend(),
                    handle_clicks=True,
                    handle_hover=True,
                ),
                charts.FunnelChart(
                    width=500,
                    height=300,
                    margin=margin,
                    funnels=[charts.Funnel('value', data=[
                        {
                            'value': i * 20,
                            'fill': colors[i],
                            'name': f'random{i}'
                        } for i in range(5)
                    ], label_lists=[
                        charts.LabelList(
                            dataKey='name', position='left',
                            fill='#000'
                        )])],
                    tooltip=charts.Tooltip(),
                ),
                charts.ScatterChart(
                    height=300,
                    width=500,
                    identity='scatter-chart',
                    scatters=[
                        charts.Scatter(
                            name='Series A',
                            data=data,
                            fill=colors[2],
                            identity='scatter-series'
                        ),
                    ],
                    legend=charts.Legend(),
                    tooltip=charts.Tooltip(),
                    x_axis=[
                        charts.XAxis(dataKey='x', name='length', unit='cm')],
                    y_axis=[
                        charts.YAxis(dataKey='y', name='weight', unit='kg')],
                    z_axis=[
                        charts.ZAxis(dataKey='z', name='score', unit='km')],
                    cartesian_grid=charts.CartesianGrid(strokeDasharray='1 3'),
                    reference_areas=[charts.ReferenceArea(
                        x1=200, x2=260, y1=10, y2=18,
                        stroke='red', strokeOpacity=0.5,
                        fill=colors[0], fillOpacity=0.5
                    )],
                    reference_lines=[
                        charts.ReferenceLine(
                            y=14, label='middle',
                            stroke='blue', strokeDasharray='1 1'
                        )
                    ],
                    reference_dots=[
                        charts.ReferenceDot(
                            y=9, x=200, fill='green', stroke='blue',
                        )
                    ]
                ),
                charts.PieChart(
                    width=500,
                    height=300,
                    margin=margin,
                    identity='pie',
                    legend=charts.Legend(),
                    tooltip=charts.Tooltip(),
                    pies=[
                        charts.Pie(dataKey='value', data=[
                            {'value': 200, 'name': 'foo', 'fill': colors[1]},
                            {'value': 400, 'name': 'bar', 'fill': colors[2]},
                            {'value': 140, 'name': 'help', 'fill': colors[3]}
                        ])
                    ]
                ),
                charts.RadarChart(
                    width=500,
                    height=300,
                    margin=margin,
                    outer_radius=90,
                    data=radar_data,
                    legend=charts.Legend(),
                    tooltip=charts.Tooltip(),
                    identity='radar',
                    radars=[
                        charts.Radar(
                            name='Alice', dataKey='a',
                            fill=colors[0], fillOpacity=0.6
                        ),
                        charts.Radar(
                            name='Bob', dataKey='b',
                            fill=colors[1], fillOpacity=0.6,
                        ),
                    ],
                    polar_grid=charts.PolarGrid(True),
                    polar_angle_axis=[charts.PolarAngleAxis(dataKey='type')],
                    polar_radius_axis=[
                        charts.PolarRadiusAxis(angle=30, domain=[0, 150])
                    ]
                ),
                charts.RadialBarChart(
                    width=500,
                    height=300,
                    margin=margin,
                    identity='radial',
                    data=radar_data,
                    legend=charts.Legend(),
                    tooltip=charts.Tooltip(),
                    radial_bars=[
                        charts.RadialBar(
                            dataKey='a', background=True,
                        )
                    ]
                ),
                charts.Treemap(
                    width=500,
                    height=300,
                    margin=margin,
                    data=treemap_data,
                    dataKey='size',
                    aspectRatio=4 / 3,
                ),
                charts.SankeyChart(
                    width=500,
                    height=300,
                    margin=margin,
                    identity='sankey',
                    nodePadding=50,
                    link={'stroke': colors[0]},
                    data=sankey_data,
                    nameKey='name',
                    tooltip=charts.Tooltip(),
                ),
                charts.ComposedChart(
                    width=500,
                    height=300,
                    margin=margin,
                    data=composed_data,
                    identity='composed',
                    x_axis=[charts.XAxis(dataKey='name')],
                    y_axis=[charts.YAxis()],
                    tooltip=charts.Tooltip(),
                    legend=charts.Legend(),
                    cartesian_grid=charts.CartesianGrid(stroke='#f5f5f5'),
                    areas=[charts.Area(type='monotone', dataKey='amt', fill=colors[0], stroke=colors[0])],
                    bars=[charts.Bar(dataKey='pv', barSize=20, fill=colors[2])],
                    lines=[
                        charts.Line(
                            type='monotone',
                            dataKey='uv',
                            stroke=colors[4]
                        )
                    ]
                ),
            ], justify='center', wrap='wrap'),
            core.Container([
               core.Box([
                   core.Button('prepend data', identity='prepend-data'),
                   core.Button('append data', identity='append-data'),
                   core.Button('concat data', identity='concat-data'),
                   core.Button('delete data', identity='delete-data'),
                   core.Button('insert data', identity='insert-data'),
                   core.Button('sort data', identity='sort-data'),
                   core.Button('change scatter fill', identity='change-scatter-fill'),
               ]),
            ]),
            core.Container([
                core.Container(identity='hovered-output'),
                core.Container(identity='hover-event-output'),
                core.Container(identity='clicks-output'),
                core.Container(identity='click-event-output'),
            ])
        ]),
    ]),
)

page.tie('clicks@bar-chart', 'children@clicks-output')
page.tie('hovered@bar-chart', 'children@hovered-output').t(t.ToJson())
page.tie('click_event@bar-chart', 'children@click-event-output').t(t.ToJson())
page.tie('hover_event@bar-chart', 'children@hover-event-output').t(t.ToJson())

@page.bind('clicks@prepend-data')
async def on_click_prepend(ctx: BindingContext):
    await ctx.set_aspect('line-chart', prepend_data={
        "y": 100,
        'z': 120,
        'x': 110,
        'name': f'prepended',
        'u': f'under110'
    })

@page.bind('clicks@append-data')
async def on_click_prepend(ctx: BindingContext):
    await ctx.set_aspect('line-chart', append_data={
        "y": 100,
        'z': 120,
        'x': 110,
        'name': f'appended',
        'u': f'under111'
    })

@page.bind('clicks@insert-data')
async def on_click_prepend(ctx: BindingContext):
    await ctx.set_aspect('line-chart', insert_data={
        'value': {
            "y": 100,
            'z': 120,
            'x': 110,
            'name': f'named112',
            'u': f'under112'
        },
        'index': 1
    })

@page.bind('clicks@delete-data')
async def on_click_delete_data(ctx: BindingContext):
    await ctx.set_aspect('line-chart', delete_data={
        'key': 'name', 'value': 'named1'
    })

@page.bind('clicks@concat-data')
async def on_click_prepend(ctx: BindingContext):
    await ctx.set_aspect('line-chart', concat_data=[{
        "y": 80,

        'z': 100,
        'x': 60,
        'name': f'concat',
        'u': f'undercat'
    }])

@page.bind('clicks@sort-data')
async def on_click_sort(ctx: BindingContext):
    await ctx.set_aspect('line-chart', sort_data={'key': 'x'})

@page.bind('clicks@change-scatter-fill')
async def on_click_change_fill(ctx: BindingContext):
    await ctx.set_aspect('scatter-series', fill=colors[0])


import random

class Pokemon(object):

    def __init__(self):
        self.name = None
        self.first_evolv = None
        self.second_evolv = None
        self.pokedex = None
        self.maxlebenspunkte = 60
        self.lebenspunkte = self.maxlebenspunkte
        self.trainer = None
        self.level = 1
        self.angriffswert = 1
        self.maxerfahrung = 3
        self.erfahrung = 0

    def __del__(self):
        print(f"Du hast {self.name} gelöscht.")

    def attack(self,attackname,Pokemon,hitPos,angriffswert):
        if Pokemon==self:
            print (f"{self.name} kann sich nicht selbst angreifen.")
        elif Pokemon.lebenspunkte <= 0:
            print(f"Du kannst nicht angreifen. {Pokemon.name} wurde schon besiegt.")
        elif self.lebenspunkte <= 0:
            print(f"Du kannst nicht angreifen. Dein Pokemon {self.name} wurde besiegt.")
        else:
            if self.hitPos(hitPos) == True:
                print(f"{self.name} attakiert {Pokemon.name} mit {attackname} und verursacht {int(self.angriffswert*angriffswert)} Schaden:")
                Pokemon.lebenspunkte = Pokemon.lebenspunkte - int(self.angriffswert*angriffswert)
                if Pokemon.lebenspunkte > 0:
                    print(f"{Pokemon.name} hat noch {Pokemon.lebenspunkte} Lebenspunkte.")
                else:
                    Pokemon.lebenspunkte = 0
                    print(f"{Pokemon.name} wurde besiegt.")
                    self.erfahrung+=1
                    print(f"{self.name} erhält einen Erfahrungspunkt.")
                    if self.erfahrung==self.maxerfahrung:
                        self.lvlUp()
                        self.erfahrung = 0
            else:
                print(f"{self.name} hat {Pokemon.name} verfehlt.")

    def schrei(self,Pokemon):
        if Pokemon==self:
            print (f"{self.name} kann sich nicht selbst angreifen.")
        elif Pokemon.lebenspunkte <= 0:
            print(f"Du kannst nicht angreifen. {Pokemon.name} wurde schon besiegt.")
        elif self.lebenspunkte <= 0:
            print(f"Du kannst nicht angreifen. Dein Pokemon {self.name} wurde besiegt.")
        else:
            if self.hitPos(95) == True:
                print(f"{self.name} verwendet Schrei und steigert seinen Angrifsswert um 5.")
                self.angriffswert = self.angriffswert + 5
            else:
                print(f"{self.name} hat mit Schrei verfehlt.")

    def changeTrainer(self, trainer):
        self.trainer = trainer

    def lvlUp(self):
        if self.level < 100:
            self.level += 1
            self.lebenspunkte = int(self.lebenspunkte+1.03**self.level)
            print(f"{self.name} erreicht Level: {self.level}")
            if self.level == 20 and self.first_evolv != None:
                print(f"Hey! {self.name} entwickelt sich zu: ")
                self.name = self.first_evolv
                print(self.name)
            elif self.level == 40 and self.first_evolv != None:
                print(f"Hey! {self.name} entwickelt sich zu: ")
                self.name = self.second_evolv
                print(self.name)
        else:
            print(f"{self.name} hat bereits die höchste Levelstufe: {self.level} erreicht.")

    def showStats(self):
        print(
            f"Name: {self.name}\nLevel: {self.level}\nPokedex-Nr: {self.pokedex}\nLebenspunkte: {self.lebenspunkte}\nErfahrungspunkte: {self.erfahrung}\nTrainer: {self.trainer}")

    def hitPos(self, possibility):
        pos = random.randrange(0, 100, 1)
        if pos <= possibility:
            return True
        return False


import geopandas as gpd

if __name__ == "__main__":
    DRIVE_FILE_ID = "1kdqgi94qhdEVvOJAvlpHvurYcurh_5d9"
    url = f"https://drive.google.com/uc?export=download&id={DRIVE_FILE_ID}"

    df_kgiop_objects = gpd.read_file(url)
    print(df_kgiop_objects.head())

    DRIVE_FILE_ID = "107DtdB8wUehAFoASn-rtQ1jokVam04FN"
    url = f"https://drive.google.com/uc?export=download&id={DRIVE_FILE_ID}"

    df_roads = gpd.read_file(url)
    df_roads = df_roads.set_index("id")
    print(df_roads.head())

    K_MEAN_POINTS = 5
    mean_distance = df_roads.geometry.apply(
        lambda road: df_kgiop_objects.distance(road).nsmallest(K_MEAN_POINTS).mean())

    mean_distance.to_json("k_mean_points_distance.json")


import discord
from discord.ext import commands
import asyncio
import os
import subprocess
import ffmpeg
from voice_generator import creat_WAV

client = commands.Bot(command_prefix='.')
voice_client = None

@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')

@client.command()
async def join(ctx):
    print('#join')
    print('#voicechannelを取得')
    vc = ctx.author.voice.channel
    print('#voicechannelに接続')
    await vc.connect()

@client.command()
async def bye(ctx):
    print('#bye')
    print('#切断')
    await ctx.voice_client.disconnect()

@client.command()
async def register(ctx, arg1, arg2):
    with open('C:/open_jtalk/bin/dic.txt', mode='a') as f:
        f.write('\n'+ arg1 + ',' + arg2)
        print('dic.txtに書き込み：''\n'+ arg1 + ',' + arg2)
    await ctx.send('`' + arg1+'` を `'+arg2+'` として登録しました')

@client.event
async def on_voice_state_update(member, before, after):
    server_id_test = "サーバーID"
    text_id_test = "通知させたいテキストチャンネルID"

    if member.guild.id == server_id_test:   # サーバーid
        text_ch = client.get_channel(text_id_test)   # 通知させたいTEXTチャンネルid
        if before.channel is None:
            msg = f'【VC参加ログ】{member.name} が {after.channel.name} に参加しました。'
            await text_ch.send(msg)

@client.event
async def on_message(message):
    print('---on_message_start---')
    msgclient = message.guild.voice_client
    print(msgclient)
    if message.content.startswith('.'):
        pass

    else:
        if message.guild.voice_client:
            print('#message.content:'+ message.content)
            creat_WAV(message.content)
            source = discord.FFmpegPCMAudio("output.wav")
            message.guild.voice_client.play(source)
        else:
            pass
    await client.process_commands(message)
    print('---on_message_end---')

client.run("トークン")