#! /usr/bin/env python
"""
Modified Next Reaction Method with delays
=========================================

This module performs the Next Reaction Method with delay from Anderson [1], Algorithm 7.
Note that the definition of Cai is used for types of delayed reactions: consuming and non-consuming.

[1] David F. Anderson "A modified next reaction mehtod for simulating chemical systems with
time dependent propensities and delays", J. Phys. Chem., 2007, 127, 214107

Author: M. Moinat, T.R. Maarleveld
Adapted from 'NextReactionMethod' by T.R. Maarleveld, Amsterdam, The Netherlands
Last Change: June 08, 2015
"""
from __future__ import division, print_function, absolute_import
import sys,copy,time,os

from .StochPyTools import __species__,StochPySSA_Shared,np

#############################################################

class DelayedNRM(StochPySSA_Shared):
    """
    Modified Next Reaction Method from Anderson 2007 [1].

    [1] David F. Anderson "A modified next reaction mehtod for simulating chemical systems with
      time dependent propensities and delays", J. Phys. Chem., 2007, 127, 214107

    Input:
     - *model_file* filename.psc
     - *model_dir* /home/user/Stochpy/pscmodels/filename.psc
    """
    def __init__(self,model_file,model_dir,IsQuiet=False):
        self.Parse(model_file,model_dir,IsQuiet=IsQuiet,IsNRM = True, IsDelayed=True,IsSMM = False)

    def Execute(self,settings,IsStatusBar=False):
        """
        Generates steps of the Markov jump process.

        Input:
         - *settings* (class object)
        """
        if settings.IsSeed:
            np.random.seed(5)

        self._IsInitial = True
        self.settings = settings
        self.sim_t = copy.copy(settings.starttime)
        self.X_matrix = copy.deepcopy(settings.X_matrix)
        self.fixed_species_amount = copy.deepcopy(self.parse.fixed_species_amount)

        try:
            self.volume_code = settings.volume_code
        except AttributeError:                             # No volume_code present in settings
            self.volume_code = "self._current_volume = 1"

        #self.species_to_update = [s for s in range(self.n_species)] # ensure that the first run updates all species
        self.BuildInits()                                  # Step 1
        self.Propensities()                                # Step 2

        if not self.sim_t:
            self.timestep = 1
            self.sim_output = []
            self.propensities_output = []
            self.V_output = []
            self._IsTrackPropensities = copy.copy(settings.IsTrackPropensities)
            self.SpeciesSelection()
            self.RateSelection()
            self.SetEvents()  # April 15, moved into here, because otherwise each new cell division cycle starts with a time event, if specified
            if not settings.IsOnlyLastTimepoint:
                self.Initial_Conditions()
            # Delayed Direct method specific
            self.Tstruct = [(0, np.nan), (np.inf, np.nan)]  # Will hold delayed reactions

        #Step 3 Initialize P
        m_randoms = np.random.random(size = self.n_reactions)
        self.P = -1*np.log(m_randoms)                       # Exponential (unit rate) distribution
        self.T = np.zeros(self.n_reactions)                 # Step 1
        self.BuildTaus()                                    # Step 4, initialization

        nstep_counter = 1
        t1 = time.time()
        while self.sim_t < settings.endtime and self.timestep < settings.timesteps:
            if self.sim_a_mu.sum() == 0 and len(self.Tstruct) <= 2:       # All reactants got exhausted and no delayed reactions pending.
                 settings.endtime = 10**50
                 break

            self.RunExactTimestep()                         # Step 5-10
            self.HandleEvents()

            #Update system, only if max time or steps is not passed
            if (self.sim_t < settings.endtime) and (self.timestep < settings.timesteps):
                # Bug Fix Maxim september 05, 2014
                if self._IsPerformEvent:
                    m_randoms = np.random.random(size = self.n_reactions)
                    self.P = -1*np.log(m_randoms)           # Exponential (unit rate) distribution
                    self.T = np.zeros(self.n_reactions)     # Step 1
                    self.BuildTaus()                        # Step 4, initialization
                    self.species_to_update  = [s for s in range(self.n_species)]
                else:
                    self.UpdateTP()                         # Steps 11,12

                self.Propensities()                         # Step 13

                #Update taus (and order)
                self.BuildTaus()                            # Step 4, iterative

                if not settings.IsOnlyLastTimepoint: #16-01-2014
                   self.GenerateOutput()

            if (self.sim_t < settings.endtime):
                self.timestep += 1
            t2 = time.time()
            if IsStatusBar and t2-t1> 1:
                t1 = time.time()
                sys.stdout.write('\rsimulating {0:s}\r'.format('.'*nstep_counter) )
                sys.stdout.flush()
                nstep_counter+=1
                if nstep_counter > 10:
                    nstep_counter = 1

        if settings.IsOnlyLastTimepoint or settings.endtime != 10**50:
            self.GenerateOutput()

        if IsStatusBar and t1 and not settings.quiet:
            sys.stdout.write('\rsimulation done!               \n')

    def BuildInits(self):
        """ Build initials that are necessary to generate a trajectory """
        self.rFire= np.ones(self.n_reactions)
        self.sim_a_mu_zero = []
        for i in range(self.n_reactions):
            self.sim_a_mu_zero.append({'t1':0,'a_alpha_old':0,'tau_alpha':0})
        self.sim_taus = None                            # necessary for iteration

    def BuildTaus(self):
        """ (Re)Calculates and orders taus """
        self.sim_taus = (self.P - self.T)/self.sim_a_mu # Calculates all initial taus from P and T arrays.
        self.tauPairs = [(tau, reaction_index) for reaction_index, tau in enumerate(self.sim_taus)]
        self.tauPairs.sort()                            # Sorts on reaction times (taus), ascending.

    def UpdateTP(self):
        """ Update T and P """
        #Update all T's (= a kind of integral)
        self.T += self.sim_a_mu * self.tau              # Step 8

        #Only update P of reaction that initiated (so is not a completed delayed reaction). Only random generated each step is here
        if not self._IsCompletionDelayed:
            random = np.random.random()
            self.P[self.reaction_index] += -1*np.log(random)

    def RunExactTimestep(self):
        """ Perform a direct SSA time step """
        self.GetTauReaction()                           # Step 5
        self.sim_t += self.tau                          # Step 6
        if self.sim_t < self.settings.endtime:
            #Perform reaction
            if self._IsCompletionDelayed:               # Step 7, complete the delayed reaction.
                self.CompleteReaction()
                if self.reactions_NonConsuming:         # Saves time if no nonconsuming
                    self.CheckReactantExhaustion()      # 9-01-2014 Prevents negative species due to delayed nonconsuming reactions.
            else:
                self.InitiateReaction()                 # Steps 8,9,10

            self.prop_to_update = self.parse.dep_graph[self.reaction_index] # Propensities to update, does not see difference N_matrix_reactants or N_matrix_products into account
            if self.reaction_index not in self.prop_to_update:
                self.prop_to_update.append(self.reaction_index)     # Always add fired reaction to update
            self.rFire= np.zeros(self.n_reactions)
            for pos in self.prop_to_update:
                self.rFire[pos] = 1                                 # Makes sure that in Propensities() only changed propensities get updated
        else:
            self.sim_t = self.settings.endtime
            self.reaction_index = np.nan

    def GetTauReaction(self):
        """ Gets minimum tau, corresponding reaction index and whether it initiates or completes """
        #Tau is relative, not absolute as in normal NRM (!!!)
        self.minimum_reaction = self.tauPairs[0]                   # Pick first initiation reaction to occur
        self.tau_reaction = self.minimum_reaction[0]               # Pick tau of the reaction

        self.minimum_delay = self.Tstruct[1]                       # From sorted Tstruct (on index 0 is the initial (0, np.nan))
        self.tau_delay = self.minimum_delay[0] - self.sim_t        # Convert from absolute to relative time

        if self.tau_reaction <= self.tau_delay:                    # Initiate a reaction
            self.tau = self.tau_reaction
            self.reaction_index = self.minimum_reaction[1]
            self._IsCompletionDelayed = False
        else:                                                      # A delayed reaction completes (self.tau_delay < self.tau_reaction)
            self.tau = self.tau_delay
            self.reaction_index = self.minimum_delay[1]
            self._IsCompletionDelayed = True

    def InitiateReaction(self):
        """ Initiates a reaction based on being delayed (consuming or nonconsuming) or not """
        if self.reaction_index in self.reactions_Consuming:                     # Step 10, Consuming delayed
            self.X_matrix += self.N_matrix_transpose_reactants[self.reaction_index]             # Updates only reactants
            self.species_to_update = self.parse.reactant_indices[ self.reaction_index ]
            self.add_delay()
        elif self.reaction_index in self.reactions_NonConsuming:                # Step 9, Non-consuming delayed
            self.add_delay()
            self.species_to_update = []
        else:                                                                   # Step 8, A normal, non-delayed reaction
            self.X_matrix += self.N_matrix_transpose[self.reaction_index]
            self.species_to_update = self.parse.reaction_affects[ self.reaction_index ]

    def CompleteReaction(self):
        """ Completes a delayed reaction, depending on consuming or not or not"""
        if self.reaction_index in self.reactions_Consuming:                     # Only updates products
            self.X_matrix += self.N_matrix_transpose_products[self.reaction_index]
            self.species_to_update = self.parse.product_indices[ self.reaction_index ]
        elif self.reaction_index in self.reactions_NonConsuming:                # Updates reactants and products
            self.X_matrix += self.N_matrix_transpose[self.reaction_index]
            self.species_to_update = self.parse.reaction_affects[ self.reaction_index ]
        else:
            print("This should not happen. A non-delayed reaction is completing with a delay...")

        self.Tstruct.pop(1)                                                     # Remove the completion time from the list, assumes Tstruct is sorted and Tstruct[0] = (0,np.nan)

    def add_delay(self):
        """ Adds delay time from distribution, specified in DoDelayedStochSim (StochSim.py) """
        delay = self.distr_functions[ self.reaction_index ]( *self.distr_parameters[ self.reaction_index ] )    # Each delayed reaction has its own distribution

        if type(delay) == np.ndarray:
            print("Warning! Delay parameters don't match the distribution ({0} with {1})".format(self.distr_functions[ self.reaction_index ], self.distr_parameters[ self.reaction_index ]))
            delay = delay[0]

        #Check for negative delays
        i=0
        while delay < 0:
            print("Warning: The chosen distribution ({0}) produced a negative delay. Drawing new delay.".format(self.distr_functions[ self.reaction_index ]))
            if i==0:
                print("Delay distributions will be distorted and simulation speed will be drastically lower.")
            delay = self.distr_functions[ self.reaction_index ]( *self.distr_parameters[ self.reaction_index ] )
            i += 1
            if i >= 10:
                print("Error: negatives delays keep occuring. Please choose different delay distributions.")
                sys.exit(1)

        #Add ABSOLUTE completion time and resort Tstruct
        self.Tstruct.insert(-1, (delay + self.sim_t, self.reaction_index))
        self.Tstruct.sort()

    def CheckReactantExhaustion(self):
        """ Checks wheter a reactant is exhausted after completion and deletes the pending delayed reactions of this reactant."""
        for r_nonconsuming in self.reactions_NonConsuming:
            for r in self.parse.reactant_indices[r_nonconsuming]:
                if self.X_matrix[r] == 0:                     # Reactant Exhausted
                    # Remove all pending r_nonconsuming reactions from Tstruct, if one of reactants exhausted. Order is not affected.
                    self.Tstruct = [tau_pair for tau_pair in self.Tstruct if tau_pair[1] != r_nonconsuming]
                                   #list(filter(lambda tau_pair: tau_pair[1] != r_nonconsuming, self.Tstruct)) Python 3.x


import nengo
import nengo_spa as spa
import numpy as np
import sys

# Import our classes
sys.path.append('..')
from modules import *
from vocabs import *

BG_bias = .5
BG_thr = .5
D = 64
vocab = create_vocab(D, key_range(1,11,1) + ['D0=D1*~D1'] + ['GET_V ; GET_COM ; GET_ADD ; SET_COM ; SET_ADD ; SET_M'])

with spa.Network() as model:

    input_INSTRUCTIONS = spa.Transcode(
        lambda t: '\
                D1 * (GET_V) +\
                D2 * (GET_ADD + SET_ADD) +\
                D3 * (GET_COM + SET_COM) + \
                D4 * (SET_M) \
            ',
        output_vocab=vocab
    )
    POS = WM(100, vocab)
    clean_POS = spa.WTAAssocMem(
        threshold=.2,
        input_vocab=POS.vocab,
        mapping=['D1','D2','D3','D4'],
        n_neurons=50,
        function=lambda x: x>0
    )
    nengo.Connection(POS.output, clean_POS.input)
    INCREMENT = WM(100, vocab)

    PRIM = spa.Bind(neurons_per_dimension=200, vocab=vocab, unbind_right=True)
    GET_PRIM = spa.WTAAssocMem(
        threshold=.5,
        input_vocab=PRIM.vocab,
        mapping=['GET_V', 'GET_COM', 'GET_ADD'],
        n_neurons=50,
        function=lambda x: x>0
    )
    SET_PRIM = spa.WTAAssocMem(
        threshold=.5,
        input_vocab=PRIM.vocab,
        mapping=['SET_COM', 'SET_ADD', 'SET_M'],
        n_neurons=50,
        function=lambda x: x>0
    )
    PRIM >> GET_PRIM
    PRIM >> SET_PRIM

    input_INSTRUCTIONS >> PRIM.input_left
    spa.translate(clean_POS, vocab) >> PRIM.input_right

    SET_exec = spa.Transcode(input_vocab=vocab, output_vocab=vocab)
    GET_exec = spa.Transcode(input_vocab=vocab, output_vocab=vocab)

    # GET selector
    with spa.Network(label='GET selector') as GET_selector:
        GET_selector.labels = []
        with spa.ActionSelection() as GET_selector.AS:

            GET_selector.labels.append("GET V (FIXATE)")
            spa.ifmax(GET_selector.labels[-1], BG_bias + FIXATE_detector,
                V.preconscious >> GW.AMs[V].input,
                s.D1 >> POS.input,
                s.D1 * clean_POS >> INCREMENT.input
            )

            # GET_selector.labels.append("GET V")
            # spa.ifmax(GET_selector.labels[-1], BG_bias + spa.dot(GET_PRIM, s.GET_V) * (1-spa.dot(GET_exec, s.GET_V)),
            #     s.GET_V >> GET_exec,
            #     1 >> POS.gate,
            # )

            GET_selector.labels.append("GET ADD")
            spa.ifmax(GET_selector.labels[-1], BG_bias + spa.dot(GET_PRIM, s.GET_ADD) * (1-GW.detectors[ADD]),
                ADD.preconscious >> GW.AMs[ADD].input,
                1 >> POS.gate,
                s.D1 * clean_POS >> INCREMENT.input
            )

            GET_selector.labels.append("GET COM")
            spa.ifmax(GET_selector.labels[-1], BG_bias + spa.dot(GET_PRIM, s.GET_COM) * (1-GW.detectors[COM]),
                COM.preconscious >> GW.AMs[COM].input,
                1 >> POS.gate,
                s.D1 * clean_POS >> INCREMENT.input
            )

            GET_selector.labels.append("Thresholder")
            spa.ifmax(GET_selector.labels[-1], BG_bias + BG_thr,
                1 >> INCREMENT.gate,
                INCREMENT >> POS.input

            )

    # SET selector
    with spa.Network(label='SET selector', seed=seed) as SET_selector:
        SET_selector.labels = []
        with spa.ActionSelection() as SET_selector.AS:

            # SET_selector.labels.append("SET ADD")
            # spa.ifmax(SET_selector.labels[-1], BG_bias + spa.dot(SET_PRIM, s.SET_ADD) * (1-GW.detectors[ADD]),
            #     GW.AMs[COM] >> ADD.broadcast,
            #     GW.AMs[V] >> ADD.broadcast,
            # )

            SET_selector.labels.append("SET COM")
            spa.ifmax(SET_selector.labels[-1], BG_bias + spa.dot(SET_PRIM, s.SET_COM) * (1-GW.detectors[COM]),
                # GW.AMs[ADD] >> COM.broadcast,
                GW.AMs[V] >> COM.broadcast,
            )

            SET_selector.labels.append("SET M")
            spa.ifmax(SET_selector.labels[-1], BG_bias + spa.dot(SET_PRIM, s.SET_M),
                GW.AMs[COM] >> M.broadcast,
                GW.AMs[V] >> M.broadcast,
                # GW.AMs[ADD] >> M.broadcast,
            )

            SET_selector.labels.append("Thresholder")
            spa.ifmax(SET_selector.labels[-1], BG_bias + BG_thr) # Threshold for action


"""
>>> import cmdix
>>> cmdix.runcommandline('sleep 0')
"""

import time

def parseargs(p):
    """
    Add arguments and `func` to `p`.

    :param p: ArgumentParser
    :return:  ArgumentParser
    """
    p.set_defaults(func=func)
    p.description = "delay for a specified amount of time"
    p.epilog = (
        "Pause for NUMBER seconds. SUFFIX may be 's' for "
        + "seconds (the default), 'm' for minutes, 'h' for "
        + "hours or 'd' for days. Unlike most implementations "
        + "that require NUMBER be an integer, here NUMBER may "
        + "be an arbitrary floating point number. Given two or "
        + "more arguments, pause for the amount of time"
    )
    p.add_argument('number', nargs='+', type=duration)
    return p

def duration(spec):
    """
    >>> duration('1')
    1.0
    >>> duration('1s')
    1.0
    >>> duration('1 s')
    1.0
    >>> duration('1h')
    3600.0
    >>> duration('1d')
    86400.0
    >>> duration('1m')
    60.0
    """
    if spec.endswith('s'):
        return float(spec[:-1])
    elif spec.endswith('m'):
        return float(spec[:-1]) * 60
    elif spec.endswith('h'):
        return float(spec[:-1]) * 3600
    elif spec.endswith('d'):
        return float(spec[:-1]) * 86400
    return float(spec)

def func(args):
    time.sleep(sum(args.number))


from odoo import _, api, fields, models

class SaleOrder(models.Model):
    _inherit = "sale.order"

    payment_ids = fields.Many2many(
        string="Payments",
        comodel_name="account.payment",
        compute="_compute_payment_ids")
    payment_count = fields.Integer(
        string="Payments Count",
        compute="_compute_payment_count")

    def _compute_payment_count(self):
        for sale in self:
            sale.payment_count = len(sale.payment_ids)

    def _compute_payment_ids(self):
        for sale in self:
            sale.payment_ids = False
            payments = []
            for move in sale.invoice_ids:
                for payment in move.payment_ids:
                    if payment not in payments:
                        payments.append(payment.id)
            if payments:
                sale.payment_ids = [(6, 0, payments)]

    def action_view_payments(self):
        return {
            "name": _("Payments"),
            "view_mode": "tree,form",
            "res_model": "account.payment",
            "domain": [("id", "in", self.payment_ids.ids)],
            "type": "ir.actions.act_window",
            "context": self.env.context
            }


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

class Classifier(nn.Module):

    def __init__(self, model, im_size, num_classes):
        super(Classifier, self).__init__()
        self.model = model
        sample_inp = torch.randn((1,3, im_size, im_size)).cuda()
        _, x = model(sample_inp)
        b_sz = x.shape[0]
        in_channel = x.view(b_sz, -1).shape[1]

        self.linear = nn.Linear(in_channel, num_classes)

    def forward(self, x):
        _, x = self.model(x)
        x = self.linear(x)
        return F.log_softmax(x, dim=1)


import numpy as np
import cv2
import datasets

def expand_channels(dataset:datasets.ClassificationDataset,c:int):
    if dataset.dataformat=="NHWC":
        axis=3
    else:
        axis=1

    dataset.x_train = np.repeat(dataset.x_train,c,axis=axis)
    dataset.x_test = np.repeat(dataset.x_test, c, axis=axis)

def collapse_channels(dataset:datasets.ClassificationDataset):
    if dataset.dataformat=="NHWC":
        axis=3
    else:
        axis=1
    dataset.x_train = dataset.x_train.mean(axis=axis,keepdims=True)
    dataset.x_test  = dataset.x_test.mean(axis=axis,keepdims=True)

def resize(dataset:datasets.ClassificationDataset,h:int,w:int,c:int):

    if dataset.dataformat=="NCHW":
        dataset.x_train=np.transpose(dataset.x_train,axes=(0,2,3,1))
        dataset.x_test = np.transpose(dataset.x_test, axes=(0, 2, 3, 1))

    subsets = [dataset.x_train, dataset.x_test]
    new_subsets=[np.zeros((s.shape[0],h,w,c)) for s in subsets]

    for (subset,new_subset) in zip(subsets,new_subsets):
        for i in range(subset.shape[0]):
            img=subset[i, :]
            if c==1:
                #remove channel axis, resize, put again
                img=img[:,:,0]
                img= cv2.resize(img, dsize=(h, w))
                img = img[:, :, np.newaxis]
            else:
                #resize
                img = cv2.resize(img, dsize=(h, w))

            new_subset[i,:]=img

    dataset.x_train = new_subsets[0]
    dataset.x_test = new_subsets[1]

    if dataset.dataformat=="NCHW":
        dataset.x_train = np.transpose(dataset.x_train,axes=(0,3,1,2))
        dataset.x_test = np.transpose(dataset.x_test, axes=(0, 3, 1, 2))

def adapt_dataset(dataset:datasets.ClassificationDataset, dataset_template:str):
    dataset_template = datasets.get_classification(dataset_template)
    h,w,c= dataset_template.input_shape
    del dataset_template
    oh,ow,oc=dataset.input_shape

    # fix channels
    if c !=oc and oc==1:
        expand_channels(dataset,c)

    elif c != oc and c ==1:
        collapse_channels(dataset)
    else:
        raise ValueError(f"Cannot transform image with {oc} channels into image with {c} channels.")

    #fix size
    if h!=oh or w!=ow:
        resize(dataset,h,w,c)

    dataset.input_shape=(h,w,c)


from django.http import HttpResponse
from django.http import Http404
from django.contrib.auth.models import User
from django.shortcuts import render, redirect, get_object_or_404
from .forms import NewTopicForm
from .models import Board, Topic, Post
from django import template
from django.contrib.auth.models import Group
from django.core.mail import BadHeaderError, EmailMessage
from django.core.mail import send_mail
from django.conf import settings

def new_topic(request, pk):
    board = get_object_or_404(Board, pk=pk)
    user = User.objects.first()  # TODO: get the currently logged in user
    if request.method == 'POST':
        form = NewTopicForm(request.POST)
        if form.is_valid():
            topic = form.save(commit=False)
            topic.board = board
            topic.starter = user
            topic.save()
            post = Post.objects.create(
                message=form.cleaned_data.get('message'),
                topic=topic,
                created_by=user
            )
            return redirect('board_topics', pk=board.pk)  # TODO: redirect to the created topic page
    else:
        form = NewTopicForm()
    return render(request, 'new_topic.html', {'board': board, 'form': form})

def home(request):
    board = Board.objects.all()
    return render(request, 'home.html', {'board': board})

def dashboard(request):
    boards = Board.objects.all()
    return render(request, 'dashboard.html', {'boards': boards})

def forum(request):
    boards = Board.objects.all()
    return render(request, 'forum.html', {'boards': boards})

def thank(request):
    boards = Board.objects.all()
    return render(request, 'thank.html', {'boards': boards})

def contact(request):
    #check for POST requests on load.
    request.method == 'POST'
    subject = request.POST.get('subject')
    message = request.POST.get('message')
    email = request.POST.get('email')

    if subject and message and email:
        try:
            send_mail(subject= subject,message= message,from_email=settings.DEFAULT_FROM_EMAIL,recipient_list = [email],fail_silently  = True,)
        except BadHeaderError:
            return HttpResponse('Invalid header found.')
        return redirect('thank')

    else:
        #loading contacts.html if no requests
        return render(request, 'contact.html')

def board_topics(request, pk):
    board = get_object_or_404(Board, pk=pk)
    return render(request, 'topics.html', {'board': board})

def new_topic(request, pk):
    board = get_object_or_404(Board, pk=pk)
    user = User.objects.first()  # TODO: get the currently logged in user
    if request.method == 'POST':
        form = NewTopicForm(request.POST)
        if form.is_valid():
            topic = form.save(commit=False)
            topic.board = board
            topic.starter = user
            topic.save()
            post = Post.objects.create(
                message=form.cleaned_data.get('message'),
                topic=topic,
                created_by=user
            )
            return redirect('board_topics', pk=board.pk)  # TODO: redirect to the created topic page
    else:
        form = NewTopicForm()
    return render(request, 'new_topic.html', {'board': board, 'form': form})

def orderdone(request):
    boards = Board.objects.all()
    return render(request, 'orderdone.html', {'boards': boards})

# def order(request):
#     #check for POST requests on load.
#     request.method == 'POST'
#     user = User.objects.first()
#     paquet = request.POST.get('paquet')
#     quantity = request.POST.get('quantity')
#     other = request.POST.get('other')
#     check = request.POST.get('check')

#     if paquet and quantity and check:
#         return redirect('order')

#     else:

#         return render(request, 'home.html')


from model.ljp.Bert import LJPBert, LJPBert_test
# from model.ljp.CNN import SCMCNN
# from model.ljp.LoRA import CLLoRA
# from model.ljp.CNN import LJPCNN
# from model.ljp.LSTM import LSTM

model_list = {
    "LJPBert": LJPBert,
    "LJPBert_test": LJPBert_test
    # "SCMCNN": SCMCNN,
    # "CLLoRA": CLLoRA
    # "LJPCNN": LJPCNN,
    # "LJPLSTM": LSTM,
}

def get_model(model_name):
    if model_name in model_list.keys():
        return model_list[model_name]
    else:
        raise NotImplementedError


import json
import logging
import operator
import os
import webbrowser
from enum import Enum
from enum import unique
from typing import List
from typing import Optional

import click
import click_spinner
from taurus_datajob_api import DataJobExecution
from taurus_datajob_api import DataJobExecutionLogs
from taurus_datajob_api import DataJobExecutionRequest
from vdk.internal.control.configuration.defaults_config import load_default_team_name
from vdk.internal.control.exception.vdk_exception import VDKException
from vdk.internal.control.rest_lib.factory import ApiClientFactory
from vdk.internal.control.rest_lib.rest_client_errors import ApiClientErrorDecorator
from vdk.internal.control.utils import cli_utils
from vdk.internal.control.utils import output_printer
from vdk.internal.control.utils.cli_utils import get_or_prompt
from vdk.internal.control.utils.output_printer import OutputFormat

log = logging.getLogger(__name__)

@unique
class ExecuteOperation(Enum):
    """
    An enum used to store the types of deploy operations
    """

    START = "start"
    CANCEL = "cancel"
    WAIT = "wait"
    SHOW = "show"
    LIST = "list"
    LOGS = "logs"

class JobExecute:
    def __init__(self, rest_api_url: str):
        self.__execution_api = ApiClientFactory(rest_api_url).get_execution_api()

    @staticmethod
    def __model_executions(executions, output_format: OutputFormat) -> str:
        def transform_execution(e: DataJobExecution):
            d = e.to_dict()
            d["job_version"] = e.deployment.job_version
            if e.deployment.python_version:
                d["python_version"] = e.deployment.python_version
            del d["deployment"]
            return d

        executions = list(map(lambda e: transform_execution(e), executions))
        output_printer.create_printer(output_format).print_table(executions)

    @staticmethod
    def __validate_and_parse_args(arguments: str) -> str:
        try:
            if arguments:
                return json.loads(arguments)
            else:
                return {}
        except Exception as e:
            vdk_ex = VDKException(
                what="Failed to validate job arguments.",
                why=str(e),
                consequence="I will not make the API call.",
                countermeasure="Make sure provided --arguments is a valid JSON string.",
            )
            raise vdk_ex

    @ApiClientErrorDecorator()
    def start(
        self, name: str, team: str, output_format: OutputFormat, arguments: str
    ) -> None:
        execution_request = DataJobExecutionRequest(
            started_by=f"manual/vdk-control-cli",
            args=self.__validate_and_parse_args(arguments),
        )
        log.debug(f"Starting job with request {execution_request}")
        headers = self.__execution_api.data_job_execution_start_with_http_info(
            team_name=team,
            job_name=name,
            deployment_id="production",  # TODO
            data_job_execution_request=execution_request,
        ).headers
        log.debug(f"Received headers: {headers}")

        location = headers["Location"]
        execution_id = os.path.basename(location)
        if output_format == OutputFormat.TEXT.value:
            click.echo(
                f"Execution of Data Job {name} started. "
                f"See execution status using: \n\n"
                f"vdk execute --show --execution-id {execution_id} -n {name} -t {team}\n\n"
                f"See execution logs using: \n\n"
                f"vdk execute --logs --execution-id {execution_id} -n {name} -t {team}"
            )
        else:
            result = {
                "job_name": name,
                "team": team,
                "execution_id": execution_id,
            }
            output_printer.create_printer(output_format).print_dict(result)

    @ApiClientErrorDecorator()
    def cancel(self, name: str, team: str, execution_id: str) -> None:
        click.echo("Cancelling data job execution. Might take some time...")
        with click_spinner.spinner():
            response = self.__execution_api.data_job_execution_cancel(
                team_name=team, job_name=name, execution_id=execution_id
            )
            log.debug(f"Response: {response}")
        click.echo("Job cancelled successfully.")

    @ApiClientErrorDecorator()
    def show(
        self, name: str, team: str, execution_id: str, output_format: OutputFormat
    ) -> None:
        execution: DataJobExecution = self.__execution_api.data_job_execution_read(
            team_name=team, job_name=name, execution_id=execution_id
        )
        self.__model_executions([execution], output_format)

    @ApiClientErrorDecorator()
    def list(self, name: str, team: str, output_format: OutputFormat) -> None:
        executions: List[
            DataJobExecution
        ] = self.__execution_api.data_job_execution_list(team_name=team, job_name=name)
        self.__model_executions(executions, output_format)

    def __get_execution_to_log(
        self, name: str, team: str, execution_id: str
    ) -> Optional[DataJobExecution]:
        if not execution_id:
            executions: list[
                DataJobExecution
            ] = self.__execution_api.data_job_execution_list(
                team_name=team, job_name=name
            )
            if not executions:
                return None
            log.info(
                "No execution id has been passed as argument. "
                "We will print the logs of the last started execution."
            )
            executions.sort(key=operator.attrgetter("start_time"), reverse=True)
            execution = executions[0]
        else:
            execution: DataJobExecution = self.__execution_api.data_job_execution_read(
                team_name=team, job_name=name, execution_id=execution_id
            )
        return execution

    @ApiClientErrorDecorator()
    def logs(self, name: str, team: str, execution_id: str) -> None:
        execution = self.__get_execution_to_log(name, team, execution_id)
        if not execution:
            log.info("No executions found.")
            return

        log.debug(f"Get execution details: {execution.to_dict()}")
        log.info(f"Logs for execution with id {execution.id} ...")
        if execution.logs_url:
            log.info(f"Opening browser to check logs at:\n{execution.logs_url}")
            is_open = webbrowser.open(execution.logs_url)
            if not is_open:
                log.info(
                    "We failed to open the browser automatically .\n"
                    f"Navigate manually in your favourite browser to {execution.logs_url} to find the execution logs."
                )
        else:
            log.debug("Fetch logs from Execution Current Logs API: ")
            logs: DataJobExecutionLogs = self.__execution_api.data_job_logs_download(
                team_name=team, job_name=name, execution_id=execution.id
            )
            click.echo(logs.logs)

# Below is the definition of the CLI API/UX users will be interacting
# Above is the actual implementation of the operations

@click.command(
    help="Starts execution of a data job that is deployed or check status of job execution(s). (Beta)"
    """
Examples:

\b
# Start new remote execution of Data Job 'example-job'
# As an output it will print how to get starts and it's execution ID:
vdk execute --start -n example-job -t "Example Team"
\b
# Start a new remote execution of Data Job 'example-job' with extra arguments
# Arguments are passed to each step. Arguments must be a valid JSON object with key/value pairs.
vdk execute --start -n example-job -t "Example Team" --arguments '{"key1": "value1", "key2": "value2"}'

\b
# Check status of a currently executing Data Job:
vdk execute --show --execution-id example-job-1619094633811-cc49d  -n example-job -t "Example Team"

\b
# Cancel a currently executing Data Job:
vdk execute --cancel -t "Example Team" -n example-job --execution-id example-job-1619094633811-cc49d

\b
# List recent execution of a Data Job:
vdk execute --list -n example-job -t "Example Team"

\b
# We want to see the logs of the current execution that is running.
vdk execute --logs -n example-job -t "Example Team" --execution-id example-job-1619094633811-cc49d

""",
)
@click.option("-n", "--name", type=click.STRING, help="The job name.")
@click.option(
    "-t",
    "--team",
    type=click.STRING,
    default=load_default_team_name(),
    required=True,
    prompt="Job Team",
    help="The team name to which the job belong to.",
)
@click.option("-i", "--execution-id", type=click.STRING, help="The job execution ID.")
@click.option(
    "--start",
    "operation",
    flag_value=ExecuteOperation.START.value,
    help="Start execution of a Data Job. ",
)
@click.option(
    "--wait",
    "operation",
    hidden=True,
    flag_value=ExecuteOperation.WAIT.value,
    help="Wait for current job execution (if any) to finish "
    "(if specified execution id wait for execution with given id to finish)."
    "Require --execution-id to be provided. "
    "Should be printed when using vdk execute --start",
)
@click.option(
    "--cancel",
    "operation",
    flag_value=ExecuteOperation.CANCEL.value,
    help="Cancels a running or submitted Data Job execution. Requires --execution-id to be provided. "
    "Should be printed when using vdk execute --start",
)
@click.option(
    "--list",
    "operation",
    flag_value=ExecuteOperation.LIST.value,
    help="List recent and/or current executions of the Data Job. ",
)
@click.option(
    "--show",
    "operation",
    flag_value=ExecuteOperation.SHOW.value,
    help="Shows details Data Job Executions. Requires --execution-id to be provided. "
    "Should be printed when using vdk execute --start",
)
@click.option(
    "--logs",
    "operation",
    flag_value=ExecuteOperation.LOGS.value,
    help="Shows logs about Data Job Execution. It will either provide link to central logging system or"
    " print the logs locally."
    "If --execution-id is omitted, it will fetch logs from more recently started job execution."
    " --execution-id should be provided to get logs from specific job execution."
    "Execution id is printed when using vdk execute --start. "
    "You can also see execution id with vdk execute --list operation.",
)
@cli_utils.rest_api_url_option()
@cli_utils.output_option()
@click.option(
    "--arguments",
    type=click.STRING,
    required=False,
    help="Pass arguments when starting a data job. "
    "Those arguments will be passed to each step. "
    "Must be in valid JSON format",
)
@cli_utils.check_required_parameters
def execute(
    name, team, execution_id, operation, rest_api_url, output, arguments
) -> None:
    cmd = JobExecute(rest_api_url)
    if operation == ExecuteOperation.START.value:
        name = get_or_prompt("Job Name", name)
        cmd.start(name, team, output, arguments)
    elif operation == ExecuteOperation.SHOW.value:
        name = get_or_prompt("Job Name", name)
        execution_id = get_or_prompt("Job Execution ID", execution_id)
        cmd.show(name, team, execution_id, output)
    elif operation == ExecuteOperation.LIST.value:
        name = get_or_prompt("Job Name", name)
        cmd.list(name, team, output)
    elif operation == ExecuteOperation.CANCEL.value:
        name = get_or_prompt("Job Name", name)
        team = get_or_prompt("Job Team", team)
        execution_id = get_or_prompt("Job Execution ID", execution_id)
        cmd.cancel(name, team, execution_id)
    elif operation == ExecuteOperation.LOGS.value:
        name = get_or_prompt("Job Name", name)
        team = get_or_prompt("Job Team", team)
        cmd.logs(name, team, execution_id)
    elif operation == ExecuteOperation.WAIT.value:
        name = get_or_prompt("Job Name", name)
        # cmd.wait(name, team)
        click.echo("Operation wait not implemented")
    else:
        click.echo(
            f"No execute operation specified. "
            f"Please specify one of: {['--' + str(op.value) for op in ExecuteOperation]}"
        )


# -*- coding: utf-8 -*-
"""
Created on Sat Jun 13 18:13:21 2020

@author: FFernandes
"""

# Libbraries importing section
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import pandas as pd
import json
import dash_table
from dash_table.Format import Format, Group, Scheme, Symbol
import datetime as dt
import numpy as np

'''
Source of Population Info: https://www.ibge.gov.br/estatisticas/sociais/populacao/9103-estimativas-de-populacao.html?edicao=25272&t=downloads
Source of Maps: https://www.ibge.gov.br/geociencias/organizacao-do-territorio/15774-malhas.html?=&t=downloads
Source of COVID data: https://brasil.io/dataset/covid19/caso?format=csv
'''

#Reading data section

## Reading last update info
readfile = open('last_update.txt', 'r')
last_update = readfile.readlines()
last_update_message = 'Dados atualizados em: ' + last_update[0]
readfile.close()

## Reading maps  #Those maps were prepared before construction of these program
with open('Maps/brasil_1.json', encoding='utf-8') as geofile1:
    jdataBra_states = json.load(geofile1)

with open('Maps/brasil_2.json', encoding='utf-8') as geofile2:
    jdataBra_rgintermed = json.load(geofile2)

with open('Maps/brasil_3.json', encoding='utf-8') as geofile3:
    jdataBra_rgimed = json.load(geofile3)

with open('Maps/brasil_4.json', encoding='utf-8') as geofile4:
    jdataBra_municipios = json.load(geofile4)

## Reading info from the hard drive previously downloaded and manipulated file

estados = pd.read_csv('Tables/uf.csv', encoding = 'latin1', dtype = 'object')
rgint = pd.read_csv('Tables/rgintermed.csv', encoding = 'latin1', dtype = 'object')
rgi = pd.read_csv('Tables/rgi.csv', encoding = 'latin1', dtype = 'object')
cidades = pd.read_csv('Tables/municipios.csv', encoding = 'latin1', dtype = 'object')
cidades['localidade'] = cidades['nome_mun'] + ' / ' + cidades['sigla']

tdf = pd.read_csv('Tables/tdf.csv',
                  parse_dates = ['data'],
                  dtype = {'total_casos': 'int64',
                           'total_obitos': 'int64',
                           'novos_casos': 'int64',
                           'novos_obitos': 'int64',
                           'cod_rgi': 'object',
                           'cod_rgint': 'object',
                           'cod_uf': 'object'},
                           encoding = 'latin1',
                           compression = 'gzip')
tdf = tdf.drop(axis = 1, labels = ['Unnamed: 0'])

tdf_rgi = pd.read_csv('Tables/tdf_rgi.csv',
                  parse_dates = ['data'],
                  dtype = {'total_casos': 'int64',
                           'total_obitos': 'int64',
                           'novos_casos': 'int64',
                           'novos_obitos': 'int64',
                           'cod_rgi': 'object',
                           'cod_rgint': 'object',
                           'cod_uf': 'object'},
                           encoding = 'latin1',
                           compression = 'gzip')
tdf_rgi = tdf_rgi.drop(axis = 1, labels = ['Unnamed: 0'])

tdf_rgint = pd.read_csv('Tables/tdf_rgint.csv',
                  parse_dates = ['data'],
                  dtype = {'total_casos': 'int64',
                           'total_obitos': 'int64',
                           'novos_casos': 'int64',
                           'novos_obitos': 'int64',
                           'cod_rgint': 'object',
                           'cod_uf': 'object'},
                           encoding = 'latin1',
                           compression = 'gzip')
tdf_rgint = tdf_rgint.drop(axis = 1, labels = ['Unnamed: 0'])

tdf_estados = pd.read_csv('Tables/tdf_estados.csv',
                  parse_dates = ['data'],
                  dtype = {'total_casos': 'int64',
                           'total_obitos': 'int64',
                           'novos_casos': 'int64',
                           'novos_obitos': 'int64'},
                           encoding = 'latin1',
                           compression = 'gzip')
tdf_estados = tdf_estados.drop(axis = 1, labels = ['Unnamed: 0'])

### Keeping only the updated info
df_hoje = tdf[tdf['atualizado']].copy()

df_estados_hoje = tdf_estados[tdf_estados['data'] == tdf_estados['data'].max()].copy()
df_rgint_hoje = tdf_rgint[tdf_rgint['data'] == tdf_rgint['data'].max()].copy()
df_rgi_hoje = tdf_rgi[tdf_rgi['data'] == tdf_rgi['data'].max()].copy()

'''
NOTA:
Os dados de município carregam apenas as informações mais atuais de cada município.
Os dados agrupados de regiões e estados consideram a soma dos dados mais atuais de cada município que os compõem.
Isso significa que possivelmente os dados dessas regiões estarão um pouco desatualizadas.
'''

##### including a column to make identification easier
df_hoje['name'] = df_hoje['nome_mun'] + ' / ' + df_hoje['sigla']
df_rgi_hoje['name'] = df_rgi_hoje['nome_rgi'] + ' / ' + df_rgi_hoje['sigla']
df_rgint_hoje['name'] = df_rgint_hoje['nome_rgint'] + ' / ' + df_rgint_hoje['sigla']
df_estados_hoje['name'] = df_estados_hoje['estado']

### Summing up total numbers
total_cases = df_estados_hoje['total_casos'].sum()
total_deaths = df_estados_hoje['total_obitos'].sum()

### Creating the locations for each level of geo organization
locations_states = df_estados_hoje['sigla']
locations_rgintermed = df_rgint_hoje['cod_rgint']
locations_rgi =df_rgi_hoje['cod_rgi']
locations_mun = df_hoje['codigo_ibge']

### Creating options for the filters
opcoes_estados = estados.sort_values(by = 'estado')[['estado', 'sigla']].rename(columns = {'estado': 'label', 'sigla': 'value'}).to_dict(orient = 'records')

#Creating the core of the dashboard
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

server = app.server #Disable it when in test / development mode. Enable it to Production mode
app.layout = html.Div([
        #dcc.Store(id="store_data"), #later understand why this is useful

        html.Div(html.H1('Painel COVID-19 nas localidades brasileiras')),

        html.Div(html.Label(last_update_message)),

        html.Div([
                html.Div(
                    [html.Label('Total de casos confirmados no Brasil'),
                     html.H1(total_cases)
                    ]),

                html.Div(
                    [html.Label('Total de óbitos confirmados no Brasil'),
                     html.H1(total_deaths)
                    ]),
                    ],
            id="header",
            className="row flex-display",
            style={"margin-bottom": "25px"}), #closing Div with overall scores

        html.Div([
            html.Div(html.H3('Configure o mapa:')),
            html.Div([html.Div('Nível de organização do território:'),
                    dcc.Dropdown(id = 'dropdown_geo_level',
                                   options = [
                                           {'label': 'Estados', 'value': 'states'},
                                           {'label': 'Regiões Geográficas Intermediárias', 'value': 'rgintermed'},
                                           {'label': 'Regiões Geográficas Imediatas', 'value': 'rgi'},
                                           {'label': 'Municípios', 'value': 'cities'}
                                           ],
                                   value = 'states',
                                   multi = False)]),

            html.Div([html.Div('Variável de interesse:'),
                    dcc.Dropdown(id = 'dropdown_info',
                                   options = [
                                           {'label': 'A - Total de casos', 'value': 'total_casos'},
                                           {'label': 'B - Total de óbitos', 'value': 'total_obitos'},
                                           {'label': 'C - Novos casos', 'value': 'novos_casos'},
                                           {'label': 'D - Novos óbitos', 'value': 'novos_obitos'},
                                           {'label': 'E - Média móvel dos novos casos - 7 dias', 'value': 'mm_7dias_novos_casos'},
                                           {'label': 'F - Média móvel dos novos óbitos - 7 dias', 'value': 'mm_7dias_novos_obitos'},
                                           {'label': 'G - Total de casos por 100.000 habitantes', 'value': 'total_casos%'},
                                           {'label': 'H - Total de óbitos por 100.000 habitantes', 'value': 'total_obitos%'},
                                           {'label': 'I - Novos casos por 100.000 habitantes', 'value': 'novos_casos%'},
                                           {'label': 'J - Novos óbitos por 100.000 habitantes', 'value': 'novos_obitos%'},
                                           {'label': 'K - Média móvel dos novos casos - 7 dias - por 100.000 habitantes', 'value': 'mm_7dias_novos_casos%'},
                                           {'label': 'L - Média móvel dos novos óbitos - 7 dias - por 100.000 habitantes', 'value': 'mm_7dias_novos_obitos%'},
                                           {'label': 'M - Variação percentual da média móvel dos novos casos - 7 dias', 'value': 'var_casos_7dias'},
                                           {'label': 'N - Variação percentual da média móvel dos novos óbitos - 7 dias', 'value': 'var_obitos_7dias'}],
                                   value = 'total_casos',
                                   multi = False)]), ### closing Div-Div-Dropdown

            html.Div(html.H3('E aplique filtros:')),
            html.Div([
                    html.Div('Estado:'),
                    dcc.Dropdown(id = 'dropdown_state',
                                   options = opcoes_estados,
                                   value = 'all',
                                   searchable = True,
                                   clearable = True,
                                   placeholder = 'Todos os Estados',
                                   multi = True),

                    html.Div('Região Geográfica Intermediária:'),
                    dcc.Dropdown(id = 'dropdown_rgint',
                                   value = 'all',
                                   searchable = True,
                                   clearable = True,
                                   placeholder = 'Todas as Regiões Geográficas Intermediárias',
                                   multi = True),

                    html.Div('Região Geográfica Imediata:'),
                    dcc.Dropdown(id = 'dropdown_rgi',
                                   value = 'all',
                                   searchable = True,
                                   clearable = True,
                                   placeholder = 'Todas as Regiões Geográficas Imediatas',
                                   multi = True),

                    html.Div('Município:'),
                    dcc.Dropdown(id = 'dropdown_city',
                                   value = 'all',
                                   searchable = True,
                                   clearable = True,
                                   placeholder = 'Todos os Municípios',
                                   multi = True)

                                 ]),

        ]),  ### closing configuring and filtering section.

        html.Div(dcc.Graph(id = 'main_map')), ### closing Div-Graph - Map

        html.Div(dcc.Graph(id = 'main_lineplot')), ### closing Div-Graph - Line plot

        html.Div([html.H6('Legenda:'),
                  html.Div('A - Total de casos'),
                  html.Div('B - Total de óbitos'),
                  html.Div('C - Novos casos'),
                  html.Div('D - Novos óbitos'),
                  html.Div('E - Média móvel dos novos casos - 7 dias'),
                  html.Div('F - Média móvel dos novos óbitos - 7 dias'),
                  html.Div('G - Total de casos por 100.000 habitantes'),
                  html.Div('H - Total de óbitos por 100.000 habitantes'),
                  html.Div('I - Novos casos por 100.000 habitantes'),
                  html.Div('J - Novos óbitos por 100.000 habitantes'),
                  html.Div('K - Média móvel dos novos casos - 7 dias - por 100.000 habitantes'),
                  html.Div('L - Média móvel dos novos óbitos - 7 dias - por 100.000 habitantes'),
                  html.Div('M - Variação percentual da média móvel dos novos casos - 7 dias'),
                  html.Div('N - Variação percentual da média móvel dos novos óbitos - 7 dias')
                                    ]),

        html.Div(dash_table.DataTable(id='table',
                                      export_format = 'csv',
                                      style_cell={'textAlign': 'left'},
                                      style_data_conditional=[
                                                {
                                                'if': {'row_index': 'odd'},
                                                'backgroundColor': 'rgb(248, 248, 248)'
                                                },
                                                {
                                                    'if': {'column_id': 'pop'},
                                                    'textAlign': 'right'
                                                },
                                                {
                                                    'if': {'column_id': 'total_casos'},
                                                    'textAlign': 'right'
                                                },
                                                {
                                                    'if': {'column_id': 'total_obitos'},
                                                    'textAlign': 'right'
                                                },
                                                {
                                                    'if': {'column_id': 'novos_casos'},
                                                    'textAlign': 'right'
                                                },
                                                {
                                                    'if': {'column_id': 'novos_obitos'},
                                                    'textAlign': 'right'
                                                },
                                                {
                                                    'if': {'column_id': 'mm_7dias_novos_casos'},
                                                    'textAlign': 'right'
                                                },
                                                 {
                                                    'if': {'column_id': 'mm_7dias_novos_obitos'},
                                                    'textAlign': 'right'
                                                },
                                                {
                                                    'if': {'column_id': 'total_casos%'},
                                                    'textAlign': 'right'
                                                },
                                                {
                                                    'if': {'column_id': 'total_obitos%'},
                                                    'textAlign': 'right'
                                                },
                                                {
                                                    'if': {'column_id': 'novos_casos%'},
                                                    'textAlign': 'right'
                                                },
                                                {
                                                    'if': {'column_id': 'novos_obitos%'},
                                                    'textAlign': 'right'
                                                },
                                                {
                                                    'if': {'column_id': 'mm_7dias_novos_casos%'},
                                                    'textAlign': 'right'
                                                },
                                                {
                                                    'if': {'column_id': 'mm_7dias_novos_obitos%'},
                                                    'textAlign': 'right'
                                                }
                                              ],
                                      style_header= [
                                              {
                                              'backgroundColor': 'rgb(230, 230, 230)',
                                              'fontWeight': 'bold'
                                              },
                                              {
                                               'if': {'column_id': 'pop'},
                                               'textAlign': 'right'
                                                }
                                              ]
                                      )),
        html.Div(dcc.Markdown(
                            '''
                              Os dados reportados neste painel foram obtidos na plataforma Brasil.IO, repositório de dados públicos disponibilizados em formato acessível. Conheça e apoie esta iniciativa.

                              https://brasil.io/home/

                              Os mapas foram obtidos no site do IBGE em formato shapefile e simplificados usando a biblioteca Geopandas.
                              '''
                              ) #closing Markdown
        ) ### closing Div-Markdown
]) #closing main html.Div

# Callbacks - here is where the magic happens
@app.callback([Output('main_map', 'figure'),
               Output('dropdown_rgint', 'options'),
               Output('dropdown_rgint', 'disabled'),
               Output('dropdown_rgi', 'options'),
               Output('dropdown_rgi', 'disabled'),
               Output('dropdown_city', 'options'),
               Output('dropdown_city', 'disabled'),
               Output('table', 'data'),
               Output('table', 'columns'),
               Output('main_lineplot', 'figure')],
              [Input('dropdown_info', 'value'),
               Input('dropdown_geo_level', 'value'),
               Input('dropdown_state', 'value'),
               Input('dropdown_rgint', 'value'),
               Input('dropdown_rgi', 'value'),
               Input('dropdown_city', 'value')])
def update_figure(info, geo_level, filtro_estados, filtro_rgint, filtro_rgi, filtro_cidades):
     ## Managing filters:
    if filtro_estados == 'all':
        estados_selecionados = estados['sigla']
    elif filtro_estados == []:
        estados_selecionados = estados['sigla']
    elif filtro_estados == '':
        estados_selecionados = estados['sigla']
    else:
        estados_selecionados = filtro_estados

    if filtro_rgint == 'all':
        rgint_selecionadas = rgint['cod_rgint']
    elif filtro_rgint == []:
        rgint_selecionadas = rgint['cod_rgint']
    elif filtro_rgint == '':
        rgint_selecionadas = rgint['cod_rgint']
    else:
        rgint_selecionadas = filtro_rgint

    if filtro_rgi == 'all':
        rgi_selecionadas = rgi['cod_rgi']
    elif filtro_rgi == []:
        rgi_selecionadas = rgi['cod_rgi']
    elif filtro_rgi == '':
        rgi_selecionadas = rgi['cod_rgi']
    else:
        rgi_selecionadas = filtro_rgi

    if filtro_cidades == 'all':
        cidades_selecionadas = cidades['CD_GEOCODI']
    elif filtro_cidades == []:
        cidades_selecionadas = cidades['CD_GEOCODI']
    elif filtro_cidades == '':
        cidades_selecionadas = cidades['CD_GEOCODI']
    else:
        cidades_selecionadas = filtro_cidades

    ### according to the geo_level, we'll choose the right DataFrame
    if geo_level == 'states':
        df = df_estados_hoje
        locations = locations_states
        geojson = jdataBra_states
        featureidkey = 'properties.SIGLA_UF'
        key = 'sigla'
        time_df = tdf_estados
        rgint_disabled = True
        rgi_disabled = True
        city_disabled = True
        ## Applying filters
        filtered_df = df[df['sigla'].isin(estados_selecionados)]

    elif geo_level == 'rgintermed':
        df = df_rgint_hoje
        locations = locations_rgintermed
        geojson = jdataBra_rgintermed
        featureidkey='properties.CD_RGINT'
        key = 'cod_rgint'
        time_df = tdf_rgint
        rgint_disabled = False
        rgi_disabled = True
        city_disabled = True
        ## Applying filters
        filtered_df = df[(df['sigla'].isin(estados_selecionados)) & (df['cod_rgint'].isin(rgint_selecionadas))]

    elif geo_level == 'rgi':
        df = df_rgi_hoje
        locations = locations_rgi
        geojson = jdataBra_rgimed
        featureidkey = featureidkey='properties.CD_RGI'
        key = 'cod_rgi'
        time_df = tdf_rgi
        rgint_disabled = False
        rgi_disabled = False
        city_disabled = True
        ## Applying filters
        filtered_df = df[(df['sigla'].isin(estados_selecionados)) &
                         (df['cod_rgint'].isin(rgint_selecionadas)) &
                         (df['cod_rgi'].isin(rgi_selecionadas))]

    else: #else select cities
        df = df_hoje
        locations = locations_mun
        geojson = jdataBra_municipios
        featureidkey = featureidkey='properties.CD_MUN'
        key = 'codigo_ibge'
        time_df = tdf
        rgint_disabled = False
        rgi_disabled = False
        city_disabled = False
        ## Applying filters
        filtered_df = df[(df['sigla'].isin(estados_selecionados)) &
                         (df['cod_rgint'].isin(rgint_selecionadas)) &
                         (df['cod_rgi'].isin(rgi_selecionadas)) &
                         (df['codigo_ibge'].isin(cidades_selecionadas))]

    ## arranging the dataframe to be shown
    blank_df = pd.DataFrame(index = locations)
    df_to_show = blank_df.merge(filtered_df, left_index = True, right_on = key, how = 'left').fillna(0)

    if info in ['var_casos_7dias', 'var_obitos_7dias']:
        color_sequence = 'Picnic'
        zauto = True

    else:
        color_sequence = 'RdPu'
        zauto = False

    ## Creating the map figure
    figure_map = {'data': [go.Choroplethmapbox(geojson = geojson,
                                           locations = locations,
                                           z = df_to_show[info],
                                           featureidkey = featureidkey,
                                           text = df_to_show['name'],
                                           zauto = zauto,
                                           zmid = 0,
                                           colorscale = color_sequence
                                           )],
                  'layout': go.Layout(title = 'Mapa da COVID-19 no Brasil',
                                      hovermode = 'closest',
                                      width = 1500,
                                      height = 1000,
                                      mapbox={'zoom': 3,
                                              'style': 'carto-positron',
                                              'center': {"lat": -15, "lon": -60}})
                                   } #closing figure

    table_data=filtered_df.sort_values(by = info, ascending = False).to_dict('records')

    formatlocale_ptBR_int = Format(
            scheme = Scheme.fixed,
            precision = 0,
            group = Group.yes,
            groups = 3,
            group_delimiter = '.',
            decimal_delimiter = ',',
            symbol = Symbol.no,
            symbol_prefix = u'R$')

    formatlocale_ptBR_float = Format(
            scheme = Scheme.fixed,
            precision = 1,
            group = Group.yes,
            groups = 3,
            group_delimiter = '.',
            decimal_delimiter = ',',
            symbol = Symbol.no,
            symbol_prefix = u'R$')

    formatlocale_ptBR_percent = Format(
            scheme = Scheme.fixed,
            precision = 1,
            group = Group.yes,
            groups = 3,
            group_delimiter = '.',
            decimal_delimiter = ',',
            symbol = Symbol.no,
            symbol_prefix = u'R$')

    ### Organizing the format of the table
    if geo_level == 'states':
        columns=[{'id': 'estado', 'name': 'Estado', 'type': 'text'},
                 {'id': 'sigla', 'name': 'Sigla', 'type': 'text'},
                 {'id': 'pop', 'name': 'População', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'total_casos', 'name': 'A', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'total_obitos', 'name': 'B', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'novos_casos', 'name': 'C', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'novos_obitos', 'name': 'D', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'mm_7dias_novos_casos', 'name': 'E', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'mm_7dias_novos_obitos', 'name': 'F', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'total_casos%', 'name': 'G', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'total_obitos%', 'name': 'H', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'novos_casos%', 'name': 'I', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'novos_obitos%', 'name': 'J', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'mm_7dias_novos_casos%', 'name': 'K', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'mm_7dias_novos_obitos%', 'name': 'L', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'var_casos_7dias', 'name': 'M', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'var_obitos_7dias', 'name': 'N', 'type': 'numeric', 'format': formatlocale_ptBR_float}
                 ]
    elif geo_level == 'rgintermed':
        columns=[{'id': 'nome_rgint', 'name': 'Região Intermediária', 'type': 'text'},
                 {'id': 'estado', 'name': 'Estado', 'type': 'text'},
                 {'id': 'pop', 'name': 'População', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'total_casos', 'name': 'A', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'total_obitos', 'name': 'B', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'novos_casos', 'name': 'C', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'novos_obitos', 'name': 'D', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'mm_7dias_novos_casos', 'name': 'E', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'mm_7dias_novos_obitos', 'name': 'F', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'total_casos%', 'name': 'G', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'total_obitos%', 'name': 'H', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'novos_casos%', 'name': 'I', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'novos_obitos%', 'name': 'J', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'mm_7dias_novos_casos%', 'name': 'K', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'mm_7dias_novos_obitos%', 'name': 'L', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'var_casos_7dias', 'name': 'M', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'var_obitos_7dias', 'name': 'N', 'type': 'numeric', 'format': formatlocale_ptBR_float}
                 ]
    elif geo_level == 'rgi':
        columns=[{'id': 'nome_rgi', 'name': 'Região Imediata', 'type': 'text'},
                 {'id': 'nome_rgint', 'name': 'Região Intermediária', 'type': 'text'},
                 {'id': 'estado', 'name': 'Estado', 'type': 'text'},
                 {'id': 'pop', 'name': 'População', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'total_casos', 'name': 'A', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'total_obitos', 'name': 'B', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'novos_casos', 'name': 'C', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'novos_obitos', 'name': 'D', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'mm_7dias_novos_casos', 'name': 'E', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'mm_7dias_novos_obitos', 'name': 'F', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'total_casos%', 'name': 'G', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'total_obitos%', 'name': 'H', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'novos_casos%', 'name': 'I', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'novos_obitos%', 'name': 'J', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'mm_7dias_novos_casos%', 'name': 'K', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'mm_7dias_novos_obitos%', 'name': 'L', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'var_casos_7dias', 'name': 'M', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'var_obitos_7dias', 'name': 'N', 'type': 'numeric', 'format': formatlocale_ptBR_float}
                 ]
    else: #municipios
        columns=[{'id': 'nome_mun', 'name': 'Município', 'type': 'text'},
                 {'id': 'nome_rgi', 'name': 'Região Imediata', 'type': 'text'},
                 {'id': 'nome_rgint', 'name': 'Região Intermediária', 'type': 'text'},
                 {'id': 'sigla', 'name': 'Estado', 'type': 'text'},
                 {'id': 'pop', 'name': 'População', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'total_casos', 'name': 'A', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'total_obitos', 'name': 'B', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'novos_casos', 'name': 'C', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'novos_obitos', 'name': 'D', 'type': 'numeric', 'format': formatlocale_ptBR_int},
                 {'id': 'mm_7dias_novos_casos', 'name': 'E', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'mm_7dias_novos_obitos', 'name': 'F', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'total_casos%', 'name': 'G', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'total_obitos%', 'name': 'H', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'novos_casos%', 'name': 'I', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'novos_obitos%', 'name': 'J', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'mm_7dias_novos_casos%', 'name': 'K', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'mm_7dias_novos_obitos%', 'name': 'L', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'var_casos_7dias', 'name': 'M', 'type': 'numeric', 'format': formatlocale_ptBR_float},
                 {'id': 'var_obitos_7dias', 'name': 'N', 'type': 'numeric', 'format': formatlocale_ptBR_float}
                 ]

    ## creating the line plot
    top_places = filtered_df.sort_values(by = info, ascending = False).head(5)
    data = []
    for i, place in top_places.iterrows():
        trace = go.Scatter(x = time_df[time_df[key] == place[key]]['data'],
                           y = time_df[time_df[key] == place[key]][info],
                           mode = 'lines+markers',
                           name = place['name'])
        data.append(trace)

    figure_line = go.Figure(data=data,
                       layout=go.Layout(title = 'Curva de evolução da COVID nas localidades selecionadas'))

    figure_line = figure_line.update_xaxes(rangeslider_visible=True,
                                 range = ['2020-02-25', time_df['data'].max()],
                                 rangeselector=dict(buttons=list([
                                         dict(count=7, label="7d", step="day", stepmode="backward"),
                                         dict(count=14, label="14d", step="day", stepmode="backward"),
                                         dict(count=1, label="1m", step="month", stepmode="backward"),
                                         dict(count=6, label="6m", step="month", stepmode="backward"),
                                         dict(count=1, label="YTD", step="year", stepmode="todate"),
                                         dict(step="all")])))

    figure_line.update_layout(
            autosize=True,
            #width=1500,
            #height=1200,
            margin=dict(
                l=50,
                r=50,
                b=100,
                t=100,
                pad=4),
                    paper_bgcolor="LightSteelBlue")

    ## Managing dropdown options
    ####opcoes_estados = estados.sort_values(by = 'estado')[['estado', 'sigla']].rename(columns = {'estado': 'label', 'sigla': 'value'}).to_dict(orient = 'records')
    rgint_options = rgint[rgint['sigla'].isin(estados_selecionados)].sort_values(by = ['estado', 'nome_rgint'])[['nome_rgint', 'cod_rgint']].rename(columns = {'nome_rgint': 'label', 'cod_rgint': 'value'}).to_dict(orient = 'records')

    rgi_options = rgi[(rgi['sigla'].isin(estados_selecionados)) &
                      (rgi['cod_rgint'].isin(rgint_selecionadas))].sort_values(by = ['estado', 'nome_rgi'])[['nome_rgi', 'cod_rgi']].rename(columns = {'nome_rgi': 'label', 'cod_rgi': 'value'}).to_dict(orient = 'records')

    city_options = cidades[(cidades['sigla'].isin(estados_selecionados)) &
                           (cidades['cod_rgint'].isin(rgint_selecionadas)) &
                           (cidades['cod_rgi'].isin(rgi_selecionadas))].sort_values(by = ['localidade'])[['localidade', 'CD_GEOCODI']].rename(columns = {'localidade': 'label', 'CD_GEOCODI': 'value'}).to_dict(orient = 'records')

    return figure_map, rgint_options, rgint_disabled, rgi_options, rgi_disabled, city_options, city_disabled, table_data, columns, figure_line

if __name__ == '__main__':
    app.run_server(debug = True)


from collections import deque
L = int(input())
originalL = []
t = 0
size = 2
cnt = 0

for i in range(L):
    temp = list(map(int,input().split()))
    originalL.append(temp)

dR = [0,0,-1,1]
dC = [1,-1,0,0]

def bfs(nowr,nowc):
    isfind = False
    q = deque([(nowr,nowc)])
    visited = [[-1 for _ in range(L)] for _ in range(L)]
    visited[nowr][nowc]=0
    candi = []
    dist=-1
    while q :
        r,c = q.popleft()
        print(r,c,isfind,dist)
        if isfind ==True :
            if visited[r][c]==dist:
                # dist가 바뀌는 순간!
                candi =sorted(candi)
                return candi
        # candi list sort, 하나 뽑기
        for i in range(4):
            nextr = r+dR[i]
            nextc = c+dC[i]

            if (0<=nextr<L) and (0<=nextc<L) and visited[nextr][nextc]==-1 and originalL[nextr][nextc] <= size:
                if originalL[nextr][nextc] ==size or originalL[nextr][nextc]==0 :
                    q.append((nextr,nextc))
                    visited[nextr][nextc]= visited[nowr][nowc]+1
                else :
                    dist = visited[nowr][nowc]+1
                    isfind = True
                    candi.append((nextr,nextc))

for i in range(L):
    for j in range(L) :
        if originalL[i][j]==9:
            print(bfs(i,j))


# -*- coding: utf-8 -*-
"""浙商银行网点 CZBORGANIZE  请求 URL_ 获取数据"""
import re
from database._mongodb import MongoClient
from branch_scripts import GenericScript
from tools.req_for_api import req_for_something
from tools.web_api_of_baidu import get_lat_lng, get_area

def data_shuffle(data, province_list, city_list, area_list):
    data_list = list()
    for city in city_list:
        if city["NAME_"] == "县":
            city_list.remove(city)

    prov_c = ""
    prov_n = ""
    city_c = ""
    city_n = ""
    area_c = ""
    area_n = ""

    # 省市级信息
    if "北京" in data["CITY_NAME_"]:
        prov_n = "北京市"
        prov_c = "1100"
        city_n = "北京市"
        city_c = "110100"
    elif "天津" in data["CITY_NAME_"]:
        prov_n = "天津市"
        prov_c = "1200"
        city_n = "天津市"
        city_c = "120100"
    elif "上海" in data["CITY_NAME_"]:
        prov_n = "上海市"
        prov_c = "3100"
        city_n = "上海市"
        city_c = "310100"
    elif "重庆" in data["CITY_NAME_"]:
        prov_n = "重庆市"
        prov_c = "5000"
        city_n = "重庆市"
        city_c = "500100"
    else:
        for city in city_list:
            if city["NAME_"][:-1] in data["CITY_NAME_"]:
                city_n = city["NAME_"]
                city_c = city["CODE_"]
                prov_c = city["PARENT_"]
                break
        if prov_c:
            for prov in province_list:
                if prov["CODE_"] == prov_c:
                    prov_n = prov["NAME_"]
                    break

    response = req_for_something(data["URL_"])

    a = re.sub(r"[^\w|,]+", "", response.content.decode("utf-8"))

    b = a.split("|")

    for each in b:
        re_data = dict()
        message = each.split(",")
        if len(message) == 1:
            continue
        # city_n = message[0]
        # city_c = message[1]
        name = message[2]
        addr_ = message[3]
        tel = message[4]
        business_time = message[5] + message[6]
        # lng = message[8]
        # lat = message[9]

        # # 区县级清洗
        # for area in area_list:
        #     if area["PARENT_"] == city_c:
        #         if area["NAME_"] in addr_:
        #             area_n = area["NAME_"]
        #             area_c = area["CODE_"]
        #         elif area["NAME_"][:-1] in addr_:
        #             area_n = area["NAME_"]
        #             area_c = area["CODE_"]
        #         elif area["NAME_"][:4] in addr_:
        #             area_n = area["NAME_"]
        #             area_c = area["CODE_"]
        #         elif area["NAME_"][:3] in addr_:
        #             area_n = area["NAME_"]
        #             area_c = area["CODE_"]
        #         elif area["NAME_"][:2] in addr_:
        #             area_n = area["NAME_"]
        #             area_c = area["CODE_"]

        # 地址清洗
        if prov_n in addr_:
            pass
        elif prov_n[:-1] in addr_[:len(prov_n)]:
            addr_ = addr_[:len(prov_n)].replace(prov_n[:-1], prov_n) + addr_[len(prov_n):]
        elif prov_n[:4] in addr_[:len(prov_n)]:
            addr_ = addr_[:len(prov_n)].replace(prov_n[:4], prov_n) + addr_[len(prov_n):]
        elif prov_n[:3] in addr_[:len(prov_n)]:
            addr_ = addr_[:len(prov_n)].replace(prov_n[:3], prov_n) + addr_[len(prov_n):]
        elif prov_n[:2] in addr_[:len(prov_n)]:
            addr_ = addr_[:len(prov_n)].replace(prov_n[:2], prov_n) + addr_[len(prov_n):]
        else:
            addr_ = prov_n + addr_

        if city_n in addr_[:len(prov_n) + len(city_n)]:
            addr_ = addr_
        elif city_n[:-1] in addr_[:len(prov_n) + len(city_n)]:
            addr_ = addr_[:len(prov_n) + len(city_n)].replace(
                city_n[:-1], city_n) + addr_[len(prov_n) + len(city_n):]
        elif city_n[:4] in addr_[:len(prov_n) + len(city_n)]:
            addr_ = addr_[:len(prov_n) + len(city_n)].replace(
                city_n[:4], city_n) + addr_[len(prov_n) + len(city_n):]
        elif city_n[:3] in addr_[:len(prov_n) + len(city_n)]:
            addr_ = addr_[:len(prov_n) + len(city_n)].replace(
                city_n[:3], city_n) + addr_[len(prov_n) + len(city_n):]
        elif city_n[:2] in addr_[:len(prov_n) + len(city_n)]:
            addr_ = addr_[:len(prov_n) + len(city_n)].replace(
                city_n[:2], city_n) + addr_[len(prov_n) + len(city_n):]
        else:
            addr_ = addr_[:len(prov_n)] + city_n + addr_[len(prov_n):]

        # "C"
        re_data["BANK_CODE_"] = "CZB"
        re_data["BANK_NAME_"] = data["ENTITY_NAME_"][:-3]
        re_data["SPIDER_TIME_"] = data["DATETIME_"]
        # re_data["AREA_CODE_"] = area_c
        # re_data["AREA_NAME_"] = area_n
        # re_data["UNIT_CODE_"] = "CZB" + "_" + city_c

        # "F"
        re_data["ADDR_"] = addr_
        re_data["PROVINCE_NAME_"] = prov_n
        re_data["PROVINCE_CODE_"] = prov_c
        re_data["CITY_CODE_"] = city_c
        re_data["CITY_NAME_"] = city_n
        # re_data["LAT_"] = lat
        # re_data["LNG_"] = lng
        re_data["NAME_"] = name
        # re_data["PROVINCE_CODE_"] = prov_c
        # re_data["PROVINCE_NAME_"] = prov_n

        result = get_lat_lng(address=re_data["ADDR_"])
        try:
            re_data["LAT_"] = str(result["result"]["location"]["lat"])
            re_data["LNG_"] = str(result["result"]["location"]["lng"])
        except KeyError:
            re_data["LAT_"] = ""
            re_data["LNG_"] = ""
        else:
            dis_result = get_area(",".join([re_data["LAT_"], re_data["LNG_"]]))
            try:
                re_data["AREA_NAME_"] = dis_result["result"]["addressComponent"]["district"]
            except KeyError:
                re_data["AREA_NAME_"] = ""
            try:
                re_data["AREA_CODE_"] = dis_result["result"]["addressComponent"]["adcode"]
            except KeyError:
                re_data["AREA_CODE_"] = ""
            else:
                re_data["CITY_CODE_"] = re_data["AREA_CODE_"][:4] + "00"
                re_data["PROVINCE_CODE_"] = re_data["AREA_CODE_"][:2] + "00"
                for city in city_list:
                    if city["CODE_"] == re_data["CITY_CODE_"]:
                        re_data["CITY_NAME_"] = city["NAME_"]
                        break
                for prov in province_list:
                    if prov["CODE_"] == re_data["PROVINCE_CODE_"]:
                        re_data["PROVINCE_NAME_"] = prov["NAME_"]
                        break
        re_data["UNIT_CODE_"] = "CZB" + "_" + re_data.get("CITY_CODE_", "")

        re_data["ENTITY_CODE_"] = data["ENTITY_CODE_"]
        re_data["ENTITY_NAME_"] = data["ENTITY_NAME_"]
        re_data["URL_"] = data["URL_"]
        re_data["TEL_"] = tel
        re_data["BUSINESS_HOURS_"] = business_time
        if "SOURCE_TYPE_NAME_" in data:
            re_data["SOURCE_TYPE_NAME_"] = data["SOURCE_TYPE_NAME_"]
        re_data["TYPE_NAME_"] = "支行"
        re_data["TYPE_"] = "ZH"

        data_list.append(re_data)

    return data_list

if __name__ == '__main__':
    main_mongo = MongoClient(entity_code="CZBORGANIZE", mongo_collection="WD_TY")
    sc = GenericScript
    # Mysql connection
    sc.mysql_client, sc.mysql_connection = sc.mysql_connect()
    province_list, city_list, area_list, dir_area_list, bank_list = sc.data_from_mysql()
    data_list = main_mongo.main()
    for data in data_list:
        re_data = data_shuffle(data, province_list, city_list, area_list)
        print(re_data)


# template
n, r = map(int, input().split())
result = [0 for _ in range(5)]
check = [0 for _ in range(5)]

def getResult(x):
    # x번째 for문을 돌려야함.
    if x >= r:
        for i in result:
            if i != 0:
                print(i, end='')
        print()
    else:
        for i in range(n):
            if check[i] == False:
                print(check)
                alpha = ord('a') + i
                result[x] = chr(alpha)
                check[i] = True
                getResult(x + 1)
                print(check)
                check[i] = False

getResult(0)


import os
import tensorflow as tf
import numpy as np
import argparse

SIGNAL_LENGTH = 2048
N_MELS = 80

class Denoiser:
    def __init__(self, model_path = 'denoising_model') -> None:
        self.model = tf.keras.models.load_model(model_path)

    def process(self, input_data):
        assert len(input_data.shape) == 2
        assert input_data.shape[1] == N_MELS
        if input_data.shape[0] > SIGNAL_LENGTH:
            input_arr = input_data[0: SIGNAL_LENGTH, :]
        elif input_data.shape[0] < SIGNAL_LENGTH:
            input_arr = np.zeros(shape=(SIGNAL_LENGTH, N_MELS))
            input_arr[0:input_data.shape[0], :] = input_data
        else:
            input_arr = input_data
        input_arr = np.expand_dims(input_arr, axis = 0)
        prediction = self.model(input_arr)[0].numpy()
        if input_data.shape[0] < input_arr.shape[1]:
            prediction = prediction[0: input_data.shape[0], :]
        return prediction

class Classificator:
    def __init__(self, model_path = 'classification') -> None:
        self.model = tf.keras.models.load_model(model_path)

    def process(self, input_data):
        assert len(input_data.shape) == 2
        assert input_data.shape[1] == N_MELS
        if input_data.shape[0] > SIGNAL_LENGTH:
            input_arr = input_data[0: SIGNAL_LENGTH, :]
        elif input_data.shape[0] < SIGNAL_LENGTH:
            input_arr = np.zeros(shape=(SIGNAL_LENGTH, N_MELS))
            input_arr[0:input_data.shape[0], :] = input_data
        else:
            input_arr = input_data
        input_arr = np.expand_dims(input_arr, axis = 0)
        prediction_arr = self.model(input_arr)[0]
        prediction = np.argmax(prediction_arr)
        if prediction == 0:
            pred_class = 'clear'
        else:
            pred_class = 'noise'
        confidence = prediction_arr[prediction]
        return pred_class, confidence

def get_args():
    parser = argparse.ArgumentParser(description='Description of your program')
    parser.add_argument('-m', '--mel_path', help='Path to .npy file with mel-spectrogram', required=True)
    parser.add_argument('-t', '--task', help = "Name of task: c - classification, d- denoising", default='d')
    parser.add_argument('-r', '--result_path', help = "Path to save result mel-spectrogram after denoising", default='.')
    args = parser.parse_args()
    return args

def load_data(path):
    try:
        data = np.load(path)
    except Exception as e:
        print(f"Can't load file {path}, error: {e}")
    return data

def save_data(data, data_path, path):
    fname = data_path.split(os.sep)[-1]
    fname_new = 'result_' + fname
    new_path = os.path.join(path, fname_new)
    try:
        with open(new_path, 'wb') as f:
            np.save(f, data)
        print(f"Data saved to {new_path}")
    except Exception as e:
        print(f"Can't save data to {path}, error: {e}")

if __name__ == "__main__":
    args = get_args()
    data = load_data(args.mel_path)
    if args.task == 'd':
        denoiser = Denoiser(model_path='denoising_model')
        denoized_data = denoiser.process(data)
        save_data(denoized_data, args.mel_path, args.result_path)
    if args.task == 'c':
        classificator = Classificator(model_path='classification')
        classification_results = classificator.process(data)
        print(f"Class: {classification_results[0]}, Confidence: {classification_results[1].numpy()[0]}")


from math import *
import sys

def fuel(mass):
    need = floor(mass/3) - 2

    if need <= 0:
        return 0
    else:
        return need + fuel(need)

s = sum(fuel(int(i)) for i in sys.stdin.read().split())

print(s)


# Best Example for DP and Memoization

s = "bbbab"
n = len(s)

dp = [[0] * n for _ in range(n)]

## Examine the pattern
for i in range(n-1, -1, -1):
    dp[i][i] = 1
    for j in range(i+1, n):
        if s[i] == s[j]:
            dp[i][j] = dp[i+1][j-1] +2
        else:
            dp[i][j] = max(dp[i+1][j], dp[i][j-1]) # type: ignore
print(dp[0][n-1])


from PyQt5.Qt import *

# qto
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.setWindowTitle("布局管理器的学习")
        self.resize(500, 500)

        self.setup_ui()

    def setup_ui(self):
        # 创建3个子控件
        label1 = QLabel("标签1")
        label1.setStyleSheet("background-color: cyan;")

        label2 = QLabel("标签2")
        label2.setStyleSheet("background-color: yellow;")

        label3 = QLabel("标签3")
        label3.setStyleSheet("background-color: red;")

        label4 = QLabel("标签4")
        label4.setStyleSheet("background-color: orange;")

        # 1. 创建一个布局管理器对象
        layout = QBoxLayout(QBoxLayout.BottomToTop)

        # 2. 直接把布局管理器对象设置成需要布局的父控件
        self.setLayout(layout)

        # 3. 把需要布局的子控件添加到布局管理器中
        layout.addWidget(label1)
        layout.addWidget(label2)
        layout.addWidget(label3)

        layout.setSpacing(60)

        # print(layout.contentsMargins().left())  # 查看左边的外边距
        # print(layout.contentsMargins().top())  # 查看上边的外边距
        layout.setContentsMargins(20, 40, 60, 80)

        layout.replaceWidget(label2, label4)

        label2.destroyed.connect(lambda : print("标签2被释放"))

        label2.hide()
        label2.setParent(None)
        print(label2.parent())

if __name__ == '__main__':

    import sys

    app = QApplication(sys.argv)

    window = Window()
    window.show()

    sys.exit(app.exec_())


from re import I

n, m = map(int, input().split())
num = list(map(int, input().split()))
num.sort()
check = [False] * (n+1)
a = [0] * m

def go(index, n, m):
  if index == m:
    for i in range(m):
      print(num[a[i]-1], end=' ')
    print()
    return

  for i in range(1, n+1):
    if check[i] == False:
      a[index] = i
      check[i] = True
      go(index+1, n, m)
      check[i] = False

go(0, n, m)


"""Copy Artefact.source into track, store, series & repo

Revision ID: 38807948d269
Revises: cb121ad343dd
Create Date: 2023-10-25 12:33:03.206702+00:00

"""
import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "38807948d269"
down_revision = "cb121ad343dd"
branch_labels = None
depends_on = None

def upgrade() -> None:
    artefact_table = sa.table(
        "artefact",
        sa.column("id", sa.Integer()),
        sa.column("source", sa.JSON()),
        sa.column("track", sa.String()),
        sa.column("store", sa.String()),
        sa.column("series", sa.String()),
        sa.column("repo", sa.String()),
    )

    conn = op.get_bind()
    get_artefacts_id_source = sa.select(artefact_table.c.id, artefact_table.c.source)
    for id, source in conn.execute(get_artefacts_id_source):
        conn.execute(
            sa.update(artefact_table)
            .where(artefact_table.c.id == id)
            .values(
                track=source.get("track"),
                store=source.get("store"),
                series=source.get("series"),
                repo=source.get("repo"),
            )
        )

def downgrade() -> None:
    artefact_table = sa.table(
        "artefact",
        sa.column("track", sa.String()),
        sa.column("store", sa.String()),
        sa.column("series", sa.String()),
        sa.column("repo", sa.String()),
    )

    conn = op.get_bind()
    conn.execute(
        sa.update(artefact_table).values(
            track=None,
            store=None,
            series=None,
            repo=None,
        )
    )


from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    (r"^admin/", include(admin.site.urls)),
    (r"^accounts/", include("userena.urls")),

    (r"^lists/", include("lists.urls", namespace="lists")),
    (r"", include("generic.urls", namespace="generic")),
)

from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()


"""
ソートして頭の要素が0ならそのまま0出力
前から掛けて行って10^18桁をオーバーしたら-1出力
"""

N = int(input())

A = input().split()
result = 1

A.sort()
fl = True

if int(A[0]) == 0:
    print(0)
else:
    for i in A:
        result *= int(i)
        if result > 10**18:
            fl = False
            break
    if fl:
        print(result)
    else:
        print(-1)


# https://www.acmicpc.net/problem/14501
import sys
sys.stdin = open('input.txt','r')
input = sys.stdin.readline

def dfs(day, money):
    global answer
    if day <= N: answer = max(answer, money)
    if day >= N: return
    dfs(day+1, money)
    dfs(day+arr[day][0], money+arr[day][1])

N = int(input())
arr = [list(map(int, input().split())) for _ in range(N)]
answer = 0
dfs(0, 0)
print(answer)