#   Сусликов Д. ИУ7-15б
#   Лабараторная работа 6 (18) часть 2

#   N - размер массива, b - число, k - число макс. чисел,
#   maks - максимальное число, a,с - массивы, j,i - номера чисел в массиве

#   Ввод массива и числа
N = input('Введите размер массива ')
while N.replace('e','',1).isdigit() == False or N == '0':
    N =(input('Ошибка! Введите размер массива '))
N = float(N)
N = int(N)

a = [0] * N
for i in range(N):
    print('a['+str(i)+ '] = ', sep = '', end = '')
    a[i]=(input())
    a[i].strip()
    while a[i].lstrip('-').replace('.','',1).replace('e-','',1).replace('e','',1).isdigit() == False:
        a[i]=(input('Ошибка! Введите число массива ещё раз '))
    a[i] = float(a[i])
print(a)

b = input('Введите число ')
b.strip()
while b.lstrip('-').replace('.','',1).replace('e-','',1).replace('e','',1).isdigit() == False:
    b = input('Введите число ')
b = float(b)

k = 0
maks = a[0]

#   Определение максимума и определение кол-ва максимальных чисел
for i in range (N):
    if a[i] >= maks:
        maks = a[i]
        k += 1

#   Проверка на лишнее

if a[0] < maks:
    k = k - 1

#   Создание массива с числом после каждого макс.
j = 0
c = [0]*(len(a) + k)
for i in range (len(a)):
    c[j] = a[i]
    j += 1
    if a[i] == maks:
        c[j] = ('{:.5g}'.format(b))
        j+=1
print(c)

1st_semester/Lab 6/Suslikov/Лаба 6 ч.2 (№18).py


#-*- coding: utf-8 -*-
import time
def outTxt(str,fileName='C:\SPIDER\out.txt'):
    with open(fileName, "a",encoding='utf-8') as f:
        f.writelines(str)
        f.write("\n")

f=open('C:\SPIDER\out.txt', "w+",encoding='utf-8')
f.write("爬虫test 知乎话题热门数据---by zw \n")
time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
f.write(str(time)+"\n")
f.close()


# %load q05_top_10_plotting/build.py
# default imports
import matplotlib.pyplot as plt
from greyatomlib.olympics_project_new.q04_find_top_10.build import q04_find_top_10, q03_better_event, q02_country_operations, q01_rename_columns
plt.switch_backend('agg')
path = './data/olympics.csv'
OlympicsDF=q01_rename_columns(path)
OlympicsDF=q02_country_operations(OlympicsDF)
OlympicsDF=q03_better_event(OlympicsDF)
Top10Summer,Top10Winter, Top10, Common =q04_find_top_10(OlympicsDF,'Total_Summer', 'Total_Winter','Total')

def q05_top_10_plotting(q04_find_top_10,Top10Summer,Top10Winter, Top10):
    df=OlympicsDF
    a=df[df['Country_Name'].isin(Top10Summer)]#sort df according to values in Top10Smmer list
    b=plt.bar(a['Country_Name'],a['Total'])
    c=df[df['Country_Name'].isin(Top10Winter)]
    d=plt.bar(c['Country_Name'],c['Total'])
    e=df[df['Country_Name'].isin(Top10)]
    f=plt.bar(e['Country_Name'],e['Total'])
    return b,d,f

c=q05_top_10_plotting(q04_find_top_10,Top10Summer,Top10Winter, Top10)
c


from csv import reader
from collections import Counter
import operator

class Aeroportos:

    def __init__(self, path):
        self.__path = path
        self.__data = self.open()

    def open(self):
        with open(self.__path, encoding="utf8") as arq_csv:
            leitor_csv = reader(arq_csv, delimiter=';')
            lista_csv = list(leitor_csv)
        return lista_csv
    """
    1.2) Extrair número de atrasos, recebendo como parâmetro, o ano de referência,
    e.g.: ./flight-delays -n 2006 deve listar o número de vôos com atraso em 2006.
    def atrasos(self):
    """
    def atrasos(self, ano):
        contador = 0
        len_coluna = len(self.__data[0:])
        if self.__data[1][0] == ano:
            for i in range(1, len_coluna):
                if self.__data[i][14] == 'NA':
                    contador = contador
                elif int(self.__data[i][14]) > 0:
                    contador += 1
        return contador
    """
    1.3) Mostrar lista de companhias aéreas que sofreram atraso, recebendo como parâmetro o ano de referência
    Utilizar o arquivo carriers.csv
    """
    def companhias_atrasos_comprida(self, path_carriers, ano):

        f = open(path_carriers, "r")
        data = f.readlines()
        f.close()

        # Tira as aspas do arquivo carriers e cria uma matriz (data) do conteúdo do arquivo
        # data[i][0] = código da companhia = coluna 'UniqueCarrier' do arquivo 2006.csv
        # data[i][1] = nome da companhia
        for i in range(len(data)):
            data[i] = data[i].replace('\n' , '').replace('"', "").split(",")

        # Cria uma lista (companhias) do conteúdo da coluna 8 = 'UniqueCarrier' do arquivo ano.csv
        # contendo só as COMPANHIAS QUE SOFRERAM ATRASO
        # essa coluna 8 possui o código da companhia
        companhias = []

        len_coluna = len(self.__data[0:])
        # Comprova se o ano ingressado é igual ao ano do arquivo
        if self.__data[1][0] == ano:
            for i in range(1, len_coluna):
                if self.__data[i][14] != 'NA' and int(self.__data[i][14]) > 0:
                    companhias.append(self.__data[i][8])

        # Se o código da companhia que sofreu atraso (companhias) for igual
        # ao código da lista carriers, é adicionado um novo elemento na lista_companhias, contendo
        # o nome do aeroporto que sofreu atraso

        lista_companhias = []

        if len(data) > len(companhias):

            for i in range (len(companhias)):
                for j in range (len(data)):
                    if companhias[i] == data[j][0]:
                        lista_companhias.append(data[j][1])
        else:

            for i in range (len(data)):
                for j in range (len(companhias)):
                    if data[i] == companhias[j][0]:
                        lista_companhias.append(companhias[j][1])

        return lista_companhias

    # Elimina os elementos repetidos da lista_companhias

    def companhias_atrasos_pequena(self, path_carriers, ano):

        x = Aeroportos(self.__path)
        lista_companhias = x.companhias_atrasos_comprida(path_carriers, ano)

        i = 0
        while i < len(lista_companhias):
            j = i + 1
            while j < len(lista_companhias):
                if lista_companhias[j] == lista_companhias[i]:
                    del(lista_companhias[j])
                else:
                   j += 1
            i += 1

        return lista_companhias

    """
    1.4) Mostrar a lista de Aeroportos com atrasos, recevendo como parâmetro o ano de referência
    Utilizar o arquivo airports.csv
    Criar nova issue que altere a funcionalidade de download de dataset para também baixar esse arquivo
    """
    # Quase igual ao exercício 3), diferença: pega a coluna 15 da matriz self.__data em lugar da 14

    def aeroportos_atrasos_comprida(self, path_airports, ano):

        f = open(path_airports, "r")
        data = f.readlines()
        f.close()

        # Tira as aspas do arquivo 'airports' e cria uma matriz (data) do conteúdo do arquivo
        # data[i][0] = iata
        # data[i][1] = airport
        # data[i][2] = city
        # data[i][3] = state
        # ...
        # data[i][6] = long

        for i in range(len(data)):
            data[i] = data[i].replace('\n' , '').replace('"', "").split(",")

        # Cria uma lista (aeroportos) do conteúdo da coluna 16 = 'Origin' do arquivo ano.csv
        # contendo só os códigos dos AEROPORTOS que SOFRERAM ATRASO
        # essa coluna 16 possui o código do aeroporto em que decolou o avião

        aeroportos = []

        len_coluna = len(self.__data[0:])
        # Comprova se o ano ingressado é igual ao ano do arquivo
        if self.__data[1][0] == ano:
            for i in range(1, len_coluna):
                if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0:
                    aeroportos.append(self.__data[i][16])

        # Se o código do aeroporto que sofreu atraso (aeroportos) for igual
        # ao código do aeroporto na lista 'airports' (coluna 0 da matriz data), é adicionado um novo elemento na lista_aeroporots,
        # contendo o nome do aeroporto que sofreu atraso

        lista_aeroportos = []

        if len(data) > len(aeroportos):

            for i in range (len(aeroportos)):
                for j in range (len(data)):
                    if aeroportos[i] == data[j][0]:
                        lista_aeroportos.append(data[j][1])
        else:

            for i in range (len(data)):
                for j in range (len(aeroportos)):
                    if data[i] == aeroportos[j][0]:
                        lista_aeroportos.append(aeroportos[j][1])

        return lista_aeroportos

    # Elimina os elementos repetidos da lista_aeroportos

    def aeroportos_atrasos_pequena (self,path_airports,ano):

        x = Aeroportos(self.__path)

        lista_aeroportos = x.aeroportos_atrasos_comprida(path_airports,ano)

        i = 0
        while i < len(lista_aeroportos):
            j = i + 1
            while j < len(lista_aeroportos):
                if lista_aeroportos[j] == lista_aeroportos[i]:
                    del(lista_aeroportos[j])
                else:
                   j += 1
            i += 1

        return lista_aeroportos

    """
    2.1) Contabilizar o número de atrasos ocorridos em cada aeroporto,
    listando o nome do aeroporto em uma coluna e o número de atrasos na segunda coluna (recebendo como parâmetro o ano base)
    """
    def num_atrasos_aeroporto(self, path_airports, ano):

        #Puxando o resultado do exercício 1.4
        x = Aeroportos(self.__path)
        lista_aeroporotos_comprida = x.aeroportos_atrasos_comprida(path_airports,ano)

        # Conta as ocorrencias de cada aeroporto na lista_aeroportos (versão comprida)
        # e retorna um dicionário

        num_atrasos = dict(Counter(lista_aeroporotos_comprida))

        return num_atrasos
    """
    2.2) Contabilizar o número de atrasos ocorridos em cada companhia aérea,
    listando o nome da companhia em uma coluna e o número de atrasos na segunda coluna (recebendo como parâmetro o ano base)
    """
    def num_atrasos_companhia(self, path_carriers, ano):
        #Puxando o resultado do exercício 1.3
        x = Aeroportos(self.__path)
        lista_companhias_comprida = x.companhias_atrasos_comprida(path_carriers,ano)

        # Conta as ocorrencias de cada companhia na lista_companhias (versão comprida)
        # e retorna um dicionário

        num_atrasos = dict(Counter(lista_companhias_comprida))

        return num_atrasos
    """
    2.3) Listar qual companhia teve o maior número de atrasos (atrasos somente na decolagem).
    """

    """
    extra) Mostra a lista de companhias aéreas que sofreram atraso NO DEPARTURE, recebendo como parâmetro o ano de referência
    Utilizar o arquivo carriers.csv
    """
    def companhias_atrasos_departure(self, path_carriers, ano):

        f = open(path_carriers, "r")
        data = f.readlines()
        f.close()

        # Tira as aspas do arquivo carriers e cria uma matriz (data) do conteudo do arquivo
        # data[i][0] = código da companhia = coluna 'UniqueCarrier' do arquivo 2006.csv
        # data[i][1] = nome da companhia
        for i in range(len(data)):
            data[i] = data[i].replace('\n' , '').replace('"', "").split(",")

        # Cria uma lista (companhias) do conteúdo da coluna 8 = 'UniqueCarrier' do arquivo ano.csv
        # contendo só as COMPANHIAS QUE SOFRERAM ATRASO NO DEPARTURE
        # essa coluna 8 possui o código da companhia
        companhias = []

        len_coluna = len(self.__data[0:])
        # Comprova se o ano ingressado é igual ao ano do arquivo
        if self.__data[1][0] == ano:
            for i in range(1, len_coluna):
                if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0:
                    companhias.append(self.__data[i][8])

        # Se o código da companhia que sofreu atraso NO DEPARTURE (companhias) for igual
        # ao código da lista carriers, é adicionado um novo elemento na lista_companhias, contendo
        # o nome do aeroporto que sofreu atraso

        lista_companhias = []

        if len(data) > len(companhias):

            for i in range (len(companhias)):
                for j in range (len(data)):
                    if companhias[i] == data[j][0]:
                        lista_companhias.append(data[j][1])
        else:

            for i in range (len(data)):
                for j in range (len(companhias)):
                    if data[i] == companhias[j][0]:
                        lista_companhias.append(companhias[j][1])

        return lista_companhias

    def companhia_mais_atrasos(self, path_carriers, ano):

        # Puxando o resultado da função acima
        x = Aeroportos(self.__path)
        companhias_atrasos_departures = x.companhias_atrasos_departure(path_carriers,ano)

        # Conta as ocorrencias de cada aeroporto na lista_aeroportos (versão comprida)
        # e retorna um dicionário ordenado de valores mayores a menores

        num_atrasos = dict(Counter(companhias_atrasos_departures)) # Observe that counts are always displayed in descending order.

        sorted_num_atrasos = dict(sorted(num_atrasos.items(), key=operator.itemgetter(1),reverse=True))

        num_maior_atrasos = list(sorted_num_atrasos.items())

        return num_maior_atrasos[0]
    """
    2.4) Listar qual aeroporto teve o maior número de atrasos (atrasos somente na decolagem).
    """
    def aeroporto_mais_atrasos(self, path_airports, ano):

        #Puxando o resultado do exercício 1.4
        x = Aeroportos(self.__path)
        lista_aeroporotos_comprida = x.aeroportos_atrasos_comprida(path_airports,ano)

        # Conta as ocorrencias de cada aeroporto na lista_aeroportos (versão comprida)
        # e retorna um dicionário

        num_atrasos = dict(Counter(lista_aeroporotos_comprida))

        sorted_num_atrasos = dict(sorted(num_atrasos.items(), key=operator.itemgetter(1),reverse=True))

        num_maior_atrasos = list(sorted_num_atrasos.items())

        return num_maior_atrasos[0]
    """
    2.5) Descobrir a média de atrasos na decolagem de cada voo;
    """
    def media_atrasos_decolagem(self):

        atrasos_decolagem = []
        len_coluna = len(self.__data[0:])
        cont = 0
        soma_atrasos = 0

        for i in range(1,len_coluna):
            if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0:
                atrasos_decolagem.append(self.__data[i][15])
                soma_atrasos += int(self.__data[i][15])
                cont += 1

        media_atrasos = soma_atrasos/cont

        return media_atrasos
    """
    2.6) Descobrir o voo com maior atraso em média e mostrar qual a média de atraso;
    """
    def voo_maior_atraso(self): #na decolagem

        atrasos_decolagem = []
        len_coluna = len(self.__data[0:])
        cont = 0
        soma_atrasos = 0
        maior = 0

        for i in range(1,len_coluna):
            if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0:

                atrasos_decolagem.append(self.__data[i][15])
                soma_atrasos += int(self.__data[i][15])
                cont += 1

                if int(self.__data[i][15]) > maior:
                    maior = int(self.__data[i][15])
                    voo = self.__data[i][9]

        media_atrasos = soma_atrasos/cont

        print(f'O numero do voo com maior atraso na decolagem é {voo} com atraso igual a {maior} minutos')
        print(f'A média de atraso dos voos na decolagem é {media_atrasos}')

        return media_atrasos
    """
    2.7) Descobrir dia da semana com maior número de atrasos e mostrar o número médio de atrasos;
    """
    def dia_mais_atrasos(self):
        # dia da semana com maior número de atrasos
        dia = []
        len_coluna = len(self.__data[0:])

        for i in range(1,len_coluna):
            if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0:
                dia.append(self.__data[i][3])

        dia_atrasos = dict(Counter(dia))
        sorted_dia_atrasos = dict(sorted(dia_atrasos.items(), key=operator.itemgetter(1),reverse=True))
        dia_mais_atrasos = list(sorted_dia_atrasos.items())

        # media de atrados do dia con mais atrasos
        media = 0
        cont = 0

        for i in range(1,len_coluna):
            if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0 and self.__data[i][3] == dia_mais_atrasos[0][0] :
                media += int(self.__data[i][15])
                cont += 1

        print(f'O dia da semana com mais atrasos é o {dia_mais_atrasos[0][0]} com média de atrasos igual a {media/cont} minutos')
        return dia_mais_atrasos[0][0]
    """
    2.8) Descobrir mês do ano com maior número de atrasos e mostrar o número de atrasos;
    """
    def mes_mais_atrasos(self):
        # mes do ano com maior número de atrasos
        mes = []
        len_coluna = len(self.__data[0:])

        for i in range(1,len_coluna):
            if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0:
                mes.append(self.__data[i][1])

        mes_atrasos = dict(Counter(mes))
        sorted_mes_atrasos = dict(sorted(mes_atrasos.items(), key=operator.itemgetter(1),reverse=True))
        mes_mais_atrasos = list(sorted_mes_atrasos.items())

        # media de atrados do dia con mais atrasos
        media = 0
        cont = 0

        for i in range(1,len_coluna):
            if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0 and self.__data[i][1] == mes_mais_atrasos[0][0] :
                media += int(self.__data[i][15])
                cont += 1

        print(f'O mes com mais atrasos é o {mes_mais_atrasos[0][0]} com média de atrasos igual a {media/cont} minutos')
        return mes_mais_atrasos[0][0]
    """
    2.9) Listar aeroporto com o maior número de cancelamentos;
    """
    def aeroportos_mais_cancelamentos(self, path_airports, ano):

        f = open(path_airports, "r")
        data = f.readlines()
        f.close()

        # Tira as aspas do arquivo 'airports' e cria uma matriz (data) do conteúdo do arquivo
        # data[i][0] = iata
        # data[i][1] = airport
        # data[i][2] = city
        # data[i][3] = state
        # ...
        # data[i][6] = long

        for i in range(len(data)):
            data[i] = data[i].replace('\n' , '').replace('"', "").split(",")

        # Cria uma lista (aeroportos) do conteúdo da coluna 16 = 'Origin' do arquivo ano.csv
        # contendo só os códigos dos AEROPORTOS que SOFRERAM CANCELAMENTO DE VOOS
        # essa coluna 16 possui o código do aeroporto em que decolou o avião

        aeroportos = []

        len_coluna = len(self.__data[0:])
        # Comprova se o ano ingressado é igual ao ano do arquivo
        if self.__data[1][0] == ano:
            for i in range(1, len_coluna):
                if int(self.__data[i][21]) > 0:
                    aeroportos.append(self.__data[i][16])

        # Se o código do aeroporto que sofreu atraso (aeroportos) for igual
        # ao código do aeroporto na lista 'airports' (coluna 0 da matriz data), é adicionado um novo elemento na lista_aeroporots,
        # contendo o nome do aeroporto que sofreu atraso

        lista_aeroportos = []

        if len(data) > len(aeroportos):

            for i in range (len(aeroportos)):
                for j in range (len(data)):
                    if aeroportos[i] == data[j][0]:
                        lista_aeroportos.append(data[j][1])
        else:

            for i in range (len(data)):
                for j in range (len(aeroportos)):
                    if data[i] == aeroportos[j][0]:
                        lista_aeroportos.append(aeroportos[j][1])

        aeroportos_cancelados = dict(Counter(lista_aeroportos))
        sorted_aeroportos_cancelados = dict(sorted(aeroportos_cancelados.items(), key=operator.itemgetter(1),reverse=True))
        aeroporto_mais_cancelados = list(sorted_aeroportos_cancelados.items())

        return aeroporto_mais_cancelados[0][0]
    """
    2.10) Listar voo com maior número de cancelamentos;
    """
    def voo_mais_cancelamentos(self):

        voos = []
        len_coluna = len(self.__data[0:])

        for i in range(1,len_coluna):
            if int(self.__data[i][21]) > 0:
                voos.append(self.__data[i][9])

        voos_cancelados = dict(Counter(voos))
        sorted_voos_cancelados = dict(sorted(voos_cancelados.items(), key=operator.itemgetter(1),reverse=True))
        voo_mais_cancelado = list(sorted_voos_cancelados.items())

        print(f'O número do voo mais cancelado é {voo_mais_cancelado[0][0]}')

        return voo_mais_cancelado[0][0]

#x = Aeroportos('2006.csv')
y = Aeroportos('teste_2006.csv')
# x.open()
# a = y.atrasos('2006')
# a = y.companhias_atrasos_comprida('carriers.csv', '2006')
# a = y.companhias_atrasos_pequena('carriers.csv', '2006')

# a = y.aeroportos_atrasos_comprida('airports.csv', '2006')
# b = y.aeroportos_atrasos_pequena('airports.csv', '2006')
# print(b)
# a = y.num_atrasos_aeroporto('airports.csv', '2006')
# a = y.num_atrasos_companhia('carriers.csv', '2006')

# a = y.companhias_atrasos_departure('carriers.csv', '2006')
# b = y.companhias_atrasos_comprida('carriers.csv', '2006')
# print(a)
# print(b)
# a = y.companhia_mais_atrasos('carriers.csv', '2006')
# a = y.aeroporto_mais_atrasos('airports.csv', '2006')
# a = y.media_atrasos_decolagem()
# a = y.voo_maior_atraso()
# a = y.dia_mais_atrasos()
# a = y.mes_mais_atrasos()
# a = y.aeroportos_mais_cancelamentos('airports.csv', '2006')
a = y.voo_mais_cancelamentos()
print(a)


# Copyright (C) 2018 Tetsuya Miura <miute.dev@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import copy

from .base import SVGElement, SVGGraphicsElement, SVGPathDataSettings
from .core import CSSUtils, Font, SVGLength
from .dom import Element, Node
from .freetype import FreeType
from .geometry.matrix import DOMMatrix
from .geometry.rect import DOMRect
from .harfbuzz import HBBuffer, HBDirection, HBFeature, HBFTFont, HBLanguage, \
    HBScript
from .icu import UBiDi, UBreakIterator, ULocale
from .opentype import features_from_style, iso639_codes_from_language_tag
from .path import PathParser

class SVGTextContentElement(SVGGraphicsElement):
    """Represents the [SVG2] SVGTextContentElement."""

    _CHARS_ID = 0
    _CHARS_TEXT = 1
    _CHARS_STYLE = 2
    _CHARS_PATH_DATA = 3
    _CHARS_ADVANCE_LIST = 4
    _CHARS_BBOX = 5
    _CHARS_ELEMENT = 6

    def _get_chars_info(self):
        root = self.get_nearest_text_element()
        if root is None:
            return []

        chars_info = SVGTextContentElement._get_descendant_chars_info(
            root, first=True, is_display=True, is_render=True)
        return chars_info

    @staticmethod
    def _get_descendant_chars(element, style_map=None,
                              prev_text=None, first=False, **kwargs):
        """Returns the addressable characters.

        Arguments:
            element (SVGElement):
            style_map (dict, optional):
            prev_text (str, optional):
            first (bool, optional):
            **kwargs: See below.
        Keyword Arguments:
            is_display (bool, optional):
        Returns:
            list[list[int, str, dict, list[SVGPathSegment], list[float], DOMRect,
                SVGElement]]:
                Returns a list of seven numbers <hash value of an element>,
                <text for rendering>, <computed presentation properties>,
                <list of path segments>, <list of advance measure>,
                <bbox> and <element object>.
            str: previous text for rendering.
        """
        is_display = kwargs.get('is_display', False)
        chars_info = list()
        if not element.istext() or (is_display
                                    and not element.isdisplay()):
            return chars_info, prev_text

        if style_map is None:
            style_map = dict()
        key = hash(element)
        style = style_map.get(key)
        if style is None:
            style = element.get_computed_style()
            style_map[key] = copy.deepcopy(style)
        if element.text is not None:
            out_text = CSSUtils.normalize_text_content(
                element,
                element.text,
                style,
                prev_text,
                first)
            if len(out_text) > 0:
                path_data = []
                advance_list = []
                bbox = None
                chars_info.append(
                    [key, out_text, style, path_data, advance_list, bbox,
                     element])
                prev_text = out_text
                first = False

        for child in iter(element):
            if (child.node_type == Node.ELEMENT_NODE
                    and child.istext()
                    and (not is_display
                         or (is_display and child.isdisplay()))):
                child_chars_info, out_text = \
                    SVGTextContentElement._get_descendant_chars(
                        child, style_map, prev_text, first, **kwargs)
                if len(out_text) > 0:
                    chars_info += child_chars_info
                    prev_text = out_text
                    first = False
            if (child.local_name in SVGElement.TEXT_CONTENT_CHILD_ELEMENTS
                    and child.tail is not None):
                out_text = CSSUtils.normalize_text_content(
                    child,
                    child.tail,
                    style,
                    prev_text,
                    first)
                if len(out_text) > 0:
                    path_data = []
                    advance_list = []
                    bbox = None
                    chars_info.append(
                        [key, out_text, style, path_data, advance_list, bbox,
                         element])
                    prev_text = out_text
                    first = False
        return chars_info, prev_text

    @staticmethod
    def _get_descendant_chars_info(root, first=False, **kwargs):
        """Returns the addressable characters.

        Arguments:
            root (SVGElement):
            first (bool, optional):
            **kwargs: See below.
        Keyword Arguments:
            is_display (bool, optional):
            is_render (bool, optional):
        Returns:
            list[list[int, str, dict, list[SVGPathSegment], list[float],
                DOMRect, SVGElement]]:
                Returns a list of seven numbers <hash value of an element>,
                <text for rendering>, <computed presentation properties>,
                <list of path segments>, <list of advance measure>,
                <bbox> and <element object>.
        """
        chars_info, _ = SVGTextContentElement._get_descendant_chars(
            root, first=first, **kwargs)
        if len(chars_info) > 0:
            item = chars_info[-1]
            text = item[SVGTextContentElement._CHARS_TEXT].rstrip()
            item[SVGTextContentElement._CHARS_TEXT] = text

            is_render = kwargs.get('is_render', False)
            if is_render:
                style = chars_info[0][SVGTextContentElement._CHARS_STYLE]
                x_list = style['x']
                if x_list is None:
                    x = 0
                else:
                    x = x_list[0]
                y_list = style['y']
                if y_list is None:
                    y = 0
                else:
                    y = y_list[0]

                style_map = dict()
                for info in iter(chars_info):
                    key = info[SVGTextContentElement._CHARS_ID]
                    style = info[SVGTextContentElement._CHARS_STYLE]
                    style_map[key] = copy.deepcopy(style)

                for info in iter(chars_info):
                    path_data, advance_list, bbox, (x, y) = \
                        SVGTextContentElement._get_text_path_data(
                            info[SVGTextContentElement._CHARS_ELEMENT],
                            style_map,
                            info[SVGTextContentElement._CHARS_TEXT],
                            x, y)
                    info[SVGTextContentElement._CHARS_PATH_DATA] = path_data
                    info[SVGTextContentElement._CHARS_ADVANCE_LIST] = \
                        advance_list
                    info[SVGTextContentElement._CHARS_BBOX] = bbox

        return chars_info

    @staticmethod
    def _get_text_path_data(element, style_map, out_text, start_x, start_y):
        """Returns the addressable characters.

        Arguments:
            element (SVGElement):
            style_map (dict):
            out_text (str): A text for rendering.
            start_x (float):
            start_y (float):
        Returns:
            list[SVGPathSegment]:
            list[float]:
            DOMRect:
            tuple[float, float]:
        """

        def _get_inherited_attribute(_element, _style_map, _key,
                                     _default=None):
            while _element is not None:
                if (_element.node_type == Node.ELEMENT_NODE
                        and _element.istext()
                        and _element.isdisplay()):
                    _style = _style_map.get(hash(_element))
                    if _style is None:
                        _style = _element.get_computed_style()
                        _style_map[hash(_element)] = _style
                    _value = _style.get(_key)
                    if _value is not None:
                        return _value
                _element = _element.getparent()
            return _default

        # TODO: support line-breaking and word-breaking.
        x_list = _get_inherited_attribute(element, style_map, 'x', [])
        y_list = _get_inherited_attribute(element, style_map, 'y', [])
        dx_list = _get_inherited_attribute(element, style_map, 'dx', [])
        dy_list = _get_inherited_attribute(element, style_map, 'dy', [])
        rotate_list = _get_inherited_attribute(
            element, style_map, 'rotate', [])

        style = style_map.get(hash(element))  # computed style
        assert style is not None
        font = Font(element)
        face = font.face
        hb_font = HBFTFont.create(face)

        # alignment_baseline = style['alignment-baseline']
        # baseline_shift = style['baseline-shift']

        direction = style['direction']
        ltr = True if direction == 'ltr' else False

        # dominant_baseline = style['dominant-baseline']

        # font-feature-settings, font-kerning, font-variant-*
        hb_features = list()
        features = features_from_style(style)
        for feature in features:
            hb_features.append(HBFeature.fromstring(feature))

        font_synthesis = style['font-synthesis']
        force_embolden = True if (style['font-weight'] > Font.WEIGHT_NORMAL
                                  and 'weight' in font_synthesis
                                  and (face.style_flags
                                       & FreeType.FT_STYLE_FLAG_BOLD) == 0
                                  ) else False
        force_oblique = True if (style['font-style'] != 'normal'
                                 and 'style' in font_synthesis
                                 and (face.style_flags
                                      & FreeType.FT_STYLE_FLAG_ITALIC) == 0
                                 ) else False

        # glyph_orientation_vertical = style['glyph-orientation-vertical']
        # inline_size = style['inline-size']
        # letter_spacing = style['letter-spacing']
        # line_height = style['line-height']

        # text_anchor = style['text-anchor']
        # vpx, vpy, vpw, vph = element.get_viewport_size()

        # unicode_bidi = style['unicode-bidi']
        # word_spacing = style['word-spacing']

        writing_mode = style['writing-mode']
        horizontal = True if writing_mode in [
            'horizontal-tb', 'lr', 'lr-tb', 'rl', 'rl-tb'] else False
        sideways = True if writing_mode.startswith('sideways') else False

        buf = HBBuffer.create()
        buf.set_cluster_level(HBBuffer.CLUSTER_LEVEL_MONOTONE_CHARACTERS)
        if horizontal:
            if ltr:
                hb_direction = HBDirection(HBDirection.HB_DIRECTION_LTR)
            else:
                hb_direction = HBDirection(HBDirection.HB_DIRECTION_RTL)
        else:
            hb_direction = HBDirection(HBDirection.HB_DIRECTION_TTB)
        buf.set_direction(hb_direction)

        locale = None
        font_language_override = style['font-language-override']
        if font_language_override != 'normal':
            codes = iso639_codes_from_language_tag(font_language_override)
            if codes is not None:
                # FIXME: use correct language code.
                locale = ULocale(codes[0])
        else:
            xml_lang = style.get(Element.XML_LANG)
            if xml_lang is None:
                xml_lang = style.get('lang')
            if xml_lang is not None:
                locale = ULocale(xml_lang)
        if locale is None:
            locale = ULocale.get_default()
        hb_language = HBLanguage.fromstring(locale.get_language())
        buf.set_language(hb_language)
        script = locale.get_script()
        if script is not None and len(script) == 4:
            hb_script = HBScript.fromstring(script)
            buf.set_script(hb_script)
        else:
            hb_script = buf.get_script()

        current_x = start_x
        current_y = start_y
        rotate = 0
        matrix = DOMMatrix()
        path_data_list = list()
        advance_list = list()
        text_bbox = DOMRect()
        metrics = face.size.metrics
        glyph_width = metrics.x_ppem
        glyph_height = metrics.height / 64
        descender = metrics.descender / 64

        para = UBiDi()
        para.set_para(out_text,
                      UBiDi.UBIDI_DEFAULT_LTR if ltr
                      else UBiDi.UBIDI_DEFAULT_RTL)
        max_limit = para.get_processed_length()
        bi = UBreakIterator(UBreakIterator.UBRK_LINE, locale.locale)
        logical_start = 0
        while logical_start < max_limit:
            limit, para_level = para.get_logical_run(logical_start)
            para_level &= 1
            paragraph = out_text[logical_start:limit]
            bi.set_text(paragraph)
            if ((not ltr and para_level == UBiDi.UBIDI_LTR)
                    or (ltr and para_level == UBiDi.UBIDI_RTL)):
                iterable = reversed(bi)
            else:
                iterable = bi
            for line in iterable:
                buf.clear_contents()
                buf.set_language(hb_language)
                buf.set_script(hb_script)
                buf.add_utf8(line)
                buf.guess_segment_properties()
                buf.shape(hb_font, hb_features)
                infos = buf.get_glyph_infos()
                positions = buf.get_glyph_positions()
                if infos[0].cluster > infos[-1].cluster:
                    infos = list(reversed(infos))
                    positions = list(reversed(positions))

                # re-positioning
                if len(infos) != len(line):
                    clusters = [x.cluster for x in infos]
                    cluster_min = min(clusters)
                    cluster_max = max(clusters)
                    cluster_inc = max(
                        (cluster_max - cluster_min) // len(clusters), 1)
                    # try to find ligatures
                    last_cluster = None
                    for offset, cluster in enumerate(clusters):
                        if last_cluster is None:
                            pass
                        elif last_cluster == cluster:
                            pass  # decompose
                        elif last_cluster + cluster_inc == cluster:
                            pass  # do nothing
                        else:
                            # ligature
                            index = logical_start + offset
                            if index < len(x_list):
                                _ = x_list.pop(index)
                            if index < len(y_list):
                                _ = y_list.pop(index)
                            dx_length = len(dx_list)
                            if index < dx_length:
                                dx = dx_list.pop(index)
                                if index < dx_length - 1:
                                    dx_list[index] += dx
                            dy_length = len(dy_list)
                            if index < dy_length:
                                dy = dy_list.pop(index)
                                if index < dy_length - 1:
                                    dy_list[index] += dy
                            rotate_length = len(rotate_list)
                            if rotate_length > 1 and index < rotate_length:
                                _ = rotate_list.pop(index)
                        last_cluster = cluster

                # render line
                line_path_data = list()
                line_bbox = DOMRect()
                for info, position in zip(infos, positions):
                    if len(x_list) > 0:
                        x = x_list.pop(0)
                    else:
                        x = current_x
                    if len(y_list) > 0:
                        y = y_list.pop(0)
                    else:
                        y = current_y
                    if len(dx_list) > 0:
                        dx = dx_list.pop(0)
                    else:
                        dx = 0
                    if len(dy_list) > 0:
                        dy = dy_list.pop(0)
                    else:
                        dy = 0
                    rotate_length = len(rotate_list)
                    if rotate_length == 1:
                        rotate = rotate_list[0]
                    elif rotate_length > 1:
                        rotate = rotate_list.pop(0)

                    x_offset = position.x_offset / 64
                    y_offset = position.y_offset / 64
                    x += dx + x_offset
                    y += dy - y_offset
                    if horizontal:
                        advance = position.x_advance / 64
                        if para_level == UBiDi.UBIDI_RTL:
                            x -= advance
                        glyph_bbox = DOMRect(x,
                                             y - glyph_height - descender,
                                             advance,
                                             glyph_height)
                        x_advance = advance
                        y_advance = 0
                    else:
                        # TODO: fix bbox for vertical text.
                        advance = -position.y_advance / 64
                        if sideways:
                            glyph_bbox = DOMRect(x,
                                                 y,
                                                 glyph_width,
                                                 position.x_advance / 64)
                        else:
                            glyph_bbox = DOMRect(x,
                                                 y - advance + advance + y_offset,
                                                 glyph_width,
                                                 advance)
                        x_advance = 0
                        y_advance = advance
                    advance_list.append(advance)
                    if rotate != 0:
                        matrix.clear()
                        matrix.translate_self(x, y)
                        matrix.rotate_self(rot_z=rotate)
                        matrix.translate_self(-x, -y)
                        glyph_bbox.transform_self(matrix)

                    matrix.clear()
                    if rotate != 0:
                        matrix.rotate_self(rot_z=rotate)
                    matrix.translate_self(x, -y)

                    load_flags = FreeType.FT_LOAD_NO_BITMAP
                    if not horizontal:
                        load_flags |= FreeType.FT_LOAD_VERTICAL_LAYOUT
                    face.load_glyph(info.codepoint, load_flags)
                    glyph = face.glyph
                    if force_embolden:
                        glyph.embolden()
                    if force_oblique:
                        glyph.oblique()
                    path_data = PathParser.from_glyph(face, matrix)
                    if len(path_data) > 0:
                        line_path_data += path_data

                    if para_level == UBiDi.UBIDI_LTR:
                        x += x_advance - x_offset
                    y += y_advance + y_offset
                    line_bbox |= glyph_bbox
                    current_x = x
                    current_y = y
                if horizontal:
                    if ((not ltr and para_level == UBiDi.UBIDI_LTR)
                            or (ltr and para_level == UBiDi.UBIDI_RTL)):
                        k = -1 if not ltr else 1
                        width = line_bbox.width
                        line_bbox.translate_self(k * width, 0)
                        matrix.clear()
                        matrix.translate_self(k * width, 0)
                        line_path_data = PathParser.transform(line_path_data,
                                                              matrix)
                        if not ltr:
                            current_x = line_bbox.left
                        else:
                            current_x = line_bbox.right
                path_data_list += line_path_data
                text_bbox |= line_bbox

            logical_start = limit

        return path_data_list, advance_list, text_bbox, (current_x, current_y)

    def get_bbox(self, options=None, _depth=0):
        """Returns the bounding box of the current element.

        Arguments:
            options (SVGBoundingBoxOptions, optional): Reserved.
            _depth (int, optional): For internal use only.
        Returns:
            DOMRect: The bounding box of the current element.
        """
        bbox = DOMRect()
        chars_info = self._get_chars_info()
        if len(chars_info) == 0:
            return bbox

        for info in iter(chars_info):
            bbox |= info[SVGTextContentElement._CHARS_BBOX]

        return bbox

    def get_computed_geometry(self):
        geometry = dict()
        local_name = self.local_name

        # 'x' attribute
        # Value: [ [ <length> | <percentage> | <number> ]+ ]#
        # Initial: 0 <text>
        # Initial: (none) <tspan>
        default = '0' if local_name == 'text' else None
        _x = self.get('x', default)
        if _x is None:
            x = None
        else:
            x = [
                SVGLength(n,
                          context=self,
                          direction=SVGLength.DIRECTION_HORIZONTAL).value()
                for n in Element.RE_DIGIT_SEQUENCE_SPLITTER.split(_x)
            ]
        geometry['x'] = x

        # 'y' attribute
        # Value: [ [ <length> | <percentage> | <number> ]+ ]#
        # Initial: 0 <text>
        # Initial: (none) <tspan>
        default = '0' if local_name == 'text' else None
        _y = self.get('y', default)
        if _y is None:
            y = None
        else:
            y = [
                SVGLength(n,
                          context=self,
                          direction=SVGLength.DIRECTION_VERTICAL).value()
                for n in Element.RE_DIGIT_SEQUENCE_SPLITTER.split(_y)
            ]
        geometry['y'] = y

        # 'dx' attribute
        # Value: [ [ <length> | <percentage> | <number> ]+ ]#
        # Initial: (none)
        _dx = self.get('dx')
        if _dx is None:
            dx = None
        else:
            dx = [
                SVGLength(n,
                          context=self,
                          direction=SVGLength.DIRECTION_HORIZONTAL).value()
                for n in Element.RE_DIGIT_SEQUENCE_SPLITTER.split(_dx)
            ]
        geometry['dx'] = dx

        # 'dy' attribute
        # Value: [ [ <length> | <percentage> | <number> ]+ ]#
        # Initial: (none)
        _dy = self.get('dy')
        if _dy is None:
            dy = None
        else:
            dy = [
                SVGLength(n,
                          context=self,
                          direction=SVGLength.DIRECTION_VERTICAL).value()
                for n in Element.RE_DIGIT_SEQUENCE_SPLITTER.split(_dy)
            ]
        geometry['dy'] = dy

        # 'rotate' attribute
        # Value: [ <number>+ ]#
        # Initial: (none)
        _rotate = self.get('rotate')
        if _rotate is None:
            rotate = None
        else:
            rotate = [
                float(t) for t in
                Element.RE_DIGIT_SEQUENCE_SPLITTER.split(_rotate)
            ]
        geometry['rotate'] = rotate

        return geometry

    def get_computed_text_length(self):
        return self.get_sub_string_length()

    def get_chars(self):
        """Returns the addressable characters available for rendering within
        the current element.

        Returns:
            str: The addressable characters or None.
        """
        root = self.get_nearest_text_element()
        if root is None:
            return None

        chars_info = SVGTextContentElement._get_descendant_chars_info(
            root, first=True, is_display=True)
        local_name = self.local_name
        if local_name == 'text':
            out = ''.join([x[SVGTextContentElement._CHARS_TEXT]
                           for x in chars_info])
            return out
        elif local_name in SVGElement.TEXT_CONTENT_CHILD_ELEMENTS:
            out = [x[SVGTextContentElement._CHARS_TEXT]
                   for x in chars_info
                   if x[SVGTextContentElement._CHARS_ID] == hash(self)]
            if len(out) == 0:
                return None
            return out[0]
        return None

    def get_nearest_text_element(self):
        element = self
        while element is not None:
            if element.local_name == 'text':
                return element
            element = element.getparent()
        return None

    def get_number_of_chars(self):
        """Returns the total number of addressable characters available for
        rendering within the current element.

        Returns:
            int: The total number of addressable characters.
        """
        chars = self.get_chars()
        if chars is None:
            return 0
        return len(chars)

    def get_path_data(self, settings=None):
        """Returns a list of path segments that corresponds to the path data.

        Arguments:
            settings (SVGPathDataSettings, optional): If normalize is set to
                True then the returned list of path segments is converted to
                the base set of absolute commands ('M', 'L', 'C' and 'Z').
        Returns:
            list[SVGPathSegment]: A list of path segments.
        """
        path_data = list()
        chars_info = self._get_chars_info()
        if len(chars_info) == 0:
            return path_data

        for info in iter(chars_info):
            path_data += info[SVGTextContentElement._CHARS_PATH_DATA]

        if settings is not None:
            if not isinstance(settings, SVGPathDataSettings):
                raise TypeError('Expected SVGPathDataSettings, got {}'.format(
                    type(settings)))
            if settings.normalize:
                path_data = PathParser.normalize(path_data)
        return path_data

    def get_sub_string_length(self, char_num=0, nchars=-1):
        root = self.get_nearest_text_element()
        if root is None:
            return 0

        chars_info = SVGTextContentElement._get_descendant_chars_info(
            root, first=True, is_display=True, is_render=True)
        local_name = self.local_name
        advance_list = list()
        if local_name == 'text':
            for item in iter(chars_info):
                advance_list += item[SVGTextContentElement._CHARS_ADVANCE_LIST]
        elif local_name in SVGElement.TEXT_CONTENT_CHILD_ELEMENTS:
            out = [x[SVGTextContentElement._CHARS_ADVANCE_LIST]
                   for x in chars_info
                   if x[SVGTextContentElement._CHARS_ID] == hash(self)]
            if len(out) == 0:
                return 0
            advance_list = out[0]
        else:
            raise NotImplementedError

        if nchars == -1:
            last = len(advance_list)
        else:
            last = char_num + nchars
        return sum(advance_list[char_num:last])

    def get_total_length(self):
        """Returns the total length of the path.

        Returns:
            float: The total length of the path.
        """
        _ = self
        return 0

class SVGTextPositioningElement(SVGTextContentElement):
    """Represents the [SVG2] SVGTextPositioningElement."""
    pass


import platform

if platform.system() != "Windows":
   raise Exception("Only Windows support!")

import winreg, os
from copy import deepcopy

def env_dict(arch):
    ret = {}
    hk = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Microsoft SDKs\\Windows\\v7.1A")
    try:
        p = winreg.QueryValueEx(hk, "InstallationFolder")[0]
        ret["INCLUDE"] = os.path.join(p, "Include")
        ret["PATH"] = os.path.join(p, "Bin", "x64") if arch == "x86_64" else os.path.join(p, "Bin")
        ret["LIB"] = os.path.join(p, "Lib", "x64") if arch == "x86_64" else os.path.join(p, "Lib")
        ret["CL"] = "/D_USING_V110_SDK71_"
        ret["LINK"] = "/SUBSYSTEM:CONSOLE,5.02" if arch == "x86_64" else "/SUBSYSTEM:CONSOLE,5.01"
    except WindowsError:
        pass
    return ret

def dict_append(arch, env={}, sdk=None):
    if sdk is None:
        sdk = env_dict(arch)
    ret = deepcopy(env)
    if not sdk.get("INCLUDE") is None:
        if not ret.get("INCLUDE") is None:
            ret["INCLUDE"] = sdk["INCLUDE"] + ";" + ret["INCLUDE"]
        else:
            ret["INCLUDE"] = sdk["INCLUDE"]
    if not sdk.get("PATH") is None:
        if not ret.get("PATH") is None:
            ret["PATH"] = sdk["PATH"] + ";" + ret["PATH"]
        else:
            ret["PATH"] = sdk["PATH"]
    if not sdk.get("LIB") is None:
        if not ret.get("LIB") is None:
            ret["LIB"] = sdk["LIB"] + ";" + ret["LIB"]
        else:
            ret["LIB"] = sdk["LIB"]
    if not sdk.get("CL") is None:
        if not ret.get("CL") is None:
            ret["CL"] = sdk["CL"] + " " + ret["CL"]
        else:
            ret["CL"] = sdk["CL"]
    if not sdk.get("LINK") is None:
        if not ret.get("LINK") is None:
            ret["LINK"] = sdk["LINK"] + " " + ret["LINK"]
        else:
            ret["LINK"] = sdk["LINK"]
    return ret


import pickle
import cv2
import face_recognition

class FaceDetector:
    def __init__(self, model = "hog", encodings_file = "../FaceEncodings.pickle"):
        """
        :param model: 'hog' or 'cnn'
        """
        self.frame = None
        self.faces = None
        self.landmarks = None
        self.model = model
        self.encodings_file = encodings_file
        self.data = pickle.loads(open(encodings_file, "rb").read())
        self.r = 1

    def _analyze(self):
        # convert the input frame from BGR to RGB then
        rgb = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
        # resize it to have a width of 750px (to speedup processing)
        # rgb = imutils.resize(rgb, width=750)
        self.r = self.frame.shape[1] / float(rgb.shape[1])

        # detect the (x, y)-coordinates of the bounding boxes
        # corresponding to each face in the input frame, then compute
        # the facial embeddings for each face
        boxes = face_recognition.face_locations(rgb, model=self.model)
        encodings = face_recognition.face_encodings(rgb, boxes)
        names = []

        # loop over the facial embeddings
        for encoding in encodings:
            # attempt to match each face in the input image to our known
            # encodings
            matches = face_recognition.compare_faces(self.data["encodings"], encoding)
            name = "Unknown"

            # check to see if we have found a match
            if True in matches:
                # find the indexes of all matched faces then initialize a
                # dictionary to count the total number of times each face
                # was matched
                matchedIdxs = [i for (i, b) in enumerate(matches) if b]
                counts = {}

                # loop over the matched indexes and maintain a count for
                # each recognized face face
                for i in matchedIdxs:
                    name = self.data["names"][i]
                    counts[name] = counts.get(name, 0) + 1

                # determine the recognized face with the largest number
                # of votes (note: in the event of an unlikely tie Python
                # will select first entry in the dictionary)
                name = max(counts, key=counts.get)

            # update the list of names
            names.append(name)

        self.faces = zip(boxes, names)

    def refresh(self, frame):
        """Refreshes the frame and analyzes it."""
        self.frame = frame
        self._analyze()

    def annotate_frame(self):
        frame = self.frame.copy()
        # print(frame)
        colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]
        # loop over the recognized faces
        for i, ((top, right, bottom, left), name) in enumerate(self.faces):
            color = colors[i%len(colors)]
            # rescale the face coordinates
            top = int(top * self.r)
            right = int(right * self.r)
            bottom = int(bottom * self.r)
            left = int(left * self.r)

            # draw the predicted face name on the image
            cv2.rectangle(frame, (left, top), (right, bottom), color, 2)
            y = top - 15 if top - 15 > 15 else bottom + 20
            cv2.putText(frame, name, (left, y), cv2.FONT_HERSHEY_SIMPLEX, 0.75, color, 2)
        return frame


import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import scipy.optimize as spopt
import scipy.fftpack as spfft
import scipy.ndimage as spimg
import imageio
import cvxpy as cvx

import torch
from torch.autograd import Variable
import torch.optim as optim
# from torch.nn.functional import normalize
from torchvision.transforms import Normalize,ToTensor

def dct2(x):
    return spfft.dct(spfft.dct(x.T, norm='ortho', axis=0).T, norm='ortho', axis=0)

def idct2(x):
    return spfft.idct(spfft.idct(x.T, norm='ortho', axis=0).T, norm='ortho', axis=0)

# Xorig = imageio.imread('Escher_Waterfall.jpg', as_gray=True, pilmode='L')
Xorig = imageio.imread('rome.jpg', as_gray=True, pilmode='L')
# ny, nx = Xorig.shape
# print(ny,nx)
X = spimg.zoom(Xorig, 0.04)
ny, nx = X.shape
print(X.shape)
# plt.imshow(Xorig)
# plt.imshow(X)
# plt.show()

# print(X.mean(),X.max(),X.min())
# X = X-128
# X = X/128
# print(X.mean(),X.max(),X.min())

# extract small sample of signal
k = round(nx * ny * 0.5)  # 50% sample
ri = np.random.choice(nx * ny, k, replace=False)
print("ri/n",ri.shape)
b = X.T.flat[ri]
# b = np.expand_dims(b, axis=1)
print(b.shape)

# create dct matrix operator using kron
A = np.kron(
    spfft.idct(np.identity(nx), norm='ortho', axis=0),
    spfft.idct(np.identity(ny), norm='ortho', axis=0)
)
print('before',A.shape)
A = A[ri, :]
print('after',A.shape)

mask = np.zeros(X.shape)
mask.T.flat[ri] = 255
Xm = 255 * np.ones(X.shape)
Xm.T.flat[ri] = X.T.flat[ri]

# do L1 optimization
vx = cvx.Variable(nx * ny)
objective = cvx.Minimize(cvx.norm(vx, 1))
constraints = [A * vx == b]
prob = cvx.Problem(objective, constraints)
result = prob.solve(verbose=True)
Xat2 = np.array(vx.value).squeeze()

# vx = Variable(torch.randn(nx*ny,dtype=float),requires_grad=True)
# vx = Variable(torch.tensor(Xm.flatten(),dtype=float),requires_grad=True)

# vx[ri].detach_()
# A = Variable(torch.tensor(A,dtype=float))
# b = Variable(torch.tensor(b,dtype=float))

# num_epochs = 31000
# optimzier = optim.Adam([vx],lr=0.01)
# loss_fn = torch.nn.L1Loss(reduce=False, size_average=False)

# loss = 1000000
# epoch = 0

# while(loss > 2.5):
#     epoch += 1
#     optimzier.zero_grad()
#     b_pred = torch.mv(A,vx)
#     loss = loss_fn(b_pred,b).sum()
#     loss = ((b_pred-b)**2).sum()
#     loss.backward(retain_graph=True)
#     # vx = normalize(vx,p=2,dim=-1)
#     optimzier.step()
#     if epoch % 100 == 0:
#         print(epoch,"loss: {:.3f}".format(loss.data))

# Xat2 = vx.detach().numpy()

# reconstruct signal
Xat = Xat2.reshape(nx, ny)
Xa = idct2(Xat)

# confirm solution
if not np.allclose(X.T.flat[ri], Xa.T.flat[ri]):
    print("Warning values at sample indices dont match original")

# create images of mask ( for visualization)
mask = np.zeros(X.shape)
mask.T.flat[ri] = 255
Xm = 255 * np.ones(X.shape)
Xm.T.flat[ri] = X.T.flat[ri]

plt.figure()
plt.imshow(X, cmap='gray')
plt.title('X')
# plt.figure()
# plt.imshow(A, cmap='gray')
plt.figure()
plt.imshow(Xm, cmap='gray')

plt.figure()
plt.imshow(Xat.T, cmap='gray')
plt.title('xat')

plt.figure()
plt.imshow(Xa.T, cmap='gray')
plt.title('xa')
plt.show()
# plt.savefig('2d.png',dpi=300)
print(((X-Xa.T)**2).sum())


#!/usr/bin/python3.6
# coding: utf-8

import logging

from neverland.exceptions import ArgumentError
from neverland.protocol.crypto.mode import Modes
from neverland.protocol.crypto.openssl import OpenSSLCryptor, load_libcrypto
from neverland.protocol.crypto.kc.aead.gcm import GCMKernelCryptor

logger = logging.getLogger('Crypto')

openssl_ciphers = {
    cipher: OpenSSLCryptor for cipher in OpenSSLCryptor.supported_ciphers
}

kc_aead_ciphers = {
    cipher: GCMKernelCryptor for cipher in GCMKernelCryptor.supported_ciphers
}

supported_ciphers = dict()
supported_ciphers.update(openssl_ciphers)
supported_ciphers.update(kc_aead_ciphers)

openssl_preload_func_map = {
    cipher: load_libcrypto for cipher in OpenSSLCryptor.supported_ciphers
}

preload_funcs = {}
preload_funcs.update(openssl_preload_func_map)

ALL_CIPHERS = list(supported_ciphers.keys())

def preload_crypto_lib(cipher_name, libpath=None):
    preload_func = preload_funcs.get(cipher_name)
    if preload_func is not None:
        preload_func(libpath)

class Cryptor():

    # we tag the cryptor with a label of the socket address of the remote node
    # type: str, format: "ip:port"
    attribution = None

    def __init__(self, config, key=None, iv=None, attribution=None):
        ''' Constructor

        :param config: the config
        :param key: optional, if this argument is not given, then the default
                    key derived by neverland.utils.HashTools.hkdf will be used
        :param iv: optional, if this argument is not given, then the default
                   IV derived by neverland.utils.HashTools.hdivdf will be used
        :param attribution: a tag about which remote node that this cryptor
                            belongs to.
        '''

        self.config = config
        self.attribution = attribution

        self._cipher_name = self.config.net.crypto.cipher
        self._cipher_cls = supported_ciphers.get(self._cipher_name)

        if self._cipher_cls is None:
            raise Exception('unsupported cipher')

        if self._cipher_name.startswith('kc-'):
            self._cipher_cls.check_kernel_version()

        self._init_ciphers(key, iv)

        logger.info(
            f'Loadded crypto implementation {self._cipher_cls.__name__} '
            f'with cipher {self._cipher_name}'
        )

    def _init_ciphers(self, key, iv):
        self._cipher = self._cipher_cls(self.config, Modes.ENCRYPTING, key, iv)
        self._decipher = self._cipher_cls(self.config, Modes.DECRYPTING, key, iv)

    def reset(self):
        self._cipher.reset()
        self._decipher.reset()

    def encrypt(self, data):
        return self._cipher.update(data)

    def decrypt(self, data):
        return self._decipher.update(data)

    @property
    def iv(self):
        return self._cipher._iv


# -*- coding: utf-8 -*-
"""
Created on Mon Oct 19 20:59:22 2020

@author: SA20149963
"""
import spacy
import PyPDF2

nlp = spacy.load('en_core_web_sm')

def get_pdf_content(filename):
    pdf = open(filename, 'rb')
    # Creating pdf reader object.
    pdf_reader = PyPDF2.PdfFileReader(pdf)
    # Checking total number of pages in a pdf file.
   # print("Document Metadata:", pdf_reader.getDocumentInfo())
    # Creating a page object.
    pages = pdf_reader.numPages
    # Extract data from a specific page number.
    content = ''
   # metadata = pdf_reader.getDocumentInfo()
    for i in range(pages):
        page=pdf_reader.getPage(i)
        content = content + page.extractText().replace("\n","").lower()
    pdf.close()
    return content.encode("ascii",errors='namereplace').decode()

def extract_relations(doc):

    spans = list(doc.ents) + list(doc.noun_chunks)
    for span in spans:
        span.merge()

    triples = []

    for ent in doc.ents:
        preps = [prep for prep in ent.root.head.children if prep.dep_ == "prep"]
        for prep in preps:
            for child in prep.children:
                triples.append((ent.text, "{} {}".format(ent.root.head, prep), child.text))
    return triples
pdf_content = get_pdf_content(r'D:\OSDU\Unstructured_Data\prov22.pdf')
content_from_nlp = nlp(pdf_content)
sentences = list (content_from_nlp.sents)

for text in sentences:
    print("\n" + str(text))
    relations = extract_relations(nlp(str(text)))
    for r1, r2, r3 in relations:
        print('({}, {}, {}) '.format(r1, r2, r3))


from readTiff import tiffHandle
from osgeo import gdal
import numpy as np
import osr
import argparse
from perpendicular_distance import perp_dist
from exampleDP.py import generaliseDP
import matplotlib.pyplot as plt
from interpolatePoints import interpolateLine
from scipy import interpolate
import pseudoRaster

class contour_lines_(tiffHandle):

    def sortZ(self):
        '''
        Function to make sure each z is int for the following calculation
        '''
        self.newZ = int(self.z)

    def contour_lines_range(self,interval):
        '''
        Function to determine interval by user and set each value based on the interval
        '''
        maxZ = max(self.newZ)
        minZ = min(self.newZ)
        lenZ = maxZ-minZ

        self.block = int(lenZ/interval)

        # set values
        if(np.where(self.data == 0)):
            return -999.0
        else:
            for i in range(1,self.block):
                newblock = self.block*i
                eachrange = minZ+self.block*i
                self.interval_range= np.where(self.data == newblock, eachrange)
                i = i + 1

    def plot_contour_line(self,res,bounds):
        '''
        Function to plot contour line by interpolateline
        '''
        pseudoRaster(res,bounds)
        #Construct a 2-D grid and interpolate on it
        x = np.arrange(self.minX,self.maxX,self.interval_range)
        y = np.arrange(self.minY,self.maxY,self.interval_range)
        xx, yy = np.meshgrid(x, y)
        z = self.newZ
        f = interpolate.interp2d(x, y, z, kind='cubic')

        #use the obtained interpolation function and plot the result
        xnew = np.arange(self.minX,self.maxX,self.interval_range)
        ynew = np.arange(self.minY,self.maxY,self.interval_range)
        znew = f(xnew, ynew)

        #process of connecting the dots by plt.contourf(it can also help create contour line)
        contourf = plt.contourf(xnew, ynew, znew, self.interval_range, alpha=.6, cmap=plt.cm.jet)

        #use Douglas-Peucker line generalisation(maybe unnecessary due to the type of 'cubic')
        startInd=0
        endInd=len(xnew)-1
        # create a list to hold the results. Put first two breakpoints in
        nodeIndices=[startInd,endInd]
        # call generaliser
        generaliseDP(startInd,endInd,xnew,ynew,contourf,nodeIndices)
        # sort the indices, as they will be in a funny order
        sortedIndices=np.sort(nodeIndices)

        plt.show(sortedIndices)

if __name__=="__main__":
    filename = 'task2_map1_3.tif'

    tiffHandle.readTiff(filename)
    contour_lines_range(10)


from src.helpers.helper import \
    DATA_CARSTATUS_PATH, \
    DEFAULT_SUBSCRIBED_TOPIC, \
    CAR_INDEX, DATA_PATH, \
    TS_INDEX, \
    INDEX_LIMIT, \
    POS, \
    SPEED, \
    event_car_position_msg, \
    extract_gps_data, \
    extract_timestamp, \
    find_velocity_mph, \
    find_distance_meter, \
    create_carstatus_topic_data, \
    find_positions, \
    write_file

from src.publish_topics import publish_carstatus_topic, publish_events_topic
from ftfy import fix_text
from collections import deque

import os
import json
import glob

car_long_lat_data = []

def write_raw_data(msg):
    """Function to write the raw data to file for each car from subscribed topic
    carCoordinates

    :param msg: dictionary containing topic info and data
    """

    if msg.topic == DEFAULT_SUBSCRIBED_TOPIC:
        car = json.loads(
            msg.payload.decode()
        )[CAR_INDEX]

        raw_data = f'{car}' + '_' + DEFAULT_SUBSCRIBED_TOPIC + '.txt'

        # in a real application this would have been perhaps an S3 bucket writing
        # instead! (Minio locally) but let's keep it simple!
        path = os.path.join(DATA_PATH, raw_data)

        with open(path, 'a') as raw_data_file:
            raw_data_file.writelines(msg.payload.decode() + '\n')

        transform_topic_data(car)

    else:
        raise ValueError('wrong topic')

def load_subscribed_topics(client, path=DATA_CARSTATUS_PATH):
    """Function will read the data from the subscribed raw carStatus topic written to each car,
    sends them to be published.

    :param client: the mqtt client
    :param path: path for subscribed topic data
    """
    for filename in glob.iglob(path + '**/*', recursive=True):

        with open(filename, 'r') as file:
            rows = deque(file, 2)

            if len(rows) == 2:
                row0, row1 = rows[0], rows[1]

                if isinstance(row0, str):
                    row0 = fix_text(row0)
                    data0, data1 = json.loads(row0), json.loads(row1)

                else:
                    data0, data1 = json.loads(row0.decode('utf-8')), json.loads(row1.decode('utf-8'))

                if data1['type'] == 'SPEED':
                    publish_carstatus_topic(data1, 'SPEED', client)

                elif data1['type'] == 'POSITION':
                    ts = data1.get(TS_INDEX)
                    pos0, pos1 = data0.get('value'), data1.get('value')

                    publish_carstatus_topic(data1, 'POSITION', client)
                    msg = event_car_position_msg(data1, pos0, pos1)

                    if len(msg) > 0:
                        publish_events_topic(msg, ts, client)

                    file.close()

def transform_topic_data(car):
    """Function to retrieve information to create carstatus topic, will
    write data to file
    :param car: actual car
    """
    topic_filename = f'{car}' + '_' + DEFAULT_SUBSCRIBED_TOPIC + '.txt'

    with open(os.path.join(DATA_PATH, topic_filename), 'r') as raw_data_file:
        raw_data_carstatus = deque(raw_data_file, maxlen=2)

        st0, st1 = extract_gps_data(raw_data_carstatus)
        t0, t1 = extract_timestamp(raw_data_carstatus)

        if len(car_long_lat_data) == INDEX_LIMIT:
            car_long_lat_data[car] = [st1]
            car_positions = find_positions(car_long_lat_data)

            topic_carstatus_position = f'{car}' + '_carStatus_position.txt'

            # write position
            write_file(
                topic_carstatus_position,
                create_carstatus_topic_data(t1, car, POS, car_positions[car][1] + 1),
                DATA_CARSTATUS_PATH
            )

        else:
            car_long_lat_data.append([st1])

        distance = find_distance_meter(st0, st1)
        curr_speed = find_velocity_mph(distance, t0, t1)
        topic_carstatus_speed = f'{car}' + '_carStatus_speed.txt'

        # write speed
        write_file(
            topic_carstatus_speed,
            create_carstatus_topic_data(t1, car, SPEED, curr_speed),
            DATA_CARSTATUS_PATH
        )


class Node(object):
    def __init__(self,data):
        self.item=data
        self.ref=None

class LinkedList(object):
    def __init__(self):
        self.start_node=None

    #Insert element at the end
    def insert_at_end(self,data):
        new_node=Node(data)
        if self.start_node is None:
            self.start_node=new_node
            return
        n=self.start_node
        while n.ref is not None:
            n=n.ref
        n.ref=new_node
        return

    def make_new_list(self):
        nums = int(input("How many nodes do you want to create: "))
        if nums == 0:
            return
        for i in range(nums):
            value = int(input("Enter the value for the node:"))
            self.insert_at_end(value)

    def traverse(self):
        if self.start_node is None:
            print("Linked list is empty")
            return
        else:
            n=self.start_node
            while n is not None:
                print(n.item)
                n=n.ref

    #Sort by data exchange
    def bub_sort_datachange(self):
        end=None
        while(end!=self.start_node):
            p = self.start_node
            while(p.ref !=end):
                q=p.ref
                if(p.item > q.item):
                    p.item,q.item=q.item,p.item
                p=p.ref
            end=p

ob=LinkedList()
ob.make_new_list()
ob.bub_sort_datachange()
ob.traverse()


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

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os
import sys
import unittest

sys.path.append(os.path.abspath('../../../../../../'))
from examples.csj.s5.exp.dataset.load_dataset import Dataset
from utils.io.labels.character import Idx2char
from utils.io.labels.word import Idx2word
from utils.measure_time_func import measure_time

class TestLoadDataset(unittest.TestCase):

    def test(self):

        # self.check(label_type='kanji_wb_left', data_type='eva1')
        # self.check(label_type='kanji_wb_right', data_type='eva1')
        # self.check(label_type='kanji_wb_both', data_type='eva1')
        # self.check(label_type='kanji_wb_remove', data_type='eva1')
        #
        # raise ValueError

        # data_size
        self.check(label_type='word', data_type='eval1', data_size='aps_other')
        self.check(label_type='word', data_type='eval1', data_size='all')

        # data_type
        # self.check(label_type='word', data_type='train')
        self.check(label_type='word', data_type='dev')
        self.check(label_type='word', data_type='eval1')
        self.check(label_type='word', data_type='eval2')
        self.check(label_type='word', data_type='eval3')

        # label_type
        self.check(label_type='kanji')
        self.check(label_type='kanji_wb')
        # self.check(label_type='kana')
        # self.check(label_type='kana_wb')
        # self.check(label_type='phone')
        # self.check(label_type='phone_wb')
        self.check(label_type='pos')

        # sort
        self.check(label_type='word', sort_utt=True, sort_stop_epoch=True)

        # frame stacking
        self.check(label_type='word', frame_stacking=True)

        # splicing
        self.check(label_type='word', splice=11)

        # multi-GPU
        # self.check(label_type='word', num_gpus=8)

    @measure_time
    def check(self, label_type, data_type='dev',
              data_size='all', backend='pytorch',
              shuffle=False, sort_utt=True, sort_stop_epoch=None,
              frame_stacking=False, splice=1, num_gpus=1):

        print('========================================')
        print('  backend: %s' % backend)
        print('  label_type: %s' % label_type)
        print('  data_type: %s' % data_type)
        print('  data_size: %s' % data_size)
        print('  shuffle: %s' % str(shuffle))
        print('  sort_utt: %s' % str(sort_utt))
        print('  sort_stop_epoch: %s' % str(sort_stop_epoch))
        print('  frame_stacking: %s' % str(frame_stacking))
        print('  splice: %d' % splice)
        print('  num_gpus: %d' % num_gpus)
        print('========================================')

        num_stack = 3 if frame_stacking else 1
        num_skip = 3 if frame_stacking else 1
        dataset = Dataset(
            data_save_path='/n/sd8/inaguma/corpus/csj/kaldi',
            backend=backend,
            input_freq=80, use_delta=True, use_double_delta=True,
            data_type=data_type, data_size=data_size,
            label_type=label_type, batch_size=64,
            max_epoch=1, splice=splice, num_stack=num_stack, num_skip=num_skip,
            min_frame_num=40, shuffle=shuffle,
            sort_utt=sort_utt, reverse=False, sort_stop_epoch=sort_stop_epoch,
            num_gpus=num_gpus, tool='htk', num_enque=None)

        print('=> Loading mini-batch...')
        if 'word' in label_type:
            map_fn = Idx2word(dataset.vocab_file_path)
        else:
            map_fn = Idx2char(dataset.vocab_file_path)

        for batch, is_new_epoch in dataset:
            if data_type == 'train' and backend == 'pytorch':
                for i in range(len(batch['xs'])):
                    if batch['xs'].shape[1] < batch['ys'].shape[1]:
                        raise ValueError(
                            'input length must be longer than label length.')

            if dataset.is_test:
                str_true = batch['ys'][0][0]
            else:
                str_true = map_fn(batch['ys'][0][:batch['y_lens'][0]])

            print('----- %s (epoch: %.3f, batch: %d) -----' %
                  (batch['input_names'][0], dataset.epoch_detail, len(batch['xs'])))
            print(str_true)
            print('x_lens: %d' % (batch['x_lens'][0] * num_stack))
            if not dataset.is_test:
                print('y_lens: %d' % batch['y_lens'][0])

            if dataset.epoch_detail >= 0.1:
                break

if __name__ == '__main__':
    unittest.main()


import pandas as pd
import numpy as np
import pandas_datareader.data as web
import empyrical as ep
import scipy.stats as stats
import warnings
import dash_html_components as html
import pickle
import time
from functools import lru_cache

with warnings.catch_warnings():
    warnings.filterwarnings(
        'ignore',
        'axes.color_cycle is deprecated',
        UserWarning,
        'matplotlib',
    )
    import seaborn as sns

@lru_cache(typed=False) ##### the single most important line in the app
def get_raw_backtest(backtest_file):
    with open(backtest_file, 'rb') as f:
        history, run_config = pickle.load(f)
    return history, run_config

@lru_cache(typed=False)
def get_backtest(file_name, data_dir ="/home/user/Backtests/processed/"):
    with open(data_dir+ file_name, 'rb') as f:
        data = pickle.load(f)
    return data

def get_summary(backtest_files):

    sum_headers = ["Backtest name", "Average return, %", "Sharpe ratio", "Max drawdown from start, %"]

    names_list = [x[:len(x) - 7] for x in backtest_files]

    data_list = [get_backtest(x) for x in backtest_files]
    returns_list = [get_common_returns(data) for data in data_list]
    sharpe_list = ["{0:.3g}".format(ep.sharpe_ratio(x)) for x in returns_list]

    AR_list = []
    dd_from_start_list = []
    for k in data_list:
        AR, dd_from_start = stat_from_start(k.Rcum)
        AR_list.append("{0:.3g}".format(AR))
        dd_from_start_list.append("-{0:.3g}".format(dd_from_start))

    return sum_headers, pd.Series(names_list), pd.Series(AR_list), pd.Series(sharpe_list), pd.Series(dd_from_start_list)

# processing backtest results
def get_common_returns(data):
    dailyCumReturns = data.Rcum.resample("B").last()
    returns = ep.simple_returns(dailyCumReturns)
    returns = returns.fillna(method="ffill")

    return returns

def stat_from_start(dailyCumReturns):

    initial_capital = 50000

    # drawdown manually
    local_max = dailyCumReturns.cummax()
    dd_from_start = (np.max((local_max - dailyCumReturns)) / initial_capital *100)

    dailyCumReturns = dailyCumReturns.resample("B").last()
    R = (dailyCumReturns.iloc[1:] - dailyCumReturns.iloc[:-1].values) / initial_capital
    return_yearly = R.mean() * 252
    AR = return_yearly * 100

    return AR, dd_from_start

def get_benchmark_info(benchmark_ticker='SPX'):

    #since we are aware of the period of the backtests from the very beginning
    #this part is hard-coded
    start = pd.Timestamp(2015, 1, 14)
    end = pd.Timestamp(2018, 4, 6)
    benchmark = web.DataReader("%s" % benchmark_ticker, 'morningstar', start, end)

    prices = pd.Series(data=benchmark.Close.reset_index().Close.values,
                       index=benchmark.Close.reset_index().Date)
    benchmark_rets = prices.pct_change().iloc[1:]
    benchmark_rets = benchmark_rets.fillna(method="bfill")

    benchmark_rets = benchmark_rets.tz_localize("UTC")

    return benchmark_rets

def process_bckst_for_risk_analysis(data):

    '''
    @returns: non-cumulative returns,
              margin_contract,
              margin_MValue,
              AR, dd_from_start,
              benchmark_rets
    '''

    initial_capital = 50000
    BPS = 10000
    multiplier = 1000

    #total_ret_pct = 100 * (data.Rcum[-1] - initial_capital) / initial_capital
    total_ret_usd = data.Rcum[-1] - initial_capital

    margin_contract = np.around(total_ret_usd / data.TrdVolume.abs().sum(), 4)  # margin in usd/contracts
    margin_MValue = np.around(total_ret_usd / (data.TrdMVal.abs().sum() * multiplier) * BPS, 4)  # margin in bps

    AR, dd_from_start = stat_from_start(data.Rcum)

    returns = get_common_returns(data)

    return returns, margin_contract, margin_MValue, AR, dd_from_start

#for performance graphs
def get_info_for_performance_graph(data, benchmark_ticker='SPX'):

    BacktestReturns = data.Rcum.resample("B").last()

    BacktestReturns = BacktestReturns.fillna(method="ffill")

    return BacktestReturns

def get_info_for_underwater_graph(data):

    returns = get_common_returns(data)

    df_cum_rets = ep.cum_returns(returns, starting_value=1.0)
    running_max = np.maximum.accumulate(df_cum_rets)
    underwater = -100 * ((running_max - df_cum_rets) / running_max)
    underwater = underwater[:len(returns)]

    return underwater

#for graphs depending on margin
def calc_ret(data, var_cost, start_capital=50000):
    table = data.copy()

    costs = np.cumsum(var_cost * (table.TrdMVal.abs()) * 1000)
    Rcum = start_capital + np.cumsum(table.R * 1000) - costs

    dailyCumReturns = Rcum.resample("B").last()
    returns = dailyCumReturns.pct_change().iloc[1:]

    return returns

def margin_stat(data):

    initial_capital = 50000

    total_ret_usd = data.Rcum[-1] - initial_capital

    BPS = 10000
    multiplier = 1000
    margin_MValue = round(total_ret_usd / (data.TrdMVal.abs().sum() * multiplier) * BPS, 4)  # margin in bps

    costs = np.arange(0.0, margin_MValue / BPS, 0.01)

    #calculating different returns depending on different costs
    returns_list = [calc_ret(data, var_cost) for var_cost in costs]

    an_ret_list = [ep.annual_return(returns) for returns in returns_list]
    sharpe_list = [ep.sharpe_ratio(returns) for returns in returns_list]
    dd_list = [ep.max_drawdown(returns) for returns in returns_list]

    an_returns = pd.Series(an_ret_list, index=costs) * 100
    sharpe = pd.Series(sharpe_list, index=costs)
    dd = pd.Series(dd_list, index=costs) * 100

    return an_returns, sharpe, dd

#for stats table depending on costs
def calc_costs_stat(data, commission, slippage, pip = 15.625):

    trade_data = data[data.TrdVolume != 0]
    total_trades = len(trade_data)
    # number of trades in-position
    #number_in = len([trade_data.index[i] for i in range(len(trade_data.index)) if
         #      time.strftime(str(trade_data.index[i]))[11:] == time.strftime("17:30:00+00:00")])
    # number of no trades - when just waiting for expiration
    wait_1 = len([trade_data.index[i] for i in range(len(trade_data.index)) if
                time.strftime(str(trade_data.index[i]))[11:] == time.strftime("21:50:00+00:00")])
    wait_2 = len([trade_data.index[i] for i in range(len(trade_data.index)) if
                  time.strftime(str(trade_data.index[i]))[11:] == time.strftime("22:10:00+00:00")])
    wait_3 = len([trade_data.index[i] for i in range(len(trade_data.index)) if
                  time.strftime(str(trade_data.index[i]))[11:] == time.strftime("20:50:00+00:00")])
    wait_4 = len([trade_data.index[i] for i in range(len(trade_data.index)) if
                  time.strftime(str(trade_data.index[i]))[11:] == time.strftime("21:00:00+00:00")])
    wait_5 = len([trade_data.index[i] for i in range(len(trade_data.index)) if
                  time.strftime(str(trade_data.index[i]))[11:] == time.strftime("21:10:00+00:00")])

    num_need_to_pay = total_trades - (wait_1 + wait_2 + wait_3 + wait_4 + wait_5)
    contract_multiplier = num_need_to_pay / total_trades
    strangle_multiplier = contract_multiplier / 2

    cumRet = data.Rcum
    slip_costs = np.cumsum((data.TrdVolume * strangle_multiplier) * (slippage*pip))
    com_costs = np.cumsum((data.TrdVolume * contract_multiplier) * commission)
    costs = slip_costs + com_costs
    ret = cumRet - costs
    ret = ret.resample("B").last()
    returns = ret.pct_change().iloc[1:]

    AR, dd_from_start = stat_from_start(ret)

    return returns, AR, dd_from_start

######################################################################################################################
#################################------MAKING TABLES------############################################################
######################################################################################################################

func_list = [ep.annual_return, ep.cum_returns_final, ep.annual_volatility, ep.sharpe_ratio,
             ep.calmar_ratio, ep.stability_of_timeseries, ep.max_drawdown, ep.omega_ratio,
             ep.sortino_ratio, stats.skew, stats.kurtosis, ep.tail_ratio]

stat_name_col = ["Annual return, %", "Cum_returns, %", "Annual volatility, %", "Sharpe ratio", "Calmar ratio",
                  "Stability", "Max dd, %", "Omega ratio", "Sortino ratio", "Skew", "Kurtosis", "Tail ratio",
                  "Average return, %", "Max dd from start, %"]

def make_costs_def(returns, AR, dd_from_start):

    data_list = ["{0:.3g}".format(k(returns)*100) if i <= 2 or i == 6 else "{0:.3g}".format(k(returns))
                 for i, k in enumerate(func_list)]
    data_list.append("{0:.3g}".format(AR))
    data_list.append("-{0:.3g}".format(dd_from_start))

    df = pd.DataFrame(data={
        "Stats": stat_name_col,
        "Tes": data_list
    })

    return df

def make_pandas_df(returns, benchmark_rets, margin_contract, margin_MValue, AR, dd_from_start):

    stat_list = stat_name_col.copy()
    added_func = ["Alpha", "Beta", "Margin (1 contract), usd/contract", "Margin (Mvalue), bps"]
    stat_list.extend(added_func)

    data_list = ["{0:.3g}".format(k(returns) * 100) if i <= 2 or i == 6 else "{0:.3g}".format(k(returns))
                 for i, k in enumerate(func_list)]

    added_values = [AR, -dd_from_start, ep.alpha(returns, benchmark_rets), ep.beta(returns, benchmark_rets)]
    values = rnd(added_values)
    values.extend([round(margin_contract,2), round(margin_MValue,2)])
    data_list.extend(values)

    df = pd.DataFrame(data= {
        "Stats" : stat_list,
        "Tes" : data_list
    })

    return df

# beautiful digit output
def rnd(col):
    col = ["{0:.3g}".format(x) for x in col]
    return col

#calculating stats
def comparison_table(returns_list):

    cols = []
    for b in returns_list:
        back_col = [k(b)*100 if i <= 2 or i == 6 else k(b)  for i, k in enumerate(func_list)]
        cols.append(back_col)

    res_cols = [rnd(x) for x in cols]

    return res_cols

#Strategy descriptions
description_dict = {
    "51WednesdayAll" : [
        html.P('STRATEGY: 5:1 Wednesday'),
        html.P('ASSET: U.S. Treasury Bond Options'),
        html.P('1. Selling 5 and buying 1 strangles at the distance of 1.5 SD'),
        html.P('2. Closing all positions if spot goes 0.5 figure out of our strangle '),
        html.P('3. Hedge is used'),
        html.P('4. Trades are being executed on Wednesday'),
        html.P('5. Trading options with 9 days to expiration')
    ],
    "1WednesdayAll" : [
        html.P('STRATEGY: 1 Wednesday'),
        html.P('ASSET: U.S. Treasury Bond Options'),
        html.P('1. Selling 1 strangle at the distance of 1.5 SD'),
        html.P('2. Closing all positions if spot goes 0.5 figure out of our strangle '),
        html.P('3. No hedge is used'),
        html.P('4. Trades are being executed on Wednesday'),
        html.P('5. Trading options with 9 days to expiration')
    ],
    "51TuesdayAll" : [
        html.P('STRATEGY: 5:1 Tuesday'),
        html.P('ASSET: U.S. Treasury Bond Options'),
        html.P('1. Selling 5 and buying 1 strangles at the distance of 1.5 SD'),
        html.P('2. Closing all positions if spot goes 0.5 figure out of our strangle '),
        html.P('3. Hedge is used'),
        html.P('4. Trades are being executed on Tuesday'),
        html.P('5. Trading options with 10 days to expiration')
    ],
    "1TuesdayAll" : [
        html.P('STRATEGY: 1 Tuesday'),
        html.P('ASSET: U.S. Treasury Bond Options'),
        html.P('1. Selling 1 strangle at the distance of 1.5 SD'),
        html.P('2. Closing all positions if spot goes 0.5 figure out of our strangle '),
        html.P('3. No hedge is used'),
        html.P('4. Trades are being executed on Tuesday'),
        html.P('5. Trading options with 10 days to expiration')
    ],
    "51FridayAll" : [
        html.P('STRATEGY: 5:1 Friday'),
        html.P('ASSET: U.S. Treasury Bond Options'),
        html.P('1. Selling 5 and buying 1 strangles at the distance of 1.5 SD'),
        html.P('2. Closing all positions if spot goes 0.5 figure out of our strangle '),
        html.P('3. Hedge is used'),
        html.P('4. Trades are being executed on Friday'),
        html.P('5. Trading options with 14 days to expiration')
    ],
    "1FridayAll" : [
        html.P('STRATEGY: 1 Friday'),
        html.P('ASSET: U.S. Treasury Bond Options'),
        html.P('1. Selling 1 strangle at the distance of 1.5 SD'),
        html.P('2. Closing all positions if spot goes 0.5 figure out of our strangle '),
        html.P('3. No hedge is used'),
        html.P('4. Trades are being executed on Friday'),
        html.P('5. Trading options with 14 days to expiration')
    ]
}