import itertools
import pytest
import logging

from django.urls import reverse
from django.db.models import Q

from tasks.models import Task
from tasks.views import (CREATE_VIEW, LIST_VIEW, UPDATE_VIEW,
                         DELETE_VIEW, DETAIL_VIEW)
from tasks.views import (LIST_TITLE, CREATE_TITLE, DELETE_TITLE,
                         UPDATE_TITLE, DETAIL_TITLE)
from tasks.views import (MESSAGE_UPDATE_SUCCESS, MESSAGE_DELETE_SUCCESS,
                         MESSAGE_CREATE_SUCCESS, DELETE_CONSTRAINT_MESSAGE,
                         QUESTION_DELETE)

logger = logging.getLogger(__name__)

NEW_TASK = {
    "name": "forth task name",
    "description": "forth task description",
    "status": 1,
    "executor": 1,
    "labels": [1, 3]
}

@pytest.mark.django_db
def test_create_get(client, log_user1):
    response = client.get(reverse(CREATE_VIEW))
    content = response.rendered_content
    assert content.find('method="post"') > 0
    assert content.find('name="description"') > 0
    assert content.find('name="name"') > 0
    assert content.find('name="status"') > 0
    assert content.find('name="executor"') > 0
    assert content.find('name="labels"') > 0
    assert content.find(CREATE_TITLE) > 0

@pytest.mark.django_db
@pytest.mark.parametrize('configuration', [
    (reverse(CREATE_VIEW), 1, MESSAGE_CREATE_SUCCESS),
    (reverse(UPDATE_VIEW, kwargs={'pk': 1}), 0, MESSAGE_UPDATE_SUCCESS)])
def test_create_update_task_post(client, log_user1,
                                 setup_tasks, configuration):
    """ in this tests two views are tested : update and create"""
    path, incremental, msg = configuration
    initial_count = Task.objects.all().count()
    response = client.post(path, NEW_TASK)
    created_item = Task.objects.get(name=NEW_TASK['name'])
    assert response.status_code == 302
    assert response.url == reverse(LIST_VIEW)
    assert Task.objects.all().count() == initial_count + incremental
    assert created_item.description == NEW_TASK['description']
    assert created_item.executor.id == NEW_TASK['executor']
    assert created_item.author.id == log_user1.id
    assert created_item.status.id == NEW_TASK['status']
    assigned_labels = list(itertools.chain(
        *created_item.labels.values_list('id')))
    assert assigned_labels == NEW_TASK['labels']
    # force flashing of message
    response = client.get(response.url)
    content = response.rendered_content
    assert content.find(msg)

@pytest.mark.django_db
def test_update_html_tasks(client, log_user1, setup_tasks):
    item = Task.objects.all().first()
    response = client.get(reverse(UPDATE_VIEW,
                                  kwargs={'pk': item.id}))
    assert response.status_code == 200
    content = response.rendered_content
    assert content.find('method="post"') > 0
    assert content.find('name="name"') > 0
    assert content.find(UPDATE_TITLE) > 0
    assert content.find(item.name) > 0

@pytest.mark.django_db
@pytest.mark.parametrize('test_string',
                         ['name', 'author__first_name', 'author__last_name',
                          'executor__first_name', 'executor__last_name',
                          'status__name'])
def test_view_tasks(client, log_user1, setup_tasks, test_string, filter_data):
    get_request_args, q = filter_data
    response = client.get(reverse(LIST_VIEW), get_request_args)
    content = response.rendered_content
    lines = content.count('</tr')
    lines_expected = Task.objects.all().filter(Q(**q)).count()
    assert lines == lines_expected
    assert content.find(LIST_TITLE) > 0
    names = Task.objects.filter(Q(**q)).values_list(test_string).all()
    inclusions = list(map(lambda x: content.find(str(*x)) > 0, names))
    assert all(inclusions)
    assert content.find(reverse(CREATE_VIEW)) > 0

@pytest.mark.django_db
def test_delete_html_task(
        client, log_user1, setup_tasks):
    item = Task.objects.all().first()
    response = client.get(reverse(DELETE_VIEW,
                                  kwargs={'pk': item.id}))
    assert response.status_code == 200
    content = response.rendered_content
    assert content.find('method="post"') > 0
    assert content.find(QUESTION_DELETE) > 0
    assert content.find(DELETE_TITLE) > 0
    assert content.find(item.name) > 0

@pytest.mark.django_db
def test_delete_own_task(client, log_user1, setup_tasks):
    count_before = Task.objects.all().count()
    item = Task.objects.all().first()
    response = client.post(reverse(DELETE_VIEW,
                                   kwargs={'pk': item.id}))
    assert response.status_code == 302
    assert response.url == reverse(LIST_VIEW)
    with pytest.raises(Exception) as e:
        Task.objects.get(id=item.id)
    assert e.match('matching query does not exist')
    count_after = Task.objects.all().count()
    assert count_after == count_before - 1
    # force flashing of message
    response = client.get(response.url)
    content = response.rendered_content
    assert content.find(MESSAGE_DELETE_SUCCESS)

@pytest.mark.django_db
def test_delete_not_own_task(client, log_user1, setup_tasks):
    count_before = Task.objects.all().count()
    item = Task.objects.exclude(author=log_user1.id).first()
    response = client.post(reverse(DELETE_VIEW,
                                   kwargs={'pk': item.id}))
    assert response.status_code == 302
    assert response.url == reverse(LIST_VIEW)
    assert Task.objects.get(id=item.id)
    count_after = Task.objects.all().count()
    assert count_after == count_before
    # force to flash message
    response = client.get(response.url)
    content = response.rendered_content
    assert content.find(DELETE_CONSTRAINT_MESSAGE) > 0

@pytest.mark.django_db
def test_detail_view_task(client, log_user1, setup_tasks):
    item = Task.objects.get(id=1)
    response = client.get(reverse(DETAIL_VIEW,
                                  kwargs={'pk': 1}))
    assert response.status_code == 200
    content = response.rendered_content
    assert content.find(DETAIL_TITLE) > 0
    assert content.find(item.name) > 0
    assert content.find(item.description) > 0
    assert content.find(item.author.get_full_name()) > 0
    assert content.find(item.executor.get_full_name()) > 0
    assert content.find(item.status.name) > 0
    labels = list(itertools.chain(
        *item.labels.values_list('name')))
    inclusions = list(map(lambda x: content.find(str(x)) > 0, labels))
    assert all(inclusions)
    assert content.find(reverse(DELETE_VIEW, kwargs={'pk': 1})) > 0
    assert content.find(reverse(UPDATE_VIEW, kwargs={'pk': 1})) > 0


#!/usr/bin/env python
# -*- coding: utf-8 -*-
from gtts import gTTS
from playsound import playsound
import os
from datetime import datetime
from PyDictionary import PyDictionary
from nltk.corpus import wordnet

now_UTC_hr = datetime.utcnow().hour # Get the UTC time
print('The UTC Time is ', datetime.utcnow())
dictionary=PyDictionary()
language = 'en'

path_of_file = 'C:/Users/khushal/Pictures/temp.txt'
file = open(path_of_file,'w')

def gratitude_wish(word,language):
    print(word)
    myobj = gTTS(text=word, lang=language, slow=False)
    # Saving the converted audio in a mp3 file named
    path_of_file_tst = 'C:/Users/khushal/Documents/Python Scripts/gratiude.mp3'
    # Saving the converted audio in a mp3 file named
    myobj.save(path_of_file_tst)
    # Playing the converted file
    if os.path.exists(path_of_file_tst):
        playsound(path_of_file_tst)
        os.remove(path_of_file_tst)
    else:
        print("The file does not exist")

def gratiude_language(language):
    if now_UTC_hr >= 4 and now_UTC_hr < 12:
        print("It's time to say, Good Morning")
        gratiude = 'Good Morning'
        gratitude_wish(gratiude, language)
    elif now_UTC_hr >= 12 and now_UTC_hr < 17:
        print("It's time to say, Good Afternoon")
        gratiude = 'Good Afternoon'
        gratitude_wish(gratiude, language)
    elif now_UTC_hr >= 17 and now_UTC_hr <= 21:
        print("It's time to say, Good Evening")
        gratiude = 'Good Evening'
        gratitude_wish(gratiude, language)
    elif now_UTC_hr > 21:
        print("It's time to sleep, Good Night")
        gratiude = 'Good Night'
        gratitude_wish(gratiude, language)

gratiude_language(language)

synonyms = []
antonyms = []

#keyword_for_synonyms_antonyms = input("Enter the keyword for in which you want synonyms & antonyms = \n")
keyword_for_synonyms_antonyms = "bring"

def word_for_synonyms_antonyms(keyword_for_synonyms_antonyms):
    print('keyword_for_synonyms_antonyms := ', keyword_for_synonyms_antonyms)
    #to get synonyms and antonyms
    for syn in wordnet.synsets(keyword_for_synonyms_antonyms):
        for l in syn.lemmas():
            synonyms.append(l.name())
            if l.antonyms():
                antonyms.append(l.antonyms()[0].name())

    #print(set(synonyms))
    synonyms_words =set(synonyms)
    synonyms_words_dict = dict()
    pos_l1 = set()
    for words in synonyms_words:
        for tmp in wordnet.synsets(words):
            if tmp.name().split('.')[0] == words:
                pos_l1.add(tmp.pos())
        synonyms_words_dict[words] = pos_l1
    #print(set(antonyms))
    antonyms_words =set(antonyms)
    antonyms_words_dict = dict()
    pos_l2 = set()
    for words in antonyms_words:
        for tmp in wordnet.synsets(words):
            if tmp.name().split('.')[0] == words:
                pos_l2.add(tmp.pos())
        antonyms_words_dict[words] = pos_l2

    return synonyms_words_dict,antonyms_words_dict

w = keyword_for_synonyms_antonyms
pos_all = dict()
pos_l = set()
for tmp in wordnet.synsets(w):
    if tmp.name().split('.')[0] == w:
        pos_l.add(tmp.pos())
pos_all[w] = pos_l

output_synonyms_words,output_antonyms_words = word_for_synonyms_antonyms(keyword_for_synonyms_antonyms)
print('output_synonyms_words = ',output_synonyms_words,'\noutput_antonyms_words = ', output_antonyms_words)

# using Pydictionary module
def word_with_meaning(word):
    meaning_of_word = dictionary.meaning(keyword_for_synonyms_antonyms)
    print(meaning_of_word.keys())
    meaning_of_word_google = dictionary.googlemeaning(keyword_for_synonyms_antonyms)
    print(meaning_of_word_google)
    for key in list(meaning_of_word.keys()):
        if key == 'Noun':
            meaning_of_word_Noun = meaning_of_word['Noun']
            return meaning_of_word_Noun, meaning_of_word_google
            break
            # print("Noun Meaning", meaning_of_word_Noun)
        elif key == 'Verb':
            meaning_of_word_Verb = meaning_of_word['Verb']
            return meaning_of_word_Verb, meaning_of_word_google
            break
            # print("Verb meaning", meaning_of_word_Verb)

meaning_of_word_Output,meaning_of_word_From_google = word_with_meaning(keyword_for_synonyms_antonyms)

def audible_meaning_of_word(value,word):
    if value.upper() == 'Y':
        print('-'*60)
        print('Listen it carefully !!')
        i =0
        for values in word:
            print(values)
            myobj = gTTS(text=values, lang=language, slow=False)
            i +=1
            # Saving the converted audio in a mp3 file named
            path_of_file_tst = 'C:/Users/khushal/Documents/Python Scripts/word_meaning' + str(i) + '.mp3'
            # Saving the converted audio in a mp3 file named
            myobj.save(path_of_file_tst)
            # Playing the converted file
            if os.path.exists(path_of_file_tst):
                playsound(path_of_file_tst)
                os.remove(path_of_file_tst)
            else:
                print("The file does not exist")

    elif value.upper() == 'N':
        print('-'*60)
        print('Displaying the result !!')
        for values in word:
            print(values)
        pass
    else:
        print("You've entered the incorrect value")
word_meaning = list(meaning_of_word_Output)
switch = 'y'
audible_meaning_of_word(switch,word_meaning)
switch = 'n'
audible_meaning_of_word(switch,word_meaning)
file.close()


import scipy.stats

### Starter code for Homework 2, problem 7 ###

#Our true mean function: will be sin(x/2) on [0,4*pi] and sin(6*x) on [4*pi,8*pi]
def mu(x):
  #Initialize a vector of zeros
  y = np.zeros(len(x))
  #Figure out which points are to the left or right of 4*pi
  left_points = (x<=4*np.pi)
  right_points = (x>4*np.pi)
  #Assign the appropriate sine values
  y[left_points] = np.sin(x[left_points]/2.0)
  y[right_points] = np.sin(6*x[right_points])
  #Return y
  return(y)

#A function to draw a sample from this curve
def generate_sample(n):
  #Sample the x coordinates uniformly on [0,8*pi].
  #We sort the x here to make plotting easier later.
  x = np.random.uniform(low=0, high=8*np.pi, size=n)
  x.sort()

  #Sample the y coordinates as gaussians around mu(x)
  y = mu(x) + np.random.normal(loc=0, scale=0.2, size=n)
  #Bind this all together into a pandas data frame
  return(pd.DataFrame({'x':x, 'y':y}))
  #you can access like df['x'], df['y'], among many other ways

#We set the seed so that your homeworks will match
scipy.random.seed(7)
#Sample 300 points.  This is your data set!
data = generate_sample(500)


from typing import Dict, List, Optional, Tuple, Type, Union

from autoconf import cached_property

import autoarray as aa
import autogalaxy as ag

from autoarray.inversion.inversion.factory import inversion_unpacked_from

from autolens.analysis.preloads import Preloads

class TracerToInversion(ag.AbstractToInversion):
    def __init__(
        self,
        tracer,
        dataset: Optional[Union[aa.Imaging, aa.Interferometer]] = None,
        data: Optional[Union[aa.Array2D, aa.Visibilities]] = None,
        noise_map: Optional[Union[aa.Array2D, aa.VisibilitiesNoiseMap]] = None,
        w_tilde: Optional[Union[aa.WTildeImaging, aa.WTildeInterferometer]] = None,
        settings_pixelization=aa.SettingsPixelization(),
        settings_inversion: aa.SettingsInversion = aa.SettingsInversion(),
        preloads=Preloads(),
        run_time_dict: Optional[Dict] = None,
    ):
        self.tracer = tracer

        super().__init__(
            dataset=dataset,
            data=data,
            noise_map=noise_map,
            w_tilde=w_tilde,
            settings_pixelization=settings_pixelization,
            settings_inversion=settings_inversion,
            preloads=preloads,
            run_time_dict=run_time_dict,
        )

    @property
    def planes(self):
        return self.tracer.planes

    @cached_property
    @aa.profile_func
    def traced_grid_2d_list_of_inversion(self) -> List[aa.type.Grid2DLike]:
        return self.tracer.traced_grid_2d_list_from(grid=self.dataset.grid_pixelization)

    @cached_property
    def lp_linear_func_list_galaxy_dict(
        self,
    ) -> Dict[ag.LightProfileLinearObjFuncList, ag.Galaxy]:
        if not self.tracer.perform_inversion:
            return {}

        lp_linear_galaxy_dict_list = {}

        traced_grids_of_planes_list = self.tracer.traced_grid_2d_list_from(
            grid=self.dataset.grid
        )

        if self.dataset.blurring_grid is not None:
            traced_blurring_grids_of_planes_list = self.tracer.traced_grid_2d_list_from(
                grid=self.dataset.blurring_grid
            )
        else:
            traced_blurring_grids_of_planes_list = [None] * len(
                traced_grids_of_planes_list
            )

        for plane_index, plane in enumerate(self.planes):
            plane_to_inversion = ag.PlaneToInversion(
                plane=plane,
                dataset=self.dataset,
                grid=traced_grids_of_planes_list[plane_index],
                blurring_grid=traced_blurring_grids_of_planes_list[plane_index],
                noise_map=self.noise_map,
            )

            lp_linear_galaxy_dict_of_plane = (
                plane_to_inversion.lp_linear_func_list_galaxy_dict
            )

            lp_linear_galaxy_dict_list = {
                **lp_linear_galaxy_dict_list,
                **lp_linear_galaxy_dict_of_plane,
            }

        return lp_linear_galaxy_dict_list

    def cls_pg_list_from(self, cls: Type) -> List:
        return [plane.cls_list_from(cls=cls) for plane in self.planes]

    @cached_property
    def adapt_galaxy_image_pg_list(self) -> List:
        return [
            plane.adapt_galaxies_with_pixelization_image_list for plane in self.planes
        ]

    @cached_property
    @aa.profile_func
    def sparse_image_plane_grid_pg_list(self) -> List[List]:
        """
        Specific pixelizations, like the `VoronoiMagnification`, begin by determining what will become its the
        source-pixel centres by calculating them  in the image-plane. The `VoronoiBrightnessImage` pixelization
        performs a KMeans clustering.
        """

        sparse_image_plane_grid_list_of_planes = []

        for plane in self.planes:
            plane_to_inversion = ag.PlaneToInversion(
                plane=plane,
                grid_pixelization=self.dataset.grid,
                settings_pixelization=self.settings_pixelization,
                noise_map=self.noise_map,
            )

            sparse_image_plane_grid_list = (
                plane_to_inversion.sparse_image_plane_grid_list
            )
            sparse_image_plane_grid_list_of_planes.append(sparse_image_plane_grid_list)

        return sparse_image_plane_grid_list_of_planes

    @cached_property
    @aa.profile_func
    def traced_sparse_grid_pg_list(self) -> Tuple[List[List], List[List]]:
        """
        Ray-trace the sparse image plane grid used to define the source-pixel centres by calculating the deflection
        angles at (y,x) coordinate on the grid from the galaxy mass profiles and then ray-trace them from the
        image-plane to the source plane.
        """
        if (
            self.preloads.sparse_image_plane_grid_pg_list is None
            or self.settings_pixelization.is_stochastic
        ):
            sparse_image_plane_grid_pg_list = self.sparse_image_plane_grid_pg_list

        else:
            sparse_image_plane_grid_pg_list = (
                self.preloads.sparse_image_plane_grid_pg_list
            )

        traced_sparse_grid_pg_list = []

        for plane_index, plane in enumerate(self.planes):
            if sparse_image_plane_grid_pg_list[plane_index] is None:
                traced_sparse_grid_pg_list.append(None)
            else:
                traced_sparse_grids_list = []

                for sparse_image_plane_grid in sparse_image_plane_grid_pg_list[
                    plane_index
                ]:
                    try:
                        traced_sparse_grids_list.append(
                            self.tracer.traced_grid_2d_list_from(
                                grid=sparse_image_plane_grid
                            )[plane_index]
                        )
                    except AttributeError:
                        traced_sparse_grids_list.append(None)

                traced_sparse_grid_pg_list.append(traced_sparse_grids_list)

        return traced_sparse_grid_pg_list, sparse_image_plane_grid_pg_list

    @cached_property
    def mapper_galaxy_dict(self) -> Dict[aa.AbstractMapper, ag.Galaxy]:
        mapper_galaxy_dict = {}

        if self.preloads.traced_grids_of_planes_for_inversion is None:
            traced_grids_of_planes_list = self.traced_grid_2d_list_of_inversion
        else:
            traced_grids_of_planes_list = (
                self.preloads.traced_grids_of_planes_for_inversion
            )

        if self.preloads.traced_sparse_grids_list_of_planes is None:
            (
                traced_sparse_grids_list_of_planes,
                sparse_image_plane_grid_list,
            ) = self.traced_sparse_grid_pg_list
        else:
            traced_sparse_grids_list_of_planes = (
                self.preloads.traced_sparse_grids_list_of_planes
            )
            sparse_image_plane_grid_list = self.preloads.sparse_image_plane_grid_list

        for plane_index, plane in enumerate(self.planes):
            if plane.has(cls=aa.Pixelization):
                plane_to_inversion = ag.PlaneToInversion(
                    plane=plane,
                    grid_pixelization=traced_grids_of_planes_list[plane_index],
                    settings_pixelization=self.settings_pixelization,
                    preloads=self.preloads,
                    noise_map=self.noise_map,
                )

                galaxies_with_pixelization_list = plane.galaxies_with_cls_list_from(
                    cls=aa.Pixelization
                )

                for mapper_index in range(
                    len(traced_sparse_grids_list_of_planes[plane_index])
                ):
                    pixelization_list = self.cls_pg_list_from(cls=aa.Pixelization)

                    mapper = plane_to_inversion.mapper_from(
                        mesh=pixelization_list[plane_index][mapper_index].mesh,
                        regularization=pixelization_list[plane_index][
                            mapper_index
                        ].regularization,
                        source_plane_mesh_grid=traced_sparse_grids_list_of_planes[
                            plane_index
                        ][mapper_index],
                        image_plane_mesh_grid=sparse_image_plane_grid_list[plane_index][
                            mapper_index
                        ],
                        adapt_galaxy_image=self.adapt_galaxy_image_pg_list[plane_index][
                            mapper_index
                        ],
                    )

                    galaxy = galaxies_with_pixelization_list[mapper_index]

                    mapper_galaxy_dict[mapper] = galaxy

        return mapper_galaxy_dict

    @cached_property
    def inversion(self):
        inversion = inversion_unpacked_from(
            dataset=self.dataset,
            data=self.data,
            noise_map=self.noise_map,
            w_tilde=self.w_tilde,
            linear_obj_list=self.linear_obj_list,
            settings=self.settings_inversion,
            preloads=self.preloads,
            run_time_dict=self.tracer.run_time_dict,
        )

        inversion.linear_obj_galaxy_dict = self.linear_obj_galaxy_dict

        return inversion


import sqlite3
import requests
import datetime
from bs4 import BeautifulSoup

try:

    URL = 'https://www.crosswalk.com/devotionals/everydaylight/'
    page = requests.get(URL)

    soup = BeautifulSoup(page.content, 'html.parser')
    content = soup.find('div', id='content')
    content1 = content.find('div', class_="articleContentBody")

    divs = content1.find_all('div')
    strongs = content1.find_all('strong')

    reading_and_meditation = content1.find('font', class_="headSub")
    related = reading_and_meditation.find_next_siblings()

    main_scripture = related[0].text  # main scriptural reference
    verse = related[2].text  # focus verse

    day = strongs[0].text
    title = strongs[1].text
    reading = divs[0].text.lstrip()
    prayer = divs[3].text.lstrip()

    other_references = ""
    for tags in divs[0].find_next_siblings():
        ass = tags.find_all('a')
        for yas in ass:
            other_references = other_references + yas.get_text() + ". "

    todays_reading = {
        'day': day,
        'main': main_scripture,
        'focus': verse,
        'topic': title,
        'reference': other_references,
        'reading': reading,
        'prayer': prayer
    }

    postURI = 'http://localhost:3030/add-today'
    response = requests.post(postURI, json=todays_reading)

    r = response.json()
    console.log(r)

except:
    print("Error while creating sqlite table")

finally:
    print("Finally")


#!/usr/bin/env python3
# Author: Armit
# Create Time: 2022/11/06

import os
from argparse import ArgumentParser
from collections import Counter

import torch
import torch.nn as nn
from torch.nn.parameter import Parameter
try:
  from sklearnex import patch_sklearn
  patch_sklearn()
except:
  print('cannot import sklearnex, if you have Intel CPU, do `pip install scikit-learn-intelex` for calculation acceleration')
from sklearn.cluster import KMeans
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from model import MODELS, get_model
from util import frac_to_str

stats = {
  # 'layer_name': ((n_kernel_original, n_kernel_clustered), (L0, L1, L2, Linf))
}

def optimal_number_of_clusters(wcss, n_clust_min, n_clust_max, step=1):
  x1, y1 = n_clust_min, wcss[0]
  x2, y2 = n_clust_max, wcss[len(wcss)-1]

  distances = []
  for i in range(len(wcss)):
    x0 = i+n_clust_min
    y0 = wcss[i]
    numerator = np.abs((y2-y1)*x0 - (x2-x1)*y0 + x2*y1 - y2*x1)
    denominator = np.sqrt((y2 - y1)**2 + (x2 - x1)**2)
    distances.append(numerator/denominator)

  return distances.index(max(distances)) * step + n_clust_min

@torch.no_grad()
def cluster_kernels(name:str, layer:nn.Conv2d, args):
  print(f'[cluster_kernels] {name}')

  weight = layer.weight                             # [C_o, C_i, K_h, K_w]
  C_out, C_in, K_h, K_w = weight.shape

  data = weight.flatten(start_dim=1).cpu().numpy()  # [C_o, C_i*K_h*K_w], vectorize

  # reduce by fixed ratio
  if args.method == 'fixed':
    n_clust = round(C_out * args.fixed)

  # reduce by inertia limit
  if args.method == 'inertia':
    for n_clust in range(C_out-1, C_out//2, -1):
      model = KMeans(n_clust)
      model.fit(data)
      inertia = model.inertia_
      del model
      print(f'   n_clust: {n_clust}, inertia: {inertia}')
      if inertia > args.inertia: break

    n_clust = n_clust + 1

  # reduce by optimal `wcss` metric
  if args.method == 'wcss':
    n_clust_min, n_clust_max = round(C_out * args.wcss_from), round(C_out * args.wcss_to)
    rng = n_clust_max - n_clust_min + 1
    step = max(1, round(np.log2(rng) - 3))

    wcss = []
    for n_clust in range(n_clust_min, n_clust_max, step):
      model = KMeans(n_clust)
      model.fit(data)
      print(f'   n_clust: {n_clust}, inertia: {model.inertia_}')
      wcss.append(model.inertia_)
      del model

    if args.show: plt.plot(wcss) ; plt.title('wcss') ; plt.show()

    n_clust = optimal_number_of_clusters(wcss, n_clust_min, n_clust_max)

  model = KMeans(n_clust)
  pred = model.fit_predict(data).tolist()
  centroids = model.cluster_centers_
  print(f'decision: n_clust={model.n_clusters}, inertia={model.inertia_}')

  if args.show:
    plt.subplot(211) ; plt.title('hist') ; plt.hist(pred, bins=n_clust)
    plt.subplot(212) ; plt.title('freq') ; plt.plot(sorted(Counter(pred).values(), reverse=True))
    plt.show()

    distmat = np.abs(centroids[None, :, :] - centroids[:, None, :]).mean(axis=-1)
    sns.heatmap(distmat)
    plt.title('dist matrix')
    plt.show()

  # update kernels
  kernel_prototypes = centroids.reshape([-1, C_in, K_h, K_w])   # de-vectorize
  weight_prototypes = torch.from_numpy(kernel_prototypes[pred])
  if 'repalce with centroids':
    new_weight = weight_prototypes
  if not 'step away from centroids':
    d_w = weight - weight_prototypes
    new_weight = weight + d_w * 0.1
  layer.weight = Parameter(new_weight, requires_grad=True)

  # calc states
  d_weight = new_weight - weight
  d_weight_abs = d_weight.abs()
  n_param = weight.numel()

  L0   = (d_weight != 0).sum() / n_param
  L1   = d_weight_abs.sum() / n_param
  L2   = d_weight.square().sum().sqrt() / n_param
  Linf = d_weight_abs.max()

  stats[name] = (
    (C_out, n_clust),
    (L0, L1, L2, Linf),
  )

def prune(args):
  print(f'>> loading pretrained {args.model}')
  model = get_model(args.model).eval()

  for name, mod in model.named_modules():
    if isinstance(mod, nn.Conv2d):
      cluster_kernels(name, mod, args)
      if args.only_first_layer: break

  fp = os.path.join(args.out_path, f'{args.name}.pth')
  print(f'>> saving weights to {fp}')
  torch.save(model.state_dict(), fp)

  fp = os.path.join(args.out_path, f'{args.name}.txt')
  print(f'>> saving stats to {fp}')
  with open(fp, 'w', encoding='utf-8') as fh:
    for k, v in stats.items():
      lines = [
        f'[{k}] {v[0][0]} => {v[0][1]}',
        f'   L0:   {v[1][0]}',
        f'   L1:   {v[1][1]}',
        f'   L2:   {v[1][2]}',
        f'   Linf: {v[1][3]}',
      ]
      log = '\n'.join(lines)
      fh.write(log) ; fh.write('\n')
      print(log)

if __name__ == '__main__':
  parser = ArgumentParser()
  parser.add_argument('-M', '--model', default='resnet18', choices=MODELS)
  parser.add_argument('--method', default='fixed', choices=['fixed', 'wcss', 'inertia'])
  parser.add_argument('--fixed',     default=0.9,  type=float, help='reduction ratio in range (0, 1)')
  parser.add_argument('--wcss_from', default=0.5,  type=float, help='reduction ratio in range (0, 1)')
  parser.add_argument('--wcss_to',   default=0.75, type=float, help='reduction ratio in range (0, 1)')
  parser.add_argument('--inertia',   default=2.0, type=float,  help='cluster inertia limit')

  parser.add_argument('--only_first_layer', action='store_true')

  parser.add_argument('--show', action='store_true')
  parser.add_argument('--overwrite', action='store_true')
  parser.add_argument('--data_path', default='data')
  parser.add_argument('--out_path', default='out')
  args = parser.parse_args()

  os.makedirs(args.data_path, exist_ok=True)
  os.makedirs(args.out_path, exist_ok=True)

  if args.method == 'fixed':
    suffix = f'_fixed={frac_to_str(args.fixed)}'
  if args.method == 'wcss':
    suffix = f'_wcss={frac_to_str(args.wcss_from)}~{frac_to_str(args.wcss_to)}'
  if args.method == 'inertia':
    suffix = f'_inertia={frac_to_str(args.inertia)}'
  suffix += '_ofl' if args.only_first_layer else ''
  args.name = f'{args.model}{suffix}'

  fp = os.path.join(args.out_path, f'{args.name}.pth')
  if not args.overwrite and os.path.exists(fp):
    print(f'safely ignore {args.name} due to file exists: {fp}')
    exit(0)

  prune(args)


# -*- coding: utf-8 -*-
'''
Created on 2012/07/25
@author: YuK_Ota
'''
import numpy
import pandas  # @UnresolvedImport

class BikeScore(object):
    '''
    compute BikeScore and xPower
    '''

    def __init__(self, dataset, cp):
        '''
        Constructor
        dataset=[(datetime.datetime,power)]
        cp CriticalPower
        '''
        self.dataSet = pandas.Series(dataset)
        self.cp = cp
        #Series型に変換する
        sirializeData = dict([(datum[0], datum[1]) for datum in dataset])
        date = sorted(sirializeData.keys())
        power = [sirializeData[key] for key in date]

        self.timePower = pandas.Series(power, index=date)

        (self.smoothTimePower, self.period) = \
            self._ewmaOfTimePower(self.timePower)

        self.xPower = self._computeXPower()
        self.RI = self._computeRelativeIntensity()
        self.normalizedWork = self._computeNormalizedWork()
        self.bikeScore = self._computeBikeScore()

    def _ewmaOfTimePower(self, time_power):
        '''
        calculate ewma of time_power
        時系列区間N=25s
        return ewmaを適用したSeries, 計測時間
        '''
        #時系列間隔を1sごとに調整
        replot = time_power.asfreq('1S', method='pad')
        smoothTimePower = pandas.ewma(replot, span=25)
        return smoothTimePower, len(replot)

    def _computeXPower(self):
        '''
        xPowerを計算する
        1.smoothTimePowerの4乗を取得する
        2.4乗の平均をとる
        3.平均値の4乗根を取る:
        '''
        fourthMean = numpy.array([i ** 4 for i in self.smoothTimePower]).mean()
        xPower = fourthMean ** (1.0 / 4.0)
        return xPower

    def getXPower(self):
        return self.xPower

    def _computeRelativeIntensity(self):
        '''
        RI = xPower/ CriticalPower
        '''
        return self.xPower / self.cp

    def _computeNormalizedWork(self):
        '''
        7.Multiply the xPower by the duration of the workout
        in seconds to obtain a Multiply the xPower
        by the duration of the workout in seconds to obtain a
        “normalized work” value in joules.
        workout時間にxPowerを掛ける
        '''
        return self.xPower * self.period

    def _computeBikeScore(self):
        '''
        9. Divide the values from step 8 by the amount
        of work performed during an hour at Critical Power.
        10. Multiply the number from step 9
        by 100 to obtain the final BikeScore.
        '''
        rawBikeScore = self.normalizedWork * self.RI
        amountTime = self.period / 60
        hourPower = rawBikeScore / amountTime
        bikeScore = hourPower / 100
        return bikeScore

    def getBikeScore(self):
        return self.bikeScore

import scipy.optimize

class CriticalPower(object):
    def __init__(self, dataset):
        '''
        dataset = [(sec,work J)]
        tuple need more than 2.
        compute CriticalPower
        '''
        seconds = numpy.array([datum[0] for datum in dataset])
        works = numpy.array([datum[1] for datum in dataset])

        fitfunc = lambda p, x: p[0] * x + p[1]
        errfunc = lambda p, x, y: fitfunc(p, x) - y
        p0 = [0, 0]
        self._p1, success = \
            scipy.optimize.leastsq(errfunc, p0, args=(seconds, works))
        if success == False:
            raise ArithmeticError

    def getCP(self):
        '''
        Return CriticalPower
        '''
        return self._p1[0]


import sqlite3 as lite

# TODO pr save event... ce ni subjecta, vrni neko napako al neki

# prejsnja verzija:
#(ID,d,m,y,subj,desc,h:m,notify,weekday,repeat,repDays,repUntil,show)
# se mi zdi
################################################################
def create_events():
    # Options.db file must not exist!
    con = lite.connect('Events.db')
    with con:
        cur = con.cursor()
        # dateChanged    - "YYYY-MM-DD HH:MM:SS"  datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        # repeat         - one of [none,daily, weekly, monthly, anualy, custom]
        # repeatWeekdays - tuple containing weekday numbers eg. "(1,3,4)"
        # repeatUntil    - tuple "(yyyy,mm,dd)"
        # show           - boolean
        # notify         - boolean
        cur.execute('''CREATE TABLE Events(Id INTEGER PRIMARY KEY,
                       dateChanged TEXT,
                       subject TEXT,
                       description TEXT,
                       year INTEGER,
                       month INTEGER,
                       day INTEGER,
                       h_m TEXT,
                       repeat TEXT,
                       repeatWeekdays TEXT,
                       repeatUntil TEXT,
                       show INTEGER,
                       notify INTEGER)''')

def save_event(dateChanged,subject,description,year,month,day,h_m,repeat='None',repeatWeekdays='()',repeatUntil='(,,)',show=1,notify=0):
##    print dateChanged,subject,year,month,day,h_m
    if subject == '':
        print('No subject!')
        return 0
    con = lite.connect('Events.db')
    with con:
        cur = con.cursor()
        cur.execute('SELECT * FROM Events WHERE year='+str(year)+' AND month='+str(month)+' AND day= '+str(day)+' AND h_m="'+str(h_m)+'" AND subject="'+subject+'"')
        test = cur.fetchall()
        if test: return 0 # event ze obstaja, zato ne shranimo nic
        cur.execute('INSERT INTO Events(dateChanged,subject,description,year,month,day,h_m,repeat,repeatWeekdays,repeatUntil,show,notify) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)', (dateChanged,subject,description,year,month,day,h_m,repeat,repeatWeekdays,repeatUntil,show,notify))

def change_event_id(id, names, values):
    # id - id of event
    # name - tuple of names of values to change
    # value - new values for corresponding names
    if len(names) != len(values): return 0
    if len(names) == 0: return 0
    changes = ''
    for i in range(len(names)):
        if type(values[i]) == type(''):
            changes = changes + str(names[i])+'="'+str(values[i])+'", '
        else:
            changes = changes + str(names[i])+'='+str(values[i])+', '
    changes = changes[:-2]+' '
    print('UPDATE Events set '+changes+'WHERE Id = '+str(id))
    con = lite.connect('Events.db')
    with con:
        cur = con.cursor()
        cur.execute('UPDATE Events set '+changes+'WHERE Id = '+str(id))

def delete_event_id(id):
    print(id)
    con = lite.connect('Events.db')
    with con:
        cur = con.cursor()
        cur.execute('DELETE FROM Events WHERE Id = '+str(id))

def get_events_day(year,month,day):
    # TODO check everything
    con = lite.connect('Events.db')
    with con:
        cur = con.cursor()
        cur.execute('SELECT * FROM Events WHERE year='+str(year)+' AND month='+str(month)+' AND day='+str(day))
        out = cur.fetchall()
    out2 = dict()
    for i in out:
        if out2.get(int(i[7][:2])): out2[int(i[7][:2])].append(i)
        else: out2[int(i[7][:2])] = [i]
    return out2

def get_events_month(year,month,day_first,day_last):
    # TODO repeating events not implemented yet i think

    # for display on main window
    # day_first - month day of the first day of the previous month, that is displayed
    # day_last - month day of the last day of the next month, that is displayed
    con = lite.connect('Events.db')
    with con:
        cur = con.cursor()
        cur.execute('SELECT * FROM Events WHERE year='+str(year if month!=1 else year-1)+' AND month='+str(month-1 if month!=1 else 12)+' AND day>='+str(day_first))
        out = cur.fetchall()
        cur.execute('SELECT * FROM Events WHERE year='+str(year)+' AND month='+str(month))
        out += cur.fetchall()
        cur.execute('SELECT * FROM Events WHERE year='+str(year if month!=12 else year+1)+' AND month='+str(month+1 if month!=12 else 1)+' AND day<='+str(day_last))
        out += cur.fetchall()

    out2 = dict()
    for i in out:
        try:
            # (year, month, day)
            out2[(i[4],i[5],i[6])] += [i]
##            out2[(int(i[4]),int(i[5]),int(i[6]))] += [i]
        except:
            out2[(i[4],i[5],i[6])] = [i]
##            out2[(int(i[4]),int(i[5]),int(i[6]))] = [i]

    return out2

################################################################
################################################################
def create_options():
    # Options.db file must not exist!
    con = lite.connect('Options.db')
    with con:
        cur = con.cursor()
        cur.execute('''CREATE TABLE Colors(Id INTEGER PRIMARY KEY,
                       color1 TEXT,
                       color2 TEXT,
                       color3 TEXT,
                       color4 TEXT,
                       color5 TEXT,
                       color6 TEXT)''')
        cur.execute('INSERT INTO Colors(color1,color2,color3,color4,color5,color6)VALUES (?,?,?,?,?,?)', ('#808080', '#cfcfcf', '#ffffff', '#808080', '#ffffff', '#ffffff'))

        cur.execute('''CREATE TABLE ColorScheme(Id INTEGER PRIMARY KEY,
                       name TEXT,
                       color1 TEXT,
                       color2 TEXT,
                       color3 TEXT,
                       color4 TEXT,
                       color5 TEXT,
                       color6 TEXT)''')
        cur.execute('INSERT INTO ColorScheme(name,color1,color2,color3,color4,color5,color6)VALUES (?,?,?,?,?,?,?)', ('The Grey','#808080', '#cfcfcf', '#ffffff', '#808080', '#ffffff', '#ffffff'))

        cur.execute('''CREATE TABLE Misc(Id INTEGER PRIMARY KEY,
                       width INTEGER,
                       height INTEGER,
                       title INTEGER,
                       x INTEGER,
                       y INTEGER,
                       alpha INTEGER,
                       mouse INTEGER,
                       del INTEGER)''')
        cur.execute('INSERT INTO Misc(width,height,title,x,y,alpha,mouse,del) VALUES (?,?,?,?,?,?,?,?)', (80,60,20,10,10,80,1,0))

################################################################
def get_misc():
    con = lite.connect('Options.db')
    with con:
        cur = con.cursor()
        cur.execute('SELECT * FROM Misc')
        misc = cur.fetchall()[0][1:]
    return misc

def save_misc(width,height,title,x,y,alpha,mouse,delete):
    con = lite.connect('Options.db')
    with con:
        cur = con.cursor()

        cur.execute('DELETE FROM Misc WHERE Id = 1')
        cur.execute('INSERT INTO Misc(width,height,title,x,y,alpha,mouse,del) VALUES (?,?,?,?,?,?,?,?)', (width,height,title,x,y,alpha,mouse,delete))

################################################################
def change_colors_sql(colors):
    con = lite.connect('Options.db')
    with con:
        cur = con.cursor()

        cur.execute('DELETE FROM Colors WHERE Id = 1')
        cur.execute('INSERT INTO Colors(color1,color2,color3,color4,color5,color6)VALUES (?,?,?,?,?,?)', colors)

def get_colors():
    con = lite.connect('Options.db')
    with con:
        cur = con.cursor()
        cur.execute('SELECT * FROM Colors')
        colors = cur.fetchall()[0][1:]
    return colors

def save_color_scheme(name,colors):
    con = lite.connect('Options.db')
    with con:
        cur = con.cursor()
        cur.execute('INSERT INTO ColorScheme(name,color1,color2,color3,color4,color5,color6)VALUES (?,?,?,?,?,?,?)', [name]+colors)

def delete_color_scheme(id):
    con = lite.connect('Options.db')
    with con:
        cur = con.cursor()
        cur.execute('DELETE FROM ColorScheme WHERE Id = '+str(id))

def get_colors_schemes():
    con = lite.connect('Options.db')
    with con:
        cur = con.cursor()
        cur.execute('SELECT * FROM ColorScheme')
        schemes = cur.fetchall()

    return schemes

##def get_colors_scheme(id):
##    con = lite.connect('Options.db')
##    with con:
##        cur = con.cursor()
##        cur.execute('SELECT * FROM ColorScheme WHERE Id = '+str(id))
##        colors = cur.fetchall()[0]
##
##        cur.execute('DELETE FROM Colors WHERE Id = 1')
##        cur.execute('INSERT INTO Colors(color1,color2,color3,color4,color5,color6)VALUES (?,?,?,?,?,?)', colors[2:])
##    return colors

def get():
    con = lite.connect('Events.db')
    with con:
        cur = con.cursor()
        cur.execute('SELECT * FROM Events')
        out = cur.fetchall()
    for i in out:print(i)
##    return out

if __name__ == '__main__':
    try:
        create_options()
    except:
        pass
    try:
        create_events()
    except:
        pass
##    get()


import time
import matplotlib.pyplot as plt

import sys

import numpy as np

from datetime import datetime
import os
import pickle

class Plotloss():
    def __init__(self,loss_names,pretrain=False):
        self.loss_names=loss_names
        if pretrain==True:
            historyFile='/home/yong/hdd/HPE/output/2019_10_26_20_54/history.pickle'
            self.losses={}
            with open(historyFile, 'rb') as f:
                for nm in loss_names:
                    self.losses[nm]=pickle.load(f)

            self.loss_best=999999
        else:
            self.losses={}
            for nm in loss_names:
                self.losses[nm]=[]
            self.loss_best=999999

        self.initialize_local()

    def initialize_local(self):
        #initialize local
        self.loss_local={}
        for nm in self.loss_names:
            self.loss_local[nm]=[]

    def append_local(self,loss_,nm):
        self.loss_local[nm].append(loss_)
        '''
        for i,nm in enumerate(self.loss_names):
            self.loss_local[nm].append(loss_[i])
        '''

    def append_loss(self):
        for nm in self.loss_names:
            self.losses[nm].append(np.mean(self.loss_local[nm]))
        self.initialize_local()

    def get_average(self,nm):
        return np.mean(self.loss_local[nm])

    def get_std(self,nm):
        return np.std(self.loss_local[nm])

    def save_plot(self,plt_title,fname):
        plt.figure()

        min_list=[]
        max_list=[]
        for nm in self.loss_names:
            vals=[x for x in self.losses[nm]]
            plt.plot(vals,label=nm)

            min_list.append(min(vals))
            max_list.append(max(vals))

        plt.autoscale(enable=True,axis='y')
        #plt.ylim(0,min(min_list)*100)
        #plt.ylim(0,0.01)

        plt.xlabel('epoch')
        plt.ylabel('loss')
        plt.title(plt_title)
        plt.legend()
        plt.grid()
        fig=plt.gcf()
        #plt.show()
        fig.savefig(fname)
        plt.close()
        '''
        plt.figure()

        for nm in self.loss_names:
            plt.plot([x for x in self.losses[nm]],label=nm)

        plt.autoscale(enable=True,axis='y')

        plt.xlabel('epoch')
        plt.ylabel('loss')
        plt.title(plt_title)
        plt.legend()
        plt.grid()
        fig=plt.gcf()
        #plt.show()
        fig.savefig(fname)
        plt.close()
        '''


from fastapi import APIRouter, Depends, HTTPException, Request

from app.auth import get_current_active_user
from app.servicios.conectar_mongo import conexion_mongo
from app.servicios.Filtro import Filtro
from datetime import datetime, date, timedelta, time
from app.servicios.conectar_sql import conexion_sql, crear_diccionario
from app.servicios.permisos import tienePermiso
from app.servicios.logs import loguearConsulta, loguearError
import traceback
from inspect import stack
from app.servicios.formatoFechas import mesTexto

router = APIRouter(
    prefix="/columnasBasicas",
    # dependencies=[Depends(get_current_active_user)],
    responses={404: {"description": "Not found"}},
)

class ColumnasBasicas():
    def __init__(self, filtros: Filtro, titulo: str):
        self.filtros = filtros
        self.titulo = titulo
        if self.filtros.fechas != None:
            self.fecha_ini_a12 = datetime.combine(datetime.strptime(filtros.fechas['fecha_ini'], '%Y-%m-%dT%H:%M:%S.%fZ'), datetime.min.time()) if filtros.fechas['fecha_ini'] != None and filtros.fechas['fecha_ini'] != '' else None
            self.fecha_fin_a12 = datetime.combine(datetime.strptime(filtros.fechas['fecha_fin'], '%Y-%m-%dT%H:%M:%S.%fZ'), datetime.min.time()) + timedelta(days=1) if filtros.fechas['fecha_fin'] != None and filtros.fechas['fecha_fin'] != '' else None

    async def FoundRate(self):
        categorias = []
        series = []

        if self.titulo == 'Found Rate Vs. Fulfillment Rate':
            serie1 = []
            serie2 = []

            if self.filtros.region != '' and self.filtros.region != "False" and self.filtros.region != None:
                filtro_lugar = True
                if self.filtros.zona != '' and self.filtros.zona != "False" and self.filtros.zona != None:
                    nivel = 'zona'
                    siguiente_nivel = 'tiendaNombre'
                    lugar = int(self.filtros.zona)
                else:
                    nivel = 'region'
                    siguiente_nivel = 'zonaNombre'
                    lugar = int(self.filtros.region)
            else:
                filtro_lugar = False
                siguiente_nivel = 'regionNombre'
                lugar = ''

            collection = conexion_mongo('report').report_foundRate
            pipeline = [{'$unwind': '$sucursal'}]
            if filtro_lugar:
                pipeline.append({'$match': {'sucursal.'+ nivel: lugar}})
            pipeline.append({'$match': {'fechaUltimoCambio': {'$gte': self.fecha_ini_a12, '$lt': self.fecha_fin_a12}}})
            pipeline.append({'$group':{'_id':'$sucursal.'+siguiente_nivel, 'items_ini': {'$sum': '$items_ini'}, 'items_fin': {'$sum': '$items_fin'}, 'items_found': {'$sum': '$items_found'}}})
            pipeline.append({'$project':{'_id':'$_id', 'fulfillment_rate': {'$divide': ['$items_fin', '$items_ini']}, 'found_rate': {'$divide': ['$items_found', '$items_ini']}}})
            cursor = collection.aggregate(pipeline)
            arreglo = await cursor.to_list(length=1000)
            if len(arreglo) >0:
                hayResultados = "si"
                for row in arreglo:
                    categorias.append(row['_id'])
                    serie1.append(round(row['fulfillment_rate'], 4))
                    serie2.append(round(row['found_rate'], 4))
                series.extend([
                    {'name': 'Fulfillment Rate', 'data':serie1, 'color': 'primary'},
                    {'name': 'Found Rate', 'data':serie2, 'color': 'secondary'}
                ])
            else:
                hayResultados = "no"
        return {'hayResultados':hayResultados,'categorias':categorias, 'series':series, 'pipeline': pipeline, 'categoria':self.filtros.categoria}
        # Para debugging
        # return {'hayResultados':'no','categorias':[], 'series':[], 'pipeline': []}

    async def Nps(self):
        categorias = []
        series = []
        clauseCatProveedor = ""
        if len(self.filtros.provLogist) > 0:
            clauseCatProveedor = " AND ("
            contador = 0
            for prov in self.filtros.provLogist:
                if prov == 'Recursos Propios':
                    clauseCatProveedor += f" ho.tercero IS NULL "
                else:
                    clauseCatProveedor += f" ho.tercero = '{prov}' "
                if contador < len(self.filtros.provLogist) - 1:
                    clauseCatProveedor += f" OR "
                else:
                    clauseCatProveedor += f") "
                contador += 1

        if self.titulo == 'Distribución de clientes por calificación':
            serie1 = []
            serie2 = []

            if self.filtros.agrupador == 'dia':
                agrupador_select = "dt.fecha"
                mes = int(self.filtros.periodo['mes'])
                mes = str(mes) if mes >= 10 else '0'+str(mes)
                dia = int(self.filtros.periodo['dia'])
                dia = str(dia) if dia >= 10 else '0'+str(dia)
                agrupador_where = f" dt.fecha='{self.filtros.periodo['anio']}-{mes}-{dia}'"
            elif self.filtros.agrupador == "semana":
                agrupador_select = "dt.anio, dt.num_semana"
                semana_completa = str(self.filtros.periodo['semana'])
                num_semana = str(int(semana_completa[4:]))
                anio = semana_completa[0:4]
                agrupador_where = f" dt.anio={anio} and dt.num_semana='W{num_semana}'"
            elif self.filtros.agrupador == "mes":
                agrupador_select = "dt.anio, dt.num_mes"
                agrupador_where = f" dt.num_mes={self.filtros.periodo['mes']} and dt.anio={self.filtros.periodo['anio']}"

            # Rawa
            # pipeline = f"""select nd.calificacion,count(1) reg, {agrupador_select}
            # from DWH.limesurvey.nps_mail_pedido nmp
            # inner join DWH.limesurvey.nps_detalle nd on nmp.id_encuesta =nd.id_encuesta and nd.nEncuesta=nmp.nEncuesta
            # left join DWH.artus.catTienda ct on nmp.idTienda =ct.tienda
            # left join DWH.dbo.dim_tiempo dt on nmp.fecha = dt.fecha
            # where {agrupador_where} """
            pipeline = f"""select nd.calificacion,count(1) reg, {agrupador_select}
            from DWH.limesurvey.nps_mail_pedido nmp
            inner join DWH.limesurvey.nps_detalle nd on nmp.id_encuesta =nd.id_encuesta and nd.nEncuesta=nmp.nEncuesta
            left join DWH.artus.catTienda ct on nmp.idTienda =ct.tienda
            LEFT JOIN DWH.dbo.hecho_order ho ON ho.order_number =nmp.pedido
            left join DWH.dbo.dim_tiempo dt on ho.creation_date = dt.fecha
            where {agrupador_where} """
            if self.filtros.tienda != '' and self.filtros.tienda != None and self.filtros.tienda != 'False':
                pipeline += f""" and ct.tienda ='{self.filtros.tienda}' """
            elif self.filtros.zona != '' and self.filtros.zona != None and self.filtros.zona != 'False':
                pipeline += f" and ct.zona='{self.filtros.zona}' "
            elif self.filtros.region != '' and self.filtros.region != None and self.filtros.region != 'False':
                pipeline += f" and ct.region ='{self.filtros.region}' "
            pipeline += clauseCatProveedor
            pipeline += f" group by nd.calificacion, {agrupador_select} order by calificacion"

            # print("query desde columnas básicas nps ahorita: "+pipeline)
            cnxn = conexion_sql('DWH')
            cursor = cnxn.cursor().execute(pipeline)
            arreglo = crear_diccionario(cursor)

            if len(arreglo) > 0:
                hayResultados = "si"
                for i in range(len(arreglo)):
                    categorias = []
                    serie1.append(arreglo[i]['reg'])

                series = [
                    {
                        'name': 'Distribución',
                        'data': serie1,
                        'type': 'column',
                        'formato_tooltip':'entero',
                        'color':'primary'
                    }
                ]
            else:
                hayResultados = 'no'

        if self.titulo == 'Distribución de clientes por calificación 2':
            serie1 = []
            serie2 = []

            if self.filtros.agrupador == 'dia':
                agrupador_select = "dt.fecha"
                mes = int(self.filtros.periodo['mes'])
                mes = str(mes) if mes >= 10 else '0'+str(mes)
                dia = int(self.filtros.periodo['dia'])
                dia = str(dia) if dia >= 10 else '0'+str(dia)
                agrupador_where = f" dt.fecha='{self.filtros.periodo['anio']}-{mes}-{dia}'"
            elif self.filtros.agrupador == "semana":
                agrupador_select = "dt.anio, dt.num_semana"
                semana_completa = str(self.filtros.periodo['semana'])
                num_semana = str(int(semana_completa[4:]))
                anio = semana_completa[0:4]
                agrupador_where = f" dt.anio={anio} and dt.num_semana='W{num_semana}'"
            elif self.filtros.agrupador == "mes":
                agrupador_select = "dt.anio, dt.num_mes"
                agrupador_where = f" dt.num_mes={self.filtros.periodo['mes']} and dt.anio={self.filtros.periodo['anio']}"
            # Rawa
            # pipeline = f"""select nd.calificacion,count(1) reg, {agrupador_select}
            # from DWH.limesurvey.nps_mail_pedido nmp
            # inner join DWH.limesurvey.nps_detalle nd on nmp.id_encuesta =nd.id_encuesta and nd.nEncuesta=nmp.nEncuesta
            # left join DWH.artus.catTienda ct on nmp.idTienda =ct.tienda
            # left join DWH.dbo.dim_tiempo dt on nmp.fecha = dt.fecha
            # where {agrupador_where} """
            pipeline = f"""select nd.calificacion,count(1) reg, {agrupador_select}
            from DWH.limesurvey.nps_mail_pedido nmp
            inner join DWH.limesurvey.nps_detalle nd on nmp.id_encuesta =nd.id_encuesta and nd.nEncuesta=nmp.nEncuesta
            left join DWH.artus.catTienda ct on nmp.idTienda =ct.tienda
            LEFT JOIN DWH.dbo.hecho_order ho ON ho.order_number =nmp.pedido
            left join DWH.dbo.dim_tiempo dt on ho.creation_date = dt.fecha
            where {agrupador_where} """
            if self.filtros.tienda != '' and self.filtros.tienda != None and self.filtros.tienda != 'False':
                pipeline += f""" and ct.tienda ='{self.filtros.tienda}' """
            elif self.filtros.zona != '' and self.filtros.zona != None and self.filtros.zona != 'False':
                pipeline += f" and ct.zona='{self.filtros.zona}' "
            elif self.filtros.region != '' and self.filtros.region != None and self.filtros.region != 'False':
                pipeline += f" and ct.region ='{self.filtros.region}' "
            pipeline += clauseCatProveedor
            pipeline += f" group by nd.calificacion, {agrupador_select} order by calificacion"

            # print("query desde columnas básicas nps ahorita: "+pipeline)
            cnxn = conexion_sql('DWH')
            cursor = cnxn.cursor().execute(pipeline)
            arreglo = crear_diccionario(cursor)

            if len(arreglo) > 0:
                hayResultados = "si"
                categorias = ['']
                for i in range(len(arreglo)):
                    name = int(arreglo[i]['calificacion'])
                    y = [arreglo[i]['reg']]
                    if name <=6:
                        color = 'danger'
                    elif name <= 8:
                        color = 'warning'
                    else:
                        color = 'success'
                    series.append( {
                        'name': name,
                        'y': y,
                        'type': 'column',
                        'formato_tooltip':'entero',
                        'color': color
                    })
            else:
                hayResultados = 'no'

        return {'hayResultados':hayResultados,'categorias':categorias, 'series':series, 'pipeline': pipeline, 'categoria':self.filtros.categoria}
        # Para debugging
        # return {'hayResultados':'no','categorias':[], 'series':[], 'pipeline': []}

    async def CostoPorPedido(self):
        categorias = []
        series = []
        subSubTitulo = ''
        queryMetodoEnvio = f"and cf.TiendaEnLinea = '{self.filtros.metodoEnvio}'" if self.filtros.metodoEnvio != '' and self.filtros.metodoEnvio != "False" and self.filtros.metodoEnvio != None else ''
        if self.filtros.anio != 0 and self.filtros.anio != None:
            query1Anio = f"and cf.Anio = {self.filtros.anio}"
            query2Anio = f"and Anio = {self.filtros.anio}"
        else:
            query1Anio = query2Anio = ''
        if self.filtros.mes != 0 and self.filtros.mes != None:
            query1Mes = f"and cf.Mes = {self.filtros.mes}"
            query2Mes = f"and Mes = {self.filtros.mes}"
        else:
            query1Mes = query2Mes = ''
        if self.filtros.region != '' and self.filtros.region != "False" and self.filtros.region != None:
            if self.filtros.zona != '' and self.filtros.zona != "False" and self.filtros.zona != None:
                if self.filtros.tienda != '' and self.filtros.tienda != "False" and self.filtros.tienda != None:
                    queryLugar = f""" and ct.tienda = {self.filtros.tienda} """
                    lugar = f"tiendaNombre"
                else:
                    queryLugar = f""" and ct.zona = {self.filtros.zona} """
                    lugar = f"tiendaNombre"
            else:
                queryLugar = f""" and ct.region = {self.filtros.region} """
                lugar = f"zonaNombre"
        else:
            queryLugar = ''
            lugar = f"regionNombre"

        if self.titulo == 'Pedidos por Picker':
            series = []
            data = []
            query = f"""select * from  DWH.artus.catCostos"""
            cnxn = conexion_sql('DWH')
            cursor = cnxn.cursor().execute(query)
            costosReferencia_tmp = crear_diccionario(cursor)
            costosReferencia = {}
            for row in costosReferencia_tmp:
                costosReferencia[row['descripCosto']] = row['Costo']
            pipeline = f"""select {lugar} as lugar, sum(cf.pRH) pedidos from dwh.report.consolidadoFinanzas cf
                left join DWH.artus.catTienda ct on cf.Cebe = ct.tienda
                left join DWH.dbo.dim_tiempo dt on dt.id_fecha = cf.Anio * 10000 + cf.Mes * 100 + 1
                where Mes <= 12
                {queryMetodoEnvio}
                {query1Anio}
                {query1Mes}
                {queryLugar}
                group by {lugar}
                """
            # print(f"query desde ColumnasBasicas->PedidosPorPicker->{self.titulo}->General: {str(pipeline)}")
            cnxn = conexion_sql('DWH')
            cursor = cnxn.cursor().execute(pipeline)
            arreglo = crear_diccionario(cursor)
            if len(arreglo) > 0:
                hayResultados = "si"
                for row in arreglo:
                    query = f"""select SUM(Ocupada) as pickers from DWH.report.consolidadoFinanzasPicker cfp
                    left join DWH.artus.catTienda ct on cfp.Cebe = ct.tienda
                    where Puesto like '%surtidor%'
                    and ct.{lugar} = '{row['lugar']}'
                    {query2Anio}
                    {query2Mes}
                    {queryLugar}"""
                    # print(f"query desde columnasBasicas->PedidosPorPicker->{self.titulo}->Picker: {str(query)}")
                    cursor = cnxn.cursor().execute(query)
                    arregloSub = crear_diccionario(cursor)
                    pedidos = float(row['pedidos'])
                    pickers = float(arregloSub[0]['pickers']) if arregloSub[0]['pickers'] is not None else 0
                    # print(f"DataSub: {str(dataSub)}")
                    pedidosPorPicker = pedidos / pickers if pickers != 0 else 0
                    data.append((pedidosPorPicker, row['lugar']))
                # Lo ordenas según https://stackoverflow.com/questions/31942169/python-sort-array-of-arrays-by-multiple-conditions
                data = sorted(data)
                # Extraes los datos para las series y las categories
                for tupla in data:
                    series.append(tupla[0])
                    categorias.append(tupla[1])
                series = [
                    {
                        'name': 'Pedidos por Picker',
                        'data': series,
                        'type': 'column',
                        'formato_tooltip':'moneda',
                        'color':'primary'
                    }
                ]
            else:
                hayResultados = 'no'
                series = []

        if self.titulo == 'Costo de RH por pedido':
            series = []
            data = []
            query = f"""select * from  DWH.artus.catCostos"""
            cnxn = conexion_sql('DWH')
            cursor = cnxn.cursor().execute(query)
            costosReferencia_tmp = crear_diccionario(cursor)
            costosReferencia = {}
            for row in costosReferencia_tmp:
                costosReferencia[row['descripCosto']] = row['Costo']
            pipeline = f"""select {lugar} as lugar, sum(cf.pRH) pedidos, sum(cf.RH) RH, SUM(cf.Envio) Envio, SUM(cf.Combustible) Combustible from dwh.report.consolidadoFinanzas cf
                left join DWH.artus.catTienda ct on cf.Cebe = ct.tienda
                left join DWH.dbo.dim_tiempo dt on dt.id_fecha = cf.Anio * 10000 + cf.Mes * 100 + 1
                where Mes <= 12
                {queryMetodoEnvio}
                {query1Anio}
                {query1Mes}
                {queryLugar}
                group by {lugar}
                """
            # print(f"query desde tablas->CostoPorPedido->{self.titulo}->General: {str(pipeline)}")
            cnxn = conexion_sql('DWH')
            cursor = cnxn.cursor().execute(pipeline)
            arreglo = crear_diccionario(cursor)
            if len(arreglo) > 0:
                hayResultados = "si"
                for row in arreglo:
                    pedidos = float(row['pedidos'])
                    RH = float(row['RH']) if row['RH'] is not None else 0
                    Envio = float(row['Envio']) if row['Envio'] is not None else 0
                    Combustible = float(row['Combustible']) if row['Combustible'] is not None else 0
                    # print(f"DataSub: {str(dataSub)}")
                    RHxPedido = ((RH + Envio + Combustible) / pedidos) if pedidos != 0 else 0
                    data.append((RHxPedido, row['lugar']))
                # Lo ordenas según https://stackoverflow.com/questions/31942169/python-sort-array-of-arrays-by-multiple-conditions
                data = sorted(data)
                # Extraes los datos para las series y las categories
                for tupla in data:
                    series.append(
                    {
                        'name': tupla[1],
                        'y': tupla[0],
                        'type': 'column',
                        'formato_tooltip':'moneda',
                        'color':'secondary'
                    }
                    )
            else:
                hayResultados = 'no'
                series = []

        if self.titulo == 'Prueba':
            hayResultados = 'si'
            pipeline = []
            categorias = ['mexicanos', 'al', 'grito', 'de', 'guerra', 'acero']
            series = []
            #     {
            #         'name': 'Costo de RH por Pedido',
            #         'data': [5,3,7,9,4,5],
            #         'type': 'column',
            #         'formato_tooltip':'moneda',
            #         'color':'secondary'
            #     }
            # ]
            data = [300,500,100, 900,600,300]
            for i in range(6):
                if i % 3 == 0:
                    color = 'success'
                elif i % 3 == 1:
                    color = '#FFFFFF'
                else:
                    color = 'danger'
                series.append( {
                    'y': data[i],
                    'type': 'column',
                    'formato_tooltip':'entero',
                    'color': color
                })
            subSubTitulo = f'Actualizado al {datetime.now().strftime("%d/%m/%Y a las %H:%M")}'
        return {'hayResultados':hayResultados, 'series':series, 'categorias': categorias, 'subSubTitulo': subSubTitulo, 'pipeline': pipeline}

    async def PedidosPendientes(self):
        pipeline = []
        data = []
        categorias = []
        subSubTitulo = ''
        series = []
        filtroHoy = {
            '$match': {
                'prioridad': {
                    '$ne': 'Futuro'
                }
            }
        }
        if self.filtros.region != '' and self.filtros.region != "False" and self.filtros.region != None:
            filtro_lugar = True
            if self.filtros.zona != '' and self.filtros.zona != "False" and self.filtros.zona != None:
                if self.filtros.tienda != '' and self.filtros.tienda != "False" and self.filtros.tienda != None:
                    nivel = 'idTienda'
                    lugar = int(self.filtros.tienda)
                else:
                    nivel = 'zona'
                    lugar = int(self.filtros.zona)
            else:
                nivel = 'region'
                lugar = int(self.filtros.region)
        else:
            filtro_lugar = False
            lugar = ''

        collection = conexion_mongo('report').report_pedidoPendientes
        pipeline.extend([
            {'$unwind': '$sucursal'},
            filtroHoy
            ])
        if filtro_lugar:
            pipeline.append({'$match': {'sucursal.'+ nivel: lugar}})
        if self.filtros.tipoEntrega != None and self.filtros.tipoEntrega != "False" and self.filtros.tipoEntrega != "":
            pipeline.append({'$match': {'metodoEntrega': self.filtros.tipoEntrega}})
        if self.filtros.origen != None and self.filtros.origen != "False" and self.filtros.origen != "":
            pipeline.append({'$match': {'origen': self.filtros.origen}})

        if self.titulo == 'Pedidos pendientes de entrega':
            # pipeline.append({'$project': {'2_DIAS': {'$cond': [{'$eq':['$prioridad', '2 DIAS']}, 1, 0]}, 'HOY_ATRASADO': {'$cond': [{'$eq':['$prioridad', 'HOY ATRASADO']}, 1, 0]}, '1_DIA': {'$cond': [{'$eq':['$prioridad', '1 DIA']}, 1, 0]}, 'HOY_A_TIEMPO': {'$cond': [{'$eq':['$prioridad', 'HOY A TIEMPO']}, 1, 0]}, 'ANTERIORES': {'$cond': [{'$eq':['$prioridad', 'ANTERIORES']}, 1, 0]}}})
            # pipeline.append({'$group':{'_id':0, '2_DIAS':{'$sum':'$2_DIAS'}, 'HOY_ATRASADO':{'$sum':'$HOY_ATRASADO'}, '1_DIA':{'$sum':'$1_DIA'}, 'HOY_A_TIEMPO':{'$sum':'$HOY_A_TIEMPO'}, 'ANTERIORES':{'$sum':'$ANTERIORES'}}})
            pipeline.append({
                '$group': {
                    '_id':'$prioridad',
                    'pedidos':{'$sum':1},
                    'actualizacion': {'$max': '$fechaUpdate'}
                }
            })
            # print(f"Pipeline desde columnasBasicas -> Pedidos Pendientes: {str(pipeline)}")
            cursor = collection.aggregate(pipeline)
            arreglo = await cursor.to_list(length=1000)
            # print(str(arreglo))
            if len(arreglo) <= 0:
                # print("No hubo resultados")
                hayResultados = "no"
            else:
                hayResultados = "si"
                estatus = ['ANTERIORES', '2 DIAS', '1 DIA', 'HOY ATRASADO', 'HOY A TIEMPO']
                categorias = [elemento.title() for elemento in estatus]
                valores = [next((item.get("pedidos", 0) for item in arreglo if item["_id"] == key),0) for key in estatus]
                # print(f"Valores = {valores}")
                for i in range(len(estatus)):
                    if i == 0:
                        color = 'danger'
                    elif i == 4:
                        color = 'secondary'
                    else:
                        color = 'light'
                    # res[indice]['y'] = resultado['pedidos']
                    series.append({
                        'y': valores[i],
                        'type': 'column',
                        'formato_tooltip':'entero',
                        'color': color
                    })
                actualizacion = arreglo[0]['actualizacion'] - timedelta(hours=6)
                actualizacion = actualizacion.strftime("%d/%m/%Y a las %H:%M:%S")
                subSubTitulo = f"Actualizado al {actualizacion} hrs."

        return {'hayResultados':hayResultados, 'series':series, 'categorias': categorias, 'subSubTitulo': subSubTitulo, 'pipeline': pipeline}

@router.post("/{seccion}")
async def columnas_basicas (filtros: Filtro, titulo: str, seccion: str, request: Request, user: dict = Depends(get_current_active_user)):
    loguearConsulta(stack()[0][3], user.usuario, seccion, titulo, filtros, request.client.host)
    if tienePermiso(user.id, seccion):
        try:
            objeto = ColumnasBasicas(filtros, titulo)
            funcion = getattr(objeto, seccion)
            diccionario = await funcion()
        except:
            error = traceback.format_exc()
            loguearError(stack()[0][3], user.usuario, seccion, titulo, error, filtros, request.client.host)
            return {'hayResultados':'error'}
        return diccionario

    else:
        return {"message": "No tienes permiso para acceder a este recurso."}


from itertools import repeat
import time

arraySet1 = list(repeat(4, 1000000))
arraySet2 = list(repeat(8, 1000000))
arraySet3 = list(repeat(16, 1000000))

def NoThread(arraySet):
    t0 = time.time()
    print(sum(arraySet))
    t = time.time()
    print('Time Rate : %2.9f' % (t-t0))
    time.sleep(2)

NoThread(arraySet1)
NoThread(arraySet2)
NoThread(arraySet3)

print(" ")
input('press any key to exit...')


import requests
from flask import Flask, render_template, request, session, redirect
from twilio.rest import Client
from flask_session import Session
import random

account_sid = ""
auth_token = ""
client = Client(account_sid, auth_token)
app = Flask(__name__, "/static")

@app.route('/')
def index():
    session["user"] = None
    data_json = requests.get("https://api.covid19india.org/v4/data.json").json()
    data = {}
    for state in data_json:
        districts_list = []
        if "districts" not in data_json[state].keys():
            continue
        data_list = data_json[state]["districts"]
        for district in data_list:
            if "total" not in data_list[district].keys():
                continue
            if "confirmed" not in data_list[district]["total"].keys():
                continue
            if "meta" not in data_list[district].keys():
                continue
            if "population" not in data_list[district]["meta"].keys():
                continue
            districts_list.append(district)
        if len(districts_list) == 0:
            continue
        data[state] = districts_list
    return render_template("index.html", data=data)

@app.route("/verify", methods=["POST"])
def verify():
    session["user"] = request.form
    string = str(random.randint(0, 9))
    string += str(random.randint(0, 9))
    string += str(random.randint(0, 9))
    string += str(random.randint(0, 9))
    mobile_number = request.form["mobile_number"]
    client.messages.create("+91" + str(mobile_number), from_="",
                           body="OTP for ePass registration is " + string)
    session["otp"] = string
    return render_template("verify.html", number=mobile_number, otp=string, check="0")

@app.route("/verification", methods=["POST"])
def verification():
    if session["user"] is None:
        return redirect("/")
    string = request.form["1"]
    string += request.form["2"]
    string += request.form["3"]
    string += request.form["4"]
    if string == session["otp"]:
        return redirect("/status")
    else:
        return render_template("verify.html", number=session["user"]["mobile_number"], otp=string, check="1")

@app.route("/status", methods=["GET"])
def details():
    if session["user"] is None:
        return redirect("/")
    first_name = session["user"]["first_name"]
    last_name = session["user"]["last_name"]
    aadhaar_number = session["user"]["aadhaar_number"]
    from_state = session["user"]["from_state"]
    from_district = session["user"]["from_district"]
    to_state = session["user"]["to_state"]
    to_district = session["user"]["to_district"]
    mobile_number = session["user"]["mobile_number"]
    from_date = session["user"]["from_date"]
    to_date = session["user"]["to_date"]
    data = requests.get("https://api.covid19india.org/v4/data.json").json()
    count = data[to_state]["districts"][to_district]["total"]["confirmed"]
    total = data[to_state]["districts"][to_district]["meta"]["population"]
    percentage = (count / total) * 100
    if percentage < 20:
        status = "CONFIRMED"
    else:
        status = "NOT CONFIRMED"
    client.messages.create("+91" + str(mobile_number), from_="",
                           body="Hello " + first_name + " " + last_name + ", your travel from " + from_district + " to " + to_district + " is " + status.lower() + ".")
    session["user"] = None
    return render_template("status.html", var1=first_name + " " +  last_name, var2=aadhaar_number, var3=from_state,
                           var4=from_district, var5=to_state, var6=to_district, var7=mobile_number, var8=from_date,
                           var9=to_date, var10=status)

if __name__ == "__main__":
    app.config["SESSION_PERMANENT"] = False
    app.config["SESSION_TYPE"] = "filesystem"
    Session(app)
    app.run(port=1000, debug=True)


from django.urls import include, path
from rest_framework.routers import DefaultRouter

from custom_auth.views import (
    CustomAuthTokenLoginOrRequestMFACode,
    CustomAuthTokenLoginWithMFACode,
    FFAdminUserViewSet,
    delete_token,
)

app_name = "custom_auth"

ffadmin_user_router = DefaultRouter()
ffadmin_user_router.register(r"users", FFAdminUserViewSet)

urlpatterns = [
    # Override some endpoints for throttling requests and delete user
    path(
        "login/",
        CustomAuthTokenLoginOrRequestMFACode.as_view(),
        name="custom-mfa-authtoken-login",
    ),
    path(
        "login/code/",
        CustomAuthTokenLoginWithMFACode.as_view(),
        name="mfa-authtoken-login-code",
    ),
    path("", include(ffadmin_user_router.urls)),
    path("token/", delete_token, name="delete-token"),
    # NOTE: endpoints provided by `djoser.urls`
    # are deprecated and will be removed in the next Major release
    path("", include("djoser.urls")),
    path("", include("trench.urls")),  # MFA
    path("", include("trench.urls.djoser")),  # override necessary urls for MFA auth
    path("oauth/", include("custom_auth.oauth.urls")),
]


import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D, Activation

def PatchNet(input_shape,
             num_filters=(32, 64),
             filter_size=(3, 3),
             num_fc_units=(128,),
             drop_keep_prob=(0.5,),
             num_classes=77,
             optimizer='rmsprop'):
    # input
    model = Sequential()
    model.add(Conv2D(num_filters[0], filter_size, input_shape=input_shape))
    model.add(Activation('relu'))

    # build conv parts
    for n in num_filters[1:]:
        model.add(Conv2D(n, filter_size))
        model.add(Activation('relu'))
        model.add(MaxPooling2D(pool_size=(2, 2)))
        if len(drop_keep_prob) > 1:
            model.add(Dropout(drop_keep_prob[0]))

    # build fc parts
    model.add(Flatten())
    for n in num_fc_units:
        model.add(Dense(n))
        model.add(Activation('relu'))
        model.add(Dropout(drop_keep_prob[-1]))

    # output
    model.add(Dense(num_classes))
    model.add(Activation('softmax'))

    if optimizer == 'rmsprop':
        opt = keras.optimizers.rmsprop(lr=0.0001, decay=1e-6)
    elif optimizer == 'adam':
        opt = keras.optimizers.adam(lr=0.0001)
    elif optimizer == 'sgd':
        opt = keras.optimizers.sgd(lr=0.0001, momentum=0.9, nesterov=True)
    else:
        raise ValueError
    # opt = keras.optimizers.Adam(lr = 0.0001)
    model.compile(loss='categorical_crossentropy',
                  optimizer=opt,
                  metrics=['accuracy'])
    return model


"""
Set the path to import from parent directory.
"""
import os
import sys
import inspect
import json
import pytest

currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)

import numpy as np

# Try imports for good work of the LSP
try:
    from ..parsers import (
        Decoder,
        CoordNumber,
        CoordNumbers,
        Information,
        CnrFileItemType,
    )
except ImportError:
    from parsers import (
        Decoder,
        CoordNumber,
        CoordNumbers,
        Information,
        CnrFileItemType,
    )

@pytest.fixture
def json_path(tmp_path) -> str:
    path = tmp_path / "test.json"
    with open(os.path.join(currentdir, "./info_test.json")) as f:
        fcontent = f.read()
    fcontent = fcontent.replace("{path}", os.path.join(parentdir, "data"))
    path.write_text(fcontent)
    return path

@pytest.fixture
def coord_number() -> CoordNumber:
    """
    Fixture for CoordNumber class.
    """
    distances = np.linspace(0, 2, 100)
    return CoordNumber(
        fpath=os.path.join(parentdir, "data/EAN/cnr_BA_anion_cation_metal.txt"),
        column=1,
        header="Test header",
        charge=2,
        distances=distances,
        cnr=np.concatenate((np.zeros(10), np.arange(90))),
    )

@pytest.fixture
def coord_numbers_info(json_path: str) -> CnrFileItemType:
    """
    Fixture for CoordNumbers class.
    """
    data = json.load(
        open(json_path, "r"),
        cls=Decoder,
    )
    return data["Li"]["cnrs"]

@pytest.fixture
def information(json_path: str) -> Information:
    """
    Fixture for Information class.
    """
    return Information(json_path)

def test_decoder():
    """
    Test the Decoder class.
    """
    test_json = """
    {
        "coord_numbers": [
            {
                "test": "1.5",
                "information": {
                    "name": "test",
                    "value": "1"
                }
            }
        ]
    }
    """
    parsed_json = json.loads(test_json, cls=Decoder)
    assert parsed_json["coord_numbers"][0]["test"] == 1.5
    assert parsed_json["coord_numbers"][0]["information"]["name"] == "test"
    assert parsed_json["coord_numbers"][0]["information"]["value"] == 1

def test_coord_number(coord_number):
    """
    Test the CoordNumber class.
    """
    chr_dis = coord_number.charge_distribution
    assert len(coord_number.distances) == 100
    assert np.isclose(chr_dis[0], 0.0, rtol=1e-2)
    assert np.isclose(chr_dis[-1], 89 * 2, rtol=1e-2)
    distance = np.linspace(0, 2, 100)[11]
    assert coord_number.exclusion_radius == distance
    assert coord_number.charge == 2

def test_coord_numbers(coord_numbers_info):
    """
    Test the CoordNumbers class.
    """
    coord_numbers = CoordNumbers("Li", coord_numbers_info)
    assert set(coord_numbers.keys()) == {"anion", "cation", "metal"}
    assert isinstance(coord_numbers["anion"], CoordNumber)
    assert coord_numbers["anion"].charge == -1
    assert coord_numbers["cation"].charge == 1
    assert coord_numbers["metal"].charge == 1
    tot_char = coord_numbers.total_charge_distribution
    assert isinstance(tot_char, np.ndarray)
    assert tot_char.shape == (len(coord_numbers.distances),)
    assert len(coord_numbers.distances) == 1250

def test_information(information: Information):
    """
    Test the Information class.
    """
    assert set(information.keys()) == {"Li", "Na"}
    assert isinstance(information["Li"], dict)
    assert set(information["Li"].keys()) == {
        "cnrs",
        "Q",
        "enthalpy",
        "enthalpy_md",
        "ionic_radius",
        "cnrs",
    }
    assert isinstance(information["Li"]["cnrs"], CoordNumbers)
    assert information["Li"]["Q"] == 1
    assert information["Li"]["enthalpy"] == -505.71
    assert information["Li"]["enthalpy_md"] == -695.7
    assert information["Li"]["ionic_radius"] == 0.59
    assert isinstance(information.distances, np.ndarray)
    assert len(information.distances) == len(information["Li"]["cnrs"]["anion"].cnr)
    excl_rad = {k: v for k, v in zip(information.keys(), information.exclusion_radii)}
    compare = {"Li": 0.222, "Na": 0.266}
    assert excl_rad == compare
    assert round(information["Li"]["cnrs"].electrostatic_work) == -818
    assert round(information["Na"]["cnrs"].electrostatic_work) == -674


from flask import Flask, request, make_response, jsonify

app = Flask(__name__)
app.debug = True
DT = {}

@app.route("/kvs/<string:key_name>", methods=['GET', 'PUT', 'DELETE'])

def root(key_name):
	if (request.method == 'GET'):
		return getValue(key_name)

	if (request.method == 'PUT'):
		v = request.form['val']
		return putValue(key_name,v)

	if (request.method == 'DELETE'):
		#return "Delete value and key: %s" % key_name
		return delValue(key_name)
	else:
		return "Invalid request."

# Working
def getValue(key):
	if (key in DT):
		value = DT[key]
		j = jsonify(msg='success',value=value)
		return make_response(j,200,{'Content-Type':'application/json'})
	else:
		j = jsonify(msg='error',error='key does not exist')
		return make_response(j,404,{'Content-Type':'application/json'})

# Working
def putValue(key,value):
	if (key in DT):
		DT[key]=value
		j = jsonify(msg='success',replaced=1)
		return make_response(j,200, {'Content-Type' : 'application/json'})
	else:
		DT[key]=value
		j = jsonify(msg='success',replaced=0)
		return make_response(j,201,{'Content-Type' : 'application/json'})

# idk
def delValue(key):
	if (key in DT):
		DT.pop(key,None)
		j = jsonify(msg='success')
		return make_response(j,200,{'Content-Type':'application/json'})
	else:
		j = jsonify(msg='error',error='key does not exist')
		return make_response(j,404,{'Content-Type':'application/json'})

if __name__ == '__main__':
	app.run(port=8080)


import sys
from PyQt5.QtWidgets import QDialog, QMainWindow, QApplication, QFileDialog, QMessageBox
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QIcon
import MainWindow
import pandas as pd
import numpy as np
from pydispatch import dispatcher
import os

class StartPegasusViewer(QMainWindow):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.showMaximized()
        self.ui = MainWindow.Ui_MainWindow()
        # attributes initialised in subsequent methods
        self.dm = None

        self.ui.setupUi(self)
        self.ui.pushButton_2.clicked.connect(self.choose_file)
        # self.ui.comboBox.currentIndexChanged.connect(self.x_changed)
        self.ui.comboBox_2.currentIndexChanged.connect(self.y_changed)
        self.ui.comboBox_session.currentIndexChanged.connect(self.session_changed)
        self.ui.pushButton.clicked.connect(self.apply_btn_press)
        self.ui.pushButton_export.clicked.connect(self.export_btn_press)
        self.ui.pushButton_smooth.clicked.connect(self.apply_moving_avg)

    @pyqtSlot()
    def choose_file(self):
        fd = QFileDialog(self)
        filename = fd.getOpenFileName()
        from os.path import isfile
        if isfile(filename[0]):
            raw_data = pd.read_csv(filename[0], delimiter=',', header=5)
            self.dm = DataManager(raw_data)
            # self.ui.comboBox.addItems(self.dm.x_columns)
            self.ui.comboBox_2.addItems(self.dm.y_columns)
            self.ui.comboBox_session.addItems([str(x) for x in self.dm.get_sorted_session_keys()])
            # dispatcher.send('UpdateXCombo', update=self.dm.x_columns[0])
            self.ui.pushButton_2.setEnabled(False)

    def apply_btn_press(self):
        start_time = self.ui.timeEdit.time().toPyTime()
        end_time = self.ui.timeEdit_2.time().toPyTime()
        self.dm.apply_time_filter(start_time, end_time)
        dispatcher.send("UpdatePlot", plot_params=self.dm.plot_data)

    def export_btn_press(self):
        fd = QFileDialog(self)
        export_dir = str(fd.getExistingDirectory(self, "Select Export Directory"))
        folder_str = str(self.dm.current_session_key).replace(':', '-')
        export_dir = os.path.dirname(export_dir + os.sep + folder_str + os.sep)
        if not os.path.exists(export_dir):
            os.makedirs(export_dir)

        # Load standard plots from config file
        if os.path.isfile(r'config/Standard_Plots.csv'):
            std_plots_df = pd.read_csv(r'config/Standard_Plots.csv')
            read_plots = std_plots_df.columns.tolist()
            export_vars = list(set(read_plots).intersection(self.dm.y_columns))
        else:
            export_vars = ['Temperature (degC)', 'Humidity (%)', 'Pressure (hPa)']
        for export_var in export_vars:
            self.dm.update_y_plot_data(export_var)
            dispatcher.send("ExportPlot", plot_params=self.dm.plot_data, export_dir=export_dir)

    def apply_moving_avg(self):
        self.dm.apply_moving_avg()
        dispatcher.send("UpdatePlot", plot_params=self.dm.plot_data)

    # @pyqtSlot()
    # def x_changed(self):
    #     new_value = self.ui.comboBox.currentText()
    #     self.dm.update_x_plot_data(new_value)
    #     dispatcher.send("UpdatePlot", plot_params=self.dm.plot_data)

    def y_changed(self):
        new_value = self.ui.comboBox_2.currentText()
        self.dm.update_y_plot_data(new_value)
        dispatcher.send("UpdatePlot", plot_params=self.dm.plot_data)

    def session_changed(self):
        new_session_key = pd.to_datetime(self.ui.comboBox_session.currentText(), format='%Y/%m/%d %H:%M:%S')
        self.dm.update_session_plot_data(new_session_key)
        dispatcher.send("UpdatePlot", plot_params=self.dm.plot_data)
        dispatcher.send("UpdateTimeFields", s_time=self.dm.cur_start_time, e_time=self.dm.cur_end_time)

class DataManager():
    def __init__(self, data=None):
        self.data = data
        self.x_columns = None
        self.y_columns = None
        self.plot_data = None
        self.current_session_key = None
        self.cur_start_time = None
        self.cur_end_time = None
        self.cur_plot_df = None
        self.sessions = dict()

        if self.data is not None:
            self.inititialise_data()

    def inititialise_data(self):
        if ('Date (D/M/Y)' in self.data.columns) & ('Time (H:M:S)' in self.data.columns):
            # Filter out null dates
            null_dates = self.data['Date (D/M/Y)'] == '0/0/0'
            self.data = self.data[~null_dates]
            self.data = self.data.dropna()
            self.data = self.data.reset_index()

            # Concatenate date and time into single column
            datetime_str = self.data['Date (D/M/Y)'] + 'T' + self.data['Time (H:M:S)']
            date_times = pd.to_datetime(datetime_str, format='%d/%m/%YT%H:%M:%S')
            date_times = pd.Series(date_times)
            del self.data['Date (D/M/Y)']
            del self.data['Time (H:M:S)']
            if ('Master Index' in self.data.columns):
                del self.data['Master Index']
            del self.data['index']
            # self.x_columns = ['date_time'] + self.data.columns.tolist()
            self.data['date_time'] = date_times
            self.data.set_index(['date_time'], inplace=True)
            # Create dictionary for which each entry is a session
            self.split_on_id()
            session_keys = self.get_sorted_session_keys()
            # Set current session
            self.y_columns = self.data.columns.tolist()
            self.current_session_key = session_keys[0]
            self.cur_plot_df = self.sessions[self.current_session_key]
            self.cur_start_time = self.cur_plot_df.index[0]
            self.cur_end_time = self.cur_plot_df.index[len(self.cur_plot_df)-1]
            # Create plot data dictionary
            self.plot_data = dict()
            self.plot_data['x_name'] = 'date_time'
            self.plot_data['x_data'] = None
            self.plot_data['y_name'] = self.y_columns[1]
            self.plot_data['y_data'] = self.cur_plot_df[self.plot_data['y_name']]
        else:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Warning)
            msg.setWindowTitle('Incorrect Data')
            msg.setInformativeText(
                r"Unable to locate the Date and Time columns with the correctly named column header")
            msg.setStandardButtons(QMessageBox.Ok)
            msg.exec_()

    def update_x_plot_data(self, new_value):
        self.plot_data['x_name'] = new_value
        if new_value == 'date_time':
            self.plot_data['x_data'] = None
        else:
            self.plot_data['x_data'] = self.cur_plot_df[new_value].values

    def update_y_plot_data(self, new_value):
        self.plot_data['y_name'] = new_value
        if self.plot_data['x_name'] == 'date_time':
            self.plot_data['y_data'] = self.cur_plot_df[new_value]
        else:
            self.plot_data['y_data'] = self.cur_plot_df[new_value].values

    def update_session_plot_data(self, new_session_key):
        self.current_session_key = new_session_key
        self.cur_plot_df = self.sessions[self.current_session_key]
        # If plotting time series then no need to set x_data, use index instead
        if self.plot_data['x_name'] == 'date_time':
            self.plot_data['x_data'] = None
            self.plot_data['y_data'] = self.cur_plot_df[self.plot_data['y_name']]
        else:
            self.plot_data['x_data'] = self.cur_plot_df[self.plot_data['x_name']].values
            self.plot_data['y_data'] = self.cur_plot_df[self.plot_data['y_name']].values
        start_time = self.cur_plot_df.index[0]
        self.cur_start_time = DataManager.PdTimestamp2Datetime(start_time).time()
        end_time = self.cur_plot_df.index[len(self.cur_plot_df) - 1]
        self.cur_end_time = DataManager.PdTimestamp2Datetime(end_time).time()

    def split_on_id(self):
        gap_indexes = np.where(self.data['Session Index'] == 0)[0]
        del self.data['Session Index']
        if len(gap_indexes) == 1:
            self.sessions[self.data.index[0]] = self.data
        else:
            for i in range(len(gap_indexes) - 1):
                df_session = self.data.iloc[gap_indexes[i]: gap_indexes[i+1]]
                self.sessions[df_session.index[0]] = df_session
            df_session = self.data.iloc[gap_indexes[len(gap_indexes)-1]:]
            self.sessions[df_session.index[0]] = df_session

    def get_sorted_session_keys(self):
        if self.sessions:
            session_keys = []
            for key in self.sessions:
                session_keys.append(key)
            return sorted(session_keys)
        else:
            return None

    def apply_time_filter(self, start_time, end_time):
        import datetime as dt
        self.cur_start_time = start_time
        self.cur_end_time = end_time
        date = self.sessions[self.current_session_key].index[0].date()
        start_time = pd.to_datetime(dt.datetime.combine(date, start_time))
        end_time = pd.to_datetime(dt.datetime.combine(date, end_time))
        current_session = self.sessions[self.current_session_key]
        self.cur_plot_df = current_session[(current_session.index > start_time) &
                                           (current_session.index < end_time)]
        if self.plot_data['x_name'] == 'date_time':
            self.plot_data['y_data'] = self.cur_plot_df[self.plot_data['y_name']]
        else:
            self.plot_data['x_data'] = self.cur_plot_df[self.plot_data['x_name']].values
            self.plot_data['y_data'] = self.cur_plot_df[self.plot_data['y_name']].values

    def apply_moving_avg(self, window_len=10):
        self.cur_plot_df = self.cur_plot_df.rolling(window_len).mean()
        # Get the pandas series from current df
        y_data = self.cur_plot_df[self.plot_data['y_name']]
        # y_data = y_data.rolling(window=window_len).mean()
        null_mask = pd.notnull(y_data)
        y_data = y_data[null_mask]
        self.cur_plot_df = self.cur_plot_df[null_mask]
        if self.plot_data['x_name'] == 'date_time':
            self.plot_data['y_data'] = y_data
        else:
            self.plot_data['y_data'] = y_data.values
            self.plot_data['x_data'] = self.plot_data['x_data'][null_mask]

    @staticmethod
    def PdTimestamp2Datetime(PdTimestamp):
        import datetime
        time_str = str(PdTimestamp)
        return datetime.datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')

if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setStyle('cleanlooks')
    app.setWindowIcon(QIcon(r'resources/PegasusLogo.PNG'))
    myapp = StartPegasusViewer()
    myapp.show()
    msg = QMessageBox()
    msg.setIcon(QMessageBox.Warning)
    msg.setWindowTitle('Terms of Use, Software Use and Disclaimer')
    msg.setText('Pegasus Viewer v1.0.0')
    msg.setInformativeText(r"This software is provided on an ‘as is’ basis with no warranty implied or given by "
            "BAE Systems.  It  is supplied as freely distributable software for use by UK Sport, the British Equestrian "
            "Federation and related bodies for the purpose of graphical representation of data derived from Pegasus units.  "
            "The company takes no responsibility for any loss or damage arising, directly or indirectly, as a result of "
            "use of the software, and gives no guarantees as to the veracity of the resultant formatted/plotted data.")
    msg.setStandardButtons(QMessageBox.Ok)
    msg.exec_()

    sys.exit(app.exec_())


# -*- coding: utf-8 -*-
from numpy import arange, asarray, concatenate, convolve, exp, mat, zeros
from numpy.linalg import pinv
from scipy.misc import factorial
from matplotlib.pyplot import figure, plot

def deconvolve(x, y, sigma, noise, wsize=3):
    """ Deconvolves function y(x) by factor sigma.
        Noisy data  => large wsize (so derivatives don't fluctuate wildly)
        Large wsize => curve overshoots at base of peaks and peaks cannot
        become so narrow
        => We want smallest wsize possible while still getting smooth results
    """
    sigma = float(sigma)
    ret = zeros(y.size)
    dx = x[1] - x[0]

    # Find optimal window size for smoothing of y
    w0 = 3
    dw = durbin_watson(y, savitzky_golay(y, w0, 2, dx))
    while True:
        dw0 = durbin_watson(y, savitzky_golay(y, w0+2, 2, dx))
        if (abs(dw0-1) < abs(dw-1)):
            dw = dw0
            w0 = w0 + 2
        else:
            break

    i = 0
    while True:
        w = wsize*2*i + w0
        y0 = concatenate((zeros(w), y, zeros(w)))
        temp = savitzky_golay(y0, w, 2*i, dx, deriv=2*i)[w:-w]
        c = (-sigma**2/4)**i / factorial(i)
        temp *= c

        if max(abs(temp)) > max(abs(y)):    # Process probably won't converge
            print('Deconvolution Failed')
            return None

        elif max(abs(temp)) > noise:
            ret += temp
            i += 1

        else:
            break

        # Remove noise along x=0 at each iteration
        # (otherwise noise may be amplified)
        ret[ret < noise] = 0

    return ret

def durbin_watson(y1, y2):
    """ Returns the Durbin-Watson parameter for a pair of curves.
        The closer DW is to 1, the better y2 approximates y1
    """
    n = asarray(y1).size
    num = 0.
    den = (y1[0]-y2[0])**2

    for i in range(1, n):
        temp = (y1[i]-y2[i]) - (y1[i-1]-y2[i-1])
        num += temp**2
        den += (y1[i]-y2[i])**2

    n = float(n)

    return (n/(n-1)) * (num / (4*den))

def G(x, n, p):
    """ Returns the evaluation at x of the sum of n Gaussian curves of the form
        A * exp(-(x-m)^2/s).
        For the kth curve (k=0...n-1), A=p[3*k], m=p[3*k+1], s=p[3*k+2].
    """
    if n == 0:
        return 0
    else:
        return p[0] * exp(-(x-p[1])**2 / p[2]) + G(x, n-1, p[3:])

def multi_deconvolve(x, y, sigs, noise, wsize=3):
    """ Apply multiple recursive deconvolutions, with deconvolution parameters
        given by sigs. Applying many small recursive deconvolutions is often
        more stable than apply one large deconvolution.
    """
    n = len(sigs)

    if n > 1:
        yd = deconvolve(x, y, sigs[-1], noise, wsize)
        if yd is None:
            return None
        else:
            return multi_deconvolve(x, yd, sigs[:-1], noise, wsize)
    else:
        return deconvolve(x, y, sigs[0], noise, wsize)

def savitzky_golay(y, window_size, order, dx, deriv=0):
    """ Uses the Savitsky-Golay algorithm to return a smoothed version of the
        specified derivative of y
    """
    half_window = (window_size - 1) // 2
    b = mat([[k**i for i in range(order+1)]
             for k in range(-half_window, half_window+1)])
    m = pinv(b).A[deriv] * (1/dx)**deriv * factorial(deriv)

    firstvals = y[0] + abs(y[1:half_window+1][::-1] - y[0])
    lastvals = y[-1] - abs(y[-half_window-1:-1][::-1] - y[-1])

    y = concatenate((firstvals, y, lastvals))

    return convolve(m[::-1], y, mode="valid")

if __name__ == "__main__":
    """ A demonstration of the deconvolution of a superposition of two
        overlapping Gaussian curves
    """
    x = arange(-10, 10, 0.025)
    y = G(x, 2, [100, 0, 1, 70, 1.5, 1])
    figure(1)
    plot(x, y, c='b')                           # Plot sum of curves
    plot(x, G(x, 1, [100, 0, 1]), c='r')        # Plot curve 1
    plot(x, G(x, 1, [70, 1.5, 1]), c='r')       # Plot curve 2
    figure(2)
    plot(x, deconvolve(x, y, 0.5, 0.1), c='b')  # Plot deconvolution
    plot(x, G(x, 1, [100, 0, 1]), c='r')        # Plot curve 1
    plot(x, G(x, 1, [70, 1.5, 1]), c='r')       # Plot curve 2


import os
import json

VALID_CHARS = '0123456789abcdef'

os.system('(cd repo && git log main --oneline --reverse) | grep -E "^\w+ Merge pull request #" > list.txt')

commits = []

with open('list.txt') as fd:
    for line in fd:
        commit_id, message = line.split(' ', 1)

        if any(c not in VALID_CHARS for c in commit_id):
            raise Exception('')

        commits.append({
            'commit': commit_id,
            'message': message
        })

os.makedirs('data/data', exist_ok=True)

with open('data/data/commits.json', 'w') as fd:
    json.dump(commits, fd, indent=1)