from time import sleep, clock_gettime, CLOCK_REALTIME
from grove.i2c import Bus

class bme280:
    """
    Grove bme280 sensor control library.
    Objects:
        - set_mode(mode, t_sb)
        - set_oversampling(osrs_h, osrs_t, osrs_p)
        - set_filter(filter_coefficient)
        - set_spi(spi3w_en)
        - write_reset()
        - read_id()
        - read_status()
        - read_compensated_signals()
        - read_raw_signals()
        - set_pressure_calibration(level, pressure)
        - get_altitude(pressure)
    """

    # Constant Definitions
    # Modes
    MODE_SLEEP = 0b00
    MODE_FORCE = 0b01
    MODE_NORMAL = 0b11

    # Normal mode standby values
    t_sb_0_5 = 0b000
    t_sb_62_5 = 0b001
    t_sb_125 = 0b010
    t_sb_250 = 0b011
    t_sb_500 = 0b100
    t_sb_1000 = 0b101
    t_sb_10 = 0b110
    t_sb_20 = 0b111

    # IIR filter coefficient
    filter_0 = 0b000
    filter_2 = 0b001
    filter_4 = 0b010
    filter_8 = 0b011
    filter_16 = 0b100

    # SPI control
    SPI_ON = 0b01
    SPI_OFF = 0b00

    # Oversampling modes
    OVRS_x0 = 0b000
    OVRS_x1 = 0b001
    OVRS_x2 = 0b010
    OVRS_x4 = 0b011
    OVRS_x8 = 0b100
    OVRS_x16 = 0b101

    def __init__(self):
        # Rev 2 Pi, Pi 2 & Pi 3 uses bus 1,  Rev 1 Pi uses bus 0
        # bme280 default I2C Address is 0x76
        self.bus = Bus()
        self.address = 0x76
        self.mode = self.MODE_SLEEP
        self.t_sb = self.t_sb_1000
        self.last_meas = 0

        # Calibration data
        # Calibration data registers are 0x88-0xA1(25 bytes) and 0xE1-0xE7(7 bytes) total 32 bytes
        self.calib = [0x00]*32

        # Init raw data array and variables
        self.raw_data = [0x00]*8
        self.raw_temperature = 0x00000
        self.raw_pressure = 0x00000
        self.raw_humidity = 0x00000

        # Init parameters
        self.osrs_h = self.OVRS_x0
        self.osrs_t = self.OVRS_x0
        self.osrs_p = self.OVRS_x0

        # IIR filter and SPI interface are off by default
        self.filter = self.filter_0
        self.spi3w_en = self.SPI_OFF

        # Status word. Only has two significant bits bit0 = im_update and bit3 = measuring
        self.status = 0x00
        self.im_update = False
        self.measuring = False

        # Compensation values
        # Temperature trimming values
        self.dig_T1 = 0x0000
        self.dig_T2 = 0x0000
        self.dig_T3 = 0x0000
        # Pressure trimming params
        self.dig_P1 = 0x0000
        self.dig_P2 = 0x0000
        self.dig_P3 = 0x0000
        self.dig_P4 = 0x0000
        self.dig_P5 = 0x0000
        self.dig_P6 = 0x0000
        self.dig_P7 = 0x0000
        self.dig_P8 = 0x0000
        self.dig_P9 = 0x0000
        # Humidity trimming params
        self.dig_H1 = 0x00
        self.dig_H2 = 0x0000
        self.dig_H3 = 0x00
        self.dig_H4 = 0x0000
        self.dig_H5 = 0x0000
        self.dig_H6 = 0x00

        # Get the trimming values
        self.__read_calib()

        # Variables for compensated measurements
        self.temperature = 0x00000
        self.pressure = 0x00000
        self.humidity = 0x00000
        self.calibrated_temperature = 0x00000
        self.calibrated_pressure = 0x00000
        self.calibrated_humidity = 0x00000

        # Variables for measurement calibration
        self.calibration_temperature = 0
        self.calibration_pressure = 0
        self.calibration_humidity = 0

    #########################################
    # set bme280 operating mode             #
    #########################################
    def set_mode(self, mode=MODE_SLEEP, t_sb=t_sb_1000):
        # Writes ctrl_meas register with current temperature and pressure oversampling settings
        # Only changes the mode
        # If normal mode selected also sets the standby time in config register

        # Set class variables
        self.mode = mode
        self.t_sb = t_sb

        # If no measurements are enabled there is no point going into measurement
        if self.osrs_t + self.osrs_p + self.osrs_h == 0:
            print("No measurement enabled!\nSee set_oversampling()-function to enable measurement.")
            return 0

        try:
            # If normal mode set also t_sb(standby time)
            if self.mode == self.MODE_NORMAL:
                # Write normal mode standby time t_sb to config register
                self.__config(t_sb, self.filter, self.spi3w_en)
                # Write mode to ctr_meas register
                self.__ctrl_meas(self.osrs_t, self.osrs_p, self.mode)
            # Otherwise just change the mode in ctrl_meas register
            else:
                self.__ctrl_meas(self.osrs_t, self.osrs_p, self.mode)

            self.last_meas = clock_gettime(CLOCK_REALTIME)
            # Everything went well return 1
            return 1
        except Exception as e:
            # e = sys.exc_info()[0]
            print("
Error: %s
" % e)
            return 0

    #########################################################################
    # Set oversampling/enable measurement. OVRS_x0 disables the measurement #
    #########################################################################
    def set_oversampling(self, osrs_h=OVRS_x0, osrs_t=OVRS_x0, osrs_p=OVRS_x0):
        # Set oversampling variables
        self.osrs_h = osrs_h
        self.osrs_t = osrs_t
        self.osrs_p = osrs_p

        try:
            # Set humidity oversampling
            self.__ctrl_hum(self.osrs_h)
            # Set temperature and pressure oversampling
            self.__ctrl_meas(self.osrs_t, self.osrs_p, self.mode)
        except Exception as e:
            # e = sys.exc_info()[0]
            print("
Error: %s
" % e)
            return 0

        # Everything went well return 1
        return 1

    #########################################
    # Set internal IIR filter               #
    #########################################
    def set_filter(self, filter_coefficient=filter_0):
        self.filter = filter_coefficient

        try:
            # Write config register with new filter setting
            self.__config(self.t_sb, self.filter, self.spi3w_en)
            return 1
        except Exception as e:
            # print("Error in set_filter()")
            print("
Error: %s
" % e)
            return 0

    #########################################
    # Set internal SPI interface            #
    #########################################
    def set_spi(self, spi3w_en=SPI_OFF):
        self.spi3w_en = spi3w_en

        try:
            # Write config register with new spi setting
            self.__config(self.t_sb, self.filter, self.spi3w_en)
            return 1
        except Exception as e:
            # print("Error in set_filter()")
            print("
Error: %s
" % e)
            return 0

    #########################################
    # Reset command                         #
    #########################################
    def write_reset(self):
        register = 0xE0
        data = 0xB6    # Reset command to register, other values than 0xB6 has no effect
        r_len = 0
        delay = 10

        command = ([register, data], r_len, delay)

        try:
            self.read_write(command)
            return 1
        except Exception as e:
            # print("Error in set_filter()")
            print("
Error: %s
" % e)
            return 0

    #########################################
    # read ID register                      #
    #########################################
    def read_id(self):
        register = 0xD0
        data = 0x00
        r_len = 1
        delay = 10

        command = ([register, data], r_len, delay)

        try:
            return hex(self.read_write(command)[0])
        except Exception as e:
            # print("Error in set_filter()")
            print("
Error: %s
" % e)
            return 0

    #########################################
    # read STATUS register                  #
    #########################################
    def read_status(self):
        register = 0xF3
        data = 0x00
        r_len = 1
        delay = 10

        command = ([register, data], r_len, delay)

        try:
            self.status = self.read_write(command)[0]
            self.measuring = (self.status >> 3) & 0b1
            self.im_update = self.status & 0b1
            return [self.status, self.measuring, self.im_update]
        except Exception as e:
            # print("Error in set_filter()")
            print("
Error: %s
" % e)
            return 0

    #########################################
    # read calibration registers            #
    #########################################
    def __read_calib(self):
        # Calibration data registers are 0x88-0xA1(25 bytes) and 0xE1-0xE7(7 bytes) total 32 bytes
        # command format ([Register, Data Bytes], Number of bytes to read, Additional sleep(ms))
        # If Number of bytes to read > 0 then read_write function reads from I2C Bus
        # Otherwise Write operation is performed.
        register1 = 0x88
        register2 = 0xE1
        data = 0x00
        r_len1 = 26
        r_len2 = 7
        delay = 10

        command1 = ([register1, data], r_len1, delay)
        command2 = ([register2, data], r_len2, delay)

        try:
            self.calib[0:26] = self.read_write(command1)
            self.calib[26:32] = self.read_write(command2)
        except Exception as e:
            # print("Error in set_filter()")
            print("
Error: %s
" % e)
            return 0

        # Assign fetched data to trim parameters
        # Temperature trimming params
        # unsigned are ok, signed must be calculated with twos complement
        bytes_short = 16
        bytes_char = 8

        self.dig_T1 = (self.calib[1] << 8) + (self.calib[0] & 0xffff)
        self.dig_T2 = self.__twos_complement(((self.calib[3] << 8) + self.calib[2]), bytes_short)
        self.dig_T3 = self.__twos_complement((self.calib[5] << 8) + self.calib[4], bytes_short)

        # Pressure trimming params
        self.dig_P1 = ((self.calib[7] << 8)+self.calib[6]) & 0xffff
        self.dig_P2 = self.__twos_complement((self.calib[9] << 8) + self.calib[8], bytes_short)
        self.dig_P3 = self.__twos_complement((self.calib[11] << 8) + self.calib[10], bytes_short)
        self.dig_P4 = self.__twos_complement((self.calib[13] << 8) + self.calib[12], bytes_short)
        self.dig_P5 = self.__twos_complement((self.calib[15] << 8) + self.calib[14], bytes_short)
        self.dig_P6 = self.__twos_complement((self.calib[17] << 8) + self.calib[16], bytes_short)
        self.dig_P7 = self.__twos_complement((self.calib[19] << 8) + self.calib[18], bytes_short)
        self.dig_P8 = self.__twos_complement((self.calib[21] << 8) + self.calib[20], bytes_short)
        self.dig_P9 = self.__twos_complement((self.calib[23] << 8) + self.calib[22], bytes_short)

        # Humidity trimming params
        self.dig_H1 = self.calib[25] & 0xff
        self.dig_H2 = self.__twos_complement((self.calib[27] << 8) + self.calib[26], bytes_short)
        self.dig_H3 = self.calib[28] & 0xff
        self.dig_H4 = self.__twos_complement((self.calib[29] << 4) + (self.calib[30] & 0x0f), bytes_short)
        self.dig_H5 = self.__twos_complement((self.calib[31] << 4) + ((self.calib[30] & 0xf0) >> 4), bytes_short)
        self.dig_H6 = self.__twos_complement(self.calib[32], bytes_char)

        # Everything went well return 1
        return 1

    #########################################
    # read raw signals registers            #
    #########################################
    def read_raw_signals(self):
        # RAW Signals memory area is 0xF7-0xFE so there is 8 bytes
        # command format ([Register, Data Bytes], Number of bytes to read, Additional sleep(ms))
        # If Number of bytes to read > 0 then read_write function reads from I2C Bus
        # Otherwise Write operation is performed.
        register = 0xF7
        data = 0x00
        r_len = 8
        delay = 10

        command = ([register, data], r_len, delay)

        try:
            self.raw_data = self.read_write(command)
            self.raw_pressure = (((self.raw_data[0] << 8) + self.raw_data[1]) << 4) + ((self.raw_data[2] >> 4) & 0x0f)
            self.raw_temperature = ((((self.raw_data[3] << 8) + self.raw_data[4]) << 4)
                                    + ((self.raw_data[5] >> 4) & 0x0f))
            self.raw_humidity = ((self.raw_data[6] << 8) + self.raw_data[7])
        except Exception as e:
            # print("Error in set_filter()")
            print("
Error: %s
" % e)
            return 0

        # Everything went well return 1
        return 1

    #########################################
    # read compensated signals              #
    #########################################
    def read_compensated_signals(self):
        # Assuming that raw signals are already read
        # Compensation is performed like in datasheet appendix 8
        # 8.1 Compensation formulas in double precision floating point

        try:
            # Get Temperature t_fine value
            t_fine = self.__comp_temperature()
            self.temperature = t_fine / 5120.0  # Output value of “51.23” equals 51.23 DegC
            self.calibrated_temperature = (self.temperature
                                           + (0 if self.calibration_temperature is 0 else self.calibration_temperature))

            # Get pressure
            self.pressure = self.__comp_pressure(t_fine) / 100.0
            self.calibrated_pressure = (self.pressure
                                        + (0 if self.calibration_pressure is 0 else self.calibration_pressure))

            # Get Humidity
            self.humidity = self.__comp_humidity(t_fine)
            self.calibrated_humidity = (self.humidity
                                        + (0 if self.calibration_humidity is 0 else self.calibration_humidity))

            return 1
        except Exception as e:
            # print("Error in set_filter()")
            print("
Error: %s
" % e)
            return 0

    #########################################
    # Temperature compensation formulas     #
    # returns t_fine, because it is used in #
    # other compensation formulas           #
    #########################################
    def __comp_temperature(self):
        var1 = ((self.raw_temperature / 16384.0) - (self.dig_T1 / 1024.0)) * self.dig_T2
        var2 = ((((self.raw_temperature / 131072.0) - (self.dig_T1 / 8192.0))
                 * ((self.raw_temperature / 131072.0) - (self.dig_T1 / 8192.0))) * self.dig_T3)
        # t_fine = var1 + var2
        return var1 + var2

    #############################################################
    # Pressure compensation formulas                            #
    # Returns pressure in Pa as double.                         #
    # Output value of “96386.2” equals 96386.2 Pa = 963.862 hPa #
    #############################################################
    def __comp_pressure(self, t_fine):
        var1 = (t_fine / 2.0) - 64000.0
        var2 = var1 * var1 * self.dig_P6 / 32768.0
        var2 = var2 + var1 * self.dig_P5 * 2.0
        var2 = (var2 / 4.0) + (self.dig_P4 * 65536.0)
        var1 = (self.dig_P3 * var1 * var1 / 524288.0 + self.dig_P2 * var1) / 524288.0
        var1 = (1.0 + var1 / 32768.0) * self.dig_P1
        if var1 == 0.0:
            return 0    # avoid exception caused by division by zero

        p = 1048576.0 - self.raw_pressure
        p = (p - (var2 / 4096.0)) * 6250.0 / var1
        var1 = self.dig_P9 * p * p / 2147483648.0
        var2 = p * self.dig_P8 / 32768.0
        p = p + (var1 + var2 + self.dig_P7) / 16.0
        return p

    ##################################################
    # Humidity compensation formulas                 #
    # Returns humidity in %rH as as double.          #
    # Output value of “46.332” represents 46.332 %rH #
    ##################################################
    def __comp_humidity(self, t_fine):
        var_h = t_fine - 76800.0
        var_h = ((self.raw_humidity - (self.dig_H4 * 64.0 + (self.dig_H5 / 16384.0 * var_h)))
                 * (self.dig_H2 / 65536.0 * (1.0 + self.dig_H6 / 67108864.0 * var_h
                                             * (1.0 + self.dig_H3 / 67108864.0 * var_h))))
        var_h = var_h * (1.0 - self.dig_H1 * var_h / 524288.0)
        if var_h > 100.0:
            var_h = 100.0
        elif var_h < 0.0:
            var_h = 0.0

        return var_h

    #########################################
    # write ctrl_hum register               #
    #########################################
    def __ctrl_hum(self, osrs_h=OVRS_x0):
        register = 0xF2
        r_len = 0
        delay = 10

        # Make byte to send
        # data = ((0x00 << 3) + osrs_h)
        data = osrs_h

        command = ([register, data], r_len, delay)
        self.read_write(command)

    #########################################
    # write ctrl_meas register              #
    #########################################
    def __ctrl_meas(self, osrs_t=OVRS_x0, osrs_p=OVRS_x0, mode=MODE_SLEEP):
        register = 0xF4
        r_len = 0
        delay = 10

        # Make byte to send
        data = ((((osrs_t << 3) + osrs_p) << 2) + mode)

        command = ([register, data], r_len, delay)
        self.read_write(command)

    #########################################
    # write config register                 #
    #########################################
    def __config(self, t_sb, iir_filter, spi3w_en):
        register = 0xF5
        r_len = 0
        delay = 10

        # Make byte to send
        data = ((((t_sb << 3) + iir_filter) << 2) + spi3w_en)

        command = ([register, data], r_len, delay)
        self.read_write(command)

    ##############################################################
    # set_pressure_calibration                                   #
    # level = known level from sea                               #
    # pressure =  current local pressure normalized to sea level #
    ##############################################################
    def set_pressure_calibration(self, level, pressure):
        self.calibration_pressure = (pressure - level / 8) - self.pressure

    #########################################
    # get current altitude                  #
    # pressure = current sea level pressure #
    #########################################
    def get_altitude(self, pressure):
        return (pressure - self.calibrated_pressure) * 8

    ###########################################
    # read and write data to the bme280/(I2C) #
    ###########################################
    def read_write(self, command):
        if command[1] <= 0:
            # Write to I2C-bus
            # write_i2c_block_data(address, offset, [data_bytes])
            self.bus.write_i2c_block_data(self.address, command[0][0], command[0][1:])
            sleep(command[2]/1000)
            return 1
        else:
            # Read from I2C-Bus
            # read_i2c_block_data(address, register, number_of_data_bytes)
            return self.bus.read_i2c_block_data(self.address, command[0][0], command[1])

    #########################################
    # Twos complement calculation           #
    #########################################
    @staticmethod
    def __twos_complement(input_value, num_bits):
        """Calculates a two's complement integer from the given input value's bits."""

        mask = 2 ** (num_bits - 1)
        return -(input_value & mask) + (input_value & (mask-1))


import numpy as np
from scipy.spatial import cKDTree as KDTree
from gym import Wrapper

from envs.goal_demo_wrapper import goal_distance
from utils.helpers import extract_observable_state
from utils.load_confs import load_reward_params, load_parameters

params = load_parameters()

def logistic(x, tau):
    return 1 / (1 + np.exp(tau * -x))

def compute_sbs_phi(exp_kdtree, query_state, dist_scale):
    # k for k-nearest neighbors, p for p-norm
    dist, idx = exp_kdtree.query(query_state, k=1, p=2, n_jobs=1) # find expert state closest to query state
    similarity = np.exp(- 0.5 * (dist**2) * dist_scale)
    return similarity

class RewardWrapper(Wrapper):
    def __init__(self, env, env_id, expert_demo, reward_type, displace_t=1,
                 params_filename=None, reward_params=None, raw=False, time_feat=True):
        '''
        displace_t: if agent's state is s_t, use expert state s^e_{t+displace_t}
        reward_type: choices are ['huber', 'kimura', 'env']
        Can choose to pass in params_filename OR reward_params
        '''
        super(RewardWrapper, self).__init__(env)
        self.env = env
        self.env_id = env_id
        self.expert_demo = expert_demo
        assert len(self.expert_demo.shape) ==  2
        self.n_demo_timesteps = self.expert_demo.shape[0]

        self.displace_t = displace_t

        self.reward_type = reward_type
        self.time_feat = time_feat
        self.raw = raw
        if raw:
            obs_type = "raw"
        else:
            obs_type = "full"

        # if reward params specified either by passing in or through a params yaml, use those
        # otherwise use ones specified in the paramemters.yml
        self.reward_params = params['rew_shaping'][env_id.strip("-v2").lower()][obs_type]
        self.dist_std = self.reward_params["dist_std"] # no matter what, retrieve the dist_std from parameters.yml
        if params_filename:
            self.reward_params = load_reward_params(params_filename)
        elif reward_params:
            self.reward_params = reward_params

        if self.reward_type in ['huber', 'huber2']:
            self.imit_rew_coef = self.reward_params['imit_rew_coef']
            self.alpha = self.reward_params["alpha"]
            self.gamma = self.reward_params["gamma"]
        elif self.reward_type == 'potential':
            self.discount = params['sac'][env_id.strip("-v2").lower()]["gamma"]
            self.terminal_phi0 = params['pbrs']['terminal_phi0']
        elif self.reward_type == 'sbs_potential':
            assert not self.raw, "SBS should be run with full states."
            self.discount = params['sac'][env_id.strip("-v2").lower()]["gamma"]
            self.terminal_phi0 = params['pbrs']['terminal_phi0']
            self.dist_scale = self.reward_params["dist_scale"]
            self.tau = self.reward_params["tau"]
            self.exp_kdtree = KDTree(logistic(self.expert_demo, self.tau))

        self.current_t = 0

    def get_expert_demo(self, ob):
        '''At time t, append expert's state at time t+displace_t'''
        # current_t = 50, n_demo_timesteps = 50
        if (self.current_t + self.displace_t) > self.n_demo_timesteps -1 :
            # append expert state
            self.demo_ob = self.expert_demo[self.n_demo_timesteps - 1]
        else:
            self.demo_ob = self.expert_demo[self.current_t + self.displace_t]
        self.current_t += 1

    def reset(self):
        ob = self.env.reset()
        self.prev_ob = ob
        self.current_t = 0
        self.get_expert_demo(ob) # sets current_t = 1
        self.prev_demo_ob = self.demo_ob
        return ob

    def step(self, action):
        ob, reward_env, done, reward_info = self.env.step(action)
        self.get_expert_demo(ob)

        if self.reward_type in  ["huber", "huber2"]:
            if self.raw:
                raw_ob = extract_observable_state(ob, self.env_id)
                d = goal_distance(raw_ob, self.demo_ob, dim_scale=False if self.reward_type=="huber" else True)
            else:
                d = goal_distance(ob, self.demo_ob, dim_scale=False if self.reward_type=="huber" else True)

            sq_dist = np.square(d)
            if self.reward_type == "huber2":
                sq_dist = sq_dist / self.dist_std
            imit_reward = - (self.alpha * sq_dist) - ((1 - self.alpha) * np.sqrt(self.gamma + sq_dist))
            reward = ((1 - self.imit_rew_coef) * reward_env) + (self.imit_rew_coef * imit_reward)

        elif self.reward_type == "potential":
            demo_ob_t = self.prev_demo_ob
            demo_ob_tp1 = self.demo_ob

            if self.raw:
                ob_t = extract_observable_state(self.prev_ob, self.env_id)
                ob_tp1 = extract_observable_state(ob, self.env_id)
            else:
                ob_t, ob_tp1 = self.prev_ob, ob

            if done and self.terminal_phi0: # needed for policy invariance in finite horizon domains
                d_tp1 = 0
            else:
                d_tp1 = goal_distance(ob_tp1, demo_ob_tp1, dim_scale=True)
            d_t = goal_distance(ob_t, demo_ob_t, dim_scale=True)
            potential = - self.discount * d_tp1 + d_t
            reward = reward_env + potential

        elif self.reward_type == "sbs_potential":
            if self.time_feat:
                ob_t, ob_tp1 = logistic(self.prev_ob[:-1], self.tau), logistic(ob[:-1], self.tau) # slice to remove time feat
            else:
                ob_t, ob_tp1 = logistic(self.prev_ob, self.tau), logistic(ob, self.tau)

            if done and self.terminal_phi0: # needed for policy invariance in finite horizon domains
                phi_tp1 = 0
            else:
                phi_tp1 = compute_sbs_phi(self.exp_kdtree, query_state=ob_tp1, dist_scale=self.dist_scale)
            phi_t = compute_sbs_phi(self.exp_kdtree, query_state=ob_t, dist_scale=self.dist_scale)
            # no negative sign necessary on phi_t because phi_t is a similarity score
            potential = self.discount * phi_tp1 - phi_t
            reward = reward_env + potential

        elif self.reward_type == "env":
            reward = reward_env

        reward_info['reward_shaped'] = reward
        reward_info['reward_env'] = reward_env

        self.prev_ob = ob
        self.prev_demo_ob = self.demo_ob
        return ob, reward, done, reward_info


# -*- coding: utf-8 -*-
"""
Spyder Editor

This is a temporary script file.
"""

from pandas import read_csv
from os import listdir
#from sklearn import tree
#from sklearn import cluster
#from sklearn.tree import DecisionTreeRegressor
import matplotlib.pyplot as plt
import seaborn as sns
#import graphviz
import pandas as pd
#import random
#import xgboost as xgb
#from scipy.stats.mstats import zscore
#from xgboost import XGBRegressor
#from xgboost import plot_tree
import os

#os.environ["PATH"] += os.pathsep + 'D:/Program Files (x86)/graphviz-2.38/release/bin/'

#import math
#from sklearn.linear_model import LinearRegression
#import statsmodels.api as sm

composite_cycle = None
training_cycle = listdir('FCEV_csv')
randomindex = []
composite_cycle = None

for cyc in training_cycle:
    if '.csv' in cyc:
        print("process cycle name " + cyc)
        cycle_to_process = read_csv('FCEV_csv/' + cyc, sep = ',')
        cycle_to_process = cycle_to_process[cycle_to_process['Acceleration(mph/s)'].abs() < 10]
        cycle_to_process['fuel_rate(J)'] = cycle_to_process['fuelrate(kg/s)'] * 142000000.0 * 0.1
    #    cutpoint_cycle = cycle_to_process['tracpower(watt)'].quantile(0.9)
    #    cycle_to_process = cycle_to_process[cycle_to_process['tracpower(watt)'].abs() <= cutpoint_cycle]

        if cycle_to_process.size > 0:
            if composite_cycle is None:
                composite_cycle = cycle_to_process
            else:
                composite_cycle = pd.concat([composite_cycle, cycle_to_process])

quartile_1, quartile_3 = composite_cycle['tracpower(watt)'].quantile(0.25), composite_cycle['tracpower(watt)'].quantile(0.75)
iqr = quartile_3 - quartile_1
lower_bound = quartile_1 - (iqr * 1.5)
upper_bound = quartile_3 + (iqr * 1.5)

composite_cycle = composite_cycle[(composite_cycle['tracpower(watt)'] >= lower_bound) & (composite_cycle['tracpower(watt)'] <= upper_bound)]

#quartile_1, quartile_3 = composite_cycle['fuelrate(kg/s)'].quantile(0.25), composite_cycle['fuelrate(kg/s)'].quantile(0.75)
#iqr = quartile_3 - quartile_1
#lower_bound = quartile_1 - (iqr * 1.5)
#upper_bound = quartile_3 + (iqr * 1.5)
#composite_cycle = composite_cycle[(composite_cycle['fuelrate(kg/s)'] >= lower_bound) & (composite_cycle['fuelrate(kg/s)'] <= upper_bound)]

#composite_cycle = composite_cycle.loc[~composite_cycle['elec_energy(J)'].isnull()]
composite_cycle = composite_cycle.loc[composite_cycle['mot_command'] != 0]
composite_cycle = composite_cycle.loc[composite_cycle['fc_on'] != 0]

# <codecell>
plt.style.use('ggplot')
sample_cycle = composite_cycle.sample(n=30000)
sample_cycle = sample_cycle[['time(s)', 'road_type', 'SOC', 'Speed(mph)','Acceleration(mph/s)', 'road_grade(rad)', 'VSP', 'torque_demand(Nm)',
                             'fc_on', 'fc_temp_coeff', 'fc_command_pwr(watt)', 'ess_current', 'ess_volt', 'mot_torque(Nm)', 'mot_speed(rad/s)', 'fuelrate(kg/s)', 'elec_energy(J)']]
sample_cycle.loc[:, 'SOC_high'] = 1 * (sample_cycle.loc[:, 'SOC'] - 0.6 >= 0) + 0 * (sample_cycle.loc[:, 'SOC'] - 0.6 < 0)

to_plot = composite_cycle[['SOC', 'Speed(mph)', 'Acceleration(mph/s)','VSP', 'fc_on', 'fuel_rate(J)',  'elec_energy(J)']].sample(n=10000)
to_plot['elec_energy(J)'] *= 10
to_plot['fuel_rate(J)'] *= 10

to_plot.columns = ['SOC', 'Speed (mph)', 'Acceleration (mph/s)','VSP', 'FC on','fuel rate (Watt)', 'Elec. rate (Watt)']
sns.set(font_scale=1)
sns.pairplot(to_plot[['SOC', 'Speed (mph)', 'Acceleration (mph/s)','VSP', 'FC on','fuel rate (Watt)', 'Elec. rate (Watt)']],  kind='reg', plot_kws={'line_kws':{'color':'navy'}, 'scatter_kws': {'alpha': 0.1}})
plt.savefig('FCEV_variable_pair_plot.jpg', bbox_inches = 'tight', dpi=500)

#corr = sample_cycle.corr(method = 'spearman')
#fig, ax = plt.subplots(figsize=(10, 10))
#cax = ax.matshow(corr, cmap = 'coolwarm')
#cbar = fig.colorbar(cax)
#cbar.set_clim(-1.0, 1.0)
#plt.xticks(range(len(corr.columns)), corr.columns, rotation='vertical')
#plt.yticks(range(len(corr.columns)), corr.columns)
#plt.savefig('FCEV_Corr_matrix_noparam.jpg', bbox_inches = 'tight', dpi=500)
#plt.show()
#plt.ylim([-0.001, 0.002])
#g1= sns.jointplot(sample_cycle['VSP'], sample_cycle['fuelrate(kg/s)'], ylim=(0, 0.0016), joint_kws={"alpha":.05})
g1= plt.scatter(sample_cycle['VSP'], sample_cycle['elec_energy(J)']*10, c=sample_cycle['SOC'], cmap='jet_r', alpha=0.2)
cbar = plt.colorbar(g1)
plt.xlabel('VSP (watt/tonne)')
plt.ylabel("Electricity rate (Watt)")
plt.ylim([-40000, 30000])
cbar.ax.get_yaxis().labelpad = 15
cbar.set_label('SOC', rotation=270)
#plt.ylim([0, 0.016])
plt.savefig('FCEV_ELEC_VS_SOC_VSP.jpg', bbox_inches = 'tight', dpi = 200)
plt.show()
#g2 = sns.lmplot(x='VSP', y='fuelrate(kg/s)', col='SOC_high', data=sample_cycle, scatter_kws={"alpha":.05})
#g2.set(ylim=(0, 0.0016))
#sns.jointplot(sample_cycle['Speed(mph)'], sample_cycle['fuelrate(kg/s)'], ylim=(0, 0.0016), joint_kws={"alpha":.05})

# <codecell>
#sample_cycle_lowvsp = sample_cycle.loc[(sample_cycle['VSP'] <= 10000) & (sample_cycle['VSP'] > 0)  & (sample_cycle['SOC'] > 0.6)]
##sns.pairplot(sample_cycle_lowvsp[['SOC', 'Speed(mph)','Acceleration(mph/s)', 'road_grade(rad)', 'fc_temp_coeff', 'VSP', 'fuelrate(kg/s)']], kind='reg', plot_kws={'line_kws':{'color':'red'}, 'scatter_kws': {'alpha': 0.1}})
#lowvsp_features = sample_cycle_lowvsp.describe()
#total_features = composite_cycle.describe()
#
#plt.scatter(sample_cycle_lowvsp['VSP'], sample_cycle_lowvsp['fuelrate(kg/s)'], c=sample_cycle_lowvsp['elec_energy(J)'], cmap='RdBu',  alpha=0.3)
#plt.ylim([0, 0.0016])
#plt.show()

#sns.jointplot(sample_cycle['VSP'], sample_cycle['elec_energy(J)'], joint_kws={"alpha":.05})
#sns.jointplot(sample_cycle['SOC'], sample_cycle['elec_energy(J)'], joint_kws={"alpha":.05})
#sns.jointplot(sample_cycle['fc_temp_coeff'], sample_cycle['fuelrate(kg/s)'], ylim=(0, 0.0016), joint_kws={"alpha":.05})

# <codecell>

### linear regression and cross validation
from sklearn import linear_model
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score, cross_val_predict
from sklearn import metrics
import numpy as np
import statsmodels.api as sm
from sklearn.feature_selection import SelectFromModel
from sklearn import preprocessing

kf = KFold(n_splits=10)
#lm = linear_model.LinearRegression()

x = composite_cycle[['SOC', 'VSP', 'fuel_rate(J)']]
#x.loc[:, 'VSP_Square'] = x.loc[:, 'VSP'] ** 2
y = composite_cycle['fuel_rate(J)'] * 10
y2 = composite_cycle['elec_energy(J)'] * 10
#x_scaled = preprocessing.scale(x)
#y_scaled = preprocessing.scale(y)
##sample_y.loc[:, 'elec_energy(J)'] *= 10
#clf = linear_model.LassoCV()
#
## Set a minimum threshold of 0.25
#sfm = SelectFromModel(clf, threshold=1e-5)
#sfm.fit(x_scaled, y_scaled)
#x_transform = sfm.transform(x_scaled)
#n_features = sfm.transform(x_scaled).shape[1]

# Reset the threshold till the number of features equals two.
# Note that the attribute can be set directly instead of repeatedly
# fitting the metatransformer.
#while n_features > 3:
#    sfm.threshold += 0.1
#
#    n_features = x_transform.shape[1]

# <codecell>
est = sm.OLS(y, x)
est2 = est.fit()
print(est2.summary())

X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)

#OLS_accuracy = []
piecewise_accuracy = []
for train_index, test_index in kf.split(X_train):
    X_train_cv, X_test_cv = X_train.iloc[train_index], X_train.iloc[test_index]
    y_train_cv, y_test_cv = y_train.iloc[train_index], y_train.iloc[test_index]
    lm = linear_model.LinearRegression()
#    model = lm.fit(X_train, y_train)
#    predictions = lm.predict(X_test)
#    accuracy = metrics.r2_score(y_test, predictions)
#    OLS_accuracy.append(accuracy)
#    print("OLS Cross-Predicted Accuracy:", accuracy)

    X_train_pos = X_train_cv.loc[X_train_cv['VSP'] >= 0]
    X_train_neg = X_train_cv.loc[X_train_cv['VSP'] < 0]

    y_train_pos = y_train_cv.loc[X_train_cv['VSP'] >= 0]
    y_train_neg = y_train_cv.loc[X_train_cv['VSP'] < 0]

    results_pos = lm.fit(X_train_pos, y_train_pos)
#    a1 = results_pos.coef_
#    b1 = results_pos.intercept_
    X_test_pos = X_test_cv.loc[X_test_cv['VSP'] >= 0]
    y_test_pos = y_test_cv.loc[X_test_cv['VSP'] >= 0]
    y_pred_pos = results_pos.predict(X_test_pos)

#    results_neg = lm.fit(X_train_neg, y_train_neg)
#    a2 = results_neg.coef_
#    b2 = results_neg.intercept_
    X_test_neg = X_test_cv.loc[X_test_cv['VSP'] < 0]
    y_test_neg = y_test_cv.loc[X_test_cv['VSP'] < 0]
    y_pred_neg = y_test_neg
    y_pred_neg.loc[:] = y_train_neg.mean()
    y_pred_cv =  np.concatenate((y_pred_pos, y_pred_neg))
    y_test_cv = pd.concat([y_test_pos, y_test_neg])
    piecewise_mse = metrics.mean_squared_error(y_test_cv, y_pred_cv)
    piecewise_accuracy.append(piecewise_mse)
    print("piecewise Cross-Predicted Accuracy:", piecewise_mse)
#print(np.mean(OLS_accuracy))
print(np.mean(piecewise_accuracy))
#    break
X_train_pos = X_train.loc[X_train['VSP'] >= 0]
X_train_neg = X_train.loc[X_train['VSP'] < 0]

y_train_pos = y_train.loc[X_train['VSP'] >= 0]
y_train_neg = y_train.loc[X_train['VSP'] < 0]

results_pos = lm.fit(X_train_pos, y_train_pos)
a1 = results_pos.coef_
b1 = results_pos.intercept_
X_test_pos = X_test.loc[X_test['VSP'] >= 0]
y_test_pos = y_test.loc[X_test['VSP'] >= 0]
y_pred_pos = results_pos.predict(X_test_pos)

results_neg = lm.fit(X_train_neg, y_train_neg)
a2 = results_neg.coef_
b2 = results_neg.intercept_
X_test_neg = X_test.loc[X_test['VSP'] < 0]
y_test_neg = y_test.loc[X_test['VSP'] < 0]
y_pred_neg = y_test_neg
y_pred_neg.loc[:] = y_train_neg.mean()
y_pred =  np.concatenate((y_pred_pos, y_pred_neg))
y_test = pd.concat([y_test_pos, y_test_neg])
piecewise_r2 = metrics.r2_score(y_test, y_pred)
piecewise_mse = metrics.mean_squared_error(y_test, y_pred)
print(piecewise_r2)
print(np.sqrt(piecewise_mse))

# <codecell>
X_train, X_test, y2_train, y2_test = train_test_split(x, y2, test_size=0.2, random_state=42)

#OLS_accuracy = []
piecewise_accuracy = []
for train_index, test_index in kf.split(X_train):
    X_train_cv, X_test_cv = X_train.iloc[train_index], X_train.iloc[test_index]
    y2_train_cv, y2_test_cv = y2_train.iloc[train_index], y2_train.iloc[test_index]
    lm = linear_model.LinearRegression()

    X_train_pos = X_train_cv.loc[X_train_cv['VSP'] >= 0]
    X_train_neg = X_train_cv.loc[X_train_cv['VSP'] < 0]

    y2_train_pos = y2_train_cv.loc[X_train_cv['VSP'] >= 0]
    y2_train_neg = y2_train_cv.loc[X_train_cv['VSP'] < 0]

    results_pos = lm.fit(X_train_pos, y2_train_pos)
#    a1 = results_pos.coef_
#    b1 = results_pos.intercept_
    X_test_pos = X_test_cv.loc[X_test_cv['VSP'] >= 0]
    y2_test_pos = y2_test_cv.loc[X_test_cv['VSP'] >= 0]
    y2_pred_pos = results_pos.predict(X_test_pos)

#    results_neg = lm.fit(X_train_neg, y_train_neg)
#    a2 = results_neg.coef_
#    b2 = results_neg.intercept_
    X_test_neg = X_test_cv.loc[X_test_cv['VSP'] < 0]
    y2_test_neg = y2_test_cv.loc[X_test_cv['VSP'] < 0]
    result_neg = lm.fit(X_train_neg, y2_train_neg)
    y2_pred_neg = results_pos.predict(X_test_neg)
    y2_pred_cv =  np.concatenate((y2_pred_pos, y2_pred_neg))
    y2_test_cv = pd.concat([y2_test_pos, y2_test_neg])
    piecewise_mse = metrics.mean_squared_error(y2_test_cv, y2_pred_cv)
    piecewise_accuracy.append(piecewise_mse)
    print("piecewise Cross-Predicted Accuracy:", piecewise_mse)
#print(np.mean(OLS_accuracy))
print(np.mean(piecewise_accuracy))
#    break
X_train_pos = X_train.loc[X_train['VSP'] >= 0]
X_train_neg = X_train.loc[X_train['VSP'] < 0]

y2_train_pos = y2_train.loc[X_train['VSP'] >= 0]
y2_train_neg = y2_train.loc[X_train['VSP'] < 0]

results_pos = lm.fit(X_train_pos, y2_train_pos)
a1 = results_pos.coef_
b1 = results_pos.intercept_
X_test_pos = X_test.loc[X_test['VSP'] >= 0]
y2_test_pos = y2_test.loc[X_test['VSP'] >= 0]
y2_pred_pos = results_pos.predict(X_test_pos)

results_neg = lm.fit(X_train_neg, y2_train_neg)
a2 = results_neg.coef_
b2 = results_neg.intercept_
X_test_neg = X_test.loc[X_test['VSP'] < 0]
y2_test_neg = y2_test.loc[X_test['VSP'] < 0]
y2_pred_neg = results_neg.predict(X_test_neg)
y2_pred =  np.concatenate((y2_pred_pos, y2_pred_neg))
y2_test = pd.concat([y2_test_pos, y2_test_neg])
piecewise_r2 = metrics.r2_score(y2_test, y2_pred)
piecewise_mse = metrics.mean_squared_error(y2_test, y_pred)
print(piecewise_r2)
print(np.sqrt(piecewise_mse))

# <codecell>

comb_piecewise_r2 = metrics.r2_score(y_test+y2_test, y_pred+y2_pred)
comb_piecewise_mse = metrics.mean_squared_error(y_test+y2_test, y_pred+y2_pred)
print(comb_piecewise_r2)
print(np.sqrt(comb_piecewise_mse))


# -*- coding: utf-8 -*-
"""
Created on Mon Sep 10 14:02:56 2018

@author: Paulo Augusto
"""
import random
from scipy.stats import truncnorm
import numpy as np
import snkbrain

def truncated_normal(mean=0, sd=1, low=-10, upp=10):
    return truncnorm(
        (low - mean) / sd, (upp - mean) / sd, loc=mean, scale=sd)
#    X = truncated_normal(mean=0, sd=0.4, low=-0.5, upp=0.5)
#   matrix = X.rvs(m,n)
def feature_scaling(v):
    mean = np.mean(v)
    temp = [a-mean for a in v]
    return temp/np.std(v)

def randomMatrix(m,n,cap):
    mat=[]
    for i in range(0,m):
        mat.append([])
        for i in range(0,n):
            mat[-1].append((random.random()*2-1)*cap)
    return mat
def sigma(x):
    return 1/(1+np.exp(-x))
def dsigma(x):
    return np.exp(-x)/(pow(1+np.exp(-x),2))
def dtanh(x):
    return 1/pow(np.cosh(x),2)

class brain():

    def __init__(self,
                 neurons,
                 biases):

        self.brainMatrixes=self.gen_neural_network(neurons,
                                                   biases)#[[random.random() for i in range(0,nNeuron)] for i in range(0,nNeuron)]
        self.biases=biases
    def train(self,input_vector,target_vector,learning_rate):

        target=np.array(target_vector,ndmin=2).T
        inpt=np.array(input_vector,ndmin=2).T
        logging,output=self.run(input_vector)
        global tw
        tw=logging
        error=target-logging[-1]
        for i in range(0,len(logging)-1):
#            print i
            tmp=np.multiply(error , logging[-1-i])
            tmp=np.multiply( tmp, (1.0 - logging[-1-i] ))
            tmp=learning_rate*np.dot(tmp,(logging[-2-i]).T)
            tmp=tmp[0:len(tmp)-self.biases[-i-1]]
#            print tmp,error
            self.brainMatrixes[-i-1]+=tmp
            error=np.dot(self.brainMatrixes[-1-i].T,error[0:len(error)-self.biases[-1-i]])

    def gen_bias_matrix(self,vec):
        m=[]
        for i in range(0,len(vec)):
            m.append([])
            for j in range(0,vec[i]):
                m[i].append(random.random()*2-1)
        return m

    def gen_neural_network(self,
                           neurons,
                           biases):
        mat=[]
        rad = 1 / np.sqrt(neurons[0])
        X = truncated_normal(mean=0, sd=0.1, low=-rad, upp=rad)

        neuronVec=[]
        [ neuronVec.append(a+bias) for a,bias in zip(neurons,biases[0:len(biases)]) ]

        numberOfLayers=len(neurons)

        self.biasMatrix=self.gen_bias_matrix(neuronVec)
        self.biases=biases

        for i in range(0,numberOfLayers-1):
            m=X.rvs((neuronVec[i+1]-biases[i+1],neuronVec[i]))
#            m=randomMatrix(neuronVec[i+1]-biases[i+1],neuronVec[i],rad)
            mat.append(np.matrix(m))
        return mat

    def run(self,inpt):
        import numpy
        global sigma
        def relu(v):
            for i in range(0,len(v)):
                if v[i]<-1:
                    v[i]=-1
                if v[i]>1:
                    v[i]= 1
        logging=[]
        vecIn = np.matrix(inpt)
        saida=vecIn.T
#        print saida
        logging.append(saida)
        for i in range(0, len(self.brainMatrixes)):

            prox=[c for c in saida.A1]
            if self.biases[i]:
                prox.append(1)
                logging[i]=np.concatenate((logging[i],np.array([1],ndmin=2)))
            prox=np.matrix(prox)
            prox=prox.T
            saida=sigma(self.brainMatrixes[i]*prox)#+np.matrix(self.biasMatrix[i+1]).T)
            logging.append(saida)

#            saida=np.tanh(self.brainMatrixes[i]*prox)#+np.matrix(self.biasMatrix[i+1]).T)

        return logging,saida.A1


import pygame

def transform_image(image, scale: tuple, flip_x: bool, flip_y: bool):
    return pygame.transform.flip(
        pygame.transform.scale(
            image,
            scale
        ), flip_x, flip_y
    )

class Player(pygame.sprite.Sprite):
    def __init__(self, *groups):
        super().__init__(*groups)

        # image
        self.width, self.height = 100, 100

        self.image = pygame.image.load("data/sprites/player/pixil-frame-0.png")
        self.image = pygame.transform.scale(self.image, [self.width, self.height])

        # rect
        self.rect = pygame.Rect(690, 600/2 - 100, 60, 95)

        self.speed = 8

        # properties
        self.kills = 0
        self.bullets = 16
        self.hp = 100
        self.coins = 0

        # animation
        self.sprites = [
            pygame.image.load("data/sprites/player/pixil-frame-0.png").convert_alpha(),
            pygame.image.load("data/sprites/player/pixil-frame-1.png").convert_alpha(),
            pygame.image.load("data/sprites/player/pixil-frame-2.png").convert_alpha()
        ]

        self.in_move = 0
        self.index = 0
        self.frame_rate = 5

        # difficulty
        self.difficulty_index = 10

        # guns
        self.guns = {
            "classic pistol": "blé"
        }
        self.selected_gun = self.guns["classic pistol"]

    def movement_control(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_w] or keys[pygame.K_UP]:
            self.rect.y -= self.speed
            self.in_move = 1

        elif keys[pygame.K_s] or keys[pygame.K_DOWN]:
            self.rect.y += self.speed
            self.in_move = 1

        elif keys[pygame.K_a] or keys[pygame.K_LEFT]:
            self.rect.x -= self.speed
            self.in_move = 1

        elif keys[pygame.K_d] or keys[pygame.K_RIGHT]:
            self.rect.x += self.speed
            self.in_move = 1

        else:
            self.in_move = 0

    def animation_control(self):
        if self.in_move:
            self.index += 1

        else:
            self.index = 0
            self.image = transform_image(self.sprites[0], (100, 100), False, False)

        if self.index > self.frame_rate:
            self.image = transform_image(self.sprites[1], (100, 100), False, False)

            if self.index > self.frame_rate * 2:
                self.image = transform_image(self.sprites[2], (100, 100), False, False)

                if self.index > self.frame_rate * 3:
                    self.index = 0

    def update(self, *args):
        self.movement_control()
        self.animation_control()

        if self.rect.y > 500:
            self.rect.y = 500

        elif self.rect.y < -5:
            self.rect.y = -5

        if self.rect.x > 770:
            self.rect.x = 770

        elif self.rect.x < -10:
            self.rect.x = -10

        if self.hp <= 0:
            self.kill()
            self.hp = 0


from rest_framework import authentication
from rest_framework import exceptions
from settings.models import system_settings

from rest_framework import permissions

class APIKeyPermission(permissions.BasePermission):
    def has_permission(self, request, view):
        access_key = request.GET.get("access_key", None)
        if not access_key:
            raise exceptions.NotFound("Access key not provided.")
        try:
            system_settings.objects.get(access_key=access_key)
            return True
        except system_settings.DoesNotExist:
            raise exceptions.PermissionDenied("No found the access key or API is disabled")
        except ValueError:
            raise exceptions.ValidationError("Badly formed hexadecimal UUID string")

        return False


"""This file is for defining 3 functions,
isOdd, returns true if odd, isEven, returns,
true if even, and isOddorEven, which will
tell you if something is odd or even."""

def isOdd(number):
    if(isinstance(number, float)):
        return False
    elif(number%2) != 0:
        return True
    else: return False

def isEven(number):
    if(isinstance(number, float)):
        return False
    elif(number%2) == 0:
        return True
    else: return False

def isOddorEven(number):
    if(isinstance(number, float)):
        print("That's a decimal, guy.")
    elif(number%2) == 0:
        print("The " + str(number) + " is even.")
    else:
        print("The " + str(number) + " is odd.")

assert isOdd(42) == False
assert isOdd(9999) == True
assert isOdd(-10) == False
assert isOdd(-11) == True
assert isOdd(3.1415) == False
assert isEven(42) == True
assert isEven(9999) == False
assert isEven(-10) == True
assert isEven(-11) == False
assert isEven(3.1415) == False

isOddorEven(43)
isOddorEven(-43)
isOddorEven(42)
isOddorEven(-42)
isOddorEven(3.1415)
isOddorEven(-3.1415)


from turtle import Turtle

class Ball(Turtle):
    def __init__(self) :
        super().__init__()
        self.shape("circle")
        self.color("Pink")
        self.penup()
        self.x = 30
        self.y = 30
        self.speed(0)
        self.score_l = 0
        self.score_r = 0

    def ball_starter(self):
        if self.ycor() > 320 :
            self.y = self.y * -1
        if self.ycor() < -320:
            self.y = self.y * -1
        if  self.xcor() > 750:
            self.home()
            self.y = self.y * -1
            self.x = self.x * -1
            self.score_l = self.score_l +1
        if  self.xcor() < -750:
            self.home()
            self.score_r = self.score_r +1
            self.y = self.y * -1
            self.x = self.x * -1

        self.goto(self.xcor() +self.x,self.ycor() + self.y )


#Data structure for testing outside zapier and debugging:

input_data = {"first_name": "FirstName",
              "last_name": "LastName",
              "company_id": "00000000", # Company ID that they should be associated with
              "email_address": "example@contoso.com",
              "phone_number": "0000000000"}

#Copy below this to Zapier:

# Zapier contact import script
# used in conjunction with a second zap that brings across the company and main contact
# Copyright 2020 Dorks Delivered

import requests

# Customize this:
domain = "subdomain" # Replace with your syncromsp subdomain (https://mymsp.syncromsp.com.au) would enter mymsp
api_key = "syncro_api_key_here" #Replace with your API key from syncro

# Don't change:
url = "https://" + domain + ".syncromsp.com/api/v1/contacts"
fullname = input_data['first_name'] + " " + input_data['last_name']
phone_number = input_data.get("phone_number")

payload = {'customer_id': input_data['company_id'],
           'name': fullname,
           'email': input_data['email_address']}

if(phone_number != None):
    payload['phone_number'] = phone_number

params = {'api_key': api_key}

#print("URL: " + url + "\n")
#print("Request payload: \n")
#print(payload)
#print("Requesting...")

r = requests.post(url, json=payload, params={'api_key': api_key})

#print("Response: \n" + r.text + "\n")

if(r.status_code == 200):
    status = "pass"
else:
    status = "fail"


import argparse
import locale
import os
import pandas as pd
from tqdm import tqdm

from source.main.address_to_coords import AddressToCoords, get_data_dir

def get_args():
    parser = argparse.ArgumentParser(description='Transform supplier file to usable file by umap')
    parser.add_argument('filename', type=str, help='Name of the data file to read from the data directory')
    return parser.parse_args()

if __name__ == '__main__':
    args = get_args()

    # Read data
    data = pd.read_csv(os.path.join(get_data_dir(), args.filename), encoding='cp1252', sep=';')

    # Add coordinates
    addr2c = AddressToCoords()
    data['lat'] = None
    data['lon'] = None
    try:
        for index, row in tqdm(data.iterrows(), total=len(data)):
            address = row['Adresse 1'] if not pd.isnull(row['Adresse 1']) else row['RaisonSociale']
            if not pd.isnull(row['Adresse 2']):
                address += ' ' + row['Adresse 2']
            if pd.isnull(row['C.Postal']) or int(row['C.Postal']) == 0:
                continue
            address += ' ' + str(int(row['C.Postal'])) + ' ' + row['Ville']
            location = addr2c.get_coordinates(address, 'France' if pd.isnull(row['Pays']) else row['Pays'])
            data.loc[index, 'lat'] = location[0]
            data.loc[index, 'lon'] = location[1]
    finally:
        addr2c.save_database()

    # Format Date
    locale.setlocale(locale.LC_TIME, '')
    data['DatePartenariat'] = pd.to_datetime(data['Date partenariat'], format='%d/%m/%Y').dt.strftime('%B %Y')
    data['DatePartenariat'] = data['DatePartenariat'].apply(lambda d: '' if d == 'NaT' else d[0].upper() + d[1:])

    # Export some data
    missing_coordinates_nb = pd.isnull(data['lat']).sum()
    print(f'{missing_coordinates_nb} suppliers with no coordinates')
    data2 = data[~pd.isnull(data['lat'])]
    columns_to_keep = ['RaisonSociale', 'lat', 'lon', 'Site', 'Rayon', 'Description', 'Slogan', 'Photo', 'Produits',
                       'DatePartenariat']
    data2[columns_to_keep].to_csv(os.path.join(get_data_dir(), 'umap_filtered.csv'),
                                  encoding='utf8', index=None, sep=';')


# Tetris

# ejemplo de tetris https://gist.github.com/silvasur/565419/d9de6a84e7da000797ac681976442073045c74a4
# video tutorial https://www.youtube.com/watch?v=zfvxp7PgQ6c
# tetris con pygame https://recursospython.com/codigos-de-fuente/tetris-pygame/
# ![graficos](https://e3ab9255-a-62cb3a1a-s-sites.googlegroups.com/site/ddrkirby/coding-projects/keyblox/keyblox_screen_2.png?attachauth=ANoY7cqnEjNk2seGFyLINcmmdsHvspmcinJfiUlUGY9-xbn1yczq4LYae21z7EvQv7GiTO1yEtikxPcyWBL0j9__ZZXBVbOLXJvr38BfzaecvLiAEB2PPi2wPnlTF9oLFZDLVArK-1a8XczoxbN7LVVcIKXqh6pduTLULduvMLmNyfKG1MnHAevC-zeEiA48aE1_B1VeW0a_e_vjCg4zLtehc54iWqKvmXPxrLbCK21UH_kIr8NgLfgjh3PgKQwOOwDrZA3kYJPA&attredirects=0)

v = '0.6'

import time
import machine
import st7789py as st7789
import fhello

fhello.init()

back_color = st7789.color565(10,10,10)
def tile(x,y,l,r,g,b,ancho = 3):
    fhello.display.fill_rect(x, y ,l, l, st7789.color565(r,g,b))
    for i in range(1,ancho):
        fhello.display.hline(x + i, y + i, l - 2 * i, st7789.color565(r+50,g+50,b+50))
        fhello.display.vline(x + i, y + i, l - 2 * i, st7789.color565(r+100,g+100,b+100))
        fhello.display.vline(x + l -i, y + i, l - 2 * i, st7789.color565(r//3,g//3,b//3))
        fhello.display.hline(x + i, y + l - i , l - 2 * i, st7789.color565(r//2,g//2,b//2))

def test_fill(l = 20 ):
    for x in range(0,fhello.display.width//l):
        for y in range(0,fhello.display.height//l):
            tile(x*l,y*l,l,x*l,y*l,(x+y)*l//2)

def fall(x=fhello.display.width//2,y=0,l=20,r=0,g=0,b=150):
    frame()
    lButton=machine.Pin(0,machine.Pin.PULL_DOWN)
    rButton=machine.Pin(35,machine.Pin.PULL_DOWN)
    while y+l<fhello.display.height-1:
        fhello.display.fill_rect(x,y,l,l,back_color)
        y+=1
        if lButton.value() == 0:
            x -= 5
            if x < 1 :
                x = 1
        if rButton.value() == 0:
            x += 5
            if x  > fhello.display.width - l - 2:
                x = fhello.display.width - l - 2

        tile(x,y,l,r,g,b)
        time.sleep(0.1)

def frame():
    fhello.display.fill(back_color)
    fhello.display.vline(0,0,fhello.display.height-1,st7789.WHITE)
    fhello.display.vline(fhello.display.width-1,0,fhello.display.height-1,st7789.WHITE)
    fhello.display.hline(0,fhello.display.height-1,fhello.display.width-1,st7789.WHITE)


import numpy as np
import random
import local_learning

import logging
logger = logging.getLogger()

node_memory_size = 3
edge_memory_size = 5
# node_memory: signal_memory, signal_just_sent, error_just_sent
# edge_memory: signal (not multiplied by weight), has_signal, error, has_error, weight

# some help for thinking about error...
# error = (expected_signal - actual_signal) * gradient

NODE_SIGNAL_MEMORY_INDEX = 0
NODE_SIGNAL_JUST_SENT_INDEX = 1
NODE_ERROR_JUST_SENT_INDEX = 2

EDGE_SIGNAL_INDEX = 0
EDGE_HAS_SIGNAL_INDEX = 1
EDGE_ERROR_INDEX = 2
EDGE_HAS_ERROR_INDEX = 3
EDGE_WEIGHT_INDEX = 4

from local_learning.graph.feedforward import make_feedforward_adjacency_dict
from local_learning.network import Network

def backprop_initialize_rule(node_memory_size, edge_memory_size, edges):
    node_buffer = np.zeros(node_memory_size + edge_memory_size * edges)
    node_buffer[NODE_SIGNAL_MEMORY_INDEX] = 0
    node_buffer[NODE_SIGNAL_JUST_SENT_INDEX] = 0
    node_buffer[NODE_ERROR_JUST_SENT_INDEX] = 0
    node_buffer[node_memory_size + EDGE_SIGNAL_INDEX::edge_memory_size] = 0.0
    node_buffer[node_memory_size + EDGE_HAS_SIGNAL_INDEX::edge_memory_size] = 0
    node_buffer[node_memory_size + EDGE_ERROR_INDEX::edge_memory_size] = 0.0
    node_buffer[node_memory_size + EDGE_HAS_ERROR_INDEX::edge_memory_size] = 0
    node_buffer[node_memory_size + EDGE_WEIGHT_INDEX::edge_memory_size] = np.random.normal(size=edges) * 0.03
    return node_buffer

LEAKY_RELU_LEFT_SIDE_COEFFICIENT = 0.1
LEARNING_RATE = 0.03
# double this to make it equivalent to the same learning rule in regular backprop
# because of weird edge conflict write resolution rule

def backprop_step_rule(node_read_buffer, node_write_buffer, node_memory_size, edge_memory_size, edges):
    node_write_buffer[:] = node_read_buffer

    if node_read_buffer[NODE_SIGNAL_JUST_SENT_INDEX] == 0 and (node_read_buffer[node_memory_size + EDGE_HAS_SIGNAL_INDEX::edge_memory_size] != 0).any():
        # trigger on any incoming signals
        # part of forward pass
        node_signal = 0.0

        for neighbor in range(edges):
            edge_memory = node_read_buffer[node_memory_size + neighbor * edge_memory_size:node_memory_size + (neighbor + 1) * edge_memory_size]
            if edge_memory[EDGE_HAS_SIGNAL_INDEX] != 0:
                # this edge has a signal
                node_signal += edge_memory[EDGE_SIGNAL_INDEX] * edge_memory[EDGE_WEIGHT_INDEX]
            else:
                # this edge does not have a signal
                pass

        # leaky ReLU
        if node_signal < 0.0:
            node_signal = LEAKY_RELU_LEFT_SIDE_COEFFICIENT * node_signal

        for neighbor in range(edges):
            edge_memory_start_index = node_memory_size + neighbor * edge_memory_size
            edge_memory_end_index = edge_memory_start_index + edge_memory_size
            if node_read_buffer[edge_memory_start_index + EDGE_HAS_SIGNAL_INDEX] != 0:
                # this edge has a signal
                node_write_buffer[edge_memory_start_index + EDGE_SIGNAL_INDEX] = 0
                node_write_buffer[edge_memory_start_index + EDGE_HAS_SIGNAL_INDEX] = 0
            else:
                # this edge has a signal
                node_write_buffer[edge_memory_start_index + EDGE_SIGNAL_INDEX] = node_signal * 2
                # node_signal*2 is a weird requirement due to undirected graph having edge write conflicts
                node_write_buffer[edge_memory_start_index + EDGE_HAS_SIGNAL_INDEX] = 2

        node_write_buffer[NODE_SIGNAL_MEMORY_INDEX] = node_signal
        node_write_buffer[NODE_SIGNAL_JUST_SENT_INDEX] = 1
        return

    if node_read_buffer[NODE_SIGNAL_JUST_SENT_INDEX] != 0:
        # trigger if we sent a signal last step
        # part of forward pass

        # not sending a signal this step
        node_write_buffer[NODE_SIGNAL_JUST_SENT_INDEX] = 0
        # if we sent a signal last step, get rid of all signals and has_signals which touch us
        node_write_buffer[node_memory_size + EDGE_SIGNAL_INDEX::edge_memory_size] = 0
        node_write_buffer[node_memory_size + EDGE_HAS_SIGNAL_INDEX::edge_memory_size] = 0
        return

    if node_read_buffer[NODE_ERROR_JUST_SENT_INDEX] == 0 and (node_read_buffer[node_memory_size + EDGE_HAS_ERROR_INDEX::edge_memory_size] != 0).any():
        # trigger on any incoming errors
        # part of backward pass

        actual_signal = node_read_buffer[NODE_SIGNAL_MEMORY_INDEX]
        if actual_signal < 0.0:
            derivative = LEAKY_RELU_LEFT_SIDE_COEFFICIENT
        else:
            derivative = 1.0

        total_incoming_error = 0.0
        for neighbor in range(edges):
            edge_memory_start_index = node_memory_size + neighbor * edge_memory_size
            if node_read_buffer[edge_memory_start_index + EDGE_HAS_ERROR_INDEX] != 0:
                # has an error on it
                total_incoming_error += node_read_buffer[edge_memory_start_index + EDGE_ERROR_INDEX]
            else:
                pass

        error = total_incoming_error * derivative

        for neighbor in range(edges):
            edge_memory_start_index = node_memory_size + neighbor * edge_memory_size
            if node_read_buffer[edge_memory_start_index + EDGE_HAS_ERROR_INDEX] != 0:
                # has an error on it; adjust the weight and get rid of the error signal
                node_write_buffer[edge_memory_start_index + EDGE_HAS_ERROR_INDEX] = 0
                node_write_buffer[edge_memory_start_index + EDGE_ERROR_INDEX] = 0
                node_write_buffer[edge_memory_start_index + EDGE_WEIGHT_INDEX] = node_read_buffer[edge_memory_start_index + EDGE_WEIGHT_INDEX] + error * LEARNING_RATE
            else:
                # does not have an error on it; error should be propagated backwards to this edge
                node_write_buffer[edge_memory_start_index + EDGE_HAS_ERROR_INDEX] = 2
                node_write_buffer[edge_memory_start_index + EDGE_ERROR_INDEX] = error

        node_write_buffer[NODE_ERROR_JUST_SENT_INDEX] = 1

    if node_read_buffer[NODE_ERROR_JUST_SENT_INDEX] != 0:
        # trigger if we did a weight update and propagated error backwards last step
        # part of backward pass

        # not sending any error this step
        node_write_buffer[NODE_ERROR_JUST_SENT_INDEX] = 0
        # if we sent any error last step, get rid of all errors touching us and has_errors touching us this step
        node_write_buffer[node_memory_size + EDGE_ERROR_INDEX::edge_memory_size] = 0
        node_write_buffer[node_memory_size + EDGE_HAS_ERROR_INDEX::edge_memory_size] = 0

class BackpropModel:
    def __init__(self, input_size=2, hidden_size=1, output_size=1, layers=1):
        if layers != 1:
            raise Exception('BackpropModel does not support layers != 1 just yet')
        self.network = Network(in_adjacency_dict=make_feedforward_adjacency_dict(input_size=input_size, hidden_size=hidden_size, output_size=output_size, secondary_output_layer=True, layers=layers), node_memory_size=node_memory_size, edge_memory_size=edge_memory_size, step_rule=backprop_step_rule)
        self.network.initialize(initialize_rule=backprop_initialize_rule)
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.output_size = output_size
        self.layers = layers

        self.secondary_output_nodes = list(range(len(self.network.nodes) - self.output_size, len(self.network.nodes)))

    def train(self, dataset, iterations=100):
        for iteration in range(iterations):
            input_data, output_data = random.choice(dataset)
            self.async_train(input_data, output_data)

    def clean(self):
        # clear everything except weights
        for node_buffer in self.network.read_buffer:
            node_memory = node_buffer[:node_memory_size]
            edge_memory = node_buffer[node_memory_size:]
            node_memory[NODE_SIGNAL_MEMORY_INDEX] = 0
            node_memory[NODE_SIGNAL_JUST_SENT_INDEX] = 0
            node_memory[NODE_ERROR_JUST_SENT_INDEX] = 0
            edge_memory[EDGE_SIGNAL_INDEX] = 0.0
            edge_memory[EDGE_HAS_SIGNAL_INDEX] = 0
            edge_memory[EDGE_ERROR_INDEX] = 0.0
            edge_memory[EDGE_HAS_ERROR_INDEX] = 0
            # don't reset weights

    def forward(self, input_data, max_steps=1000):
        # set input data
        for node, signal in enumerate(input_data):
            self.network.read_buffer[node][NODE_SIGNAL_MEMORY_INDEX] = signal
            self.network.read_buffer[node][NODE_SIGNAL_JUST_SENT_INDEX] = 1
            for neighbor in self.network.adjacency_dict[node]:
                edge_memory = self.network.get_edge_memory((node, neighbor))[:]
                edge_memory[EDGE_SIGNAL_INDEX] = signal
                edge_memory[EDGE_HAS_SIGNAL_INDEX] = 1
                self.network.set_edge_memory(edge=(node, neighbor), edge_memory=edge_memory)

        # propagate input data forward
        # note that right now multiple input signals coming in out of sync would make the network send output data along input edges
        # so don't try doing anything fancy to handle out of sync signals, since there's no way around this unfortunate fact

        # wait for all secondary_output_nodes to have NODE_SIGNAL_JUST_SENT_INDEX

        steps = 0
        info = {}

        while True:
            #self.network.debug_log_buffers('step={}'.format(steps))
            self.network.step()
            ready = all(self.network.get_node_memory(output_node)[NODE_SIGNAL_JUST_SENT_INDEX] == 1 for output_node in self.secondary_output_nodes)
            if ready:
                break
            steps += 1
            if steps > max_steps:
                logger.error('ERROR: ran > {} steps in a forward pass without getting an output; probably a bug!'.format(max_steps))
                raise Exception('ran > {} steps in forward pass without getting an output'.format(max_steps))

        output = []
        info['steps'] = steps

        for output_node in self.secondary_output_nodes:
            output.append(self.network.read_buffer[output_node][NODE_SIGNAL_MEMORY_INDEX])

        return output, info

    def backward(self, output_data, max_steps=1000):
        # apply error to the secondary output edges
        # then run step until there's no error left
        for expected_signal, output_node in zip(output_data, self.secondary_output_nodes):
            actual_signal = self.network.read_buffer[output_node][NODE_SIGNAL_MEMORY_INDEX]

            if actual_signal < 0.0:
                derivative = LEAKY_RELU_LEFT_SIDE_COEFFICIENT
            else:
                derivative = 1.0

            error = (expected_signal - actual_signal) * derivative

            for neighbor in self.network.adjacency_dict[output_node]:
                edge_memory = self.network.get_edge_memory((output_node, neighbor))
                edge_memory[EDGE_HAS_ERROR_INDEX] = 1
                edge_memory[EDGE_ERROR_INDEX] = error
                self.network.set_edge_memory((output_node, neighbor), edge_memory)

            self.network.read_buffer[output_node][NODE_ERROR_JUST_SENT_INDEX] = 1

        steps = 0
        info = {}

        while True:
            self.network.step()
            ready = all(node_buffer[NODE_ERROR_JUST_SENT_INDEX] == 0 for node_buffer in self.network.read_buffer)
            if ready:
                break
            steps += 1
            if steps > max_steps:
                logger.error('ERROR: ran > {} steps in a backward pass without getting an output; probably a bug!'.format(max_steps))
                raise Exception('ran > {} steps in backward pass without getting an output'.format(max_steps))

        info['steps'] = steps

        return None, info

    def set_weights(self, weights):
        # weights = {(node_a, node_b): weight, ...}
        self.clean()
        for edge, weight in weights.items():
            edge_memory = np.zeros(edge_memory_size)
            edge_memory[EDGE_WEIGHT_INDEX] = weight
            self.network.set_edge_memory(edge, edge_memory)

    def get_weights(self):
        weights = {}
        for node in self.network.adjacency_dict:
            for neighbor in self.network.adjacency_dict[node]:
                edge = (node, neighbor)
                weight = self.network.get_edge_memory(edge)[EDGE_WEIGHT_INDEX]
                weights[edge] = weight
        return weights

    def async_train(self, input_data, output_data):
        self.clean()
        self.forward(input_data)
        self.backward(output_data)


#2. Create an example for three types of inheritance in one program by using Person as main class?

class Person:
    def set(self,age,gender):
        self.age=age
        self.gender=gender
        print("age:",self.age)
        print("gender:",self.gender)
class Father(Person):
    def set1(self,name,company,job,relation):
        self.name=name
        self.company=company
        self.job=job
        self.relation=relation
        print("name:",self.name)
        print("company:",self.company)
        print("job:", self.job)
        print("relation:",self.relation)
class Mother(Person):
    def set2(self,name1,company1,job1,relation1):
        self.name1=name1
        self.company1=company1
        self.job1=job1
        self.relation1=relation1
        print("name:", self.name1)
        print("company:", self.company1)
        print("job:", self.job1)
        print("relation:", self.relation1)
class Child(Father,Mother):
    def set3(self,name2,school,std,mark):
        self.name2=name2
        self.school=school
        self.std=std
        self.mark=mark
        print("name:",self.name2)
        print("school:",self.school)
        print("standard:",self.std)
        print("mark:",self.mark)
ch=Child()
ch.set3("Aravind","S.N.D.PH.S.S",10,550)
ch.set1("Venu","Cochin Shipyard","Charge man","Father")
ch.set2("Thulasi","nil","Home maker","Mother") # multiple inheritance father & mother --> Child (considering above sentance)
ch.set(15,"Male") #multilevel inheritance Person-->Father-->Child
fa=Father()
fa.set1("Anand","Dry Dock","Safety officer","Father")
fa.set(29,"Male") #single inheritance Person-->Father


# -*- coding: utf-8 -*-
"""
Created on Thu Nov 9 20:05:23 2017

@author: Joeri de Bruijckere
"""

import numpy as np
from scipy import ndimage, signal
from scipy.interpolate import interp1d, interp2d

def derivative(data, method, times_x, times_y):
    times_x, times_y = int(times_x), int(times_y)
    if len(data) == 3:
        for _ in range(times_x):
            data[-1] = np.gradient(data[-1], data[0][:,0], axis=0)
        for _ in range(times_y):
            data[-1] = np.gradient(data[-1], data[1][0,:], axis=1)
    elif len(data) == 2:
        for _ in range(times_y):
            data[-1] = np.gradient(data[-1], data[0])
    return data

def smooth(data, method, width_x, width_y):
    filters = {'Gauss': ndimage.gaussian_filter,
               'Median': ndimage.median_filter}
    filters1d = {'Gauss': ndimage.gaussian_filter1d}

    if method == 'Gauss':
        width_x, width_y = float(width_x), float(width_y)
    elif method == 'Median':
        width_x, width_y = int(np.ceil(float(width_x)))+1, int(np.ceil(float(width_y)))+1
    if len(data) == 3:
        if width_x:
            if width_y:
                data[-1] = filters[method](data[-1], [width_x, width_y])
            else:
                data[-1] = filters1d[method](data[-1], width_x, axis=0)
        else:
            if width_y:
                data[-1] = filters1d[method](data[-1], width_y, axis=1)
    elif len(data) == 2:
        if width_y:
            data[-1] = filters1d[method](data[-1], width_y)
    return data

def sav_gol(data, method, window_length, polyorder):
    polyorder = int(polyorder)
    window_length = int(window_length)
    if window_length < polyorder:
        window_length = polyorder + 1
    if window_length % 2 == 0:
        window_length += 1
    if 'Y' in method:
        axis = 1
    elif 'X' in method:
        axis = 0
    deriv = method.count('d')
    if len(data) == 3:
        data[-1] = signal.savgol_filter(data[-1], window_length, polyorder,
                                        deriv=deriv, axis=axis)
        for _ in range(deriv):
            data[-1] /= np.gradient(data[axis], axis=axis)
    elif len(data) == 2:
        data[-1] = signal.savgol_filter(data[-1], window_length, polyorder,
                                        deriv=deriv)
        for _ in range(deriv):
            data[-1] /= np.gradient(data[0])
    return data

def crop_x(data, method, left, right):
    if method != 'Lim':
        min_data = np.min(data[0])
        max_data = np.max(data[0])
        left, right = float(left), float(right)
        if (left < right and max_data > left and min_data < right):
            if method == 'Abs':
                mask = ((data[0] < left) | (data[0] > right))
            elif method == 'Rel':
                mask = (((data[0] >= min_data) & (data[0] <= min_data + abs(left))) |
                        ((data[0] <= max_data) & (data[0] >= max_data - abs(right))))
            if len(data) == 3:
                for i in [1,2,0]:
                    data[i] = np.ma.compress_rowcols(np.ma.masked_array(data[i], mask=mask), axis=0)
            elif len(data) == 2:
                for i in [1,0]:
                    data[i] = np.ma.masked_array(data[i], mask=mask)
    return data

def crop_y(data, method, bottom, top):
    if len(data) == 3 and method != 'Lim':
        min_data = np.min(data[1])
        max_data = np.max(data[1])
        bottom, top = float(bottom), float(top)
        if (bottom < top and max_data > bottom and min_data < top):
            for i in [0,2,1]:
                if method == 'Abs':
                    mask = ((data[1] < bottom) | (data[1] > top))
                elif method == 'Rel':
                    mask = (((data[1] >= min_data) & (data[1] <= min_data + abs(bottom))) |
                            ((data[1] <= max_data) & (data[1] >= max_data - abs(top))))
                data[i] = np.ma.compress_rowcols(
                        np.ma.masked_array(data[i], mask=mask), axis=1)
    return data

def roll_x(data, method, position, amount):
    if len(data) == 3:
        amount = int(amount)
        position = int(position)
        data[2][:,position:] = np.roll(data[2][:,position:], shift=amount, axis=0)
    return data

def roll_y(data, method, position, amount):
    if len(data) == 3:
        amount = int(amount)
        position = int(position)
        data[2][position:,:] = np.roll(data[2][position:,:], shift=amount, axis=1)
    return data

def cut_x(data, method, left, width):
    if len(data) == 3:
        left, width = int(left), int(width)
        part1 = data[-1][:left,:]
        part2 = data[-1][left:left+width,:]
        part3 = data[-1][left+width:,:]
        data[-1] = np.vstack((part1,part3,part2))
    return data

def cut_y(data, method, bottom, width):
    if len(data) == 3:
        bottom, width = int(bottom), int(width)
        part1 = data[-1][:,:bottom]
        part2 = data[-1][:,bottom:bottom+width]
        part3 = data[-1][:,bottom+width:]
        data[-1] = np.hstack((part1,part3,part2))
    return data

def swap_xy(data, method, setting1, setting2):
    data[0], data[1] = data[1], data[0]
    return data

def flip(data, method, setting1, setting2):
    if method == 'U-D':
        data[-1] = np.fliplr(data[-1])
    elif method == 'L-R':
        data[-1] = np.flipud(data[-1])
    return data

def normalize(data, method, point_x, point_y):
    if method == 'Max':
        norm_value = np.max(data[-1])
    elif method == 'Min':
        norm_value = np.min(data[-1])
    elif method == 'Point' and len(data) == 3:
        x_index = np.argmin(np.abs(data[0][:,0] - float(point_x)))
        y_index = np.argmin(np.abs(data[1][0,:] - float(point_y)))
        norm_value = data[-1][x_index,y_index]
    elif method == 'Point' and len(data) == 2:
        x_index = np.argmin(np.abs(data[0] - float(point_x)))
        norm_value = data[-1][x_index]
    data[-1] = data[-1] / norm_value
    return data

def offset(data, method, setting1, setting2):
    if method == 'X':
        data[0] += float(setting1)
    if method == 'Y':
        data[1] += float(setting1)
    if method == 'Z' and len(data) == 3:
        data[2] += float(setting1)
    return data

def absolute(data, method, setting1, setting2):
    data[-1] = np.absolute(data[-1])
    return data

def multiply(data, method, setting1, setting2):
    if setting1 == 'e^2/h':
        value = 0.025974
    else:
        value = float(setting1)

    axis = {'X': 0, 'Y': 1, 'Z': 2}
    if len(data) == 3:
        data[axis[method]] *= value
    elif len(data) == 2 and axis[method] < 2:
        data[axis[method]] *= value
    return data

def logarithm(data, method, setting1, setting2):
    if method == 'Mask':
        data[-1] = np.ma.log10(data[-1])
    elif method == 'Shift':
        min_value = np.amin(data[-1])
        if min_value <= 0.0:
            data[-1] = np.ma.log10(data[-1]-min_value)
        else:
            data[-1] = np.ma.log10(data[-1])
    elif method == 'Abs':
        data[-1] = np.ma.log10(np.abs(data[-1]))
    return data

def root(data, method, setting1, setting2):
    root = float(setting1)
    if root > 0:
        data[-1] = np.abs(data[-1])**(1/float(setting1))
    return data

def interpolate(data, method, n_x, n_y):
    if len(data) == 3:
        x, y = data[0][:,0], data[1][0,:]
        f_z = interp2d(y, x, data[2], kind=method)
        n_x, n_y = int(n_x), int(n_y)
        min_x, max_x = np.amin(data[0]), np.amax(data[0])
        min_y, max_y = np.amin(data[1]), np.amax(data[1])
        yp, xp = np.linspace(min_y, max_y, n_y), np.linspace(min_x, max_x, n_x)
        data[1], data[0] = np.meshgrid(yp, xp)
        data[2] = f_z(yp, xp)
    elif len(data) == 2:
        f = interp1d(data[0], data[1], kind=method)
        n_x = int(n_x)
        min_x, max_x = np.amin(data[0]), np.amax(data[0])
        data[0] = np.linspace(min_x, max_x, n_x)
        data[1] = f(data[0])
    return data

def add_slope(data, method, a_x, a_y):
    if len(data) == 3:
        a_x, a_y = float(a_x), float(a_y)
        data[-1] += a_x*data[0] + a_y*data[1]
    elif len(data) == 2:
        a_y = float(a_y)
        data[-1] += a_y*data[0]
    return data

def subtract_trace(data, method, index, setting2):
    if len(data) == 3:
        index = int(float(index))
        if method == 'Hor':
            data[-1] -= np.tile(data[-1][:,index], (len(data[-1][0,:]),1)).T
        elif method == 'Ver':
            data[-1] -= np.tile(data[-1][index,:], (len(data[-1][:,0]),1))
    return data

def divide(data, method, setting1, setting2):
    axis = {'X': 0, 'Y': 1, 'Z': 2}
    if len(data) == 3:
        data[axis[method]] /= float(setting1)
    elif len(data) == 2 and axis[method] < 2:
        data[axis[method]] /= float(setting1)
    return data

def invert(data, method, setting1, setting2):
    axis = {'X': 0, 'Y': 1, 'Z': -1}
    data[axis[method]] = 1./data[axis[method]]
    return data


'''
@Author       : Scallions
@Date         : 2020-03-20 11:38:52
@LastEditors  : Scallions
@LastEditTime : 2020-03-20 11:43:07
@FilePath     : /algorithm-ex/tests/test_tree.py
@Description  :
'''

import sys
import pytest
sys.path.append("./structure/tree")

import tree

@pytest.fixture()
def get_a_btree():
    return tree.BinaryTree(0)

def test_init():
    root = tree.BinaryTree(6)
    assert root.data == 6
    assert root.left == None
    assert root.right == None

def test_set_child():
    root = get_a_btree
    root.left = tree.BinaryTree(5)
    assert root.left.data == 5


import sys

class Stack():

    def __init__(self):
        self.stk = []

    def pop(self):
        """raises IndexError if you pop when it's empty"""
        return self.stk.pop()

    def push(self, elt):
        self.stk.append(elt)

    def is_empty(self):
        return len(self.stk) == 0

    def peek(self):
        if not self.stk.is_empty():
            return self.stk[-1]

class Queue():

    def __init__(self):
        self.q = Stack()  # the primary queue
        self.b = Stack()  # the reverse, opposite q (a joke: q vs b)
        self.front = None

    def is_empty(self):
        return self.q.is_empty()

    def peek(self):
        if self.q.is_empty():
            return None
        else:
            return self.front

    def enqueue(self, elt):
        self.front = elt
        self.q.push(elt)

    def dequeue(self):
        """raises IndexError if you dequeue from an empty queue"""
        while not self.q.is_empty() > 0:
            elt = self.q.pop()
            self.b.push(elt)
        val = self.b.pop()
        elt = None
        while not self.b.is_empty() > 0:
            elt = self.b.pop()
            self.q.push(elt)
        self.front = elt
        return val

def isValid(row, col, total_row, total_col):
    return (row >= 0) and (row < num_row) and (col >= 0) and (col < num_col)

def BFS(maze, src, dst, visited, dr, dc, num_row, num_col, pi):
    visited[src[0]][src[1]] = True
    pi[src[0]][src[1]] = 0

    q = Queue()
    q.enqueue((src, 0))
    while(not q.is_empty()):
        curr = q.dequeue()
        print(curr)
        pt = curr[0]
        if (pt==dst):
            return (curr, pi)

        for i in range(4):
            row = pt[0] + dr[i]
            col = pt[1] + dc[i]
            if(isValid(row, col, num_row, num_col) and not visited[row][col] and maze[row][col]!='0'):
                visited[row][col] = True
                q.enqueue(((row, col), curr[1]+1))
                pi[row][col] = curr[0]
    return -1

def trace(pi, pt):
    route = []
    while(pi[pt[0]][pt[1]] != 0):
        prev = pi[pt[0]][pt[1]]
        if (prev[0] < pt[0] and prev[1] == pt[1]):
            route.append('3')
        elif(prev[0] > pt[0] and prev[1] == pt[1]):
            route.append('1')
        elif(prev[0] == pt[0] and prev[1] < pt[1]):
            route.append('2')
        elif(prev[0] == pt[0] and prev[1] > pt[1]):
            route.append('4')
        pt = prev
    return route

if __name__ == '__main__':
    in_file = sys.argv[1]
    out_file = sys.argv[2]
    maze, visited, pi = [], [], []
    src, dst = -1, -1
    row_cnt = 0

    with open(in_file ,'r') as f:
        for line in f:
            row = line.strip().split()
            if '2' in row:
                src = (row_cnt, row.index('2'))
            if '3' in row:
                dst = (row_cnt, row.index('3'))
            v_row = [False for _ in range(len(row))]
            pi_row = [-1 for _ in range(len(row))]
            maze.append(row)
            visited.append(v_row)
            pi.append(pi_row)
            row_cnt+=1

    num_row = len(maze)
    num_col = len(maze[0])
    dr = [-1, 0, 0, 1]
    dc = [0, -1, 1, 0]

    result = BFS(maze, src, dst, visited, dr, dc, num_row, num_col, pi)
    if result!=-1:
        (curr, pi) = result
        rev_route = trace(pi, curr[0])
        route = rev_route[::-1]

        with open(out_file, 'w') as f:
            f.write(str(' '.join(route)))
            f.write('\n')
            f.write(str(curr[1]))
    else:
        with open(out_file, 'w') as f:
            f.write(str(-1))


from django.core.management.base import BaseCommand

from app.models import Player, PlayerRole, Spectator, Moderator, most_recent_game

class Command(BaseCommand):
    help = 'Prints a list of all zombie emails'

    def handle(self, *args, **options):
        game = most_recent_game()
        spectators = Spectator.objects.filter(game=game)
        moderators = Moderator.objects.filter(game=game)
        zombies = Player.objects.filter(game=game, active=True, role=PlayerRole.ZOMBIE)

        spectator_emails = [s.user.email for s in spectators]
        moderator_emails = [m.user.email for m in moderators]
        zombie_emails = [z.user.email for z in zombies] + spectator_emails + moderator_emails
        print(", ".join(zombie_emails))


import chessWrapper as cw
from tkinter import *

class Chessboard(Canvas):

    images = []
    pieces = ["wp","wN","wB","wR","wQ","wK","bp","bN","bB","bR","bQ","bK"]
    chessboard = cw.chessGame()
    fx = 0
    fy = 0
    tx = 0
    ty = 0
    mp = ""
    cp = ""

    def __init__(self, master=None, cnf={}, **kw):
        Canvas.__init__(self, master=None, cnf={}, **kw)
        #load images
        for x in range(12):
            self.images.append(PhotoImage(file=f"./assets/{self.pieces[x]}.png", name=self.pieces[x]))
        self.drawBoard()
        self.drawPieces()

    def drawBoard(self):
        for x in range(8):
            for y in range(8):
                if ((x + y) % 2) == 0:
                    self.create_rectangle(x*100, y*100, x*100 + 100, y*100 + 100, fill="white",outline="white", tags="board")

    def drawPieces(self):
        for x in range(8):
            for y in range(8):
                self.delete(f"x{x}y{y}")
                if self.chessboard.board[x][y] != "--":
                    self.create_image(x*100 + 50, y*100 + 50, image=self.images[self.getImageIndex(self.chessboard.getPiece(x,y))], tags=f"x{x}y{y}")

    def getImageIndex(self, pieceName:str):
        for x in range(12):
            if pieceName == self.images[x].name:
                return x
        return NONE

    def mouseDown(self,e):
        self.fx = int(e.x/100)
        self.fy = int(e.y/100)
        self.mp = self.chessboard.getPiece(int(e.x/100),int(e.y/100))

        if self.mp != "--":
            self.delete(f"x{int(e.x/100)}y{int(e.y/100)}")
            self.create_image(e.x,e.y, image=self.images[self.getImageIndex(self.mp)], tags = "moving")

    def move(self, e):
        if self.mp != "--":
            self.delete("moving")
            self.create_image(e.x,e.y, image=self.images[self.getImageIndex(self.mp)], tags = "moving")

    def mouseUp(self, e):
        self.delete("moving")

        self.tx = int(e.x/100)
        self.ty = int(e.y/100)
        self.cp = self.chessboard.getPiece(int(e.x/100),int(e.y/100))

        self.chessboard.tryTurn(fx=self.fx, fy=self.fy, tx=self.tx, ty=self.ty, mp=self.mp, cp=self.cp)
        self.chessboard.updateBoard()
        self.drawPieces()

root = Tk()
root.title("Ultra Deluxe Chess")

app_width = 800
app_height = 800

root.geometry(f"{app_width}x{app_height}")

canvas = Chessboard(root, width=app_width,height=app_height, bg="green")

canvas.bind("<B1-Motion>",canvas.move)

canvas.bind("<Button-1>",canvas.mouseDown)

canvas.bind("<ButtonRelease-1>",canvas.mouseUp)

canvas.pack()

root.mainloop()


# https://leetcode.com/problems/maximum-units-on-a-truck/
class Solution:
    def maximumUnits(self, boxTypes: List[List[int]], truckSize: int) -> int:
        # sort box types by units highest to lowest
        boxTypes = sorted(boxTypes, key=lambda x: (x[1]), reverse=True)
        res = 0
        while truckSize > 0 and len(boxTypes) > 0:
            bt = boxTypes[0]
            # quantity of this box type
            q = bt[0]
            # number of units of this box type
            u = bt[1]

            if q > 0 and truckSize > 0:
                # if the trucksize can absorb this quantity completely
                # then add u * q to result
                # subtract capacity of truck size by q
                # remove the first boxtype with highest units, so the next boxtype can be picked
                if q <= truckSize:
                    boxTypes.pop(0)
                    res += u * q
                    truckSize -=q
                else:
                    res += u * truckSize
                    return res

        return res


import sys
import os
import json

from .classmodule import MyClass
from .funcmodule import startDjangoProject
from .createreact import getcurrent
from .visuals import ascii_dact

def main():

    args = sys.argv[1:]

    if len(args) < 1:
        ascii_dact()
        print(

            """
            Congratulations! Dact is successfully installed in your system.
            To learn more about dact, go to https://ayushmankumar7.github.io/dact/.

            To get started with Dact, type dact newproject

            Hurray! Your first Django + React Project is ready to be worked on.

            """
        )

    elif len(args) == 1:
        startDjangoProject(args[0])

    elif len(args) ==2:
        startDjangoProject(args[0], args[1])

def watch_react():
    with open("dact_config.json") as f:
        data = json.load(f)
    frontend_app = data['Frontend_AppName']
    os.chdir(f"{frontend_app}/static")
    os.system("npm run dev")

def package_install():
    with open("dact_config.json") as f:
        data = json.load(f)
    frontend_app = data['Frontend_AppName']
    os.chdir(f"{frontend_app}/static")
    os.system("npm install")

def testing():
    print("Testing function was called")

if __name__ == '__main__':
    main()


import sys
sys.stdin = open('input.txt')

T = 10
for tc in range(1, T+1):
    N = int(input())
    lst = list(map(int, input().split()))

    cnt = 0
    for i in range(2, N-2):
        check = max(lst[i-2], lst[i-1], lst[i+1], lst[i+2])
        if lst[i] - check > 0:
            cnt += lst[i] - check
        else:
            continue

    print(f'#{tc} {cnt}')


from django.test import TestCase
from django.contrib.auth.models import User

from person.models import Profile

class ProfileTest(TestCase):

	def setUp(self):
		self.user = User(
			username='jdoe',
			first_name='John',
			last_name='Doe'
		)
		self.user.save()

		self.profile = Profile()
		self.profile.user = self.user
		self.profile.nickname = 'doer'

		self.profile.save()

	def tearDown(self):
		self.profile.delete()
		self.user.delete()

	def test_get_fullname(self):
		self.assertEqual(self.user.get_profile().get_fullname(), 'John Doe')


# leetcode 0981 - Time Based Key-Value Store
# Medium

# Design a time-based key-value data structure that can store multiple values for the same key at different time stamps
# and retrieve the key's value at a certain timestamp.
#
# Implement the TimeMap class:
#     TimeMap() Initializes the object of the data structure.
#     void set(String key, String value, int timestamp)
#           Stores the key key with the value value at the given time timestamp.
#     String get(String key, int timestamp)
#           Returns a value such that set was called previously, with timestamp_prev <= timestamp.
#           If there are multiple such values, it returns the value associated with the largest timestamp_prev.
#           If there are no values, it returns "".
class TimeMap:

    def __init__(self):
        self.store = {}  # key: list of [value, timestamp]

    def set(self, key: str, value: str, timestamp: int) -> None:
        if key not in self.store:
            self.store[key] = []
        self.store[key].append([value, timestamp])

    def get(self, key: str, timestamp: int) -> str:
        result = ""  # return empty string if there are no values
        values = self.store.get(key, [])

        # binary search operation
        left, right = 0, len(values) - 1
        while left <= right:
            middle = (left + right) // 2
            if values[middle][1] <= timestamp:
                result = values[middle][0]
                left = middle + 1
            else:
                right = middle - 1

        return result


import network
from esp import espnow
import time

# A WLAN interface must be active to send()/recv()
w0 = network.WLAN(network.STA_IF)  # Or network.AP_IF
w0.active(True)

w0.config('mac') ## my mac adress

e = espnow.ESPNow()
e.init()

peer_list = [b'X\xbf%\x9d\x8c\x94', b'0\xae\xa4\xd3\xa3\xe8']
for peer in peer_list:
    e.add_peer(peer)

#peer = b'0\xae\xa4\xd3\xa3\xe8'  # MAC address of peer's wifi interface
#e.add_peer(peer)

e.send("Starting...")       # Send to all peers
for i in range(100):
    e.send(peer, str(i)*20, True)
    time.sleep(0.5)
e.send(b'end')


import weakref

from . import serializable_object
from . import type_registry

import copy

@type_registry.register_type
class Composable(serializable_object.SerializableObject):
    """An object that can be composed by tracks.

    Base class of:
        Item
        Transition
    """

    name = serializable_object.serializable_field(
        "name",
        doc="Composable name."
    )
    metadata = serializable_object.serializable_field(
        "metadata",
        doc="Metadata dictionary for this Composable."
    )

    _serializable_label = "Composable.1"
    _class_path = "core.Composable"

    def __init__(self, name=None, metadata=None):
        super(Composable, self).__init__()
        self._parent = None

        # initialize the serializable fields
        self.name = name
        self.metadata = copy.deepcopy(metadata) if metadata else {}

    @staticmethod
    def visible():
        """Return the visibility of the Composable. By default True."""

        return False

    @staticmethod
    def overlapping():
        """Return whether an Item is overlapping. By default False."""

        return False

    # @{ functions to express the composable hierarchy
    def _root_parent(self):
        return ([self] + self._ancestors())[-1]

    def _ancestors(self):
        ancestors = []
        seqi = self
        while seqi.parent() is not None:
            seqi = seqi.parent()
            ancestors.append(seqi)
        return ancestors

    def parent(self):
        """Return the parent Composable, or None if self has no parent."""

        return self._parent() if self._parent is not None else None

    def _set_parent(self, new_parent):
        if new_parent is not None and self.parent() is not None:
            raise ValueError(
                "Composable named '{}' is already in a composition named '{}',"
                " remove from previous parent before adding to new one."
                " Composable: {}, Composition: {}".format(
                    self.name,
                    self.parent() is not None and self.parent().name or None,
                    self,
                    self.parent()
                )
            )
        self._parent = weakref.ref(new_parent) if new_parent is not None else None

    def is_parent_of(self, other):
        """Returns true if self is a parent or ancestor of other."""

        visited = set([])
        while other.parent() is not None and other.parent() not in visited:
            if other.parent() is self:
                return True
            visited.add(other)
            other = other.parent()

        return False

    # @}

    def __repr__(self):
        return (
            "otio.{}("
            "name={}, "
            "metadata={}"
            ")".format(
                self._class_path,
                repr(self.name),
                repr(self.metadata)
            )
        )

    def __str__(self):
        return "{}({}, {})".format(
            self._class_path.split('.')[-1],
            self.name,
            str(self.metadata)
        )


"""
Reporting module.
"""
import logging
import socket
from datetime import datetime

_HOSTNAME = socket.gethostname()

reporting_logger = logging.getLogger(__name__)

def make_report(report_type, msg, params=None, resource=''):
    """Return a dictionary compatible with ReportFormatter.
    """
    if params is None:
        params = {}
    return {
        'params': params,
        'resource': resource,
        'report_type': report_type,
        'msg': msg
    }

class ReportFormatter:
    """Formatter class creating messages for the report index.
    """
    def __init__(self, process_name):
        self.process_name = process_name

    def format(self, report):
        """Take a report templated dictionary and return a dictionary formatted
        for the report index.
        """
        try:
            report_type = report['report_type']
        except KeyError:
            raise ValueError("Report: %s is missing report required field 'report_type'" % report)
        return {
            'report_type': report_type, # CRITICAL, ERROR, INFO, DEBUG, WARN
            'host': _HOSTNAME,
            'process': self.process_name,
            'resource': report.get('resource', ''),
            'params': report.get('params', {}),
            'report_time': datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3],
            'message': report.get('msg', '')
        }


from tweepy import API
from tweepy import Cursor
from tweepy.streaming import StreamListener
from tweepy import OAuthHandler
from tweepy import Stream
from textblob import TextBlob

import credentials
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import re
import json

class TwitterClient():
    def __init__(self, twitter_user=None):
        self.auth = TwitterAuthenticator().authenticate_twitter_app()
        self.twitter_client = API(self.auth)

        self.twitter_user = twitter_user

    def get_twitter_client_api(self):
        return self.twitter_client

    def get_user_timeline_tweets(self, num_tweets):
        tweets = []
        for tweet in Cursor(self.twitter_client.user_timeline, id=self.twitter_user).items(num_tweets):
            tweets.append(tweet)
        return tweets

    def get_friend_list(self, num_friends):
        friend_list = []
        for friend in Cursor(self.twitter_client.friends, id=self.twitter_user).items(num_friends):
            friend_list.append(friend)
        return friend_list

    def get_home_timeline_tweets(self, num_tweets):
        home_timeline_tweets = []
        for tweet in Cursor(self.twitter_client.home_timeline, id=self.twitter_user).items(num_tweets):
            home_timeline_tweets.append(tweet)
        return home_timeline_tweets

class TwitterAuthenticator():

    def authenticate_twitter_app(self):
        auth = OAuthHandler(credentials.CONSUMER_KEY,
                            credentials.CONSUMER_SECRET)
        auth.set_access_token(credentials.ACCESS_TOKEN,
                              credentials.ACCESS_TOKEN_SECRET)
        return auth

class TwitterStreamer():
    def __init__(self):
        self.twitter_autenticator = TwitterAuthenticator()

    def stream_tweets(self, json_file, hash_tag_list):
        listener = TwitterListener(json_file)
        auth = self.twitter_autenticator.authenticate_twitter_app()
        stream = Stream(auth, listener)

        # filter data by the keywords:
        stream.filter(track=hash_tag_list)

class TwitterListener(StreamListener):
    def __init__(self, json_file):
        self.json_file = json_file

    def on_data(self, data):
        try:
            print(data)
            with open(self.json_file, 'a') as jsonfile:
                jsonfile.write(data+',')
            return True
        except BaseException as e:
            print("Error on_data %s" % str(e))
        return True

    def on_error(self, status):
        if status == 420:
            return False
        print(status)

class TweetAnalyzer():

    def clean_tweet(self, tweet):
        return ' '.join(re.sub("(@[A-Za-z0-9]+)|([^0-9A-Za-z \t])|(\w+:\/\/\S+)", " ", tweet).split())

    def tweets_to_data_frame(self, tweets):
        df = pd.DataFrame(
            data=[tweet.text for tweet in tweets], columns=['text'])

       # df['id'] = np.array([tweet.id for tweet in tweets])
       # df['len'] = np.array([len(tweet.text) for tweet in tweets])
       # df['date'] = np.array([tweet.created_at for tweet in tweets])
       # df['source'] = np.array([tweet.source for tweet in tweets])
        df['likes'] = np.array([tweet.favorite_count for tweet in tweets])
       # df['retweets'] = np.array([tweet.retweet_count for tweet in tweets])

        return df

    def analyze_sentiment(self, tweet):
        analysis = TextBlob(self.clean_tweet(tweet))
        return analysis.sentiment.polarity

if __name__ == '__main__':

    # To get streamed tweets
    # hash_tag_list = ["donald trump"]
    # json_file = "tweets.json"

    # twitter_client = TwitterClient('jayanthracharya')

    # tweet = twitter_client.get_user_timeline_tweets(1)
    # print(tweet)
    # with open("self.json", "w") as text_file:
    #     print(str(tweet), file=text_file)

    # twitter_streamer = TwitterStreamer()
    # twitter_streamer.stream_tweets(json_file, hash_tag_list)

    twitter_client = TwitterClient()
    tweet_analyzer = TweetAnalyzer()

    api = twitter_client.get_twitter_client_api()

    tweets = api.user_timeline(screen_name="realDonaldTrump", count=200)

    # print(dir(tweets[0]))
    # print(tweets[0].retweet_count)

    df = tweet_analyzer.tweets_to_data_frame(tweets)
    df['sentiment'] = np.array(
        [tweet_analyzer.analyze_sentiment(tweet) for tweet in df['text']])

    # print(df.head(10))
    with open('sentimetalanalysis.json', 'w') as f:
        f.write(json.dumps(json.loads(df.reset_index().to_json(orient='records')), indent=2))

    # Graph plot
    # time_likes = pd.Series(data=df['likes'].values, index=df['date'])
    # time_likes.plot(figsize=(16, 4), label="likes", legend=True)
    # time_retweets = pd.Series(data=df['retweets'].values, index=df['date'])
    # time_retweets.plot(figsize=(16, 4), label="retweets", legend=True)
    # plt.show()