import itertools
import numpy as np

from pytesmo.validation_framework.upscaling import Upscaling, MixinReadTs

class DataManager(MixinReadTs):

    """
    Class to handle the data management.

    Parameters
    ----------
    datasets : dict of dicts
        :Keys : string, datasets names
        :Values : dict, containing the following fields

            'class' : object
                Class containing the method `read` for reading the data.
            'columns' : list
                List of columns which will be used in the validation process.
            'args' : list, optional
                Args that are passed to the reading function.
            'kwargs' : dict, optional
                Kwargs that are passed to the reading function.
            'grids_compatible' : boolean, optional
                If set to True the grid point index is used directly when
                reading other, if False then lon, lat is used and a nearest
                neighbour search is necessary.
                default: False
            'use_lut' : boolean, optional
                If set to True the grid point index (obtained from a
                calculated lut between reference and other) is used when
                reading other, if False then lon, lat is used and a
                nearest neighbour search is necessary.
                default: False
            'max_dist' : float, optional
                Maximum allowed distance in meters for the lut calculation.
                default: None
    ref_name : string
        Name of the reference dataset. The reference dataset is used as spatial
        reference, i.e. all other dataset will be interpolated to the locations
        of the reference dataset.
    period : list, optional
        Of type [datetime start, datetime end]. If given then the two input
        datasets will be truncated to start <= dates <= end.
    read_ts_names : string or dict of strings, optional
        if another method name than 'read' should be used for reading the data
        then it can be specified here. If it is a dict then specify a
        function name for each dataset.
    upscale_parms : dict, optional. Default is None.
        dictionary with parameters for the upscaling methods. Keys:
            * 'upscaling_method': method for upscaling
            * 'temporal_stability': bool for using temporal stability
            * 'upscaling_lut': dict of shape
                {'other_name':{ref gpi: [other gpis]}}

    Methods
    -------
    use_lut(other_name)
        Returns lut between reference and other if use_lut for other dataset
        was set to True.
    get_result_names()
        Return results names based on reference and others names.
    read_reference(*args)
        Function to read and prepare the reference dataset.
    read_other(other_name, *args)
        Function to read and prepare the other datasets.
    """

    def __init__(
        self,
        datasets,
        ref_name,
        period=None,
        read_ts_names="read",
        upscale_parms=None,
    ):
        self.datasets = datasets
        self._add_default_values()
        self.reference_name = ref_name
        self.upscale_parms = upscale_parms

        self.other_name = []
        for dataset in datasets.keys():
            if dataset != ref_name:
                self.other_name.append(dataset)
                if "use_lut" not in self.datasets[dataset]:
                    self.datasets[dataset]["use_lut"] = False

        try:
            self.reference_grid = self.datasets[self.reference_name][
                "class"
            ].grid
        except AttributeError:
            self.reference_grid = None

        self.period = period

        # get reading functions
        if type(read_ts_names) is dict:
            self.read_ts_names = read_ts_names
        else:
            d = {}
            for dataset in datasets:
                d[dataset] = read_ts_names
            self.read_ts_names = d

        # match points in space
        if upscale_parms:
            # initialize class that performs upscaling operations
            others_class = {}
            for other in self.other_name:
                others_class[other] = self.datasets[other]["class"]
            self.luts = Upscaling(
                ref_class=datasets[self.reference_name]["class"],
                others_class=others_class,
                upscaling_lut=upscale_parms["upscaling_lut"],
                manager_parms=self.__dict__,
            )
        else:
            # combine ref to NNs only
            self.luts = self.get_luts()

    def _add_default_values(self):
        """
        Add defaults for args, kwargs, grids_compatible, use_lut and
        max_dist to dataset dictionary.
        """
        defaults = {
            "use_lut": False,
            "args": [],
            "kwargs": {},
            "grids_compatible": False,
            "max_dist": np.inf,
        }
        for dataset in self.datasets.keys():
            new_defaults = dict(defaults)
            new_defaults.update(self.datasets[dataset])
            self.datasets[dataset] = new_defaults

    def get_luts(self):
        """
        Returns luts between reference and others if use_lut for other datasets
        was set to True.

        Returns
        -------
        luts : dict
            Keys: other datasets names
            Values: lut between reference and other, or None
        """
        luts = {}
        for other_name in self.other_name:
            if self.datasets[other_name]["use_lut"]:
                luts[other_name] = self.reference_grid.calc_lut(
                    self.datasets[other_name]["class"].grid,
                    max_dist=self.datasets[other_name]["max_dist"],
                )
            else:
                luts[other_name] = None

        return luts

    @property
    def ds_dict(self):
        ds_dict = {}
        for dataset in self.datasets.keys():
            ds_dict[dataset] = self.datasets[dataset]["columns"]
        return ds_dict

    def get_results_names(self, n=2):

        return get_result_names(self.ds_dict, self.reference_name, n=n)

    def read_reference(self, *args):
        """
        Function to read and prepare the reference dataset.

        Calls read of the dataset.
        Takes either 1 (gpi) or 2 (lon, lat) arguments.

        Parameters
        ----------
        gpi : int
            Grid point index
        lon : float
            Longitude of point
        lat : float
            Latitude of point

        Returns
        -------
        ref_df : pandas.DataFrame or None
            Reference dataframe.
        """
        return self.read_ds(self.reference_name, *args)

    def read_other(self, name, *args):
        """
        Function to read and prepare non-reference datasets.

        Calls read of the dataset.

        Takes either 1 (gpi) or 2 (lon, lat) arguments.

        Parameters
        ----------
        name : string
            Name of the other dataset.
        gpi : int
            Grid point index
        lon : float
            Longitude of point
        lat : float
            Latitude of point

        Returns
        -------
        data_df : pandas.DataFrame or None
            Data DataFrame.
        """
        return self.read_ds(name, *args)

    def get_data(self, gpi, lon, lat):
        """
        Get all the data from this manager for a certain
        grid point, longitude, latidude combination.

        Parameters
        ----------
        gpi: int
            grid point indices
        lon: float
            grid point longitude
        lat: type
            grid point latitude

        Returns
        -------
        df_dict: dict of pandas.DataFrames
            Dictionary with dataset names as the key and
            pandas.DataFrames containing the data for the point
            as values.
            The dict will be empty if no data is available.
        """
        df_dict = {}

        ref_dataframe = self.read_reference(gpi)
        # if no reference data available continue with the next gpi
        if ref_dataframe is None:
            return df_dict

        other_dataframes = self.get_other_data(gpi, lon, lat)
        # if no other data available continue with the next gpi
        if len(other_dataframes) == 0:
            return df_dict

        df_dict = other_dataframes
        df_dict.update({self.reference_name: ref_dataframe})

        return df_dict

    def get_other_data(self, gpi, lon, lat):
        """
        Get all the data for non reference datasets
        from this manager for a certain
        grid point, longitude, latidude combination.

        Parameters
        ----------
        gpi: int
            grid point indices
        lon: float
            grid point longitude
        lat: type
            grid point latitude

        Returns
        -------
        other_dataframes: dict of pandas.DataFrames
            Dictionary with dataset names as the key and
            pandas.DataFrames containing the data for the point
            as values.
            The dict will be empty if no data is available.
        """

        other_dataframes = {}
        for other_name in self.other_name:
            grids_compatible = self.datasets[other_name]["grids_compatible"]
            if grids_compatible:
                other_dataframe = self.read_other(other_name, gpi)
            elif isinstance(self.luts, Upscaling):
                other_dataframe = self.luts.get_upscaled_ts(
                    gpi=gpi, other_name=other_name, **self.upscale_parms
                )
            elif self.luts[other_name] is not None:
                other_gpi = self.luts[other_name][gpi]
                if other_gpi == -1:
                    continue
                other_dataframe = self.read_other(other_name, other_gpi)
            else:
                # other_dataframe = self.read_other(other_name, lon, lat)
                max_dist = self.datasets[other_name].get("max_dist", np.inf)
                grid = self.datasets[other_name]["class"].grid
                other_gpi, dist = grid.find_nearest_gpi(
                    lon, lat, max_dist=max_dist
                )
                if np.isinf(dist):
                    # no other point found in range, currently this is handled
                    # by returning None
                    other_dataframe = None
                else:
                    other_dataframe = self.read_other(other_name, other_gpi)

            if other_dataframe is not None:
                other_dataframes[other_name] = other_dataframe
        return other_dataframes

def flatten(seq):
    eltl = []
    for elt in seq:
        t = type(elt)
        if t is tuple or t is list:
            for elt2 in flatten(elt):
                eltl.append(elt2)
        else:
            eltl.append(elt)
    return eltl

def get_result_combinations(ds_dict, n=2):
    """
    Get all possible combinations dataset columns

    Parameters
    ----------
    ds_dict: dict
       Dict of lists containing the dataset names as keys and a list of the
       columns to read from the dataset as values.
    n: int
        Number of datasets for combine with each other.
        If n=2 always two datasets will be combined into one result.
        If n=3 always three datasets will be combined into one results and
        so on.
        n has to be <= the number of total datasets.

    Returns
    -------
    results_names : list of tuples
        Containing all possible combinations of
        (dataset_x.column, dataset_y.column)
        for all datasets in ds_dict
    """
    combis = []
    for key in ds_dict:
        combis.extend(get_result_names(ds_dict, key, n=n))
    return sorted(list(set(combis)))

def get_result_names(ds_dict, refkey, n=2):
    """
    Return result names based on all possible combinations based on a
    reference dataset.

    Parameters
    ----------
    ds_dict: dict
       Dict of lists containing the dataset names as keys and a list of the
       columns to read from the dataset as values.
    refkey: string
       dataset name to use as a reference
    n: int
        Number of datasets for combine with each other.
        If n=2 always two datasets will be combined into one result.
        If n=3 always three datasets will be combined into one results and
        so on.
        n has to be <= the number of total datasets.

    Returns
    -------
    results_names : list of tuples
        Containing all combinations of
        (referenceDataset.column, otherDataset.column)
    """
    results_names = []

    ref_columns = []
    for column in ds_dict[refkey]:
        ref_columns.append((refkey, column))

    other_columns = []
    other_names = list(ds_dict)
    del other_names[other_names.index(refkey)]
    for other in sorted(other_names):
        for column in ds_dict[other]:
            other_columns.append((other, column))

    for comb in itertools.product(
        ref_columns, itertools.combinations(other_columns, n - 1)
    ):
        results_names.append(comb)

    # flatten to one level and remove those that do not have n unique
    # datasets
    results_names = flatten(results_names)

    # iterate in chunks of n*2 over the list
    result_combos = []
    for chunk in [
        results_names[pos: pos + n * 2]
        for pos in range(0, len(results_names), n * 2)
    ]:
        combo = []
        datasets = chunk[::2]
        columns = chunk[1::2]
        # if datasets are compared to themselves then don't include the
        # combination
        if len(set(datasets)) != n:
            continue
        for dataset, column in zip(datasets, columns):
            combo.append((dataset, column))
        result_combos.append(tuple(sorted(combo)))

    return result_combos


import pandas as pd
import numpy as np
# print(pd.Series([10,9,8,7,6]))

#serie con columna de indexacion
sr = pd.Series([10,9,8,7,6])

# print(sr)

# #para visualizarlo como array
# print(sr.values)

# #para obtener un resumen desde los indices
# print(sr.index)

# #dimensionalidad del objeto
# print(sr.shape)

# #para seleccionar un elemento
# print(sr[3])

# #para seleccionar distintos elementos, estos se mostraran segun la seleccion del indice
# print(sr[[0,4,2]])

# sr = pd.Series([10,9,8,7,6], index=["a","b","c","d","e"])

# # print(sr)

# #seleccion de rangos
# print(sr["a":"c"])

###------------ DICCIONARIO ------------###
dictionario = {
    "CO": 100,
    "MX": 200,
    "AR": 300,
    "CL": 400,
}

# # print(dictionario)

# #keys del diccionario
# print(dictionario.keys())

# #values del diccionario
# print(dictionario.values())

sr = pd.Series(dictionario, index=["CO","MX","PE"])
# print(sr)

#funciones
#isnull()
#notnull()

np.nan

print(sr.isnull())


# import the necessary packages
import pickle
import cv2
from rgbhistogram import RGBHistogram
from moviebox import find_box

def index_movie(inputFile, outputFile):
	# construct the argument parser and parse the arguments
	# ap = argparse.ArgumentParser()
	# ap.add_argument("-i", "--input", required = True,
	# 	help = "Path to the movie to be indexed")
	# ap.add_argument("-o", "--output", required = True,
	# 	help = "Path to where the computed index will be stored")
	# args = vars(ap.parse_args())

	# initialize the index dictionary to store our our quantifed
	# images, with the 'key' of the dictionary being the image
	# filename and the 'value' our computed features
	index = {}

	# initialize our image descriptor -- a 3D RGB histogram with
	# 8 bins per channel
	desc = RGBHistogram([8, 8, 8])

	cap = cv2.VideoCapture(inputFile)
	index[-1] = cap.get(cv2.CAP_PROP_FPS)
	count = 0

	x, y, w, h = find_box(inputFile)

	while cap.isOpened():
		ret, frame = cap.read()
		if ret:
		    # load the image, describe it using our RGB histogram
			# descriptor, and update the index
			features = desc.describe(frame[y:y+h, x:x+w])
			index[count] = features
			count = count + 1
		else:
			break

# we are now done indexing our image -- now we can write our
# index to disk
	f = open(outputFile, "wb")

	f.write(pickle.dumps(index))
	f.close()
	return index


import numpy as np
import matplotlib.pyplot as plt

plt.style.use('bmh')

R = 1
k = np.linspace(-20,20,10000)

def w(k,R):
    res = np.where(k==0,2*R,2*np.sin(k*R)/k)
    fwhm = FWHM(res,k)
    return res,fwhm

def FWHM(w,k):
    half_max = w.max()/2
    id_half_max = np.argmin(np.abs(w-half_max)) # first id at half max
                                        # this gives k value on negative side
    k_value = np.abs(k[id_half_max])
    return [[-k_value,k_value],half_max]

w,fwhm = w(k,R)
width = np.abs(fwhm[0][1]-fwhm[0][0])
print('The full width at half max: FWHM = {:.2f}'.format(width))

fig,ax = plt.subplots()
ax.plot(k,w)
#ax.annotate(s='FWHM',xy=(fwhm[0][0],fwhm[1]),xytext=(fwhm[0][1],fwhm[1]),arrowprops=dict(arrowstyle='<->'))
ax.arrow(fwhm[0][0],fwhm[1],width,0,width=0.01)# not so fancy, but does the trick
ax.set_xlabel('k')
ax.set_ylabel(r'$\tilde{W}(k)$')
ax.set_title('Fourier Transformed Top-hat Smoothing Function in 1D')
fig.savefig('window_func.pdf')
plt.show()


import os
import glob
import json
import datetime
import cv2
from tqdm.auto import tqdm

def categories2coco(data_root):
    categories = []
    cat_id = 0

    with open(os.path.join(data_root, 'classes.txt')) as cls_file:
        lines = cls_file.readlines()

        for line in lines:
            line = line.strip()

            # category name
            cat_name = line.split(',')[-1]

            # coco categories format
            categories.append({
                'id' : cat_id,
                'name' : cat_name,
            })

            cat_id += 1

    return categories

def get_coco_images(img_id, img_path):
    # date captured
    date_captured = os.path.getmtime(img_path)
    date_captured = datetime.datetime.fromtimestamp(date_captured).strftime('%Y-%m-%d %H:%M:%S')

    # file name
    file_name = '/'.join(img_path.replace('\\', '/').split('/')[-2:])

    # images
    # width & height
    img = cv2.imread(img_path)
    img_h, img_w, _ = img.shape

    coco_image = {
        'id' : img_id,
        'width' : img_w,
        'height' : img_h,
        'file_name' : file_name,
        'date_captured' : date_captured
    }

    return coco_image

def get_coco_bbox(labelme_bbox):
    xs = [labelme_bbox[i] for i in range(0, 8, 2)]
    ys = [labelme_bbox[i] for i in range(1, 8, 2)]

    x_min = min(xs)
    y_min = min(ys)
    x_max = max(xs)
    y_max = max(ys)

    w = x_max - x_min
    h = y_max - y_min

    coco_bbox = [x_min, y_min, w, h]

    return coco_bbox

def train2coco(train_path):
    ISCROWD = 0

    images_path = sorted(glob.glob(os.path.join(train_path, '*.png')))
    annotations_path = sorted(glob.glob(os.path.join(train_path, '*.txt')))

    coco_images = []
    coco_annotations = []
    ann_id = 0

    print('converting train data to COCO format...')
    for img_id, (img_path, ann_path) in enumerate(zip(tqdm(images_path), annotations_path)):
        # coco images format
        coco_image = get_coco_images(img_id, img_path)
        coco_images.append(coco_image)

        # annotations
        with open(ann_path, 'r') as ann_file:
            lines = ann_file.readlines()

            for line in lines:
                line = line.strip()

                # category_id
                category_id = int(float(line.split(' ')[0]))

                # bbox
                labelme_bbox = list(map(lambda x : float(x), line.split(' ')[1:]))
                coco_bbox = get_coco_bbox(labelme_bbox)

                # area
                bbox_w = coco_bbox[2]
                bbox_h = coco_bbox[3]
                area = bbox_w * bbox_h

                # coco annotations format
                coco_annotations.append({
                    'id' : ann_id,
                    'image_id' : img_id,
                    'category_id' : category_id,
                    'area' : area,
                    'bbox' : coco_bbox,
                    'iscrowd' : ISCROWD,
                })

                ann_id += 1

    return coco_images, coco_annotations

def test2coco(test_path):
    images_path = sorted(glob.glob(os.path.join(test_path, '*.png')))

    coco_images = []

    print('converting test data to COCO format...')
    for img_id, img_path in enumerate(tqdm(images_path)):
        # coco images format
        coco_image = get_coco_images(img_id, img_path)
        coco_images.append(coco_image)

    return coco_images

def save_coco(
    coco_path,
    categories,
    images,
    annotations=[]
):
    coco = {
        'categories' : categories,
        'images' : images,
        'annotations' : annotations
    }

    if annotations:
        file_name = 'train.json'
    else:
        file_name = 'test.json'

    print(f"saving '{file_name}'...")
    with open(os.path.join(coco_path, file_name), 'w') as coco_file_name:
        json.dump(coco, coco_file_name, indent=2)

def convert2coco(data_root):
    coco_path = os.path.join(data_root, 'coco/')
    train_path = os.path.join(data_root, 'images/')
    test_path = os.path.join(data_root, 'test/')

    # coco 데이터가 저장될 directory
    os.makedirs(coco_path, exist_ok=True)

    # coco categories format
    categories = categories2coco(data_root)

    # convert train data to coco format & save
    train_images, train_annotations = train2coco(train_path)
    save_coco(
        coco_path,
        categories,
        train_images,
        train_annotations
    )
    # convert test data to coco format & save
    test_images = test2coco(test_path)
    save_coco(
        coco_path,
        categories,
        test_images
    )

if __name__ == '__main__':
    import argparse
    import sys

    sys.path.append('..')

    from utils import rename_folder

    parser = argparse.ArgumentParser(
        description='convert labelme txt format to COCO json format.'
    )
    parser.add_argument(
        '-d',
        '--data_root',
        dest='data_root',
        default='../../data/',
        help='input data root directory.',
    )
    args = parser.parse_args()

    data_root = args.data_root

    # data 폴더 내에 images 폴더가 존재하지 않는다면, train 폴더명을 images로 변경
    if 'images' not in os.listdir(data_root):
        rename_folder.train2images(data_root)

    convert2coco(data_root)


# for clean text
import pymorphy2 as pm
import re
import numpy as np

# for excel r/w
import xlrd, xlwt
from pymysql import NULL

class Excel:

    @staticmethod
    def clean_text(text):
        text = text.replace("\\", " ").replace(u"╚", " ").replace(u"╩", " ")
        text = text.lower()

        text = text.replace("добрый день", " ").replace("добрый вечер", " ").replace("доброе утро", " ")
        text = text.replace("день добрый", " ").replace("утро доброе", " ").replace("вечер добрый", " ")
        text = text.replace("доброго времени суток", " ").replace("здравствуйте", " ").replace("с уважением", " ")

        text = re.sub('\-\s\r\n\s{1,}|\-\s\r\n|\r\n', '', text)  # deleting newlines and line-breaks
        text = re.sub('[.,:;_%©?*,!@#$%^&()\d]|[+=]|[[]|[]]|[/]|"|\s{2,}|-', ' ', text)  # deleting symbols
        text = " ".join(pm.MorphAnalyzer().parse(np.unicode(word))[0].normal_form for word in text.split())
        text = ' '.join(word for word in text.split() if len(word) > 3)

        return text

    @staticmethod
    def db_to_excel(self, begin_data, end_data ):
        # coding: utf-8
        from sqlalchemy import create_engine
        import pymysql
        import pandas as pd

        # print('Запускаю скрипт')
        conn = create_engine('mysql+pymysql://login:password,M1@10.1.10.5/otrs')
        # print('Соединился с базой')
        query = """SELECT
        ticket.id AS ticket_id,
        ticket.create_time as ticket_create_time,
        ticket.queue_id AS ticket_queue_id,
        ticket_queue.name AS ticket_queue_name,
        ticket.service_id AS ticket_service_id,
        service.name AS ticket_service_name,
        article.a_from AS article_a_from,
        article.a_to AS article_a_to,
        article.a_subject AS article_a_subject,
        article.a_body AS article_a_body
        FROM otrs.ticket AS ticket
        LEFT JOIN otrs.ticket_history AS ticket_history ON ticket.id = ticket_history.ticket_id
        LEFT JOIN otrs.queue AS ticket_queue ON ticket_queue.id = ticket.queue_id
        LEFT JOIN otrs.queue AS ticket_history_queue ON ticket_history_queue.id = ticket_history.queue_id
        LEFT JOIN otrs.service AS service ON service.id = ticket.service_id
        LEFT JOIN otrs.ticket_history_type AS ticket_history_type ON ticket_history_type.id = ticket_history.history_type_id
        LEFT JOIN otrs.users AS users_create_by ON users_create_by.id = ticket_history.create_by
        LEFT JOIN otrs.users AS users_change_by ON users_change_by.id = ticket_history.change_by
        LEFT JOIN otrs.users AS users_owner_id ON users_owner_id.id = ticket_history.owner_id
        INNER JOIN otrs.article AS article ON article.id = ticket_history.article_id
        LEFT JOIN otrs.ticket_state AS ticket_state ON ticket_state.id = ticket_history.state_id
        WHERE ticket.create_time BETWEEN '""" + begin_data + """ 0:00:00' AND '""" + end_data + """ 23:59:59'
        AND ticket_history.history_type_id = 12
        AND users_create_by.last_name <> 'Zabbix'
        AND ticket.queue_id <> 3
        AND ticket.ticket_state_id IN (2,3)"""

        # print('Запускаю запрос:')
        df = pd.read_sql(query, conn)
        # print('Выполнил запрос')
        df.to_excel(r'd:/tickets.xlsx', index=False)
        # print('готово')

        return df.shape[0]

    @staticmethod
    def excel_to_db(self):
        # открываем файл
        doc = xlrd.open_workbook('./tickets.xlsx')

        # выбираем активный лист
        sheet = doc.sheet_by_index(0)

        for i in range(0, sheet.nrows):
            print(i)
            if (sheet.row_values(i)[4] == ''):
                serv_id = NULL
            else:
                serv_id = round(sheet.row_values(i)[4])

            if (sheet.row_values(i)[5] == ''):
                serv_name = NULL
            else:
                serv_name = '"' + sheet.row_values(i)[5].replace('\\', '\\\\').replace('"', '\\"') + '"'

            stmt = "INSERT INTO {database}.{table} " \
                   "(ticket_id, ticket_create_time, ticket_queue_id, " \
                   "ticket_queue_name, ticket_service_id, ticket_service_name, article_a_from, article_a_to, " \
                   "article_a_subject, article_a_body) " \
                   "VALUES ({ticket_id}, {ticket_create_time}, {ticket_queue_id}, {ticket_queue_name}, " \
                   "{ticket_service_id}, {ticket_service_name}, {article_a_from}, {article_a_to}, " \
                   "{article_a_subject}, {article_a_body})".format(
                database=self.dbinfo['database'],
                table=self.dbinfo['table'],
                ticket_id=round(sheet.row_values(i)[0]),
                ticket_create_time='"' + str(
                    xlrd.xldate.xldate_as_datetime(sheet.row_values(i)[1], doc.datemode)) + '"',
                ticket_queue_id=round(sheet.row_values(i)[2]),
                ticket_queue_name='"' + sheet.row_values(i)[3].replace('\\', '\\\\').replace('"', '\\"') + '"',
                ticket_service_id=serv_id,
                ticket_service_name=serv_name,
                article_a_from='"' + sheet.row_values(i)[6].replace('\\', '\\\\').replace('"', '\\"') + '"',
                article_a_to='"' + sheet.row_values(i)[7].replace('\\', '\\\\').replace('"', '\\"') + '"',
                article_a_subject='"' + sheet.row_values(i)[8].replace('\\', '\\\\').replace('"', '\\"') + '"',
                article_a_body='"' + sheet.row_values(i)[9].replace('\\', '\\\\').replace('"', '\\"') + '"'
            )

            print('Запускаю запрос')
            con = self.get_connection()
            cur = con.cursor()
            cur.execute(stmt)
            con.commit()
            print('Выполнил запрос')


import os

class Setup:
    def __init__(self) -> None:
        self.__createWhiteBackgroundIcon()

    def __createWhiteBackgroundIcon(self) -> None:
        """ Create an icon with white background instead of transparency """

        projectDir = os.path.split(__file__)[0]
        buildDir = os.path.join(projectDir, "build")
        iconPath = os.path.join(projectDir, "icon.png")
        whiteIconPath = os.path.join(buildDir, "icon_white.png")

        if os.path.exists(whiteIconPath): return
        print("Creating an icon with white background...")
        from PIL import Image

        if not os.path.exists(buildDir):
            os.mkdir(buildDir)

        iconImg = Image.open(iconPath)
        iconImg.load()

        whiteImg = Image.new("RGB", iconImg.size, (239, 239, 239))
        whiteImg.paste(iconImg, mask=iconImg.split()[3])
        whiteImg.save(whiteIconPath)

        iconImg.close()
        whiteImg.close()

if __name__ == "__main__":
    Setup()


import tensorflow as tf

class DMFLodel(tf.keras.Model):

    def __init__(self, model):
        super(DMFLodel, self).__init__()
        self.model = model

    def compile(self, optimizer, loss, metrics, class_occ, tau):
        super(DMFLodel, self).compile(optimizer=optimizer, loss=loss, metrics=metrics)
        s = tf.constant([1e-8], tf.float32)
        class_occ_tensor = tf.constant(class_occ, tf.float32)
        # To not have zeros and generate nan
        self.class_occ = tf.math.maximum(class_occ_tensor, s)
        self.tau = tau

    def train_step(self, data):
        x, y = data

        def logit_calibrated_loss(y, logit, class_occ, tau):
            # tf.print("\n distrib ", class_occ, summarize=-1)
            cal_logit = tf.math.exp(
                logit - tf.repeat(
                    tf.expand_dims(tau * tf.math.pow(class_occ, -1 / 4), axis=0),
                    repeats=tf.shape(y)[0],
                    axis=0)
            )
            # y_logit = tf.gather(cal_logit, indices=y)
            # i_not_equal_y = tf.gather(cal_logit, indices=tf.expand_dims(y, axis=-1))
            y_logit = tf.gather(cal_logit, indices=y, axis=1, batch_dims=1)

            # extract true class logit needed in the denominator
            z = logit
            del_ind = y
            ones = tf.ones((tf.shape(z)[0], tf.shape(z)[1]), dtype=tf.bool)
            rows = tf.range(tf.shape(z)[0])
            del_idx = tf.stack([rows, tf.squeeze(tf.cast(del_ind, tf.int32), axis=1)], axis=1)
            updates = tf.fill([tf.shape(z)[0]], False)
            mask = tf.tensor_scatter_nd_update(ones, del_idx, updates)
            masked = tf.boolean_mask(z, mask)
            z_ntd = tf.reshape(masked, (tf.shape(z)[0], tf.shape(z)[1] - 1))

            denominator = y_logit + tf.reduce_sum(z_ntd, axis=-1, keepdims=True)
            calibrated_loss = -tf.math.log(tf.math.divide_no_nan(y_logit, denominator))

            loss = tf.reduce_mean(calibrated_loss)
            tf.print(loss)
            return loss
            # return logit

        with tf.GradientTape() as tape:
            y_pred = self.model(x, training=True)  # Forward pass
            loss_ce = logit_calibrated_loss(y, y_pred, self.class_occ, self.tau)

        # Compute gradients
        trainable_vars = self.model.trainable_variables
        gradients = tape.gradient(loss_ce, trainable_vars)
        # Update weights
        self.optimizer.apply_gradients(zip(gradients, trainable_vars))
        # Update metrics (includes the metric that tracks the loss)
        self.compiled_metrics.update_state(y, y_pred)

        result = {m.name: m.result() for m in self.metrics}
        return result


import torch
import numpy as np
import importlib

# Helpers when setting up training

def importNet(net):
    # this is actually function as string value in way of splitting and regrouping
    # to make same string values are separated
    # this function be used at pose.py make_network() and make_network() as init() in train.py
    # also has code for decreasing the learning rate after a iteration number
    t = net.split('.')
    path, name = '.'.join(t[:-1]), t[-1]
    module = importlib.import_module(path)
    return eval('module.{}'.format(name))

def make_input(t, requires_grad=False, need_cuda = True):
    # used in pose.py
    # calculate the gradient and convert the data type to the cuda.LongTensor
    inp = torch.autograd.Variable(t, requires_grad=requires_grad)
    if need_cuda:
        inp = inp.cuda()
    return inp

def make_output(x):
    # make sure data is matrix and cpu data type
    if not (type(x) is list):
        return x.cpu().data.numpy()
    else:
        return [make_output(i) for i in x]

# Image processing functions

def inv_mat(mat):
    # compute Moore-Penrose inverse matrix
    ans = np.linalg.pinv(np.array(mat).tolist() + [[0,0,1]])
    return ans[:2]

def get_transform(center, scale, res, rot=0):
    # used in dp.py & test.py
    # Generate transformation matrix
    h = 200 * scale
    t = np.zeros((3, 3))
    t[0, 0] = float(res[1]) / h
    t[1, 1] = float(res[0]) / h
    t[0, 2] = res[1] * (-float(center[0]) / h + .5)
    t[1, 2] = res[0] * (-float(center[1]) / h + .5)
    t[2, 2] = 1
    if not rot == 0:
        # defining rotation matrix
        rot = -rot # To match direction of rotation from cropping
        rot_mat = np.zeros((3,3))
        rot_rad = rot * np.pi / 180
        sn,cs = np.sin(rot_rad), np.cos(rot_rad)
        rot_mat[0,:2] = [cs, -sn]
        rot_mat[1,:2] = [sn, cs]
        rot_mat[2,2] = 1
        # Need to rotate around center
        t_mat = np.eye(3)
        t_mat[0,2] = -res[1]/2
        t_mat[1,2] = -res[0]/2
        t_inv = t_mat.copy()
        t_inv[:2,2] *= -1
        t = np.dot(t_inv,np.dot(rot_mat,np.dot(t_mat,t)))
    return t

def kpt_affine(kpt, mat):
    # used in dp.py
    kpt = np.array(kpt)
    shape = kpt.shape
    kpt = kpt.reshape(-1, 2)
    # concatenate along Y-axis
    return np.dot(np.concatenate((kpt, kpt[:, 0:1]*0+1), axis=1), mat.T).reshape(shape)

def resize(im, res):
    # used in test.py
    import cv2
    return np.array([cv2.resize(im[i],res) for i in range(im.shape[0])])


from flask import Blueprint, jsonify
from flask_restful import reqparse
from werkzeug.exceptions import BadRequest

import requests
import settings
import logging

deposit_mod = Blueprint('deposit_mod', __name__)
LOGGER = logging.getLogger('root')

@deposit_mod.route('/api/deposit')
def deposit():
    parser = reqparse.RequestParser()
    parser.add_argument('account', required=True)
    parser.add_argument('asset_code', required=True)
    parser.add_argument('anchor', required=True)
    parser.add_argument('email', required=True)
    parser.add_argument('Authorization', required=True, location='headers')

    try:
        request_args = parser.parse_args()
    except BadRequest:
        err_msg = 'Not enough arguments provided'
        LOGGER.error(err_msg)
        return jsonify({'error': err_msg, 'status': 400})

    account_pubkey = request_args['account']
    asset_code = request_args['asset_code']
    anchor_name = request_args['anchor']
    anchor_name = settings.ANCHORS[anchor_name]
    account_email = request_args['email']
    token = request_args['Authorization']

    url = anchor_name['TRANSFER_SERVER'] + '/deposit'
    params = {
        'account': account_pubkey,
        'asset_code': asset_code,
        'email_address': account_email,
    }
    headers = {
        'Authorization': token,
    }

    try:
        response = requests.get(url, params=params, headers=headers)
    except requests.exceptions.RequestException as error:
        LOGGER.error(error)
        return jsonify({'status': 400, 'error': str(error)})

    deposit_info = response.json()
    return jsonify({'response': deposit_info, 'status': response.status_code})


import os, json
layout_file = '/tmp/poco_layout.json'
decorations_file = '/tmp/poco_decoration.json'

def write(layout):
	with open(layout_file, 'w') as f:
		json.dump(to_json(layout), f, indent=True)

def write_decorations(decoration_map):
	state_json = {}
	for k in decoration_map.keys():
		state_json[k] = decoration_map[k]
	with open(decorations_file, 'w') as f:
		json.dump(state_json, f, indent=True)

def read_layout():
	if os.path.exists(layout_file):
		with open(layout_file, 'r') as f:
			try:
				return json.load(f)
			except json.decoder.JSONDecodeError:
				return None
	return None

def read_decorations():
	if os.path.exists(decorations_file):
		with open(decorations_file, 'r') as f:
			try:
				return json.load(f)
			except json.decoder.JSONDecodeError:
				return None
	return None

def to_json(layout):
	stack_state = {}
	state = {
		'stack_state': stack_state,
		'nmaster': layout.monitor.nmaster, 'mfact': layout.monitor.mfact,
		'function': layout.function_key}
	for w in layout.windows.buffers:
		w_id = w.get_xid()
		key = str(w_id)
		if key not in stack_state:
			stack_state[key] = {}
		stack_state[key]['name'] = w.get_name()
		stack_state[key]['stack_index'] = layout.stack.index(w_id) if w_id in layout.stack else -1

	for client_key in list(stack_state.keys()):
		if client_key not in map(lambda x: str(x.get_xid()), layout.windows.buffers):
			del stack_state[client_key]

	return state


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Please note that the function 'make_request' is provided for your reference only.
# You will not be able to to actually use it from within the Udacity web UI.
# Your task is to process the HTML using BeautifulSoup, extract the hidden
# form field values for "__EVENTVALIDATION" and "__VIEWSTATE" and set the approprate
# values in the data dictionary.
# All your changes should be in the 'extract_data' function
from bs4 import BeautifulSoup
import requests
import json

html_page = "page_source.html"

def extract_data(page):
    data = {"eventvalidation": "",
            "viewstate": ""}
    with open(page, "r") as html:
        soup = BeautifulSoup(html)
        forms = soup.findAll("form", {"id" : "form1"})
        if len(forms) == 1:
            form = forms[0]
            hiddens = form.findAll("input", {"type": "hidden"})
            for hidden in hiddens:
                hidden_name = hidden["name"]
                # __EVENTVALIDATION -> eventvalidation
                data_key = hidden_name[2:].lower()
                if data_key in data:
                    data[data_key] = hidden["value"]
                # optionally:
                # ev = soup.find(id="__EVENTVALIDATION")
                # data["eventvalidation"] = ev["value"]

        else:
            raise
        # print data

    return data

def make_request(data):
    eventvalidation = data["eventvalidation"]
    viewstate = data["viewstate"]

    r = requests.post("http://www.transtats.bts.gov/Data_Elements.aspx?Data=2",
                    data={'AirportList': "BOS",
                          'CarrierList': "VX",
                          'Submit': 'Submit',
                          "__EVENTTARGET": "",
                          "__EVENTARGUMENT": "",
                          "__EVENTVALIDATION": eventvalidation,
                          "__VIEWSTATE": viewstate
                    })

    return r.text

def test():
    data = extract_data(html_page)
    assert data["eventvalidation"] != ""
    assert data["eventvalidation"].startswith("/wEWjAkCoIj1ng0")
    assert data["viewstate"].startswith("/wEPDwUKLTI")

test()


#!/usr/bin/env python3
"""
Library: Solve 9 Letter Word Puzzle.
"""

from collections import Counter
from re import match

def is_valid_letters(letters: str) -> bool:
    """Must have 9 alphabetic, lowercase characters.

    Parameters
    ----------

    letters : str
        the letters that words can be made from

    Returns
    -------

    bool
        true if letters are lowercase, false otherwise
    """
    return bool(match(r"^[a-z]{9}$", letters))

def is_valid_word(size: int, letters: list[str], word: str) -> bool:
    """Check that a dictionary word only contains valid letters
    and is of the correct size.

    The mandatory character is chosen as the first letter in the list of
    letters argument.

    Parameters
    ----------

    size : int
        minimum word size
    letters : str
        the letters that words can be made from
    word : str
        the dictionary word to check

    Returns
    -------

    bool
        true if word is valid, false otherwise
    """
    # word of the correct size
    if not size <= len(word) <= 9:
        return False

    # mandatory letter must be in word
    if letters[0] not in word:
        return False

    # check if all letters in the word can be formed from the letters list
    letter_counts = Counter(letters)
    word_counts = Counter(word)
    return all(word_counts[letter] <= letter_counts[letter] for letter in word_counts)


from dock_host import *

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~ Definitions
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

class dock_host_sash(dock_host):
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #~ Constants / Variables / Etc.
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    defaultSettings = dock_host .defaultSettings.copy()
    defaultSettings.update({
        })

    defaultStyleSettings = dock_host .defaultStyleSettings.copy()
    defaultStyleSettings.update({
        })

    sashWindows = wxClasses(wx.SashWindow, wx.SashLayoutWindow)

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #~ Definitions
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    def createWidget(self, parentObj):
        obj = dock_host.createWidget(self, parentObj)
        obj.sash = self.findXMLParentObjectOfType(self.sashWindows)

        hideEmpty = obj.getHideEmpty()
        if hideEmpty and isinstance(hideEmpty, (int, bool)):
            obj.setHideEmpty(obj.sash)

        obj.onLayoutComplete.add(lambda obj: obj.sash.SendSizeEvent())
        return obj


class Solution:
    # def rotate1(self, nums, k):
    #     """
    #     :type nums: List[int]
    #     :type k: int
    #     :rtype: void Do not return anything, modify nums in-place instead.
    #     """
    #     if len(nums) == 0:
    #         return nums
    #     k_new = k % len(nums)
    #     # 这种方法是O(n^2)
    #     for i in range(k_new):
    #         tmp = nums[len(nums) - 1]
    #         i = 0
    #         for i in range(len(nums) - 1, 0, -1):
    #             nums[i] = nums[i - 1]
    #         nums[0] = tmp

    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        # 时间复杂度O(n)
        k_new = k % len(nums)
        if k_new == 0:
            return
        last_idx = len(nums) - 1
        total = len(nums)
        n = 0
        idx = last_idx
        temp = nums[last_idx]
        while True:
            idx_0 = idx - k_new
            if idx_0 < 0:
                idx_0 += len(nums)
                if idx_0 == last_idx:
                    nums[idx] = temp
                    n += 1
                    if n < total:
                        last_idx = last_idx - 1
                        idx = last_idx
                        temp = nums[last_idx]
                        continue
                    else:
                        break
            nums[idx] = nums[idx_0]
            idx = idx_0
            n += 1
        return nums

if __name__ == '__main__':
    l = [1]  # [1, 2, 3, 4, 5, 6,7]
    s = Solution()
    s.rotate(l, 0)
    print(l)


import socket, sys, argparse

server = input("Please enter server IP [default = 192.168.4.3]: ")
server = server or "192.168.4.3"

def echo_client(port):
	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	server_address = (server, port)
	print("Connecting to %s port %s" % server_address)
	sock.connect(server_address)

	try:
		message = "Test message. This will be echoed"
		print("Sending %s" % message)
		sock.sendall(message.encode("ascii"))
		amount_received = 0
		amount_expected = len(message)
		while amount_received < amount_expected:
			data = sock.recv(16)
			amount_received += len(data)
			print("Received: %s" % data.decode("ascii"))
	except socket.error:
		print("Socket error")
	except Exception:
		print("Other exception")
	finally:
		print("Closing connection to the server")
		sock.close()

if __name__ == '__main__':
	parser = argparse.ArgumentParser(description="Socket Server Example")
	parser.add_argument('--port', action="store", dest="port", type=int, required=True)
	given_args = parser.parse_args()
	port = given_args.port
	echo_client(port)


from math import gcd

value = '''<x=16, y=-11, z=2>
<x=0, y=-4, z=7>
<x=6, y=4, z=-10>
<x=-3, y=-2, z=-4>'''

def string_to_list(value):
  value = value.split()
  ret = [[]]

  for val in value:
    start = val.index('=')
    try:
      stop = val.index(',')
    except ValueError:
      stop = val.index('>')

    if len(ret[-1]) < 3:
      ret[-1].append(int(val[start+1:stop]))
    else:
      ret.append([int(val[start+1:stop])])

  return ret

class Moon():
  def __init__(self, x, y, z):
    self.x = x
    self.y = y
    self.z = z
    self.dx = 0
    self.dy = 0
    self.dz = 0

  def gravity_x(self, rest):
    for moon in rest:
      if self.x < moon.x:
        self.dx += 1
      elif self.x > moon.x:
        self.dx -= 1

  def gravity_y(self, rest):
    for moon in rest:
      if self.y < moon.y:
        self.dy += 1
      elif self.y > moon.y:
        self.dy -= 1

  def gravity_z(self, rest):
    for moon in rest:
      if self.z < moon.z:
        self.dz += 1
      elif self.z > moon.z:
        self.dz -= 1

  def gravity(self, rest):
    self.gravity_x(rest)
    self.gravity_y(rest)
    self.gravity_z(rest)

  def velocity(self):
    self.x += self.dx
    self.y += self.dy
    self.z += self.dz

  def energy(self):
    return (abs(self.x) + abs(self.y) + abs(self.z)) * (abs(self.dx) + abs(self.dy) + abs(self.dz))

def calculate1(value, repeat):
  value = string_to_list(value)
  value = [Moon(*val) for val in value]

  for i in range(repeat):
    for inx, moon in enumerate(value):
      moon.gravity(value[:inx] + value[inx+1:])
    for moon in value:
      moon.velocity()
  return sum([moon.energy() for moon in value])

def calculate2(value):
  value = string_to_list(value)
  beginning = value
  value = [Moon(*val) for val in value]
  i = 0
  x = 0
  y = 0
  z = 0

  while True:
    for inx, moon in enumerate(value):
      moon.gravity_x(value[:inx] + value[inx+1:])
    for moon in value:
      moon.velocity()
    i += 1
    check = [[moon.x, moon.y, moon.z] for moon in value]
    check_vel = [moon.dx for moon in value]
    if check == beginning and not any(check_vel):
      x = i
      break
  i = 0

  while True:
    for inx, moon in enumerate(value):
      moon.gravity_y(value[:inx] + value[inx+1:])
    for moon in value:
      moon.velocity()
    i += 1
    check = [[moon.x, moon.y, moon.z] for moon in value]
    check_vel = [moon.dy for moon in value]
    if check == beginning and not any(check_vel):
      y = i
      break
  i = 0

  while True:
    for inx, moon in enumerate(value):
      moon.gravity_z(value[:inx] + value[inx+1:])
    for moon in value:
      moon.velocity()
    i += 1
    check = [[moon.x, moon.y, moon.z] for moon in value]
    check_vel = [moon.dz for moon in value]
    if check == beginning and not any(check_vel):
      z = i
      break

  x_and_y = int((x*y) / gcd(x, y))
  return int((x_and_y*z) / gcd(x_and_y, z))

print(calculate1(value, 1000), calculate2(value))


import pandas as pd
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt

# Load the transaction data into a pandas dataframe
df = pd.read_csv('transaction_data.csv')

# Preprocess the data by scaling numerical variables
scaler = StandardScaler()
df_scaled = scaler.fit_transform(df)

# Choose an appropriate number of clusters using the elbow method
inertias = []
for k in range(1, 11):
    kmeans = KMeans(n_clusters=k, random_state=42)
    kmeans.fit(df_scaled)
    inertias.append(kmeans.inertia_)

plt.plot(range(1, 11), inertias)
plt.title('Elbow Method')
plt.xlabel('Number of Clusters')
plt.ylabel('Inertia')
plt.show()

# Fit the K-Means clustering model to the data and predict cluster labels
kmeans = KMeans(n_clusters=3, random_state=42)
kmeans.fit(df_scaled)
labels = kmeans.predict(df_scaled)

# Analyze the resulting clusters to identify distinct groups of customers with similar spending and purchase behavior
df['cluster'] = labels
print(df.groupby('cluster').mean())

# Visualize the clusters using scatter plots or other appropriate visualizations to gain insights into customer distribution and distinguish different segments
plt.scatter(df['total_amount'], df['num_items'], c=df['cluster'])
plt.title('Customer Segmentation')
plt.xlabel('Total Amount Spent')
plt.ylabel('Number of Items Purchased')
plt.show()


import whisper
import pyaudio
import wave
import os
import ffmpeg
import threading

from PIL import Image, ImageTk
from tkinter import Tk,Button, PhotoImage, Label

import openai
from elevenlabs import set_api_key
from elevenlabs import clone, generate, voices, play

from dotenv import load_dotenv

load_dotenv()
set_api_key(os.environ["ELEVEN_LABS_KEY"])
openai.api_key = os.environ["OPENAI_KEY"]

FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
CHUNK = 1024
RECORD_SECONDS = 7
WAVE_OUTPUT_FILENAME = "grabacion_temporal.wav"
MP3_OUTPUT_FILENAME = "grabacion_temporal.mp3"

voices = voices()
WAIFU_VOICE = voices[-1]

model = whisper.load_model("small")

def speech_to_text(audio_file:str):
    # load audio and pad/trim it to fit 30 seconds
    audio = whisper.load_audio(audio_file)
    audio = whisper.pad_or_trim(audio)

    # make log-Mel spectrogram and move to the same device as the model
    mel = whisper.log_mel_spectrogram(audio).to(model.device)

    # detect the spoken language
    _, probs = model.detect_language(mel)
    print(f"Detected language: {max(probs, key=probs.get)}")

    # decode the audio
    options = whisper.DecodingOptions(fp16 = False)
    result = whisper.decode(model, mel, options)
    # print the recognized text
    print(result.text)
    return result.text

def record_audio():
    audio = pyaudio.PyAudio()
    # configurar la grabación de audio
    stream = audio.open(format=FORMAT, channels=CHANNELS,
                        rate=RATE, input=True,
                        frames_per_buffer=CHUNK)

    print("Grabando audio...")
    # grabar audio en un archivo temporal
    frames = []
    for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        data = stream.read(CHUNK)
        frames.append(data)
    # cerrar el stream de audio
    stream.stop_stream()
    stream.close()
    audio.terminate()

    print("Grabación finalizada.")
    # guardar el archivo de audio temporal como archivo .wav
    waveFile = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
    waveFile.setnchannels(CHANNELS)
    waveFile.setsampwidth(audio.get_sample_size(FORMAT))
    waveFile.setframerate(RATE)
    waveFile.writeframes(b''.join(frames))
    waveFile.close()
    print("Archivo de audio temporal guardado como " + WAVE_OUTPUT_FILENAME)
    import ffmpeg
    (
        ffmpeg
        .input(WAVE_OUTPUT_FILENAME)
        .output(MP3_OUTPUT_FILENAME, format='mp3')
        .run()
    )

    print("Archivo de audio temporal convertido a " + MP3_OUTPUT_FILENAME)
    # eliminar el archivo temporal
    os.remove(WAVE_OUTPUT_FILENAME)
    print("Archivo de audio temporal eliminado")

def send_commands():
    record_audio()
    command = speech_to_text(MP3_OUTPUT_FILENAME)
    command = command.lower()
    os.remove(MP3_OUTPUT_FILENAME)
    if 'hola' in command and 'bianca' in command:
        run_chatgpt('Saluda de manera formal, presentandote como BIANCA, un asistente virtual potenciado por inteligencia artificial.')
    else:
        run_chatgpt(command)

def run_chatgpt(prompt:str):
    completion = openai.Completion.create(
        engine = "text-davinci-003",
        prompt = prompt,
        max_tokens = 2048
    )
    result = completion.choices[0].text
    audio = generate(text=result, voice=WAIFU_VOICE, model='eleven_multilingual_v1')

    play(audio)

class App(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.start()

    def callback(self):
        self.root.quit()

    def run(self):
        root = Tk()
        root.geometry('500x600')
        root.title('B.I.A.N.C.A')
        waifu_img = Image.open("imgs/waifu.png")
        test = ImageTk.PhotoImage(waifu_img)

        label1 = Label(image=test)
        label1.image = test
        label1.place(x=60,y=0)
        microphone_img = PhotoImage(file=r'imgs/microphone.png')
        microphone_img = microphone_img.subsample(4,4)
        btn_micro = Button(root,text='Click me',image=microphone_img,command=send_commands)
        btn_micro.place(x=150,y=425)
        root.mainloop()

if __name__ == '__main__':
    app = App()


from pyknp import Juman
jumanpp = Juman()

data = ["すもももももももものうち",
                            "井の中の蛙"]
wakachi = []
for d in data:
    # for mrph in result.mrph_list(): # 各形態素にアクセス
        # print("見出し:%s, 読み:%s, 原形:%s, 品詞:%s, 品詞細分類:%s, 活用型:%s, 活用形:%s, 意味情報:%s, 代表表記:%s" \
        #         % (mrph.midasi, mrph.yomi, mrph.genkei, mrph.hinsi, mrph.bunrui, mrph.katuyou1, mrph.katuyou2, mrph.imis, mrph.repname))
    r = [mrph.midasi for mrph in jumanpp.analysis(d).mrph_list()]
    r = " ".join(r)
    wakachi.append(r)
print(wakachi)

import jieba

data = ['真好吃耶', '不好意思我不對', '每天發技術文章']
wakachi = []
# 精確模式
for d in data:
    r = ' '.join(jieba.cut(d))
    wakachi.append(r)

print(wakachi)
# print('---------------')

# # 全模式
# for sentence in documents:
#     seg_list = jieba.cut(sentence, cut_all=True)
#     print(' '.join(seg_list))

# print('---------------')

# # 搜索引擎模式
# for sentence in documents:
#     seg_list = jieba.cut_for_search(sentence)
#     print('/'.join(seg_list))


import math
import os
import random
import re
import sys
sys.setrecursionlimit(10**8)

def componentsInGraph(gb, n):
    # Write your code here
    adj={}
    visited={}
    component=[]

    for i in range(1, 2*n+1):
        visited[i]=0
    for i in range(1, 2*n+1):
        adj[i]=[]
    for u, v in gb:
        adj[u].append(v)
        adj[v].append(u)
    def dfs(node, adj, component):
        component.append(node)
        visited[node]=1
        for i in adj[node]:
            if visited[i]==0:
                visited[i]=1
                dfs(i, adj, component)
        count=len(component)
        return count

    lst=[]
    for i in range(1, 2*n+1):
        if visited[i]==0:
            lst.append(dfs(i, adj, []))
    minm=0
    outlst=[]
    for i in lst:
        if i!=1:
            outlst.append(i)

    ans=[]
    ans.append(min(outlst))
    ans.append(max(outlst))
    return ans


# This code is prepared for knn method

import numpy as np
import random
import handle_data

def count_general_pre(y_true, y_pred, positive_value, negative_value, threshold_value):
    tp = 0
    fp = 0
    fn = 0
    for i in range(len(y_true)):
        if int(y_true[i]) == positive_value and y_pred[i] > threshold_value:
            tp += 1
        elif int(y_true[i]) == positive_value and y_pred[i] < threshold_value:
            fn += 1
        elif int(y_true[i]) == negative_value and y_pred[i] > threshold_value:
            fp += 1
    return tp, fp, fn

def count_top(y_true, y_pred, top):
    tp = 0
    exact = 0
    if top <= len(y_true):
        top_true = y_true[:top]
        len_exact = top
    else:
        top_true = y_true
        len_exact = len(y_true)
    length = len(top_true)
    len_pre = len(y_pred)
    for i in range(length):
        if top_true[i] in y_pred:
            tp += 1
            if i < len_pre:
                if top_true[i] == y_pred[i]:
                    exact += 1
    if len_pre == 0:
        group_top_pre = 0
        group_recall = 0
        group_top_exact_accuracy = 0
    else:
        group_top_pre = tp/len_pre
        group_recall = tp/len_exact
        group_top_exact_accuracy = exact/len_exact
    return group_top_pre, group_recall, group_top_exact_accuracy

def precision_recall(tp, fp, fn):
    if (tp+fp) == 0:
        precision = 0
    else:
        precision = tp / (tp + fp)
    if (tp+fn) == 0:
        recall = 0
    else:
        recall = tp / (tp + fn)
    return precision, recall

def general_test(test_data, test_label, model, positive_value, negative_value, threshold_value, record):
    general_predict = model.predict(test_data)
    general_tp, general_fp, general_fn = count_general_pre(test_label, general_predict, positive_value, negative_value, threshold_value)
    general_precision, general_recall = precision_recall(general_tp, general_fp, general_fn)
    general_accuracy = (len(test_label) - general_fp - general_fn) / len(test_label)
    # --------------------------------------------------------------------
    record.write("the general true positive is {0}\n".format(general_tp))
    record.write("the general false positive is {0}\n".format(general_fp))
    record.write("the general false negative is {0}\n".format(general_fn))
    general_tn = len(test_label) - general_fp - general_fn - general_tp
    record.write("the general true negative is {0}\n".format(general_tn))
    # --------------------------------------------------------------------
    record.write("the general precision is {0}\n".format(general_precision))
    record.write("the general recall is {0}\n".format(general_recall))
    record.write("the general accuracy is {0}\n".format(general_accuracy))
    record.write("-------------------------------------------------------------------------------------------\n")

def record_middle_result(name, list, record):
    record.write(name)
    for i in list:
        record.write("{0:2d}\t".format(i))
    record.write('\n')

def record_rank_reference(reference, rank, predict_rank, record):
    t = [i for i in range(1,len(rank)+1)]
    record_middle_result('                      ', t, record)
    record_middle_result('the random order is   ', reference, record)
    record_middle_result('the true rank is      ', rank, record)
    record_middle_result('the predict rank is   ', predict_rank, record)

def group_test(Data, Label, Ds, Dl, num_of_train, model, top, all_group_top_precision, all_group_recall, all_group_top_exact_accuracy, record):
    for group_index_start in range(num_of_train, len(Ds)):
        group_start = Ds[group_index_start]
        length = Dl[group_index_start]
        group_end = group_start + length
        group_data = Data[group_start:group_end, :]
        group_label = Label[group_start:group_end]
        predict_result = model.predict(group_data)
        result = np.where(predict_result==1)
        result = result[0].tolist()
        group_rank = handle_data.exchange(group_label)
        group_top_precision, group_recall, group_top_exact_accuracy = count_top(group_rank, result, top)

        all_group_top_precision.append(group_top_precision)
        all_group_recall.append(group_recall)
        all_group_top_exact_accuracy.append(group_top_exact_accuracy)

        record.write("the group top precision is {0}\n".format(group_top_precision))
        record.write("the group recall is {0}\n".format(group_recall))
        record.write("the group top exact accuracy is {0}\n".format(group_top_exact_accuracy))
        record.write("-------------------------------------------------------------------------------------------\n")
    return all_group_top_precision, all_group_recall, all_group_top_exact_accuracy

def cal_average(all_group_top_precision, all_group_recall, all_group_top_exact_accuracy, record):
    totle = len(all_group_top_precision)
    average_group_top_precision = sum(all_group_top_precision)/totle
    average_group_recall = sum(all_group_recall)/totle
    average_group_top_exact_accuracy = sum(all_group_top_exact_accuracy)/totle

    # record.write("\nthe average group top precision is {0}\n".format(average_group_top_precision))
    record.write("the average group top precision is {0}\n".format(average_group_top_precision))
    record.write("the average group recall is {0}\n".format(average_group_recall))
    record.write("the average group top exact accuracy is {0}\n".format(average_group_top_exact_accuracy))

    # record.write("-------------------------------------------------------------------------------------------\n\n")


from viewAllTasks import view_all_tasks
from viewPendingTasks import view_pending_tasks
from createTask import create_new_task
def main():
    go = True
    while go:
        print("\nMini Todo List App\n")
        print("Enter 1 - View all tasks")
        print("Enter 2 - View pending tasks")
        print("Enter 3 - Create a new task")
        print("Enter 0 - Quit\n")
        answer = input("Please enter your choice: ")
        if answer == "1":
            view_all_tasks()
        elif answer == "2":
            view_pending_tasks()
        elif answer == "3":
            create_new_task()
        elif answer == "0":
            print("Good-Bye!!")
            break
        else:
            print("Invalid choice. Please enter a number between 0 and 3: ")
if __name__ == "__main__":
    main()


def read_input():
    row, col = [int(x) for x in input().split()]
    arr = [list(input()) for _ in range(row)]
    return arr

def print_output(obj):
    for i in obj:
        print(''.join(i))

def test_pos(obj, grid, row, col):
    for i in range(len(obj)):
        for j in range(len(obj[0])):
            if grid[row + i][col + j] != '.' and obj[i][j] != '.':
                return False
    return True

def place_at_pos(obj, grid, row, col):
    arr = grid
    for i in range(len(obj)):
        for j in range(len(obj[0])):
            if obj[i][j] != '.':
                arr[row + i][col + j] = obj[i][j]
    return arr

ob = read_input()
gr = read_input()

positions = []

for di in range(len(gr) - len(ob) + 1):
    for dj in range(len(gr[0]) - len(ob[0]) + 1):
        if test_pos(ob, gr, di, dj):
            positions.append((di, dj))

print(len(positions))

if len(positions) == 1:
    display = place_at_pos(ob, gr, positions[0][0], positions[0][1])
    print_output(display)


class ArthmeticProgression:

    def __init__(self, begin, step ,end =None):
        self.begin = begin
        self.step = step
        self.end = end

    def __iter__(self):
        result = type(self.begin + self.step)(self.begin)
        forever = self.end is None
        while forever or result < self.end:
            result += self.step
            yield result

if __name__ == '__main__':
    arthmethic = ArthmeticProgression(1, 0.5, 10)

    for i in iter(arthmethic):
        print(i)