from typing import Dict,List,Tuple,Union,NamedTuple,Optional
from typing_extensions import Literal
import json,re
import daa_luigi
from common_functions import ExecutionFolder,raise_exception,as_inputs
from copy import copy
import pandas as pd
from pathlib import Path
import sissopp
from sissopp.py_interface import get_fs_solver
from sklearn.cluster import KMeans
from sklearn.metrics import pairwise_distances_argmin_min
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

Repr2Members = Dict[str,List[str]]
ExecutionType = Literal["singletask_on_representatives", "multitask_on_all"]

class PrimarySpaceParams(NamedTuple):
    data_file:str
    property_key:str = 'lat'
    leave_out_inds: List[int] = []
    leave_out_frac: Optional[float] = 0.25
    def deterministic(self) -> "PrimarySpaceParams":
        testset_chosenby_index = (len(self.leave_out_inds) > 0)
        testset_chosen_randomly = not testset_chosenby_index and (0 <= self.leave_out_frac < 1)
        whole_set = pd.read_csv(self.data_file, index_col='material')
        work_set = whole_set.loc[set(whole_set.index) - set(self.leave_out_inds), :] if testset_chosenby_index \
            else whole_set if self.leave_out_frac == 0.0 \
            else train_test_split(whole_set, test_size=self.leave_out_frac)[0] if testset_chosen_randomly \
            else raise_exception(
            "leave_out_inds must be list of length > 0 and/or leave_out_frac must be float between 0 and 1")
        leave_out_inds = [list(whole_set.index).index(mat)
                          for mat in list(set(whole_set.index) - set(work_set.index))]
        return PrimarySpaceParams(str(self.data_file),self.property_key,leave_out_inds,None)

class DerivedSpaceParams(NamedTuple):
    data_file: str
    property_key: str = 'lat'
    leave_out_inds: List[int] = []
    leave_out_frac: float = 0.25
    task_key:str=None
    opset:List[Literal['add', 'sub', 'mult', 'div', 'sq', 'cb', 'cbrt', 'sqrt']] = ['add', 'sub', 'mult', 'div', 'sq', 'cb', 'cbrt', 'sqrt']
    param_opset:List[Literal['add', 'sub', 'mult', 'div', 'sq', 'cb', 'cbrt', 'sqrt']] = ['add', 'sub', 'mult', 'div', 'sq', 'cb', 'cbrt', 'sqrt']
    calc_type:Literal["regression", "log regression", "classification"] = "regression"
    desc_dim:int = 3
    n_sis_select:int = 100
    max_rung:int = 2
    n_residual:int = 1
    n_models_store: int = 1
    n_rung_store:int =1
    n_rung_generate:int = 0
    min_abs_feat_val: float = 1e-05
    max_abs_feat_val:float = 100000000.0
    fix_intercept:bool = False
    max_feat_cross_correlation:float = 1.0
    nlopt_seed:int = 13
    global_param_opt:bool = False
    reparam_residual:bool = True
    def deterministic(self) -> "DerivedSpaceParams":
        testset_chosenby_index = (len(self.leave_out_inds) > 0)
        testset_chosen_randomly = not testset_chosenby_index and (0 <= self.leave_out_frac < 1)
        whole_set = pd.read_csv(self.data_file, index_col='material')
        work_set = whole_set.loc[set(whole_set.index) - set(self.leave_out_inds), :] if testset_chosenby_index \
            else whole_set if self.leave_out_frac == 0.0 \
            else train_test_split(whole_set, test_size=self.leave_out_frac)[0] if testset_chosen_randomly \
            else raise_exception(
            "leave_out_inds must be list of length > 0 and/or leave_out_frac must be float between 0 and 1")
        leave_out_inds = [list(whole_set.index).index(mat)
                          for mat in list(set(whole_set.index) - set(work_set.index))]
        deterministic_repr = self._asdict()
        deterministic_repr.update({"data_file":str(self.data_file),
            "leave_out_inds":leave_out_inds, "leave_out_frac":None})
        return DerivedSpaceParams(**deterministic_repr)
    def get_primary_space_params(self)->PrimarySpaceParams:
        return PrimarySpaceParams(**{k:v for k,v in self._asdict().items()
                                     if k in ['data_file','property_key','leave_out_inds','leave_out_frac']})

data_csvpath = "/home/oehlers/Documents/masterthesis/02-data/csvs/cubic_perovskites.csv"

class MyKmeans():
    def __init__(self, space_params: Union[PrimarySpaceParams,DerivedSpaceParams],
                 n_clusters: int,
                 save_proto2members_at: Union[Path,str] = None,
                 interm_results_path: Union[Path,str] = None):
        """
        In the following, the Work Set will be defined as the dataset that remains after subtracting the Test Set.
        Cluster extraction is based on Work Set only; cluster assignment of Test Set materials is conducted afterwards.
        This function returns dictionary of Work Set cluster centers pointing to list of Work and Test Set cluster members
        space_params (short: space_params): dictionary returned by either
                     PrimarySpaceParams or DerivedSpaceParams class,
                     determines in which space kmeans will be applied
                     (either the space spanned by standardized primary features without target property,
                     or the space spanned by the derived features times respective fitting coefficients of sisso
                     - in the latter case, all execution parameters for sisso are defined by the
                     DerivedSpaceParams class)
        n_clusters: number of clusters
        save_proto2members_at: path to future file location
        interm_results_path: if set to path or str, folder it points to is created if non-existent and used
                                       if set to None, temp folder is created in data_file folder and deleted after exe
        """
        self.space_params = space_params
        self.n_clusters = n_clusters
        self.save_proto2members_at = save_proto2members_at
        self.interm_results_path = interm_results_path
        self.proto2members = self._get_kmeans_center2members()

    def _train_and_test_streched_derived_feature_dfs(self, sisso, exe_folder: ExecutionFolder) -> Tuple[
        pd.DataFrame, pd.DataFrame]:
        """"sisso must be SISSOregressor as returned by 'feat_space,sisso = get_fs_solver
        (for some reason this cannot be indicated via typing)
        """
        # Extract derived space from SISSO results by reading train and testfile:
        # (no python binding was found for directly extracting derived space)

        streched_derived_feature_space = {}
        for train_or_test in ['train', 'test']:
            filepath = exe_folder.path.joinpath(train_or_test + "file")
            derivedspacepath = exe_folder.path.joinpath(train_or_test + "_derived_space.csv")
            sisso.models[-1][0].to_file(str(filepath), train_or_test == train_or_test)
            with open(filepath, "r") as file:
                with open(derivedspacepath, 'w') as derivedspace:
                    lines = file.readlines()
                    writeit = 0
                    for line in lines:
                        if line[:len("# Sample ID")] == "# Sample ID":
                            line = line.replace("# Sample ID", "material")
                            writeit = 1
                        if writeit == 1:
                            derivedspace.write(line)
            target_and_derived_features = pd.read_csv(derivedspacepath, sep=',', index_col=0)
            derived_features = target_and_derived_features.iloc[:, 2:]
            strech_coefs = sisso.models[-1][0].coefs[0][:-1]
            streched_derived_features = derived_features.multiply(strech_coefs).values
            streched_derived_feature_space[train_or_test] = streched_derived_features

        return streched_derived_feature_space['train'], streched_derived_feature_space['test']

    def _get_kmeans_center2members(self) -> Repr2Members:

        space_params = self.space_params

        testset_chosenby_index = ( len(space_params.leave_out_inds)>0 and space_params.leave_out_frac is None )
        clustering_in_primary_space = isinstance(space_params,PrimarySpaceParams)
        clustering_in_derived_space = isinstance(space_params,DerivedSpaceParams)

        whole_set = pd.read_csv(space_params.data_file, index_col='material').astype(float)
        test_set_materials = [list(whole_set.index)[ind] for ind in space_params.leave_out_inds]
        test_set = whole_set.loc[test_set_materials, :]
        work_set = whole_set.loc[set(whole_set.index) - set(test_set_materials), :]

        if testset_chosenby_index and clustering_in_primary_space:
            # Get standardized primary space without target:
            target_property_col = [col for col in whole_set.columns
                                   if re.match(r"{} (...)".format(space_params.property_key), col)][0]
            work_primary_features = work_set.drop(target_property_col, axis=1).values
            test_primary_features = test_set.drop(target_property_col, axis=1).values
            standardized_work_primary_features = StandardScaler().fit_transform(work_primary_features)
            standardized_test_primary_features = StandardScaler().fit_transform(test_primary_features)

            # Use standardized primary space for Kmeans clustering:
            kmeans_results = KMeans(self.n_clusters).fit(standardized_work_primary_features)
            virtual_cluster_centers = kmeans_results.cluster_centers_
            actual_cluster_center_inds = pairwise_distances_argmin_min(virtual_cluster_centers,
                                                                       standardized_work_primary_features)[0]
            test_labels = kmeans_results.predict(standardized_test_primary_features)

        elif testset_chosenby_index and clustering_in_derived_space:
            assert space_params.task_key is None, """This code applies to clustering in space derived by Single-Task SISSO only,
            for clustering in Multi-Task-SISSO space code has to be checked for necessary adaptations"""

            # Create execution folder:
            exe_folder = ExecutionFolder(permanent_location=self.interm_results_path,
                                         refers_to_data_file=space_params.data_file)

            # Execute SISSO:
            space_params_dict = space_params._asdict()
            inp = as_inputs(exe_folder.path.joinpath("derived_space_constr_params"), **space_params_dict)
            print(inp)
            inputs = sissopp.Inputs(inp)
            feature_space, sisso = get_fs_solver(inputs)
            sisso.fit()

            # Extract streched derived space:
            work_streched_derived_features, test_streched_derived_features \
                = self._train_and_test_streched_derived_feature_dfs(sisso, exe_folder)

            # Use streched derived space for Kmeans clustering:
            kmeans_results = KMeans(self.n_clusters).fit(work_streched_derived_features)
            virtual_cluster_centers = kmeans_results.cluster_centers_
            actual_cluster_center_inds = pairwise_distances_argmin_min(virtual_cluster_centers,
                                                                       work_streched_derived_features)[0]
            test_labels = kmeans_results.predict(test_streched_derived_features)

            # Remove execution folder if set to be temporal:
            exe_folder.delete_if_not_permanent()

        else:
            raise Exception("""space_construction_parameters must be either of PrimarySpaceParams or DerivedSpaceParams
            class""")

        # Determine cluster center and member material names:
        actual_cluster_center_materials = [list(work_set.index)[ind] for ind in actual_cluster_center_inds]

        work_set_with_tasks = copy(work_set).assign(task=kmeans_results.labels_)
        test_set_with_tasks = copy(test_set).assign(task=test_labels)
        whole_set_with_tasks = work_set_with_tasks.append(test_set_with_tasks)

        center2members = {}
        for task in set(whole_set_with_tasks['task']):
            members = list(whole_set_with_tasks[whole_set_with_tasks['task'] == task].index)
            center = list(set(actual_cluster_center_materials).intersection(set(members)))[0]
            center2members[center] = members
        if self.save_proto2members_at is not None:
            with open(self.save_proto2members_at, 'w') as jsonfile:
                json.dump(center2members, jsonfile)
        return center2members

class MyDeepAA():
    def __init__(self,space_params:Union[PrimarySpaceParams,DerivedSpaceParams],
                 at_loss_factor:float, target_loss_factor:float, recon_loss_factor:float, kl_loss_factor:float,
                 latent_dim:int,n_epochs:int,arche2members_path:Union[str,Path]=None):
        self.space_params = space_params
        self.at_loss_factor = at_loss_factor
        self.target_loss_factor = target_loss_factor
        self.recon_loss_factor = recon_loss_factor
        self.kl_loss_factor = kl_loss_factor
        self.latent_dim = latent_dim
        self.n_epochs = n_epochs
        self.arche2members_path = arche2members_path

        self.nn = daa_luigi.build_network(latent_dim=latent_dim,epochs=n_epochs)
        As, arche2members = self._extract_weightdfs_and_arche2members()
        self.weight_dfs = As
        self.arche2members = arche2members

    def _get_stan_work_and_test_df(self) -> Tuple[pd.DataFrame, pd.DataFrame]:
        whole_set = pd.read_csv(self.space_params.data_file, index_col='material').astype(float)
        test_set_materials = [list(whole_set.index)[ind] for ind in self.space_params.leave_out_inds]
        test_set = whole_set.loc[test_set_materials, :]
        work_set = whole_set.loc[set(whole_set.index) - set(test_set_materials), :]
        # Standardize iot weigh reconstruction of each feature equally important
        work_mean, work_std = work_set.mean(axis=0), work_set.std(axis=0)
        stan_work_set = (work_set - work_mean) / work_std
        stan_test_set = (test_set - work_mean) / work_std
        return stan_work_set, stan_test_set

    def _get_nn_data_input(self) -> Dict:
        standardized_work, standardized_test = self._get_stan_work_and_test_df()
        target = [col for col in standardized_work if self.space_params.property_key in col][0]
        nn_data_input = {'train_feat': standardized_work.drop([target], axis=1).values,
                         'train_targets': standardized_work[target].values,
                         'test_feat': standardized_test.drop([target], axis=1).values,
                         'test_targets': standardized_test[target].values}
        return nn_data_input

    def _extract_weightdfs_and_arche2members(self) -> Tuple[Dict[str,pd.DataFrame],Repr2Members]:
        """
        nn_results: result yielded by nn
        space_params: yielded by primary_space_construction_parameters function
        arche2members_path: path to future file location
        """
        nn_data_input = self._get_nn_data_input()
        nn_results = self.nn(nn_data_input, self.at_loss_factor, self.target_loss_factor,
                             self.recon_loss_factor, self.kl_loss_factor)
        stan_work_set, stan_test_set = self._get_stan_work_and_test_df()
        As = {'train': pd.DataFrame(nn_results[('train', 'latent space', 'As')], index=stan_work_set.index),
              'test': pd.DataFrame(nn_results[('test', 'latent space', 'As')], index=stan_test_set.index)}

        # collect actual arche and resp. clusters IFF virtual arche really the one closest to actual arche candidate
        def mat_closest_to(virtualarche: int, train_or_test: str = 'train') -> str:
            return As[train_or_test].loc[:, virtualarche].idxmax()

        def virtualarche_clostest_to(mat: str, train_or_test: str = 'train') -> int:
            return As[train_or_test].loc[mat, :].idxmax()

        actualarches = [mat_closest_to(virtualarche, 'train') for virtualarche in As['train'].columns
                        if virtualarche_clostest_to(mat_closest_to(virtualarche, 'train'), 'train') == virtualarche]
        assert len(actualarches) == len(As['train'].columns), \
            "For at least one virtual archetype, no material could be found which would be assigned to it, when all " \
            "materials are assigned to closest virtual archetype in latent space; latent space cannot be used; " \
            "NN has to be retrained "
        for train_or_test in ['train', 'test']:
            As[train_or_test].columns = actualarches
        arche2members = {arche: [] for arche in As['train'].columns}
        for train_or_test in ['train', 'test']:
            for mat in As[train_or_test].index:
                arche = As[train_or_test].loc[mat, :].idxmax()
                arche2members[arche] += [mat]
        with open(self.arche2members_path, 'w') as jsonfile:
            json.dump(arche2members, jsonfile)
        return As, arche2members

class MySisso():
    def __init__(self,execution_parameters:DerivedSpaceParams,
              clusters:Repr2Members,
              singletask_on_representatives_or_multitask_on_all:ExecutionType = "singletask_on_representatives",
              store_intermediate_results_in:Path = None):
        self.execution_parameters = execution_parameters
        self.clusters = clusters
        self.singletask_on_representatives_or_multitask_on_all = singletask_on_representatives_or_multitask_on_all
        self.intermediate_results_path = store_intermediate_results_in
        self.results = self._get_sisso()

    def _get_sisso(self):
        """returns SISSOregressor, see https://sissopp_developers.gitlab.io/sissopp/quick_start/code_ref.html#input-files
        sisso_execution_parameters (short: sisso_params): must be output of function sisso_execution_parameters
            or derived_space_construction_parameters
        clusters: must be dict yielded by get_kmeans_center2members_dict function
        singletask_on_representatives_or_multitask_on_all:
                        if set to 'singletask_on_representatives', single-task sisso is trained on representatives, and
                                             tested on materials determined by sisso_execution_parameters['leave_out_inds']
                        if set to 'multitask_on_all', multi-task sisso is trained on all Work Set materials, an tested
                                             on all Test Set materials as determined by
                                             sisso_execution_parameters['leave_out_inds'],
                                             where tasks are determined by :clusters: arg
        store_intermediate_results_in: if set to None, temporal folder will be created and deleted after execution
        """
        sisso_params = self.execution_parameters._asdict()

        # Create execution folder:
        exe_folder = ExecutionFolder(permanent_location=self.intermediate_results_path,
                                     refers_to_data_file=sisso_params['data_file'])

        # Prepare csv and json file for sisso execution:
        whole_set = pd.read_csv(sisso_params['data_file'], sep=',', index_col='material')
        test_materials = [list(whole_set.index)[ind] for ind in sisso_params['leave_out_inds']]

        whole_data_filepath = Path(sisso_params['data_file'])
        training_and_test_data_filepath = exe_folder.path.joinpath("training_and_test_" + whole_data_filepath.name)

        if self.singletask_on_representatives_or_multitask_on_all == 'singletask_on_representatives':
            training_materials = list(self.clusters.keys())
            training_and_test_set = whole_set.loc[training_materials + test_materials, :]

        elif self.singletask_on_representatives_or_multitask_on_all == 'multitask_on_all':
            mat2center = {mat: center for center in self.clusters.keys()
                          for mat in self.clusters[center]}
            tasks = [str(mat2center[mat_in_sequence]) for mat_in_sequence in whole_set.index]
            training_and_test_set = whole_set.assign(task=tasks)
            training_and_test_set = training_and_test_set[['task'] +
                                                          [col for col in list(whole_set.columns) if col != 'task']]
            sisso_params['task_key'] = 'task'

        else:
            raise_exception(""":singletask_on_centers_or_multitask_on_all: must be set to 'singletask_on_centers'
            or 'multitask_on_all'""")

        training_and_test_set.to_csv(training_and_test_data_filepath, sep=',')
        sisso_params['data_file'] = training_and_test_data_filepath
        sisso_params['leave_out_inds'] = [list(training_and_test_set.index).index(mat) for mat in test_materials]

        # Execute SISSO and extract results:
        inputspath = as_inputs(exe_folder.path.joinpath("sisso_exe"), **sisso_params)
        inputs = sissopp.Inputs(inputspath)
        feature_space, sisso = get_fs_solver(inputs)
        sisso.fit()

        # Remove execution folder if set to be temporal:
        exe_folder.delete_if_not_permanent()

        return sisso


import os
import signal
import time

def sigint_handler(signum, frame):
    print('Has presionado Ctrl+C. Saliendo...')
    os._exit(0)

signal.signal(signal.SIGINT, sigint_handler)

def child_process():
    print('El proceso hijo ha comenzado.')
    while True:
        print('El proceso hijo está en ejecución.')
        time.sleep(2)

if __name__ == '__main__':

    print('El proceso padre ha comenzado.')

    pid = os.fork()

    if pid == 0:
        child_process()
    else:
        time.sleep(10)
        print('El proceso padre envía la señal SIGKILL al proceso hijo.')
        os.kill(pid, signal.SIGKILL)


import numpy as np
from matplotlib import pyplot as plt
import matplotlib.colors
import random as rand

class Board:
    def __init__(self,dim,targetTerrain): #set default values for a board
        self.board = np.zeros((dim,dim), dtype= float)
        self.target = (rand.randint(0,dim-1),rand.randint(0,dim-1))
        self.dim = dim
        self.populateTerrain()
        self.newTarget(targetTerrain)

    def populateTerrain(self):
        terrain = [.1, .3, .7, .9]
        for i in range(self.dim):
            for j in range(self.dim):
                self.board[i,j] = rand.choices(terrain,weights = (.2, .3, .3, .2))[0]

    def newTarget(self,terrain):
        while True:
            x,y = (rand.randint(0,self.dim-1),rand.randint(0,self.dim-1))
            if self.board[x,y] == terrain:
                self.target = (x,y)
                break

    def printBoard(self):
        #print(self.board)
        plt.figure(figsize = (10,10))
        plt.pcolor(self.board,edgecolors = "black", cmap = 'Set3', linewidths = 1)
        for (j,i),label in np.ndenumerate(self.board): #consider using a mapping for label to mine/flag
            plt.text(i,j,label,ha='left',va='bottom')
        plt.tight_layout()
        plt.show() #block=False
        #plt.pause(.2)
        #plt.close()


"""
Aprenda a manipular datas
Realizar conversao de texto para data e vice-versa
realizar soma e subtracao em datas
- Como recuperar a data atual(DATE)
- Como trabalhar com a data, alterando sua formatação
- Como gerar um horário(TIME)
- Retornar data e hora atual(DATETIME)
- Alterar formação do DATETIME
- Realizar soma e subtracao de datas com TIMEDELTA
"""

from datetime import date, time, datetime, timedelta

def trabalhando_date():
    data_atual = date.today()
    print(data_atual.strftime('%d/%m/%Y')) # Dia - número, m - Mês, - Y - Ano com 4 digitos # strftime - vira string
    print(data_atual.strftime('%A %B %Y')) # Dia - nome, m - Mês, Y - Ano com 4 digitos # strftime - vira string

def trabalhando_time():
    time_atual = time(hour=15, minute=10, second=30)
    print(time_atual)
    print(time_atual.strftime('%H:%M:%S')) # H - Hora, M - Minuto, S - segundo # strftime - vira string

def trabalhando_datetime():
    data_atual = datetime.now()
    print(data_atual)
    print(data_atual.strftime('%d/%m/%Y - %H:%M:%S')) # d - Dia número, m - Mês numero, Y - Ano numero # strftime - vira string
    print(data_atual.strftime('%c')) # c - Dia da semana nome, Mês nome, Dia numero, Hora:minuto:segundos, ano 4 digitos  # strftime - vira string
    tupla = ('Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sabado', 'Domingo')
    print(tupla[data_atual.weekday()])
    data_string = '01/01/2019 12:20:25'
    data_convertida = datetime.strptime(data_string, '%d/%m/%Y %H:%M:%S')
    print(data_convertida)
    nova_data = data_convertida - timedelta(days=365)
    print(nova_data)

if __name__ == '__main__':
    trabalhando_date()
    trabalhando_time()
    trabalhando_datetime()


class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        reverse_prices = prices[::-1]
        profit = 0
        sell_price = 0
        for price in reverse_prices:
            if price > sell_price:
                sell_price = price
            if price <= sell_price:
                profit_new = sell_price - price
                if profit_new > profit:
                    profit = profit_new
        return profit


import os
from music21 import humdrum
from music21 import converter
import chant21

class MultipleSpinesException(Exception):
    """An exception raised when encountering multiple spines
    while expecting only 1"""
    pass

def extract_phrases_from_spine(spine):
    """Enxtract the phrases as music21 streams from kern
    Phrases in a humdrum file are delimited by curly brackets.
    All events that do not occur between an opening and closing bracket
    (i.e., are not in a phrase) are ignored.

    Parameters
    ----------
    spine : music21.humdrum.spineParser.KernSpine
        A humdrum spine with the melody

    Returns
    -------
    list
        A list of phrases, each represented as a music21.stream.Stream
    """
    phrases = []
    in_phrase = False
    cur_phrase = humdrum.spineParser.KernSpine()
    for event in spine:
        is_phrase_start = event.contents.startswith('{')
        is_phrase_end = event.contents.endswith('}')

        if is_phrase_start:
            in_phrase = True

        if in_phrase:
            cur_phrase.append(event)

        if is_phrase_end and in_phrase:
            phrases.append(cur_phrase)
            cur_phrase = humdrum.spineParser.KernSpine()
            in_phrase = False

    # Parse spines and return streams
    for phrase in phrases: phrase.parse()
    streams = [phrase.stream.flat for phrase in phrases]
    return streams

def extract_phrases_from_kern_file(filename: str) -> list:
    """Extract all phrases from a kern file.
    Phrases are returned as flattened music21 streams

    Parameters
    ----------
    filename : string
        filename of the file

    Returns
    -------
    list
        List of phrases as music21.stream.Stream objects

    Raises
    ------
    MultipleSpinesException
        Whenever the file contains multiple spines
    """
    song = humdrum.parseFile(filename)
    if len(song.spineCollection.spines) > 1:
        raise MultipleSpinesException
    spine = song.spineCollection.spines[0]
    return extract_phrases_from_spine(spine)

def extract_phrases_from_gabc_file(filename: str) -> list:
    chant = converter.parse(filename)
    return chant.phrases

def extract_phrases_from_file(filepath: str) -> list:
    """Extract phrases from a file to a list of music21 streams.
    Delegates the extration based on the file extension.

    Parameters
    ----------
    filename : string
        filename of the file

    Returns
    -------
    list
        List of phrases as music21.stream.Stream objects
    """
    if not os.path.exists(filepath):
        raise FileNotFoundError
    extension = os.path.splitext(filepath)[1]
    if extension == '.krn':
        return extract_phrases_from_kern_file(filepath)
    elif extension == '.gabc':
        return extract_phrases_from_gabc_file(filepath)
    else:
        raise Exception('Unknown file format')


"""
Vector construction and manipulation functions for MCRoute networks.

This module contains methods that enable the constructing of vectors needed as
initial conditions for traversal and probability evolution through the network.
Typically, these methods require a defined :class:`mcroute.StateSpace` object
which is used to provide context for building the distribution.
For example:

.. code-block:: Python

    from mcroute import StateSpace
    import mcroute.vector as vector

    space = StateSpace.from_range(-2, 3)
    vector.unit(space, '0')

will produce a unit vetor with zero probability in all rows except for the named
state '0', which will have probability 1.0. All vector creation
methods in this module will return :class:`numpy.Array` objects.
"""
import numpy as np

def uniform(state_space):
    """Create a uniformly distributed probability vector under a state space.

    :param state_space: The state space under which to construct the distribution
    :type state_space: :class:`mcroute.StateSpace`
    :return: A vector of probabilities
    :rtype: :class:`numpy.array`
    """
    p = 1.0/state_space.size
    r = [p for i in range(state_space.size)]
    r[-1] = 1.0 - sum(r[:-1])
    return np.array(r)

def unit(state_space, state_name):
    """Create a unit probability vector at a specified state name.

    This method creates a vector with all zeroes except for at the specified
    state name, which will have probability 1.0.

    :param state_space: The state space under which to construct the vector
    :type state_space: :class:`mcroute.StateSpace`
    :param state_name: The name of the state with unit probability
    :type state_name: str
    :return: A vector of probabilities
    :rtype: :class:`numpy.array`
    """
    r = [0.0 for i in range(state_space.size)]
    r[state_space.index_at(state_name)] = 1.0
    return np.array(r)


import cv2
import numpy as np
import os
os.environ["OPENCV_IO_ENABLE_OPENEXR"]="1"
from PIL import Image
from utils.metrics_nocs import align, prepare_data_posefitting, draw_detections
from datasets.datasets import exr_loader,load_meta
syn_depth_path = '/data/sensor/data/real_data/test_0/0000_gt_depth.exr'
nocs_path = '/data/sensor/data/real_data/test_0/0000_coord.png'
mask_path = '/data/sensor/data/real_data/test_0/0000_mask.png'
meta_path = '/data/sensor/data/real_data/test_0/0000_meta.txt'
obj_dir = '/data/sensor/data/cad_model/real_cat_known'
synset_names = ['other',  # 0
                    'bottle',  # 1
                    'bowl',  # 2
                    'camera',  # 3
                    'can',  # 4
                    'car',  # 5
                    'mug',  # 6
                    'aeroplane',  # 7
                    'BG',  # 8
                    ]
intrinsics = np.zeros((3,3))

img_h = 720
img_w = 1280
fx = 918.295227050781
fy = 917.5439453125

cx = img_w * 0.5 - 0.5
cy = img_h * 0.5 - 0.5
camera_params = {
    'fx': fx,
    'fy': fy,
    'cx': cx,
    'cy': cy,
    'yres': img_h,
    'xres': img_w,
}
hw = (640 / img_w, 360 / img_h)
camera_params['fx'] *= hw[0]
camera_params['fy'] *= hw[1]
camera_params['cx'] *= hw[0]
camera_params['cy'] *= hw[1]
camera_params['xres'] *= hw[0]
camera_params['yres'] *= hw[1]
intrinsics[0,0] = camera_params['fx']
intrinsics[0,2] = camera_params['cx']
intrinsics[1,1] = camera_params['fy']
intrinsics[1,2] = camera_params['cy']
intrinsics[2,2] = 1.0

_syn_depth =  cv2.imread(syn_depth_path, cv2.IMREAD_ANYCOLOR | cv2.IMREAD_ANYDEPTH)
if len(_syn_depth.shape) == 3:
    _syn_depth = _syn_depth[:, :, 0]
coords = Image.open(nocs_path).convert('RGB')
coords = np.array(coords) / 255.

if mask_path.split('.')[-1] == 'exr':
    _mask = exr_loader(mask_path, ndim=1)
else:
    _mask = Image.open(mask_path)
    _mask = np.array(_mask)
if mask_path.split('.')[-1] == 'exr':
    _mask = np.array(_mask * 255, dtype=np.int32)
_meta = load_meta(meta_path)

_mask_sem = np.full(_mask.shape, 8) #, 0）
_scale = np.ones((10,3)) #(class_num+1,3)
for i in range(len(_meta)):
    _mask_sem[_mask == _meta[i]["index"]] = _meta[i]["label"] #1
    if _meta[i]["instance_folder"] !=" " :

        bbox_file = os.path.join(obj_dir,_meta[i]["instance_folder"] ,_meta[i]["name"],'bbox.txt')
        bbox = np.loadtxt(bbox_file)
        _scale[_meta[i]["label"]] = bbox[0, :] - bbox[1, :]
    else :
        _scale[_meta[i]["label"]] = np.ones((3))
    _scale[_meta[i]["label"]] /= np.linalg.norm(_scale[_meta[i]["label"]])

gt_class_ids , gt_scores , gt_masks ,gt_coords ,\
                    gt_boxes = prepare_data_posefitting(_mask_sem,coords)

result = {}
result['gt_RTs'], scales, error_message, _ = align(gt_class_ids,
                                                        gt_masks,
                                                        gt_coords,
                                                        _syn_depth,
                                                        intrinsics,
                                                        synset_names)

if 1:
    output_path = 'tmp'
    draw_rgb = False
    save_dir =os.path.join(output_path ,'save_{}'.format(i))
    if not os.path.exists(save_dir) :
        os.mkdir(save_dir)
    data = 'camera'
    result['gt_handle_visibility'] = np.ones_like(gt_class_ids)
    rgb_path = '/data/sensor/data/real_data/test_0/0000_color.png'
    _rgb = Image.open(rgb_path).convert('RGB')
    _rgb = _rgb.resize((640,360))
    _rgb = np.array(_rgb)

    draw_detections(_rgb, save_dir, data, 1, intrinsics, synset_names, draw_rgb,
                            gt_boxes, gt_class_ids, gt_masks, gt_coords, result['gt_RTs'], scales, np.ones(gt_boxes.shape[0]),
                            gt_boxes, gt_class_ids, gt_masks, gt_coords, result['gt_RTs'], np.ones(gt_boxes.shape[0]), scales)


from client import Client
import values
from lib import *
from class_user import user
SQL = values.sql_connect()
cursor = SQL.cursor()

class defs:

    def __init__ (self , bot_token):
        self.bot_token = bot_token
        self.client = Client(bot_token)

    def get_message (self):
        messages = self.client.get_messages()
        for message in messages:
            yield message

    def send_message (self , user_id , message , keyboard=None):
        self.client.send_text(user_id , message , self.client.make_keyboard(keyboard))

    def change_keyboard (self , to , keyboard):
        self.client.change_keyboard(to, self.client.make_keyboard(keyboard))

    def send_group (self , list_of_user_id , name_karbar , message , keyboard=None):
        text = '%s : %s'
        for har_fard in list_of_user_id:
            self.send_message(har_fard[0] , text % (name_karbar , message) , keyboard)

    def magics_game (self , karbar):
        pass

    def exit_game (self , karbar:user , server , keyboard=None):
        user_id = karbar.ID
        tmp_keyboard = [[{'text' : 'بله' , 'command' : '//yes_exit'} , {'text' : 'نه' , 'command' : '//no_exit'}]]
        self.send_message(user_id , 'ایا مطمعن به خروج از بازی هستید؟' , tmp_keyboard)
        for message in self.get_message():
            if message['body'][0:2] == '//':
                if message['body'] == '//yes_exit':
                    cursor.execute('DELETE FROM %s WHERE ID="%s"' % (server.server_name , user_id))
                    t_m = 'کاربر %s از بازی خارج شد' % karbar.name # tmp_message
                    self.send_group(server.all , 'سیستم' , t_m , keyboard)
                    return True

                if message['body'] == '//no_exit':
                    self.send_message(user_id , 'باشه پس به بازی ادامه بده' , keyboard)
                    return False
            else:
                self.send_group(server.server_name , karbar.name , message['body'])

    def reset_rank (self , user_id):
        tmp_message = 'ایا مطمعن به پاک کردن تمام اطلاعات خود شامل امتیاز , نام و  id شما در ربات هستید؟'
        tmp_keyboard = [[{'text' : 'بله' , 'command' : '//yes_reset_rank'} , {'text' : 'نه' , 'command' : '//no_reset_rank'}]]
        self.send_message(user_id , tmp_message , tmp_keyboard)
        for message in self.get_message():
            if message['body'][0:2] == '//':
                if message['body'] == '//yes_reset_rank':
                    cursor.execute('DELETE FROM %s WHERE ID="%s"' %(values.table_users() , user_id))
                    SQL.commit()
                    self.send_message(user_id , 'اطلاعات شما با موفقیت پاک شد')
                    return True
                if message['body'] == '//no_reset_rank':
                    self.send_message(user_id , 'باشه')
                    return False
            else:
                self.send_message(user_id , 'جوون؟ :/')

    def start_game (self , karbar):
        tmp_message = 'ایا مطمعن به شروع بازی هستید؟'
        tmp_keyboard = [ [{'text' : 'بله' , 'command' : '//yes_start_game_main_page'} , {'text' : 'نه' , 'command' : '//no_start_game_main_page'}] ]
        self.send_message(karbar.ID , tmp_message , tmp_keyboard)

        for message in self.get_message():
            if message['from'] == karbar.ID:
                body = message['body']
                if body == '//yes_start_game_main_page':
                    game_loop(karbar)
                    break
                elif body == '//no_start_game_main_page':
                    self.send_message(karbar.ID , 'باشه')
                    break

    def change_name (self , karbar):
        user_id = karbar.ID
        name_karbar = None
        tmp_message_2 = 'لطفا اسم خود را وارد نمایید'
        tmp_keyboard_2 = [ [{'text' : 'منصرف شدم' , 'command' : '//cancel_change_name_main_page'}] ]
        self.send_message(user_id , tmp_message_2 , tmp_keyboard_2)

        for message in self.get_message():

            if message['from'] == user_id:
                body = message['body']
                if message['body'] == '//cancel_change_name_main_page': # cancel
                    self.send_message(user_id , 'باشه')
                    return False
                if body == '//yes_change_name': # change name
                    karbar.updater('Name' , name_karbar)
                    self.send_message(user_id , 'اسم شما با موفقیت تغییر کرد')
                    return True
                if not body[0:2] == '//':
                    name_karbar = body
                if body == '//no_change_name': # wrong onderstand
                    self.send_message(user_id , 'ببخشید لطفا دوباره بگید')
                    name_karbar = None
                if name_karbar != None:
                    tmp_message = 'اسم شما %s هست دیگه نه؟' % name_karbar
                    tmp_keyboard = [[{'text' : 'اره همینه' , 'command' : '//yes_change_name'} , {'text' : 'نه اشتباهه' , 'command' : '//no_change_name'}]]
                    self.send_message(user_id , tmp_message , tmp_keyboard)

    def amtiaz_hai_karbar (self , karbar):
        cursor.execute('SELECT Amtiaz , tedad_davat , tedad_seke FROM %s WHERE ID="%s"' %(values.table_users() , karbar.ID))
        data = cursor.fetchall()[0]
        tmp = 'امتیاز شما هست: %i\nتعداد نفرات دعوت شده توسط شما هست: %i\nنعداد سکه های شما هست: %i' % (data[0] , data[1] , data[2])
        self.send_message(karbar.ID , tmp)

    def show_best_gamer (self , karbar , keyboard=None):
        list_name = ['بهترین های این بازی از لحاظ امتیاز برابر است با:\n']
        tmp = ' %s : %s'
        counter = 0
        SQL = values.sql_connect()
        cursor = SQL.cursor()
        cursor.execute('SELECT Amtiaz , Name FROM %s' % values.table_users())
        data = cursor.fetchall()
        data.sort(reverse=True)

        for har_shakhs in data:
            number = jaigozari(har_shakhs[0])

            if counter == 11:
                break
            if counter == 0:
                list_name.append('🥇.' + tmp % (har_shakhs[1] , number))
            elif counter == 1:
                list_name.append('🥈.' + tmp % (har_shakhs[1] , number))
            elif counter == 2:
                list_name.append('🥉.' + tmp % (har_shakhs[1] , number))
            else:
                list_name.append('🌟.' + tmp % (har_shakhs[1] , number))
            counter += 1
        list_name.append('\n\n⭕' + tmp % (karbar.name , karbar.amtiaz))

        self.send_message(karbar.ID , '\n'.join(list_name) , keyboard)

    def help_about_game (self , karbar , keyboard=None):
        pass

    def random_karakter (self , list_user_id):
        Dict = dict()
        from random import sample

        jon       = ','.join( sample( ['doktor'       , 'badygard' ] , 1))                       # حفاظتی ها
        dideban   = ','.join( sample( ['tizbin'       , 'radgir'   ] , 1))                       # دیدهبان ها
        plus      = ','.join( sample( ['ghebgo'       , 'zerehposh'] , 1))                       # کمکی ها
        mostaghel = ','.join( sample( ['gorgine'      , 'ghatel'  , 'joker'   ] , 1))            # مستقل ها
        sabet     = ','.join( sample( ['pedar_khande' , 'sniper' , 'bazpors' ] , 3))             # ثابت ها
        mafia     = ','.join( sample( ['haker'        , 'noche'   , 'maftesh' , 'shaiad' ] , 1)) # مافیا ها

        List_karakters = (jon + ',' + dideban + ',' + mostaghel + ',' + sabet + ',' + mafia + ',' + plus).split(',')
        List_karakters = sample(List_karakters , len(List_karakters))

        for counter in range(len(List_karakters)):
            Dict[list_user_id[counter]] = List_karakters[counter]

        return Dict


from common.FrontendTexts import FrontendTexts
view_texts = FrontendTexts('quotes')

labels = view_texts.getComponent()['selector']['choices']

ACTION_CHOICES = (
    (1, labels['edit']),
    (2, labels['edit_materials'])
)

PROVIDER_CHOICES = (
    (1, "MP100001 - Conpancol Ingenieros"),
    (2, "MP100002 - Maasteel UK")
)


from datetime import datetime

import requests
from flask import Flask, render_template

app = Flask(__name__)

year = datetime.now().year
# print(year)
response = requests.get('https://api.npoint.io/362a61befce3d173e925')
blog_posts = response.json()

# print(blog_posts)

@app.route('/')
def home():
    return render_template("index.html", post_data=blog_posts, date=year)

@app.route('/post/<int:index>')
def post_selected(index):
    post_current = None
    for post in blog_posts:
        if post['id'] == index:
            post_current = post

    return render_template("post.html", post_data=post_current, date=year)

if __name__ == "__main__":
    app.run(debug=True)


#Prime, Composite, Even Odd
def list1(n):
    l1=[]
    even=[]
    odd=[]
    prime=[]
    comp=[]

    for i in range(n):
        e=int(input("Enter The Element:"))
        l1.append(e)
    for j in l1:
         if j%2==0:
            even.append(j)
         if j%2!=0:
            odd.append(j)
    for k in l1:
        c=0
        for p in range(1,k+1):
            mod=k%p
            if mod==0:
                c+=1
        if c==2:
            prime.append(k)
        if c>2:
            comp.append(k)

    print("The Even Elements Are:",even)
    print("The Odd Elements Are:",odd)
    print("The Prime Elements Are:",prime)
    print("The Composite Elements Are:",comp)

n=int(input("Enter The Number Of Elements:"))

list1(n)


from ftplib import FTP
import ftplib
import os
import xml.etree.ElementTree as EleTree
import VAPublishUtil as VAUtil
import shutil
import EchoItemXML

__author__ = 'Jiao Zhongxiao'

# 选择的功能分支
FEATURE_BRANCH = None

# 确认的版本号
VERSION_NUM = None

ASSET_EXT = ".json,.jpg,.png,.swf,.xml,.mp3,.wdp,.xcom"
IGNORE_EXT = ".xcom"
IGNORE_FILES = ["towerDefenseFight", "PvpPlayerPanel", "commonLang_config"]

def print_branch_select_menu():
    """展示功能分支选择菜单"""
    publish_config = VAUtil.parse_publish_config()
    print("可以发布的功能分支：")
    i = 0
    for feature_node in publish_config.findall("feature"):
        print(str(i) + ": " + feature_node.get("name"))
        i += 1

def publish_feature_branch():
    """发布指定功能分支"""
    print("开始发布功能分支: --> " + FEATURE_BRANCH)
    publish_dir = VAUtil.publish_dir()
    # 更新 config.xml
    EchoItemXML.scan_dir(os.path.join(VAUtil.PRE_PUBLISH_ROOT_DIR, FEATURE_BRANCH))
    # 拷贝到临时目录
    copy_file_to_temp_dir()
    # 打版本
    version_files()
    # 同步到发布目录
    # sync_to_publish_dir()
    # 提交 SVN
    # VAUtil.svn_commit(publish_dir, "版本更新" + VERSION_NUM)
    # 同步 FTP
    sync_to_ftp(collect_files())
    input("版本发布完成")

def sync_to_ftp(all_files):
    """上传到 FTP"""
    ftp = VAUtil.prepare_ftp()
    ftp_dir = "/www/" + FEATURE_BRANCH + "/flash"
    ftp.cwd(ftp_dir)
    temp_dir = VAUtil.temp_dir()
    while len(all_files) > 0:
        upload_file = all_files.pop(0)
        print("Uploading:" + upload_file)
        rel_path = os.path.relpath(upload_file, temp_dir).replace("\\", "/")
        file_dir = os.path.dirname(rel_path)
        if len(file_dir) > 0:
            print("创建目录" + file_dir)
            try:
                ftp.mkd(file_dir)
            except ftplib.error_perm:
                print("目录已经存在")
        cur_uploading_file = open(upload_file, 'rb')
        ftp.storbinary("STOR " + rel_path, cur_uploading_file)

def collect_files():
    """收集要同步的文件"""
    temp_dir = VAUtil.temp_dir()
    all_files = []
    for rootDir, assetsDirs, files in os.walk(temp_dir):
        for file in files:
            file_path = os.path.join(temp_dir, os.path.join(rootDir, file))
            all_files.append(file_path)
    return all_files

def sync_to_publish_dir():
    """复制到发布目录"""
    temp_dir = VAUtil.temp_dir()
    publish_dir = VAUtil.publish_dir()
    for rootDir, assetsDirs, files in os.walk(temp_dir):
        for file in files:
            print("Copying:" + file)
            if os.path.isfile(os.path.join(rootDir, file)):
                rel_path = os.path.relpath(os.path.join(rootDir, file), temp_dir)
                print("原始：" + rel_path)
                rel_path = os.path.join(publish_dir, rel_path)
                print("新的：" + rel_path)
                file_dir = os.path.dirname(rel_path)
                print("FileDir:" + file_dir)
                if not os.path.exists(file_dir):
                    os.makedirs(file_dir)
                shutil.copyfile(os.path.join(rootDir, file), rel_path)
                print("Copy " + os.path.join(rootDir, file) + " 完成")

def copy_file_to_temp_dir():
    """将相关资源拷贝到临时目录"""
    temp_dir = os.path.join(VAUtil.PRE_PUBLISH_ROOT_DIR, VAUtil.PUBLISH_TEMP_DIR)
    source_dir = os.path.join(VAUtil.PRE_PUBLISH_ROOT_DIR, FEATURE_BRANCH)
    print("拷贝资源到缓存目录:\nsourceDir:->" + temp_dir + "\n缓存目录" + temp_dir)
    if os.path.exists(temp_dir):
        shutil.rmtree(temp_dir)
    os.mkdir(temp_dir)
    wrapper_file = "wrapper.swf"
    # wrapper.swf
    src = os.path.join(source_dir, wrapper_file)
    dst = os.path.join(temp_dir, wrapper_file)
    shutil.copy(src, dst)
    # release & ver_config
    dirs = [VAUtil.RES_RELEASE_DIR_NAME, VAUtil.RES_CONFIG_STORE_DIR_NAME]
    for copy_dir in dirs:
        src = os.path.join(source_dir, copy_dir)
        dst = os.path.join(temp_dir, copy_dir)
        copy_files(src, dst)
    print("拷贝资源完成")

def copy_files(src_dir, dst_dir):
    """拷贝项目认可的资源文件"""
    for root_dir, assets_dirs, files in os.walk(src_dir):
        for file in files:
            ext = os.path.splitext(file)[1]
            if ext != "" and ASSET_EXT.find(ext) != -1:
                # 相对路径
                rel_path = os.path.relpath(os.path.join(root_dir, file), src_dir)
                print("原始：" + rel_path)
                dst_path = os.path.join(dst_dir, rel_path)
                print("新的：" + dst_path)
                file_dir = os.path.dirname(dst_path)
                print("FileDir:" + file_dir)
                if not os.path.exists(file_dir):
                    os.makedirs(file_dir)
                shutil.copyfile(os.path.join(root_dir, file), dst_path)
                print("Copy " + os.path.join(root_dir, file) + " 完成")

def check_is_ignore_file(file_name):
    """检查是否是是接加版本号的文件"""
    for ignore_file in IGNORE_FILES:
        if file_name.find(ignore_file) != -1:
            return True
    return False

def version_file_with_ver_num(file_path, xml_node):
    """将文件直接加上版本号"""
    ext = os.path.splitext(file_path)[1]
    print("尝试将文件直接加上版本号 Processing:" + file_path)
    if IGNORE_EXT.find(ext) != -1 or check_is_ignore_file(xml_node.get("id")):
        crc = VERSION_NUM
        xml_node.set("size", str(os.path.getsize(file_path)))
        xml_node.text = xml_node.text.replace(ext, "_" + crc + ext)
        new_file = file_path.replace(ext, "_" + crc + ext)
        os.replace(file_path, new_file)
        return True
    else:
        return False

def version_dir_with_ver_num(work_dir):
    """将目录下的文件直接加上版本号"""
    files = os.listdir(work_dir)
    for file in files:
        old_file = os.path.join(work_dir, file)
        is_file = os.path.isfile(old_file)
        print(old_file + "---" + str(is_file))
        if is_file:
            ext = os.path.splitext(file)[1]
            new_file = old_file.replace(ext, "_" + str(VERSION_NUM) + ext)
            print("重命名：" + old_file + "<>" + new_file)
            os.replace(old_file, new_file)

def res_config_file_path():
    """获取当前的资源配置路径"""
    return os.path.join(VAUtil.temp_dir(), VAUtil.RES_CONFIG_STORE_DIR_NAME, EchoItemXML.XML_FILE_NAME)

def com_res_config_file_path():
    """获取当前的资源配置压缩路径"""
    return os.path.join(VAUtil.temp_dir(), VAUtil.RES_CONFIG_STORE_DIR_NAME, EchoItemXML.COM_XML_FILE_NAME)

def version_file_with_crc32():
    """根据文件的 CRC32 校验加版本号"""
    temp_dir = VAUtil.temp_dir()
    config_file = res_config_file_path()
    config = EleTree.parse(config_file)
    root = config.getroot()
    for folderElement in root:
        folder = folderElement.get("folder")
        for item in folderElement:
            file = os.path.join(temp_dir, folder, item.text)
            if os.path.exists(file):
                if not version_file_with_ver_num(file, item):
                    VAUtil.version_file_with_crc32(file, item)
    config.write(config_file)
    VAUtil.compress_file(config_file, com_res_config_file_path())

def version_files():
    """给所有文件加上相应的版本后缀"""
    print("开始给所有文件加上版本后缀")
    root_dir = VAUtil.temp_dir()
    # 主目录 wrapper.swf
    version_dir_with_ver_num(root_dir)
    # release 目录
    version_file_with_crc32()
    # ver_config 目录
    version_dir_with_ver_num(os.path.join(root_dir, VAUtil.RES_CONFIG_STORE_DIR_NAME))

def feature_test():
    p_root_dir = VAUtil.try_find_project_root_dir()
    if p_root_dir:
        # 更新 SVN
        VAUtil.svn_update(p_root_dir)
        p_config = VAUtil.parse_publish_config()
        # 展示菜单
        print_branch_select_menu()
        # 读取选项
        select_i = VAUtil.read_select_index()
        # 设置发布分支
        global FEATURE_BRANCH
        FEATURE_BRANCH = p_config.findall("feature")[select_i].get("branchDir")
        global VERSION_NUM
        # 确认发布版本号
        if select_i < 0:
            VERSION_NUM = str(select_i)
        else:
            VERSION_NUM = input("确认发布版本号:\n")
        publish_feature_branch()

if __name__ == "__main__":
    feature_test()


# Importing Required Libraries
import cv2
# define a class called ImageReader
class ImageReader:
    def __init__(self, filename):
        self.filename = filename

    def read_image(self):
        try:
            img = cv2.imread(self.filename)
            if img is None:
                raise Exception("Error: Unable to read image file")
        except Exception as e:
            print(str(e))
        else:
            return img

# create an instance of the ImageReader
reader = ImageReader(r"C:\PYTHON\AI_ML\OpenCV\Computer_vision.jpeg")
# call the read_image() method
img = reader.read_image()
if img is not None:
    # to show an image
    cv2.imshow("Image", img)
    # to dispaly upto defined time
    cv2.waitKey(0)
    # to close the open window
    cv2.destroyAllWindows()
# After executing this code seperate window will be open with an image which has given in the path.

# ### Reading an Image by allow the user to enter a link

# Importing Required Libraries
import cv2
import urllib.request
import numpy as np

# define a class called ImageReader
class ImageReader:
    def __init__(self, url):
        self.url = url

    def read_image(self):
        try:
            resp = urllib.request.urlopen(self.url)
            img = np.asarray(bytearray(resp.read()), dtype="uint8")
            img = cv2.imdecode(img, cv2.IMREAD_COLOR)
            if img is None:
                raise Exception("Error: Unable to read image file")
        except Exception as e:
            print(str(e))
        else:
            return img

# create an instance of the ImageReader
url = input("Enter the URL of the image file: ")
reader = ImageReader(url)
img = reader.read_image()
if img is not None:
    cv2.imshow("Image", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
# After Executing above code It will ask you to enter an url link to diaplay an image.


import tweepy
import json
import time
import datetime
import ConfigParser
import tweepy
from tweepy.streaming import StreamListener

'''
Get API keys from Configurations document
'''
config = ConfigParser.ConfigParser()
config.readfp(open(r'./configurations.txt'))

consumerKey=config.get('API Keys', 'consumerKey')
consumerSecret=config.get('API Keys', 'consumerSecret')
accessToken=config.get('API Keys', 'accessToken')
accessSecret=config.get('API Keys', 'accessSecret')

'''
Returns given number of tweets for given Twitter handle
'''
def get_tweets(twitter_handle, num_tweets):

    auth = tweepy.AppAuthHandler(consumerKey, consumerSecret)
    api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True)

    timeline = api.user_timeline(screen_name=twitter_handle, count=num_tweets)

    user_tweets = []

    for current_tweet in timeline:
        if not current_tweet.retweeted:
            tweet = {}
            tweet['tweetId'] = current_tweet.id
            tweet['message'] = current_tweet.text
            tweet['author'] = current_tweet.user.name
            s = str(current_tweet.created_at)
            new_s = time.mktime(datetime.datetime.strptime(s, "%Y-%m-%d %H:%M:%S").timetuple()) * 1000
            tweet['timestamp'] = new_s
            user_tweets.append(tweet)

    return user_tweets


from utils.terminal import clear
from utils.Database import Database
import requests
from utils.OpenApi import OpenApi

class Dialogue:

    def __init__(self):
        self.database = Database()
        self.main_menu()
        self.open_api = OpenApi()

    def main_menu(self) -> None:
        """
        This function prints the main menu for the application and gets the input for the options
        :return: None
        """
        options = [
            {"text": "Chercher un produit", "method": self.show_categories},
            {"text": "Voir mes aliments substitués", "method": self.show_substitutes},
        ]  # Put the options in a list as dicts with a pointer to the method they have to call
        clear()
        while True:
            for index, option in enumerate(options):  # foreach option print it with its index
                print(str(index) + ". " + option["text"])
            print("\x1b[6;32;40mChoisissez une option en écrivant le chiffre correspondant et "
                  "appuyez sur entrée:\x1b[0m")
            try:
                choice = int(input())
                clear()
                if 0 <= choice < len(options):  # if the input is within the range of options available
                    return options[choice]["method"]()  # call the method that's in the option at 'index'
                print("\x1b[6;31;40mChoix inconnu\x1b[0m")
            except ValueError:  # int(input()) throws a ValueError
                clear()
                print("\x1b[6;31;40mVeuillez entrer un nombre entier svp\x1b[0m")

    def show_categories(self) -> None:
        """
        This method prints the categories available in the database and gets an input from the user to chose
        which category to search in
        :return: None
        """
        categories = self.database.select("category")  # Get all the categories in the db
        while True:
            for index, category in enumerate(categories):  # for each category
                print(str(index) + ". " + category[1])  # print the category name and its index
            print("-1. Revenir au menu principal")
            print("\x1b[6;32;40mChoisissez une option en écrivant le chiffre correspondant et "
                  "appuyez sur entrée:\x1b[0m")
            try:
                choice = int(input())
                clear()
                if choice == -1:
                    self.main_menu()
                if 0 <= choice < len(categories):
                    # Show the products corresponding to the chosen category
                    return self.show_products(categories[choice])
                print("\x1b[6;31;40mChoix inconnu\x1b[0m")
            except ValueError:  # int(input()) throws a ValueError
                clear()
                print("\x1b[6;31;40mVeuillez entrer un nombre entier svp\x1b[0m")

    def show_products(self, category: list) -> None:
        """
        This method prints the products that are in the category given in the arguments and gets an input from the
        user to chose a product
        :param category: list
        :return: None
        """
        # Retrieve the products that have the chosen category's id in their category field
        products = self.database.select("aliment", "category=" + str(category[0]))
        while True:
            for index, product in enumerate(products):
                print(str(index) + ". " + product[1])
            print("-1. Revenir au menu principal")
            print("\x1b[6;32;40mChoisissez une option en écrivant le chiffre correspondant et "
                  "appuyez sur entrée:\x1b[0m")
            try:
                choice = int(input())
                clear()
                if choice == -1:
                    self.main_menu()
                if 0 <= choice < len(products):
                    return self.show_product_info(products[choice], category)
                else:
                    print("\x1b[6;31;40mChoix inconnu\x1b[0m")
            except ValueError:  # int(input()) throws a ValueError
                clear()
                print("\x1b[6;31;40mVeuillez entrer un nombre entier svp\x1b[0m")

    @staticmethod
    def generate_search_params(category: list, nutrition_grade: str) -> str:
        """
        This method generates the search parameters needed to get the products from a category and a certain
        nutrition grade
        :param category: the category from which the product is
        :param nutrition_grade: the nutrition grade of the product
        :return: the parameters to add to the search URL
        """
        params = "?action=process&" \
                 "tagtype_0=categories&" \
                 "tag_contains_0=contains&" \
                 "tag_0={}&" \
                 "tagtype_1=nutrition_grades&" \
                 "tag_contains_1=contains&" \
                 "tag_1={}&" \
                 "json=1".format(category[0], nutrition_grade)
        return params

    def show_product_info(self, product: list, category: list) -> None:
        """
        This function shows the infos on a product, searchs for a substitute and asks the user if he wants to save it
        in the database
        :param product: the product the user chose
        :param category: the category of the product ( used to search for the substitute )
        :return: None
        """
        print("Infos produit:")
        print("Nom:", product[1])
        print("Grade nutritionnel:", product[3])
        if "stores" in product:
            print(product[4] + "\n")
        substitut = self.search_substitute(product, category)
        if substitut:
            print("Voulez-vous enregistrer le substitut en base de données ?")
            print("o. Oui")
            print("n. Non")
            print("\x1b[6;32;40mChoisissez une option en écrivant la lettre correspondante et "
                  "appuyez sur entrée:\x1b[0m")
            while True:
                choice = input()
                if str(choice).lower() == "o":
                    self.save_substitute(substitut, product)
                    print("\x1b[6;32;40mSubstitut sauvegardé avec succès!\x1b[0m")
                    break
                elif str(choice).lower() == "n":
                    print("Substitut non sauvegardé.")
                    break
                else:
                    print("\x1b[6;31;40mVeuillez entrer un choix valide svp\x1b[0m")
        print("\nAppuyez sur entrée pour revenir au menu principal")
        input()
        self.main_menu()

    def save_substitute(self, substitut: dict, product: list) -> None:
        """
        This method saves a substitute to the database and links it to an aliment
        :param substitut: The substitute we got from the API
        :param product: the product the user chose ( to link the substitute to it )
        :return: None
        """
        already_exists = self.database.select("substitute", "product_name = '{}'"
                                              .format(substitut["product_name"].replace("'", "\\'")))
        if already_exists:
            substitute_id = already_exists[0][0]
        else: # if the substitute doesn't exist create it
            headers = ["product_name", "category", "nutrition_grades", "stores"]
            substitut["category"] = product[2]
            data = []
            for header in headers:
                try:
                    data.append("'" + substitut[header].replace("'", "\\'") + "'")
                except KeyError:
                    data.append("NULL")
                except AttributeError:  # if it's an int ( = the id of the category )
                    data.append(str(substitut["category"]))
            substitute_id = self.database.insert("substitute", headers, data)
        # update the aliment with the substitute's id
        self.database.update("aliment", ["substitute_id=" + str(substitute_id)], ["id=" + str(product[0])])

    def search_substitute(self, product: list, category: list) -> dict:
        """
        Uses the search API to retrieve a more healthy substitute to a product
        :param product: the product we want to search a substitute for
        :param category: the category of the product
        :return: the found substitute or an empty dict
        """
        substitut = None
        search_url = "https://fr.openfoodfacts.org/cgi/search.pl"
        for i in range(0, 5):
            # get ascii value of A and add the current index to it so we can get the next letters
            nutrition_grade = chr(ord("A") + i)
            if ord(nutrition_grade) >= ord(product[3]):  # if the nutrigrade is the same as the product's, break
                print("Nous n'avons pas pu trouver de substitut plus sain à ce produit")
                break
            params = Dialogue.generate_search_params(category[1], nutrition_grade)
            r = requests.get(search_url + params).json()  # get the search url with the generated search params
            if r["count"]:
                substitut = r["products"][0]
                print("\nSubstitut:")
                print("Nom:", substitut["product_name"])
                try:
                    print("Grade nutritionnel:", substitut["nutrition_grades"])
                except KeyError:
                    pass
                try:
                    print("Ou l'acheter:", substitut["stores"] + "\n")
                except KeyError:
                    pass
                break
        if substitut:
            substitut["category"] = category[1]
            return substitut
        return {}

    def show_substitutes(self) -> None:
        """
        Show all the aliments that have a substitute saved in the database
        :return: None
        """
        aliments = self.database.select("aliment", "substitute_id is not null")
        while True:
            for index, aliment in enumerate(aliments):
                print(str(index) + ". " + aliment[1])
            print("-1. Revenir au menu principal")
            print("\x1b[6;32;40mChoisissez une option en écrivant le chiffre correspondant et "
                  "appuyez sur entrée:\x1b[0m")
            try:
                choice = int(input())
                clear()
                if choice == -1:
                    self.main_menu()
                if 0 <= choice < len(aliments):
                    self.show_substitute_infos(aliments[choice])
                else:
                    print("\x1b[6;31;40mChoix inconnu\x1b[0m")
            except ValueError:  # int(input()) throws a ValueError
                clear()
                print("\x1b[6;31;40mVeuillez entrer un nombre entier svp\x1b[0m")

    def show_substitute_infos(self, aliment) -> None:
        """
        Show the infos on a saved substitute
        :param aliment: the aliment chosen by the user
        :return: None
        """
        substitute = self.database.select("substitute", "id=" + str(aliment[-1]))[0]
        category = self.database.select("category", "id=" + str(substitute[2]))
        print("Substitut à {}:".format(aliment[1]))
        print("nom:", substitute[1])
        print("categorie:", category[0][1])
        print("grade nutritionnel:", substitute[3])
        print("Magasins:", substitute[4])
        print("\nAppuyez sur entrée pour revenir au menu principal")
        input()
        self.main_menu()


alien_o = {'color' : 'green', 'points' : 5}

print (alien_o)

alien_o['x_position'] = 0
alien_o['y_position'] = 25
print (alien_o)

# change the value of dictionary
print ("The alien color is " + alien_o['color'] + ".")
alien_o['color'] = 'yellow'
print ("The alien is now " + alien_o['color'] + ".")

# move the alien to the right side
# accroding the speed to decide how far the alien move

alien_i = {'x_position': 0, 'y_position': 25, 'speed': 'medium'}
print ("Original x_position: " + str(alien_i['x_position']))

if alien_i['speed'] == 'slow':
    x_increment = 1
elif alien_i['speed'] == 'medium':
    x_increment = 2
else:
    # the speed of this alien must fast
    x_increment = 3

# the new position equals the old position add the increment
alien_i['x_position'] = alien_i['x_position'] + x_increment
print ("New x_position: " + str(alien_i['x_position']))

# delete the key-value
alien_u = {'color': 'blue', 'point': 7}
print (alien_u)

del  alien_u['point']
print (alien_u)


import sys
import threading

def main():

    t = int(input())
    count = 0

    def beautify(nums):
        nonlocal count
        if len(nums) == 1:
            return nums

        mid = len(nums) // 2
        left = beautify(nums[:mid])
        right = beautify(nums[mid:])

        if left[0] > right[0]:
            count += 1
            return right + left
        return left + right

    def check(nums, count):

        for i in range(1, len(nums)):
            if nums[i] != nums[i-1] + 1:
                return -1
        return count

    for _ in range(t):
        n = int(input())
        nums = [int(x) for x in input().split()]
        count = 0

        newNums = beautify(nums)
        print(check(newNums, count))

if __name__ == '__main__':
    sys.setrecursionlimit(1 << 30)
    threading.stack_size(1 << 27)

    main_thread = threading.Thread(target=main)
    main_thread.start()
    main_thread.join()