import os.path as osp

import torch
import torch.nn as nn
from torch.nn import functional as F

from dassl.engine import TRAINER_REGISTRY, TrainerX
from dassl.metrics import compute_accuracy
from dassl.utils import load_pretrained_weights, load_checkpoint
from dassl.optim import build_optimizer, build_lr_scheduler

from clip import clip
from clip.simple_tokenizer import SimpleTokenizer as _Tokenizer

_tokenizer = _Tokenizer()

CUSTOM_TEMPLATES = {
    'OxfordPets': 'a photo of a {}, a type of pet.',
    'OxfordFlowers': 'a photo of a {}, a type of flower.',
    'FGVCAircraft': 'a photo of a {}, a type of aircraft.',
    'DescribableTextures': '{} texture.',
    'EuroSAT': 'a centered satellite photo of {}.',
    'StanfordCars': 'a photo of a {}.',
    'Food101': 'a photo of {}, a type of food.',
    'SUN397': 'a photo of a {}.',
    'Caltech101': 'a photo of a {}.',
    'UCF101': 'a photo of a person doing {}.',
    'ImageNet': 'a photo of a {}.',
    'ImageNetSketch': 'a photo of a {}.',
    'ImageNetV2': 'a photo of a {}.',
    'ImageNetA': 'a photo of a {}.',
    'ImageNetR': 'a photo of a {}.'
}

def load_clip_to_cpu(cfg):
    backbone_name = cfg.MODEL.BACKBONE.NAME
    url = clip._MODELS[backbone_name]
    model_path = clip._download(url)

    try:
        # loading JIT archive
        model = torch.jit.load(model_path, map_location='cpu').eval()
        state_dict = None

    except RuntimeError:
        state_dict = torch.load(model_path, map_location='cpu')

    model = clip.build_model(state_dict or model.state_dict())

    return model

class Adapter(nn.Module):
    def __init__(self, c_in, reduction=4):
        super(Adapter, self).__init__()
        self.fc = nn.Sequential(
            nn.Linear(c_in, c_in // reduction, bias=False),
            nn.ReLU(inplace=True),
            nn.Linear(c_in // reduction, c_in, bias=False),
            nn.ReLU(inplace=True)
        )

    def forward(self, x):
        x = self.fc(x)
        return x

class TextEncoder(nn.Module):

    def __init__(self, cfg, classnames, clip_model):
        super().__init__()
        self.cfg = cfg
        self.classnames = classnames
        self.clip_model = clip_model
        self.dtype = clip_model.dtype

    def forward(self):
        temp = CUSTOM_TEMPLATES[self.cfg.DATASET.NAME]
        prompts = [temp.format(c.replace('_', ' ')) for c in self.classnames]
        prompts = torch.cat([clip.tokenize(p) for p in prompts])
        prompts = prompts.to('cuda')
        text_features = self.clip_model.encode_text(prompts)
        x = text_features
        return x

class CustomCLIP(nn.Module):

    def __init__(self, cfg, classnames, clip_model):
        super().__init__()
        self.image_encoder = clip_model.visual
        self.text_encoder = TextEncoder(cfg, classnames, clip_model)
        self.logit_scale = clip_model.logit_scale
        self.dtype = clip_model.dtype
        self.adapter = Adapter(1024, 4).to(clip_model.dtype)

    def forward(self, image):
        image_features = self.image_encoder(image.type(self.dtype))
        x = self.adapter(image_features)

        ratio = 0.2
        image_features = ratio * x + (1 - ratio) * image_features

        text_features = self.text_encoder()

        image_features = image_features / image_features.norm(dim=-1, keepdim=True)
        text_features = text_features / text_features.norm(dim=-1, keepdim=True)

        logit_scale = self.logit_scale.exp()
        logits = logit_scale * image_features @ text_features.t()

        return logits

@TRAINER_REGISTRY.register()
class CLIP_Adapter(TrainerX):
    """ CLIP-Adapter """

    def build_model(self):
        cfg = self.cfg
        classnames = self.dm.dataset.classnames

        print(f'Loading CLIP (backbone: {cfg.MODEL.BACKBONE.NAME})')
        clip_model = load_clip_to_cpu(cfg)
        clip_model.float()

        print('Building custom CLIP')
        self.model = CustomCLIP(cfg, classnames, clip_model)

        print('Turning off gradients in both the image and the text encoder')
        for name, param in self.model.named_parameters():
            if 'adapter' not in name:
                param.requires_grad_(False)

        if cfg.MODEL.INIT_WEIGHTS:
            load_pretrained_weights(self.model.adapter, cfg.MODEL.INIT_WEIGHTS)

        self.model.to(self.device)
        # NOTE: only give text_encoder.adapter to the optimizer
        self.optim = build_optimizer(self.model.adapter, cfg.OPTIM)
        self.sched = build_lr_scheduler(self.optim, cfg.OPTIM)

        self.register_model('clip_adapter', self.model.adapter, self.optim, self.sched)

        device_count = torch.cuda.device_count()
        if device_count > 1:
            print(f'Multiple GPUs detected (n_gpus={device_count}), use all of them!')
            self.model = nn.DataParallel(self.model)

    def forward_backward(self, batch):
        image, label = self.parse_batch_train(batch)
        output = self.model(image)
        loss = F.cross_entropy(output, label)
        self.model_backward_and_update(loss)

        loss_summary = {
            'loss': loss.item(),
            'acc': compute_accuracy(output, label)[0].item()
        }

        if (self.batch_idx + 1) == self.num_batches:
            self.update_lr()

        return loss_summary

    def parse_batch_train(self, batch):
        input = batch['img']
        label = batch['label']
        input = input.to(self.device)
        label = label.to(self.device)
        return input, label

    def load_model(self, directory, epoch=None):
        if not directory:
            print(
                'Note that load_model() is skipped as no pretrained model is given'
            )
            return

        names = self.get_model_names()

        # By default, the best model is loaded
        model_file = 'model-best.pth.tar'

        if epoch is not None:
            model_file = 'model.pth.tar-' + str(epoch)

        for name in names:
            model_path = osp.join(directory, name, model_file)

            if not osp.exists(model_path):
                raise FileNotFoundError(
                    'Model not found at "{}"'.format(model_path)
                )

            checkpoint = load_checkpoint(model_path)
            state_dict = checkpoint['state_dict']
            epoch = checkpoint['epoch']

            # Ignore fixed token vectors
            if 'token_prefix' in state_dict:
                del state_dict['token_prefix']

            if 'token_suffix' in state_dict:
                del state_dict['token_suffix']

            print(
                'Loading weights to {} '
                'from "{}" (epoch = {})'.format(name, model_path, epoch)
            )
            # set strict=False
            self._models[name].load_state_dict(state_dict, strict=False)


def add_node(vertex):
    if vertex in graph:
        print(vertex," vertex is already present")
    else:
        graph[vertex]=[]
# def add_edge(v1,v2):
#     if v1 not in graph:
#         print(v1," vertex not found")
#     elif v2 not in graph:
#         print(v2," vertex v2 not found")
#     else:
#         graph[v1].append(v2)
#         graph[v2].append(v1)

def add_edge(v1,v2,cost):
    if v1 not in graph:
        print(v1," vertex not found")
    elif v2 not in graph:
        print(v2," vertex v2 not found")
    else:
        list1=[v2,cost]
        list2=[v1,cost]
        graph[v1].append(list1)
        graph[v2].append(list2)
def delete_node(v):
    if v not in graph:
        print(v," vertex not found in graph")
    else:
        graph.pop(v)
        for i in graph.keys():
            list1=graph[i]
            # print(list1)
            for j in list1:
                if v in j:
                    j.clear()
def delete_edge(v1,v2,cost):
    if v1 not in graph:
        print(v1," vertex not found in graph")
    elif v2 not in graph:
        print(v2," vertex not found in graph")
    else:
        temp=[v1,cost]
        temp1=[v2,cost]
        if temp1 in graph[v1]:
            graph[v1].remove(temp1)
            graph[v2].remove(temp)
graph={}
add_node("A")
add_node("B")
add_node("C")
add_node("D")
add_node("E")
add_node("F")
add_node("G")
add_edge("A","B",10)
add_edge("B","E",14)
add_edge("A","C",5)
add_edge("A","D",19)
add_edge("B","D",13)
add_edge("C","D",1)
add_edge("E","D",2)
print(graph)
print("after deletion")
delete_edge("C","D",1)
print(graph)
# delete_node("C")
# print("after deletion")
# print(graph)


import requests
import time
import json
import datetime
from pprint import pprint
from datetime import datetime
from tqdm import tqdm

def get_biggest_photos():
    '''Функция получения отсортированного по размеру списка с фото'''
    with open('tokenvk.txt', 'r') as f, open('vk_id.txt', 'r') as v:
        access_token = f.read().strip()
        user_id = v.read().strip()
    URL = 'https://api.vk.com/method/photos.get'
    params = {
        'user_ids': user_id,
        'access_token': access_token,
        'v': '5.131',
        'owner_id': '739837048',
        'album_id': '291838858',
        'extended': '1',
        'photo_sizes': '1',
        'count': '5'
    }
    res = requests.get(URL, params=params)
    dic = res.json()['response']['items']
    selected_photos = []
    for photos_info in dic:
        photos_dic = {}
        photos_dic.update(dict(id=photos_info['id'], likes=photos_info['likes']['count'], sizes=photos_info['sizes'],
                               date=photos_info['date']))
        sorted_size = sorted(photos_dic['sizes'], key=lambda x: x['height'])
        del photos_dic['sizes']
        photos_dic.setdefault('url', sorted_size[-1]['url'])
        photos_dic.setdefault('size', sorted_size[-1]['type'])
        selected_photos.append(photos_dic)
    return selected_photos

def date_name_converse():
    '''Функция перевода даты в читабельный формат, присвоения имени фотографии, записи json файла. Поскольку все фото
    были загружены единовременно для целей данной курсовой, а лайков почти нет, добавил последние 2 цифры id фотографии
    к имени'''
    selected_photos = get_biggest_photos()
    json_list = []
    for unix_dates in selected_photos:
        unix_date = int(unix_dates['date'])
        norm_date = str(datetime.fromtimestamp(unix_date))
        unix_dates['date'] = norm_date
    names_list = []
    for name in selected_photos:
        name['file_name'] = str(name['likes']) + '.jpeg'
        names_list.append(name['file_name'])
        if names_list.count(name['file_name']) > 1:
            name['file_name'] = str(name['likes']) + '_' + name['date'][0:10] + '_' + str(name['id'])[-2:] + '.jpeg'
        json_list.append({'file_name': name['file_name'], 'size': name['size']})
    with open('VK_photo.txt', 'w') as outfile:
        json.dump(json_list, outfile)
    return selected_photos

def folder_create (folder_name):
    '''Функция создания папки на ЯД для загрузки фото'''
    with open('tokenyandex.txt', 'r') as f:
        tokenyandex = f.read().strip()
        fold_url = 'https://cloud-api.yandex.net/v1/disk/resources'
        params = {'path': folder_name, "overwrite": "true"}
        headers = {'Content-Type': 'application/json', 'Authorization': tokenyandex}
        folder = requests.put(url=fold_url, headers=headers, params=params)
        if folder.status_code == 201:
            print(f'Папка {folder_name}успешно создана')
        elif folder.status_code == 409:
            print(f'Папка с именем {folder_name} уже существует')
        return folder_name

def photos_upload():
    '''Функция загрузки фотографий на ЯД'''
    selected_photos = date_name_converse()
    folder_name = folder_create('vk_pictures')
    with open('tokenyandex.txt', 'r') as f:
        tokenyandex = f.read().strip()
    headers = {'Content-Type': 'application/json', 'Authorization': tokenyandex}
    upload_url = 'https://cloud-api.yandex.net/v1/disk/resources/upload'
    for photo in tqdm(selected_photos, desc='Photos loading progress', colour='green', leave=False):
        par = {'path': folder_name+'/'+photo['file_name'], 'url': photo['url'], 'overwrite': 'true'}
        result = requests.post(url=upload_url, headers=headers, params=par)
        result.raise_for_status()
    if result.status_code == 202:
        print('Загрузка проведена успешно')
    else:
        print(f'Ошибка при выполнении загрузки {result.status_code}')
photos_upload()


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

T = int(input())

for test_case in range(T):
    map_info = []
    for i in range(4):
        temp_list = list(map(int, input().split()))
        map_info.append(temp_list)
    Table = [[] for i in range(6)]
    s = set()
    for i in range(7):
        if i == 0:
            for j in range(4):
                for k in range(4):
                    Table[i].append([map_info[j][k], j, k])
        elif i == 6:
            for j in Table[i-1]:
                for k in range(4):
                    if j[1] + dx[k] < 0 or j[1] + dx[k] > 3 or j[2] + dy[k] < 0 or j[2] + dy[k] > 3:
                        continue
                    s.add(j[0]*10+map_info[j[1]+dx[k]][j[2]+dy[k]])
        else:
            for j in Table[i-1]:
                for k in range(4):
                    if j[1] + dx[k] < 0 or j[1] + dx[k] > 3 or j[2] + dy[k] < 0 or j[2] + dy[k] > 3:
                        continue
                    Table[i].append([j[0]*10+map_info[j[1]+dx[k]][j[2]+dy[k]], j[1]+dx[k], j[2]+dy[k]])

    print("#{0} {1}".format(test_case+1, len(s)))


from mrjob.job import MRJob

class MyMapReduceJob(MRJob):

	def mapper(self, _, line):
		table_artname = line.split("\t")
		artname = table_artname[3]
		yield artname, 1

	def reducer(self, key, values):
		yield key, sum(values)

if __name__ == '__main__':
	MyMapReduceJob.run()


import numpy as np
from scipy import optimize
import random

_floatX = np.float32
_intX = np.int8

class EMDiverseDensity(object):
    """
        bags is a list of bag
        each bag is a dict required following <key, value>
        key: inst_prob, value: a vector indicating each instance's probability
        key: label, value: a scalar indicating this bag's label
        key: prob, value: a scalar indicating this bag's probability
        key: instances, value: a numpy array indicating instances in this bag, each row is a instance, each column is a
        feature
        this version select given number of positive bags and take all positive instances insider these positive bags as
        starting points, in predict process, from all learned concepts, using training data to select the concept
         minimise classify error, then use this selected concept to predict test data.
    """

    def __init__(self):
        pass

    def diverse_density_nll(self, params, instances, labels):
        [n_instances, n_dim] = instances.shape
        if params.shape[0] == n_dim:
            target = params
            scale = np.ones(n_dim, )
        else:
            target = params[0:n_dim]
            scale = params[n_dim:]

        nll_cost = 0

        dist = np.mean(((instances - target) ** 2) * (scale ** 2), axis=1)
        inst_prob = np.exp(-dist)
        for inst_idx in range(n_instances):
            if labels[inst_idx] == 1:
                if inst_prob[inst_idx] == 0:
                    inst_prob[inst_idx] = 1e-10
                nll_cost += -np.log(inst_prob[inst_idx])
            else:
                if inst_prob[inst_idx] == 1:
                    inst_prob[inst_idx] = 1 - 1e-10
                nll_cost += -np.log(1 - inst_prob[inst_idx])
        return nll_cost

    def em(self, bags, scale_indicator, init_target, init_scale, tol=1e-5):
        target = init_target
        scale = init_scale

        # select an optimal instance from each bag according to current target and scale
        diff = np.inf
        prev_nll_cost = np.inf
        nll_cost = 0

        init_nll_cost = 0
        init_nll_cost_indicator = 1

        em_loop_count = 0
        while diff > tol:

            em_loop_count += 1
            if em_loop_count > 1000:
                raise NotImplementedError('em loop error, loop number is %d larger than 1000.' % em_loop_count)

            selected_instances = list()
            selected_labels = list()
            # select an instance with highest probability from each bag
            for bag in bags:
                instances = np.asarray(bag['instances'])
                [_, n_dim] = instances.shape
                dist = np.mean(((instances - target) ** 2) * (scale ** 2), axis=1)
                bag['inst_prob'] = np.exp(-dist)
                max_idx = np.argmax(bag['inst_prob'])
                selected_instances.append(instances[max_idx, :])
                selected_labels.append(bag['label'])

            selected_instances = np.asarray(selected_instances)

            if scale_indicator == 1:
                init_params = np.hstack((target, scale))
                if init_nll_cost_indicator == 1:
                    init_nll_cost = self.diverse_density_nll(init_params, selected_instances, selected_labels)
                    init_nll_cost_indicator = 0
                optimized_params = optimize.minimize(self.diverse_density_nll, init_params,
                                                     args=(selected_instances, selected_labels,), method='L-BFGS-B')
                target = optimized_params.x[0:n_dim]
                scale = optimized_params.x[n_dim:]
            else:
                init_params = target
                if init_nll_cost_indicator == 1:
                    init_nll_cost = self.diverse_density_nll(init_params, selected_instances, selected_labels)
                    init_nll_cost_indicator = 0
                optimized_params = optimize.minimize(self.diverse_density_nll, init_params,
                                                     args=(selected_instances, selected_labels,), method='L-BFGS-B')
                target = optimized_params.x
                scale = np.ones(n_dim, )

            nll_cost = optimized_params.fun
            diff = prev_nll_cost - nll_cost
            prev_nll_cost = nll_cost

        print('em phase completed, loop number is %d. ' % em_loop_count, end='')

        return target, scale, nll_cost, init_nll_cost

    def train(self, bags, scale_indicator, epochs, threshold):
        n_bag = len(bags)
        n_pos_bag = 0

        n_pos_instances = 0
        for bag in bags:
            if bag['label'] == 1:
                n_pos_bag += 1
                n_pos_instances += bag['instances'].shape[0]

        epochs = min(n_pos_instances, epochs)
        print('training, total epochs number is %d, #positive bags is %d, #positive instances is %d'
              % (epochs, n_pos_bag, n_pos_instances))

        targets = list()
        scales = list()
        nll_costs = list()

        selected_instances = list()

        for epoch_idx in range(epochs):
            # randomly select a positive bag
            bag_idx = random.randint(0, n_bag - 1)
            while bags[bag_idx]['selected'] == 1:
                bag_idx = random.randint(0, n_bag - 1)
            bags[bag_idx]['selected'] = 1
            selected_instances.extend(bags[bag_idx]['instances'])

        selected_instances = np.asarray(selected_instances, dtype=_floatX)

        [n_instances, n_dim] = selected_instances.shape

        print('total selected instances number is %d.' % n_instances)

        for instance_idx in range(n_instances):
            # scale is initialized to one
            print('instance index %d, ' % instance_idx, end='')
            [target, scale, nll_cost, init_nll_cost] = self.em(bags,
                                                               scale_indicator,
                                                               selected_instances[instance_idx, :],
                                                               np.ones(n_dim, ))
            print('nll before optimization is %f, nll after optimization is %f' % (init_nll_cost, nll_cost))

            targets.append(target)
            scales.append(scale)
            nll_costs.append(nll_cost)

        targets = np.asarray(targets)
        scales = np.asarray(scales)

        [n_targets, _] = targets.shape
        n_acc = -np.inf
        best_idx = -1
        for target_idx in range(n_targets):
            target = targets[target_idx, :]
            scale = scales[target_idx, :]
            current_acc = 0
            for bag_idx in range(n_bag):
                instances = np.asarray(bags[bag_idx]['instances'])
                dist = np.mean(((instances - target) ** 2) * (scale ** 2), axis=1)
                inst_prob = np.exp(-dist)
                inst_label = np.int8(inst_prob > threshold)
                bag_label = np.any(inst_label)
                if bag_label == bags[bag_idx]['label']:
                    current_acc += 1

            if current_acc > n_acc:
                best_idx = target_idx
                n_acc = current_acc

        target = targets[best_idx, :]
        scale = scales[best_idx, :]

        return target, scale

    def predict(self, target, scale, bags, threshold):

        n_bag = len(bags)

        bags_label = np.zeros(n_bag, )
        bags_prob = np.zeros(n_bag, )
        instances_prob = list()
        instances_label = list()

        for bag_idx in range(n_bag):
            instances = np.asarray(bags[bag_idx]['instances'])
            dist = np.mean(((instances - target) ** 2) * (scale ** 2), axis=1)
            inst_prob = np.exp(-dist)
            inst_label = np.int8(inst_prob > threshold)
            bags_prob[bag_idx] = np.max(inst_prob)
            bags_label[bag_idx] = np.any(inst_label)
            instances_prob.append(inst_prob)
            instances_label.append(inst_label)

        return bags_label, bags_prob, instances_label, instances_prob


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

def conv(matrix,kernel):
    row = matrix.shape[0]
    col = matrix.shape[1]

    r = 2
    c = 2
    new_img = np.zeros((row - r,col - c),dtype=np.uint8)
    for i in range(row - r):
        for j in range(col - c):
            temp = np.sum(np.multiply(matrix[i:3+i,j:3+j],kernel))
            if temp > 255:
                new_img[i][j] = 255
            elif temp < 0:
                new_img[i][j] = 0
            else:
                new_img[i][j] = temp
    return new_img

def main():
    img_path = 'animation.jpg'
    rgb = plt.imread(img_path)

    grayscale = cv2.cvtColor(rgb,cv2.COLOR_RGB2GRAY)
    kernel = np.array([
        [-1,-1,-1],
        [-1,8,-1],
        [-1,-1,-1]
    ])
    val1 = conv(grayscale,kernel)
    val2 = cv2.filter2D(grayscale,-1,kernel)

    plt.subplot(1,1,1)
    plt.title('Built In Function')
    plt.imshow(val1,cmap='gray')

    plt.savefig('Built In Neighbourhood.jpg')
    plt.show()

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
"""
Created on Tue Jan 22 17:14:17 2019

@author: baccarini_a
"""
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.gridspec as gridspec
import seaborn as sns
import numpy as np

def newfigure(num=None,x=-1800,y=50,w=1200,h=1100):
       hfig = plt.figure(num)
       plt.get_current_fig_manager().window.setGeometry(x,y,w,h)
       return hfig

def ConvertIgorTime(Igortime):
    #this function convert igor timestamp into normal dates
    Pytime=pd.to_datetime(Igortime, unit='s',origin=pd.Timestamp('1904-01-01'))
    return Pytime

def ConvertMatlabTime(matlabtime):
    #this function convert matlab timestamp into normal dates
    #719529 is the number of days from matlab epoch to Unix epoch
    Pytime=pd.to_datetime(matlabtime-719529,unit='d')#.round('s')
    return Pytime

class SeabornFig2Grid():

    def __init__(self, seaborngrid, fig,  subplot_spec):
        self.fig = fig
        self.sg = seaborngrid
        self.subplot = subplot_spec
        if isinstance(self.sg, sns.axisgrid.FacetGrid) or \
            isinstance(self.sg, sns.axisgrid.PairGrid):
            self._movegrid()
        elif isinstance(self.sg, sns.axisgrid.JointGrid):
            self._movejointgrid()
        self._finalize()

    def _movegrid(self):
        """ Move PairGrid or Facetgrid """
        self._resize()
        n = self.sg.axes.shape[0]
        m = self.sg.axes.shape[1]
        self.subgrid = gridspec.GridSpecFromSubplotSpec(n,m, subplot_spec=self.subplot)
        for i in range(n):
            for j in range(m):
                self._moveaxes(self.sg.axes[i,j], self.subgrid[i,j])

    def _movejointgrid(self):
        """ Move Jointgrid """
        h= self.sg.ax_joint.get_position().height
        h2= self.sg.ax_marg_x.get_position().height
        r = int(np.round(h/h2))
        self._resize()
        self.subgrid = gridspec.GridSpecFromSubplotSpec(r+1,r+1, subplot_spec=self.subplot)

        self._moveaxes(self.sg.ax_joint, self.subgrid[1:, :-1])
        self._moveaxes(self.sg.ax_marg_x, self.subgrid[0, :-1])
        self._moveaxes(self.sg.ax_marg_y, self.subgrid[1:, -1])

    def _moveaxes(self, ax, gs):
        #https://stackoverflow.com/a/46906599/4124317
        ax.remove()
        ax.figure=self.fig
        self.fig.axes.append(ax)
        self.fig.add_axes(ax)
        ax._subplotspec = gs
        ax.set_position(gs.get_position(self.fig))
        ax.set_subplotspec(gs)

    def _finalize(self):
        plt.close(self.sg.fig)
        self.fig.canvas.mpl_connect("resize_event", self._resize)
        self.fig.canvas.draw()

    def _resize(self, evt=None):
        self.sg.fig.set_size_inches(self.fig.get_size_inches())

#%% Signal processing
def Hampel_filter(vals_orig, k=7, t0=3):
    '''
    vals: pandas series of values from which to remove outliers
    k: size of window (including the sample; 7 is equal to 3 on either side of value)
    '''
    #Dropnan otherwise median is set to nan
    vals = vals_orig.dropna().copy()

    #Hampel Filter
    L = 1.4826

    rolling_median = vals.rolling(window=k, center=True).median()
    MAD = lambda x: np.median(np.abs(x - np.median(x)))
    rolling_MAD = vals.rolling(window=k, center=True).apply(MAD)
    threshold = t0 * L * rolling_MAD
    difference = np.abs(vals - rolling_median)

    if np.any(threshold==0):
        print('Threshold is zero, check data')

    outlier_idx = difference > threshold
    vals[outlier_idx] = np.nan

    #Refill the series with the originally removed nans
    vals=vals.reindex(vals_orig.index,method='asfreq')
    return(vals)

#%% Numpy based functions
def find_nearest(array, value):
    array = np.asarray(array)
    idx = (np.abs(array - value)).argmin()
    return array[idx]

def find_nearest_idx(array, value):
    array = np.asarray(array)
    idx = (np.abs(array - value)).argmin()
    return idx

#%%Fitting
# =============================================================================
# Linear regression without intercept
# =============================================================================
def LR_nointerc(x,y):
    '''Calculate the slope, I should add R2
    input should be arrays'''
    slope=np.sum(x*y)/np.sum(x**2)
    return(slope)

# =============================================================================
# Linear regression keeping into account errors, from M. Loreti 2006
# Functions are not carefully checked
# =============================================================================
def LinFit(x,y,sigma):
    N = len(x)
    Delta = N*np.sum(x**2)-np.sum(x)**2
    a = 1/Delta*(np.sum(x**2)*np.sum(y) - np.sum(x)*np.sum(x*y))
    b = 1/Delta*(N*np.sum(x*y) - np.sum(x)*np.sum(y))
    sig_a = sigma*np.sqrt(np.sum(x**2)/Delta)
    sig_b = sigma*np.sqrt(N/Delta)
    return(a,b,sig_a,sig_b)

def LinFitWeight(x,y,sigma):
    Delta = np.sum(1/sigma**2)*np.sum(x**2/sigma**2)-np.sum(x/sigma**2)**2
    a = 1/Delta*(np.sum(x**2/sigma**2)*np.sum(y/sigma**2) -\
                 np.sum(x/sigma**2)*np.sum(x*y/sigma**2))
    b = 1/Delta*(np.sum(1/sigma**2)*np.sum(x*y/sigma**2) -\
                 np.sum(x/sigma**2)*np.sum(y/sigma**2))
    sig_a = np.sum(x**2/sigma**2)/Delta
    sig_b = np.sum(1/sigma**2)/Delta
    return(a,b,sig_a,sig_b)

#%% Cartopy functions
def add_map_background(axis, debug = False, name = "natural-earth-1", resolution = "medium0512px", extent = None):
    import json
    import os
    '''
    Function adapted from https://github.com/Guymer/PyGuymer3 to modify the default background picture in cartopy
    it requires the correct system variable containing all the PNG files and .Json file

    '''
    os.environ['CARTOPY_USER_BACKGROUNDS'] = 'C:\\Anaconda2\\envs\\spyder-beta\\Lib\\site-packages\\cartopy\\data\\raster\\new_bkg\\'

    # Initialize trigger ...
    default = True

    # Check if the environment variable has been defined ...
    if "CARTOPY_USER_BACKGROUNDS" in os.environ:
        # Determine JSON path and check it exists ...
        jpath = os.path.join(os.environ["CARTOPY_USER_BACKGROUNDS"], "images.json")
        if os.path.exists(jpath):
            # Load JSON and check keys exist ...
            info = json.load(open(jpath, "rt"))
            if name in info:
                if resolution in info[name]:
                    # Determine image path and check it exists ...
                    ipath = os.path.join(os.environ["CARTOPY_USER_BACKGROUNDS"], info[name][resolution])
                    if os.path.exists(ipath):
                        default = False

    # Draw background image ...
    if default:
        if debug:
            print("INFO: Drawing default background.")
        axis.stock_img()
    else:
        if debug:
            print("INFO: Drawing user-requested background.")
        axis.background_img(name = name, resolution = resolution, extent = extent)


import numpy as np
# My scripts import
from scripts.Segmentation import Segmentation
from scripts.Rect import Rect
from scripts.extremumlib import get_cwt, get_cwt_swt, linear, bound_filter

from keras.models import model_from_json
import matplotlib.pyplot as plt
import math
import matplotlib.patches as patches
from mpl_toolkits.mplot3d import Axes3D

jsonfile = '../../KerasCNN/models/model_cwt.json' #model_nclasses_46_1
h5file   = '../../KerasCNN/models/model_cwt.h5'

# cnn = load_cnn(jsonfile, h5file)
model_json_path = '../../KerasCNN/models/model_cwt_10k.json' #model_nclasses_46_1
model_h5_path   = '../../KerasCNN/models/model_cwt_10k.h5'
json_file = open(model_json_path, 'r')
loaded_model_json = json_file.read()
json_file.close()
cnn = model_from_json(loaded_model_json)
# load weights into new model
cnn.load_weights(model_h5_path)
cnn._make_predict_function()
print("Loaded model from disk")

opt = 'adam'
loss = 'categorical_crossentropy'
metrics = ['accuracy']
# Compile the classifier using the configuration we want
cnn.compile(optimizer=opt, loss=loss, metrics=metrics)

with open('../train_data/temp.txt', 'r') as f:
    lines = list(f)
    price_series = [float(x) for x in lines[0][1:-2].split(',')]
    price_times = [str(x) for x in lines[1][1:-2].split(",")]
    # print(line)
    n = len(price_series)
    # print(price_series)

price_series = signal = np.sin(np.linspace(0, 20 * math.pi, 256))

def predict(window, scale=50, assurance=0.9, wdname='db6', wcname='morl'):
    print("i am in predict function")
    block_sizex = 32
    block_sizey = 32

    assert len(window) >= block_sizey + 10
    try:
        window = np.array(window)
    except:
        return [],[]

    M = get_cwt_swt(window,
                    scale=scale,
                    mask=[1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
                    wdname=wdname,
                    wcname=wcname
                    )

    M = linear(M)
    # M = bound_filter(M, alpha=0.5)

    test = []
    coords = []

    for i in range(scale - block_sizex):
        for j in range(0,M.shape[1]-block_sizey + 1):
            print(i,i + block_sizex, j,j + block_sizey)
            test.append(M[i:i + block_sizex, j: j + block_sizey])
            coords.append((i, j))

    test = np.array(test)
    print(test)
    test = test.reshape(test.shape[0], block_sizex, block_sizey, 1)
    result = cnn.predict(test, verbose=1)

    cnt = 0
    wow = []
    wow_coords = []
    for i in range(len(result)):
        if result[i, 2] > assurance:
            cnt += 1
            wow.append(test[i, :, :, 0])
            wow_coords.append(coords[i])

    wow_rects = [Rect(wow_coords[i], 32, 32) for i in range(cnt)]
    wow_rects = sorted(wow_rects, key=lambda a: a.x[1])

    correct_rects = []

    for rect in wow_rects:
        if len(correct_rects) == 0:
            correct_rects.append(rect)
        elif not correct_rects[-1].is_crossing(rect):
            correct_rects.append(rect)
        else:
            correct_rects[-1] = correct_rects[-1].get_convex_rect(rect)

    wow = [M[x.x[0]: x.x[0] + x.h, x.x[1]: x.x[1] + x.w] for x in correct_rects]
    segmentations = []

    for i in range(len(wow)):
        cur_rect = correct_rects[i]
        cur_coords = (cur_rect.x[1], cur_rect.x[0])

        segmentations.append(Segmentation(wow[i]))
        segmentations[-1].extract(alpha=0.5)

    return correct_rects, segmentations, M

correct_rects, segmentations, M = predict(price_series[-256:], assurance=0.5, wdname='dmey')
fig, ax = plt.subplots()
plt.matshow(M, fignum=False)

for i in range(len(correct_rects)):
    cur_rect = correct_rects[i]
    cur_coords = (cur_rect.x[1], cur_rect.x[0])

    r = patches.Rectangle(cur_coords, cur_rect.w, cur_rect.h, edgecolor='red', facecolor='none', alpha=0.8)
    ax.add_patch(r)

plt.show()


from sqlalchemy import Column, String
from userbot.plugins.sql_helper import SESSION, BASE

class PMPermit(BASE):
    __tablename__ = "pmpermit"
    chat_id = Column(String(14), primary_key=True)
    reason = Column(String(127))

    def __init__(self, chat_id, reason=""):
        self.chat_id = chat_id
        self.reason = reason

PMPermit.__table__.create(checkfirst=True)

def is_approved(chat_id):
    try:
        return SESSION.query(PMPermit).filter(PMPermit.chat_id == str(chat_id)).one()
    except:
        return None
    finally:
        SESSION.close()

def approve(chat_id, reason):
    adder = PMPermit(str(chat_id), str(reason))
    SESSION.add(adder)
    SESSION.commit()

def disapprove(chat_id):
    rem = SESSION.query(PMPermit).get(str(chat_id))
    if rem:
        SESSION.delete(rem)
        SESSION.commit()

def get_all_approved():
    rem = SESSION.query(PMPermit).all()
    SESSION.close()
    return rem


personal_info = {}

# name = input('Enter your name :')
# age = input('Enter your age :')
# fav_sports = input('Enter your favourite sports by separating them comma : ').split(',')
# fav_language = input('Enter your favourite language by separating them comma : ').split(',')

# personal_info['name'] = name
# personal_info['age'] = age
# personal_info['fav_sports'] =fav_sports
# personal_info['fav_language'] =fav_language

# print(personal_info)

# you can print 2 way
# one is
# for i in personal_info:
#     print(f' {i} : {personal_info[i]} ')

# another is
# for key, value in personal_info.items():
#     print(f' {key} : {value} ')

user_info ={
    'name' : 'limon',
    'age' : 20,
    'hobby' : 'programming',
    'lang' : ['javascript','python'],
    'tuple' : ('salman','tamim')
}

print(user_info)
another_lang = ['html','css','bootstrap']

user_info['lang'].extend(another_lang)
print(user_info)

# pop_items = user_info.popitem()

# print(pop_items)
# print(type(pop_items))

# pop_item = user_info.pop('tuple')
# print(pop_item)
# print(type(pop_item))

# if user_info.get('names'):
#         print('yeah this is present')
# else:
#         print('sorry! not present')


import numpy as np
from ppo_torch import Agent
from mlagents_envs.environment import UnityEnvironment
from mlagents_envs.side_channel.engine_configuration_channel import EngineConfigurationChannel
import reward
import Functions as func

channel = EngineConfigurationChannel()
env = UnityEnvironment(file_name='CoE202', side_channels=[channel])
channel.set_configuration_parameters(time_scale=15)

action_list = [[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 1, 0], [0, 1, 1], [0, 1, 2], [0, 2, 0], [0, 2, 1],
                       [0, 2, 2], [1, 0, 0], [1, 0, 1], [1, 0, 2], [2, 0, 0], [2, 0, 1], [2, 0, 2]]

env.reset()

behavior_name_1 = list(env.behavior_specs)[0]
behavior_name_2 = list(env.behavior_specs)[1]
decision_steps_p, terminal_steps_p = env.get_steps(behavior_name_1)
decision_steps_b, terminal_steps_b = env.get_steps(behavior_name_2)

obs_p1, obs_p2, obs_b1, obs_b2 = func.get_state(decision_steps_p, decision_steps_b)

obs_p1 = np.reshape(obs_p1, 112)

N = 64
batch_size = 8
n_epochs = 8
alpha = 0.0003

agent_p1 = Agent(n_actions=15, batch_size=batch_size,
                alpha=alpha, n_epochs=n_epochs,
                input_dims=obs_p1.shape, chkpt_dir = "p1_strk1")
agent_p2 = Agent(n_actions=15, batch_size=batch_size,
                alpha=alpha, n_epochs=n_epochs,
                input_dims=obs_p1.shape, chkpt_dir = "p2_keep1")
agent_b1 = Agent(n_actions=15, batch_size=batch_size,
                alpha=alpha, n_epochs=n_epochs,
                input_dims=obs_p1.shape, chkpt_dir = "b1_strk1")
agent_b2 = Agent(n_actions=15, batch_size=batch_size,
                alpha=alpha, n_epochs=n_epochs,
                input_dims=obs_p1.shape, chkpt_dir = "b2_keep1")

n_games = 100000
best_score_p1, best_score_p2, best_score_b1, best_score_b2 = -99999, -99999, -99999, -99999
score_history_p1, score_history_p2, score_history_b1, score_history_b2 = [], [], [], []
learn_iters = 0
avg_score_p1, avg_score_p2, avg_score_b1, avg_score_b2 = 0, 0, 0, 0
n_steps = 0

for i in range(n_games):
    env.reset()

    behavior_name_1 = list(env.behavior_specs)[0]
    behavior_name_2 = list(env.behavior_specs)[1]
    decision_steps_p, terminal_steps_p = env.get_steps(behavior_name_1)
    decision_steps_b, terminal_steps_b = env.get_steps(behavior_name_2)

    obs_p1, obs_p2, obs_b1, obs_b2 = func.get_state(decision_steps_p, decision_steps_b)

    observation_p1 = np.reshape(obs_p1, 112)
    observation_p2 = np.reshape(obs_p2, 112)
    observation_b1 = np.reshape(obs_b1, 112)
    observation_b2 = np.reshape(obs_b2, 112)

    done = False
    score_p1, score_p2, score_b1, score_b2 = 0, 0, 0, 0

    t = 0
    while not done:
        t+=1
        a_p1, prob_p1, val_p1 = agent_p1.choose_action(observation_p1)
        a_p2, prob_p2, val_p2 = agent_p2.choose_action(observation_p2)
        a_b1, prob_b1, val_b1 = agent_b1.choose_action(observation_b1)
        a_b2, prob_b2, val_b2 = agent_b2.choose_action(observation_b2)

        action_p1 = action_list[a_p1]
        action_p2 = action_list[a_p2]
        action_b1 = action_list[a_b1]
        action_b2 = action_list[a_b2]

        co_p1, co_back_p1, co_p2, co_back_p2, co_b1, co_back_b1, co_b2, co_back_b2 = func.get_cur_obs(decision_steps_p,
                                                                                decision_steps_b)

        # action_p1, a_p1 = func.logic(co_p1, co_back_p1, action_p1, a_p1, avg_score_p1, "s", i)
        # action_p2, a_p2 = func.logic(co_p2, co_back_p2, action_p2, a_p2, avg_score_p2, "k", i)
        # action_b1, a_b1 = func.logic(co_b1, co_back_b1, action_b1, a_b1, avg_score_b1, "s", i)
        # action_b2, a_b2 = func.logic(co_b2, co_back_b2, action_b2, a_b2, avg_score_b2, "k", i)

        env.set_actions(behavior_name_1, np.array([action_p1, action_p2]))
        env.set_actions(behavior_name_2, np.array([action_b1, action_b2]))

        env.step()

        behavior_name_1 = list(env.behavior_specs)[0]
        behavior_name_2 = list(env.behavior_specs)[1]
        decision_steps_p, terminal_steps_p = env.get_steps(behavior_name_1)
        decision_steps_b, terminal_steps_b = env.get_steps(behavior_name_2)

        obs_p1_, obs_p2_, obs_b1_, obs_b2_ = func.get_state(decision_steps_p, decision_steps_b)

        observation_p1_ = np.reshape(obs_p1_, 112)
        observation_p2_ = np.reshape(obs_p2_, 112)
        observation_b1_ = np.reshape(obs_b1_, 112)
        observation_b2_ = np.reshape(obs_b2_, 112)

        co_p1, co_back_p1, co_p2, co_back_p2, co_b1, co_back_b1, co_b2, co_back_b2 = func.get_cur_obs(decision_steps_p, decision_steps_b)

        # r_p1 = reward.get_reward_1(co_p1, co_back_p1, decision_steps_p.reward[0])
        # r_p2 = reward.get_reward_1(co_p2, co_back_p2, decision_steps_p.reward[0])
        # r_b1 = reward.get_reward_1(co_b1, co_back_b1, decision_steps_b.reward[0])
        # r_b2 = reward.get_reward_1(co_b2, co_back_b2, decision_steps_b.reward[0])

        # r_p1 = reward.get_reward_2(co_p1, co_back_p1, decision_steps_p.reward[0])
        # r_p2 = reward.get_reward_2(co_p2, co_back_p2, decision_steps_p.reward[0])
        # r_b1 = reward.get_reward_2(co_b1, co_back_b1, decision_steps_b.reward[0])
        # r_b2 = reward.get_reward_2(co_b2, co_back_b2, decision_steps_b.reward[0])

        r_p1 = reward.get_reward_striker(co_p1, co_back_p1, decision_steps_p.reward[0])
        r_p2 = reward.get_reward_keeper(co_p2, co_back_p2, decision_steps_p.reward[0])
        r_b1 = reward.get_reward_striker(co_b1, co_back_b1, decision_steps_b.reward[0])
        r_b2 = reward.get_reward_keeper(co_b2, co_back_b2, decision_steps_b.reward[0])

        n_steps += 1

        score_p1 += r_p1
        score_p2 += r_p2
        score_b1 += r_b1
        score_b2 += r_b2

        if decision_steps_b.reward[0] != 0:
            env.reset()
            behavior_name_1 = list(env.behavior_specs)[0]
            behavior_name_2 = list(env.behavior_specs)[1]
            decision_steps_p, terminal_steps_p = env.get_steps(behavior_name_1)
            decision_steps_b, terminal_steps_b = env.get_steps(behavior_name_2)

            obs_p1, obs_p2, obs_b1, obs_b2 = func.get_state(decision_steps_p, decision_steps_b)

            observation_p1_ = np.reshape(obs_p1, 112)
            observation_p2_ = np.reshape(obs_p2, 112)
            observation_b1_ = np.reshape(obs_b1, 112)
            observation_b2_ = np.reshape(obs_b2, 112)

        if t == 255 or decision_steps_b.reward[0] != 0:
            done = True

        agent_p1.remember(observation_p1, a_p1, prob_p1, val_p1, r_p1, done)
        agent_p2.remember(observation_p2, a_p2, prob_p2, val_p2, r_p2, done)
        agent_b1.remember(observation_b1, a_b1, prob_b1, val_b1, r_b1, done)
        agent_b2.remember(observation_b2, a_b2, prob_b2, val_b2, r_b2, done)

        if n_steps % N == 0:
            agent_p1.learn()
            agent_p2.learn()
            agent_b1.learn()
            agent_b2.learn()
            learn_iters += 1

        observation_p1 = observation_p1_
        score_history_p1.append(score_p1)
        avg_score_p1 = np.mean(score_history_p1[-200:])

        observation_p2 = observation_p2_
        score_history_p2.append(score_p2)
        avg_score_p2 = np.mean(score_history_p2[-200:])

        observation_b1 = observation_b1_
        score_history_b1.append(score_b1)
        avg_score_b1 = np.mean(score_history_b1[-200:])

        observation_b2 = observation_b2_
        score_history_b2.append(score_b2)
        avg_score_b2 = np.mean(score_history_b2[-200:])

        if i > 0:
            if avg_score_p1 > best_score_p1:
                best_score_p1 = avg_score_p1
                agent_p1.save_models(i)

            if avg_score_p2 > best_score_p2:
                best_score_p2 = avg_score_p2
                agent_p2.save_models(i)

            if avg_score_b1 > best_score_b1:
                best_score_b1 = avg_score_b1
                agent_b1.save_models(i)

            if avg_score_b2 > best_score_b2:
                best_score_b2 = avg_score_b2
                agent_b2.save_models(i)

            if decision_steps_b.reward[0] != 0:
                if decision_steps_b.reward[0] > 0:
                    agent_b1.save_models(i)
                    agent_b2.save_models(i)
                else:
                    agent_p1.save_models(i)
                    agent_p2.save_models(i)

    print('episode', i, 'score_p1 %.1f' % score_p1, 'score_p2 %.1f' % score_p2, 'score_b1 %.1f' % score_b1,\
          'score_b2 %.1f' % score_b2, 'avg_score_p1 %.1f' % avg_score_p1, 'avg_score_p2 %.1f' % avg_score_p2,\
          'avg_score_b1 %.1f' % avg_score_b1, 'avg_score_b2 %.1f' % avg_score_b2 ,'time_steps', n_steps, 'learning_steps', learn_iters)


import logging
import signal

from mmm_experiments.agents.bmm import DrowsyBMMAgent

if __name__ == "__main__":
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    try:
        agent = DrowsyBMMAgent()
        signal.signal(signal.SIGINT, agent.signal_handler)
        agent.start(ask_at_start=True)
    except Exception as e:
        agent.stop(exit_status="fail", reason=f"{e}")
        raise e


#!/usr/bin/python

filenames = [
    'boxes',
    'arrows',
]

command = ''
for name in filenames:
    command += "echo {}.svg --export-pdf={}.pdf;\n".format(name, name)
command = "({}) |\nDISPLAY= inkscape --shell".format(command)

import os
os.system(command)


import os
import pandas as pd
import torchaudio
import numpy as np
from speechbrain.pretrained import SpeakerRecognition
from sklearn.metrics.pairwise import cosine_similarity
import logging
from multiprocessing import Pool

logging.basicConfig(filename='app.log', level=logging.INFO,
                    format='%(asctime)s - %(levelname)s - %(message)s')

def process_file(filename, directory_path, model, similarity_threshold):
    try:
        logging.info(f"Processing file: {filename}")
        waveform, sample_rate = torchaudio.load(os.path.join(directory_path, filename))
        embedding = model.encode_batch(waveform)
        embedding_np = embedding.numpy().reshape(-1)
        return filename, embedding_np
    except Exception as e:
        logging.error(f"Error processing {filename}: {str(e)}")
        return None, None

def identify_speakers_and_generate_csv(directory_path, output_csv_path, similarity_threshold=0.6):
    try:
        logging.info("Loading SpeakerRecognition model...")
        model = SpeakerRecognition.from_hparams(source="speechbrain/spkrec-ecapa-voxceleb", savedir="tmpdir_emozr")
        logging.info("SpeakerRecognition model loaded successfully.")

        file_speaker_pairs = []

        logging.info("Processing WAV files and extracting embeddings...")

        # Use multiprocessing to process files concurrently
        with Pool() as pool:
            results = [result for result in pool.starmap(process_file, [(filename, directory_path, model, similarity_threshold) for filename in os.listdir(directory_path) if filename.endswith(".mp3")])]

        for filename, embedding_np in results:
            if embedding_np is not None:
                matched_speaker_id = None
                for _, _, existing_embedding, existing_speaker_id in file_speaker_pairs:
                    similarity_score = cosine_similarity([embedding_np], [existing_embedding])[0][0]
                    if similarity_score >= similarity_threshold:
                        matched_speaker_id = existing_speaker_id
                        break

                if matched_speaker_id is None:
                    new_speaker_id = len(file_speaker_pairs) + 1
                    file_speaker_pairs.append((filename, new_speaker_id, embedding_np, new_speaker_id))
                    logging.info(f"New speaker ID assigned: {new_speaker_id}")
                else:
                    file_speaker_pairs.append((filename, matched_speaker_id, embedding_np, matched_speaker_id))
                    logging.info(f"Matched with existing speaker ID: {matched_speaker_id}")

        logging.info("Creating CSV file...")

        df = pd.DataFrame(file_speaker_pairs, columns=['File Name', 'Speaker ID'])
        df.to_csv(output_csv_path, index=False)

        logging.info(f"CSV file '{output_csv_path}' generated successfully.")

    except Exception as e:
        logging.error(f"An error occurred: {str(e)}")

# Example usage
directory_path = "cv-corpus-5.1-2020-06-22/rw/selected_clips"
output_csv_path = "output.csv"
identify_speakers_and_generate_csv(directory_path, output_csv_path)


from time import time, sleep
from functools import wraps

def measure(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        t = time()
        func(*args, **kwargs)
        print(f'{func.__name__}:{time() - t:.4f}')
    return wrapper

@measure
def foo(sleep_time=0.3):
    '''Function foo sleeps sleep time seconds'''
    sleep(sleep_time)

if __name__ == '__main__':

    foo()
    foo(0.5)
    print(f'{foo.__name__} doc str:{foo.__doc__}')
    print('---')


from rest_framework import serializers
from rest_framework.exceptions import MethodNotAllowed
from rest_framework.generics import get_object_or_404

from utils.drf import errors
from utils.drf.exceptions import ValidationError
from .membership import StudyMembershipSerializer
from ..models import (
    StudyInviteToken,
)

class StudyInviteTokenSerializer(serializers.ModelSerializer):
    class Meta:
        model = StudyInviteToken
        fields = (
            'key',
        )

class StudyInviteTokenCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = StudyInviteToken
        fields = (
            'study',
        )

    def to_representation(self, instance):
        return StudyInviteTokenSerializer(instance).data

class StudyMembershipCreateByInviteTokenSerializer(serializers.Serializer):
    key = serializers.CharField()
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())

    def create(self, validated_data):
        key = validated_data.get('key')
        user = validated_data.get('user')
        if not (key and user):
            raise ValueError('key, user는 모두 존재해야 합니다')
        token = get_object_or_404(StudyInviteToken, key=key)

        membership, created = user.membership_set.get_or_create(study=token.study)
        if not created:
            if membership.is_withdraw:
                membership.is_withdraw = False
                membership.save()
            else:
                raise ValidationError(errors.MEMBERSHIP_ALREADY_EXISTS)
        return membership

    def update(self, instance, validated_data):
        raise MethodNotAllowed('update는 허용하지 않습니다')

    def to_representation(self, instance):
        return StudyMembershipSerializer(instance).data


"""
@framebot (телеграм бот для записи людей на определенное время)

"""
import telebot
from telebot import types
import time
from datetime import datetime, timedelta
import re
from settings import *
from dbclass import *

bot = telebot.TeleBot(TOKEN, threaded=False)  # отключена многопоточность библиотеки threaded=False
print('Start program...{}'.format(datetime.now()))

# Сразу создадим таблицы
initdb = SqliteDb()
initdb.create_table()
initdb.create_config_table()
initdb.create_limittable()
initdb.create_timetable()
initdb.close()
print('Ok...')

def is_allowed(string):
    characherRegex = re.compile(r'[^a-zA-Z0-9.:\s]')
    string = characherRegex.search(string)
    return not bool(string)

def get_shift_intervals(goodsymbol=GoodSymbol, default_value=SHIFT_INTERVALS):
    try:
        connect = SqliteDb()
        rows = connect.get_configs()
        connect.close()

        SHIFT_INTERVALS = {}
        for row in rows:
            q = dict(row)
            SHIFT_INTERVALS[str(q['id'])] = goodsymbol + q['shift']
        if bool(SHIFT_INTERVALS):
            return SHIFT_INTERVALS
        else:
            return default_value
    except Exception as exc:
        print(exc.args)

def get_shiftmax(default_value=SHIFTMAX):
    try:
        connect = SqliteDb()
        dt = connect.get_max()
        connect.close()
        dt = dict(dt[0])
    except Exception as exc:
        print(exc.args)

    if dt:
        if dt['vlimit'].isdigit():
            return int(dt['vlimit'])
    else:
        return default_value

def get_time():
    connect = SqliteDb()
    lim = connect.get_timelimit()
    connect.close()

    f = dict(lim[0])
    timestart = f['timestart']
    timelimit = f['timelimit']
    try:

        timestart = datetime.strptime(timestart, '%Y-%m-%d %H:%M:%S.%f')
        timeend = timestart + timedelta(minutes=int(timelimit))
    except Exception as exc:
        print(exc.args)
    return [timestart, timeend]

def create_inlinekeyboarb(message):
    SHIFTMAX = get_shiftmax()
    SHIFT_INTERVALS = get_shift_intervals()
    limlist = get_time()
    db = SqliteDb()
    inlinekeyboarb = types.InlineKeyboardMarkup(row_width=2)

    for shift in SHIFT_INTERVALS:
        text = SHIFT_INTERVALS[shift]
        us = len(db.count_rows(shift=shift))
        if us == SHIFTMAX:
            text = SHIFT_INTERVALS[shift] + " ❌ Запись закрыта"

        itembtnlook = types.InlineKeyboardButton(text='Участники {}/{} 🙋'.format(us, SHIFTMAX), callback_data=shift+'_look')
        itembtn1 = types.InlineKeyboardButton(text=text, callback_data=shift)

        inlinekeyboarb.row(itembtnlook, itembtn1)
    db.close()

    tend = str(limlist[1])

    text = """Запись на завтра открыта 🔔🔔🔔
Выберите,пожалуйста,время 🔻🔻
(Запись до {})""".format(tend[11:16])

    bot.send_message(message.chat.id,
                     text=text,
                     reply_markup=inlinekeyboarb)

def delete_or_insert(call):
    """
    :param call: принимает данные из инлайн-клавиатуры
    :return: answer_callback_query  Делает запрос в БД и показавает всплывающее окно об удаление или добавлении записи.
    """
    SHIFTMAX = get_shiftmax()
    SHIFT_INTERVALS = get_shift_intervals()
    db = SqliteDb()
    value = db.get(user_id=call.from_user.id, shift=call.data)
    if value == True:
        db.delete(user_id=call.from_user.id, shift=call.data)
        db.close()
        bot.answer_callback_query(callback_query_id=call.id,
                                  show_alert=True,
                                  text="Запись на смену {} удалена".format(SHIFT_INTERVALS[call.data]))
    else:
        if len(db.count_rows(shift=call.data)) == SHIFTMAX:
            db.close()
            bot.answer_callback_query(callback_query_id=call.id,
                                      show_alert=True,
                                      text="{}, записаться уже нельзя. Выберите другую смену!".format(call.from_user.first_name))
        else:
            try:
                user_name = call.from_user.first_name + '_' + call.from_user.last_name
            except Exception:
                user_name = 'Безымянный'

            status = db.insert(shift=call.data, user_id=call.from_user.id, user_name=user_name,
                               date=datetime.now())

            db.close()
            bot.answer_callback_query(callback_query_id=call.id,
                                      show_alert=True,
                                      text="{}, Вы записаны на {}. Нажмите еще раз если хотите отписаться".format(call.from_user.first_name,
                                                                                SHIFT_INTERVALS[call.data]))

@bot.message_handler(func=lambda m: True)
def process_main(message):
    SHIFT_INTERVALS = get_shift_intervals()
    if message.text == '/start':
        if str(message.from_user.id) in ADMIN_LIST:
            create_inlinekeyboarb(message)

    elif message.text == '/help':
        text = """Дамы и господа! Я обычный бот для записи.
        Мои основные команды:
          /start - вывести окно записи
          /look - посмотреть всех записавшихся
          /push - удалить всех записавшихся, отобразить новое пустое окно записи, обнулить время начала записи.
          /config - редактировать окно записи(после config перечислите названия смен через пробел):
        Для отложенного запуска окна записи:
           -наберите команды и удерживайте кнопку _отправить_ > в мобильной версии
           или правой кнопкой мыши в десктопе
          /max - максимальное количество записей на одну смену
          /timelimit - установить время действие окна записи в минутах.По умолчанию 240минут(4 часа)

           @graphinfinit

        """
        bot.send_sticker(message.chat.id, 'CAACAgIAAxkBAAJIzV6ZAxBrxUQi0nrkXj1UrbMCRtIuAAJxbAACY4tGDL3Mn3hoWa1cGAQ')
        bot.send_message(message.chat.id,
        text=text)

    elif message.text == '/look':
        if str(message.from_user.id) in ADMIN_LIST:
            db = SqliteDb()
            for shift in SHIFT_INTERVALS:
                count_rows = db.count_rows(shift=shift)
                bot.send_message(message.chat.id,
                                 text='Записались на {} - {} человек.'.format(SHIFT_INTERVALS[shift], len(count_rows)))
                for row in count_rows:
                    row = dict(row)
                    text ="{}".format(row['user_id'], row['user_name'])
                    bot.send_message(message.chat.id, text=text, parse_mode='HTML')
            db.close()

    elif message.text == '/push':
        if str(message.from_user.id) in ADMIN_LIST:
            db = SqliteDb()
            db.drop_table()
            db.create_table()
            db.update_timestart(timestart=datetime.now())

            db.close()
            bot.send_message(message.chat.id, text=".".format(
                message.from_user.first_name), parse_mode='HTML')
            create_inlinekeyboarb(message)
        else:
            bot.send_message(message.chat.id, text="!{}, я слушаюсь только хозяина.".format(message.from_user.first_name), parse_mode='HTML')

    elif message.text[:7] == '/config':
        if str(message.from_user.id) in ADMIN_LIST:
            try:
                data = message.text[8:]
                if is_allowed(data) and len(data) > 2:
                    shift_list = message.text[8:].split()
                    db = SqliteDb()
                    db.drop_config()
                    db.create_config_table()
                    for shift in shift_list:
                        db.insert_config(shift=shift)
                    db.close()

                    bot.send_message(message.chat.id, text="{}, Данные были обновлены!!!".format(
                        message.from_user.first_name))
                else:
                    bot.send_message(message.chat.id,
                    text="Ошибка. В названии интервала допустимы только цифры, буквы и двоеточие ':'")

            except:
                bot.send_message(message.chat.id,
                text="Ошибка. Придерживайтесь формата /config[пробел]Название интервала[пробел]Название интервала 2...")
        else:
            bot.send_message(message.chat.id, text="!{}, я слушаюсь только хозяина.".format(message.from_user.first_name), parse_mode='HTML')

    elif message.text[:4] == '/max':
        if str(message.from_user.id) in ADMIN_LIST:
            try:
                data = message.text[5:]
                if data.isdigit():
                    if int(data) >= 1:
                        db = SqliteDb()
                        db.drop_max()
                        db.create_limittable()
                        db.set_max(data)
                        db.close()
                        bot.send_message(message.chat.id,
                                         text="Ограничение исполнено.")
                else:
                    bot.send_message(message.chat.id,
                                     text="Ошибка входных данных.")
            except Exception:
                bot.send_message(message.chat.id,
                                 text="Ошибка!!")
    elif message.text[:10] == '/timelimit':
        if str(message.from_user.id) in ADMIN_LIST:
            if message.text[11:].isdigit():
                try:
                    timelimit = message.text[11:]
                    db = SqliteDb()
                    db.update_timelimit(timelimit=timelimit)
                    db.close
                    bot.send_message(message.chat.id,
                                     text="Ограничение по времени успешно обновлено")
                except Exception as exc:
                    print(exc.args)
            else:
                bot.send_message(message.chat.id,
                                 text="Неправильные данные. Введите число после команды")

        else:
            bot.send_message(message.chat.id, text="!{}, я слушаюсь только хозяина.", parse_mode='HTML')

    else:
        pass

@bot.callback_query_handler(func=lambda call: True)
def process_call(call):
    SHIFT_INTERVALS = get_shift_intervals()
    lim = get_time()
    timeend = lim[1]
    timenow = datetime.now()

    for key_of_shift in SHIFT_INTERVALS:
        if call.data == key_of_shift:
            if timeend > timenow:
                delete_or_insert(call)
                bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id)
                create_inlinekeyboarb(call.message)
            else:
                bot.answer_callback_query(callback_query_id=call.id,
                                          show_alert=True,
                                          text='К сожалению время записи истекло. Попробуйте в другой раз')

        if call.data == key_of_shift + '_look':
            db = SqliteDb()
            count_rows = db.count_rows(shift=key_of_shift)
            text = 'Записались {} человек:  '.format(len(count_rows))
            for row in count_rows:
                row = dict(row)
                text += "  {}  ".format(row['user_name'])
            db.close()

            bot.answer_callback_query(callback_query_id=call.id,
                                      show_alert=True,
                                      text=text)

if __name__ == '__main__':
    while True:
        try:
            bot.infinity_polling(True)
        except Exception as problem:
            print(problem.args)
            time.sleep(20)


from ...function.update_table import UpdateTable
from ...model.ccost_mdb import CcostMdb
from ...model.djasa_ddb import DjasaDdb
from ...model.dprod_ddb import DprodDdb
from ...model.inv_pb_hdb import InvpbHdb
from ...model.lokasi_mdb import LocationMdb
from ...model.ordpb_hdb import OrdpbHdb
from ...model.prod_mdb import ProdMdb
from ...model.jasa_mdb import JasaMdb
from ...model.unit_mdb import UnitMdb
from ...schema.dord_hdb import DordSchema, dord_schema
from ...shared.shared import db
from ...utils.response import response
from sqlalchemy.exc import *
from ...schema.prod_mdb import prod_schema
from ...schema.jasa_mdb import jasa_schema
from ...schema.unit_mdb import unit_schema
from ...schema.inv_pb_hdb import InvpbSchema, invpb_schema
from ...schema.dprod_ddb import dprod_schema
from ...schema.djasa_ddb import djasa_schema
from ...schema.lokasi_mdb import loct_schema

class InvoicePb:
    def __new__(self, user, request):
        if request.method == "POST":
            inv_code = request.json["inv_code"]
            inv_date = request.json["inv_date"]
            ord_id = request.json["ord_id"]
            inv_tax = request.json["inv_tax"]
            inv_ppn = request.json["inv_ppn"]
            inv_desc = request.json["inv_desc"]
            total_bayar = request.json["total_bayar"]

            invoice = InvpbHdb(
                inv_code,
                inv_date,
                ord_id,
                inv_tax,
                inv_ppn,
                inv_desc,
                total_bayar,
                False,
            )

            db.session.add(invoice)

            db.session.commit()

            # UpdateFakturPj(faktur.id, False, faktur.sale_id, user.id, user.product, user.company, glUrl, request)

            return response(200, "success", True, invpb_schema.dump(invoice))
        else:
            try:
                inv = (
                    db.session.query(InvpbHdb, OrdpbHdb)
                    .outerjoin(OrdpbHdb, OrdpbHdb.id == InvpbHdb.ord_id)
                    .order_by(InvpbHdb.id.desc())
                    .all()
                )
                dprod = (
                    db.session.query(DprodDdb, ProdMdb, UnitMdb, LocationMdb)
                    .outerjoin(ProdMdb, ProdMdb.id == DprodDdb.prod_id)
                    .outerjoin(UnitMdb, UnitMdb.id == DprodDdb.unit_id)
                    .outerjoin(LocationMdb, LocationMdb.id == DprodDdb.location)
                    .all()
                )

                djasa = (
                    db.session.query(DjasaDdb, JasaMdb, UnitMdb)
                    .outerjoin(JasaMdb, JasaMdb.id == DjasaDdb.jasa_id)
                    .outerjoin(UnitMdb, UnitMdb.id == DjasaDdb.unit_id)
                    .all()
                )

                final = []
                for x in inv:
                    product = []
                    if x[1]:
                        for y in dprod:
                            if x[1]:
                                if y[0].ord_id == x[1].id:
                                    y[0].prod_id = prod_schema.dump(y[1])
                                    y[0].unit_id = unit_schema.dump(y[2])
                                    y[0].location = (
                                        loct_schema.dump(y[3])
                                        if y[0].location
                                        else None
                                    )
                                    product.append(dprod_schema.dump(y[0]))

                    jasa = []
                    if x[1]:
                        for z in djasa:
                            if x[1]:
                                if z[0].ord_id == x[1].id:
                                    z[0].jasa_id = jasa_schema.dump(z[1])
                                    z[0].unit_id = unit_schema.dump(z[2])
                                    jasa.append(djasa_schema.dump(z[0]))

                    final.append(
                        {
                            "id": x[0].id,
                            "inv_code": x[0].inv_code,
                            "inv_date": x[0].inv_date.isoformat(),
                            "ord_id": dord_schema.dump(x[1]),
                            "inv_tax": x[0].inv_tax,
                            "inv_ppn": x[0].inv_ppn,
                            "inv_lunas": x[0].inv_lunas,
                            "inv_desc": x[0].inv_desc,
                            "total_bayar": x[0].total_bayar,
                            "faktur": x[0].faktur,
                            "post": x[0].post,
                            "closing": x[0].closing,
                            "product": product,
                            "jasa": jasa,
                        }
                    )

                return response(200, "success", True, final)
            except ProgrammingError as e:
                return UpdateTable(
                    [
                        InvpbHdb,
                        OrdpbHdb,
                        DprodDdb,
                        ProdMdb,
                        UnitMdb,
                        LocationMdb,
                        DjasaDdb,
                        JasaMdb,
                    ],
                    request,
                )


import os
from multiprocessing import Pool
import sys
import glob
import time

def run_model_test(data_info, GPU_SET):
    cmd = "python train_model.py"
    data_path = "/rd2/lijy/KDD/vCNNFinal/Data/ChIPSeqData/HDF5/" + data_info + "/"
    result_root = "/home/luox/softpooling/result/local_window_for_real_data"
    set = cmd + " " + data_path + " " +result_root + "  " + data_info + " "+GPU_SET
    print(set)
    os.system(set)

def get_data_info():
    path = "/rd2/lijy/KDD/vCNNFinal/Data/ChIPSeqData/HDF5/"
    path_list = glob.glob(path + '*/')
    data_list = []
    for rec in path_list:
        data_info = rec.split("/")[-2]
        data_list.extend([data_info])
    return data_list

if __name__ == '__main__':

    GPU_SET = sys.argv[1]
    start_time =  time.time()
    data_list = get_data_info()
    # print(len(data_list))
    # print(data_list[0:10])
    pool = Pool(processes  = 5)
    #data_list = ["wgEncodeAwgTfbsHaibGm12878Tcf3Pcr1xUniPk", "wgEncodeAwgTfbsSydhHepg2Mazab85725IggrabUniPk", "wgEncodeAwgTfbsSydhK562E2f6UcdUniPk", "wgEncodeAwgTfbsSydhGm12878Pol2IggmusUniPk"]

    for data_info in data_list[95:300]:
        time.sleep(2)
        pool.apply_async(run_model_test,(data_info,GPU_SET))
    pool.close()
    pool.join()
    print("all model cost ",  time.time() - start_time)


import logging

def make_logger(name='logger',  reuse=False):
    logging.basicConfig(level=logging.INFO)
    filename = '{}.txt'.format(name)
    formatter = logging.Formatter('{message:s}', style='{')
    fileout = logging.FileHandler(filename=filename, mode='w')
    mylog = logging.getLogger(name)
    mylog.addHandler(fileout)
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    console.setFormatter(formatter)
    mylog.addHandler(console)
    mylog.propagate = True
    return mylog


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

current_year = int(input("Enter current year: "))
python_year = 1989

age_of_python = current_year - python_year

your_name = input("Enter your name: ")
your_age = input("Enter your age: ")

print("Hello {0} :)".format(your_name))
print("My name is Python and i am {0} years old.".format(age_of_python))

if int(your_age) < age_of_python:
    print("You are younger than python.")
else:
    print("You are not younger than python.")

sites with exercises/python101.readthedocs.io/1.Basics/1.5.1 name me python.py


import tkinter as tk

from logic.study.sqlalchemy.Opening import Opening

class OpeningEntry(tk.OptionMenu):
    def __init__(self, window: tk.Tk, master: tk.Widget, option_var: tk.StringVar) -> None:
        super().__init__(
            master,
            option_var,
            'PLACEHOLDER'
        )
        self.window = window
        self.option_var = option_var
        menu = self['menu']
        menu.delete(0, tk.END)
        openings = self.window.database.get_openings()
        ordered_openings = sorted(openings, key = lambda x: x.name)
        for opening in ordered_openings:
            menu.add_command(label = opening.name, command = tk._setit(self.option_var, opening.name))
        self.pack(anchor = tk.W, padx = 15, pady = (5, 10))


import numpy as np
import argparse
import time
import cv2

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", help = "Path to the image file")
args = vars(ap.parse_args())

# Define lower and upper limit for color you want to track
fishLower = np.array([192, 192, 192], dtype = "uint8")
fishUpper = np.array([51, 51, 0], dtype = "uint8")

frame = cv2.imread(args["image"])
cv2.imshow("Original", frame)
cv2.waitKey(0)

fish = cv2.inRange(frame, fishLower, fishUpper)
fish = cv2.GaussianBlur(fish, (3, 3), 0)

# Find contours of thersholded image
(_, cnts, _) = cv2.findContours(fish.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Check to make sure contours were found
if len(cnts) > 0:
    cnt = sorted(cnts, key = cv2.contourArea, reverse = True) [0]
    rect = np.int32(cv2.boxPoints(cv2.minAreaRect(cnt)))
    cv2.drawContours(frame, [rect], -1, (0, 255, 0), 2)

cv2.imshow("Tracking", frame)
cv2.imshow("Binary", fish)
cv2.waitKey(0)

# Masking


# perf1.py
# Time of a long running request

from socket import *
import time

sock = socket(AF_INET, SOCK_STREAM)
sock.connect(('localhost', 25000))

while True:
    start = time.time()
    sock.send(b'30')
    resp =sock.recv(100)
    end = time.time()
    print(end-start)


# keras61_cifar10_DNN.py

# 10가지 컬러 이미지

from keras.datasets import cifar10
from keras.utils import np_utils
from keras.models import Sequential, Model
from keras.layers import Input, Dense , LSTM, Conv2D, Flatten, MaxPool2D, Dropout, BatchNormalization
import matplotlib.pyplot as plt

# 데이터

(x_train, y_train),(x_test,y_test) = cifar10.load_data()

y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)

x_train  = x_train.reshape(50000,3072).astype('float32')/255.0
x_test  = x_test.reshape(10000,3072).astype('float32')/255.0

# print(x_train.shape)  #(50000, 1024)
# print(x_test.shape)   #(10000, 1024)      # functional 모델에 맞게 reshape

# ____________모델 구성____________________

model= Sequential()

input1 = Input(shape=(3072,), name= 'input_1')

dense1 = Dense  (216, activation = 'relu', name = 'output_1')(input1)
batch_1 = BatchNormalization()(dense1)
dropout1 = Dropout(0.25)(batch_1)

dense1_2 = Dense (512, activation = 'relu',  name = 'output_1_2')(dropout1)
batch_2 = BatchNormalization()(dense1_2)
dropout2 = Dropout(0.25)(batch_2)

dense1_3 = Dense (512, activation = 'relu', name = 'output_1_3')(dropout2)
batch_3 = BatchNormalization()(dense1_3)
dropout3 = Dropout(0.25)(batch_3)

dense1_4 = Dense (512, activation = 'relu', name = 'output_1_4')(dropout3)
batch_4 = BatchNormalization()(dense1_4)
dropout4 = Dropout(0.25)(batch_4)

dense1_5 = Dense (10, activation= 'softmax' , name = 'output_1_5')(batch_4)

model = Model (inputs = input1, outputs= (dense1_5))

model.summary()

# 훈련

from keras.callbacks import EarlyStopping
early_stopping = EarlyStopping( monitor='loss', patience= 100, mode ='auto')

model.compile(loss = 'categorical_crossentropy', optimizer='adam', metrics = ['acc'])

model.fit(x_train,y_train, epochs= 20, batch_size= 120, validation_split= 0.25 ,callbacks= [early_stopping])

# 평가 및 예측

loss, acc = model.evaluate(x_test,y_test, batch_size=1)

print('loss :', loss)
print('accuracy : ', acc)

'''

loss : 1.8836045649481303
accuracy :  0.4902999997138977

'''


import pymongo
import datetime
import bottle
import json

class speed_project(object):
   def __init__(self):
      '''sets up mongo connection'''
      self.repl_set = ["mongodb://mongo%s:27017" % i for i in range(1,4)]
      self.repl_set_name = "rs0"
      self.write_concern = 2
      self.j = True
      self.connection = pymongo.MongoClient(host=self.repl_set, replicaSet=self.repl_set_name, w=self.write_concern, j=self.j)
      self.db = self.connection.speeds
      self.col = self.db.test

   def average_day_report(self):
      '''Runs an aggregate report grouping by day'''
      project = {"$project" : {
                 "_id" : "$_id",
                 "download" : "$Download",
                  "upload" : "$Upload" ,
                  "day" : {"$dayOfWeek" :"$date"}}}
      group = {"$group" : {
               "_id" : "$day",
               "avg_d" : {"$avg" : "$download"},
               "avg_u" : { "$avg" : "$upload"}}}
      aggregate = self.col.aggregate([ project , group ])
      return aggregate

   def test(self):
      '''tests mongo connection'''
      db = self.connection.test
      cursor = db.test.find()
      stuff = [document for document in cursor]
      return stuff

   def add_date_now(self, doc):
     '''adds the date now'''
     doc['date'] = datetime.datetime.utcnow()
     return doc

   def update_speed(self, doc):
      '''updates document'''
      doc = self.add_date_now(doc)
      doc = self.col.insert(doc)
      return doc

   def get_date(self, speed, direction='Download'):
      '''returns a date if given a speed assumes speed is download unless direction="Upload"'''
      cursor = self.col.find({direction: speed},{"_id":False,"date":True})
      date = cursor.next()['date']
      return str(date)

   def get_aggregate(self):
      '''aggregates speed, accepts upload/download as argument'''
      aggregation_object = {
                     "$group" : {
                        "_id"    : "Aggregate",
                        "Average download" : {"$avg" : "$Download"},
                        "Average upload" : {"$avg" : "$Upload"},
                        "Max Download" : {"$max" : "$Download"},
                        "Max Upload" : {"$max" : "$Upload"},
                        "Min Download" : {"$min" : "$Download"},
                        "Min Upload" : {"$min" : "$Upload"}
                                }
                           }
      average = self.col.aggregate(aggregation_object)
      return average

   def average_time(self):
      '''aggregates speed according to the hour in the day'''
      aggregation_object = {
                     "$group" : {
                        "_id"   : {"$hour":"$date"},
                        "download" : {"$avg":"$Download"},
                        "upload": {"$avg" : "$Upload"}
                                }
                           }
      average_time = self.col.aggregate(aggregation_object)
      return average_time

   def last_40(self):
     sort = [("date", -1)]
     find_filter = {"_id":0}
     limit = 40
     cursor = self.col.find({},find_filter).sort(sort).limit(limit)
     most_recent = {}
     for i in range(40,0,-1):
        most_recent[i] = cursor.next()
        most_recent[i]["date"] = most_recent[i]["date"].hour * 100 + most_recent[i]["date"].minute
     return most_recent


import json
from flask import (
    request,
    session,
    url_for,
    redirect,
    Blueprint)
from jose import jwt
from urllib.request import urlopen
from functools import wraps

# Local imports...
from config import Config
from exceptions import AuthError

auth_bp = Blueprint('auth_bp', __name__)

###########################################################
#
# CONSTANTS
#
###########################################################

conf = Config()

api_audience = conf.API_AUDIENCE
auth0_domain = conf.AUTH0_DOMAIN
algorithms = conf.ALGORITHMS
client_id = conf.CLIENT_ID
client_secret = conf.CLIENT_SECRET
access_token_url = conf.ACCESS_TOKEN_URL
authorize_url = conf.AUTHORIZE_URL
callback_uri = conf.CALLBACK_URL
secret_key = conf.SECRET_KEY
test_token = conf.TEST_TOKEN
conf_access_key = conf.ACCESS_KEY
profile_key = conf.PROFILE_KEY

'''
    Implement _get_token_auth_header() method
    it should attempt to get the header from the request
        it should raise an AuthError if no header is present
    it should attempt to split bearer and the token
        it should raise an AuthError if the header is malformed
    return the token part of the header
'''

def _get_token_auth_header():

    #############################################################
    #
    # TODO This is not the correct way to implement security,
    # I'd imagine that one should be passing the access key
    # between the front end and back end through the request
    # header. However, I have spend two weeks trying different
    # ways and still couldn't come up with a feasible solution.
    # Since this part is not critical for the capstone, I have
    # implemented this temporary solution to force the
    # application to work, and I will try to figure it out in
    # a later time.
    #
    # This implementation does not grab the access token from
    # the request header, but check the host url from the request
    # header and see if it's the same as the 'API Audience' set
    # up using the Auth0 API UI. If it is, grab the access key
    # stored in the Flask session when the application is going
    # through the callback code after logging in. And all the
    # steps after that follow strictly to how we are taught.
    #
    ###############################################################

    if request.headers['HOST'] in api_audience:
        # Postman test work-around
        if 'POSTMAN_TOKEN' not in request.headers:
            # Unit test work-around
            if 'test_permission' in request.headers:
                return test_token

            if conf_access_key in session:
                access_key = session[conf_access_key]
                return access_key['access']
            else:
                raise AuthError({
                    "code": "authorization_required",
                    "description": "User is not logged in"
                }, 401)

    if 'Authorization' not in request.headers:
        raise AuthError({
            "code": "authorization_required",
            "description": "Authorization is expected in header"
        }, 401)

    # "Authorization": "bearer <<token>>"
    auth_header = request.headers['Authorization']

    header_parts = auth_header.split(' ')

    if len(header_parts) != 2 or header_parts[0].lower() != 'bearer':
        raise AuthError({
            "code": "invalid_token",
            "description": "Mendatory authorization requires 'bearer' token"
        }, 401)

    return header_parts[1]

'''
    Implement check_permissions(permission, payload) method
    @INPUTS
        permission: string permission (i.e. 'post:drink')
        payload: decoded jwt payload

    it should raise an AuthError if permissions are not included in the payload
        !!NOTE check your RBAC settings in Auth0
    it should raise an AuthError if the requested permission string is
    not in the payload permissions array
    return true otherwise
'''

def _check_permissions(permission, payload):
    if 'permissions' not in payload:
        raise AuthError({
            'code': 'invalid_claims',
            'description': 'Permissions not included in JWT'
        }, 400)

    # For unit testing purposes
    # The key-value pair of 'test_permission' is included in the request
    # headers when the request is identified as an unit test request;
    # permissions of the routes then can be tested via the manipulations of
    # the permissions list in the payload
    if 'test_permission' in request.headers:
        payload['permissions'] = [request.headers['test_permission']]

    if isinstance(permission, list) and len(permission) > 1:
        if not set(permission).intersection(payload['permissions']):
            raise AuthError({
                'code': 'unauthorized',
                'description': 'Permission not found'
            }, 401)
    else:
        if permission not in payload['permissions']:
            raise AuthError({
                'code': 'unauthorized',
                'description': 'Permission not found'
            }, 401)

    return True

'''
    Implement verify_decode_jwt(token) method
    @INPUTS
        token: a json web token (string)

    it should be an Auth0 token with key id (kid)
    it should verify the token using Auth0 /.well-known/jwks.json
    it should decode the payload from the token
    it should validate the claims
    return the decoded payload

    !!NOTE urlopen has a common certificate error described here:
    https://stackoverflow.com/questions/50236117/scraping-ssl-certificate-verify-failed-error-for-http-en-wikipedia-org
'''

def _verify_decode_jwt(token):
    # Get the public key from Auth0
    jsonurl = urlopen(
        f'https://{auth0_domain}/.well-known/jwks.json')
    jwks = json.loads(jsonurl.read())

    # Get the data in the header
    unverified_header = jwt.get_unverified_header(token)

    # Choose the key
    rsa_key = {}
    if 'kid' not in unverified_header:
        raise AuthError({
            'code': 'invalid_header',
            'description': 'Authorization malformed'
        }, 401)

    for key in jwks['keys']:
        if key['kid'] == unverified_header['kid']:
            rsa_key = {
                'kty': key['kty'],
                'kid': key['kid'],
                'use': key['use'],
                'n': key['n'],
                'e': key['e']
            }

    # Finally, verify!!!
    if rsa_key:
        try:
            # USE THE KEY TO VALIDATE THE JWT
            payload = jwt.decode(
                token,
                rsa_key,
                algorithms=algorithms,
                audience=api_audience,
                issuer=(
                    f'https://{auth0_domain}/')
            )

            return payload

        except jwt.ExpiredSignatureError:
            raise AuthError({
                'code': 'token_expired',
                'description': 'Token expired'
            }, 401)

        except jwt.JWTClaimsError:
            raise AuthError({
                'code': 'invalid_claims',
                'description':
                    'Incorrect claims. Please check the audience and issuer'
            }, 401)
        except Exception:
            raise AuthError({
                'code': 'invalid_header',
                'description': 'Unable to parse authentication token'
            }, 400)
    raise AuthError({
        'code': 'invalid_header',
        'description': 'Unable to find the appropriate key'
    }, 400)

def requires_auth(permission=''):
    def requires_auth_decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            token = _get_token_auth_header()
            try:
                payload = _verify_decode_jwt(token)
            except BaseException:
                raise AuthError({
                    "code": "jwt_decode_error",
                    "description": "Error decoding JWT"
                }, 401)

            _check_permissions(permission, payload)

            return f(payload, *args, **kwargs)

        return wrapper
    return requires_auth_decorator

def requires_login(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if profile_key not in session:
            session.clear()
            return redirect(url_for('login'))
        return f(*args, **kwargs)

    return decorated


import argparse, os, sys, csv
import xml.etree.ElementTree as ET

def processCSV(csvFilename, folders):
	if (csvFilename == "-"):
		csvFile = sys.stdin.readlines()		# Read from stdin
	else:
		csvFile = open(csvFilename, "r")	# Read from input file

	reader = csv.reader(csvFile)

	# Skip the header lines
	next(reader, None)
	next(reader, None)

	for row in reader:
		# Read the fields from the CSV file
		repeater = {"codes":{}, "modes":{}}
		repeater["call"]         = row[7]										# H  Callsign
		repeater["city"]         = row[5]										# F  City
		repeater["coverageArea"] = row[6]										# G  Coverage area
		repeater["freqOut"]      = float(row[2])								# C  Output frequency
		repeater["freqIn"]       = float(row[3])								# D  Input frequency
		repeater["latitude"]     = float(row[34])								# AI Latitude
		repeater["longitude"]    = float(row[35])								# AJ Longitude
		repeater["sponsor"]      = row[8]										# I  Sponsor
		repeater["url"]          = row[33]										# AH URL

		# Repeater Access codes
		repeater["codes"]["ctcss"]    = row[9]									# J  CTCSS In
		repeater["codes"]["ctcssOut"] = row[10]									# K  CTCSS Out
		repeater["codes"]["dcs"]      = row[11]									# J  DCS
		repeater["codes"]["dmrCC"]    = row[19]									# T  DMR Color Code
		repeater["codes"]["ysfDSC"]   = row[21]									# V  YSF digital squelch code
		repeater["codes"]["p25NAC"]   = row[24]									# Y  P25 NAC
		repeater["codes"]["nxdnRAN"]  = row[27]									# AB NXDN NAC

		# Repeater Modes
		repeater["modes"]["WFM"]      = True if row[14] == 'Y' else False		# O  Wide FM
		repeater["modes"]["NFM"]      = True if row[15] == 'Y' else False		# P  Narrow FM
		repeater["modes"]["DSTAR_DV"] = True if row[16] == 'Y' else False		# Q  D-Star Digital Voice
		repeater["modes"]["DSTAR_DD"] = True if row[17] == 'Y' else False		# R  D-Star Digital Data
		repeater["modes"]["DMR"]      = True if row[18] == 'Y' else False		# S  DMR
		repeater["modes"]["YSF"]      = True if row[20] == 'Y' else False		# U  Yaesu System Fusion
		repeater["modes"]["P25"]      = True if row[22] == 'Y' else False		# W  P25 Phase 1
		repeater["modes"]["P25_P2"]   = True if row[23] == 'Y' else False		# X  P25 Phase 2
		repeater["modes"]["NXDN"]     = True if row[25] == 'Y' else False		# Z  NXDN Digital
		repeater["modes"]["NXDN_MIX"] = True if row[26] == 'Y' else False		# AA NXDN Mixed
		repeater["modes"]["ATV"]      = True if row[28] == 'Y' else False		# AC Amateur TV
		repeater["modes"]["DATV"]     = True if row[29] == 'Y' else False		# AD Digital Amateur TV

		# Make a string with all of the supported modes
		getModes(repeater)

		# Make a string with all the codes
		getCodes(repeater)

		# Get the offset type and band
		getOffset(repeater)

		# Add the repeater to the kml document
		addRepeater(repeater, folders)

	# Close file if not reading from stdin
	if (csvFilename != "-"):
		csvFile.close()

def getModes(repeater):
	repeater["modeString"] = ""

	# Make a string with all of the supported modes
	nModes = 0
	if (repeater["modes"]["WFM"]):
		repeater["modeString"] = "WFM"
		nModes+=1

	if (repeater["modes"]["NFM"]):
		repeater["modeString"] += " / NFM" if nModes else "NFM"
		nModes+=1

	if (repeater["modes"]["DSTAR_DV"]):
		repeater["modeString"] += " / D-Star" if nModes else "D-Star"
		nModes+=1

	if (repeater["modes"]["DSTAR_DD"]):
		repeater["modeString"] += " / D-Star DD" if nModes else "D-Star Digital Data"
		nModes+=1

	if (repeater["modes"]["DMR"]):
		repeater["modeString"] += " / DMR" if nModes else "DMR"
		nModes+=1

	if (repeater["modes"]["YSF"]):
		repeater["modeString"] += " / YSF" if nModes else "YSF"
		nModes+=1

	if (repeater["modes"]["P25"]):
		repeater["modeString"] += " / P25" if nModes else "P25"
		nModes+=1

	if (repeater["modes"]["P25_P2"]):
		repeater["modeString"] += " / P25 Phase 2" if nModes else "P25 Phase 2"
		nModes+=1

	if (repeater["modes"]["NXDN"]):
		repeater["modeString"] += " / NXDN" if nModes else "NXDN"
		nModes+=1

	if (repeater["modes"]["ATV"]):
		repeater["modeString"] += " / Analog TV" if nModes else "Analog TV"
		nModes+=1

	if (repeater["modes"]["DATV"]):
		repeater["modeString"] += " / Digital TV" if nModes else "Digital TV"
		nModes+=1

def getCodes(repeater):
	# Make a string with all the codes
	nCodes = 0
	ctcssTx = repeater["codes"]["ctcss"]
	ctcssRx = repeater["codes"]["ctcssOut"]
	dcs     = repeater["codes"]["dcs"]
	cc      = repeater["codes"]["dmrCC"]
	dsc     = repeater["codes"]["ysfDSC"]
	nac     = repeater["codes"]["p25NAC"]
	ran     = repeater["codes"]["nxdnRAN"]

	repeater["code"] = ""

	if (ctcssTx != ''):
		repeater["code"] = ctcssTx
		nCodes += 1

	if (ctcssRx != ''):
		repeater["code"] += "/" + ctcssRx if nCodes else ctcssRx
		nCodes += 1

	if (dcs != ''):
		repeater["code"] += " / DCS: " + dcs if nCodes else "DCS: " + dcs
		nCodes += 1

	if (cc != ''):
		repeater["code"] += " / " + cc if nCodes else cc
		nCodes += 1

	if (dsc != ''):
		repeater["code"] += " / DSC: " + dsc if nCodes else "DSC: " + dsc
		nCodes += 1

	if (nac != ''):
		repeater["code"] += " / NAC: " + nac if nCodes else "NAC: " + nac
		nCodes += 1

	if (ran != ''):
		repeater["code"] += " / RAN: " + ran if nCodes else "RAN: " + ran

def getOffset(repeater):
	#  Get the repeater offset in KHz
	repeater["offset"] = int(repeater["freqIn"]*1000)-int(repeater["freqOut"]*1000)

	# Get the offset type and band

	# 10 Meter
	if (repeater["freqOut"] >= 28.0 and repeater["freqOut"] <= 29.7):
		repeater["band"] = 0
		if (repeater["offset"] == -100):
			repeater["ofsType"] = "-"
		elif (repeater["offset"] == 100):
			repeater["ofsType"] = "+"
		elif (repeater["offset"] == 0):
			repeater["ofsType"] = ""
		else:
			repeater["ofsType"] = " Odd"

	# 6 Meter
	elif (repeater["freqOut"] >= 50.0 and repeater["freqOut"] <= 54.0):
		repeater["band"] = 1
		if (repeater["offset"] == -1700):
			repeater["ofsType"] = "-"
		elif (repeater["offset"] == 1700):
			repeater["ofsType"] = "+"
		elif (repeater["offset"] == 0):
			repeater["ofsType"] = ""
		else:
			repeater["ofsType"] = " Odd"

	# 2 Meter
	elif (repeater["freqOut"] >= 144.0 and repeater["freqOut"] <= 148.0):
		repeater["band"] = 2
		if (repeater["offset"] == -600):
			repeater["ofsType"] = "-"
		elif (repeater["offset"] == 600):
			repeater["ofsType"] = "+"
		elif (repeater["offset"] == 0):
			repeater["ofsType"] = ""
		else:
			repeater["ofsType"] = " Odd"

	# 1.25 Meter
	elif (repeater["freqOut"] >= 222.0 and repeater["freqOut"] <= 225.0):
		repeater["band"] = 3
		if (repeater["offset"] == -1600):
			repeater["ofsType"] = "-"
		elif (repeater["offset"] == 1600):
			repeater["ofsType"] = "+"
		elif (repeater["offset"] == 0):
			repeater["ofsType"] = ""
		else:
			repeater["ofsType"] = " Odd"

	# 70 CM
	elif (repeater["freqOut"] >= 420.0 and repeater["freqOut"] <= 450.0):
		repeater["band"] = 4
		if (repeater["offset"] == -5000):
			repeater["ofsType"] = "-"
		elif (repeater["offset"] == 5000):
			repeater["ofsType"] = "+"
		elif (repeater["offset"] == 0):
			repeater["ofsType"] = ""
		else:
			repeater["ofsType"] = " Odd"

	# 33 CM
	elif (repeater["freqOut"] >= 902.0 and repeater["freqOut"] <= 928.0):
		repeater["band"] = 5
		if (repeater["offset"] == -25000):
			repeater["ofsType"] = "-"
		elif (repeater["offset"] == 25000):
			repeater["ofsType"] = "+"
		elif (repeater["offset"] == 0):
			repeater["ofsType"] = ""
		else:
			repeater["ofsType"] = " Odd"

	# 23 CM
	elif (repeater["freqOut"] >= 1240.0 and repeater["freqOut"] <= 1300.0):
		repeater["band"] = 6
		if (repeater["offset"] == -20000):
			repeater["ofsType"] = "-"
		elif (repeater["offset"] == 20000):
			repeater["ofsType"] = "+"
		elif (repeater["offset"] == 0):
			repeater["ofsType"] = ""
		else:
			repeater["ofsType"] = " Odd"

def createKML(doc, folders):
	bands = ["10M Repeaters", "6M Repeaters", "2M Repeaters", "1.25M Repeaters", "70CM Repeaters", "33CM Repeaters", "23CM Repeaters"]

	# Create the style section
	style      = ET.SubElement(doc,        "Style", id="IDLE")

	iconStyle  = ET.SubElement(style,      "IconStyle")
	scale      = ET.SubElement(iconStyle,  "IconStyle").text = "0.6"
	icon       = ET.SubElement(iconStyle,  "Icon")
	href       = ET.SubElement(icon,       "href").text = "https://www.repeaterbook.com/images/ham/gmapicon.png"

	labelStyle = ET.SubElement(style,      "LabelStyle")
	color      = ET.SubElement(labelStyle, "color").text = "ff00ff00"
	scale      = ET.SubElement(labelStyle, "scale").text = "0.7"
	name       = ET.SubElement(doc,        "name").text = "WWARA Repeaters"
	desc       = ET.SubElement(doc,        "description").text = \
	"Western Washington Repeaters.
Created with rptrlist2kml using the WWARA database"

	# Create folders for each band
	folders.append(ET.SubElement(doc,      "Folder"))
	folders.append(ET.SubElement(doc,      "Folder"))
	folders.append(ET.SubElement(doc,      "Folder"))
	folders.append(ET.SubElement(doc,      "Folder"))
	folders.append(ET.SubElement(doc,      "Folder"))
	folders.append(ET.SubElement(doc,      "Folder"))
	folders.append(ET.SubElement(doc,      "Folder"))

	# Set the folder names
	for i in range(0, 7):
		ET.SubElement(folders[i], "name").text = bands[i]

def addRepeater(r, f):
	# Create the description string
	description  = "{:4.4f}{:1s} {:s}
".format(r["freqOut"], r["ofsType"], r["code"])
	description += "{:s} - {:s}
".format(r["city"].title(), r["coverageArea"].title())
	description += "Modes: {:s}
".format(r["modeString"])
	description += "Offset: {:4.2f} MHz
".format(float(r["offset"])/1000.0)
	if (r["url"] != ""):
		description += "Sponsor: {:s}".format(r["url"], r["sponsor"])
	else:
		description += "Sponsor: {:s}".format(r["sponsor"])

	# Create a new placemark for the repeater
	pm    = ET.SubElement(f[r["band"]], "Placemark")
	name  = ET.SubElement(pm,    "name").text = r["call"]
	style = ET.SubElement(pm,    "styleUrl").text = "IDLE"
	desc  = ET.SubElement(pm,    "description").text = description
	point = ET.SubElement(pm,    "Point")
	coord = ET.SubElement(point, "coordinates").text = "{:f}, {:f}, 0".format(r["longitude"], r["latitude"])

parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description='''\
This program converts the WWARA repeater list to a Google Earth KML file.
The current list can be downloaded from www.wwara.org/DataBaseExtract.zip

If the input file is "-", the input CSV will be read from STDIN.
If no output file is given, the output KML will be written to STDOUT.\
''', epilog='''
Example usage:
rptrlist2kml.py -i WWARA-rptrlist.csv Repeaters.kml''')

parser.add_argument("-i", metavar="Input", required=True, dest="infile", help="CSV Input File")
parser.add_argument("outfile", metavar="Output", nargs="?", help="KML Output File")
args = parser.parse_args()

folders = []																	# Array to hold the folder elements for each band
kml     = ET.Element("kml", xmlns="http://www.opengis.net/kml/2.2")				# Create the root kml element
kmlDoc  = ET.SubElement(kml, "Document")										# Create the document element
tree    = ET.ElementTree(kml)													# Create the element tree

createKML(kmlDoc, folders)														# Create the empty kml document
processCSV(args.infile, folders)												# Process the CSV file and add the repeaters to the kml document

# Write the kml to the output file if set or stdout if no file is given
if (args.outfile is None):
	sys.stdout.write(ET.tostring(kml, encoding="unicode") + "\n")				# Write to stdout
else:
	tree.write(args.outfile)													# Write the tree to the output file


from django.urls import path

from apps.videos import views

urlpatterns = [
    path('upload/',             views.upload_video,         name='upload'),
    path('editVideo/',          views.edit_video,           name='editVideo'),
    path('playVideo/',          views.play_video,           name='playVideo'),

    path('ajax/like/',          views.like_video,           name='like'),
    path('ajax/unlike/',        views.unlike_video,         name='unlike'),

    path('ajax/watchLater/',    views.watch_later,          name='watchLater'),
    path('ajax/unWatchLater/',  views.unwatch_later,        name='unWatchLater'),

    path('ajax/deleteHistory/', views.delete_watch_history, name='deleteHistory'),
    path('ajax/deleteVideo/',   views.delete_video,           name='deleteVideo'),
]