from main.models import *
from main.stuff import *
from collections import defaultdict
import json
import pandas as pd
import os

class Logger:
    def __init__(self, path):
        self.path = path
        f = open(path, 'w')
        f.close() # erase file initially
        self.open = True
    def close(self):
        self.open = False
    def write(self,s):
        if self.open:
            with open(self.path, 'a', encoding='utf8') as f:
                f.write(s)
    def writeline(self,s):
        self.write(s+'\n')

class Comp:
    slippage = 0.005
    tax = 0.003
    def __init__(self, code):
        self.code = code
        self.comp = Company.objects.get(code=code)
        self.prices = self.comp.price_set.all()
        self.fundy = self.comp.fund_y_set.all()
        self.fundq = self.comp.fund_q_set.all()

    def validate(self, dfrom, dto, market):
        print('\rvalidate ' + self.code, end='')
        if self.code == '^KS11':
            return False
        if self.prices.all().count() == 0:
            return False
        if MyDate(self.prices.earliest('date').date) > dfrom:
            return False
        if MyDate(self.prices.latest('date').date) < dto:
            return False
        return True

    def get_fund_related_data(self, t, dataname, freq):
        try:
            if dataname == 'eps':
                return self.get_eps(t, freq)
            elif dataname == 'bps':
                return self.get_bps(t, freq)
            elif dataname == 'per':
                return self.get_per(t, freq)
            elif dataname == 'pbr':
                return self.get_pbr(t, freq)
            return None
        except Exception as e:
            return None

    def get_eps(self, t, freq):
        net_profit = self.get_recent_fund(t, 'net_profit', freq)
        shares = self.comp.shares
        return net_profit / shares

    def get_bps(self, t, freq):
        tot_capital = self.get_recent_fund(t, 'tot_capital', freq)
        shares = self.comp.shares
        return tot_capital / shares

    def get_per(self, t, freq):
        eps = self.get_eps(t, freq)
        per = self.get_recent_adjc(t) / eps
        return per

    def get_pbr(self, t, freq):
        bps = self.get_bps(t, freq)
        pbr = self.get_recent_adjc(t) / bps
        return pbr

    def get_recent_fund(self, t, index, freq):
        if freq == 'y' or freq == 'a':
            table = self.fundy
        else:
            table = self.fundq
        try:
            row = table.filter(date__lte=t).latest('date')
            ret = getattr(row, index)
            return ret * 100000000 # 단위가 억원
        except Exception as e:
            return None

    def get_adjc(self, t):
        try:
            return self.prices.get(date=t).adjclose
        except Exception as e:
            return None

    def get_recent_adjc(self, t):
        try:
            return self.prices.filter(date__lte=t).latest('date').adjclose
        except Exception as e:
            return None

    def get_buy_price(self, t):
        p = self.get_adjc(t)
        if p:
            return p*(1+Comp.slippage)
        return None

    def get_sell_price(self, t):
        p = self.get_adjc(t)
        if p:
            return p*(1-Comp.slippage-Comp.tax)
        return None

    def get_recent_sell_price(self, t):
        p = self.get_recent_adjc(t)
        if p:
            return p*(1-Comp.slippage-Comp.tax)
        return None

    def can_trade(self, t):
        return (self.get_adjc(t) != None)

    def __hash__(self):
        return hash(self.code)

    def __eq__(self, other):
        return self.code == other.code

    def __ne__(self, other):
        return not(self == other)

class Wallet:
    def __init__(self, cash, log):
        self.original_cash = cash
        self.cash = cash
        self.log = log
        self.stocks = defaultdict(lambda:0)  # dictionary from corp to amount of stocks
        self.history = pd.DataFrame()
        self.history['Corps'] = []

    def can_buy(self, t, corp):
        assert(corp.can_trade(t))
        p = corp.get_buy_price(t)
        return int(self.cash / p)
    def corp_value(self, t, corp):
        return corp.get_recent_sell_price(t) * self.stocks[corp]
    def get_total(self, t):
        ret = self.cash
        for key, value in self.stocks.items():
            sp = key.get_recent_sell_price(t)
            if sp:
                ret += sp * value
        return ret
    def get_clean_total(self, t):
        ret = self.cash
        for key, value in self.stocks.items():
            sp = key.get_recent_adjc(t)
            if sp:
                ret += sp * value
        return ret
    def buy(self, t, corp, amount):
        if amount > self.can_buy(t, corp):
            amount = self.can_buy(t, corp) # naive fix
        assert(amount <= self.can_buy(t, corp))
        assert(corp.can_trade(t))
        p = corp.get_buy_price(t)
        self.cash -= p*amount
        self.stocks[corp] += amount
        if p*amount > 0:
            self.log.writeline(str(t) + ":buy " + str(amount) + " " + corp.comp.name + corp.comp.code + " at " + human_readable_float(p*amount))
        return # don't need to record history

        t = str(t)
        if t not in list(self.history.columns):
            self.history[t] = ""
        code = corp.code
        if code not in list(self.history['Corps']):
            self.history = self.history.append(pd.Series([code], index=['Corps']), ignore_index = True)
        if 'cash' not in list(self.history['Corps']):
            self.history = self.history.append(pd.Series(['cash'], index=['Corps']), ignore_index = True)
        s = str(self.stocks[corp])
        self.history.loc[self.history['Corps'] == code, t] = s
        self.history.loc[self.history['Corps'] == 'cash', t] = str(self.cash)
    def sell(self, t, corp, amount):
        if amount > self.stocks[corp]:
            amount = self.stocks[corp]
        assert(amount <= self.stocks[corp])
        assert(corp.can_trade(t))
        p = corp.get_sell_price(t)
        self.cash += p*amount
        self.stocks[corp] -= amount
        if p*amount > 0:
            self.log.writeline(str(t) + ":sell " + str(amount) + " " + corp.comp.name + corp.comp.code + " at " + human_readable_float(p*amount))
        return # don't need to record history

        t = str(t)
        if t not in list(self.history.columns):
            self.history[t] = ""
        code = corp.code
        if code not in list(self.history['Corps']):
            self.history = self.history.append(pd.Series([code], index=['Corps']), ignore_index = True)
        if 'cash' not in list(self.history['Corps']):
            self.history = self.history.append(pd.Series(['cash'], index=['Corps']), ignore_index = True)
        s = str(self.stocks[corp])
        self.history.loc[self.history['Corps'] == code, t] = s
        self.history.loc[self.history['Corps'] == 'cash', t] = str(self.cash)
    def sell_all(self, t, corp):
        self.sell(t, corp, self.stocks[corp])
    def buy_target(self, t, corp, target):
        assert(target >= self.stocks[corp])
        self.buy(t, corp, target - self.stocks[corp])
    def sell_target(self, t, corp, target):
        assert(target <= self.stocks[corp])
        self.sell(t, corp, self.stocks[corp] - target)
    def match_target(self, t, corp, target):
        if target > self.stocks[corp]:
            self.buy_target(t, corp, target)
        else:
            self.sell_target(t, corp, target)
    def match_portfolio(self, t, corpPercent): # invest total*p in corp. corpPercent : (corp * percent) list
        tot = 0
        buyCorps = []
        for (corp, p) in corpPercent:
            assert(corp.can_trade(t))
            assert(0 <= p and p <= 1)
            buyCorps.append(corp)
            tot += p
        assert(tot <= 1)
        # get cash first
        for corp in self.stocks:
            if corp not in buyCorps and corp.can_trade(t):
                self.sell_all(t, corp)
        for (corp, p) in corpPercent:
            target_cash = self.get_total(t)*p # is it right to use get_total()?
            target = int(target_cash / corp.get_buy_price(t))
            self.match_target(t, corp, target)
    def liquidate(self, t):
        for key, value in self.stocks.items():
            if key.can_trade(t):
                self.sell(t, key, value)
    def earned(self, t):
        tot = self.get_total(t)
        return round( (tot - self.original_cash) / self.original_cash * 100, 2 )
    def conclude(self):
        pass
    def record(self, t, chart):
        d = SfData()
        d.chart = chart
        d.x = t.__str__()
        d.y = self.get_clean_total(t)
        d.save()

class Sim:
    def __init__(self, dfrom, dto, simfolder, simnum):
        self.log = Logger(os.path.join(simfolder, 'log.txt'))
        self.dfrom = dfrom
        self.dto = dto
        self.comps = [Comp(c.code) for c in Company.objects.all()]
        self.log.writeline('Load ' + str(len(self.comps)))
        market = Comp('^KS11')
        self.comps = [c for c in self.comps if c.validate(dfrom, dto, market)]
        self.log.writeline('Valid ' + str(len(self.comps)))
        self.simfolder = simfolder
        self.simnum = simnum

    def run(self, strategy, startcash, modelSim, justResult=False):
        if not justResult:
            # write metadata
            metadata = {}
            metadata['from'] = self.dfrom.__str__()
            metadata['to'] = self.dto.__str__()
            metadata['startcash'] = startcash
            metadata['companyCodes'] = [c.code for c in self.comps]
            json.dump(metadata, open(os.path.join(self.simfolder, 'metadata.txt'), 'w'))

        wallet = Wallet(startcash, self.log)

        if justResult:
            log.close()

        context = {}
        if not justResult:
            chart = Chart()
            chart.sim = modelSim
            chart.name = 'simulation' # required
            chart.save()
        for d in mdrange(self.dfrom, self.dto+1):
            strategy(d, self.comps, wallet, context)
            if not justResult:
                wallet.record(d, chart)

        wallet.conclude()

        modelSim.progress = 100.0
        modelSim.save()

        return wallet.earned(self.dto)

def simInit(num, name, detail, dfrom, dto, progress=0.0):
    try:
        sim = Simulation.objects.get(num=num)
        sim.delete()
    except Exception as e:
        pass
    sim = Simulation()
    sim.num = num
    sim.name = name
    sim.detail = detail
    sim.progress = progress
    sim.save()
    SimInstance = Sim(dfrom, dto, '/var/www/stockAnalyzeWeb/main/sim_data/f'+str(num), num)
    return (sim, SimInstance)


import csv
import os
import sys
import time
import pymongo
import argparse
import hashlib
try:
    from root import servers
except ModuleNotFoundError:
    path = os.path.abspath('.')
    sys.path.insert(1, path)
    from root import servers

SEPARATOR = "___SEPARATOR___"

def show_help():
    print('Este script sirve para comparar dos dbs.')
    print('Pueden estar como archivos csv o se puede buscar los datos al mongo local y api presence(u otra fecha del local si se pone a comparar dos fechas)')
    print('Imprime en pantalla los match entre ambos. ')
    print('Como opcional tambien imprime los contenidos que no estan en el otro.\n')
    print('Para ejecutar:\n')
    print('\tSi se comparan csv:\n')
    print('\t\033[1mpython handle/comparar_scraping.py archivo1.csv archivo2.csv --col NombreColumna --sinMatch --export NombreArchivo\033[0m\n')

    print('\t\tcsv1 y csv2 son los archivos a comparar')
    print('\t\t\033[1m--col\033[0m\t\t columna del csv a comparar (por default es Title)')
    print('\t\t\033[1m--sinMatch\033[0m\t es un opcional para imprimir lista de los contenidos diferentes')
    print('\t\t\033[1m--export\033[0m\t es un opcional para que guarde lo que se imprime en pantalla en un .log\n')

    print('\tSi se busca la data de mongo:\n')
    print('\t\033[1mpython handle/comparar_scraping.py PlatformCode --at CreatedAt --col NombreColumna --sinMatch --mongo --export NombreArchivo --epis\033[0m\n')
    print('\t\tPlatformCode inclyendo iso-code.')
    print('\t\t\033[1m--at\033[0m\t\t Fecha del scraping local en formato YYYY-MM-DD (por default, la ultima del mongo local). \n\t\t\t\t Si son 2 fechas diferentes se compara el scraping de local de una fecha y de otra, en vez de local y apiPresence:')
    print('\t\t\t\t python handle/comparar_scraping.py PlatformCode --at \033[1mCreatedAt1 CreatedAt2\033[0m --col NombreColumna --sinMatch --mongo --export NombreArchivo --epis\n')
    print('\t\t\033[1m--col\033[0m\t\t columna a comparar (por default es Title)')
    print('\t\t\033[1m--sinMatch\033[0m\t es un opcional para imprimir lista de los contenidos diferentes')
    print('\t\t\033[1m--mongo\033[0m\t\t necesario para que busque en la db')
    print('\t\t\033[1m--export\033[0m\t es un opcional para que guarde lo que se imprime en pantalla en un .log')
    print('\t\t\033[1m--epis\033[0m\t\t es un opcional para que compare episodios ')

class Comparator():

    def __init__(self, dbs_or_source_files: list, column: str, use_mongo: bool, list_created_at=[], epis=False) -> None:
        self.__dbs_source_file = dbs_or_source_files
        self.__column = column
        self.__use_mongo = use_mongo
        self.__list_created_at = list_created_at
        self.__epis = epis
        self.__file = None

    def compare(self, export_file: str, sin_match=False) -> None:
        if export_file:
            if '.' in export_file:
                print('El nombre del archivo no puede contenter puntos')
                self.__file = None
            else:
                export = export_file + '.log'
                self.__file = open(export, 'w', encoding="utf-8")
        else:
            self.__file = None

        column = self.__column
        dbs = self.__dbs_source_file
        list_created_at = self.__list_created_at
        epis = self.__epis

        if self.__use_mongo:
            self.compare_mongo_db(dbs, list_created_at, column, sin_match, self.__file, epis)
        else:
            if len(self.__dbs_source_file) == 2:
                filename_tp = dbs[0]
                filename_scraping = dbs[1]
                self.compare_csv(filename_tp, filename_scraping, column, sin_match, export_file)
            else:
                print('Solo se pueden comparar 2 csv')

        if self.__file:
            self.__file.close()

    @classmethod
    def compare_csv(cls, filename_tp: str, filename_scraping: str, col: str, sin_match=False, export_file=None) -> None:
        titulos_tp = []
        with open(filename_tp, newline='', encoding='utf-8') as csvfile:
            lector = csv.reader(csvfile)
            headers = lector.__next__()
            if col in headers:
                col_index = headers.index(col)
                for row in lector:
                    title = row[col_index]
                    titulos_tp.append(title)
            else:
                cls.print_or_write('valor incorrecto de col')
                cls.print_or_write('Disponibles:')
                cls.print_or_write(headers)

        titulos_scraping = []
        match_scraping = 0

        titulos_scraping_no_tp = []
        with open(filename_scraping, newline='', encoding='utf-8') as csvfile:
            lector = csv.reader(csvfile)
            headers = lector.__next__()
            if titulos_tp and col in headers:
                col_index = headers.index(col)

                for row in lector:
                    title = row[col_index]
                    titulos_scraping.append(title)
                    if any(title == title_tp for title_tp in titulos_tp):
                        match_scraping += 1
                    else:
                        titulos_scraping_no_tp.append(title)
            else:
                cls.print_or_write('valor incorrecto de col')
                cls.print_or_write('Disponibles:')
                cls.print_or_write(headers)

        cls.print_or_write(f'{filename_scraping} Matcheo {match_scraping} de {len(titulos_scraping)}', export_file)

        titulos_tp_no_scraping = []
        match_tp = 0
        if titulos_scraping:
            for titulo in titulos_tp:
                if any(titulo == title_s for title_s in titulos_scraping):
                    match_tp += 1
                else:
                    titulos_tp_no_scraping.append(titulo)
            cls.print_or_write(f'{filename_tp} Matcheo {match_tp} de {len(titulos_tp)}', export_file)

        if sin_match:
            cls.print_or_write('')
            cls.print_or_write(f'TITULOS EN {filename_scraping.upper()} QUE NO ESTAN EN {filename_tp.upper()}', export_file)
            cls.print_or_write(titulos_scraping_no_tp, export_file)
            cls.print_or_write('')
            cls.print_or_write(f'TITULOS EN {filename_tp.upper()} QUE NO ESTAN EN {filename_scraping.upper()}', export_file)
            cls.print_or_write(titulos_tp_no_scraping, export_file)

    @classmethod
    def compare_mongo_db(cls, dbs: list, list_created_at: list, col:str, sin_match=False, export_file=None, epis=False) -> None:
        """Función utilizada para comparar el scraping que se encuentra localmente frente a lo disponible en apiPresence.\n
        También tiene la opción de comparar entre 2 fechas localmente en el caso de comparar diferencias entre fechas.

        Args:
            - list_created_at :class:`list`: Lista de fechas. Si son 2 fechas se compara localmente. En el caso que sea 1 fecha se asume como segunda DB a apiPresence.
            - col :class:`str`: Columna que se desea comparar
            - sin_match :class:`bool`: Indica si se desea imprimir en pantalla la lista de contenidos que no hicieron match
            - export_file :class:`str`: Nombre del archivo a guardar los resultados como log
            - epis :class:`bool`: Indica si se desea comparar episodios
        """
        client_local = pymongo.MongoClient("mongodb://localhost:27017")
        db_local = client_local["titan"]
        collection_name = 'titanScrapingEpisodes' if epis else 'titanScraping'
        collection = db_local[collection_name]

        platform_code = dbs[0]

        sub_col = None
        if '.' in col:
            col = col.split('.')
            sub_col = col[1]
            col = col[0]

        dict_dbs = {
            "db1": [],  # local fecha1
            "db2": [],  # local fecha2 ó apipresence
        }

        # Si se ingresa 2 fechas se comparan localmente
        for counter, created_at in enumerate(list_created_at):
            if counter >= 2:
                break
            if created_at == 'last':
                params = {'PlatformCode': platform_code}
                sort   = [("CreatedAt", pymongo.DESCENDING)]
                limit = 1
                lastItem = collection.find(params).sort(sort).limit(limit)
                if collection.count_documents(params, limit=limit) > 0:
                    for lastContent in lastItem:
                        created_at = lastContent['CreatedAt']
            cls.print_or_write('Mongo local: ' + created_at)
            payload = {
                'PlatformCode'  : platform_code,
                'CreatedAt'     : created_at
            }
            cls.print_or_write('Obteniendo DB de Mongo local ...')
            col = 'CleanTitle' if col == 'Title' and not epis else col
            if col == 'HashUnique':
                if epis:
                    projection = ['ParentId', 'Episode', 'PlatformCode']
                    projection_scraping = ['Id', 'CleanTitle', 'Year', 'Type']
                    scraping = db_local['titanScraping'].find(payload, no_cursor_timeout=True, projection=projection_scraping).batch_size(100)
                    scraping = [dict(item) for item in scraping if item['Type'] == 'serie']
                else:
                    projection = ['CleanTitle','Type','Year','PlatformCode']
            else:
                projection = [col,'ParentId'] if epis else [col]

            local = collection.find(payload, no_cursor_timeout=True, projection=projection).batch_size(100)
            local = [item for item in local]
            if col == 'HashUnique':
                if epis:
                    for epi in local:
                        for serie in scraping:
                            if epi['ParentId'] == serie['Id']:
                                epi['Year'] = serie['Year']
                                epi['Title'] = serie['CleanTitle']
                    # print('No se puede realizar la comparacion por HashUnique (por ahora)')
                    # return
                local = [cls._generate_hash_unique(item, epis) for item in local]

            db_name = 'db1' if counter == 0 else 'db2'
            dict_dbs[db_name] = local

        # Si solo se ingresó 1 fecha se comparará con apiPresence
        if len(list_created_at) == 1:
            apipresence = []
            try:
                ssh_connection = servers.MisatoConnection()
                with ssh_connection.connect() as server:
                    client   = pymongo.MongoClient('127.0.0.1', server.local_bind_port)
                    business = client['business']
                    db_api = business['apiPresence']

                    payload_api = {
                        'PlatformCode': platform_code,
                        'Status': {'$ne': 'inactive'}
                    }
                    cls.print_or_write('Obteniendo DB de apiPresence ...')
                    if epis:
                        episodios = []
                        payload_api['Type'] = 'serie'
                        apipresence = db_api.find(payload_api, no_cursor_timeout=True, projection=['Episodes', 'Status']).batch_size(100)
                        for doc in apipresence:
                            for epi in doc['Episodes']:
                                episodios.append({col:epi[col], 'ParentId':epi['ParentId']})
                        apipresence = episodios
                    else:
                        col = 'Title' if col == 'CleanTitle' else col
                        col = 'ContentId' if col == 'Id' else col
                        apipresence = db_api.find(payload_api, no_cursor_timeout=True, projection=[col, 'Status']).batch_size(100)
                        apipresence = [item for item in apipresence]

            except Exception as e:
                cls.print_or_write(f'No se pudo conectar con apiPresence -> {e}')
            else:
                dict_dbs['db2'] = apipresence
            finally:
                client.close()
                server.stop()

        print("COMPARANDO...")
        if dict_dbs['db2']:
            match_local = 0
            match_api = 0
            api_no_local = []
            local_no_api = []

            if col == 'ContentId':
                col_local = 'Id'
            elif col == 'Title' and not epis:
                col_local = 'CleanTitle'
            else:
                col_local = col

            tmp_dict_fields = {
                "local": {},
                "api": {},
            }
            for name in tmp_dict_fields:
                temporary_dict = tmp_dict_fields[name]
                db_name = 'db1' if name == 'local' else 'db2'
                current_db = dict_dbs[db_name]  # local1 | local2 | apipresence
                for item in current_db:
                    custom_col_name = col_local if name == "local" else col
                    first_part = item['ParentId'] if epis else ''
                    second_part = item[col][sub_col] if sub_col else item[custom_col_name]
                    custom_field_value = f"{first_part}{SEPARATOR}{second_part.lower()}"

                    # Se almacenan los títulos que coinciden con el campo. Puede contener una lista de 1 o más(repetidos)
                    # Ej: "__SEPARATOR__title1": ['Title1", 'TITLE1', 'title1']
                    list_column_values = temporary_dict.setdefault(custom_field_value, [])
                    list_column_values.append(second_part)
                    # temporary_dict[custom_field_value] = list_column_values

            ##############################################
            #  Método de comparación usando set          #
            ##############################################
            # >>> a = {1, 2, 3, 4, 5, 6, 7}
            # >>> b = {1, 2, 4, 5, 8, 9}
            # >>>
            # >>> a - b
            # {3, 6, 7}
            # >>> b - a
            # {8, 9}
            ##############################################
            set_apipresence = set(tmp_dict_fields['api'].keys())
            set_local = set(tmp_dict_fields['local'].keys())

            # Se compara la diferencia entre local vs apiPresence o local vs local(otra fecha)
            api_no_local = set_apipresence - set_local  # Contenidos que están en apiPresence, pero no en local
            local_no_api = set_local - set_apipresence  # Contenidos que están en local, pero no en apiPresence

            list_all_apipresence = []
            list_diff_apipresence = []
            list_all_local = []
            list_diff_local = []
            for k, list_values in tmp_dict_fields['api'].items():
                for field_value in list_values:
                    list_all_apipresence.append(field_value)
                    if k in api_no_local:
                        list_diff_apipresence.append(field_value)
            for k, list_values in tmp_dict_fields['local'].items():
                for field_value in list_values:
                    list_all_local.append(field_value)
                    if k in local_no_api:
                        list_diff_local.append(field_value)

            match_api = len(list_all_apipresence) - len(list_diff_apipresence)
            match_local = len(list_all_local) - len(list_diff_local)
            cls.print_or_write(f'apiPresence/otra DB matcheó {match_api} de {len(list_all_apipresence)}', export_file)
            cls.print_or_write(f'Local matcheó {match_local} de {len(list_all_local)}', export_file)

            if sin_match:
                cls.print_or_write('-------Titulos apiPresence que no estan en Local-------', export_file)
                cls.print_or_write(list_diff_apipresence, export_file)
                cls.print_or_write('')
                cls.print_or_write('-------Titulos Local que no estan en apiPresence-------', export_file)
                cls.print_or_write(list_diff_local, export_file)

    @staticmethod
    def print_or_write(text, file=None):
        if file:
            if type(text) == list:
                for item in text:
                    file.write(str(item) + '\n')
            else:
                file.write(str(text) + '\n')
        print(text)

    @staticmethod
    def _generate_hash_unique(item, epis):
        if epis:
            text = f'{item["Title"]}{item["Episode"]}{item["Year"]}{item["PlatformCode"]}'
        else:
            text =  f'{item["CleanTitle"]}{item["Type"]}{item["Year"]}{item["PlatformCode"]}'
        hash_unique = hashlib.md5(text.encode('UTF-8')).hexdigest()
        return {'HashUnique': hash_unique, 'ParentId': item["ParentId"]} if epis else {'HashUnique': hash_unique}

if __name__ == '__main__':
    parser =  argparse.ArgumentParser()
    parser.add_argument('dbs', help='archivos a comparar o PlatformCode de la DB', type=str, nargs="+")
    parser.add_argument('--col',help='Columna a comparar', type=str, default='Title')
    parser.add_argument('--sinMatch', help='Opcional para mostrar diferencia entre archivos/dbs', nargs='?', default=False, const=True)
    parser.add_argument('--mongo', help='Comparar dbs de mongo local y misato', nargs='?', default=False, const=True)
    parser.add_argument('--at', help='CreatedAt', type=str, nargs="+", default=['last'])
    parser.add_argument('--export', help='Nombre de archivo donde guardar lo que se imprime en pantalla', type=str)
    parser.add_argument('--epis', help='Si se desea comparar episodios', nargs='?', default=False, const=True)
    parser.add_argument('--h', help='Ver ayuda', nargs='?', default=False, const=True)

    try:
        args = parser.parse_args()
        dbs             = args.dbs
        col             = args.col
        sin_match       = args.sinMatch
        mongo           = args.mongo
        list_created_at = args.at
        export          = args.export
        epis            = args.epis
        _help           = args.h
        if _help:
            show_help()
        else:
            comparator = Comparator(dbs_or_source_files=dbs, column=col, use_mongo=mongo, list_created_at=list_created_at, epis=epis)
            comparator.compare(export_file=export, sin_match=sin_match)
    except Exception as e:
        show_help()
        raise


from BKITVisitor import BKITVisitor
from BKITParser import BKITParser
from AST import *

class ASTGeneration(BKITVisitor):

    def IntegerStandardization(self, s: str):
        if self.checkHex(s):
            temp = int(s, base=16)
            return temp
        elif self.checkOct(s):
            temp = int (s, base=8)
            return temp
        else:
            return int(s)

    def checkHex(self, s: str):
        if 'x' in s or 'X' in s:
            return True
        else:
            return False

    def checkOct(self, s: str):
        if 'o' in s or 'O' in s:
            return True
        else:
            return False

    def visitProgram(self, ctx: BKITParser.ProgramContext):
        if ctx.getChildCount() == 1:
            return Program([])
        else:
            listDecl = []
            for i in range(ctx.getChildCount()-1):
                listDecl += self.visit(ctx.getChild(i))
            return Program(listDecl)

    def visitVar_declaration_part(self, ctx: BKITParser.Var_declaration_partContext):
        res = []
        for i in range(2, ctx.getChildCount() - 1, 2):
            res = res + [self.visit(ctx.getChild(i))]
        return res

    def visitSingle_var_list(self, ctx:BKITParser.Single_var_listContext):
        idName = ctx.ID().getText()
        dimen = []
        if ctx.ASSIGN():
            if ctx.INT_LIT():
                init = IntLiteral(self.IntegerStandardization(ctx.INT_LIT().getText()))
            elif ctx.FLOAT_LIT():
                init = FloatLiteral(float(ctx.FLOAT_LIT().getText()))
            elif ctx.STRING_LIT():
                init = StringLiteral(ctx.STRING_LIT().getText())
            elif ctx.BOOL_LIT():
                temp = ctx.BOOL_LIT().getText()
                if temp == 'True':
                    init = BooleanLiteral(True)
                else:
                    init = BooleanLiteral(False)
            else:
                init = self.visit(ctx.array_lit())
            return VarDecl(Id(idName), dimen, init)
        else:
            return VarDecl(Id(idName), dimen, None)

    def visitArray_list(self, ctx: BKITParser.Array_listContext):
        idName = ctx.ID().getText()
        numberOfLSB = len(ctx.getTokens(27))
        dimen = []
        for i in range(numberOfLSB):
            temp = self.IntegerStandardization(ctx.INT_LIT(i).getText())
            dimen = dimen + [temp]
        init = None
        if ctx.ASSIGN():
            if ctx.INT_LIT(numberOfLSB):
                init = IntLiteral(self.IntegerStandardization(ctx.INT_LIT(numberOfLSB).getText()))
            elif ctx.FLOAT_LIT():
                init = FloatLiteral(float(ctx.FLOAT_LIT().getText()))
            elif ctx.STRING_LIT():
                init = StringLiteral(ctx.STRING_LIT().getText())
            elif ctx.BOOL_LIT():
                temp = ctx.BOOL_LIT().getText()
                if temp == 'True':
                    init = BooleanLiteral(True)
                else:
                    init = BooleanLiteral(False)
            else:
                init = self.visit(ctx.array_lit())
            return VarDecl(Id(idName), dimen, init)
        else:
            return VarDecl(Id(idName), dimen, init)

    def visitArray_lit(self, ctx:BKITParser.Array_litContext):
        res = []
        indexINT = 0
        indexFLOAT = 0
        indexSTRING = 0
        indexBOOL = 0
        for i in range(1, ctx.getChildCount()-1, 2):
            temp = ctx.getChild(i)
            if isinstance(temp, BKITParser.Array_litContext):
                res = res + [self.visit(ctx.getChild(i))]
            else:
                if ctx.getChild(i) == ctx.INT_LIT(indexINT):
                    res = res + [IntLiteral(self.IntegerStandardization(ctx.INT_LIT(indexINT).getText()))]
                    indexINT += 1
                elif ctx.getChild(i) == ctx.FLOAT_LIT(indexFLOAT):
                    res = res + [FloatLiteral(float(ctx.FLOAT_LIT(indexFLOAT).getText()))]
                    indexFLOAT += 1
                elif ctx.getChild(i) == ctx.BOOL_LIT(indexBOOL):
                    temp = ctx.BOOL_LIT(indexBOOL).getText()
                    if temp == 'True':
                        res = res + [BooleanLiteral(True)]
                    else:
                        res = res + [BooleanLiteral(False)]
                    indexBOOL += 1
                else:
                    res = res + [StringLiteral(ctx.STRING_LIT(indexSTRING).getText())]
                    indexSTRING += 1
        return ArrayLiteral(res)

    # FUNCTION DECLARATION PART

    def visitFunc_declaration_part(self, ctx: BKITParser.Func_declaration_partContext):
        idName = ctx.ID().getText()
        if ctx.param_list():
            paramList = self.visit(ctx.param_list())
        else:
            paramList = []
        funcBody = self.visit(ctx.func_body())
        return [FuncDecl(Id(idName), paramList, funcBody)]

    def visitParam_list(self, ctx: BKITParser.Param_listContext):
        res = []
        listParamElement = ctx.param_element()
        if listParamElement:
            for ele in listParamElement:
                res += [self.visit(ele)]
        return res

    '''
    def visitParam_element(self, ctx: BKITParser.Param_elementContext):
        return self.visit(ctx.getChild(0))
    '''

    def visitParam_element(self, ctx: BKITParser.Param_elementContext):
        idName = ctx.ID().getText()
        if ctx.getChildCount() == 1:
            return VarDecl(Id(idName), [], None)
        else:
            listOfTokenInt = ctx.INT_LIT()
            listDimen = []
            for it in listOfTokenInt:
                listDimen += [self.IntegerStandardization(it.getText())]
            return VarDecl(Id(idName), listDimen, None)

    def visitFunc_body(self, ctx: BKITParser.Func_bodyContext):
        return self.visit(ctx.var_decl_and_statement())

    # STATEMENTS

    def visitStatement_in_function(self, ctx: BKITParser.Statement_in_functionContext):
        return self.visit(ctx.getChild(0))

    def visitAssignment(self, ctx: BKITParser.AssignmentContext):
        lhs = ctx.getChild(0)
        if isinstance(lhs, BKITParser.Element_expressionContext):
            lhs = self.visit(lhs)
        else:
            lhs = Id(lhs.getText())
        expression = self.visit(ctx.exp())
        return Assign(lhs, expression)

    def visitIf_statement_in_function(self, ctx: BKITParser.If_statement_in_functionContext):
        ifthenStmt = []
        elseStmt = ([], [])

        for i in range(ctx.getChildCount()):
            if ctx.exp(i) and ctx.var_decl_and_statement(i):
                expression = self.visit(ctx.exp(i))
                declAndStatement = self.visit(ctx.var_decl_and_statement(i))
                ifthenStmt += [(expression, declAndStatement[0], declAndStatement[1])]
            elif not(ctx.exp(i)) and ctx.var_decl_and_statement(i):
                elseStmt = self.visit(ctx.var_decl_and_statement(i))
            else:
                pass

        return If(ifthenStmt, elseStmt)

    def visitFor_statement_in_function(self, ctx:BKITParser.For_statement_in_functionContext):
        idx1 = ctx.ID().getText()
        exp1 = self.visit(ctx.exp(0))
        exp2 = self.visit(ctx.exp(1))
        exp3 = self.visit(ctx.exp(2))
        loop = self.visit(ctx.var_decl_and_statement())
        return For(Id(idx1), exp1, exp2, exp3, loop)

    def visitWhile_statement_in_function(self, ctx: BKITParser.While_statement_in_functionContext):
        expr = self.visit(ctx.exp())
        sl = self.visit(ctx.var_decl_and_statement())
        return While(expr, sl)

    def visitDo_while_statement_in_function(self, ctx: BKITParser.Do_while_statement_in_functionContext):
        expr = self.visit(ctx.exp())
        sl = self.visit(ctx.var_decl_and_statement())
        return Dowhile(sl, expr)

    def visitVar_decl_and_statement(self, ctx:BKITParser.Var_decl_and_statementContext):
        varDecl = []
        stmt = []
        for i in range(ctx.getChildCount()):
            temp = ctx.getChild(i)
            if isinstance(temp, BKITParser.Var_declaration_partContext):
                varDecl += self.visit(temp)
            else:
                stmt += [self.visit(temp)]
        return (varDecl, stmt)

    def visitBreak_statement(self, ctx: BKITParser.Break_statementContext):
        return Break()

    def visitContinue_statement(self, ctx: BKITParser.Continue_statementContext):
        return Continue()

    def visitReturn_statement(self, ctx:BKITParser.Return_statementContext):
        expr = None
        if ctx.exp():
            expr = self.visit(ctx.exp())

        return Return(expr)

    def visitFunction_call_statement(self, ctx: BKITParser.Function_call_statementContext):
        methodName = ctx.ID().getText()
        argList = []
        if ctx.argument_list():
            argList = self.visit(ctx.argument_list())
        return CallStmt(Id(methodName), argList)

    def visitFunction_call(self, ctx: BKITParser.Function_callContext):
        methodName = ctx.ID().getText()
        argList = []
        if ctx.argument_list():
            argList = self.visit(ctx.argument_list())
        return CallExpr(Id(methodName), argList)

    def visitArgument_list(self, ctx: BKITParser.Argument_listContext):
        res = []
        for i in range(ctx.getChildCount()):
            temp = ctx.exp(i)
            if temp:
                res += [self.visit(temp)]
        return res

    # EXPRESSION

    def visitElement_expression(self, ctx: BKITParser.Element_expressionContext):
        if ctx.ID():
            arr = Id(ctx.ID().getText())
        if ctx.exp():
            arr = self.visit(ctx.exp())
        if ctx.function_call():
            arr = self.visit(ctx.function_call())
        expList = self.visit(ctx.index_operators())
        return ArrayCell(arr, expList)

    def visitIndex_operators(self, ctx: BKITParser.Index_operatorsContext):
        res = []
        for i in range(ctx.getChildCount()):
            temp = ctx.exp(i)
            if temp:
                res += [self.visit(temp)]
        return res

    def visitExp(self, ctx: BKITParser.ExpContext):
        if ctx.getChildCount() == 1:
            return self.visit(ctx.exp1(0))
        else:
            left = self.visit(ctx.exp1(0))
            right = self.visit(ctx.exp1(1))
            op = ctx.getChild(1).getText()
            return BinaryOp(op, left, right)

    def visitExp1(self, ctx: BKITParser.Exp1Context):
        if ctx.getChildCount() == 1:
            return self.visit(ctx.exp2())
        else:
            left = self.visit(ctx.exp1())
            right = self.visit(ctx.exp2())
            op = ctx.getChild(1).getText()
            return BinaryOp(op, left, right)

    def visitExp2(self, ctx: BKITParser.Exp2Context):
        if ctx.getChildCount() == 1:
            return self.visit(ctx.exp3())
        else:
            left = self.visit(ctx.exp2())
            right = self.visit(ctx.exp3())
            op = ctx.getChild(1).getText()
            return BinaryOp(op, left, right)

    def visitExp3(self, ctx: BKITParser.Exp3Context):
        if ctx.getChildCount() == 1:
            return self.visit(ctx.exp4())
        else:
            left = self.visit(ctx.exp3())
            right = self.visit(ctx.exp4())
            op = ctx.getChild(1).getText()
            return BinaryOp(op, left, right)

    def visitExp4(self, ctx: BKITParser.Exp4Context):
        if ctx.getChildCount() == 1:
            return self.visit(ctx.exp5())
        else:
            op = ctx.NOT().getText()
            body = self.visit(ctx.exp4())
            return UnaryOp(op, body)

    def visitExp5(self, ctx: BKITParser.Exp5Context):
        if ctx.getChildCount() == 1:
            return self.visit(ctx.operand())
        else:
            op = ctx.getChild(0).getText()
            body = self.visit(ctx.exp5())
            return UnaryOp(op, body)

    def visitOperand(self, ctx: BKITParser.OperandContext):
        if ctx.ID():
            return Id(ctx.ID().getText())
        elif ctx.INT_LIT():
            return IntLiteral(self.IntegerStandardization(ctx.INT_LIT().getText()))
        elif ctx.FLOAT_LIT():
            return FloatLiteral(float(ctx.FLOAT_LIT().getText()))
        elif ctx.BOOL_LIT():
            temp = ctx.BOOL_LIT().getText()
            if temp == 'False':
                return BooleanLiteral(False)
            else:
                return BooleanLiteral(True)
        elif ctx.STRING_LIT():
            return StringLiteral(ctx.STRING_LIT().getText())
        elif ctx.function_call():
            return self.visit(ctx.function_call())
        elif ctx.element_expression():
            return self.visit(ctx.element_expression())
        elif ctx.array_lit():
            return self.visit(ctx.array_lit())
        else:
            return self.visit(ctx.exp())


import unittest
from unittest.mock import patch
import redstreak.sort as sort
import random

def make_sort_data(amount):
    letters = "qwertyuiopasdfghjklzxcvbnm"
    random.seed = 'outofcore'
    raw = [
        {
            'value': "".join([random.choice(letters) for _ in range(10)]),
            "other_attribute": "constant",
        }
        for _ in range(amount)]
    return raw

class TestSortNode(unittest.TestCase):

    def test_sort_key(self):
        raw = ["a", "abracadbra", "bd", "test", "testimony", ]
        raw = [{'value': val} for val in raw]

        expected = ["a", "abracadbra", "bd", "test", "testimony", ]
        expected = [{'value': val} for val in expected]

        self.assertEqual(list(sort.Sort('value', raw)),
                         expected)

    @patch('redstreak.sort.MAX_RECORD_LEN', 5)
    def test_small_out_of_core_sort(self):
        raw = make_sort_data(10)

        def expected_sort_key(item):
            return item['value']

        expected = sorted(raw, key=expected_sort_key)
        self.assertEqual(list(sort.Sort('value', raw)),
                         expected)

    @patch('redstreak.sort.MAX_RECORD_LEN', 45)
    def test_medium_out_of_core_sort(self):
        raw = make_sort_data(500)

        def expected_sort_key(item):
            return item['value']

        expected = sorted(raw, key=expected_sort_key)
        self.assertEqual(list(sort.Sort('value', raw)),
                         expected)

    @patch('redstreak.sort.MAX_RECORD_LEN', 1000)
    def test_huge_out_of_core_sort(self):
        """Wew"""
        raw = make_sort_data(100000)

        def expected_sort_key(item):
            return item['value']

        expected = sorted(raw, key=expected_sort_key)
        self.assertEqual(list(sort.Sort('value', raw)),
                         expected)

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


from DNN import DNN
import numpy as np
from tools import *
from sklearn import preprocessing
import os
import time

def main():
    currencies = read_data()

    # data = [read_one_data('./Data/Bitcoin.csv')]

    bs = [i for i in range(50, 1000, 50)]
    bs = bs[:13]
    # ts2bs = [i * 2 for i in bs]
    ts3bs = [i * 3 for i in bs]
    # bs = bs * 2
    # ts = ts2bs + ts3bs
    ts = ts3bs
    bs = list([bs[1]])
    ts = list([ts[1]])
    print(bs)
    print(ts)
    # time.sleep(1000)
    # normalizer = preprocessing.Normalizer().fit([data])
    # data = normalizer.transform([data])
    # data = data.reshape(-1)

    for i in currencies:
        tmp = i[1]['Open']
        name = i[0].split('.')[0]
        path = './new/'

        # sort_data(path, name + '.txt')

        # if not os.path.exists(path + name):
        #     os.mkdir(path + name)
        for j in range(len(bs)):
            dnn = DNN(tmp, bs[j], ts[j])
            # model = dnn.dnn(path, name)
            new_name = ''
            # if j < len(bs) / 2:
            #     new_name = name + '2bs'
            # else:
            #     new_name = name + '3bs'
            lstm = dnn.dnn(path, new_name)
            # model.save('./new/' + name + '/dnn_' + str(name) + '_' + str(j) + '_' + '_model.h5')

    # import tools
    # for i in currencies:
    #     name = i[0].split('.')[0]
    #     tools.show_single_plot(i[1]['Open'], name)
    #
    # print(currencies[0][1]['Open'])

    # sort_bitcoin_data()

    # recognize_data()

if __name__ == '__main__':
    main()


import netifaces
from pysnmp.entity.rfc3413.oneliner import cmdgen
import time

def remove_duplicates(l):
    return list( dict.fromkeys(l))

def ip_cidr_route_next_hop(snmp_agent_host, snmp_port, snmp_community):
    cmdGen = cmdgen.CommandGenerator()

    errorIndication, errorStatus, errorIndex, varBinds = cmdGen.bulkCmd(
        cmdgen.CommunityData(snmp_community),
        cmdgen.UdpTransportTarget((snmp_agent_host, snmp_port)),
        0, 25,
        '1.3.6.1.2.1.4.24.4.1.4'
    )

    if errorIndication:
        return None
    else:
        if errorStatus:
            return None
        else:
            for binds in varBinds:
                for bind, ip_bin in binds:
                    ip_dec = '.'.join(map(str, ip_bin))
                    if ip_dec != '0.0.0.0':
                        yield ip_dec
    return None

def walk_and_print(default_snmp_agent_host_list, snmp_port, snmp_community):
    for snmp_agent_host in default_snmp_agent_host_list:
        new_snmp_agent_host = ip_cidr_route_next_hop(snmp_agent_host, snmp_port, snmp_community)
        if not new_snmp_agent_host:
            return
        new_snmp_agent_host = list(new_snmp_agent_host)
        if len(new_snmp_agent_host) == 0:
            return
        print("Hopping from " + str(snmp_agent_host) + " to "+ str(remove_duplicates(new_snmp_agent_host)))
        walk_and_print(new_snmp_agent_host, snmp_port, snmp_community)

if __name__ == '__main__':
    print("Starting program")
    gateways = netifaces.gateways()
    gateways_ips = [info[0] for info in gateways.pop("default").values()]
    gateways_ips = gateways_ips + [info[0] for garray in gateways.values() for info in garray]
    gateways_ips = remove_duplicates(gateways_ips)
    print("Gateway IPs: " + str(gateways_ips))

    snmp_agent_host_list = gateways_ips
    SNMP_PORT = 161
    SNMP_COMMUNITY = 'PSIPUB'
    walk_and_print(snmp_agent_host_list, SNMP_PORT, SNMP_COMMUNITY)


import sequence
import gc

# Sets animation for lamp using parameters provided with GET request
def setSequence(params, globals, config):

    globals.redraw_active = False

    sequenceName = params["sequenceName"] if "sequenceName" in params else globals.sequenceName

    for index, strip in list(enumerate(globals.stripData)):
        if "previous" in globals.stripData[index]["animation_data"]:
            del globals.stripData[index]["animation_data"]["previous"]

    globals.previousData = globals.stripData
    tmp = sequence.getStripData(config["controller"]["deviceID"], sequenceName, globals)
    globals.stripData = tmp

    globals.reset = True

    del tmp

    gc.collect()

    return "FINE"

# Routes mapping to functions
routes = {
    "sequence": setSequence,
}


"""
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""

class Solution:
    """
    @param root: the root of binary tree
    @return: the new root
    """

    def convertBST(self, root):
        self.sum = 0
        self.dfs(root)
        return root

    def dfs(self, root):
        if root is None:
            return
        if root.right:
            self.dfs(root.right)
        self.sum += root.val
        root.val = self.sum
        if root.left:
            self.dfs(root.left)


from pytorch_lightning.loggers import TensorBoardLogger
from pytorch_lightning.utilities import rank_zero_only
import torch
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.colors import Normalize
import torch.nn.functional as F
from os import path, makedirs
from omegaconf import OmegaConf as OC
from datetime import datetime, timedelta
from utils.stft import STFTMag
import librosa as rosa

class TensorBoardLoggerExpanded(TensorBoardLogger):
    def __init__(self, hparam):
        super().__init__(hparam.log.tensorboard_dir, name=hparam.name,
                default_hp_metric= False)
        self.hparam = hparam
        self.log_hyperparams(hparam)

        self.stftmag = STFTMag()

    def fig2np(self, fig):
        data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
        data = data.reshape(fig.canvas.get_width_height()[::-1] + (3, ))
        return data

    def plot_spectrogram_to_numpy(self, y, y_noisy, z_error, y_recon_allstep, y_recon, downsampled, step, logsnr):
        fig = plt.figure(figsize=(9, 18))

        name_list = ['y0', 'downsampled', 'y_recon_allstep', f'y_noisy(Diffstep_{step}_{logsnr})', 'y_recon', 'z_error']
        for i, yy in enumerate([y, downsampled, y_recon_allstep, y_noisy, y_recon, z_error]):
            yy = torch.clamp(yy, -1, 1 - 1e-6)
            ax=plt.subplot(6, 1, i + 1)
            ax.set_title(name_list[i])
            plt.imshow(rosa.amplitude_to_db(self.stftmag(yy).numpy(),
                       ref=np.max,top_db=80.),
                       #vmin = -20,
                       vmax = 0.,
                       aspect='auto',
                       origin='lower',
                       interpolation='none')
            # plt.colorbar()
            plt.xlabel('Frames')
            plt.ylabel('Channels')
            plt.tight_layout()

        fig.canvas.draw()
        data = self.fig2np(fig)

        plt.close()
        return data

    @rank_zero_only
    def log_spectrogram(self, y, y_noisy, z_error, y_recon_allstep, y_recon, downsampled, diff_step, logsnr, epoch):
        y, y_noisy, z_error, y_recon_allstep, y_recon, downsampled = \
            y.detach().cpu(), y_noisy.detach().cpu(), z_error.detach().cpu(), y_recon_allstep.detach().cpu(), \
            y_recon.detach().cpu(), downsampled.detach().cpu()
        spec_img = self.plot_spectrogram_to_numpy(
                y, y_noisy, z_error, y_recon_allstep, y_recon, downsampled, diff_step, logsnr)
        self.experiment.add_image(path.join(self.save_dir, 'result'),
                                  spec_img,
                                  epoch,
                                  dataformats='HWC')
        self.experiment.flush()
        return

    @rank_zero_only
    def log_audio(self, y, y_noisy, y_recon, y_recon_allstep, downsampled, epoch):
        y, y_noisy, y_recon, y_recon_allstep, downsampled, = y.detach().cpu(), y_noisy.detach().cpu(), \
                                                             y_recon.detach().cpu(), y_recon_allstep.detach().cpu(), \
                                                             downsampled.detach().cpu()

        name_list = ['y', 'y_noisy', 'y_recon', 'y_recon_allstep', 'downsampled']

        for n, yy in zip(name_list, [y, y_noisy, y_recon, y_recon_allstep, downsampled]):
            self.experiment.add_audio(n,
                                      yy, epoch, self.hparam.audio.sampling_rate)

        self.experiment.flush()
        return

    @rank_zero_only
    def log_learning_rate(self, learning_rate, step):
        self.experiment.add_scalar('learning_rate', learning_rate, step)


import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
import math
def cos_dist():
    data = pd.read_csv("WithoutOneCollegium.csv")
    #pairs
    start = 'О котрій годині ви зазвичай прокидаєтесь зранку? (якщо це не залежить від розкладу пар, наприклад у вихідні)_7:00 - 9:00'
    mid_st = 'Спосіб відпочинку [Подорожі до інших міст]_Дуже часто'
    mid = 'О котрій годині ви зазвичай прокидаєтесь зранку? (якщо це не залежить від розкладу пар, наприклад у вихідні)_Сусід_1_7:00 - 9:00'
    x = data.loc[:, start:mid_st]
    y = data.loc[:, mid::]

    cos_sim = [cosine_similarity(x.loc[[i]].values, y.loc[[i]].values) for i in range(len(x))]
    #print(cos_sim)

    simple_cos_sim = []
    for a in cos_sim:
        for b in a:
            for c in b:
                simple_cos_sim.append(c)
    #print(simple_cos_sim)

    degrees = []
    for i in simple_cos_sim:
        angle_in_radians = math.acos(i)
        degrees.append(math.degrees(angle_in_radians))
    #print(degrees)

    # label = data['Oцінка задоволення сусідом']
    # #print(label)
    # comparison =[[label[i], degrees[i]] for i in range(len(degrees))]
    #print(comparison)
    #interpretatiion of degrees
    #0-50 - similar
    #50-90 - uncorrelated not similar
    #180 - opposite
    # two=[i for i in comparison if i[0] == 2]
    # three =[i for i in comparison if i[0] == 3]
    # four = [i for i in comparison if i[0] == 4]
    # five = [i for i in comparison if i[0] == 5]
    #
    # import numpy as np
    # print(np.mean([round(i[1],1) for i in five]))
    return degrees


import json
import logging
import traceback

class Log:
    @staticmethod
    def log(o: any, title: str = "", jsonFormat: bool = False) -> None:
        # Sends input logs to the "checkpoint" logger (settings).
        log = logging.getLogger("django")
        if title:
            if title == "_":
                for j in range(80):
                    title = title + "_"
            log.debug(title)

        if jsonFormat:
            log.debug(json.dumps(o))
        else:
            log.debug(o)

        if title:
            log.debug(title)

    @staticmethod
    def dump(o: any) -> None:
        import re
        log = logging.getLogger("django")

        oOut = dict()
        oVars = vars(o)
        oDir = dir(o)

        for i, v in enumerate(oDir):
            if v in oVars:
                oOut[v] = oVars[v]
            else:
                if not re.search("^__(.*)__$", str(v)):
                    oOut[v] = getattr(o, v)

        log.debug(oOut)

    @staticmethod
    def logException(e: Exception) -> None:
        # Logs the stack trace information and the raw output if any.
        Log.log(traceback.format_exc(), 'Error')

        try:
            Log.log(e.raw, 'Raw f5 data')
        except Exception:
            pass

    @staticmethod
    def actionLog(o: any, user: dict = None) -> None:
        # Sends input logs to the "f5" logger (settings).
        user = user or {}
        log = logging.getLogger("django")

        try:
            if "username" in user:
                log.debug("["+user['username']+"] "+o)
            else:
                log.debug(o)
        except Exception:
            pass


# -*- coding: utf-8 -*-
import numpy as np
import math
import random
import copy

def calcbits(bounds,precision):
    xRange = bounds[:,1] - bounds[:,0]
    bits = np.ceil(np.log2(xRange/precision))
    return bits

class Ga(object):
    def __init__(self, bounds, popSize=100,  pc=0.7, pm=0.08, options=(1e-6, 1),epoch=50):
        self.popSize = popSize
        self.bounds = bounds
        self.pc = pc
        self.pm = pm
        self.options = options
        self.maxGen = epoch
        self.numVar = bounds.shape[0]

    def initPop(self):
        popSize = self.popSize
        bounds = self.bounds
        chromLength = calcbits(bounds,self.options[0])
        bitLength = int(np.sum(chromLength))
        pop = np.round(np.random.random([popSize,bitLength]))
        return pop

    def tournSelect(self,pop,fitvalue,tournament_size=3):
        tournSize = tournament_size
        e = pop.shape[1]
        n = pop.shape[0]
        newPop = np.zeros((n,e))
        tourns = np.floor(np.random.rand(tournSize, n)*n)
        tourns[tourns==n] = n-1

        for i in range(n):
            curIndex = tourns[:,i]
            curIndex = curIndex.astype(np.int16)
            candiate = fitvalue[curIndex]
            if self.options[1]==1:
                winnerIndex = np.argmin(candiate)
            else:
                winnerIndex = np.argmax(candiate)
            newPop[i,:] = pop[curIndex][winnerIndex]

        return newPop

    def normGeomSelect(self,pop,fitvalue,Pro=0.09):
        q = Pro
        e = pop.shape[1]
        n = pop.shape[0]
        newPop = np.zeros((n, e))
        fit = np.zeros(n)
        x = np.zeros((n, 2),dtype=np.int)
        x[:,0] = np.arange(n, 0, -1)
        x[:,1] = np.argsort(fitvalue)
        r = q / (1 - np.power(1-q,n))
        fit[x[:,1]] = r * np.power(1-q, x[:,0] - 1)
        fit = np.cumsum(fit)
        rNums = np.sort(np.random.random(n))

        fitin = 0
        newin = 0

        while newin < n:
            if rNums[newin] < fit[fitin]:
                newPop[newin,:] = pop[fitin, :]
                newin += 1
            else:
                fitin += 1
        return newPop

    def selection(self,pop, fitvalue):

        [px, py] = pop.shape[:]
        fitvalue = fitvalue + abs(np.min(fitvalue))

        totalfit = np.sum(fitvalue)
        p_fitvalue = fitvalue / totalfit
        p_fitvalue = np.cumsum(p_fitvalue)
        ms = np.sort(np.random.random(px))
        fitin = 0
        newin = 0
        newpop = None

        while newin < px:
            if ms[newin] < p_fitvalue[fitin]:
                if newpop is None:
                    newpop = pop[fitin, :].reshape((1, -1))
                else:
                    newpop = np.concatenate((newpop, pop[fitin, :].reshape((1, -1))), axis=0)
                newin += 1

            else:
                fitin += 1
        return newpop

    def crossover(self,pop):
        [px, py] = pop.shape[:]
        newpop = np.ones(pop.shape)

        for i in range(0,px-1,2):
            if random.random() < self.pc:
                cpoint =round(random.random()*py)
                if cpoint==py:
                    cpoint = py-1
                newpop[i,:] = np.concatenate((pop[i,0:cpoint],pop[i+1,cpoint:]),axis=0)
                newpop[i+1, :] = np.concatenate((pop[i+1,0:cpoint], pop[i, cpoint:]), axis=0)
            else:
                newpop[i, :] = pop[i,:]
                newpop[i+1, :] = pop[i+1, :]
        return newpop

    def mutation(self,pop):
        [px, py] = pop.shape[:]
        newpop = np.ones(pop.shape)

        for i in range(px):
            if random.random() <self.pm:
                mpoint = round(random.random()*py)
                if mpoint==py:
                    mpoint = py-1
                newpop[i,:] = pop[i,:]
                if newpop[i,mpoint]==0:
                    newpop[i, mpoint] = 1
                else:
                    newpop[i, mpoint] = 0
            else:
                newpop[i, :] = pop[i, :]
        return newpop

    @staticmethod
    def binary2decimal(pop,bounds,eps):

        numVar = bounds.shape[0]
        chromList = calcbits(bounds, eps)

        xrange = bounds[:,1] - bounds[:,0]
        [px, py] = pop.shape[:]
        startIndex = 0
        FinalPos = np.zeros((px,numVar))

        for k in range(numVar):
            singlePop = pop[:,startIndex:startIndex+int(chromList[k])]
            startIndex = startIndex + int(chromList[k])
            py = int(chromList[k])
            pop1 = None
            for i in range(py):
                temp = np.power(2, (py - 1 - i) * singlePop[:, i])
                if pop1 is None:
                    pop1 = temp.reshape((-1, 1))
                else:
                    pop1 = np.concatenate((pop1, temp.reshape((-1, 1))), axis=1)
            temp = np.sum(pop1, axis=1)
            FinalPos[:, k] = temp * xrange[k]/(np.power(2.0, chromList[k]) - 1) + bounds[k,0]

        return FinalPos

    def train(self,Func,kwargs):
        print('开始遗传优化')
        pop = self.initPop()
        decimalValue = Ga.binary2decimal(pop,self.bounds,self.options[0])
        kwargs['pop'] = decimalValue
        fitness = Func(**kwargs)

        if self.options[1]==1:
            index = np.argmin(fitness)
            bestfit = np.min(fitness)
        else:
            index = np.argmax(fitness)
            bestfit = np.max(fitness)

        bestSolution = pop[index,:]
        record = np.zeros(self.maxGen)
        for i in range(self.maxGen):

            # 选择操作
            newpop = self.tournSelect(pop,fitness)

            #交叉操作
            newpop = self.crossover(newpop)

            #变异操作
            newpop = self.mutation(newpop)

            decimalValue = Ga.binary2decimal(newpop, self.bounds, self.options[0])
            kwargs['pop'] = decimalValue
            fitness = Func(**kwargs)

            if self.options[1] == 1:
                index = np.argmin(fitness)
                bestFitValue = np.min(fitness)
            else:
                index = np.argmax(fitness)
                bestFitValue = np.max(fitness)

            bestindividual = newpop[index, :]

            if self.options[1] == 1:
                if bestFitValue < bestfit:
                    bestfit = bestFitValue
                    bestSolution = bestindividual
            else:
                if bestFitValue > bestfit:
                    bestfit = bestFitValue
                    bestSolution = bestindividual

            record[i] = bestfit
            # print('Fitness[%d]: %.3f' % (i, record[i]))
            print("%d/%d[==============]Loss:%.4f" % (i + 1, self.maxGen, record[i]))
            pop = newpop

        bestSolution = bestSolution.reshape(1,-1)
        bestSolution = Ga.binary2decimal(bestSolution, self.bounds, self.options[0])

        bestSolution = bestSolution.reshape(bestSolution.shape[1],)
        return bestSolution, record


# -*- coding: utf-8 -*-
#2-3. 다중 회귀 분석 Multivariate Regression
# 여러개의 독립 변수가 종속 변수에 영향을 주고 선형 관계를 갖는 경우 사용(지도 학습; 실제 종속변수 데이터 알고 있는 상태에서 학습하므로)
# 각 독립 변수의 계수와 상수항에 적절한 값을 찾아 모형 완성(Y=b+a1x1+a2X2+''')

### 기본 라이브러리 불러오기
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

'''
[Step 1 ~ 3] 데이터 준비
'''
# CSV 파일을 데이터프레임으로 변환
df = pd.read_csv('./auto-mpg.csv', header=None)

# 열 이름 지정
df.columns = ['mpg','cylinders','displacement','horsepower','weight',
              'acceleration','model year','origin','name']

# horsepower 열의 자료형 변경 (문자열 ->숫자)
df['horsepower'].replace('?', np.nan, inplace=True)      # '?'을 np.nan으로 변경
df.dropna(subset=['horsepower'], axis=0, inplace=True)   # 누락데이터 행을 삭제
df['horsepower'] = df['horsepower'].astype('float')      # 문자열을 실수형으로 변환

# 분석에 활용할 열(속성)을 선택 (연비, 실린더, 출력, 중량)
ndf = df[['mpg', 'cylinders', 'horsepower', 'weight']]

'''
Step 4: 데이터셋 구분 - 훈련용(train data)/ 검증용(test data)
'''

# 속성(변수) 선택: 여러개의 독립변수, x: dataframe
X=ndf[['cylinders', 'horsepower', 'weight']]  #독립 변수 X1, X2, X3
y=ndf['mpg']     #종속 변수 Y

# train data 와 test data로 구분(7:3 비율)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=10)

print('훈련 데이터: ', X_train.shape)
print('검증 데이터: ', X_test.shape)
print('\n')

'''
Step 5: 다중회귀분석 모형 - sklearn 사용 (모형 학습 및 검증)
'''

# sklearn 라이브러리에서 선형회귀분석 모듈 가져오기
from sklearn.linear_model import LinearRegression

# 단순회귀분석 모형 객체 생성
lr = LinearRegression()

# train data를 가지고 모형 학습
lr.fit(X_train, y_train)

# 학습을 마친 모형에 test data(검증 데이터)를 적용하여 결정계수(R-제곱) 계산 (훈련데이터 제외)
r_square = lr.score(X_test, y_test) #평가 지표 결정계수
print(r_square)
print('\n')

# 회귀식의 기울기
print('X 변수의 계수 a: ', lr.coef_) #리스트 형태로 반환[, ,]
print('\n')

# 회귀식의 y절편
print('상수항 b', lr.intercept_)
print('\n')

#모형이 예측한 결과와 실제 값 비교
# train data의 산점도와 test data로 예측한 회귀선을 그래프로 출력
y_hat = lr.predict(X_test) #모형 예측값 저장

plt.figure(figsize=(10, 5))
ax1 = sns.kdeplot(y_test, label="y_test") #실제 예측값
ax2 = sns.kdeplot(y_hat, label="y_hat", ax=ax1)
plt.legend() # plt.legend():   https://pyvisuall.tistory.com/55
plt.show()
# 단순 회귀 분석에 비해 덜 뾰족하지만(첨도가 누그러짐)(7-1),
#다항 회귀 분석에 비해서는 두 그래프가 편향된 정도가 더 큰 듯(7-2)


#----------------------------------------------------------------------------#
# Imports
#----------------------------------------------------------------------------#

import json
import dateutil.parser
import babel
from flask import Flask, render_template, request, Response, flash, redirect, url_for
from flask_moment import Moment
from flask_sqlalchemy import SQLAlchemy
import logging
from logging import Formatter, FileHandler
from flask_wtf import Form
from forms import *

from flask_migrate import Migrate
from datetime import datetime
import sys
from models import db, app, Venue, Artist, Show

#----------------------------------------------------------------------------#
# App Config.
#----------------------------------------------------------------------------#

# app = Flask(__name__)
moment = Moment(app)
app.config.from_object('config')
# db = SQLAlchemy(app)
db.init_app(app)

# TODO: connect to a local postgresql database
# migrate = Migrate(app, db)

#----------------------------------------------------------------------------#
# Models.
#----------------------------------------------------------------------------#

#----------------------------------------------------------------------------#
# Filters.
#----------------------------------------------------------------------------#

def format_datetime(value, format='medium'):
  date = dateutil.parser.parse(value)
  if format == 'full':
      format="EEEE MMMM, d, y 'at' h:mma"
  elif format == 'medium':
      format="EE MM, dd, y h:mma"
  return babel.dates.format_datetime(date, format, locale='en')

app.jinja_env.filters['datetime'] = format_datetime

#----------------------------------------------------------------------------#
# Controllers.
#----------------------------------------------------------------------------#

@app.route('/')
def index():
  return render_template('pages/home.html')

#  Venues
#  ----------------------------------------------------------------

@app.route('/venues')
def venues():
  # TODO: replace with real venues data.
  # num_shows should be aggregated based on number of upcoming shows per venue.

  print(datetime.today())
  # print('2021-05-04 22:20:28.968967'==datetime.now())

  data = []
  citiesstates = Venue.query.with_entities(Venue.city,Venue.state).group_by(Venue.city,Venue.state).all()
  # print(citiesstates)
  for citystate in citiesstates:
    # print(Venue.city.value)
    venues = Venue.query.filter(Venue.city==citystate.city, Venue.state==citystate.state).all()
    venuesindata=[]
    for venue in venues:
      # num_upcoming_shows = venue.query(func.count().filter(Show.start_time > db.DateTime.now()))
      upcoming_shows=venue.showss.filter(Show.start_time > datetime.now()).all()
      num_upcoming_shows=len(upcoming_shows)
      venuesindata.append(
        {
          "id": venue.id,
          "name": venue.name,
          "num_upcoming_shows":num_upcoming_shows
        }
      )
    data.append({
      "city":citystate.city,
      "state":citystate.state,
      "venues": venuesindata
    })
    # print(data)
  # if error:
  #   return render_template('errors/404.html')
  return render_template('pages/venues.html', areas=data);

@app.route('/venues/search', methods=['POST'])
def search_venues():
  # TODO: implement search on artists with partial string search. Ensure it is case-insensitive.
  # seach for Hop should return "The Musical Hop".
  # search for "Music" should return "The Musical Hop" and "Park Square Live Music & Coffee"
  search_term = request.form.get('search_term')
  items = Venue.query.filter(Venue.name.ilike('%'+search_term+'%')).all()
  data = []
  count = len(items)

  for item in items:
    num_upcoming_shows=len(item.showss.filter(Show.start_time > datetime.now()).all())
    data.append({
      "id":item.id,
      "name":item.name,
      "num_upcoming_shows":num_upcoming_shows
  })
  response=({"count":count,"data":data})

  return render_template('pages/search_venues.html', results=response, search_term=request.form.get('search_term', ''))

@app.route('/venues/<int:venue_id>')
def show_venue(venue_id):
  # shows the venue page with the given venue_id
  # TODO: replace with real venue data from the venues table, using venue_id
  # print(venue1)

  # The code joins tables from existing models to select Artists by Venues where they previously performed,
  # successfully filling out the Venues page with a “Past Performances” section.

  venue1 = Venue.query.get(venue_id)
  # upcoming_shows = venue1.showss.filter(Show.start_time > datetime.now()).all()
  # num_upcoming_shows = len(upcoming_shows)

  # jnArSh = db.session.query(Show,Artist).join(Artist).filter(Show.venue_id==venue_id)
  upcoming_shows = db.session.query(Show,Artist).join(Artist,Show.artist_id==Artist.id).filter(Show.venue_id==venue_id,Show.start_time>datetime.now())
  num_upcoming_shows = 0
  print(num_upcoming_shows)

  upcoming_shows_list = []
  for upcoming_show in upcoming_shows:
    num_upcoming_shows +=1
    upcoming_shows_list.append(
      {
      # "artist_id": upcoming_show.artist_id,
      "artist_id": upcoming_show.Artist.id,
      # "artist_name": upcoming_show.artist.name,
      "artist_name": upcoming_show.Artist.name,
      # "artist_image_link": upcoming_show.artist.image_link,
      "artist_image_link": upcoming_show.Artist.image_link,
      # "start_time": str(upcoming_show.start_time)
      "start_time": str(upcoming_show.Show.start_time)
      }
    )

  past_shows_list=[]

  # past_shows=venue1.showss.filter(Show.start_time < datetime.now()).all()
  # num_past_shows=len(past_shows)

  # past_shows = jnArSh.filter(Show.start_time < datetime.now()).all
  past_shows = db.session.query(Show, Artist).join(Artist).filter(Show.venue_id==venue_id,Show.start_time<datetime.now())
  # num_past_shows = 0
  # print(past_shows)

  for past_show in past_shows:
    # num_past_shows +=1
    # print(past_show.artist)
    past_shows_list.append(
      {
      "artist_id": past_show.Artist.id,
      "artist_name": past_show.Artist.name,
      "artist_image_link": past_show.Artist.image_link,
      "start_time": str(past_show.Show.start_time)
      }
    )
  num_past_shows = len(past_shows_list)
  # print(past_show.artist.name)
  # x="".join(venue1.genres)
  # print(x)
  # for genre in x:
  #   print( genre)
  data1 = {
    "id": venue1.id,
    "name": venue1.name,
    # "genres": "".join(venue1.genres).split(','),
    "genres": venue1.genres.split(','),
    "address": venue1.address,
    "city": venue1.city,
    "state": venue1.state,
    "phone": venue1.phone,
    "website": venue1.website,
    "facebook_link": venue1.facebook_link,
    "seeking_talent": venue1.seeking_talent,
    "seeking_description": venue1.seeking_description,
    "image_link": venue1.image_link,
    "past_shows":past_shows_list,
    "upcoming_shows":upcoming_shows_list,
    "past_shows_count":num_past_shows,
    "upcoming_shows_count":num_upcoming_shows
  }
  print(data1['genres'])

  # data = list(filter(lambda d: d['id'] == venue_id, [data1, data2, data3]))[0]
  return render_template('pages/show_venue.html', venue=data1)

#  Create Venue
#  ----------------------------------------------------------------

@app.route('/venues/create', methods=['GET'])
def create_venue_form():
  form = VenueForm()
  return render_template('forms/new_venue.html', form=form)

@app.route('/venues/create', methods=['POST'])
def create_venue_submission():
  # TODO: insert form data as a new Venue record in the db, instead
  # TODO: modify data to be the data object returned from db insertion

  error = False
  # form = VenueForm()
  data = request.form
  print(data)
  name = data['name']
  city = data['city']
  state = data['state']
  address = data['address']
  phone = data['phone']
  # print(request.form.genres.data)
  # genres = data.getlist('genres')
  genres = ",".join(data.getlist('genres'))
  print(genres)
  facebook_link = data['facebook_link']
  image_link = data['image_link']
  website = data['website_link']

  seeking_talent='seeking_talent' in data
  print(seeking_talent)
  seeking_description = data['seeking_description']

  try:
    venue = Venue(
      name = name,
      city = city,
      state = state,
      address = address,
      phone = phone,
      # genres = ','.join(genres),
      # genres=genres.split(','),
      genres = genres,
      facebook_link = facebook_link,
      image_link = image_link,
      website = website,
      seeking_talent = seeking_talent,
      seeking_description = seeking_description
    )
    print(venue.genres)
    # print(venue.genres.split(','))
    # form.populate_obj(venue)

    db.session.add(venue)
    db.session.commit()

  except:
    error = True
    db.session.rollback()
    print(sys.exc_info())

  finally:
    db.session.close()

  # on successful db insert, flash success
  # flash('Venue ' + request.form['name'] + ' was successfully listed!')
  if not error:
    flash('Venue ' + name + ' was successfully listed!')

  # TODO: on unsuccessful db insert, flash an error instead.
  # e.g., flash('An error occurred. Venue ' + data.name + ' could not be listed.')
  # see: http://flask.pocoo.org/docs/1.0/patterns/flashing/
  else:
    flash('An error occurred. Venue ' + request.form['name'] + ' could not be listed.')

  return render_template('pages/home.html')

@app.route('/venues/<venue_id>/delete', methods=['GET'])
def delete_venue(venue_id):
  # TODO: Complete this endpoint for taking a venue_id, and using
  # SQLAlchemy ORM to delete a record. Handle cases where the session commit could fail.

  venue = Venue.query.get(venue_id)
  error = False
  try:
    db.session.delete(venue)
    db.session.commit()
  except:
    db.session.rollback()
    error = True
  finally:
    db.session.close()
  if not error:
    flash(f'Venue {venue.name} deleted')
  else:
    flash('Venue not deleted')

  # BONUS CHALLENGE: Implement a button to delete a Venue on a Venue Page, have it so that
  # clicking that button delete it from the db then redirect the user to the homepage

  # DELETE Button added in show_venues.html
  return redirect(url_for('index'))

# ADDED THING
# ----------------delete artist--------------------------#
@app.route('/artists/<artist_id>/delete', methods=['GET'])
def delete_artist(artist_id):
  artist = Artist.query.get(artist_id)
  error = False
  try:
    db.session.delete(artist)
    db.session.commit()
  except:
    db.session.rollback()
    error = True
  finally:
    db.session.close()
  if not error:
    flash('Artist '+ artist.name + ' deleted')
  else:
    flash('not deleted!')

  # DELETE Button added on show_venues.html
  return redirect(url_for('index'))

#  Artists
#  ----------------------------------------------------------------
@app.route('/artists')
def artists():
  # TODO: replace with real data returned from querying the database

  data = []
  artists = Artist.query.all()
  for artist in artists:
    data.append(
      {
        "id": artist.id,
        "name":artist.name
      }
    )
  # print(data)

  return render_template('pages/artists.html', artists=data)

@app.route('/artists/search', methods=['POST'])
def search_artists():
  # TODO: implement search on artists with partial string search. Ensure it is case-insensitive.
  # seach for "A" should return "Guns N Petals", "Matt Quevado", and "The Wild Sax Band".
  # search for "band" should return "The Wild Sax Band".

  search_term = request.form.get('search_term')
  items = Artist.query.filter(Artist.name.ilike(f'%{search_term}%')).all()

  data = []
  count = len(items)

  for item in items:
    num_upcoming_shows=len(item.showss.filter(Show.start_time > datetime.now()).all())
    data.append({
      "id":item.id,
      "name":item.name,
      "num_upcoming_shows":num_upcoming_shows
  })
  response=({"count":count,"data":data})

  return render_template('pages/search_artists.html', results=response, search_term=request.form.get('search_term', ''))

@app.route('/artists/<int:artist_id>')
def show_artist(artist_id):
  # shows the artist page with the given artist_id
  # # TODO: replace with real artist data from the artist table, using artist_id
  artist1 = Artist.query.get(artist_id)
  jnVnSh = db.session.query(Show,Venue).join(Venue, Show.venue_id==Venue.id)
  upcoming_shows = jnVnSh.filter(Show.artist_id==artist_id,Show.start_time>datetime.now())

  # upcoming_shows=artist1.showss.filter(Show.start_time > datetime.now()).all()
  # num_upcoming_shows=len(upcoming_shows)

  # num_upcoming_shows = 0

  upcoming_shows_list=[]
  for upcoming_show in upcoming_shows:
    # num_upcoming_shows +=1
    upcoming_shows_list.append(
      {
      "venue_id": upcoming_show.Venue.id,
      "venue_name": upcoming_show.Venue.name,
      "venue_image_link": upcoming_show.Venue.image_link,
      "start_time": str(upcoming_show.Show.start_time)
      }
    )
  num_upcoming_shows=len(upcoming_shows_list)
  past_shows_list=[]

  # past_shows=artist1.showss.filter(Show.start_time < datetime.now()).all()
  # num_past_shows=len(past_shows)

  past_shows = jnVnSh.filter(Show.artist_id==artist_id,Show.start_time<datetime.now())

  for past_show in past_shows:
    # num_past_shows += 1
    past_shows_list.append(
      {
      "venue_id": past_show.Venue.id,
      "venue_name": past_show.Venue.name,
      "venue_image_link": past_show.Venue.image_link,
      "start_time": str(past_show.Show.start_time)
      }
    )
  num_past_shows=len(past_shows_list)

  data1 = {
    "id": artist1.id,
    "name": artist1.name,
    "genres": artist1.genres.split(','),
    "city": artist1.city,
    "state": artist1.state,
    "phone": artist1.phone,
    "website": artist1.website,
    "facebook_link": artist1.facebook_link,
    "seeking_venue": artist1.seeking_venue,
    "seeking_description": artist1.seeking_description,
    "image_link": artist1.image_link,
    "past_shows":past_shows_list,
    "upcoming_shows":upcoming_shows_list,
    "past_shows_count":num_past_shows,
    "upcoming_shows_count":num_upcoming_shows
  }
  print(data1)
  print(data1['genres'])

  # data = list(filter(lambda d: d['id'] == artist_id, [data1, data2, data3]))[0]
  return render_template('pages/show_artist.html', artist=data1)

#  Update
#  ----------------------------------------------------------------
@app.route('/artists/<int:artist_id>/edit', methods=['GET'])
def edit_artist(artist_id):
  artist = Artist.query.get(artist_id)
  # print(artist)
  form = ArtistForm()

  form.name.data = artist.name
  form.genres.data = artist.genres
  form.city.data = artist.city
  form.state.data = artist.state
  form.phone.data= artist.phone
  form.website_link.data = artist.website
  form.facebook_link.data = artist.facebook_link
  form.image_link.data = artist.image_link
  print(artist.seeking_venue)
  if artist.seeking_venue:
    form.seeking_venue.data ='y'
  form.seeking_description.data = artist.seeking_description

  # form = ArtistForm(obj=artist)

  # TODO: populate form with fields from artist with ID <artist_id>
  return render_template('forms/edit_artist.html', form=form, artist=artist)

@app.route('/artists/<int:artist_id>/edit', methods=['POST'])
def edit_artist_submission(artist_id):
  # TODO: take values from the form submitted, and update existing
  # artist record with ID <artist_id> using the new attributes

  error = False
  data = request.form
  artist = Artist.query.get(artist_id)

  if request.method == 'POST':

    try:
      name = data['name']
      city = data['city']
      state = data['state']
      phone = data['phone']
      genres = ",".join(data.getlist('genres'))
      facebook_link = data['facebook_link']
      image_link = data['image_link']
      website = data['website_link']
      seeking_venue = 'seeking_venue' in data
      seeking_description = data['seeking_description']

      artist.name = name
      artist.city = city
      artist.state = state
      artist.phone = phone
      artist.genres = genres
      artist.facebook_link = facebook_link
      artist.image_link = image_link
      artist.website = website
      artist.seeking_venue = seeking_venue
      artist.seeking_description = seeking_description

      db.session.commit()

    except:
      error = True
      db.session.rollback()
      print(sys.exc_info())

    finally:
      db.session.close()

    if not error:
      flash('successfully updated!')

    else:
      flash('could not be updated.')

  return redirect(url_for('show_artist', artist_id = artist_id))

@app.route('/venues/<int:venue_id>/edit', methods = ['GET'])
def edit_venue(venue_id):
  form = VenueForm()
  venue = Venue.query.get(venue_id)

  form.name.data = venue.name
  form.genres.data = venue.genres
  form.address.data = venue.address
  form.city.data = venue.city
  form.state.data = venue.state
  form.phone.data= venue.phone
  form.website_link.data = venue.website
  form.facebook_link.data = venue.facebook_link
  form.image_link.data = venue.image_link
  if venue.seeking_talent:
    form.seeking_talent.data ='y'
  form.seeking_description.data = venue.seeking_description

  # TODO: populate form with values from venue with ID <venue_id>
  return render_template('forms/edit_venue.html', form=form, venue=venue)

@app.route('/venues/<int:venue_id>/edit', methods=['POST'])
def edit_venue_submission(venue_id):
  # TODO: take values from the form submitted, and update existing
  # venue record with ID <venue_id> using the new attributes

  error = False
  # form = VenueForm(request.form)
  # form = VenueForm()

  data = request.form
  venue = Venue.query.get(venue_id)
  # if form.validate_on_submit():

  if request.method == 'POST':
    try:
      name = data['name']
      city = data['city']
      state = data['state']
      address = data['address']
      phone = data['phone']
      genres = ",".join(data.getlist('genres'))
      facebook_link = data['facebook_link']
      image_link = data['image_link']
      website = data['website_link']
      # seeking_talent = data['seeking_talent']
      # seeking_talent = False
      # if 'seeking_talent' in data =='y':
      #   seeking_talent = True
      seeking_talent = 'seeking_talent' in data
      seeking_description = data['seeking_description']

      # venue = Venue(
      venue.name = name
      venue.city = city
      venue.state = state
      venue.address = address
      venue.phone = phone
      venue.genres = genres
      venue.facebook_link = facebook_link
      venue.image_link = image_link
      venue.website = website
      venue.seeking_talent = seeking_talent
      venue.seeking_description = seeking_description
      # )
      # print(venue.seeking_talent)
      db.session.commit()
      print(venue.address)

    except:
      error = True
      db.session.rollback()
      print(sys.exc_info())

    finally:
      db.session.close()

    if not error:
      flash('Venue successfully updated!')

    else:
      flash('could not be updated.')
  # return render_template('forms/edit_venue.html', form=data, venue=venue)
  return redirect(url_for('show_venue', venue_id=venue_id))

#  Create Artist
#  ----------------------------------------------------------------

@app.route('/artists/create', methods=['GET'])
def create_artist_form():
  form = ArtistForm()
  return render_template('forms/new_artist.html', form=form)

@app.route('/artists/create', methods=['POST'])
def create_artist_submission():
  # called upon submitting the new artist listing form
  # TODO: insert form data as a new Venue record in the db, instead
  # TODO: modify data to be the data object returned from db insertion

  error = False
  data = request.form

  name = data['name']
  city = data['city']
  state = data['state']
  phone = data['phone']

  print(data.getlist('genres'))

  genres = ",".join(data.getlist('genres'))
  print(genres)

  facebook_link = data['facebook_link']
  image_link = data['image_link']
  website = data['website_link']
  print('seeking venue?')
  print('seeking_venue' in data)
  seeking_venue='seeking_venue' in data
  seeking_description = data['seeking_description']
  try:
    artist = Artist(
      name = name,
      city = city,
      state = state,
      phone = phone,
      genres = genres,
      facebook_link = facebook_link,
      image_link = image_link,
      website = website,
      seeking_venue = seeking_venue,
      seeking_description = seeking_description
    )
    db.session.add(artist)
    db.session.commit()

  except:
    error = True
    db.session.rollback()
    print(sys.exc_info())

  finally:
    db.session.close()

  # on successful db insert, flash success
  if not error:
    flash('Artist ' + request.form['name'] + ' was successfully listed!')

  # TODO: on unsuccessful db insert, flash an error instead.
  else:
    flash('An error occurred. Artist ' + name + ' could not be listed.')
  # e.g., flash('An error occurred. Artist ' + data.name + ' could not be listed.')
  print(seeking_venue)
  return render_template('pages/home.html')

#  Shows
#  ----------------------------------------------------------------

@app.route('/shows')
def shows():
  # displays list of shows at /shows
  # TODO: replace with real venues data.
  #       num_shows should be aggregated based on number of upcoming shows per venue.
  data = []
  shows = Show.query.all()
  for show in shows:
    data.append ({
      "venue_id": show.id,
      "venue_name": show.venue.name,
      "artist_id": show.artist.id,
      "artist_name": show.artist.name,
      "artist_image_link": show.artist.image_link,
      "start_time": str(show.start_time)
    })

  return render_template('pages/shows.html', shows=data)

@app.route('/shows/create')
def create_shows():
  # renders form. do not touch.
  form = ShowForm()
  return render_template('forms/new_show.html', form=form)

@app.route('/shows/create', methods=['POST'])
def create_show_submission():
  # called to create new shows in the db, upon submitting new show listing form
  # TODO: insert form data as a new Show record in the db, instead

  error = False
  data = request.form

  venue_id = data['venue_id']
  artist_id = data['artist_id']
  start_time = data['start_time']
  try:
    show = Show(
      venue_id = venue_id,
      artist_id = artist_id,
      start_time = start_time
    )
    db.session.add(show)
    db.session.commit()

  except:
    error = True
    db.session.rollback()
    print(sys.exc_info())

  finally:
    db.session.close()

  if not error:
    flash('Show was successfully listed!')
  # TODO: on unsuccessful db insert, flash an error instead.

  else:
    flash('An error occurred. Show could not be listed.')
  # e.g., flash('An error occurred. Show could not be listed.')
  # see: http://flask.pocoo.org/docs/1.0/patterns/flashing/
  return render_template('pages/home.html')

@app.errorhandler(404)
def not_found_error(error):
    return render_template('errors/404.html'), 404

@app.errorhandler(500)
def server_error(error):
    return render_template('errors/500.html'), 500

if not app.debug:
    file_handler = FileHandler('error.log')
    file_handler.setFormatter(
        Formatter('%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]')
    )
    app.logger.setLevel(logging.INFO)
    file_handler.setLevel(logging.INFO)
    app.logger.addHandler(file_handler)
    app.logger.info('errors')

#----------------------------------------------------------------------------#
# Launch.
#----------------------------------------------------------------------------#

# Default port:
if __name__ == '__main__':
    app.run()

# Or specify port manually:
# '''
# if __name__ == '__main__':
#     port = int(os.environ.get('PORT', 5000))
#     app.run(host='0.0.0.0', port=port)
# '''


# Задача 32: Определить индексы элементов массива (списка),
# значения которых принадлежат заданному диапазону
# (т.е. не меньше заданного минимума и не больше заданного максимума)

lst = [-5, 9, 0, 3, -1, -2, 1, 4, -2, 10, 2, 0, -9, 8, 10, -9, 0, -5, -5, 7]

inp_min = int(input('Min: '))
inp_max = int(input('Max: '))

# Создание списка всех элементов которые нужно проверить
# Проверка если пользователь не знает какое число меньше и больше ))
if inp_min > inp_max:
    inp_min, inp_max = inp_max, inp_min

# Проверка границ (обрезаем ненужное)
if inp_min < min(lst): inp_min = min(lst)
if inp_max > max(lst): inp_max = max(lst)

# Создаем список для проверки
lst_enter = [*range(inp_min, inp_max)]

# Основной цикл программы
lst_indx = []
for i in range(len(lst)):
    if lst[i] in lst_enter:
        lst_indx.append(i)

print(lst_indx)


#!/usr/bin/python3
"""
Created on Mon Oct 29 10:37:34 2018

@author: fangyucheng
"""

import cgi
import jieba

parameter = cgi.FieldStorage()

sentence = parameter['input'].value

cut_result = jieba.lcut(sentence)

output_words = ','.join(cut_result)

print("Content-type: text/html\n")
print("<TITLE>Cut Result</TITLE>")
print("
your sentence has been cut
")
print("
cut_result: %s
" % output_words)


from collections import defaultdict

class Node:
  def __init__(self, value):
    self.adjacent = []
    self.value = value

def reverse_graph(graph):
  reversed = defaultdict(list)

  for _, node in graph.items():
    for adjacent in node.adjacent:
      reversed[adjacent.value].append(node.value)

  for k in graph:
    graph[k].adjacent = reversed[k]

  return graph

a = Node('a')
b = Node('b')
c = Node('c')

a.adjacent += [b, c]
b.adjacent += [c]

graph = {
    a.value: a,
    b.value: b,
    c.value: c,
}

for _, val in reverse_graph(graph).items():
  print(val.adjacent)

Reverse a Directed Graph/Reverse a Directed Graph.py


from os import path
from setuptools import find_packages, setup

DIR_PATH = path.dirname(path.realpath(__file__))
VERSION_FILE = path.join(DIR_PATH, 'VERSION')

try:
    version = open(VERSION_FILE).read().strip()
except:
    version='0.0.1'

setup(
    name='mycli',
    version=version,
    description='dummy CLI with argparse',
    url='https://github.com/sahibdhanjal',
    maintainer='Sahib Dhanjal',
    packages=find_packages(exclude=[]),
    install_requires=[],
    package_data={'mycli':['./../VERSION']},
    entry_points={'console_scripts': ['mycli = mycli.__main__:main']},
)


import sys
import math

filename = sys.argv[1]
f1 = open(filename, 'r')
x = f1.read().splitlines()
f1.close

y = []
for term in x:
    y.append(term.split(','))
y = y[1:]

pos = 0
neg = 0
for i in range(len(y)):
    if y[i][len(y[0])-1] == 'democrat' or y[i][len(y[0])-1] == 'A':
        pos += 1
    if y[i][len(y[0])-1] == 'republican' or y[i][len(y[0])-1] == 'notA':
        neg += 1
probS = pos/float(pos+neg)
if pos >= neg:
    error = 1 - probS
else: error = probS
if probS == 0 or probS ==1:
    gainS = 0
else: gainS = probS* math.log(1/probS,2)+(1-probS)*math.log(1/(1-probS),2)

sys.stdout.write("entropy: %f\n" % gainS)
sys.stdout.write("error: %f" % error)


par_impar = [[],[]]                     # Cria duas listas dentro de uma (matriz)
cont_P_I = [0,0]                        # Variaveis q contam quantos elementos tem em cada vetor

def veri (valor_, ind_, txt_):          # Função: adiciona no vetor certo e verifica se está cheio
    par_impar[ind_].append(valor_)      # Adiciona o valor no vetor certo
    cont_P_I[ind_] += 1                 # Contador do vetor += 1

    if cont_P_I[ind_] == 5:                                                             # Se o contador for = 5 (se o vetor está cheio)
        [print('{}[{}] = {}' .format(txt_, x , par_impar[ind_][x])) for x in range(5)]  # Mostra ele
        par_impar[ind_] = []                                                            # Zera o vetor
        cont_P_I[ind_] = 0                                                              # Zera a lista

for x in range(15):
    num = int(input())                  # Entrada
    if num%2 == 0:                      # Verifica se eh par
        veri(num,0,'par')               # Orienta a função em qual vetor vai
    else:                               # Se for impar
        veri(num,1,'impar')             # Mesma coisa

maior = [[1,0],['par','impar']]         # Matrix: pega o vetor impar primeiro ddps o par e imprime (linha debaixo)
[[print('{}[{}] = {}' .format(maior[1][l], x , par_impar[l][x])) for x in range(len(par_impar[l]))] for l in maior[0] ]

Python/Uri 1179 - Preenchimento de Vetor IV.py


def partition(arr,low,high):
    pivot =arr[high]
    i=low-1

    for j in range(low,high):
        if arr[j]<=pivot:
            i=i+1
            temp=arr[i]
            arr[i]=arr[j]
            arr[j]=temp

    i=i+1
    temp=arr[i]
    arr[i]=pivot
    arr[high]=temp
    print(arr)
    return i

def quicksort(arr,low,high):
    if low<high:
        pivot=partition(arr,low,high)
        quicksort(arr,low,pivot-1)
        quicksort(arr,pivot+1,high)

arr=[6,3,9,5,10,8]
low=0
high=len(arr)-1

quicksort(arr,low,high)
print(arr)


import socket
import sys

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
	port = int(sys.argv[1])
	if (65535 < port) or (port < 1024):
		print ('Please enter a valid port1. Goodbye.')
		exit()

except:
	print ('Please enter a valid port. Goodbye.')
	exit()

ipAddress = '127.0.0.1'
server_address = (ipAddress,port)
sock.bind(server_address)

sock.listen(1)

print ('Server Running on port {} waiting...').format(port)

while True:
	connection, addr = sock.accept()
	print ('Got connection from:', addr)

	data = connection.recv(256)
	if data:
		print (data)
		if data == 'flag{y0u_say_hell0!}\n':
			connection.send('Correct: real flag is flag{and_I_say_g00dbye!}')
		else:
			connection.send('LOL. no.')
	else:
		print ('no more data')
		connection.close()


class Solution:
    def flipAndInvertImage(self, image: List[List[int]]) -> List[List[int]]:
        for i, row in enumerate(image):
            row.reverse()
            for j in range(len(row)):
                if row[j] == 0:
                    image[i][j] = 1
                else:
                    image[i][j] = 0
        return image


# Given the head of a linked list, return the node where the cycle begins. If there is no cycle, return null.

# There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail's next pointer is connected to (0-indexed). It is -1 if there is no cycle. Note that pos is not passed as a parameter.

# Do not modify the linked list.
# 142. Linked List Cycle II
# https://leetcode.com/problems/linked-list-cycle-ii/description/

# Approach: Floyd's cycle detection - Tortoise and Hare algo
# fast and slow pointer, fast will move 2x speed than slow
# if fast == slow, cycle detected
# once cycle detected, move the slow pointer to head, and
# fast stay at intersection, now both pointer move 1 step
# they will meet at the cycle point.

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow = head
        fast = head

        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next

            # If there is a cycle, the slow and fast pointers will eventually meet
            if slow == fast:
                # Move one of the pointers back to the start of the list
                slow = head
                while slow != fast:
                    slow = slow.next
                    fast = fast.next
                return slow
        # If there is no cycle, return None
        return None
# Input: head = [3,2,0,-4], pos = 1
# Output: tail connects to node index 1
# Explanation: There is a cycle in the linked list, where tail connects to the second node.