#!/usr/bin/python3

from __future__ import print_function
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from os import listdir
from os.path import isfile, join
from googleapiclient.http import MediaFileUpload
from datetime import datetime
import argparse
import pickle
import os.path
import ruamel.yaml
import sys

print()
print("Upload at: " + str(datetime.now()))
# os.chdir(r"/home/pcadmin/upload_script/")

# setup cli argparser interface for more flexibility
parser = argparse.ArgumentParser(description=(
    "This python script uploads files into the drive storage of a google account. For this to work, that account must "
    "activate the drive api (under step 1 here: https://developers.google.com/drive/api/v3/quickstart/python). There "
    "we obtain the file credentials.json, which is used to generate the token.pickle file from the browser that will "
    "pop up the first time this script is executed"))

parser.add_argument("-cf", "--config", type=str, help="The path to the config.yaml file")

args = parser.parse_args()

# read the config file passed as argument
yaml = ruamel.yaml.YAML()
with open(args.config) as f:
    config = yaml.load(f)

class Synchronizer:

    def __init__(self):
        self.service = None
        self.auth_run = False

        # Controls what the app is allowed to do in the cloud storage
        # If modifying these scopes, delete the file token.pickle. A new authentication process will be started that
        self.scopes = ['https://www.googleapis.com/auth/drive.file',
                       'https://www.googleapis.com/auth/drive.install']

        # Starts the authentication process of the client-side script
        self.authorize_app()

    def authorize_app(self):
        """
        Shows basic usage of the Drive v3 API.
        Prints the names and ids of the first 10 files the user has access to.
        """

        creds = None
        # The file token.pickle stores the user's access and refresh tokens, and is
        # created automatically when the authorization flow completes for the first
        # time.
        if os.path.exists(config["token_path"]):
            with open(config["token_path"], 'rb') as token:
                creds = pickle.load(token)

        # If there are no (valid) credentials available, let the user log in.
        if not creds or not creds.valid:
            if creds and creds.expired and creds.refresh_token:
                creds.refresh(Request())
            else:
                self.auth_run = True
                flow = InstalledAppFlow.from_client_secrets_file(config["credtials_path"], self.scopes)
                creds = flow.run_local_server()

            # Save the credentials for the next run
            with open(config["token_path"], 'wb') as token:
                pickle.dump(creds, token)

        self.service = build('drive', 'v3', credentials=creds)

    def get_folder_id(self, folder_name):
        """
        Returns the id of the given folder that exists in the cloud storage.
        :param folder_name: The name of the folder from which the ID is wanted
        :return:  The ID of the folder
        """
        page_token = None
        folder_id = ""
        while True:
            response = self.service.files().list(q=str("name='" + folder_name + "'"),
                                                 spaces='drive',
                                                 fields='nextPageToken, files(id, name)',
                                                 pageToken=page_token).execute()
            for file in response.get('files', []):
                # Process change
                folder_id = file.get('id')
            page_token = response.get('nextPageToken', None)
            if page_token is None:

                # if the remote folder does not exist
                if not folder_id:
                    print("Creating folder {} in GoogleDrive storage...".format(folder_name))
                    file_metadata = {
                        'name': folder_name,
                        'mimeType': 'application/vnd.google-apps.folder'
                    }
                    file = self.service.files().create(body=file_metadata,
                                                       fields='id').execute()

                    folder_id = file.get('id')
                else:
                    break

        return folder_id

    def get_remote_files(self, contain_query):
        """
        find all files in drive whose names containes the querry
        :param contain_query: the search querry which is checked for each files name
        :return: a list containing the file names of matches
        """
        page_token = None
        files_in_drive = []
        while True:
            print("Searching for files in Cloud storage...")
            # this gives us all files where the name contains .pdf (use this for .sql
            response = self.service.files().list(q="name contains '" + str(contain_query) + "'",
                                                 spaces='drive',
                                                 # fields='nextPageToken, files(id, name)',
                                                 fields='nextPageToken, files(*)',
                                                 pageToken=page_token).execute()

            for file in response.get('files', []):
                # only use file's that are not delete (this is probably only relevant for development)
                if not file["trashed"]:
                    files_in_drive.append(file.get('name'))

            page_token = response.get('nextPageToken', None)
            if page_token is None:
                break

        print("Found {} files in cloud storage containing the querry: {}".format(len(files_in_drive), contain_query))
        return files_in_drive

    @staticmethod
    def get_local_files(local_path, contain_query):
        """
        lists all files in the folder whose name contains the contain_query
        :param local_path: the path of the folder in which to search
        :param contain_query: the querry each files name in the folder must contain
        :return: a list of (full) file paths of the matches
        """
        print("Searching for files in local folder...")
        if os.path.exists(local_path):
            local_files = [join(local_path, f) for f in listdir(local_path) if
                           isfile(join(local_path, f)) and contain_query in f]

            print("Found {} files in {} containing the querry {}".format(len(local_files), local_path, contain_query))
            return local_files

        else:
            raise Exception("Path {0} does not exist".format(local_path))

    def upload_file(self, file, drive_folder=None):
        """
        Uploads a file into a folder on the cloud
        :param file: The file that is uploaded
        :param drive_folder: The target folder into which the file should be upload. If None uploads into root
        """
        if drive_folder is not None:
            # get id for parent folder, to save file in folder in cloud
            parent_id = self.get_folder_id(folder_name=drive_folder)
            file_metadata = {'name': str(os.path.basename(file)), 'parents': [parent_id]}
        else:
            file_metadata = {'name': str(os.path.basename(file))}

        # get file type for metadata and mimetype
        filename, file_extension = os.path.splitext(os.path.basename(file))
        if file_extension == '.sql':
            mimetype = 'application/sql'
        else:
            # default case
            mimetype = 'plain/text'

        media = MediaFileUpload(str(file),
                                mimetype=mimetype)

        file = self.service.files().create(body=file_metadata,
                                           media_body=media,
                                           fields='id').execute()

        print("File {} has been uploaded into the cloud folder {}".format(file_metadata["name"], drive_folder))

if __name__ == '__main__':
    # init drive api
    Synchronizer = Synchronizer()
    auth_run = Synchronizer.authorize_app()

    # if this was an execution acquiring the token.pickle file, stop further execution
    if Synchronizer.auth_run:
        sys.exit("Token file has been acquired, exiting...")

    # get a list of files that exists in the remote drive folder and contain the query
    remote_sql_files = Synchronizer.get_remote_files(contain_query=config["contain_query"])

    # get a second list of files that exists in the remote folder and contain the query
    local_sql_files = Synchronizer.get_local_files(local_path=config["local_backup_folder"],
                                                   contain_query=config["contain_query"])

    # compare the lists, upload files that exist on local device but not in remote storage
    uploaded_new_file = False
    for local_file in local_sql_files:
        if os.path.basename(local_file) not in remote_sql_files:
            uploaded_new_file = True
            print("Local file {} is not in list of remote files".format(os.path.basename(local_file)))
            Synchronizer.upload_file(file=local_file, drive_folder=config["remote_backup_folder"])

    if not uploaded_new_file:
        print(("No file has been uploaded, because no file was found in the local directory that was not already in "
               "the cloud storage"))


import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
import math
from multiprocessing import cpu_count

# Technical indicators
from ta.momentum import stochrsi,rsi
from ta.trend import ema_indicator, macd_diff, vortex_indicator_neg, vortex_indicator_pos, adx, cci, sma_indicator
from ta.volatility import bollinger_hband, bollinger_lband, average_true_range
from ta.volume import volume_weighted_average_price, ease_of_movement

from .filters import filterData

def swing_indicator(df:pd.DataFrame, swing_window:int=8)->pd.Series:
    df_cop = df.copy()
    df_cop['upside_momentum_gauge'] = 0
    df_cop.loc[(df_cop['High'] > df_cop['High'].shift(1)) & (df_cop['Close'] > df_cop['Open']), 'upside_momentum_gauge'] = 2
    df_cop.loc[(df_cop['High'] > df_cop['High'].shift(1)) & (df_cop['Close'] < df_cop['Open']), 'upside_momentum_gauge'] = 1
    df_cop.loc[(df_cop['High'] < df_cop['High'].shift(1)) & (df_cop['Close'] > df_cop['Open']), 'upside_momentum_gauge'] = 1
    df_cop.loc[(df_cop['High'] < df_cop['High'].shift(1)) & (df_cop['Close'] < df_cop['Open']), 'upside_momentum_gauge'] = 0

    df_cop['downside_momentum_gauge'] = 0
    df_cop.loc[(df_cop['Low'] > df_cop['Low'].shift(1)) & (df_cop['Close'] > df_cop['Open']), 'downside_momentum_gauge'] = 0
    df_cop.loc[(df_cop['Low'] > df_cop['Low'].shift(1)) & (df_cop['Close'] < df_cop['Open']), 'downside_momentum_gauge'] = 1
    df_cop.loc[(df_cop['Low'] < df_cop['Low'].shift(1)) & (df_cop['Close'] > df_cop['Open']), 'downside_momentum_gauge'] = 1
    df_cop.loc[(df_cop['Low'] < df_cop['Low'].shift(1)) & (df_cop['Close'] < df_cop['Open']), 'downside_momentum_gauge'] = 2

    df_cop['raw_swing'] = df_cop['upside_momentum_gauge'] - df_cop['downside_momentum_gauge']

    return df_cop['raw_swing'].rolling(swing_window).sum()

def add_bearish_breakouts(df:pd.DataFrame):
    df_2 = df.copy()
    df_2['Open_Close'] = df_2.apply(lambda row: (row['Open']-row['Close'])/row['Open'],axis=1)
    df_2['High_Low'] = df_2.apply(lambda row: (row['High']-row['Low'])/row['High'],axis=1)

    df_2['Open_Close_1'] = df_2.Open_Close.shift(1)
    df_2['Open_Close_2'] = df_2.Open_Close.shift(2)
    df_2['Open_Close_3'] = df_2.Open_Close.shift(3)

    def bearish_breakout(row):
        if (row['Open_Close']<0 and
            row['Open_Close_1']>0 and
            row['Open_Close_2']>0 and
            row['Open_Close_3']>0 and
            abs(row['Open_Close_1']+row['Open_Close_2']+row['Open_Close_3'])<=abs(row['High_Low'])):
            return 1
        else:
            return 0

    df['Bearish_breakout'] = df_2.apply(bearish_breakout,axis=1)
    return df

def add_bullish_breakouts(df:pd.DataFrame):
    df_2 = df.copy()
    df_2['Open_Close'] = df_2.apply(lambda row: (row['Open']-row['Close'])/row['Open'],axis=1)
    df_2['High_Low'] = df_2.apply(lambda row: (row['High']-row['Low'])/row['High'],axis=1)

    df_2['Open_Close_1'] = df_2.Open_Close.shift(1)
    df_2['Open_Close_2'] = df_2.Open_Close.shift(2)
    df_2['Open_Close_3'] = df_2.Open_Close.shift(3)

    def bullish_breakout(row):
        if (row['Open_Close']>0 and
            row['Open_Close_1']<0 and
            row['Open_Close_2']<0 and
            row['Open_Close_3']<0 and
            abs(row['Open_Close_1']+row['Open_Close_2']+row['Open_Close_3'])<=abs(row['High_Low'])):
            return 1
        else:
            return 0
    df['Bullish_breakout'] = df_2.apply(bullish_breakout,axis=1)
    return df

def addIndicators(df:pd.DataFrame,b_engulfings:bool=False, derivative:bool=False, double_derivative:bool=False,heikin_ashi:bool=False,chandelier_exit:bool=False, **kwargs) -> pd.DataFrame:
    """Apply indicators to the DataFrame.

    Args:
        df (pd.DataFrame): The dataframe you want to add indicators on.
        b_engulfings (bool, optional): Add bearish and bullish engulfing indicators. Defaults to False.
        derivative (bool, optional): Add the first derivative of the Close price. Defaults to False.
        double_derivative (bool, optional): Add the second derivative of the Close price. Defaults to False.
        heikin_ashi (bool, optional): Add the heikin_ashi candle to the dataframe. Defaults to False.
        chandelier_exit (bool, optional): Add the CE signal short and long to the dataframe. Defaults to False.
        **kwargs

    Returns:
        pd.DataFrame: The same dataframe with indicators
    """
    df['High_Low_diff'] = df.High-df.Low
    df['EMA20'] = ema_indicator(df.Close,20)
    df['EMA50'] = ema_indicator(df.Close,50)
    df['EMA100'] = ema_indicator(df.Close,100)
    df['EMA200'] = ema_indicator(df.Close,200)
    df['MACD'] = macd_diff(df.Close,kwargs.get('macd_length',14))
    df['Stoch_RSI'] = stochrsi(df.Close, kwargs.get('rsi_length',14), smooth1=3, smooth2=3)
    df['Vortex'] = (vortex_indicator_pos(df.High,df.Low,df.Close,kwargs.get('vortex_length',20),fillna=True)-1)-(vortex_indicator_neg(df.High,df.Low,df.Close,kwargs.get('vortex_length',20),fillna=True)-1)
    df['Bollinger_low'] = bollinger_hband(df.Close,kwargs.get('bollinger_length',20),fillna=True)
    df['Bollinger_high'] = bollinger_lband(df.Close,kwargs.get('bollinger_length',20),fillna=True)
    df['ADX'] = adx(df.High,df.Low,df.Close,kwargs.get('adx_length',14))
    df['ATR'] = average_true_range(df.High,df.Low,df.Close,kwargs.get('atr_length',10))
    df['CCI'] = cci(df.High,df.Low,df.Close,kwargs.get('cci_length',14))
    df['OVB'] = (np.sign(df.Close.diff())*df.Volume).fillna(0).cumsum()
    df['OVB_EMA200'] = ema_indicator(df.OVB,200)
    df['EVM'] = ease_of_movement(df.High,df.Low,df.Volume,kwargs.get('evm_length',14))
    df['Swing'] = swing_indicator(df,kwargs.get('swing_window',8))
    if chandelier_exit==True:
        df['CE_long'] = np.nan
        df['CE_short'] = np.nan
        df['CE_long'].iloc[kwargs.get('atr_length',22):] = [df['High'].iloc[i-kwargs.get('atr_length',22):i].max()-df['ATR'].iloc[i]*3 for i in range(kwargs.get('atr_length',22),len(df))]
        df['CE_short'].iloc[kwargs.get('atr_length',22):] = [df['Low'].iloc[i-kwargs.get('atr_length',22):i].min()+df['ATR'].iloc[i]*3 for i in range(kwargs.get('atr_length',22),len(df))]
    if b_engulfings==True:
        def isBearishCandleStick(candle) -> bool:
            """Check whether a candle is a bearish candle or not

            Args:
                candle (pd.Series): The current candle that contains OHLC

            Returns:
                bool: A boolean representing if the candle is bearish candle (True) or not (False)
            """
            return candle['Close']<candle['Open']

        def isBullishCandleStick(candle) -> bool:
            """Check whether a candle is a bullish candle or not

            Args:
                candle (pd.Series): The current candle that contains OHLC

            Returns:
                bool: A boolean representing if the candle is bullish candle (True) or not (False)
            """
            return candle['Close']>candle['Open']

        def isBullishEngulfing(previous_candle,current_candle) -> int:
            """A function that check for bullish engulfing pattern through candle stick

            Args:
                previous_candle (pd.Series): The previous candle that contains OHLC
                current_candle (pd.Series): The current candle that contains OHLC

            Returns:
                int: represent the pattern spotting : 1 bullish engulfing, 0 not.
            """
            return 1 if isBearishCandleStick(previous_candle) and isBullishCandleStick(current_candle) and previous_candle['Open']<current_candle['Close'] and previous_candle['Close']>current_candle['Open'] else 0

        def isBearishEngulfing(previous_candle,current_candle) -> int:
            """A function that check for bearish engulfing pattern through candle stick

            Args:
                previous_candle (pd.Series): The previous candle that contains OHLC
                current_candle (pd.Series): The current candle that contains OHLC

            Returns:
                int: represent the pattern spotting : 1 bearish engulfing, 0 not.
            """
            return 1 if isBullishCandleStick(previous_candle) and isBearishCandleStick(current_candle) and previous_candle['Close']<current_candle['Open'] and previous_candle['Open']>current_candle['Close'] else 0

        df['Bullish_engulfing'] = np.nan
        df['Bullish_engulfing'].iloc[1:] = [isBullishEngulfing(df.iloc[i-1],df.iloc[i]) for i in range(1,len(df))]
        df['Bearish_engulfing'] = np.nan
        df['Bearish_engulfing'].iloc[1:] = [isBearishEngulfing(df.iloc[i-1],df.iloc[i]) for i in range(1,len(df))]
    if derivative==True:
        df['Slope'] = df.Close.diff()
    if double_derivative==True:
        df['Acceleration'] = df.Close.diff().diff()
    if heikin_ashi==True:
        df['HA_Close'] = (df.Open + df.High + df.Low + df.Close)/4
        ha_open = [(df.Open[0] + df.Close[0]) / 2]
        [ha_open.append((ha_open[i] + df.HA_Close.values[i]) / 2) for i in range(0, len(df)-1)]
        df['HA_Open'] = ha_open
        df['HA_High'] = df[['HA_Open', 'HA_Close', 'High']].max(axis=1)
        df['HA_Low'] = df[['HA_Open', 'HA_Close', 'Low']].min(axis=1)
    return df.dropna()

def generateDatesFeatures(df:pd.DataFrame,
                          sin_cos:bool=True,
                          date_in_index:bool=True,
                          date_col=''):
    """Generate date features from a dataframe.

    Args:
        df (pd.DataFrame): _description_
        sin_cos (bool, optional): _description_. Defaults to True.
        date_in_index (bool, optional): _description_. Defaults to True.
        date_col (str, optional): _description_. Defaults to ''.

    Returns:
        _type_: _description_
    """

    day = 24*60*60
    year = (365.2425)*day

    if date_in_index:
        #df['Day']=df.index.day
        df['Month']=df.index.month
        df['Year']=df.index.year
        #df['Day_week']=df.index.day_of_week
        df['Week']=df.index.week
        df['Hour']=df.index.hour
        if sin_cos:
            timestamp_s = df.index.map(pd.Timestamp.timestamp)
            df['Day_sin'] = np.sin(timestamp_s * (2 * np.pi / day))
            df['Day_cos'] = np.cos(timestamp_s * (2 * np.pi / day))
            df['Year_sin'] = np.sin(timestamp_s * (2 * np.pi / year))
            df['Year_cos'] = np.cos(timestamp_s * (2 * np.pi / year))
        return df
    else:
        df['Day']=df[date_col].day
        df['Month']=df[date_col].month
        df['Year']=df[date_col].year
        df['Day_week']=df[date_col].day_of_week
        df['Week']=df[date_col].week
        df['Hour']=df[date_col].hour
        if sin_cos:
            timestamp_s = df[date_col].map(pd.Timestamp.timestamp).to_list()

            df['Day_sin'] = np.sin(timestamp_s * (2 * np.pi / day))
            df['Day_cos'] = np.cos(timestamp_s * (2 * np.pi / day))
            df['Year_sin'] = np.sin(timestamp_s * (2 * np.pi / year))
            df['Year_cos'] = np.cos(timestamp_s * (2 * np.pi / year))
        return df

def computeTrixIndicator(df,trix_length=9,trix_signal=21,col='Close',histo=True)->pd.DataFrame:
    """_summary_

    Args:
        df (_type_): _description_
        trix_length (_type_): _description_
        trix_signal (_type_): _description_
        col (str, optional): _description_. Defaults to 'Close'.
        histo (bool, optional): _description_. Defaults to True.

    Returns:
        pd.DateFrame: _description_
    """
    df['Trix'] = ema_indicator(ema_indicator(ema_indicator(df[col], window=trix_length), window=trix_length), window=trix_length)
    trix_pct = df['Trix'].pct_change()*100
    trix_sig = sma_indicator(trix_pct,trix_signal)
    if histo==True:
        df['Trix_histo'] = trix_pct - trix_sig
    return df.dropna()

def computeLaggingLinearRegression(df, col="Close",window=15,filter_ceof:bool=True, filter_method:str='dwt',derivative:bool=True)->pd.DataFrame:
    """Compute a lagging moving regression on a column with a window.

    Args:
        df (pd.DataFrame): The dataframe containing features.
        col (str, optional): The column we apply Linear regression on. Defaults to "Close.
        window (int, optional): The window we apply linear regression on. Defaults to 15.

    Returns:
        pd.DataFrame: The entry DataFrame we another column called B_MLR_coefs
    """
    def computeLinearRegression(x,y)->float:
        """Compute simple linear regression between 2 vectors x and y

        Args:
            x (np.array): x vector
            y (np.array): y vector

        Returns:
            float: The coefficient a corresponding to the linear regression y=ax+b.
        """
        model = LinearRegression(n_jobs=cpu_count()).fit(x,y,)
        return model.coef_[0]

    df['B_MLR_coefs'] = np.nan
    df['B_MLR_coefs'].iloc[window:] = [computeLinearRegression(df.Timestamp.values[i-window:i].reshape(-1, 1), df[col].values[i-window:i]) for i in range(window,len(df))]
    df = df.dropna()
    if filter_ceof==True:
        df['B_MLR_coefs_filtered'] = filterData(df.B_MLR_coefs.values,filter_method)
        if derivative==True:
            df['B_MLR_coefs_filtered_diff'] = df['B_MLR_coefs_filtered'].diff(3)
    else:
        if derivative==True:
            df['B_MLR_coefs_diff'] = df['B_MLR_coefs'].diff(3)
    return df.dropna()

def computeRSI_VWAP(df, rsi_window=25,vwap_window=19, stoch_rsi=False)->pd.DataFrame:
    """_summary_

    Args:
        df (pd.DataFrame): The dataframe containing features.
        rsi_window (int, optional): The window we apply VWAP indicator on. Defaults to 25.
        vwap_window (int, optional): The window we apply RSI indicator on. Defaults to 19.

    Returns:
        pd.DataFrame: The entry DataFrame with RSI_VWAP indicator column added.
    """
    if stoch_rsi==True:
        df['RSI_VWAP'] = stochrsi(volume_weighted_average_price(df.High,df.Low,df.Close,df['Volume'],vwap_window),rsi_window)
    else:
        df['RSI_VWAP'] = rsi(volume_weighted_average_price(df.High,df.Low,df.Close,df['Volume'],vwap_window),rsi_window)
    return df.dropna()

def computeVMCCB(df:pd.DataFrame)->pd.DataFrame:
    class VMC():
        """ VuManChu Cipher B + Divergences
            Args:
                High(pandas.Series): dataset 'High' column.
                Low(pandas.Series): dataset 'Low' column.
                Close(pandas.Series): dataset 'Close' column.
                wtChannelLen(int): n period.
                wtAverageLen(int): n period.
                wtMALen(int): n period.
                rsiMFIperiod(int): n period.
                rsiMFIMultiplier(int): n period.
                rsiMFIPosY(int): n period.
        """

        def __init__(
            self: pd.Series,
            Open: pd.Series,
            High: pd.Series,
            Low: pd.Series,
            Close: pd.Series,
            wtChannelLen: int = 9,
            wtAverageLen: int = 12,
            wtMALen: int = 3,
            rsiMFIperiod: int = 60,
            rsiMFIMultiplier: int = 150,
            rsiMFIPosY: int = 2.5
        ) -> None:
            self._high = High
            self._low = Low
            self._close = Close
            self._open = Open
            self._wtChannelLen = wtChannelLen
            self._wtAverageLen = wtAverageLen
            self._wtMALen = wtMALen
            self._rsiMFIperiod = rsiMFIperiod
            self._rsiMFIMultiplier = rsiMFIMultiplier
            self._rsiMFIPosY = rsiMFIPosY

            self._run()
            self.wave_1()

        def _run(self) -> None:
            self.hlc3 = (self._close + self._high + self._low)
            self._esa = ema_indicator(
                Close=self.hlc3, window=self._wtChannelLen)
            self._de = ema_indicator(
                Close=abs(self.hlc3 - self._esa), window=self._wtChannelLen)
            self._rsi = sma_indicator(self._close, self._rsiMFIperiod)
            self._ci = (self.hlc3 - self._esa) / (0.015 * self._de)

        def wave1(self) -> pd.Series:
            """VMC Wave 1
            Returns:
                pandas.Series: New feature generated.
            """
            wt1 = ema_indicator(self._ci, self._wtAverageLen)
            return pd.Series(wt1, name="wt1")

        def wave2(self) -> pd.Series:
            """VMC Wave 2
            Returns:
                pandas.Series: New feature generated.
            """
            wt2 = sma_indicator(self.wave_1(), self._wtMALen)
            return pd.Series(wt2, name="wt2")

        def moneyFlow(self) -> pd.Series:
            """VMC Money Flow
            Returns:
                pandas.Series: New feature generated.
            """
            mfi = ((self._close - self._open) /
                (self._high - self._low)) * self._rsiMFIMultiplier
            rsi = sma_indicator(mfi, self._rsiMFIperiod)
            money_flow = rsi - self._rsiMFIPosY
            return pd.Series(money_flow, name="money_flow")

    vmc = VMC(df.Open, df.High, df.Low, df.Close)
    df['Money_Flow'] = vmc.moneyFlow()
    df['Wave1'] = vmc.wave1()
    df['Wave2'] = vmc.wave2()
    def chop(high, low, close, window=14):
        """ Chopiness index
            Args:
                high(pd.Series): dataframe 'high' columns,
                low(pd.Series): dataframe 'low' columns,
                close(pd.Series): dataframe 'close' columns,
                window(int): the window length for the chopiness index,
            Returns:
                pd.Series: Chopiness index
        """
        tr1 = pd.DataFrame(high - low).rename(columns = {0:'tr1'})
        tr2 = pd.DataFrame(abs(high - close.shift(1))).rename(columns = {0:'tr2'})
        tr3 = pd.DataFrame(abs(low - close.shift(1))).rename(columns = {0:'tr3'})
        frames = [tr1, tr2, tr3]
        tr = pd.concat(frames, axis = 1, join = 'inner').dropna().max(axis = 1)
        atr = tr.rolling(1).mean()
        highh = high.rolling(window).max()
        lowl = low.rolling(window).min()
        return 100 * np.log10((atr.rolling(window).sum()) / (highh - lowl)) / np.log10(window)
    return df

def computeSuperTrend(df:pd.DataFrame,upper=False, lower=False)->pd.DataFrame:
    """Compute the super trend indicator for a dataframe.

    Args:
        df (pd.DataFrame): The input dataframe.

    Returns:
        pd.DataFrame: The resulting dataframe with 3 new columns
    """
    class SuperTrend():
        def __init__(
            self,
            High,
            Low,
            Close,
            atr_window=10,
            atr_multi=3
        ):
            self.High = High
            self.Low = Low
            self.Close = Close
            self.atr_window = atr_window
            self.atr_multi = atr_multi
            self._run()

        def _run(self):
            # calculate ATR
            price_diffs = [self.High - self.Low,
                        self.High - self.Close.shift(),
                        self.Close.shift() - self.Low]
            true_range = pd.concat(price_diffs, axis=1)
            true_range = true_range.abs().max(axis=1)
            # default ATR calculation in supertrend indicator
            atr = true_range.ewm(alpha=1/self.atr_window,min_periods=self.atr_window).mean()
            # atr = ta.volatility.average_true_range(High, Low, Close, atr_period)
            # df['atr'] = df['tr'].rolling(atr_period).mean()

            # HL2 is simply the average of High and Low prices
            hl2 = (self.High + self.Low) / 2
            # upperband and lowerband calculation
            # notice that final bands are set to be equal to the respective bands
            final_upperband = upperband = hl2 + (self.atr_multi * atr)
            final_lowerband = lowerband = hl2 - (self.atr_multi * atr)

            # initialize Supertrend column to True
            supertrend = [True] * len(self.Close)

            for i in range(1, len(self.Close)):
                curr, prev = i, i-1

                # if current Close price crosses above upperband
                if self.Close[curr] > final_upperband[prev]:
                    supertrend[curr] = True
                # if current Close price crosses below lowerband
                elif self.Close[curr] < final_lowerband[prev]:
                    supertrend[curr] = False
                # else, the trend continues
                else:
                    supertrend[curr] = supertrend[prev]

                    # adjustment to the final bands
                    if supertrend[curr] == True and final_lowerband[curr] < final_lowerband[prev]:
                        final_lowerband[curr] = final_lowerband[prev]
                    if supertrend[curr] == False and final_upperband[curr] > final_upperband[prev]:
                        final_upperband[curr] = final_upperband[prev]

                # to remove bands according to the trend direction
                if supertrend[curr] == True:
                    final_upperband[curr] = np.nan
                else:
                    final_lowerband[curr] = np.nan

            self.st = pd.DataFrame({
                'Supertrend': supertrend,
                'Final Lowerband': final_lowerband,
                'Final Upperband': final_upperband
            })

        def superTrendUpper(self):
            return self.st['Final Upperband']

        def superTrendLower(self):
            return self.st['Final Lowerband']

        def superTrendDirection(self):
            return self.st['Supertrend']

    st = SuperTrend(df.High, df.Low, df.Close)

    if upper==True:
        df['ST_Upper']  = st.superTrendUpper()
    if lower==True:
        df['ST_Lower'] = st.superTrendLower()
    df['ST_Direction'] = st.superTrendDirection()
    return df

def computeMASlope(df_true:pd.DataFrame)->pd.DataFrame:
    """Compute MA Slope indicator on a dataFrame.

    Args:
        df (pd.DataFrame): The input DataFrame.

    Returns:
        pd.DataFrame: The output dataframe with 2 new columns.
    """
    class MaSlope():
        """ Slope adaptative moving average
        """

        def __init__(
            self,
            Close: pd.Series,
            High: pd.Series,
            Low: pd.Series,
            long_ma: int = 200,
            major_length: int = 14,
            minor_length: int = 6,
            slope_period: int = 34,
            slope_ir: int = 25
        ):
            self.Close = Close
            self.High = High
            self.Low = Low
            self.long_ma = long_ma
            self.major_length = major_length
            self.minor_length = minor_length
            self.slope_period = slope_period
            self.slope_ir = slope_ir
            self._run()

        def _run(self):
            minAlpha = 2 / (self.minor_length + 1)
            majAlpha = 2 / (self.major_length + 1)
            # df = pd.DataFrame(data = [self.Close, self.High, self.Low], columns = ['Close','High','Low'])
            df = pd.DataFrame(data = {"Close": self.Close, "High": self.High, "Low":self.Low})
            df['hh'] = df['High'].rolling(window=self.long_ma+1).max()
            df['ll'] = df['Low'].rolling(window=self.long_ma+1).min()

            df = df.fillna(0)
            df['mult'] = 0
            df['mult'].iloc[self.long_ma:] = abs(2 * df['Close'].iloc[self.long_ma:] - df['ll'].iloc[self.long_ma:] - df['hh'].iloc[self.long_ma:]) / (df['hh'].iloc[self.long_ma:] - df['ll'].iloc[self.long_ma:])
            df['final'] = df['mult'] * (minAlpha - majAlpha) + majAlpha

            ma_first = (df.iloc[0]['final']**2) * df.iloc[0]['Close']

            col_ma = [ma_first]
            for i in range(1, len(df)):
                ma1 = col_ma[i-1]
                col_ma.append(ma1 + (df.iloc[i]['final']**2) * (df.iloc[i]['Close'] - ma1))

            df['ma'] = col_ma
            pi = math.atan(1) * 4
            df['hh1'] = df['High'].rolling(window=self.slope_period).max()
            df['ll1'] = df['Low'].rolling(window=self.slope_period).min()
            df['slope_range'] = self.slope_ir / (df['hh1'] - df['ll1']) * df['ll1']
            df['dt'] = (df['ma'].shift(2) - df['ma']) / df['Close'] * df['slope_range']
            df['c'] = (1+df['dt']*df['dt'])**0.5
            df['xangle'] = round(180*np.arccos(1/df['c']) / pi)
            df[df['dt']>0]['xangle'] = - df[df['dt']>0]['xangle']
            self.df = df
            # print(df)

        def ma_line(self) -> pd.Series:
            """ ma_line
                Returns:
                    pd.Series: ma_line
            """
            return self.df['ma']

        def x_angle(self) -> pd.Series:
            """ x_angle
                Returns:
                    pd.Series: x_angle
            """
            return self.df['xangle']

    ms = MaSlope(df_true.High, df_true.Low, df_true.Close)
    df_true['Angle'] = ms.x_angle()
    df_true['MA_Slope'] = ms.ma_line()
    return df_true


from django.contrib import admin
from django.contrib.auth.models import User
from django.conf import settings
from bookmeeting.models import BookingInfo, MeetingRoom

# Register your models here.

class MeetingRoomBookInline(admin.TabularInline):
    model = BookingInfo

@admin.register(MeetingRoom)
class MeetingRoomAdmin(admin.ModelAdmin):
    list_per_page = 20
    list_display = ('name', 'screen', 'capacity', 'picture', 'comment')
    list_filter = ('name', 'screen')
    inlines = [MeetingRoomBookInline, ]

@admin.register(BookingInfo)
class BookingInfoAdmin(admin.ModelAdmin):
    list_per_page = 20
    list_display = ('user', 'meeting_room', 'start_time', 'end_time',
                    'duration', 'subject', 'abstract', 'member', 'book_time', 'invitation')
    list_filter = ('user', 'meeting_room')

# class UserAdmin(admin.ModelAdmin):
#     list_per_page = 50
#     list_display = ('username', 'first_name', 'email', 'is_active', 'is_staff', 'is_superuser')
#     list_filter = ('is_active', 'username')
#     search_fields = ('username',)
#     actions = ['sync_user_from_oa']
#
#     def sync_user_from_oa(self, request, queryset):
#         from .logic import sync_user
#         sync_user()
#
#     sync_user_from_oa.short_description = '从OA系统同步用户'
#
#
# admin.site.unregister(User)
# admin.site.register(User, UserAdmin)


import urllib
from bs4 import BeautifulSoup

def get_data():
	page = "http://www.governing.com/gov-data/gentrification-in-cities-governing-report.html"

	# query the website and return the html to the variable ‘page’
	page = urllib.request.urlopen(page)

	# parse the html using beautiful soup and store in variable `soup`
	soup = BeautifulSoup(page, "html.parser")

	# get table with data
	table = soup.find("table", attrs={"id": "inputdata"})

	data = []
	# get the index price
	for row in table.find_all('tr'):
	    column_marker = 0
	    columns = row.find_all('td')
	    count = 0
	    city = ""
	    index = 0
	    for column in columns:
	    	if count == 0:
	    		city = column.get_text()
	    	elif count == 1:
	    		index = column.get_text()
	    	else:
	    		break;
	    	count += 1
	    data.append([city, index])

	data = data[2:]

	# turn percent to float
	for d in data:
		val = d[1][0:-1]
		d[1] = float(val)

	###########################################
	# get educational attainment on each city #
	###########################################
	page = "https://en.wikipedia.org/wiki/List_of_U.S._states_by_educational_attainment"

	# query the website and return the html to the variable ‘page’
	page = urllib.request.urlopen(page)

	# parse the html using beautiful soup and store in variable `soup`
	soup = BeautifulSoup(page, "html.parser")

	# get table with data
	table = soup.find("table", attrs={"class": "wikitable sortable"})

	edu = {}
	# get the educational attainment
	for row in table.find_all('tr'):
	    column_marker = 0
	    columns = row.find_all('td')
	    count = 0
	    city = ""
	    index = 0
	    for column in columns:
	    	if count == 0:
	    		city = column.get_text()
	    	elif count == 3:
	    		index = column.get_text()
	    	elif count > 3:
	    		break;
	    	count += 1
	    	edu[city] = index

	# abbreviations to states
	states = {
	        'AK': 'Alaska',
	        'AL': 'Alabama',
	        'AR': 'Arkansas',
	        'AS': 'American Samoa',
	        'AZ': 'Arizona',
	        'CA': 'California',
	        'CO': 'Colorado',
	        'CT': 'Connecticut',
	        'DC': 'District of Columbia',
	        'DE': 'Delaware',
	        'FL': 'Florida',
	        'GA': 'Georgia',
	        'GU': 'Guam',
	        'HI': 'Hawaii',
	        'IA': 'Iowa',
	        'ID': 'Idaho',
	        'IL': 'Illinois',
	        'IN': 'Indiana',
	        'KS': 'Kansas',
	        'KY': 'Kentucky',
	        'LA': 'Louisiana',
	        'MA': 'Massachusetts',
	        'MD': 'Maryland',
	        'ME': 'Maine',
	        'MI': 'Michigan',
	        'MN': 'Minnesota',
	        'MO': 'Missouri',
	        'MP': 'Northern Mariana Islands',
	        'MS': 'Mississippi',
	        'MT': 'Montana',
	        'NA': 'National',
	        'NC': 'North Carolina',
	        'ND': 'North Dakota',
	        'NE': 'Nebraska',
	        'NH': 'New Hampshire',
	        'NJ': 'New Jersey',
	        'NM': 'New Mexico',
	        'NV': 'Nevada',
	        'NY': 'New York',
	        'OH': 'Ohio',
	        'OK': 'Oklahoma',
	        'OR': 'Oregon',
	        'PA': 'Pennsylvania',
	        'PR': 'Puerto Rico',
	        'RI': 'Rhode Island',
	        'SC': 'South Carolina',
	        'SD': 'South Dakota',
	        'TN': 'Tennessee',
	        'TX': 'Texas',
	        'UT': 'Utah',
	        'VA': 'Virginia',
	        'VI': 'Virgin Islands',
	        'VT': 'Vermont',
	        'WA': 'Washington',
	        'WI': 'Wisconsin',
	        'WV': 'West Virginia',
	        'WY': 'Wyoming'
	}

	# iterate through data and get educatiuonal attainment
	for node in data:
		city = node[0]
		state = states[city[-2:]]
		node.append(float(edu[state][0:-1]))

	########################
	# get household income #
	########################
	page = "https://en.wikipedia.org/wiki/List_of_U.S._states_by_income"

	# query the website and return the html to the variable ‘page’
	page = urllib.request.urlopen(page)

	# parse the html using beautiful soup and store in variable `soup`
	soup = BeautifulSoup(page, "html.parser")

	# get table with data
	table = soup.find("table", attrs={"class": "wikitable sortable"})

	income = {}
	# get the income
	for row in table.find_all('tr'):
	    column_marker = 0
	    columns = row.find_all('td')
	    count = 0
	    city = ""
	    index = 0
	    for column in columns:
	    	if count == 1:
	    		city = column.get_text()
	    	elif count == 2:
	    		index = column.get_text()
	    	elif count > 2:
	    		break;
	    	count += 1
	    	income[city] = index
	income["District of Columbia"] = "$75,628"

	# iterate through data and get income
	for node in data:
		city = node[0]
		state = states[city[-2:]]
		val = income[state].replace(",","")[1:]
		node.append(float(val))

	return data


import time
from flask import Flask, jsonify, request, render_template, redirect, url_for, flash, session
from datetime import datetime
import hashlib, json

class blockchain:
	def __init__(self):
		self.chain = []
		self.transaction_pendientes = []
		self.transaction(0, 0, 0) # se crea la transaccion genesis
		self.create_block(proof = 1, previous_hash = '0') # se crea el bloque genesis

	def create_block(self, proof, previous_hash):
		block = {
			'index': len(self.chain) + 1,
			'tiempo': str(datetime.now()),
			'transacciones': self.transaction_pendientes,
			'proof': proof,
			'previous_hash': previous_hash
			} # despues de agregar las transacciones, se limpian las transacciones pendientes para que no se repitan en la proxima creacion de bloque
		self.transaction_pendientes = [] #limpiar las transacciones pendientes
		self.chain.append(block) #agregar el bloque a la blockchain
		return block #retornar el bloque creado

	def anterior_bloque(self): #retornar el bloque anterior
		return self.chain[-1]

	def proof_of_work(self, previous_proof):
		new_proof = 1
		check_proof = False
		while check_proof is False:
			hash_operation = hashlib.sha256(str(new_proof**2 + previous_proof**2).encode()).hexdigest()
			if hash_operation[:4] == '4242': #si el hash empieza con 4242, es correcto
				check_proof = True
			else:
				new_proof += 1
		if check_proof is True:
			blockchain.transaction('4c6e7e2a9f2f7f7ff8e7d3d6c8b7c6e8e23a7', '4c6e7e2a9f2f7f7ff8e7d3d6c8b7c6e8e23a7', 42) #transaccion para minar
			print('Se ha minado un bloque con un hash de: ' + hash_operation, 'y se han recompesado al minero: ')
		return new_proof

	def hash(self, block): #funcion para calcular el hash del bloque
		encoded_block = json.dumps(block, sort_keys = True).encode() #se codifica el bloque
		return hashlib.sha256(encoded_block).hexdigest() #se retorna el hash del bloque

	def transaction(self, sender, recipient, amount): #funcion para agregar transacciones a la blockchain
		transaccion = {
			'sender': sender,
			'recipient': recipient,
			'amount': amount
			}
		self.transaction_pendientes.append(transaccion) #se agrega la transacc
		return transaccion #se retorna la transaccion

blockchain = blockchain()

print('El bloque creado es: ')

############################## flask appp web ################################################

app = Flask(__name__)

@app.route('/', methods=['GET'])
def index():
	return r'
ft_blockchain is going on!
'

@app.route('/chain', methods=['GET'])
def chain():
	chain = {
		'chain': blockchain.chain,
		'length': len(blockchain.chain)
	}
	return jsonify(chain)

@app.route('/mine', methods=['GET'])
def mine():
	previous_block = blockchain.anterior_bloque()
	previous_proof = previous_block['proof']
	proof = blockchain.proof_of_work(previous_proof)
	previous_hash = blockchain.hash(previous_block)
	block = blockchain.create_block(proof, previous_hash)
	print ('Se ha minado un bloque con un hash de: ' + blockchain.hash(block))
	return jsonify(block), 200

@app.route('/transactions/new', methods=['POST', 'GET'])
def new_transaction():
	if request.method == 'GET':
		a = blockchain.transaction('4c6e7e2a9f2f7f7ff8e7d3d6c8b7c6e8e23a7', '4c6e7e2a9f2f7f7ff8e7d3d6c8b7c6e8e23a7', 1000) #transaccion para mi
		return jsonify(a), 200
	elif request.method == 'POST':
		values = request.get_json()
		required = ['sender', 'recipient', 'amount']
		if not all(k in values for k in required):
			return 'Missing values', 400
		blockchain.transaction(values['sender'], values['recipient'], values['amount'])
		print('Se ha agregado una transaccion a la blockchain' + str(values))
	return 'Transaccion agregada', 201
def main():
	app.run(debug=True)

if __name__ == '__main__':
	main()


import argparse

from dt_shell import DTCommandAbs, dtslogger
from utils.cli_utils import ask_confirmation
from utils.secrets_utils import SecretsManager

class DTCommand(DTCommandAbs):
    help = "Configure GitHub credentials"

    usage = f"""
Usage:

    dts config github credentials set --username <your-github-username> --token <your-github-access-token>
"""

    @staticmethod
    def command(shell, args, **kwargs):
        parser = argparse.ArgumentParser(
            prog="dts config github credentials set",
            description=("Save github logins locally for Duckietown"),
        )
        parser.add_argument(
            "--username",
            help="GitHub username",
            required=True,
        )
        parser.add_argument(
            "--token",
            help="GitHub access token",
            required=True,
        )
        parsed = parser.parse_args(args)

        username = parsed.username
        token = parsed.token

        # ---

        # set secrets
        secret_key: str = "github/credentials/token"
        # - overwrite?
        if SecretsManager.has(secret_key):
            overwrite: bool = ask_confirmation(
                "A set of credentials for GitHub is already stored, if you continue, the "
                "old credentials will be overwritten.",
                default="y",
            )
            if not overwrite:
                dtslogger.info("Leaving credentials untouched")
                return False

        # - store secrets
        secret_value: dict = {"username": username, "secret": token}
        SecretsManager.set(secret_key, secret_value)

        dtslogger.info("GitHub access credentials stored!")


import flask
import base64
import io
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_dangerously_set_inner_html as dhtml
import dash_table
from dash.dependencies import Input, Output

import os
import argparse
import numpy as np
from rdkit import Chem
from rdkit.Chem import Descriptors
from rdkit.Chem import AllChem
from rdkit.Chem import DataStructs
from rdkit.Chem import Draw
from rdkit.Chem.Draw import rdDepictor
from sklearn.decomposition import PCA

import plotly.graph_objs as go
descdict = dict(Descriptors._descList)

app = dash.Dash(__name__)

css_directory = os.getcwd()+'/static/'
stylesheets = ['bWLwgP.css']
static_css_route = '/static/'

def smi2svg(smi):
    mol = Chem.MolFromSmiles(smi)
    rdDepictor.Compute2DCoords(mol)
    mc = Chem.Mol(mol.ToBinary())
    Chem.Kekulize(mc)
    drawer = Draw.MolDraw2DSVG(300,300)
    drawer.DrawMolecule(mc)
    drawer.FinishDrawing()
    svg = drawer.GetDrawingText().replace('svg:','')
    return svg

def parse_contents(contents):
    content_type, content_string = contents.split(',')
    decoded = base64.b64decode(content_string)
    with open('./static/temp.sdf', 'w') as f:
        f.write(decoded.decode('utf-8'))
    mols = [mol for mol in Chem.SDMolSupplier('./static/temp.sdf')]
    return mols

@app.server.route('{}<stylesheet>'.format(static_css_route))
def serve_stylesheet(stylesheet):
    if stylesheet not in stylesheets:
        raise Exception()
    return flask.send_from_directory(css_directory, stylesheet)

for stylesheet in stylesheets:
    app.css.append_css({"external_url": "/static/{}".format(stylesheet)})

app.layout = html.Div(children=[
    html.H1(children='Hello Chemoinfo'),
    dcc.Upload(
        id='upload-data',
        children=html.Div(
            ['Drag and Drop SDF or ',
            html.A('Select Files')
            ]),
            style={
                    'width': '80%',
                    'height': '60px',
                    'lineHeight': '60px',
                    'borderWidth': '1px',
                    'borderStyle': 'dashed',
                    'borderRadius': '5px',
                    'textAlign': 'center',
                    'margin': '10px'
            },
            multiple=True
        ),

    html.Div(children='''
    Dash : sample plot
    '''),

    html.Div([dcc.Dropdown(id='x-column',
                           value='MaxEStateIndex',
                           options=[{'label': key, 'value': key} for key in descdict.keys()],
                           style={'width':'48%', 'display':'inline-block'}),
              dcc.Dropdown(id='y-column',
                           value='MaxEStateIndex',
                           options=[{'label': key, 'value': key} for key in descdict.keys()],
                           style={'width':'48%', 'display':'inline-block'}),
                           ]),
    html.Div([
        html.Div([html.Div(id="molimg")], className="four columns"),
        html.Div([dcc.Graph(id='example-graph')], className="eight columns")
        ], className="row"),
    #html.Div([dcc.Graph(id='chemical-space')])
    ])

@app.callback(
    Output('example-graph', 'figure'),

    [Input('upload-data', 'contents'),
     Input('x-column', 'value'),
     Input('y-column', 'value')]
)
def update_graph(contents, x_column_name, y_column_name):
    mols = parse_contents(contents[0])
    for i, mol in enumerate(mols):
        AllChem.Compute2DCoords(mol)
    x = [descdict[x_column_name](mol) for mol in mols]
    y = [descdict[y_column_name](mol) for mol in mols]

    return {'data':[go.Scatter(
        x=x,
        y=y,
        #text=['mol_{}'.format(i) for i in range(len(mols))],
        text=[Chem.MolToSmiles(mol) for mol in mols],
        mode='markers',
        marker={
            'size':15,
            'opacity':0.5
        }
    )],
    'layout':go.Layout(
        xaxis={'title':x_column_name},
        yaxis={'title':y_column_name}
    )}

@app.callback(
    Output('molimg', 'children'),
    [Input('example-graph', 'hoverData'),
    ]
)
def update_img(hoverData1):
    try:
        svg = smi2svg(hoverData1['points'][0]['text'])
    except:
        svg = 'Select molecule'
    return dhtml.DangerouslySetInnerHTML(svg)

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


"""Alert panes inspired by Bootstrap Alerts.

This example was originally created to show how to create custom Bootstrap Alerts.
The Alerts have now been contributed to Panel. You can find the reference example
[here](https://panel.holoviz.org/reference/panes/Alert.html).
"""
import panel as pn
from awesome_panel.express.testing import TestApp
from awesome_panel_extensions.site import site

APPLICATION = site.create_application(
    url="bootstrap-alerts",
    name="Bootstrap Alerts",
    author="Marc Skov Madsen",
    description="Demonstrates the look and feel of the Panel Alerts",
    description_long=__doc__,
    thumbnail="test_bootstrap_alerts.png",
    resources={
        "code": "awesome_panel_express_tests/test_bootstrap_alerts.py",
    },
    tags=["Bootstrap"],
)

def test_info_alert():
    """
    We can show an InfoAlert

    - Blue Div with normal and bold text
    - Full width by default
    - With a nice bottom margin
    """
    return TestApp(
        test_info_alert,
        pn.pane.Alert("This is an **Info Alert**!"),
        sizing_mode="stretch_width",
    )

def test_warning_alert():
    """We can show a Warning Alert

    - Yellow Div with normal and bold text
    - Full width by default
    - With a nice bottom margin
    """
    return TestApp(
        test_warning_alert,
        pn.pane.Alert("This is a **Warning Alert**!", alert_type="warning"),
        sizing_mode="stretch_width",
    )

def test_error_alert():
    """We can show an Error Alert

    - Red Div with normal and bold text
    - Full width by default
    - With a nice bottom margin
    """
    return TestApp(
        test_error_alert,
        pn.pane.Alert("This is an **Error Alert**!", alert_type="danger"),
        sizing_mode="stretch_width",
    )

@site.add(APPLICATION)
def view() -> pn.Column:
    """Wraps all tests in a Column that can be included in the Gallery or served independently

    Returns:
        pn.Column -- A Column containing all the tests
    """
    pn.config.sizing_mode = "stretch_width"
    main = [
        APPLICATION.intro_section(),
        test_info_alert(),
        test_error_alert(),
        test_warning_alert(),
    ]
    return pn.template.FastListTemplate(title="Test Bootstrap Alerts", main=main)

if __name__.startswith("bokeh"):
    view().servable()


import numpy as np
import itertools

import matplotlib.pyplot as plt
from util.data_process import plot_3d_points

"""
    This class represents a n-dimensional unit cube with a specific number of points embeded.
    Points are distributed uniformly in the initialization. A search can be made using the
    search_point function that returns the k (given) nearest neighbors of the input point.

"""

class Space:

    def __init__(self, low, high, points):

        self._low = np.array(low)
        self._high = np.array(high)
        self._range = self._high - self._low
        self._dimensions = len(low)
        self.__space = init_uniform_space([0] * self._dimensions,
                                          [1] * self._dimensions,
                                          points)

    def search_point(self, point, k):

        pnt = int(np.round(point))
        rng = int(k/2)
        low = pnt - rng
        high = low + k
        if (low < self._low):
            low = self._low
            high = low + k
        elif (high > self._high):
            high = self._high + 1
            low = high - k

        pnts = np.arange(low, high).reshape((k, 1))
        out = np.array([pnts])
        return out

    def import_point(self, point):
        return (point - self._low) / self._range

    def export_point(self, point):
        return self._low + point * self._range

    def get_space(self):
        return self.__space

    def shape(self):
        return self.__space.shape

    def get_number_of_actions(self):
        return self.shape()[0]

    def plot_space(self, additional_points=None):

        dims = self._dimensions

        if dims > 3:
            print(
                'Cannot plot a {}-dimensional space. Max 3 dimensions'.format(dims))
            return

        space = self.get_space()
        if additional_points is not None:
            for i in additional_points:
                space = np.append(space, additional_points, axis=0)

        if dims == 1:
            for x in space:
                plt.plot([x], [0], 'o')

            plt.show()
        elif dims == 2:
            for x, y in space:
                plt.plot([x], [y], 'o')

            plt.show()
        else:
            plot_3d_points(space)

class Discrete_space(Space):
    """
        Discrete action space with n actions (the integers in the range [0, n))
        0, 1, 2, ..., n-2, n-1
    """

    def __init__(self, n):  # n: the number of the discrete actions
        super().__init__([0], [n - 1], n)

    def export_point(self, point):
        return super().export_point(point).astype(int)

def init_uniform_space(low, high, points):
    dims = len(low)
    points_in_each_axis = round(points**(1 / dims))

    axis = []
    for i in range(dims):
        axis.append(list(np.linspace(low[i], high[i], points_in_each_axis)))

    space = []
    for _ in itertools.product(*axis):
        space.append(list(_))

    return np.array(space)


import requests
from twilio.rest import Client
from dotenv import load_dotenv
import os

env_path = os.getcwd() + "/.env"
load_dotenv(env_path)

endpoint = "https://api.openweathermap.org/data/2.5/onecall"
api_key = os.getenv('API_KEY')

twilio_sid = os.getenv('TWILIO_SID')
twilio_token = os.getenv('TWILIO_TOKEN')

parameters = {"lat": os.getenv('LAT'),
              "lon": os.getenv('LON'),
              "exclude": "currently,minutely,daily",
              "appid": api_key,
              }

response = requests.get(endpoint, params=parameters)
response.raise_for_status()
weather_data = response.json()
hours = weather_data["hourly"]

place = weather_data["timezone"]

will_rain = False

for i in range(0, 12):
    elem = hours[i]
    elem_weather = elem["weather"][0]
    print(elem_weather["id"])
    if elem_weather["id"] < 700:
        will_rain = True

if will_rain:
    client = Client(twilio_sid, twilio_token)
    message = client.messages.create(
        body=f"It will be rain in {place[5:]} today. Don't forget to take an UMBRELLA",
        from_=os.getenv('TWILIO_NUMBER'),
        to=os.getenv('YOUR_NUMBER')
    )
    print(message.status)


import json
import logging

import disnake

from cogs5e.initiative.combatant import Combatant, MonsterCombatant, PlayerCombatant
from cogs5e.initiative.utils import create_combatant_id
from cogs5e.models.automation import EffectResult, IEffectResult
from gamedata import Monster, Spell, compendium
from tests.discord_mock_data import DEFAULT_USER_ID
from tests.utils import ContextBotProxy, requires_data
from utils.argparser import argparse

log = logging.getLogger(__name__)

async def run_automation(automation, avrae, combat=None, targets=None, **kwargs):
    """
    Runs the given automation and runs basic assertions on its results.

    If *combat* is given and the automation returns ieffects granting attacks or buttons, those will be tested
    recursively.
    """
    if targets is None:
        targets = []

    default_kwargs = dict(
        ctx=ContextBotProxy(avrae), embed=disnake.Embed(), args=argparse(""), combat=combat, targets=targets
    )
    result = await automation.run(**{**default_kwargs, **kwargs})
    result_dict = result.to_dict()  # AutomationResult must be dict-serializable
    assert json.dumps(result_dict)  # and JSON-serializable

    log.info("Completed root automation")

    async def _recurse_results(result: EffectResult):
        """Recurse over an automation result, and run granted buttons and attacks"""
        for node in result:
            if isinstance(node, IEffectResult) and node.effect.combatant is not None:
                log.info(f"Found IEffect with combatant: {node.effect.name} on {node.effect.combatant.name}")
                for attack_interaction in node.effect.attacks:
                    # simulate running the attack against the same targets
                    attack = attack_interaction.attack
                    log.info(f"Simulating granted action: {attack.name}")
                    await run_automation(
                        attack.automation,
                        avrae,
                        combat=combat,
                        caster=node.effect.combatant,
                        targets=targets,
                        **attack.__run_automation_kwargs__,
                    )
                    log.info(f"Finished simulating granted action: {attack.name}")
                for button in node.effect.buttons:
                    # simulate clicking the button
                    # this is pretty much just copied from cogs5e.initiative.buttons
                    log.info(f"Simulating granted button: {button.label}")
                    if button.granting_spell_id is not None:
                        spell = compendium.lookup_entity(Spell.entity_type, button.granting_spell_id)
                    else:
                        spell = None
                    await run_automation(
                        button.automation,
                        avrae,
                        combat=combat,
                        caster=node.effect.combatant,
                        targets=[],
                        ieffect=node.effect,
                        allow_caster_ieffects=False,
                        # do not allow things like damage-boosting effects to affect dot ticks
                        ab_override=button.override_default_attack_bonus,
                        dc_override=button.override_default_dc,
                        spell_override=button.override_default_casting_mod,
                        spell=spell,
                        spell_level_override=button.granting_spell_cast_level,
                        from_button=True,
                    )
                    log.info(f"Finished simulating granted button: {button.label}")
                log.info(f"Finished IEffect on combatant: {node.effect.name} on {node.effect.combatant.name}")
            await _recurse_results(node)

    if combat is not None:
        await _recurse_results(result)

def create_basic_combatant(combat, avrae):
    """Creates a new minimal basic combatant, adds it to the combat, and returns it"""
    basic_combatant = Combatant(
        id=create_combatant_id(),
        name="Test Combatant",
        controller_id=int(DEFAULT_USER_ID),
        init=0,
        private=False,
        ctx=ContextBotProxy(avrae),
        combat=combat,
    )
    combat.add_combatant(basic_combatant)
    return basic_combatant

@requires_data(fail_if_no_data=True)
def create_monster_combatant(combat, avrae, monster_id=16939):
    """Creates a new monster combatant, adds it to the combat, and returns it. Defaults to using a kobold"""
    mon = compendium.lookup_entity(Monster.entity_type, monster_id)
    return create_monster_combatant_from_monster(combat, avrae, mon)

def create_monster_combatant_from_monster(combat, avrae, monster):
    monster_combatant = MonsterCombatant.from_monster(
        monster,
        ctx=ContextBotProxy(avrae),
        combat=combat,
        name="Test Monster",
        controller_id=int(DEFAULT_USER_ID),
        init=0,
        private=False,
    )
    combat.add_combatant(monster_combatant)
    return monster_combatant

def create_player_combatant(combat, avrae, character):
    """Creates a new player combatant from the given character and adds and returns it"""
    player_combatant = PlayerCombatant.from_character(
        character,
        ctx=ContextBotProxy(avrae),
        combat=combat,
        controller_id=int(DEFAULT_USER_ID),
        init=0,
        private=False,
    )
    combat.add_combatant(player_combatant)
    return player_combatant


from django.shortcuts import render, redirect, reverse, get_object_or_404
from .models import Artworks
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.db.models import Q
from .forms import ArtworkForm, ArtworkEditForm
from members.models import Members

def all_artworks(request):
    """ A view to show all artworks, including sorting and search queries """

    artworks = Artworks.objects.all()
    qry = None
    sort = None
    direction = None

    if request.GET:
        if 'sort' in request.GET:
            sortkey = request.GET['sort']
            sort = sortkey
            if 'direction' in request.GET:
                direction = request.GET['direction']
                if direction == 'desc':
                    sortkey = f'-{sortkey}'
            artworks = artworks.order_by(sortkey)

        if 'q' in request.GET:
            qry = request.GET['q']
            if not qry:
                messages.error(request, "You didn't enter any search criteria")
                return redirect(reverse('artworks'))

            queries = Q(title__icontains=qry) | Q(description__icontains=qry)
            artworks = artworks.filter(queries)

    current_sorting = f'{sort}_{direction}'

    context = {
        'artworks': artworks,
        'search_term': qry,
        'current_sorting': current_sorting,
    }

    return render(request, 'artworks/artworks.html', context)

def artwork_detail(request, artwork_id):
    """ A view to show individual artwork details """

    artwork = get_object_or_404(Artworks, pk=artwork_id)

    context = {
        'artwork': artwork,
    }

    return render(request, 'artworks/artwork_detail.html', context)

@login_required
def add_artwork(request):
    """ Add an artwork to the club """
    if not request.user.is_superuser:
        messages.error(request, 'Sorry, only club admin can do that.')
        return redirect(reverse('home'))

    if request.method == 'POST':
        form = ArtworkForm(request.POST, request.FILES)
        if form.is_valid():
            artwork = form.save()
            messages.success(request, 'Successfully added artwork')
            return redirect(reverse('artwork_detail', args=[artwork.id]))
        else:
            messages.error(request,
                           'Failed to add artwork.\
                            Please ensure the form is valid.')
    else:
        form = ArtworkForm()

    template = 'artworks/add_artwork.html'
    context = {
        'form': form,
    }

    return render(request, template, context)

@login_required
def edit_artwork(request, artwork_id):
    """ Edit a artwork in the club """
    if not request.user.is_superuser:
        messages.error(request, 'Sorry, only club admin can do that.')
        return redirect(reverse('home'))

    artwork = get_object_or_404(Artworks, pk=artwork_id)
    if request.method == 'POST':
        form = ArtworkEditForm(request.POST, request.FILES, instance=artwork)
        if form.is_valid():
            form.save()
            messages.success(request, 'Successfully updated artwork')
            return redirect(reverse('artwork_detail', args=[artwork.id]))
        else:
            messages.error(request, 'Failed to update artwork. \
                                     Please ensure form is valid.')
    else:
        form = ArtworkEditForm(instance=artwork)
        messages.info(request, f'You are editing {artwork.title}')

    template = 'artworks/edit_artwork.html'
    context = {
        'form': form,
        'artwork': artwork,
    }

    return render(request, template, context)

@login_required
def delete_artwork(request, artwork_id):
    """ Delete an artwork from the club """
    if not request.user.is_superuser:
        messages.error(request, 'Sorry, only club admin can do that.')
        return redirect(reverse('home'))

    artwork = get_object_or_404(Artworks, pk=artwork_id)
    artwork.delete()
    messages.success(request, 'Artwork deleted!')
    return redirect(reverse('artworks'))

@login_required
def sold_artwork(request):
    """ Query on sold artworks """

    sold = Artworks.objects.filter(sold=True)
    sold_count = sold.count()

    template = 'artworks/sold_artwork.html'
    context = {
        'artworks': sold,
        'count': sold_count,
    }

    return render(request, template, context)

@login_required
def my_sales(request):
    """ Query on sold artworks for a logged in member """

    sold = Artworks.objects.filter(sold=True)
    usrnm = request.user.username

    if usrnm:
        try:
            Members.objects.get(username=usrnm)
        except Members.DoesNotExist:
            messages.info(request, 'Sorry, only club members can do that.')
            return redirect(reverse('home'))

    template = 'artworks/my_sales.html'
    context = {
        'artworks': sold,
        'username': usrnm,
    }

    return render(request, template, context)


from scapy.layers.ssl_tls import *
from scapy.utils import rdpcap
import scapy.all as scapy
import json
import time

check_dic = {}
length = 0

def processCap(fileName, filename2):
    print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
    rawTuple_read = open(filename2, "r")
    rawTuple_dic = json.load(rawTuple_read)
    #print("CCCCCCCC")
    global check_dic
    global length
    myreader = scapy.PcapReader(fileName)
    #pkts = scapy.rdpcap(fileName)
    for key in rawTuple_dic:
        dic_ = {}
        dic_["client_sessionID"] = None
        dic_["server_sessionID"] = None
        dic_["sessionID_eq"] = None
        dic_["ssl_state"] = rawTuple_dic[key]["ssl_dic"]["sslConnection"]
        dic_["conn_state"] = rawTuple_dic[key]["conn_dic"]["connectionState"]
        dic_["certificate"] = "F"
        dic_["serverKey"] = "F"
        dic_["serverChangeCipherSpec"] = "F"
        check_dic[key] = dic_
    print("************************************************")
    #only process client hello packet
    #for pkt in pkts:
    i = 0
    while True:
        try:
            pkt = myreader.read_packet()
            if pkt is None:
                break
            # i = i + 1
            # print(i)
            if pkt.haslayer("IP"):
                srcIP = pkt["IP"].src
                dstIP = pkt["IP"].dst
                if srcIP == "10.0.2.15":
                    if pkt.haslayer("TCP"):
                        sport = pkt["TCP"].sport
                        dport = pkt["TCP"].dport
                        key = srcIP + "/" + str(sport) + "/" + dstIP + "/" + str(dport)
                        if pkt.haslayer(TLSClientHello):
                            clienthello = pkt.getlayer(TLSClientHello)
                            id_length = clienthello.session_id_length
                            if id_length != 0:
                                check_dic[key]["client_sessionID"] = clienthello.session_id
                elif dstIP == "10.0.2.15":
                    srcIP = pkt["IP"].src
                    dstIP = pkt["IP"].dst
                    if dstIP == "10.0.2.15":
                        if pkt.haslayer(TCP):
                            sport = pkt["TCP"].sport
                            dport = pkt["TCP"].dport
                            key = dstIP + "/" + str(dport) + "/" + srcIP + "/" + str(sport)
                            if pkt.haslayer(TLSRecord):
                                layer1 = pkt.getlayer(TLSCiphertext)
                                layer1.display()
                                # print(layer2)
                                print("AAAAA")
                                handshakes = pkt.getlayer(TLSHandshakes)
                                for handshake in handshakes:
                                    if handshake.haslayer(TLSServerHello):
                                        print("aaa")
                                        serverhello = pkt.getlayer(TLSServerHello)
                                        id_length = serverhello.session_id_length
                                        if id_length != 0:
                                            check_dic[key]["server_sessionID"] = serverhello.session_id
                                    elif pkt.haslayer(TLSCertificate):
                                        print("bbbb")
                                        check_dic[key]["certificate"] = "T"
                                    elif pkt.haslayer(TLSServerKeyExchange):
                                        print("cccccccc")
                                        check_dic[key]["serverKey"] = "T"
                                    elif pkt.haslayer(TLSChangeCipherSpec):
                                        check_dic[key]["serverChangeCipherSpec"] = "T"
                                    else:
                                        pass

                else:
                    pass
        except:
            break
    # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
    # for key in check_dic:
    #     length += 1
    #     if check_dic[key]["client_sessionID"] != None and check_dic[key]["server_sessionID"] != None:
    #         if check_dic[key]["client_sessionID"] == check_dic[key]["server_sessionID"]:
    #             check_dic[key]["sessionID_eq"] = "T"
    #case1
    # num_true_ssl = 0
    # num = 0
    # print(length)
    # num_cert = 0
    # num_serverkey = 0
    # num_changeCipher = 0
    # num_client_none = 0
    # for key in check_dic:
    #     if check_dic[key]["ssl_state"] == "T":
    #         num_true_ssl += 1
    #         if check_dic[key]["certificate"] == "T":
    #             num_cert += 1
    #         if check_dic[key]["serverKey"] == "T":
    #             num_serverkey += 1
    #         if check_dic[key]["serverChangeCipherSpec"] == "T":
    #             num_changeCipher += 1
    #         if check_dic[key]["client_sessionID"] == None :
    #             num_client_none += 1
    #             if check_dic[key]["server_sessionID"] == None:
    #                 num += 1
    #         else:
    #             if check_dic[key]["server_sessionID"] != None:
    #                 print(check_dic[key]["sessionID_eq"])
    #     else:
    #         print(">>>>>>>>>>>>")
    #         print(check_dic[key]["client_sessionID"])
    #         print(check_dic[key]["server_sessionID"])
    # print(num_true_ssl)
    # print("num_cert")
    # print(num_cert)
    # print("num_serverkey")
    # print(num_serverkey)
    # print("num_changeCipher")
    # print(num_changeCipher)
    # print("-----------------")
    # print(num_client_none)
    # print(num)

if __name__ == '__main__':
    rawTuple_file = "Datasets/CTU-Normal-27/bro/result_rawTuple.json"
    pcap_file = "Datasets/CTU-Normal-27/456.pcap"
    processCap(pcap_file, rawTuple_file)


import traceback
from opcua import Client

client = Client("opc.tcp://admin:admin@elmpc-129:51310/CogentDataHub/DataAccess")
client.connect()
all_ob = client.get_objects_node()

#
# def check(node_data):
#     if isinstance(node_data, list):
#         res = list_handler(node_data)
#         return res
#     else:
#         res = node_data.get_children()
#         if isinstance(node_data, list):
#             res = list_handler(node_data)
#             return res
#         return res
#
# def list_handler(node_ids):
#     store_objs = []
#     for data_points in node_ids:
#         try:
#             child = data_points.get_children()
#             if isinstance(child, list):
#                 return list_handler(child)
#
#         except Exception as e:
#             # traceback.print_exc()
#             # check(node_ids)
#             data = client.get_node(data_points).get_value()
#             store_objs.append(data)
#             return capture_data(data)
#
#
# def capture_data(data, total=[]):
#     total.append(data)
#     return data
# print(all_ob)
# print(all_ob.get_children())
# stat = check(all_ob.get_children()[1:])
# print(type(stat))
# print(capture_data(list_handler(check(stat))))
from opcua.ua.uaerrors import BadAggregateInvalidInputs, BadAttributeIdInvalid
store_all_list_node=[]
def get_all_data_values(node):
    try:
        data = client.get_node(str(node))
        store_all_list_node.append(data)
        data = data.get_value()
        # print(data)
        """Here we are getting values from the server, what we need to check is whether the request is first or not if the request is first do the
        process like we did.
        But if the request is second or more then at first request we are going to store the neccessary(which are giving data) nodes
        and then after first request we are going to call that stored nodes."""
    except BadAggregateInvalidInputs:
        if isinstance(node, list):
            main_(node)
        main_(node)
        traceback.print_tb()
        pass

    return data

def main_(data):
    try:
        get_all_data_values(data)
    except BadAttributeIdInvalid:
        check_child = data.get_children()
        if isinstance(check_child, list):
            for some_data in check_child:
                try:
                    get_all_data_values(some_data)
                except BadAttributeIdInvalid:
                    pass

        else:
            traceback.print_exception()
print(all_ob.get_children_descriptions())
print('#'*20,all_ob.get_children(refs=33))
print(client.load_type_definitions())
# print(client.load_enums())
one = all_ob.get_children(refs=33)
for i in one:
    two = i.get_children(refs=33)
    print(two)
list_of_nodes = all_ob.get_children()[1:]
for i in list_of_nodes:
    # print(i.get_children())
    if i:
        main_(i)
        print(store_all_list_node)
while True:
    for ch in store_all_list_node:
        print()
        try:
            print(ch.get_value())
            print(ch.get_browse_name())

        except BadAttributeIdInvalid:
            main_(ch)


"""
1376. Time Needed to Inform All Employees
Medium

A company has n employees with a unique ID for each employee from 0 to n - 1.
The head of the company is the one with headID.

Each employee has one direct manager given in the manager array where manager[i]
is the direct manager of the i-th employee, manager[headID] = -1.
Also, it is guaranteed that the subordination relationships have a tree structure.

The head of the company wants to inform all the company employees of an urgent piece of news.
He will inform his direct subordinates, and they will inform their subordinates,
and so on until all employees know about the urgent news.

The i-th employee needs informTime[i] minutes to inform all of his direct subordinates
(i.e., After informTime[i] minutes, all his direct subordinates can start spreading the news).

Return the number of minutes needed to inform all the employees about the urgent news.

Example 1:

Input: n = 1, headID = 0, manager = [-1], informTime = [0]
Output: 0
Explanation: The head of the company is the only employee in the company.
Example 2:

Input: n = 6, headID = 2, manager = [2,2,-1,2,2,2], informTime = [0,0,1,0,0,0]
Output: 1
Explanation: The head of the company with id = 2 is the direct manager of all the
              employees in the company and needs 1 minute to inform them all.
The tree structure of the employees in the company is shown.

test_case=
1
0
[-1]
[0]
6
2
[2,2,-1,2,2,2]
[0,0,1,0,0,0]
7
6
[1,2,3,4,5,6,-1]
[0,6,5,4,3,2,1]
15
0
[-1,0,0,1,1,2,2,3,3,4,4,5,5,6,6]
[1,1,1,1,1,1,1,0,0,0,0,0,0,0,0]
8
0
[-1,5,0,6,7,0,0,0]
[89,0,0,0,0,523,241,519]

Constraints:

1 <= n <= 105
0 <= headID < n
manager.length == n
0 <= manager[i] < n
manager[headID] == -1
informTime.length == n
0 <= informTime[i] <= 1000
informTime[i] == 0 if employee i has no subordinates.
It is guaranteed that all the employees can be informed.
"""
from collections import defaultdict
from typing import List

class Solution:
    def __init__(self):
        self.time = 0

    def numOfMinutes(
        self, n: int, headID: int, manager: List[int], informTime: List[int]
    ) -> int:
        # manager: find who is i's manager
        # informTime: give the time of i to inform
        # employee: [0..n-1]
        # head: headID (0 to n-1)
        # target: from head -> all the informTime
        # subord = {id: [subordinates]}-> id->informTime
        m = len(manager)
        subord = defaultdict(list)
        for i in range(m):
            if i == headID:
                continue
            subord[manager[i]].append(i)
        # print(subord)

        # recurse cal from emp to all subordinates neet max time
        def dfs(emp):
            if emp not in subord:
                return 0
            t = 0
            # loop over emp's all subordinates. emp: boos; it: subordinate
            for it in subord[emp]:
                t = max(t, dfs(it) + informTime[emp])
            return t

        return dfs(headID)


"""
This python file contains a class doing
loading trained model, inference from these model ,
find max scores according to prediction of the class
and bounding boxes and calculate the plate strings
"""

import os
import cv2
import numpy as np
import tensorflow as tf
import sys
import pandas as pd
from utils import label_map_util
from utils import visualization_utils as vis_util
from detect_plate import Detection

class Detection_Number_Plate:
    def __init__(self):
        sys.path.append("..")

        self.MODEL_NAME = 'inference_graph2'
        self.CWD_PATH = os.getcwd()
        self.PATH_TO_CKPT = os.path.join(self.CWD_PATH,self.MODEL_NAME,'frozen_inference_graph.pb')
        self.PATH_TO_LABELS = os.path.join(self.CWD_PATH,'training2','labelmap.pbtxt')

        self.NUM_CLASSES = 36

        self.label_map = label_map_util.load_labelmap(self.PATH_TO_LABELS)
        self.categories = label_map_util.convert_label_map_to_categories(self.label_map, max_num_classes=self.NUM_CLASSES, use_display_name=True)
        self.category_index = label_map_util.create_category_index(self.categories)

    def run(self,image):
        """
        This function responsible of running below functions
        Args:
            image: an image that contain plate that would be predicted its numbers
        Returns:
            plate: the plate numbers
            score: the score about plate numbers
        """

        self.build_graph()
        self.get_tensors()
        self.predict(image)
        self.prediction = self.get_all_classes_prediction()
        prediction_max =self.find_max_prob(0.60)
        self.box_coordinates = self.find_bounding_box_coordinates(prediction_max)
        plate, score = self.arrange_prediction()
        return plate,score

    def build_graph(self):
        """
        This function builds detection graph by loading it into memory
        """

        self.detection_graph = tf.Graph()
        with self.detection_graph.as_default():
            self.od_graph_def = tf.GraphDef()
            with tf.gfile.GFile(self.PATH_TO_CKPT, 'rb') as fid:
                self.serialized_graph = fid.read()
                self.od_graph_def.ParseFromString(self.serialized_graph)
                tf.import_graph_def(self.od_graph_def, name='')

        self.sess = tf.Session(graph=self.detection_graph)

    def get_tensors(self):
        """
        This function generates tensors
        """
        self.image_tensor = self.detection_graph.get_tensor_by_name('image_tensor:0')
        self.detection_boxes = self.detection_graph.get_tensor_by_name('detection_boxes:0')
        self.detection_scores = self.detection_graph.get_tensor_by_name('detection_scores:0')
        self.detection_classes = self.detection_graph.get_tensor_by_name('detection_classes:0')

    def predict(self,image):
        """
        This function reads image and predicts the classes ,scores and boxes
        Args:
            image: an image that contains plate
        """
        self.build_graph()
        self.get_tensors()

        image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        image_expanded = np.expand_dims(image_rgb, axis=0)

        (self.boxes, self.scores, self.classes) = self.sess.run(
            [self.detection_boxes, self.detection_scores, self.detection_classes],
            feed_dict={self.image_tensor: image_expanded})

    def get_all_classes_prediction(self):
        """
        This functions calculates predictions of all classes and stack its to python dictionary
        Returns:
            all_prediction: a dictionary having all predictions of classes
        """
        classes_ = np.squeeze(self.classes)
        scores_ = np.squeeze(self.scores)

        max_classes = classes_ .shape[0]
        all_predictions = {}

        for i in range(max_classes):
         all_predictions[i] = {}

        for i in range(max_classes):
            max_indice = np.argmax(scores_)
            class_name = self.category_index[classes_[max_indice]]['name']
            all_predictions[i][class_name] = scores_[max_indice]
            scores_ = np.delete(scores_,max_indice)
            classes_ = np.delete(classes_,max_indice)
        return all_predictions

    def find_max_prob(self,threshold):
        """
        This function finds max probabilty of predicted classes according to the threshold
        Args:
            threshold: a float number
        Returns:
            new_dict: a dictionary that contains max probability of classes
        """
        copy = self.prediction.copy()
        new_dict = {}

        for i in range(len(copy)):
            new_dict[i] = {}

        for i,k  in enumerate(copy):
            for key in copy[k]:
             if copy[k][key] > threshold:
              new_dict[i][str(key)] = copy[k][key]
             else:
                 pass

        return new_dict

    def find_bounding_box_coordinates(self,plate_dict):
        """
        This functions finds bounding box coordinates according to max probability of classes
        Args:
            plate_dict: a dictionary that contains max probability of classes
        Returns:
            finding_boxes: a numpy array that contains bounding boxes according to max probablity of classes
        """
        boxes = np.squeeze(self.boxes)
        scores = np.squeeze(self.scores)
        plate_dict = plate_dict.copy()

        finding_boxes  = []

        for i,value in enumerate(scores):
            if value in plate_dict[i].values():
             index = np.where(scores == value)
             finding_boxes.append(boxes[index])

        return np.asarray(finding_boxes)

    def get_x_mins(self,box_coordinates):
        """
        This function gives xmin coordinates
        Args:
            box_coordinates: a numpy array that contains bounding box
        Returns:
            x_mins: a numpy array that contains xmin coordinate of bounding box

        """
        box_coordinates = box_coordinates.copy()
        x_mins = []
        for b_list in box_coordinates:
            x_mins.append(b_list[0][1])

        return np.asarray(x_mins)

    def order_coordinates(self):
        """
        This function orders the bouinding box coordinates to acquire plate as ordered left-to-right
        Returns:
            sorted_array: a array of xmins coordinate of bounding boxes as sorted
            sorted_indices: indices that are sorted , numpy array
        """
        x_mins = self.get_x_mins(self.box_coordinates)
        sorted_indices = np.argsort(x_mins)
        sorted_array = x_mins[sorted_indices]

        return sorted_array, sorted_indices

    def arrange_prediction(self):
        """
        This function acquires the plate and score according to sorted predicted classes and scores
        Returns:
            plate: a string that contain plate as sorted
            score: a string that contain all classes scores bracket with "-"
        """
        sorted_coordinates , sorted_indices = self.order_coordinates()
        classes = np.squeeze(self.classes)
        scores = np.squeeze(self.scores)

        class_names = []
        scores_ = []

        for i in range(len(sorted_coordinates)):
         index = sorted_indices[i]
         class_index = classes[index]
         class_name = self.category_index[class_index]['name']
         class_names.append(class_name)
         scores_.append(scores[index])

        plate = ""
        score = ""
        for i in range(len(class_names)):
            plate += class_names[i]
            score += str(scores_[i])+"\n"

        return plate,score


############################################################
#
# craft_poisons_htbd.py
# Hidden Trigger Backdoor Attack
# June 2020
#
# Reference: A. Saha, A. Subramanya, and H. Pirsiavash. Hidden
#     trigger backdoor attacks. arXiv:1910.00033, 2019.
############################################################
import argparse
import logging
import os
import pickle
import sys

import numpy as np
import torch
import torch.utils.data
import torchvision
import torchvision.transforms as transforms
from PIL import Image

sys.path.append(os.path.realpath("."))
from learning_module import (
    TINYIMAGENET_ROOT,
    load_model_from_checkpoint,
    now,
    get_transform,
    NormalizeByChannelMeanStd,
    data_mean_std_dict,
)
from tinyimagenet_module import TinyImageNet

class LossMeter(object):
    """Computes and stores the average and current loss value"""

    def __init__(self):
        self.reset()

    def reset(self):
        self.val = 0
        self.avg = 0
        self.sum = 0
        self.count = 0

    def update(self, val, n=1):
        self.val = val
        self.sum += val * n
        self.count += n
        self.avg = self.sum / self.count

def adjust_learning_rate(lr, iteration, dataset):
    """Update the learning rate by a factor after certain iterations
    inputs:
        lr:         Current learning rate
        iter:       Current iteration number
        dataset:  Name of the dataset
    return:
        updated learning rate
    """
    if dataset.upper() == "CIFAR10":
        lr = lr * (0.95 ** (iteration // 2000))
        return lr
    else:
        lr = lr * (0.5 ** (iteration // 1000))
        return lr

def main(args):
    """Function to generate the generate the HTBD poison
    inputs:
        args:        Argument Parser object
    return:
        void
    """
    print(now(), "craft_poisons_htbd.py main() running...")
    mean, std = data_mean_std_dict[args.dataset.lower()]
    normalization_net = NormalizeByChannelMeanStd(mean, std)
    device = "cuda" if torch.cuda.is_available() else "cpu"
    net = load_model_from_checkpoint(
        args.model[0], args.model_path[0], args.pretrain_dataset
    )
    net.eval()
    normalization_net = normalization_net.to(device)
    net = net.to(device)

    ####################################################
    #               Dataset
    if args.dataset.lower() == "cifar10":
        transform_test = get_transform(False, False)
        testset = torchvision.datasets.CIFAR10(
            root="./data", train=False, download=True, transform=transform_test
        )
        trainset = torchvision.datasets.CIFAR10(
            root="./data", train=True, download=True, transform=transform_test
        )
        num_per_class = 5000
    elif args.dataset.lower() == "tinyimagenet_first":
        transform_test = get_transform(False, False, dataset=args.dataset)
        trainset = TinyImageNet(
            TINYIMAGENET_ROOT,
            split="train",
            transform=transform_test,
            classes="firsthalf",
        )
        testset = TinyImageNet(
            TINYIMAGENET_ROOT,
            split="val",
            transform=transform_test,
            classes="firsthalf",
        )
        num_per_class = 500
    elif args.dataset.lower() == "tinyimagenet_last":
        transform_test = get_transform(False, False, dataset=args.dataset)
        trainset = TinyImageNet(
            TINYIMAGENET_ROOT,
            split="train",
            transform=transform_test,
            classes="lasthalf",
        )
        testset = TinyImageNet(
            TINYIMAGENET_ROOT,
            split="val",
            transform=transform_test,
            classes="lasthalf",
        )
        num_per_class = 500
    elif args.dataset.lower() == "tinyimagenet_all":
        transform_test = get_transform(False, False, dataset=args.dataset)
        trainset = TinyImageNet(
            TINYIMAGENET_ROOT,
            split="train",
            transform=transform_test,
            classes="all",
        )
        testset = TinyImageNet(
            TINYIMAGENET_ROOT,
            split="val",
            transform=transform_test,
            classes="all",
        )
        num_per_class = 500
    else:
        print("Dataset not yet implemented. Exiting from craft_poisons_htbd.py.")
        sys.exit()
    ###################################################

    with open(args.poison_setups, "rb") as handle:
        setup_dicts = pickle.load(handle)
    setup = setup_dicts[args.setup_idx]

    losses = LossMeter()
    lr = args.lr

    trans_trigger = transforms.Compose(
        [transforms.Resize((args.patch_size, args.patch_size)), transforms.ToTensor()]
    )
    trigger = Image.open(args.trigger_path).convert("RGB")
    trigger = trans_trigger(trigger).unsqueeze(0).to(device)

    target_img_idx = (
        setup["target index"] if args.target_img_idx is None else args.target_img_idx
    )
    base_indices = (
        setup["base indices"] if args.base_indices is None else args.base_indices
    )

    target_img_save, target_label_save = testset[target_img_idx]
    target_class = target_label_save

    # Get target images
    trainset_targets = np.array(trainset.targets)
    target_class = target_class
    tar_idx = np.where(trainset_targets == target_class)[0]
    indexes = np.arange(0, num_per_class)
    indexes = np.random.choice(indexes, len(base_indices), replace=False)
    target_img_idx = np.array(tar_idx[indexes]).astype(int)

    poisoned_tuples = []
    target_tuples = []

    # get multiple bases
    base_imgs = torch.stack([trainset[i][0] for i in base_indices]).to(device)
    base_labels = torch.LongTensor([trainset[i][1] for i in base_indices]).to(device)

    target_imgs = torch.stack([trainset[i][0] for i in target_img_idx]).to(device)

    batch_size = base_imgs.shape[0]

    start_x = args.image_size - args.patch_size - 5
    start_y = args.image_size - args.patch_size - 5

    for i in range(0, len(base_imgs), batch_size):

        remaining = np.min((batch_size, len(base_imgs) - i))
        input_target_imgs = target_imgs[i : i + remaining]
        input_bases = base_imgs[i : i + remaining]
        input_target_imgs = input_target_imgs.to(device)
        input_bases = input_bases.to(device)

        for z in range(input_target_imgs.size(0)):
            # paste the trigger on input_target_imgs
            input_target_imgs[
                z,
                :,
                start_y : start_y + args.patch_size,
                start_x : start_x + args.patch_size,
            ] = trigger

        # get features of input_target_imgs
        if args.normalize:
            input_target_imgs = normalization_net(input_target_imgs)
        feat1 = net(input_target_imgs, penu=True)
        feat1 = feat1.detach().clone()

        for j in range(args.crafting_iters):
            input_bases.requires_grad_()
            lr1 = adjust_learning_rate(lr, j, args.dataset)

            # get features of input_bases
            if args.normalize:
                input_bases_proc = normalization_net(input_bases)
            else:
                input_bases_proc = input_bases

            feat2 = net(input_bases_proc, penu=True)
            feat11 = feat1.clone()
            dist = torch.cdist(feat1, feat2)
            for _ in range(feat2.size(0)):

                dist_min_index = (dist == torch.min(dist)).nonzero().squeeze()
                feat1[dist_min_index[1]] = feat11[dist_min_index[0]]
                dist[dist_min_index[0], dist_min_index[1]] = 1e5

            loss = torch.norm(feat1 - feat2) ** 2
            losses.update(loss.item(), input_target_imgs.size(0))
            loss.backward()

            input_bases = input_bases - lr1 * input_bases.grad
            pert = input_bases - base_imgs[i : i + remaining]
            pert = torch.clamp(pert, -args.epsilon, args.epsilon).detach_()
            input_bases = pert + base_imgs[i : i + remaining]
            input_bases = input_bases.clamp(0, 1)

            if j % 100 == 0:
                logging.info(
                    "Epoch: {:2d} | i: {} | iter: {:5d} | LR: {:2.5f} | Loss Val: {:5.3f} | Loss Avg: {:5.3f}".format(
                        0, i, j, lr1, losses.val, losses.avg
                    )
                )
                print(
                    "Epoch: {:2d} | i: {} | iter: {:5d} | LR: {:2.5f} | Loss Val: {:5.3f} | Loss Avg: {:5.3f}".format(
                        0, i, j, lr1, losses.val, losses.avg
                    )
                )

            if loss.item() < 10 or j == (args.crafting_iters - 1):
                logging.info("Max_Loss: {}".format(loss.item()))
                for k in range(input_bases.size(0)):
                    poisoned_tuples.append(
                        (
                            transforms.ToPILImage()(input_bases[k].cpu()),
                            int(base_labels[i + k]),
                        )
                    )
                    if len(target_tuples) < 1:
                        img = target_img_save.to(device)
                        trigger_ = trigger.cpu()

                        # Tuple for target.pickle
                        target_tuples.append(
                            (
                                transforms.ToPILImage()(img.cpu()),
                                int(target_label_save),
                                trigger_.squeeze(0),
                                [start_x, start_y],
                            )
                        )
                break

    # Creating the directories and saving the poisons
    print(now(), "Saving poisons...")
    if not os.path.isdir(args.poisons_path):
        os.makedirs(args.poisons_path)
    with open(os.path.join(args.poisons_path, "poisons.pickle"), "wb") as handle:
        pickle.dump(poisoned_tuples, handle, protocol=pickle.HIGHEST_PROTOCOL)
    with open(os.path.join(args.poisons_path, "target.pickle"), "wb") as handle:
        pickle.dump(target_tuples[0], handle, protocol=pickle.HIGHEST_PROTOCOL)
    with open(os.path.join(args.poisons_path, "base_indices.pickle"), "wb") as handle:
        pickle.dump(base_indices, handle, protocol=pickle.HIGHEST_PROTOCOL)
    ####################################################

    print(now(), "craft_poisons_htbd.py done.")
    return

if __name__ == "__main__":

    parser = argparse.ArgumentParser(description="Hidden Trigger Backdoor Attack")
    parser.add_argument("--dataset", type=str, default="CIFAR10", help="dataset")
    parser.add_argument("--normalize", dest="normalize", action="store_true")
    parser.add_argument("--no-normalize", dest="normalize", action="store_false")
    parser.set_defaults(normalize=True)
    parser.add_argument(
        "--epsilon", type=int, default=8 / 255, help="poison perturbation allowance"
    )
    parser.add_argument(
        "--model", type=str, default=["resnet18"], nargs="+", help="model name"
    )
    parser.add_argument("--image_size", type=int, default=32, help="Image Size")
    parser.add_argument("--patch_size", type=int, default=5, help="Size of the patch")
    parser.add_argument(
        "--trigger_path",
        type=str,
        default="./poison_crafting/triggers/htbd.png",
        help="Trigger path",
    )
    parser.add_argument("--lr", type=float, default=0.001, help="learning rate")
    parser.add_argument("--batch_size", type=int, default=100, help="Batch Size")
    parser.add_argument(
        "--crafting_iters", type=int, default=5000, help="Number of iterations"
    )
    parser.add_argument(
        "--poison_setups",
        type=str,
        default="./poison_setups/cifar10_transfer_learning.pickle",
        help="poison setup pickle file",
    )
    parser.add_argument("--setup_idx", type=int, default=0, help="Which setup to use")
    parser.add_argument(
        "--poisons_path",
        default="poison_examples/htbd_poisons",
        type=str,
        help="Where to save the poisons?",
    )
    parser.add_argument(
        "--base_indices", nargs="+", default=None, type=int, help="which base images"
    )
    parser.add_argument(
        "--target_img_idx",
        default=None,
        type=int,
        help="Index of the target image in the clean set.",
    )
    parser.add_argument(
        "--model_path",
        type=str,
        nargs="+",
        default=["pretrained_models/ResNet18_CIFAR100_A.pth"],
        help="Checkpoint file",
    )
    parser.add_argument(
        "--pretrain_dataset", default="CIFAR100", type=str, help="dataset"
    )

    args = parser.parse_args()

    if args.dataset.lower() == "cifar10":
        args.image_size = 32
    elif "tinyimagenet" in args.dataset.lower():
        args.image_size = 64

    main(args)