import dash
import dash_core_components as dcc
import dash_html_components as html
import matplotlib.pyplot as plt
from dash.dependencies import Input, Output
import plotly.offline as py
from plotly.graph_objs import *
import plotly.graph_objs as go
import dash_bootstrap_components as dbc
import folium
from folium import IFrame, FeatureGroup
import numpy as np
from PIL import Image
import json
import os
import base64
import glob
import pandas as pd
from folium.plugins import MarkerCluster

### Data
import pandas as pd
import pickle
### Graphing
import plotly.graph_objects as go
### Dash
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Output, Input
## Navbar
from navbar import Navbar

style1 = {'fillColor': '#00FFFFFF', 'lineColor': '#00FFFFFF','zoom_on_click':'False'}

nav = Navbar()

retval = os.getcwd()

grupos = ['CCHLA','CEAR','CCSA','CE','CCJ','CT','CBIOTEC','CCTA','CCEN','CCS','CCM']
dados = ['Quantidade de projetos em 2017','Quantidade de projetos em 2018','Quantidade de projetos em 2019','Quantidade de projetos em 2020']

dict_csv = { 'Quantidade de projetos em 2017' : 'Apoio/dados/dataset_2017.csv',
            'Quantidade de projetos em 2018' : 'Apoio/dados/dataset_2018.csv',
    		'Quantidade de projetos em 2019' : 'Apoio/dados/dataset_2019.csv',
            'Quantidade de projetos em 2020' : 'Apoio/dados/dataset_2020.csv'
}

def escala_mapa(max):
    step = (max/9)
    myscale=np.arange(1, max, step).tolist()
    myscale.extend([max])
    return myscale

dict_ajeita_ano = {'Quantidade de projetos em 2017': '2017', 'Quantidade de projetos em 2018': '2018', 'Quantidade de projetos em 2019': '2019','Quantidade de projetos em 2020':'2020'}

#state_data=pd.read_csv('C:\\Users\\gabri\\OneDrive\\Área de Trabalho\\Pasta de backup\\ODE\\dados\\projetos_2017.csv', engine='python')
#geo_data = 'C:\\Users\\gabri\\OneDrive\\Área de Trabalho\\Pasta de backup\\ODE\\ufpb_centros.json'

state_data=pd.read_csv('Apoio/Projetos_2017.csv', engine='python')
geo_data = 'Apoio/ufpb_centros.json'

professores_envolvidos ={'CBIOTEC2017': 6,
 'CBIOTEC2018': 9,
 'CBIOTEC2019': 10,
 'CBIOTEC2020': 8,
 'CCA2017': 81,
 'CCA2018': 84,
 'CCA2019': 90,
 'CCA2020': 90,
 'CCAE2017': 76,
 'CCAE2018': 90,
 'CCAE2019': 86,
 'CCAE2020': 85,
 'CCEN2017': 45,
 'CCEN2018': 46,
 'CCEN2019': 45,
 'CCEN2020': 77,
 'CCHLA2017': 78,
 'CCHLA2018': 102,
 'CCHLA2019': 94,
 'CCHLA2020': 160,
 'CCHSA2017': 65,
 'CCHSA2018': 81,
 'CCHSA2019': 74,
 'CCHSA2020': 96,
 'CCJ2017': 40,
 'CCJ2018': 45,
 'CCJ2019': 49,
 'CCJ2020': 46,
 'CCM2017': 56,
 'CCM2018': 83,
 'CCM2019': 85,
 'CCM2020': 93,
 'CCS2017': 246,
 'CCS2018': 281,
 'CCS2019': 266,
 'CCS2020': 332,
 'CCSA2017': 79,
 'CCSA2018': 80,
 'CCSA2019': 43,
 'CCSA2020': 84,
 'CCTA2017': 69,
 'CCTA2018': 69,
 'CCTA2019': 76,
 'CCTA2020': 95,
 'CE2017': 60,
 'CE2018': 53,
 'CE2019': 95,
 'CE2020': 97,
 'CEAR2017': 19,
 'CEAR2018': 21,
 'CEAR2019': 19,
 'CEAR2020': 21,
 'CI2017': 14,
 'CI2018': 25,
 'CI2019': 20,
 'CI2020': 18,
 'CT2017': 86,
 'CT2018': 69,
 'CT2019': 63,
 'CT2020': 91,
 'CTDR2017': 39,
 'CTDR2018': 22,
 'CTDR2019': 26,
 'CTDR2020': 45}

chama_ano_criacao = {
    'CCHLA': 1949
    ,'CEAR': 2011
    ,'CCSA': 1934
    ,'CE': 1978
    ,'CCJ':1949
    ,'CT': 1974
    ,'CBIOTEC':2011
    ,'CCTA':2012
    ,'CCEN': 1974
    ,'CCS': 1974
    ,'CCM': 2007
    ,'CCA': 1936
    ,'CCHSA': 2008
    ,'CCAE': 2006
    ,'CI':2012
    ,'CTDR': 2009
}

chama_departamentos = {
    'CCHLA': 11
    ,'CEAR': 2
    ,'CCSA': 6
    ,'CE': 7
    ,'CCJ':5
    ,'CT': 7
    ,'CBIOTEC':2
    ,'CCTA': 7
    ,'CCEN':9
    ,'CCS':13
    ,'CCM': 5
    ,'CCA': 7
    ,'CCHSA': 6
    ,'CCAE': 8
    ,'CTDR': 3
    ,'CI': 3
}

chama_cursos = {
    'CCHLA': ['Ciências Sociais','Comunicação em Mídias Digitais', 'Filosofia', 'História', 'Letras', 'Letras / Ead', 'Letras - Libras', 'Letras(Língua Espanhola)','Letras(Língua Francesa)','Letras(Línguas Clássicas)','Letras(Língua Inglesa)','Línguas Estrangeiras Aplicadas às Negociações Internacionais', 'Psicologia','Serviço Social','Tradução']
    ,'CEAR': ['Engenharia Elétrica', 'Engenharia de Energias Renovaveis']
    ,'CCSA': ['Admnistração', 'Admnistração Pública','Arquivologia','Biblioteconomia', 'Ciências Atuariais','Ciências Contábeis','Ciências Econômicas','Gestão Pública','Relações Internacionais','Tecnologia em Gestão Pública']
    ,'CE': ['Ciências das Religiões','Ciências Naturais','Pedagogia','Pedagogia - EAD', 'Pedagogia(Educação Do Campo)','Pedagogia(MSC)','Psicopedagogia(BACH)']
    ,'CCJ':['Direito']
    ,'CT': ['Arquitetura e Urbanismo','Engenharia Ambiental','Engenharia Civil','Engenharia De Alimentos','Engenharia De Materiais','Engenharia de Produção','Engenharia de Produção Mecânica','Engenharia Mecânica','Engenharia Química','Química Industrial']
    ,'CBIOTEC':['Biotecnologia']
    ,'CCTA': ['Artes Visuais','Cinema e Audiovisual','Comunicação Social','Dança','Educação Artística','Hotelaria', 'Jornalismo','Música','Música - Bacharelado', 'Música Popular', 'Radialismo','Regência De bandas E Fanfarras','Relações Públicas', 'Teatro(Bacharelado)','Teatro(Licenciatura)','Turismo']
    ,'CCEN':['Ciencias','Ciências Biológicas','Ciências Biológicas - EAD', 'Computação', 'Estatística','Física','Geografia','Matemática','Matemática - EAD', 'Química' ]
    ,'CCS':['Biomedicina','Educação Física','Educação Física - Licenciatura','Enfermagem','Farmácia','Fisioterapia','Fonoaudiologia','Nutrição','Odontologia','Terapia Ocupacional']
    ,'CCM': ['Medicina']
    ,'CCA': ['Agronomia','Ciências biológicas', 'Medicina Veterinaria','Química','Zootecnia']
    ,'CCHSA': ['Admnistração','Agroecologia','Agroindustria','Ciências Agrárias','Curso Superior de Tecnologia em Cooperativismo','Pedagogia']
    ,'CCAE': ['Admnistração','Antropologia','Ciência da Computação','Ciências Contábeis','Design','Ecologia','Hotelaria','Letras','Letras(Espanhol)','Letras(Inglês)','Matemática','Pedagogia','Secretariado Executivo Bilíngue','Sistemas de Informação']
    ,'CTDR': ['Gastronomia','Tecnologia de Alimentos','Tecnologia em Produção Sucroaalcoleira']
    ,'CI': ['Ciência da Computação','Ciência de Dados e Inteligência Artificial','Engenharia da Computação','Matemática Computacional']
}

chama_assessor = {
    'CCHLA': 'Nívia Pereira'
    ,'CEAR': 'Jose Mauricio Ramos de Souza Neto'
    ,'CCSA': 'Danielle Vieira'
    ,'CE': 'Quézia Furtado, Mª da Conceição Miranda'
    ,'CCJ':'Ludmila Cerqueira'
    ,'CT': 'Aurélia Idrogo, Luzia Camboim'
    ,'CBIOTEC':'Elisângela A. de Moura Kretzschmar'
    ,'CCTA': 'Luceni Caetano'
    ,'CCEN':'Jane Torelli'
    ,'CCS': 'Rosenés Lima'
    ,'CCM': 'André Bonifácio'
    ,'CCA': 'Fábio Mielezrsk'
    ,'CCHSA': 'Catarina de Medeiros'
    ,'CCAE': 'Jocélio de Oliveira'
    ,'CI': 'José Miguel Aroztegui'
    ,'CTDR': 'Ana Braga'
}

chama_diretor = {
    'CCHLA': 'Mônica Nóbrega'
    ,'CEAR': 'Zaqueu Ernesto da Silva '
    ,'CCSA': 'Walmir Rufino Da Silva'
    ,'CE': 'Wilson Honorato Aragão'
    ,'CCJ':'Fredys Orlando Souto'
    ,'CT': 'Antônio de Mello Villar'
    ,'CBIOTEC':'Valdir de Andrade Braga'
    ,'CCTA': 'José David Campos Fernandes'
    ,'CCEN':'José Roberto Soares do Nascimento'
    ,'CCS':'João Euclides Fernandes Braga'
    ,'CCM': 'Eduardo Sérgio Moura Souza'
    ,'CCA': 'Manuel Bandeira de Albuquerque'
    ,'CCHSA': 'Terezinha Domiciano Martins'
    ,'CCAE': 'Maria Angeluce Soares Perônico Barbotin'
    ,'CI': 'Hamilton Soares da Silva'
    ,'CTDR': 'José Marcelino Oliveira Cavalheiro'
}

chama_vice = {
    'CCHLA': 'Rodrigo Freire de Carvalho e Silva'
    ,'CEAR': 'Euler Cássio Tavares de Macedo'
    ,'CCSA': 'Aldo Leonardo Cunha Callado'
    ,'CE': 'Swamy de Paula Lima Soares'
    ,'CCJ': 'Valfredo de Andrade Aguiar Filho'
    ,'CT': 'Tarciso Cabral da Silva'
    ,'CBIOTEC': 'Fabíola da Cruz Nunes'
    ,'CCTA': 'Ulisses Carvalho da Silva'
    ,'CCEN': 'Severino Francisco de Oliveira'
    ,'CCS':'Fabiano Gonzaga Rodrigues'
    ,'CCM': 'Eutília Freire'
    ,'CCA': 'Ricardo Romão Guerra'
    ,'CCHSA': 'Pedro Germano Antonio Nunes'
    ,'CCAE': 'Alexandre Scaico'
    ,'CI': 'Lucídio dos Anjos Formiga Cabral'
    ,'CTDR': 'João Andrade da Silva'
}

centro_extenso = {
    'CCHLA': 'Centro de Ciências Humanas, Letras e Artes'
    ,'CEAR': 'Centro de Energias Alternativas e Renováveis'
    ,'CCSA': 'Centro de Ciências Sociais Aplicadas'
    ,'CE': 'Centro de Educação'
    ,'CCJ': 'Centro de Ciências Jurídicas'
    ,'CT': 'Centro de Tecnologia'
    ,'CBIOTEC': 'Centro de Biotecnologia'
    ,'CCTA': 'Centro de Comunicação, Turismo e Artes'
    ,'CCEN': 'Centro de Ciências Exatas e da Natureza'
    ,'CCS':'Centro de Ciências da Saúde'
    ,'CCM': 'Centro de Ciências Médicas'
    ,'CCA': 'Centro de Ciencias Agrárias'
    ,'CCHSA': 'Centro de Ciências Humanas, Sociais e Agrárias'
    ,'CCAE': 'Centro de Ciências Aplicadas e Educação'
    ,'CI': 'Centro de Informática'
    ,'CTDR': 'Centro de Tecnologia e Desenvolvimento Regional'
}

def chama_projetos(file,dado):
    state_data_1=pd.read_csv(dict_csv[dado], engine='python')
    filtered = [file]
    print(state_data_1)
    state_data_1 = state_data_1[state_data_1['centros'].isin(filtered)]
    lista= list(state_data_1['qtd_projeto'])
    return lista[0]

dict_coordenadas = {
    'cbiotec' : [-7.140993, -34.846455],
    'ccen'  : [-7.139640, -34.845020],
    'cchla' : [-7.139370, -34.850374],
    'ccj' :  [-7.141978, -34.848935],
    'ccm' : [-7.136423, -34.840567 ],
    'ccs' :  [-7.135673, -34.841516],
    'ccsa' :  [-7.141069, -34.849936],
    'ccta' : [-7.137422, -34.849572],
    'ce' : [-7.139994, -34.850124],
    'cear' : [-7.141625, -34.850556],
    'ct' : [-7.142505, -34.850309],
    'cca'  : [-6.973692, -35.716273],
    'ccae'  : [-6.829091, -35.118770],
    'cchsa'  : [-6.752077, -35.647532],
    'ci':[-7.162211,-34.817228],
    'ctdr':[-7.163018,-34.817989]
}

#folder ='C:\\Users\\gabri\\OneDrive\\Área de Trabalho\\Pasta de backup\\ODE\\logos'
folder ='Apoio/logos'

extension = '*'
separator = ','
extension = '*.' + extension
os.chdir(folder)
files_logos= glob.glob(extension)

os.chdir(retval)

#folder_1 ='C:\\Users\\gabri\\OneDrive\\Área de Trabalho\\Pasta de backup\\ODE\\arquivos_json'
#folder_1 ='C:Apoio\\arquivos_json'
folder_1='Apoio/arquivos_json'
os.chdir(folder_1)
files_json= glob.glob(extension)
os.chdir(retval)

#folder_2 ='C:\\Users\\gabri\\OneDrive\\Área de Trabalho\\Pasta de backup\\ODE\\dados'
folder_2 ='Apoio/dados'
os.chdir(folder_2)
files_dados= glob.glob(extension)
os.chdir(retval)

tooltip = "Clique para abrir a imagem"
html1 = ''.format

def limpa_nome_arquivo_json(logo):
    files=logo.replace('json','')
    files=files.replace('.','')
    return files

def limpa_nome_arquivo(logo):
    files=logo.replace('jpeg','')
    files=files.replace('jpg','')
    files=files.replace('png','')
    files=files.replace('.','')
    return files

def gera_cloropleth(geo_data,state_data,files_dados,mapa_,dado,grupos):

    state_data_1=[]
    state_data_1=pd.read_csv(dict_csv[dado], engine='python')
    #geo_data = 'C:\\Users\\Pessoal\\Desktop\\ODE\\choropleth\\gp_1.json'
    #geo_data = 'Apoio/choropleth/json_divisao_centros.json'
    with open('Apoio/choropleth/json_divisao_centros.json') as jsonfile:
        input_dict = json.load(jsonfile)

    lista_features = [x for x in input_dict['features'] if x['id'] in grupos]

    #geo_data = json.dumps(lista_features)
    geo_data ={'type': 'FeatureCollection','features': lista_features}

    filtered = grupos
    state_data_1 = state_data_1[state_data_1['centros'].isin(filtered)]

    #myscale = (state_data_1['qtd_projeto'].quantile((0,0.12,0.22,0.32,0.42,0.52,0.72,0.82,0.92,1))).tolist()
    maxi=max(list(state_data_1['qtd_projeto']))
    myscale=escala_mapa(maxi)
    myscale=[float(i) for i in myscale]
    try:
        folium.Choropleth(
                geo_data = geo_data,
                name='Choropleth',
                data=state_data_1,
                columns=['centros', 'qtd_projeto'],
                key_on='feature.id',
                fill_color='YlGn',
                fill_opacity=0.7,
                line_opacity=0.2,
                legend_name='Quantidade de projetos',
                threshold_scale=myscale,
                #show=False,
                #overlay=False
            ).add_to(mapa_)
    except KeyError:
        pass

    #folium.LayerControl().add_to(map)

def gera_camadas_ufpb(arquivo_json,mapa_,logo):
    #AQUIII
    picture1 = base64.b64encode(open('Apoio/logos/' + logo ,'rb').read()).decode()
    #img = Image.open('Apoio/logos/' + logo)

    iframe1 = IFrame(html1(picture1), width=200+20, height=200+20)
    #icon1 = folium.features.CustomIcon('C:\\Users\\gabri\\OneDrive\\Área de Trabalho\\Pasta de backup\\ODE\\logos\\' + logo, icon_size=(20,20))
    #camadas_ufpb = os.path.join('C:\\Users\\gabri\\OneDrive\\Área de Trabalho\\Pasta de backup\\ODE\\arquivos_json\\' + arquivo_json)
    camadas_ufpb = os.path.join('Apoio/arquivos_json/' + arquivo_json)

    arquivo_json=limpa_nome_arquivo_json(arquivo_json)

    camada=folium.GeoJson(camadas_ufpb,name=arquivo_json, tooltip='Clique para abrir a imagem',style_function=lambda x:style1).add_to(mapa_)

    #camada.add_child(folium.Popup(dict_centros[arquivo_json]))
    camada.add_child(folium.Popup(iframe1,width=200+20,height=200+20))

    camada.add_to(mapa_)

def gera_icones_da_ufpb(logo,dict_logo,dict_coordenadas,html1,tooltip,mapa_,arquivo_json,dado):
    #AQUIII
    #picture1 = base64.b64encode(open('C:\\Users\\gabri\\OneDrive\\Área de Trabalho\\Pasta de backup\\ODE\\logos\\' + logo ,'rb').read()).decode()
    files=limpa_nome_arquivo(logo)
    file = files.upper()
    cur=chama_cursos[file]

    if dado == 0:
        html1=f"""

 Informações sobre o {file}

    Nome do Centro: {centro_extenso[file]}

    Ano de criação: {chama_ano_criacao[file]}

    Número de departamentos: {chama_departamentos[file]}

    Cursos: {', '.join(str(x) for x in cur)}

    Diretor: {chama_diretor[file]}

    Vice-Diretor: {chama_vice[file]}

    Assessor(es): {chama_assessor[file]}

    """
    else:
        html1=f"""

 Informações sobre o {file}

    Nome do Centro: {centro_extenso[file]}

    Ano de criação: {chama_ano_criacao[file]}

    Número de departamentos: {chama_departamentos[file]}

    Cursos: {', '.join(str(x) for x in cur)}

    Diretor: {chama_diretor[file]}

    Vice-Diretor: {chama_vice[file]}

    Assessor(es): {chama_assessor[file]}

    {dado}: {chama_projetos(file,dado)}

    Quantidade de professores Envolvidos: {professores_envolvidos[file + dict_ajeita_ano[dado]]}

    """
    #picture1 = base64.b64encode(open('Apoio/logos/' + logo ,'rb').read()).decode()
    arquivo_json=limpa_nome_arquivo_json(arquivo_json)
    #iframe1 = IFrame(html1(picture1), width=200+20, height=200+20)
    icon1 = folium.features.CustomIcon('Apoio/logos/' + logo, icon_size=(20,20))

    ifr = IFrame(html=html1, width=500, height=300)
    popup1 = folium.Popup(ifr, max_width=2650)
    #popup1 = folium.Popup(dict_centros[arquivo_json],max_width=600)
    folium.Marker(location=dict_coordenadas[files],popup= popup1,tooltip='Clique para um maior conhecimento sobre centro',icon=icon1).add_to(mapa_)

def mapa_da_ufpb(tooltip, files_logos,dict_coordenadas,files_json,geo_data,state_data, files_dados,mapa_,flag,grupos,dado):
    files_json = []
    files_logos = []
    if 'CTDR' in grupos:
        files_json.extend(['CTDR.json'])
        files_logos.extend([ 'ctdr.png'])
    if 'CI' in grupos:
        files_json.extend(['CI.json'])
        files_logos.extend([ 'ci.png'])
    if 'CCA' in grupos:
        files_json.extend(['CCA.json'])
        files_logos.extend([ 'cca.png'])
    if 'CCAE' in grupos:
        files_json.extend(['CCAE.json'])
        files_logos.extend([ 'ccae.png'])
    if 'CCHSA' in grupos:
        files_json.extend(['CCHSA.json'])
        files_logos.extend([ 'cchsa.png'])
    if 'CCJ' in grupos:
        files_json.extend(['CCJ.json'])
        files_logos.extend([ 'ccj.png'])
    if 'CT' in grupos:
        files_json.extend(['CT.json'])
        files_logos.extend([ 'ct.png'])
    if 'CBIOTEC' in grupos:
        files_json.extend(['CBIOTEC.json'])
        files_logos.extend(['cbiotec.png'])
    if 'CCHLA' in grupos:
        files_json.extend(['CCHLA.json'])
        files_logos.extend([ 'cchla.png'])
    if 'CEAR' in grupos:
        files_json.extend(['CEAR.json'])
        files_logos.extend([ 'cear.png'])
    if 'CCSA' in grupos:
        files_json.extend(['CCSA.json'])
        files_logos.extend([ 'ccsa.png'])
    if 'CE' in grupos:
        files_json.extend(['CE.json'])
        files_logos.extend(['ce.png'])
    if 'CCTA' in grupos:
        files_json.extend(['CCTA.json'])
        files_logos.extend(['ccta.png'])
    if 'CCEN' in grupos:
        files_json.extend(['CCEN.json'])
        files_logos.extend(['ccen.png'])
    if 'CCHLA' in grupos:
        files_json.extend(['CCHLA.json'])
        files_logos.extend([ 'cchla.png'])
    if 'CCS' in grupos:
        files_json.extend(['CCS.json'])
        files_logos.extend([ 'ccs.png'])
    if 'CCM' in grupos:
        files_json.extend(['CCM.json'])
        files_logos.extend(['ccm.png'])

    if flag == 'nao' or dado == 0:
        for arquivo_json,logo in zip(files_json,files_logos):
            gera_camadas_ufpb(arquivo_json,mapa_,logo)
    for arquivo_json,logo in zip(files_json,files_logos):
        gera_icones_da_ufpb(logo,logo,dict_coordenadas,html1,tooltip,mapa_,arquivo_json,dado)
    if flag == 'sim' and grupos != [] and dado != 0:
        print('cheguei',flush=True)
        gera_cloropleth(geo_data,state_data,files_dados,mapa_,dado,grupos)
    #mapa_.save("C:\\Users\\gabri\\OneDrive\\Área de Trabalho\\Pasta de backup\\ODE\\mapa_ufpb_centros.html")
    mapa_.save("Apoio/mapa_ufpb_centros.html")
tab_selected_style = {
    'font-size': '70%',
    'padding': '6px'
}

tab_style = { #Estilos das Tabs
    'borderBottom': '1px solid #d6d6d6',
    'padding': '6px',
    'font-size': '75%',
    'fontSize' : '12'
    }
#####
tabs = html.Div([
    dcc.Tabs(id='tabs', value='tab-3', children=[
        dcc.Tab(label='Areia', value='tab-1', style=tab_style, selected_style=tab_selected_style),
         dcc.Tab(label='Bananeiras', value='tab-2', style=tab_style, selected_style=tab_selected_style),
          dcc.Tab(label='João Pessoa', value='tab-3', style=tab_style, selected_style=tab_selected_style),
           dcc.Tab(label='Mangabeira', value='tab-5', style=tab_style, selected_style=tab_selected_style),
            dcc.Tab(label='Mamanguape', value='tab-4', style=tab_style, selected_style=tab_selected_style),
])
    ,html.Br()])

card_content = [
    dbc.CardHeader("Filtros do Mapa",style={'font-size':24, 'textAlign':'center'}),
    dbc.CardBody(
        [
        tabs,
        html.H4("Escolha o grupo desejado:", style={'font-size':19,'margin-top':'14px'}),
        dcc.Dropdown(
        id = 'grupos',
        options=[
            {'label': j, 'value': j} for j in grupos
        ],
        value=['Todos os centros'],
        multi=True,
    searchable=False
    ),

    html.Div(html.Br()),
    html.H4("Deseja analisar o mapa pelo quantitativo de projetos por ano?", style={'font-size':19}),

    dbc.RadioItems(
                    options=[
                        {'label': 'Sim', 'value': 'sim'},
                        {'label': 'Não', 'value': 'nao'},

                    ],
                    id='flag',
                    value='1',
                    inline = True,
                    labelStyle={'display': 'inline-block','margin-bottom':'10px'}
                ),
    html.Div([
    html.H4("Escolha o ano para visualizar o mapa:", style={'font-size':19}),

    dcc.Dropdown(
        id = 'dados',
        options=[
            {'label': j, 'value': j} for j in dados
        ],
        value=0,
         multi=False,
    searchable=False,
         style={'margin-bottom':'10px'}

    ),],
    id='choropleth',
    style = {'display': 'none'}),
        ]
    ),
]

jumbotron = dbc.Card(card_content,  outline=True)

card_content_3 = [
    dbc.CardHeader("Mapa da UFPB",style={'font-size':24, 'textAlign':'center'}),
    dbc.CardBody(
        [
            html.Iframe(id='mapa', srcDoc=open('Apoio/mapa_ufpb_centros.html', 'r').read(),width='100%',height='580px'),
        ]
    ),
]

jumbotron_2 = dbc.Card(card_content_3,  outline=True)

body_1 =html.Div([

        dbc.Row(
           [
               dbc.Col(
                  [

                jumbotron,

                   ], md=4

               ),
              dbc.Col([
     	      jumbotron_2

                    ], md=8 ),

                ],no_gutters=True
            ),

])

def mapa():
    layout = html.Div([
    nav,

	body_1,
    html.Div([], id='value-container', style={'display': 'none'})

     #html.Iframe(id='mapa', srcDoc=open('C:\\Users\\gabri\\OneDrive\\Área de Trabalho\\Pasta de backup\\ODE\\mapa_ufpb_centros.html', 'r').read(), width='100%', height='430'),

     #html.Iframe(id='mapa', srcDoc=open('Apoio/mapa_ufpb_centros.html', 'r').read(), width='100%', height='430'),
    ])
    return layout


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Jul 14 09:39:50 2018

@author: linguista
"""

import nltk
#nltk.download()
from nltk.book import *

# Que texto é este?
print(text1.name)

# Vejamos quantas palavras:
print(str(len(text1)));

# Vejamos quantos termos diferentes:
print(str(len(set(text1))));

# Vejamos a presença destas palavras (“big” e “monstrous”)
text1.concordance("monstrous")
text1.concordance("big")

text1.dispersion_plot(["monstrous", "animal", "big", "terrible", "dangerous"])

# ---------------------------------------------------------

data = [];
y = [];
file = open('spam.txt', 'r')
text_full = file.read().lower();
text = text_full.split('\n');

for row in text:
	if(row[:3]=='ham'):
		classe = 'ham';
		content = row[4:]
		y.append(0);
	else:
		classe = 'spam';
		content = row[5:]
		y.append(1);
	data.append([classe, content])
file.close();

# Mais loads
from nltk.corpus import stopwords
porter = nltk.PorterStemmer()
stopWords = set(stopwords.words('english'))
from nltk.corpus import wordnet

import numpy as np

attributes = [];

vocab = set(nltk.word_tokenize(text_full));
print('Vocabulario inicial dos emails: '+str(len(vocab)));

# Uso de tokenizers
for token in vocab:
	if(not(token in stopWords) and len(wordnet.synsets(token))>0):
        	token = porter.stem(token);
	if(not(token in attributes)):
        	attributes.append(token);

print('Vocabulario final dos emails: '+str(len(attributes)));

# --------------------------------------------------
# Bag-of-word
bow = np.zeros([len(data), len(attributes)]);
i = 0;
for row in data:
	row = nltk.word_tokenize(row[1]);

	for word in row:
		word = porter.stem(word);
		if(word in attributes):
        		indice = attributes.index(word);
        		bow[i][indice] += 1;
	i+=1;
X = bow;

# MNB - treinamento
from sklearn.naive_bayes import MultinomialNB
gnb = MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)
gnb_trained = gnb.fit(X[:4000], y[:4000])
y_pred = gnb_trained.predict(X[4000:])

print('Taxa de acerto de: '+str(sum(y_pred == y[4000:])/len(y_pred)))


'''
cmd_support.py  2021-05-05  Wed

renamed from cmd_stuff.py
'''

# <editor-fold desc="python imports"
import logging as log
import sys
# </editor-fold>

# <editor-fold desc="local imports"
import settings as g
import signals as sigs
import support as s
# </editor-fold>

# <editor-fold desc="globals"
CLR = g.OP_CLR
SET = g.OP_SET
BP = g.BREAK_POINT
NL = g.NEW_LINE

GRID_NAMES_1 = g.GRID_NAMES_1
GRID_NAMES_2 = g.GRID_NAMES_2
GRID_NAMES = g.GRID_NAMES
MAX_GRID_LENGTH = g.NUMBER_OF_GRIDS
BLOCK_PEERS = g.BLOCK_PEERS
RCN_BLOCK_PEERS = g.RCN_BLOCK_PEERS
# </editor-fold>

# <editor-fold desc="logging setup"
logger_except = log.getLogger(__name__)
logger_except.setLevel(log.INFO)
formatter_except = log.Formatter(sigs.except_format)

file_handler_except = log.FileHandler(sigs.except_path)
file_handler_except.setLevel(log.ERROR)
file_handler_except.setFormatter(formatter_except)
logger_except.addHandler(file_handler_except)
# </editor-fold>

class CmdS:
    block_sqr = ''
    block_cmd = ''
    cmd_main = ''
    cmd_alt = ''
    from_cmd = ''
    grid = ''
    grid_index = 0
    numbers = ''
    operation = SET
    square = ''
    value = ''

    letters_list = g.GRID_NAMES
    cmds_list = []
    multiple_cmds_list = []
    numbers_list = []
    peer_subs = []
    block_subs = ''

    def multiple_cmds_from_last_digits(cls, big):
        try:
            length = len('r1c2=n3')
            if len(big) > length:
                base_cmd = big[:6]
                last_digits = big[6:]
                cls.multiple_cmds_list = [base_cmd + digit for digit in last_digits]
                return True
            else:
                cls.multiple_cmds_list = []
                return False

        except Exception as e:
            logger_except.exception(e)
            sys.exit()

    @classmethod
    def set(cls, cmd):
        '''
        A basic_cmd (7-types) string of length = 7 is parsed ... ref the following.

        The following class attributes are generated
        --------------------------------------------------------------------------
        block_sqr   = string of length= 2  BN where B & N is digit in '123456789'
                      B is the row index of the bns grid
                      N is the col index of the bns grid
                      unless bns basic_cmd is param, then it is the 'RC' square
                      (maybe should call alt_sqr ?)
        block_cmd   = a basic_cmd of lentth = 7 for the bns grid see cmd param:
        cmd_main    = basic_cmd string: see 1st choice of :param cmd below
        cmd_alt     = basic_cmd string: see 2nd choice of :param cmd below
        from_cmd    = basic_cmd string passed in
        grid_index  =  int:  0 | 1 | 2 | 3
        numbers     = string of length 3 for the X,Y,Z described in :param cmd
        operation   = string of length 1 = g.CLR(-) | g.SET(+)
        square      = string of length 2 = usual Sudoku grid indexing e.g '11' to '99'
                         of the basic_cmd passed int
        value       = string of length 1, the last digit in the basic_cmd

        :param cmd:  e.g. x{X} + y{Y} + {OP} + z(Z}     length = 7
               where xyz = rcn | crn   grid_index = 0
                         = rnc | ncr   grid_index = 1
                         = ncr | cnr   grid_index = 2
                         = bns         grid_index = 3
               where X, Y, Z  =  digit in '123456789'
               where OP = g.SET(=)
                          g.CLR(-)

        :return: None
        '''
        try:
            cls.from_cmd = cmd
            cls.grid = f'{cmd[0]}{cmd[2]}{cmd[5]}'

            cls.grid_index = GRID_NAMES.index(cls.grid)
            if cls.grid_index >= MAX_GRID_LENGTH:
                cls.grid_index -= MAX_GRID_LENGTH
                cls.cmd_alt = cmd
                cls.cmd_main = f'{cmd[2]}{cmd[3]}{cmd[0]}{cmd[1]}{cmd[4:7]}'
            else:
                cls.cmd_main = cmd
                cls.cmd_alt = f'{cmd[2]}{cmd[3]}{cmd[0]}{cmd[1]}{cmd[4:7]}'

            cls.grid = f'{cls.cmd_main[0]}{cls.cmd_main[2]}{cls.cmd_main[5]}'
            cls.grid_index = GRID_NAMES.index(cls.grid)
            cls.numbers = f'{cls.cmd_main[1]}{cls.cmd_main[3]}{cls.cmd_main[6]}'
            cls.operation = cls.cmd_main[4]
            cls.square = f'{cls.cmd_main[1]}{cls.cmd_main[3]}'
            cls.value = f'{cls.cmd_main[6]}'
            cls.block_sqr = s.convert_bsrc(cls.square)
            cls.block_cmd = f'b{cls.block_sqr[0]}n{cls.value}{cls.operation}s{cls.block_sqr[1]}'
        except Exception as e:
            logger_except.exception(e)
            sys.exit()

    @classmethod
    def do_lists(cls):
        try:
            cls.cmds_list = []
            cls.numbers_list = []
            rcn_numbers = [0, 0, 0]
            rnc_numbers = [0, 0, 0]
            ncr_numbers = [0, 0, 0]
            bns_numbers = [0, 0, 0]

            if cls.grid == 'rcn':
                cls.grid_index = 0
                rcn_numbers = list(cls.numbers)
            elif cls.grid == 'bns':
                cls.grid_index = 3
                bns_numbers = list(cls.numbers)
                rcn_numbers[2] = bns_numbers[1]
                sqr = bns_numbers[0] + bns_numbers[2]
                rcn_numbers[0], rcn_numbers[1] = s.convert_bsrc(sqr)
            elif cls.grid == 'rnc':
                cls.grid_index = 1
                rnc_numbers = list(cls.numbers)
                rcn_numbers[0] = rnc_numbers[0]
                rcn_numbers[1] = rnc_numbers[2]
                rcn_numbers[2] = rnc_numbers[1]
            elif cls.grid == 'ncr':
                cls.grid_index = 3
                ncr_numbers = list(cls.numbers)
                rcn_numbers[0] = ncr_numbers[2]
                rcn_numbers[1] = ncr_numbers[1]
                rcn_numbers[2] = ncr_numbers[0]

            if bns_numbers == [0, 0, 0]:
                bns_numbers[1] = rcn_numbers[2]
                sqr = rcn_numbers[0] + rcn_numbers[1]
                bns_numbers[0], bns_numbers[2] = s.convert_bsrc(sqr)
            if ncr_numbers == [0, 0, 0]:
                ncr_numbers[0] = rcn_numbers[2]
                ncr_numbers[1] = rcn_numbers[1]
                ncr_numbers[2] = rcn_numbers[0]
            if rnc_numbers == [0, 0, 0]:
                rnc_numbers[0] = rcn_numbers[0]
                rnc_numbers[1] = rcn_numbers[2]
                rnc_numbers[2] = rcn_numbers[1]

            # convert lists to string
            cmds_numbers = []
            cmds_numbers.append(''.join(rcn_numbers))
            cmds_numbers.append(''.join(rnc_numbers))
            cmds_numbers.append(''.join(ncr_numbers))
            cmds_numbers.append(''.join(bns_numbers))

            letters_list = cls.letters_list.copy()
            cls.numbers_list = cmds_numbers
            for letters, digits in zip(letters_list, cls.numbers_list):
                interleave = ''.join(let + num for let, num in zip(letters, digits))
                cmd = interleave[0:4] + cls.operation + interleave[4:7]
                cls.cmds_list.append(cmd)
            BP
        except Exception as e:
            logger_except.exception(e)
            sys.exit()

    @classmethod
    def do_peers(cls):
        try:
            if cls.operation == SET:
                L = cls.letters_list[cls.grid_index]
                D = cls.numbers_list[cls.grid_index]
                # square = D[0:2]
                peers_row = f'{L[0]}{D[0]}{L[1]}!{D[1]}{CLR}{L[2]}{D[2]}'
                peers_col = f'{L[1]}{D[1]}{L[0]}!{D[0]}{CLR}{L[2]}{D[2]}'
                if cls.grid_index == 3:
                    cls.peer_subs = [peers_row]
                elif cls.grid_index == 1 or cls.grid_index == 2:
                    cls.peer_subs = [peers_row, peers_col]

                if cls.grid_index == 0:
                    block_peers = RCN_BLOCK_PEERS[cls.square]
                    num_value = D[2]
                    row_block_peers = block_peers[0].replace('.', num_value)
                    col_block_peers = block_peers[1].replace('.', num_value)
                    cls.peer_subs = [peers_row, row_block_peers, peers_col, col_block_peers]

                    # generate block only peers
                    end_digit = cls.block_cmd[-1]
                    peer = cls.block_cmd[:-1]
                    peer = peer.replace(SET, CLR)
                    peer += BLOCK_PEERS[end_digit]
                    cls.block_subs = peer
                return True
            else:
                return False

        except Exception as e:
            logger_except.exception(e)
            sys.exit()

if __name__ == '__main__':
    file = __file__
    print(f'running {file} ')
else:
    file = __file__
    print(f'importing {file} ')


#!/usr/bin/env python3
#

import asyncio
import time

'''
uture对象有几个状态：

- Pending： 创建future，还未执行
- Running： 事件循环正在调用执行任务
- Done： 任务执行完毕
- Cancelled： Task被取消后的状态

创建future的时候，task为pending，
事件循环调用执行的时候当然就是running，
调用完毕自然就是done，
如果需要停止事件循环，就需要先把task取消。
可以使用asyncio.Task获取事件循环的task
'''

now = lambda: time.time()

async def do_some_work(x):
    print("Waiting:", x)
    await asyncio.sleep(x)
    return "Done after {}s".format(x)

async def main():
    coroutine10 = do_some_work(10)
    coroutine5 = do_some_work(5)
    coroutine3 = do_some_work(3)
    coroutine1 = do_some_work(1)

    tasks = [
        asyncio.ensure_future(coroutine10),
        asyncio.ensure_future(coroutine5),
        asyncio.ensure_future(coroutine3),
        asyncio.ensure_future(coroutine1)
    ]
    return await asyncio.gather(*tasks)

if __name__ == '__main__':

    start = now()

    loop = asyncio.get_event_loop()

    # 启动事件循环之后，马上ctrl+c，会触发 run_until_complete 的执行异常 KeyBorardInterrupt。然后通过循环 asyncio.Task 取消 future
    try:
        # main() 相当于一个打包好的 asyncio.wait(tasks) 或者 asyncio.gather(*tasks)
        loop.run_until_complete(main())
    except KeyboardInterrupt as e:
        # print(asyncio.Task.all_tasks())
        [print(task) for task in asyncio.Task.all_tasks()]
        # True表示cannel成功，loop stop之后还需要再次开启事件循环，最后在close，不然还会抛出异常

        # True表示cannel成功，loop stop之后还需要再次开启事件循环，最后再close，不然还会抛出异常：
        # [print(task.cancel()) for task in asyncio.Task.all_tasks()]
        print(asyncio.gather(*asyncio.Task.all_tasks()).cancel())
        loop.stop()
        loop.run_forever()
    finally:

        loop.close()

    print('time: ', now() - start)


import requests
import re
def match_count(card, card_counts):
    return next(filter(lambda x: x[0] == card[0], card_counts), (None, 0))[1]
html = requests.get('https://www.pokemon-card.com/deck/deck.html?deckID=ppyMSS-yKlMYW-3pRMME').text
cards = re.findall(r"PCGDECK\.searchItemName\[(.*?)\]='(.*?)'", html, re.S)
card_counts = re.findall(r'(\d{5})_(\d{1})', html, re.S)
result = map(lambda x: (x[1], match_count(x, card_counts)), cards)
for card in result:
    print(card[0]+":"+card[1]+"枚")


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Sep  5 23:03:32 2019

@author: anas
"""

# Importing the libraries

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# Importing the dataset
dataset = pd.read_csv('/Users/anas/Downloads/Machine Learning A-Z New-2/Part 2 - Regression/Section 4 - Simple Linear Regression/Salary_Data.csv')
#independent variable is X
X = dataset.iloc[:, :-1].values
#Dependent Variable is Y
y = dataset.iloc[:, 1].values

# Splitting the dataset into the Training set and Test set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 1/3, random_state = 0)

# Feature Scaling ie reducing the values to compute
"""from sklearn.preprocessing import StandardScaler
sc_X =StandardScaler()
X_train=sc_X.fit_transform(X_train)
X_test=sc_X.fit_transform(X_test)
sc_y = StandardScaler()
y_train = sc_y.fit_transform(y_train.reshape(-1,1))"""

#Fitting simple linear regression to training set
from sklearn.linear_model import LinearRegression
regressor=LinearRegression()
#fitting regressor to training set and independent then dependent
regressor.fit(X_train,y_train)
#predection of test set
y_pred=regressor.predict(X_test)

# Visualising the Training set results
plt.scatter(X_train, y_train, color = 'red')
plt.plot(X_train, regressor.predict(X_train), color = 'blue')
plt.title('Salary vs Experience (Training set)')
plt.xlabel('Years of Experience')
plt.ylabel('Salary')
plt.show()

# Visualising the Test set results
plt.scatter(X_test, y_test, color = 'red')
plt.plot(X_train, regressor.predict(X_train), color = 'blue')
plt.title('Salary vs Experience (Test set)')
plt.xlabel('Years of Experience')
plt.ylabel('Salary')
plt.show()


#!/bin/env python
# coding:utf-8
import sqlite3
import MeCab
import argparse
# ネガポジ辞書作成
import urllib.request
#from mpi4py import MPI
import pandas as pd
import codecs
import logging
import json
import numpy as np
logger = logging.getLogger("logger")    #logger名loggerを取得
logger.setLevel(logging.DEBUG)  #loggerとしてはDEBUGで

def get_emoji():
    with open("../notebook/emoji_sentiment.json","r") as f:
        emoji = json.load(f)
    return emoji

def main():
    parser = argparse.ArgumentParser(description='calculate board score')
    parser.add_argument('--db',type=str, default="/Volumes/DATA/data/board/board.db")
    parser.add_argument('--dump',type=str, default="board_emoji_score.dump")
    parser.add_argument('--logfile',type=str, default="02_emoji_score.log")
    parser.add_argument('--fmdate',type=str,default="2017-05-01")
    parser.add_argument('--todate',type=str,default="2017-05-31")
    args = parser.parse_args()

    logging.basicConfig(level=logging.DEBUG,
                        filename=args.logfile,
                        format="%(asctime)s %(levelname)-7s %(message)s")

    emoji=get_emoji()

    tagger = MeCab.Tagger('-Ochasen')
    # http://qiita.com/kasajei/items/0805b433f363f1dba785
    tagger.parse("")
    # 文をMecabで単語分割
    def mecab_analysis(sentence):
        res=[]
        s = sentence.replace('\n', ' ')
        node = tagger.parseToNode(s)
        while node:
            if node.surface != "":  # BOS/EOSを除外
                ftlist = (node.feature).split(',')
                if ftlist[6] != "*":
                    o = ftlist[6]
                else:
                    o = node.surface
                res.append(o+"\t"+ftlist[0])  # word \t hinshi
            node = node.next
        return res

    def negaposi_score(word_list,dict):
        scores=[]
        score=0
        neg=0
        pos=0
        neu=0
        emojinum=0
        for wd in word_list:
            (word,hinshi)=wd.split("\t")
            if word in dict:
               lst=dict[word]
               neg=neg+lst[0]
               neu=neu+lst[1]
               pos=pos+lst[2]
               score=score+lst[3]
               emojinum+=1
               scores.append(lst[3])

        score_std=np.std(np.array(scores))
        return (len(word_list),emojinum,score,neg,neu,pos,score_std)

    con=sqlite3.connect(args.db)
    import pandas as pd
    cur = con.cursor()
    data = pd.io.sql.read_sql_query("select * from board where date between '" + args.fmdate + "' and '" + args.todate + "'", con)
    cur.close()
    con.close()

    mcon=sqlite3.connect(":memory:")
    mcur = mcon.cursor()
    with open("board.sql", "r") as f:
        lines = "".join(f.readlines())
        for sql in lines.split(";"):
            mcur.execute(sql)
            mcon.commit()

    for code, tno, mno, body in zip(data["code"], data["tno"], data["mno"], data["body"]):
        (sentence_wordnum,emoji_num, score,neg,neu,pos,score_std) = negaposi_score(mecab_analysis(body), emoji)
        if(score==0 and neg==0 and neu==0 and pos==0):
            continue
        mcur.execute("insert into board_emoji_sentiment_score values (?,?,?,?,?,?,?,?,?,?)",(code,str(tno),str(mno),score,score_std,neg,neu,pos,emoji_num,sentence_wordnum,))
        print(str(code)+","+str(tno)+","+str(mno)+","+str(score)+","+str(emoji_num)+","+str(sentence_wordnum))

    mcon.commit()

    with open(args.dump, 'w') as f:
        for line in mcon.iterdump():
            f.write('%s\n' % line)

if __name__ == "__main__":
    main()


# -*- encoding: utf-8 -*-
from lazyblacksmith.extension.esipy import esisecurity

from flask_oauthlib.client import OAuth
from six.moves.urllib.parse import urlparse
from werkzeug import security

import config

parsed_uri = urlparse(esisecurity.oauth_token)

oauth = OAuth()
eve_oauth = oauth.remote_app(
    'lb_eve_sso',
    access_token_url=esisecurity.oauth_token,
    authorize_url='%s://%s/oauth/authorize' % (
        parsed_uri.scheme,
        parsed_uri.netloc
    ),
    access_token_method='POST',
    request_token_method='GET',
    consumer_key=config.ESI_CLIENT_ID,
    consumer_secret=config.ESI_SECRET_KEY,
    request_token_params={
        'state': lambda: security.gen_salt(10),
        'scope': config.ESI_SCOPE,
    }
)


# MIT License
#
# Copyright (c) 2019 Creative Commons
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

"""from __future__ imports must occur at the beginning of the file. DO NOT CHANGE!"""
from __future__ import annotations

import sys
import argparse

from typing import TextIO

try:
    from gettext import gettext as _
except ImportError:
    def _(message: str):
        return message

class NARGS(object):
    """Class NARGS provides constant strings that specify the number of arguments for
    the add_argument() method."""
    OPTIONAL: str = "?"
    ZERO_OR_MORE: str = "*"
    ONE_OR_MORE: str = "+"

class OPT_ARGS_ACTION(object):
    """Class OPT_ARGS_ACTION provides the actions accepted by the add_argument() method
    while adding an optional argument."""
    COUNT: str = "count"
    STORE_TRUE: str = "store_true"

class _ArgumentParser(argparse.ArgumentParser):
    """We don't want any compatibility issue so we don't overwrite the constructor!
    The parent constructor method takes the following arguments:

    :Args:
        - prog: The name of the program (default: sys.argv[0])
        - usage: The string describing the program usage (default: generated from arguments
            added to parser)
        - description: Text to display before the argument help (default: none)
        - epilog: Text to display after the argument help (default: none)
        - parents: A list of ArgumentParser objects whose arguments should also be included
        - formatter_class: A class for customizing the help output
        - prefix_chars: The set of characters that prefix optional arguments (default: ‘-‘)
        - fromfile_prefix_chars: The set of characters that prefix files from which additional
            arguments should be read (default: None)
        - argument_default: The global default value for arguments (default: None)
        - conflict_handler: The strategy for resolving conflicting optionals (usually unnecessary)
        - add_help: Add a -h/--help option to the parser (default: True)
        - allow_abbrev: Allows long options to be abbreviated if the abbreviation is unambiguous.
            (default: True)
    """
    __COLOR_DICT = {"RED": "\x1b[1;31m",
                    "GREEN": "\x1b[1;32m",
                    "YELLOW": "\x1b[1;33m",
                    "BLUE": "\x1b[1;36m",
                    "RESET": "\x1b[0m"}

    def print_usage(self: _ArgumentParser, file: TextIO = None) -> None:
        """Method print_usage() is an overrided version of the parent's print_usage() method.
        This method provides text formatting as well.

        :Args:
            - self: {_ArgumentParser} self.
            - file: {TextIO} file to send the output to.

        :Returns:
            - {None}
        """
        if file is None:
            file = sys.stdout

        message: str = self.format_usage()

        self._print_message(
            message[0].upper() + message[1:], file, self.__COLOR_DICT["YELLOW"])

    def print_help(self: _ArgumentParser, file: TextIO = None) -> None:
        """Method print_help() is an overrided version of the parent's print_help() method.
        This method provides text formatting as well.

        :Args:
            - self: {_ArgumentParser} self.
            - file: {TextIO} file to dump the message in.

        :Returns:
            - {None}
        """
        if file is None:
            file = sys.stdout

        message: str = self.format_help()

        self._print_message(
            message[0].upper() + message[1:], file, self.__COLOR_DICT["BLUE"])

    def _print_message(
        self: _ArgumentParser,
        message: str,
        file: TextIO = None,
        color: str = None
    ) -> None:
        """Method _print_message() is an overrided version of the parent's _print_message() method.
        This method provides text formatting as well.

        :Args:
            - self: {_ArgumentParser} self.
            - message: {str} message to dump into the given file.
            - file: {TextIO} file to dump the message in.
            - color: {str} color to format that text in.

        :Returns:
            - {None}
        """
        if not message:
            return

        if file is None:
            file = sys.stderr

        if color is None:
            file.write(message)
            return

        file.write(color + message.strip() + self.__COLOR_DICT["RESET"] + '\n')

    def exit(
        self: _ArgumentParser,
        status: int = 0,
        message: str = None
    ) -> None:
        """Method exit() is an overrided version of the parent's exit() method. This method
        provides text formatting as well.

        :Args:
            - self: {_ArgumentParser} self.
            - status: {int} exit status.
            - message: {str} message to print on the stderr file.

        :Returns:
            - {None}
        """
        if message:
            self._print_message(message, sys.stderr, self.__COLOR_DICT["RED"])
        sys.exit(status)

    def error(
        self: _ArgumentParser,
        message: str,
        usage: bool = True
    ) -> None:
        """Method error() is an overrided version of the parent error() method. This method
        provides formatting as well.

        :Args:
            - self: {_ArgumentParser} self.
            - message: {str} message to print on the stderr file.
            - usage: {bool} whether to print usage or not.

        :Returns:
            - {None}
        """
        if usage:
            self.print_usage(sys.stderr)
        self.exit(2, _("%(prog)s: Error: %(message)s\n") %
                  {"prog": self.prog, "message": message})


from django.shortcuts import render
from django.http import HttpResponse
from main.forms import CityForm
from main.models import City
from main.helper import get_weather_data

def index(request):
	form = CityForm()

	if request.method == 'POST':
		form = CityForm(request.POST)
		if form.is_valid():
			form.save()
			lat = form.cleaned_data.get('lat')
			lon = form.cleaned_data.get('lon')
			weather_data = get_weather_data(lat, lon)
	elif request.method == 'GET':
		try:
			lat = City.objects.latest('date_added').lat
			lon = City.objects.latest('date_added').lon
			weather_data = get_weather_data(lat, lon)
		except Exception as e:
			weather_data = None

	context = {'form': form, 'weather_data': weather_data}
	return render(request, 'main/index.html', context=context)


import collections

import tensorflow as tf

from deephyper.nas.space import AutoKSearchSpace, SpaceFactory
from deephyper.nas.space.node import ConstantNode, VariableNode
from deephyper.nas.space.op.basic import Zero
from deephyper.nas.space.op.connect import Connect
from deephyper.nas.space.op.merge import AddByProjecting
from deephyper.nas.space.op.op1d import Dense, Identity, Dropout

class DenseSkipCoFactory(SpaceFactory):
    def build(
        self,
        input_shape,
        output_shape,
        regression=True,
        num_layers=10,
        dropout=0.0,
        **kwargs,
    ):
        ss = AutoKSearchSpace(input_shape, output_shape, regression=regression)
        source = prev_input = ss.input_nodes[0]

        # look over skip connections within a range of the 3 previous nodes
        anchor_points = collections.deque([source], maxlen=3)

        for _ in range(num_layers):
            vnode = VariableNode()
            self.add_dense_to_(vnode)

            ss.connect(prev_input, vnode)

            # * Cell output
            cell_output = vnode

            cmerge = ConstantNode()
            cmerge.set_op(AddByProjecting(ss, [cell_output], activation="relu"))

            for anchor in anchor_points:
                skipco = VariableNode()
                skipco.add_op(Zero())
                skipco.add_op(Connect(ss, anchor))
                ss.connect(skipco, cmerge)

            prev_input = cmerge

            # ! for next iter
            anchor_points.append(prev_input)

        if dropout >= 0.0:
            dropout_node = ConstantNode(op=Dropout(rate=dropout))
            ss.connect(prev_input, dropout_node)

        return ss

    def add_dense_to_(self, node):
        node.add_op(Identity())  # we do not want to create a layer in this case

        activations = [None, tf.nn.swish, tf.nn.relu, tf.nn.tanh, tf.nn.sigmoid]
        for units in range(16, 97, 16):
            for activation in activations:
                node.add_op(Dense(units=units, activation=activation))

if __name__ == "__main__":
    shapes = dict(input_shape=(10,), output_shape=(1,))
    factory = DenseSkipCoFactory()
    factory.test(**shapes)
    # factory.plot_model(**shapes)
    # factory.plot_space(**shapes)


"""gh_chest_xray_frontal_lateral dataset."""

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

import tensorflow_datasets.public_api as tfds
import tensorflow as tf
import pandas as pd
from glob import glob
import os

_CITATION = """
"""

_DESCRIPTION = """
gradient health private chest xray data including frontal, lateral and none three category. The dataset has three split: train/val/test. Only the train split has labels.
"""

class GhChestXrayFrontalLateral(tfds.core.GeneratorBasedBuilder):
  """private chest xray data including frontal and lateral"""

  VERSION = tfds.core.Version('0.1.0')
  MANUAL_DOWNLOAD_INSTRUCTIONS = """\
	you need have access to this private dataset
  """

  def _info(self):
    return tfds.core.DatasetInfo(
      builder=self,
      description=_DESCRIPTION,
      features=tfds.features.FeaturesDict({
        "image/name": tfds.features.Text(),
        "image": tfds.features.Image(shape=(None, None, 1),
                                         dtype=tf.uint16,
                                         encoding_format='png'),
        "label": tfds.features.ClassLabel(names=["None", "frontal", "lateral"]),
      }),

      homepage='https://dataset-homepage/',
      citation=_CITATION,
    )

  def _split_generators(self, dl_manager):
    """Returns SplitGenerators."""
    data_path = dl_manager.manual_dir
    train_df = pd.read_csv(os.path.join(data_path, "label.csv"))
    train_df.drop('timestamp', axis=1, inplace=True)
    train_df['filename'] = train_df['filename'].apply(lambda fname: os.path.join(data_path, fname))

    val_names = glob(os.path.join(data_path, 'val/*.jpg'))
    val_df =  pd.DataFrame(list(zip(val_names, ["None" for i in range(0, len(val_names))])), columns=['filename', 'label'])

    test_names = glob(os.path.join(data_path, 'test/*.jpg'))
    test_df =  pd.DataFrame(list(zip(test_names, ["None" for i in range(0, len(test_names))])), columns=['filename', 'label'])

    return [
      tfds.core.SplitGenerator(
          name=tfds.Split.TRAIN,
          gen_kwargs={
            'df':train_df,
          },
      ),
      tfds.core.SplitGenerator(
          name=tfds.Split.VALIDATION,
          gen_kwargs={
            'df':val_df,
          },
      ),
      tfds.core.SplitGenerator(
          name=tfds.Split.TEST,
          gen_kwargs={
            'df':test_df,
          },
      ),
    ]

  def _generate_examples(self, df):
    """Yields examples."""
    for idx, row in df.iterrows():
      record = {
        "image/name": "/".join(row.filename.split("/")[-2:]),
        "image": row.filename,
        "label": row.label
      }

      yield idx, record


"""Test Resources module."""

import unittest
import logging

from pyramid import testing

from utils import BaseTest, add_test_attribute

FORMAT_STR = '%(filename)s[LINE:%(lineno)d]#\
        %(levelname)-8s [%(asctime)s]  %(message)s'
logging.basicConfig(format=FORMAT_STR, level=logging.DEBUG)

class ResourceTests(unittest.TestCase):

    """Test class "Resource"."""

    from correlator.resources import Resource

    cls = Resource

    def test_constructor(self):
        """Test Resource constructor."""
        name = 'some_resource'
        parent = self.cls(None, name='parent_res')
        request = testing.DummyRequest()

        instance = self.cls(request, name=name, parent=parent)
        self.assertEqual(instance.__name__, name)
        self.assertEqual(instance.__parent__, parent)
        self.assertEqual(instance.request, request)

    def test_url(self):
        """ Get resource url.

        http://example.com/ - default host url.

        """
        name = 'some_resource'
        request = testing.DummyRequest()
        parent = self.cls(request)
        instance = self.cls(request, name=name, parent=parent)
        inst_url = 'http://example.com/{res_name}/'.format(res_name=name)

        self.assertEqual(instance.url(), inst_url)

class TraversingMixinTests(unittest.TestCase):

    """Test of TraversingMixin methods."""

    from correlator.resources import TraversingMixin

    class TraversalWithRequest(TraversingMixin):

        """docstring for Traversal."""

        request = None

    cls = TraversingMixin
    cls_with_request = TraversalWithRequest

    def test_is_valid(self):
        """Is factory with name is valid."""
        instance = self.cls()
        name = 'some_name'
        factory = None
        # factory is None
        self.assertFalse(instance._is_valid(name, factory))

        instance.factory_item = str
        factory = int
        self.assertTrue(instance._is_valid(name, factory))

        factory = str
        name = 'wrong name'
        self.assertFalse(instance._is_valid(name, factory))

        name = '123'
        self.assertTrue(instance._is_valid(name, factory))

    def test_get_item_empty_factory_map_error(self):
        """Test __get_item__, when factory_map is empty."""
        instance = self.cls_with_request()
        name = 'some_name'
        self.assertRaises(KeyError, instance.__getitem__, name)

    def test_get_item_empty_factory_map(self):
        """Test __get_item__, when factory_map is empty."""
        from correlator.resources import Resource
        req = testing.DummyRequest()

        instance = self.cls_with_request()
        instance.request = req
        instance.factory_item = Resource

        name = '111'
        expected_item = Resource(req, name=name, parent=instance)
        item = instance.__getitem__(name)
        self.assertEqual(item.__name__, expected_item.__name__)
        self.assertEqual(item.__parent__, expected_item.__parent__)
        self.assertEqual(item.request, expected_item.request)

class GraphTests(BaseTest):

    """Test of resources.Graph methods."""

    from correlator.resources import Graph

    cls = Graph

    def test_graph_id(self):
        """Test. Get int id from self.__name__."""
        req = testing.DummyRequest()
        id_ = 145
        instance = self.cls(req, name=str(id_))
        self.assertEqual(instance.graph_id, id_)

    def test_graph_data_by_no_existing_id(self):
        """Test. Get graph data by no existing id."""
        instance = self.cls(testing.DummyRequest, name='1345')
        self.assertEqual(instance.get_graph_data(), {})

    def test_get_graph_data(self):
        """Test get graph data."""
        from utils import date_format, add_test_dynamic
        from correlator.models import Graph as mGraph
        from correlator.models import Attribute

        title = 'Abra Abra'
        start_time = date_format.format(day='01')
        end_time = date_format.format(day=27)
        m_graph = mGraph('Abra Abra', start_time, end_time)
        m_graph.add()

        # Collect Attributes.
        attributes = []
        for attr_row in add_test_attribute(self.session_db, amount=6):
            attr = Attribute.get_by_name(attr_row[1])
            attributes.append(attr)
            # Add attribute to graph.
            m_graph.attributes.append(attr)
        # Add dynamic
        attributes_id_list = mGraph.get_attributes_ids(m_graph.id)
        add_test_dynamic(self.session_db, attributes_id_list)

        graph = self.cls(testing.DummyRequest, name=str(m_graph.id))
        graph_data = graph.get_graph_data()

        self.assertEqual(graph_data['title'], title)
        self.assertEqual(str(graph_data['start_time']), start_time)
        self.assertEqual(str(graph_data['end_time']), end_time)
        # attributes_values tested in get_attributes_values
        # timestamps tested in get_timestamps
        # correlation_data tested in Statistics.attributes_correlation()

class GraphsTests(BaseTest):

    """Test of resources.Graphs methods."""

    from correlator.resources import Graphs

    cls = Graphs
    instance = cls(testing.DummyRequest())

    def test_create_graph(self):
        """Test. Create graph."""
        from correlator.models import Attribute, Graph
        from utils import add_test_attribute
        from utils import date_format

        attrs_list = add_test_attribute(self.session_db, amount=4)
        attrs_ids = [row[0] for row in attrs_list]
        attrs = [Attribute.get_by_name(row[1]) for row in attrs_list]

        title = 'TEST_GRAPH#!@1'
        start_time = date_format.format(day='01')
        end_time = date_format.format(day='31')
        graph = self.instance.create_graph(title, start_time, end_time, attrs)

        self.assertEqual(graph.title, title)
        self.assertEqual(str(graph.start_time), start_time)
        self.assertEqual(str(graph.end_time), end_time)

        attrs_ids_db = Graph.get_attributes_ids(graph.id)
        for attr_id in attrs_ids_db:
            self.assertTrue(attr_id in attrs_ids)

    def test_get_graphs_attributes(self):
        """Test. Get graph: attributes dict."""

        from collections import OrderedDict

        from correlator.models import Attribute, Graph
        from utils import date_format

        Attribute.clean_table()
        Graph.clean_table()

        expected_dict = {}
        graphs_amount = 2
        graphs = []
        for i in xrange(graphs_amount):
            attrs_list = add_test_attribute(self.session_db, amount=4)
            attrs = [Attribute.get_by_name(row[1]) for row in attrs_list]

            title = 'TEST_GRAPH#!@{index}'.format(index=i)
            start_time = date_format.format(day='01')
            end_time = date_format.format(day='31')
            graph = self.instance.create_graph(
                title,
                start_time,
                end_time,
                attrs
            )
            graphs.append(graph)
            expected_dict[graph] = attrs

        expected_dict = OrderedDict(sorted(expected_dict.items(),
                                           key=lambda t: t[0].title))
        graphs_attributes = self.instance.get_graphs_attributes()
        self.assertEqual(graphs_attributes.keys(), expected_dict.keys())
        for graph, attrs in expected_dict.iteritems():
            self.assertEqual(attrs, graphs_attributes[graph])

    def test_delete_graph(self):
        """Test. Delete Graph. Simple test."""
        from correlator.models import Attribute
        from utils import date_format

        attrs_list = add_test_attribute(self.session_db, amount=4)
        attrs = [Attribute.get_by_name(row[1]) for row in attrs_list]

        title = 'TEST_GRAPH#!@{index}'.format(index=1)
        start_time = date_format.format(day='01')
        end_time = date_format.format(day='31')
        graph = self.instance.create_graph(
            title,
            start_time,
            end_time,
            attrs
        )
        self.instance.delete_graph(graph.id)

class CorrelationAnalysisTests(BaseTest):

    """Test of resources.CorrelationAnalysis methods."""

    from correlator.resources import CorrelationAnalysis

    cls = CorrelationAnalysis
    instance = cls(testing.DummyRequest())

    def test_get_correlation_data(self):
        """Get correlation data. Math part tested, but not here."""
        import itertools
        from utils import add_test_dynamic
        from utils import date_format
        from correlator.models import Attribute

        attr_list = add_test_attribute(self.session_db, amount=5)

        attrs_ids = [row[0] for row in attr_list]
        attrs_names = [row[1] for row in attr_list]
        add_test_dynamic(self.session_db, attrs_ids)

        dependency_name ='exponential'
        start_time = date_format.format(day='01')
        end_time = date_format.format(day='31')

        expected_pairs = set(i for i in itertools.permutations(attrs_names, 2))

        attrs = [Attribute.get_by_name(row[1]) for row in attr_list]
        correlation_data = self.instance.get_correlation_data(
            start_time, end_time, attrs, dependency_name)
        prepared_data = set(
            (item['x_attribute_name'], item['y_attribute_name'])
            for item in correlation_data
        )

        self.assertEqual(len(prepared_data), len(expected_pairs))
        self.assertEqual(prepared_data, expected_pairs)

    def test_compare_attributes(self):
        """Test."""

        from utils import add_test_dynamic
        from utils import date_format
        from correlator.models import Attribute

        attr_list = add_test_attribute(self.session_db, amount=2)
        attrs_ids = [row[0] for row in attr_list]
        attrs = []
        for attr in attr_list:
            attrs.append(Attribute.get_by_name(attr[1]))
        add_test_dynamic(self.session_db, attrs_ids)

        dependency_name ='exponential'
        start_time = date_format.format(day='01')
        end_time = date_format.format(day='31')

        compared_attrs = self.instance.compare_attributes(
            attr_list[0][1],
            attr_list[1][1],
            start_time,
            end_time,
            dependency_name
        )
        self.assertEqual(compared_attrs['x_attribute_name'], attr_list[0][1])
        self.assertEqual(compared_attrs['y_attribute_name'], attr_list[1][1])
        self.assertEqual(
            len(compared_attrs['x_attribute_values']),
            len(compared_attrs['y_attribute_values'])
        )


import os
import re
from collections import deque

PATH = os.path.abspath(__file__)
DIR_PATH = os.path.dirname(PATH)
INPUT = "{}/input.txt".format(DIR_PATH)

class SimpleLCD(object):
    def __init__(self, input):
        self.SCREEN = None
        self.INPUT = INPUT
        self.LINES = None
        self.DATA_POS = 0

    def setup_screen(self, row, col):
        self.SCREEN = deque([])
        for i in range(col):
            self.SCREEN.append(deque(0 for i in range(row)))

    def load_input(self):
        lines = []
        with open(self.INPUT, mode="r") as data:
            for line in data.readlines():
                lines.append(line.strip("\n"))
        self.LINES = lines

    def process_input(self):
        for line in self.LINES:
            self.DATA_POS += 1
            num_1, num_2 = map(int, re.findall(r'[0-9]+', line))
            if 'rect' in line:
                self.draw_rect(num_1, num_2)
            if 'row' in line:
                self.rotate_row(num_1, num_2)
            if 'column' in line:
                self.rotate_col(num_1, num_2)

    def rotate_row(self, pos, pxl):
        self.SCREEN[pos].rotate(pxl)

    def rotate_col(self, pos, pxl):
        col = deque([i[pos] for i in self.SCREEN])
        col.rotate(pxl)
        for i in range(len(col)):
            self.SCREEN[i][pos] = col[i]

    def draw_rect(self, row ,col):
        for i in range(col):
            for j in range(row):
                self.SCREEN[i][j] = 1

    @property
    def pixel_count(self):
        pixels = len([ x for y in self.SCREEN for x in y if x == 1])
        return pixels

    @property
    def display(self):
        output = None
        for row in self.SCREEN:
            if output:
                output += '\n'
            else:
                output = ''
            for col in row:
                if col == 0:
                    output += ' '
                elif col == 1:
                    output += '█'
        return output

if __name__ == '__main__':
    try:
        screen = SimpleLCD(INPUT)
        print("Initializing screen...")
        screen.setup_screen(50,6)
        print("Loading input data...")
        screen.load_input()
        print("Processing input...")
        screen.process_input()
        pixels = screen.pixel_count
        print("There are {} pixels lit up").format(pixels)
        print(screen.display)
    except Exception as ERROR:
        print("ERROR processing data on line {}").format(screen.DATA_POS)
        print(ERROR)


import pandas as pd
import re
import lxml
from bs4 import BeautifulSoup
from datetime import datetime
import json
from calendar import monthrange
import numpy as np

import glob, os

os.chdir("/Users/taj/GitHub/scraping/stayz/WebData/nsw_processed_calendar")

for file in glob.glob("*.json"):

#for file in glob.glob("*_9168471.json_proc.json"):

    print("Filename: " + file)

    # Open the Processed Calendar file
    p = pd.read_json('/Users/taj/GitHub/scraping/stayz/WebData/nsw_processed_calendar/' + file )
    p.head()

    # Open the file for writing out the bookings details:
    fp = open('/Users/taj/GitHub/scraping/stayz/WebData/nsw_bookings/stayz_bookings_' + file, 'w')

    first_page = True

    # Iterate over each entry in the Processed Calendar file:
    for index, row in p.iterrows():

        c = row['calendar']

        pid = row['property_id']

        days_count = 0
        avl_count = 0
        dep_count = 0
        arr_count = 0
        uvl_count = 0

        booking_count = 0

        dates = list(c.keys())

        min_dateIndex = 0
        max_dateIndex = len(dates)

        while (min_dateIndex < max_dateIndex):

            date = dates[min_dateIndex]
            status = c[date]

            # Count the total number of days
            days_count += 1

            if( status == 'AVL'):
                avl_count += 1

            if( status == 'ARR'):
                arr_count += 1
                # Iterate while the days are Unavailble until we find a Departure

                # Keep the arrival date:
                date_arr = date

                # Reset the count for this booking
                # Has to be at least one nights stay!
                booking_days = 1

                # Move to the next day.
                # Breaks if they arrive on the last day of the 6th month!!!
                min_dateIndex += 1
                #booking_days += 1

                if(min_dateIndex < max_dateIndex):
                    date = dates[min_dateIndex]
                    status = c[date]
                else:
                    date = None
                    status = None

                # If only one night stay. be careful how to increment booking_days???
                while(( status != 'DEP') & (min_dateIndex < max_dateIndex)):
                    date = dates[min_dateIndex]
                    status = c[date]

                    # Departure date doesnt count as a booked date, but as an available date
                    #booking_days += 1

                    days_count += 1

                    min_dateIndex += 1

                # Add in the last day
                avl_count += 1
                days_count += 1

                # Get the departure day details??

                if(min_dateIndex >= max_dateIndex):
                    # Booking runs over the end of the month into the 7th month, which we dont track
                    # Ignore this booking or just track to the end of the month?
                    date_dep = None

                    booking_days = 0
                else:
                    date_dep = date

                    b_days = datetime.strptime(date_dep,'%Y-%m-%d') - datetime.strptime(date_arr,'%Y-%m-%d')

                    # If the booking runs over the month, then create two entries. One for the first month, the second for next month??

                    booking_days = b_days.days

                # Calculate the days based on the dates

                #datetime_object = datetime.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p')

                # Track the total bookings.
                #booking_count += booking_days

                # Keep the date the calendar was extracted
                ext_at = str(row['ext_at'])

                # Show the booking details
                booking_detail = {
                    'property_id': pid,
                    'ext_at' : ext_at,
                    'arr_dt': date_arr,
                    'dep_dt': date_dep,
                    'book_days': str(booking_days)
                }

                if first_page is True:
                    fp.write('[\n')
                    first_page = False
                else:
                    fp.write('\n,')

                json.dump(booking_detail, fp)

            if( status == 'UVL'):
                uvl_count += 1

            min_dateIndex += 1

    # Close off the JSON
    fp.write(']')

    #print("Total days: " + str(days_count))
    #print("Available days: " + str(avl_count))
    #print("Departure days: " + str(dep_count))
    #print("Arrival days: " + str(arr_count))
    #print("Booked days: " + str(booking_count))
    #print("Unavailable days: " + str(uvl_count))
    #print("Total check: " + str(avl_count + booking_count + uvl_count))

    # Tidy up file handles
    fp.close()

# In[26]:

# Do a scatter plot of distance from sydney vs bookings count???

# Distance vs revenue?
# Distance vs revenue per person (assuming full occupancy)

# Percentage occupancy for the month vs distance
# 30/60/90 day occupancy vs distance (forward bookings)
# Las 30/60/90 day actual occupance vs distance (history bookings)


from enum import Enum
from Command import Command
import os

""" The parser module for the assembler.
"""

# Constants.
COMMENT_PREFIX = '//'
READ_ONLY = 'r'
DEF_ENCODING = 'utf-8'
EMPTY_LINE = ''

STR_ARITHMETIC = ['add', 'sub', 'neg', 'eq', 'gt', 'lt', 'and', 'or', 'not']
STR_PUSH = 'push'
STR_POP = 'pop'
STR_LABEL = 'label'
STR_GOTO = 'goto'
STR_IF = 'if'
STR_FUNCTION = 'function'
STR_RETURN = 'return'
STR_CALL = 'call'

class CommandType(Enum):
    ''' Enum for the command type.
    '''
    NO_COMMAND = -1
    C_ARITHMETIC = 0
    C_PUSH = 1
    C_POP = 2
    C_LABEL = 3
    C_GOTO = 4
    C_IF = 5
    C_FUNCTION = 6
    C_RETURN = 7
    C_CALL = 8

content = []

def parse(file_name):
    """ Parse a given assembly language file.
    """
    # Clean up when parsing a new file
    global content
    content = []
    current_command = None
    # Read the file and parse lines
    with open(file_name, mode=READ_ONLY, encoding=DEF_ENCODING) as vm_file:
        for line in vm_file:
            # Ignore whitespace & comments in the start and end of the line
            found_comment = line.find(COMMENT_PREFIX)
            if found_comment != -1:
                line = line[:found_comment]

            line = line.strip().split(' ')
            if line[0] == EMPTY_LINE:
                continue
            # Determine whether current line is A/L/C CommandType (L for Label)
            elif line[0] in STR_ARITHMETIC:
                current_command = CommandType.C_ARITHMETIC
            elif line[0] == STR_PUSH:
                current_command = CommandType.C_PUSH
            elif line[0] == STR_POP:
                current_command = CommandType.C_POP
            elif line[0] == STR_LABEL:
                current_command = CommandType.C_LABEL
            elif line[0] == STR_GOTO:
                current_command = CommandType.C_GOTO
            elif line[0] == STR_IF:
                current_command = CommandType.C_IF
            elif line[0] == STR_FUNCTION:
                current_command = CommandType.C_FUNCTION
            elif line[0] == STR_RETURN:
                current_command = CommandType.C_RETURN
            elif line[0] == STR_CALL:
                current_command = CommandType.C_CALL

            # Add the created command to the content list
            content.append(Command(current_command, line))

        # For loop ends here.

    # File is closed here

def get_commands():
    """ Get all commands in a parsed file - use this after running the parse function.
    This is a generator, thus running 'for command in get_commands()' will yield
    all commands in the parsed file in the correct order.
    """
    for command in content:
        yield command


from persistent import Persistent

class ConflictFreeLog(Persistent):
  """Scalable conflict-free append-only double-linked list

  Wasted ZODB space due to conflicts is roughly proportional to the number of
  clients that continuously add items at the same time.
  """
  _prev = _next = None
  _tail_count = 0
  _bucket_size = 1000

  def __init__(self, items=(), bucket_size=None):
    self._log = list(items)
    if bucket_size:
      assert bucket_size > 0
      self._bucket_size = bucket_size

  def __len__(self):
    return self._tail_count + len(self._log)

  def _maybe_rotate(self):
    if self._p_estimated_size < self._bucket_size:
      self._p_changed = 1
    else:
      tail = self.__class__()
      tail._log = self._log
      prev = self._prev
      if prev is None:
        prev = self
      else:
        assert not self._next._tail_count
        tail._tail_count = self._tail_count
      tail._prev = prev
      prev._next = tail
      self._prev = tail
      tail._next = self
      self._tail_count += len(self._log)
      self._log = []

  def append(self, item):
    if not self._p_changed:
      self._maybe_rotate()
    self._log.append(item)

  def extend(self, items):
    if not self._p_changed:
      self._maybe_rotate()
    self._log.extend(items)

  def __iadd__(self, other):
    self.extend(other)
    return self

  def __iter__(self):
    bucket = self._next
    if bucket is None:
      bucket = self
    while 1:
      for item in bucket._log:
        yield item
      if bucket is self:
        break
      bucket = bucket._next

  def reversed(self):
    bucket = self
    while 1:
      for item in bucket._log[::-1]:
        yield item
      bucket = bucket._prev
      if bucket in (None, self):
        break

  def _p_resolveConflict(self, old_state, saved_state, new_state):
    # May be called for the head and its predecessor.
    old_tail_count = old_state.get('_tail_count', 0)
    d = new_state.get('_tail_count', 0) - old_tail_count
    # Added elements by us:
    added = new_state['_log'][
      # The following computed value is also non-zero
      # if we rotated during a previous conflict resolution.
      len(old_state['_log']) - d
      :]
    if d:
      if old_tail_count == saved_state.get('_tail_count', 0):
        # We are the first one to rotate. Really rotate.
        # Only the head conflicts in this case.
        return dict(new_state, _log=saved_state['_log'][d:] + added)
      # Another node rotated before us. Revert our rotation.
      # Both the head and its predecessor conflict.
    #else:
      # We didn't rotate. Just add our items to saved head.
      # Only the head conflicts.
    saved_state['_log'] += added
    return saved_state


import os
import warnings
import sys

import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.metrics import precision_recall_fscore_support as score
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split

from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier

import mlflow
import mlflow.sklearn

from preprocessing_data import preprocessing_train, preprocessing_test

import logging
logging.basicConfig(level=logging.WARN)
logger = logging.getLogger(__name__)

if __name__ == "__main__":

    warnings.filterwarnings("ignore")
    np.random.seed(40)

    train = preprocessing_train()

    X = train.drop(columns=['TARGET'])
    y = train['TARGET']

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)

    sc = StandardScaler()
    X_train = sc.fit_transform(X_train)
    X_test = sc.transform(X_test)

    lr = float(sys.argv[1]) if len(sys.argv) > 1 else 0.1
    ne = int(sys.argv[2]) if len(sys.argv) > 500 else 100
    nj = int(sys.argv[3]) if len(sys.argv) > 3 else 1

    with mlflow.start_run():

        classifier = RandomForestClassifier(n_estimators=20, random_state=0)
        classifier.fit(X_train, y_train)
        predicted_qualities = classifier.predict(X_test)

        precision,recall,fscore,support=score(y_test, predicted_qualities)
        precision0 = precision[0]
        precision1 = precision[1]
        recall0 = recall[0]
        recall1 = recall[1]
        fscore0 = fscore[0]
        fscore1 = fscore[1]
        support0 = support[0]
        support1 = support[1]

        accuracy = accuracy_score(y_test, predicted_qualities)

        print("RandomForest Model (learning_rate=%f, n_estimators=%f, n_jobs=%f):" % (lr, ne, nj))

        mlflow.log_param("learning_rate", lr)
        mlflow.log_param("n_estimators", ne)
        mlflow.log_param("n_jobs", nj)
        mlflow.log_metric("precision0", precision0)
        mlflow.log_metric("precision1", precision1)
        mlflow.log_metric("recall0", recall0)
        mlflow.log_metric("recall1", recall1)
        mlflow.log_metric("fscore0", fscore0)
        mlflow.log_metric("fscore1", fscore1)
        mlflow.log_metric("support0", support0)
        mlflow.log_metric("support1", support1)
        mlflow.log_metric("accuracy", accuracy)

        mlflow.sklearn.log_model(classifier, "RandomForestClassifier")


#!/usr/bin/env python

# Copyright (C) 2010 Red Hat, Inc.
#
# This is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of
# the License, or (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this software; if not, write to the Free
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.

from art.rhevm_api.utils.test_utils import get_api
from art.core_api.apis_utils import getDS

ELEMENT = 'tag'
COLLECTION = 'tags'
util = get_api(ELEMENT, COLLECTION)

Tag = getDS('Tag')

def _prepareTagObject(**kwargs):

    tag = Tag()

    if 'name' in kwargs:
        tag.set_name(kwargs.get('name'))

    if 'description' in kwargs:
        tag.set_description(kwargs.get('description'))

    if 'parent' in kwargs:
        parent = util.find(kwargs.pop('parent'))
        tag.set_parent(parent)

    return tag

def addTag(positive, **kwargs):
    '''
    Description: create new tag
    Author: edolinin
    Parameters:
       * name - name of a new tag
       * description - tag description
       * parent - name of the tag to be used as a parent.
    Return: status (True if tag was created properly, False otherwise)
    '''

    tag = _prepareTagObject(**kwargs)
    tag, status = util.create(tag, positive)

    return status

def updateTag(positive, tag, **kwargs):
    '''
    Description: update existed tag
    Author: edolinin
    Parameters:
       * tag - name of a tag that should be updated
       * name - new tag name
       * description - new tag description
       * parent - name of the new parent tag
    Return: status (True if tag was updated properly, False otherwise)
    '''

    tagObj = util.find(tag)
    tagUpd = _prepareTagObject(**kwargs)
    tagUpd, status = util.update(tagObj, tagUpd, positive)
    return status

def removeTag(positive, tag):
    '''
    Description: remove existed tag
    Author: edolinin
    Parameters:
       * tag - name of a tag that should be removed
    Return: status (True if tag was removed properly, False otherwise)
    '''

    tagObj = util.find(tag)
    return util.delete(tagObj, positive)


from skimage import transform as tf
from skimage.feature import (match_descriptors, ORB, plot_matches)
import matplotlib.pyplot as plt
import cv2
from skimage.filters.rank import enhance_contrast, median
from skimage.exposure import equalize_adapthist
from skimage import morphology

# from skimage.measure import ransac as skransac
# from skimage.transform import EuclideanTransform
import numpy as np
from ex4_part1 import *
from scipy import misc

# img1 = misc.imread('BL05.bmp', flatten=0)
# img1 = cv2.medianBlur(img1[:,:,0, 15)

# img2 = misc.imread('FU05.bmp', flatten=0)
# img2 = cv2.medianBlur(img2[:,:,0, 15)

img1 = cv2.imread('BL01-no.tif', 0)

img1 = median(img1, selem=np.ones((12, 12)))

img2 = cv2.imread('FU01-no.tif', 0)
img2 = median(img2, selem=np.ones((12, 12)))

descriptor_extractor = ORB(n_keypoints=200, harris_k=1e-4)

descriptor_extractor.detect_and_extract(img1)
keypoints1 = descriptor_extractor.keypoints
descriptors1 = descriptor_extractor.descriptors

descriptor_extractor.detect_and_extract(img2)
keypoints2 = descriptor_extractor.keypoints
descriptors2 = descriptor_extractor.descriptors

matches12 = match_descriptors(descriptors1, descriptors2, cross_check=True,metric='euclidean')

display_matches(img1, img2, keypoints1[matches12[:, 0]], keypoints2[matches12[:, 1]])

fig, ax = plt.subplots(nrows=2, ncols=1)

plt.gray()

plot_matches(ax[0], img1, img2, keypoints1, keypoints2, matches12)
# plt.scatter(keypoints1[matches12[:, 0]][:, 1], keypoints1[matches12[:, 0]][:, 0])
# plt.scatter(keypoints2[matches12[:, 1]][:, 1] + img1.shape[1], keypoints2[matches12[:, 1]][:, 0])
ax[0].axis('off')
ax[0].set_title("Original Image vs. Transformed Image")

f, inliers = ransac(keypoints1[matches12[:, 0]], keypoints2[matches12[:, 1]], calcPointBasedReg, calcDist,
                    minPtNum=3, iterNum=20000, thDist=5, thInlrRatio=0.2)

# g, skinliers = skransac((keypoints1[matches12[:, 0]], keypoints2[matches12[:, 1]]), EuclideanTransform, min_samples=2,
#                     residual_threshold=10, max_trials=20000)
# inliers_idx = np.nonzero(inliers)[0]
inliers_idx = matches12[inliers]
plot_matches(ax[1], img1, img2, keypoints1, keypoints2, inliers_idx)
# plt.scatter(keypoints1[inliers[:, 0]][:, 1], keypoints1[inliers[:, 0]][:, 0])
# plt.scatter(keypoints2[inliers[:, 1]][:, 1] + img1.shape[1], keypoints2[inliers[:, 1]][:, 0])
ax[1].axis('off')
ax[1].set_title("ransac")

plt.show()

display_matches(img1, img2, keypoints1[matches12[:, 0]], keypoints2[matches12[:, 1]], inliers)


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

img = cv2.imread("avatar.jpg",cv2.IMREAD_GRAYSCALE)

ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
thresh6 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 5, 3)
titles = ['BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV', 'ADAPTIVE']
images = [thresh1, thresh2, thresh3, thresh4, thresh5, thresh6]

for i in range(6):
    plt.subplot(3,2,i+1),
    plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([1]), plt.yticks([1])
plt.show()


from urllib.request import urlopen
from json import loads
from tweeter import format_top_artist_tweet, send
from time import sleep

def tweet_top_artist(link):

    top_artists = urlopen(link).read()
    top_artists_json = loads(top_artists.decode())

    artist = top_artists_json['topartists']['artist'][0]['name']
    plays = top_artists_json['topartists']['artist'][0]['playcount']

    tweet = format_top_artist_tweet(artist, plays)
    status = send(tweet)

    return status

def main():
    username = "user-name"
    api_key = "api-key"

    link = "http://ws.audioscrobbler.com/2.0/?method=user.getTopArtists&user=" + username + "&limit=" + str(1) + "&api_key=" + api_key + "&format=json"

    while True:
        result = tweet_top_artist(link)
        sleep(2419200)

if __name__ == '__main__':
    main()


#!/usr/bin/env python3
# coding=utf-8
"""
A example usage of AutoCompleter with delayed initialization of the argparse object

Copyright 2018 Eric Lin <anselor@gmail.com>
Released under MIT license, see LICENSE file
"""
from typing import List

import cmd2
from cmd2 import argparse_completer, utils

actors = ['Mark Hamill', 'Harrison Ford', 'Carrie Fisher', 'Alec Guinness', 'Peter Mayhew',
          'Anthony Daniels', 'Adam Driver', 'Daisy Ridley', 'John Boyega', 'Oscar Isaac',
          'Lupita Nyong\'o', 'Andy Serkis', 'Liam Neeson', 'Ewan McGregor', 'Natalie Portman',
          'Jake Lloyd', 'Hayden Christensen', 'Christopher Lee']

def query_actors() -> List[str]:
    """Simulating a function that queries and returns a completion values"""
    return actors

class TabCompleteExample(cmd2.Cmd):
    """ Example cmd2 application where we a base command which has a couple sub-commands."""

    CAT_AUTOCOMPLETE = 'AutoComplete Examples'

    def __init__(self):
        super().__init__()

        video_types_subparsers = TabCompleteExample.video_parser.add_subparsers(title='Media Types', dest='type')

        vid_movies_parser = argparse_completer.ACArgumentParser(prog='movies')
        vid_movies_parser.set_defaults(func=TabCompleteExample._do_vid_media_movies)

        vid_movies_commands_subparsers = vid_movies_parser.add_subparsers(title='Commands', dest='command')

        vid_movies_list_parser = vid_movies_commands_subparsers.add_parser('list')

        vid_movies_list_parser.add_argument('-t', '--title', help='Title Filter')
        vid_movies_list_parser.add_argument('-r', '--rating', help='Rating Filter', nargs='+',
                                            choices=TabCompleteExample.ratings_types)
        # save a reference to the action object
        director_action = vid_movies_list_parser.add_argument('-d', '--director', help='Director Filter')
        actor_action = vid_movies_list_parser.add_argument('-a', '--actor', help='Actor Filter', action='append')

        # tag the action objects with completion providers. This can be a collection or a callable
        setattr(director_action, argparse_completer.ACTION_ARG_CHOICES, TabCompleteExample.static_list_directors)
        setattr(actor_action, argparse_completer.ACTION_ARG_CHOICES, query_actors)

        vid_movies_add_parser = vid_movies_commands_subparsers.add_parser('add')
        vid_movies_add_parser.add_argument('title', help='Movie Title')
        vid_movies_add_parser.add_argument('rating', help='Movie Rating', choices=TabCompleteExample.ratings_types)

        # save a reference to the action object
        director_action = vid_movies_add_parser.add_argument('-d', '--director', help='Director', nargs=(1, 2),
                                                             required=True)
        actor_action = vid_movies_add_parser.add_argument('actor', help='Actors', nargs='*')

        vid_movies_load_parser = vid_movies_commands_subparsers.add_parser('load')
        vid_movie_file_action = vid_movies_load_parser.add_argument('movie_file', help='Movie database')

        vid_movies_read_parser = vid_movies_commands_subparsers.add_parser('read')
        vid_movie_fread_action = vid_movies_read_parser.add_argument('movie_file', help='Movie database')

        # tag the action objects with completion providers. This can be a collection or a callable
        setattr(director_action, argparse_completer.ACTION_ARG_CHOICES, TabCompleteExample.static_list_directors)
        setattr(actor_action, argparse_completer.ACTION_ARG_CHOICES, 'instance_query_actors')

        # tag the file property with a custom completion function 'delimiter_complete' provided by cmd2.
        setattr(vid_movie_file_action, argparse_completer.ACTION_ARG_CHOICES,
                ('delimiter_complete',
                 {'delimiter': '/',
                  'match_against': TabCompleteExample.file_list}))
        setattr(vid_movie_fread_action, argparse_completer.ACTION_ARG_CHOICES,
                ('path_complete',))

        vid_movies_delete_parser = vid_movies_commands_subparsers.add_parser('delete')
        vid_delete_movie_id = vid_movies_delete_parser.add_argument('movie_id', help='Movie ID')
        setattr(vid_delete_movie_id, argparse_completer.ACTION_ARG_CHOICES, TabCompleteExample.instance_query_movie_ids)
        setattr(vid_delete_movie_id, argparse_completer.ACTION_DESCRIPTIVE_COMPLETION_HEADER, 'Title')

        # Add the 'movies' parser as a parent of sub-parser
        video_types_subparsers.add_parser('movies', parents=[vid_movies_parser], add_help=False)

        vid_shows_parser = argparse_completer.ACArgumentParser(prog='shows')
        vid_shows_parser.set_defaults(func=TabCompleteExample._do_vid_media_shows)

        vid_shows_commands_subparsers = vid_shows_parser.add_subparsers(title='Commands', dest='command')

        vid_shows_commands_subparsers.add_parser('list')

        video_types_subparsers.add_parser('shows', parents=[vid_shows_parser], add_help=False)

    # For mocking a data source for the example commands
    ratings_types = ['G', 'PG', 'PG-13', 'R', 'NC-17']
    show_ratings = ['TV-Y', 'TV-Y7', 'TV-G', 'TV-PG', 'TV-14', 'TV-MA']
    static_list_directors = ['J. J. Abrams', 'Irvin Kershner', 'George Lucas', 'Richard Marquand',
                             'Rian Johnson', 'Gareth Edwards']
    USER_MOVIE_LIBRARY = ['ROGUE1', 'SW_EP04', 'SW_EP05']
    MOVIE_DATABASE_IDS = ['SW_EP1', 'SW_EP02', 'SW_EP03', 'ROGUE1', 'SW_EP04',
                          'SW_EP05', 'SW_EP06', 'SW_EP07', 'SW_EP08', 'SW_EP09']
    MOVIE_DATABASE = {'SW_EP04': {'title': 'Star Wars: Episode IV - A New Hope',
                                  'rating': 'PG',
                                  'director': ['George Lucas'],
                                  'actor': ['Mark Hamill', 'Harrison Ford', 'Carrie Fisher',
                                            'Alec Guinness', 'Peter Mayhew', 'Anthony Daniels']
                                  },
                      'SW_EP05': {'title': 'Star Wars: Episode V - The Empire Strikes Back',
                                  'rating': 'PG',
                                  'director': ['Irvin Kershner'],
                                  'actor': ['Mark Hamill', 'Harrison Ford', 'Carrie Fisher',
                                            'Alec Guinness', 'Peter Mayhew', 'Anthony Daniels']
                                  },
                      'SW_EP06': {'title': 'Star Wars: Episode VI - Return of the Jedi',
                                  'rating': 'PG',
                                  'director': ['Richard Marquand'],
                                  'actor': ['Mark Hamill', 'Harrison Ford', 'Carrie Fisher',
                                            'Alec Guinness', 'Peter Mayhew', 'Anthony Daniels']
                                  },
                      'SW_EP1': {'title': 'Star Wars: Episode I - The Phantom Menace',
                                 'rating': 'PG',
                                 'director': ['George Lucas'],
                                 'actor': ['Liam Neeson', 'Ewan McGregor', 'Natalie Portman', 'Jake Lloyd']
                                 },
                      'SW_EP02': {'title': 'Star Wars: Episode II - Attack of the Clones',
                                  'rating': 'PG',
                                  'director': ['George Lucas'],
                                  'actor': ['Liam Neeson', 'Ewan McGregor', 'Natalie Portman',
                                            'Hayden Christensen', 'Christopher Lee']
                                  },
                      'SW_EP03': {'title': 'Star Wars: Episode III - Revenge of the Sith',
                                  'rating': 'PG-13',
                                  'director': ['George Lucas'],
                                  'actor': ['Liam Neeson', 'Ewan McGregor', 'Natalie Portman',
                                            'Hayden Christensen']
                                  },

                      }
    USER_SHOW_LIBRARY = {'SW_REB': ['S01E01', 'S02E02']}
    SHOW_DATABASE_IDS = ['SW_CW', 'SW_TCW', 'SW_REB']
    SHOW_DATABASE = {'SW_CW': {'title': 'Star Wars: Clone Wars',
                               'rating': 'TV-Y7',
                               'seasons': {1: ['S01E01', 'S01E02', 'S01E03'],
                                           2: ['S02E01', 'S02E02', 'S02E03']}
                               },
                     'SW_TCW': {'title': 'Star Wars: The Clone Wars',
                                'rating': 'TV-PG',
                                'seasons': {1: ['S01E01', 'S01E02', 'S01E03'],
                                            2: ['S02E01', 'S02E02', 'S02E03']}
                                },
                     'SW_REB': {'title': 'Star Wars: Rebels',
                                'rating': 'TV-Y7',
                                'seasons': {1: ['S01E01', 'S01E02', 'S01E03'],
                                            2: ['S02E01', 'S02E02', 'S02E03']}
                                },
                     }

    file_list = \
        [
            '/home/user/file.db',
            '/home/user/file space.db',
            '/home/user/another.db',
            '/home/other user/maps.db',
            '/home/other user/tests.db'
        ]

    def instance_query_actors(self) -> List[str]:
        """Simulating a function that queries and returns a completion values"""
        return actors

    def instance_query_movie_ids(self) -> List[str]:
        """Demonstrates showing tabular hinting of tab completion information"""
        completions_with_desc = []

        # Sort the movie id strings with a natural sort since they contain numbers
        for movie_id in utils.natural_sort(self.MOVIE_DATABASE_IDS):
            if movie_id in self.MOVIE_DATABASE:
                movie_entry = self.MOVIE_DATABASE[movie_id]
                completions_with_desc.append(argparse_completer.CompletionItem(movie_id, movie_entry['title']))

        # Mark that we already sorted the matches
        self.matches_sorted = True
        return completions_with_desc

    ###################################################################################
    # The media command demonstrates a completer with multiple layers of subcommands
    #   - This example demonstrates how to tag a completion attribute on each action, enabling argument
    #       completion without implementing a complete_COMMAND function
    def _do_vid_media_movies(self, args) -> None:
        if not args.command:
            self.do_help('video movies')
        elif args.command == 'list':
            for movie_id in TabCompleteExample.MOVIE_DATABASE:
                movie = TabCompleteExample.MOVIE_DATABASE[movie_id]
                print('{}\n-----------------------------\n{}   ID: {}\nDirector: {}\nCast:\n    {}\n\n'
                      .format(movie['title'], movie['rating'], movie_id,
                              ', '.join(movie['director']),
                              '\n    '.join(movie['actor'])))

    def _do_vid_media_shows(self, args) -> None:
        if not args.command:
            self.do_help('video shows')

        elif args.command == 'list':
            for show_id in TabCompleteExample.SHOW_DATABASE:
                show = TabCompleteExample.SHOW_DATABASE[show_id]
                print('{}\n-----------------------------\n{}   ID: {}'
                      .format(show['title'], show['rating'], show_id))
                for season in show['seasons']:
                    ep_list = show['seasons'][season]
                    print('  Season {}:\n    {}'
                          .format(season,
                                  '\n    '.join(ep_list)))
                print()

    video_parser = argparse_completer.ACArgumentParser(prog='video')

    @cmd2.with_category(CAT_AUTOCOMPLETE)
    @cmd2.with_argparser(video_parser)
    def do_video(self, args):
        """Video management command demonstrates multiple layers of sub-commands being handled by AutoCompleter"""
        func = getattr(args, 'func', None)
        if func is not None:
            # Call whatever subcommand function was selected
            func(self, args)
        else:
            # No subcommand was provided, so call help
            self.do_help('video')

if __name__ == '__main__':
    import sys
    app = TabCompleteExample()
    sys.exit(app.cmdloop())