#python day 6
#author zach.wang
import os, time, sys
from datetime import datetime
dir = "E:\\python"
savedir = "E:\python\zach.log"

def rescuresearch(lst,suffix,tmplist):
    flag = len(suffix)
    if os.path.isdir(lst):
        for sublst in os.listdir(lst):
            rescuresearch(sublst,suffix,tmplist)
    else:
        if flag>1:
            if os.path.splitext(lst)[1] == suffix:
                print(lst)
                tmplist.append(lst)
        else:
            print(lst)

def searchall(suffix=""):
    #global file
    file = input("do you want save result to file:[y/N]:\n")
    tmplist = []
    for lst in os.listdir(dir):
        print(lst.center(50, '-'))
        root = os.path.join(dir,lst)
        mtime = datetime.fromtimestamp(os.path.getmtime(root)).strftime('%Y-%m-%d %H:%M')
        print(mtime.center(30,"#").center(50," "))
        rescuresearch(root,suffix,tmplist)
    savetofile(file,tmplist,suffix)
'''
DIR="E:\\python"
for root, dirs, files in os.walk(DIR):
    print(files)
'''
def savetofile(file,tmplist,suffix):
    if file.lower() == "y":
        with open(savedir,"w") as fp:
            for lst in tmplist:
                fp.write(lst+"\n")
                sys.stdout.write("#")
                sys.stdout.flush()
                time.sleep(0.03)
            fp.write("Total Nums of File".center(30,"*").center(50," ")+"\n")
            fp.write("%10s %5d"%(suffix,tmplist.__len__()))
        print("\n\nfile save to",savedir,"success!")
        time.sleep(1)
    else:
        print("Total Nums of File".center(30,"*").center(50," "))
        print("%10s %5d"%(suffix,tmplist.__len__()))

def searchtype():
    suffix = input("please input what suffix you want:\n")
    if len(suffix) < 1:
        print("ERROR SYNTAX!")
        exit(1)
    searchall(suffix)

if __name__ == '__main__':
    print("\033[31;1m please Type dir or suffix for\033[0m","what do you want to find?\n")
    choose = input("All file under this dir or specify suffix of file:\n")
    print(choose)
    if choose.lower() == "dir":
        searchall()
    elif choose.lower() == "suffix":
    # 指定扩展名
        searchtype()
    else:
        print("ERROR SYNTAX!")
        exit(1)


import pandas as pd

from sklearn.metrics import classification_report, accuracy_score, confusion_matrix
from sklearn.model_selection import KFold, cross_val_score, train_test_split
from sklearn.metrics import r2_score

import modelUtil as modelut
import dataUtil as dataut

'''
This will be used to calculating validation results and implementing feedback loop to improve our model
'''
def feedback(pipeline,parameters,ultimateTraindf):
	# Read feedback data
    fbkdf = pd.read_csv(path+"/out/feedback.csv")
    # Extract incorrect predictions
    fbkdf = fbkdf.loc[fbkdf['check'] == False]
	# Combine with rest of the training data
    fbkdf = fbkdf.append(ultimateTraindf, ignore_index=True)
    # Create matrix for learning and prediction
    X, y = fbkdf.drop(['score'],axis=1), fbkdf['score'].as_matrix()
    # Split further into training and validation sets
    Xtrain, Xvalidate, ytrain, yValidate = train_test_split(X, y, train_size=0.7)
    # Initialize gridSearchRegressorCV Classifier with parameters
    gridSearchRegressor = modelut.getGridSearchCv(pipeline, parameters)
    # Fit the gridSearchRegressor on Training Set
    gridSearchRegressor.fit(Xtrain,ytrain)
    # Calculate best set of parameters and make predictions on validation set
    return validate(parameters, gridSearchRegressor, Xvalidate, yValidate)

'''
In this method I calculate the best of parameters for the sklearn Pipeline.
Then, I make predictions on the validation set and evaluate metrics and scores
Arguments:
gridSearchRegressor <=> GridSearchCV object fitted with feedback data
parameters <=> Initial parameters for Pipeline components
Xvalidate <=> Learning component of validation set
yValidate <=> Prediction component of validation set
Returns:
bestParameters <=> Best set of parameters for sklearn Pipeline after retraining with feedback data
predictions <=> Predictions on the validation set
'''
def validate(parameters, gridSearchRegressor,Xvalidate, yValidate):

    # Calculate best score for gridSearchRegressor
    print ('best score: %0.3f' % gridSearchRegressor.best_score_)
    # Calculate best set of parameters for gridSearchRegressor
    bestParameters = gridSearchRegressor.best_estimator_.get_params()
    # Display best set of parameters
    print ('best parameters set:')
    for paramName in sorted(parameters.keys()):
        print ('\t %s: %r' % (paramName, bestParameters[paramName]))

    # Make predictions on validation set and evaluate performance of gridSearchRegressor
    predictions = gridSearchRegressor.predict(Xvalidate)
    print ('R2 Score:', r2_score(yValidate, predictions))

	# Return best set of parameters and predictions
    return bestParameters, predictions


''' Module to hold global settings reused throughout qualysconnect. '''

__author__ = "Colin Bell <colin.bell@uwaterloo.ca>"
__copyright__ = "Copyright 2011-2013, University of Waterloo"
__license__ = "BSD-new"

global defaults
global default_filename

default_filename = ".qcrc"

defaults = { 'hostname' : 'qualysapi.qualys.com' }


import habitat_sim
from habitat_sim.utils.common import d3_40_colors_rgb, quat_to_angle_axis, quat_to_coeffs, quat_from_coeffs, quat_from_angle_axis
from habitat.utils.visualizations import maps
import magnum as mn
import numpy as np
import math
import matplotlib.pyplot as plt
from PIL import Image
import random
from skimage.color import rgb2gray
import habitat_sim.errors

""" Notes:
        1. It is weird that the Matterport3D and Gibson does not come with the semantic offline_dataset.
        2. The .navmesh file in the same folder will be loaded simultaneously with the .ply or .glb file.
        3. The environment provides single RGB, RGB-D, Depth, and Semantic observations.
        4. The environment provides panoramic RGB, RGB-D, Depth, and Semantic observations.
        5. The environment provides top down observation (agent).
        6. The agent is randomly spawn. The location is randomly chosen from a continuous space and orientation
           is randomly chosen from [east, north, west, south]
        7. The output depth can be clipped to a fixed range see depth_clip_vmax
        8. The back observation is not flipped anymore. (changed in NeurIPs 22 release)
"""

class House(object):
    def __init__(self,
                 scene=None,
                 enable_rgb=False,
                 enable_depth=False,
                 enable_rgb_depth=False,
                 enable_semantic=False,
                 enable_panorama=False,
                 enable_obs_noise=False,
                 enable_act_noise=False,
                 enable_local_map=False,
                 top_down_type="binary",
                 sensor_height=1.5,
                 rnd_seed=1234,
                 map_meters_per_pixel=0.01,
                 local_map_size=50,
                 enable_ego_local_map=False,
                 obs_width=224,
                 obs_height=224,
                 move_forward_amount=0.25,
                 turn_left_amount=10,
                 turn_right_amount=10,
                 map_show_agent=False,
                 map_show_goal=False,
                 goal_reach_eps=0.2,  # from active neural slam paper
                 depth_clip_vmax=False,
                 allow_sliding=False,
                 max_episode_length=500,
                 plot_trajectories=False
                 ):
        """
        The wrapper class for Facebook Habitat environment with several customized functions for PointGoal navigation
        :param scene: the absolute path of the scene files. For example, name.glb (Gibson); name.ply (Replica); string
        :param enable_rgb: if True, enable the RGB observations; bool
        :param enable_depth: if True, enable the Depth observations; bool
        :param enable_rgb_depth: if True, enable the RGB-D observations; bool
        :param enable_semantic: if True, enable the Semantic observations; bool
        :param enable_panorama: if True, enable the panoramic observations; bool
        :param enable_obs_noise: if True, enable the noisy observations; bool
        :param enable_act_noise: if True, enable the noisy actions; bool
        :param enable_local_map: if True, the local map is plotted; Otherwise,the global map is plotted; bool
        :param enable_physics: related to kinematics; by default: False; bool
        :param top_down_type: binary for binary occupancy map; boundary for RGB occupancy map; string
        :param sensor_height: camera height (m); float
        :param rnd_seed: random seed; by default: 1234; int
        :param map_meters_per_pixel: map roughness parameter, number of meters for one pixel; by default 0.01; float
        :param local_map_size: 1/2 size of the local map; by default 50; int
        :param obs_width: width of the observation; @param {type: "integer"}
        :param obs_height: height of the observation; int
        :param move_forward_amount: number of meters for one forward action (m); float
        :param turn_left_amount: number of degrees for the turning left action (degree); float
        :param turn_right_amount: number of degrees for the turning right action (degree); float
        :param map_show_agent: if True, show agent on the map; bool
        :param map_show_goal: if True, show goal on the map; bool
        :param goal_reach_eps: termination signal, if distance (agent, goal) <= eps, agents reach the goal; float
        :param enable_ego_local_map: if True, plot the map in an egocentric way; bool
        :param depth_clip_vmax: max value to clip the depth observation; float
        :param allow_sliding: if False, the sliding behavior is disabled; @param {type: "boolean"}
        """

        # check the scene validation
        assert scene is not None, f"Invalid scene error: Got {scene}. Please check the path/name of the scene file."

        # scene file in: .ply or .glb
        self.scene = scene

        # epsilon for goal reaching
        self.dist_eps = goal_reach_eps

        # set randomness
        self.rnd_seed = rnd_seed

        """
            Sensor configurations
        """
        self.enable_rgb = enable_rgb
        self.enable_depth = enable_depth
        self.enable_rgb_depth = enable_rgb_depth
        self.enable_semantic = enable_semantic
        self.enable_panorama = enable_panorama
        self.enable_noise_obs = enable_obs_noise
        self.depth_clip_vmax = depth_clip_vmax
        panorama_names = ["_front", "_left", "_right", "_back"]
        # create the list containing sensor names
        # for monocular: [color_sensor, depth_sensor]
        # for panoramic: [color_sensor_front, color_sensor_left, color_sensor_right, color_sensor_back]
        # note that: rgb-d observations contain both color_sensors and depth_sensors
        if self.enable_panorama:
            if self.enable_rgb_depth:
                sensor_names = ['color_sensor' + item for item in panorama_names] + \
                               ['depth_sensor' + item for item in panorama_names]
            elif self.enable_rgb:
                sensor_names = ['color_sensor' + item for item in panorama_names]
            elif self.enable_depth:
                sensor_names = ['depth_sensor' + item for item in panorama_names]
            elif self.enable_semantic:
                sensor_names = ['semantic_sensor' + item for item in panorama_names]
            else:
                raise Exception("Invalid observation")
        else:
            if self.enable_rgb:
                sensor_names = ["color_sensor"]
            elif self.enable_depth:
                sensor_names = ["depth_sensor"]
            elif self.enable_rgb_depth:
                sensor_names = ["color_sensor", "depth_sensor"]
            else:
                raise Exception("Invalid observation")

        # set the sensor names
        self.sensor_names = sensor_names
        # add top-down observation
        self.sensor_names.append("top_down")

        """
            Habitat settings
        """
        self.habitat_settings = {
            "scene": scene,  # path the scene
            "default_agent": 0,  # index of the default agent
            "sensor_height": sensor_height,  # height of sensor in meters
            "width": obs_width,  # observation image width
            "height": obs_height,  # observation image height
            "color_sensor": enable_rgb,  # use RGB sensor
            "depth_sensor": enable_depth,  # use Depth sensor
            "semantic_sensor": enable_semantic,  # use semantic sensor
            "seed": rnd_seed,  # used in random navigation
            "enable_physics": False  # for kinematic only
        }

        # define the action space
        # todo: The action space could be customized (https://aihabitat.org/docs/habitat-sim/new-actions.html)
        self.enable_act_noise = enable_act_noise
        self.action_space = ['move_forward', 'turn_left', 'turn_right']
        self.move_forward_amount = move_forward_amount
        self.turn_left_amount = turn_left_amount
        self.turn_right_amount = turn_right_amount

        # simulator initial configurations
        self.sim_cfg = None
        # agent initial configurations
        self.agent_cfg = None
        # control the sliding behavior
        self.allow_sliding = allow_sliding
        # create simulator, agent, and optimal path follower
        self.simulator, self.agent, self.follower = self.create_simulator_and_agent()

        """
            Map configurations
        """
        self.enable_local_map = enable_local_map
        self.meters_per_pixel = map_meters_per_pixel
        self.local_map_size = local_map_size
        self.map_show_agent = map_show_agent
        self.map_show_goal = map_show_goal
        self.enable_ego_local_map = enable_ego_local_map
        if top_down_type == "binary":
            self.top_down_map = self.render_top_down_view_binary()  # occupancy map: binary representation
        elif top_down_type == "boundary":
            self.top_down_map = self.render_top_down_view_habitat()  # occupancy map: RGB representation
            self.top_down_gray_map = self.rgb2gray(self.top_down_map.copy())  # convert to gray
        else:
            raise Exception("Invalid top down map mode.")
        # plot the trajectories on the map
        self.top_down_map_traj = self.top_down_map.copy()

        """
            Environment parameters
        """
        boundary = self.simulator.pathfinder.get_bounds()  # Environment parameters
        self.min_x = boundary[0][0]
        self.max_x = boundary[1][0]  # height?
        self.min_y = boundary[0][2]
        self.max_y = boundary[1][2]  # width?

        """
            Plot the figures
        """
        self.fig = None
        self.arr = None
        self.artists = []
        self.plot_traj = plot_trajectories

        """
            Episode parameters
        """
        # sample the start location, the goal location, and the geometric distance
        self.start_loc, self.goal_loc, self.geo_dist = self.sample_start_goal_locations()
        # record the shortest path
        self.shortest_path = None
        # track the geometric distance between the agent and the goal locations
        self.agent_goal_dist = np.inf
        # maximal episode length
        self.max_episode_length = max_episode_length
        # time step counter
        self.step_counter = 0

    # render binary top down observation
    def render_top_down_view_binary(self):
        height = self.simulator.pathfinder.get_bounds()[0][1]
        sim_top_down_map = self.simulator.pathfinder.get_topdown_view(self.meters_per_pixel,
                                                                      height)
        return sim_top_down_map

    # render boundary top down observation
    def render_top_down_view_habitat(self):
        height = self.simulator.pathfinder.get_bounds()[0][1]
        top_down_map = maps.get_topdown_map(
            self.simulator.pathfinder, height, meters_per_pixel=self.meters_per_pixel
        )
        recolor_map = np.array(
            [[255, 255, 255], [128, 128, 128], [0, 0, 0]], dtype=np.uint8
        )
        top_down_map = recolor_map[top_down_map]
        return top_down_map

    # sensor specifications
    def embedded_agent_sensor_specs(self):
        # sensors
        sensor_specs = []

        # default observation resolution
        img_height = self.habitat_settings['height']
        img_width = self.habitat_settings['width']
        sensor_height = self.habitat_settings['sensor_height']

        # function to get specifications
        def obtain_sensor_spec(sensor_type, sensor_uuid, orientation):
            # get standard sensor specification
            _spec = habitat_sim.CameraSensorSpec()
            # set sensor uuid (i.e., indicator)
            _spec.uuid = sensor_uuid
            # set sensor type
            if sensor_type == "color":
                _spec.sensor_type = habitat_sim.SensorType.COLOR
            elif sensor_type == "depth":
                _spec.sensor_type = habitat_sim.SensorType.DEPTH
            elif sensor_type == "semantic":
                _spec.sensor_type = habitat_sim.SensorType.SEMANTIC
            else:
                raise Exception(f"Invalid sensor type. Expect color, depth, or semantic, but get {sensor_type}")
            # set sensor model
            _spec.sensor_subtype = habitat_sim.SensorSubType.PINHOLE
            # set sensor resolution, position and orientation
            _spec.resolution = [img_height, img_width]
            _spec.position = [0.0, sensor_height, 0.0]  # [x, y, z], meters
            _spec.orientation = orientation  # [pitch, yaw, roll], radius, counter-clock wise

            # enable observation noise
            if self.enable_noise_obs:
                if sensor_type == "color":
                    _spec.noise_model = "GaussianNoiseModel"
                    _spec.noise_model_kwargs = dict(intensity_constant=0.1)
                elif sensor_type == "depth":
                    _spec.noise_model = "RedwoodDepthNoiseModel"
                    _spec.noise_model_kwargs = dict(noise_multiplier=1.0)
                else:
                    raise Exception("Wrong sensor type")
            return _spec

        if not self.enable_panorama:
            # set the RGB camera
            if self.enable_rgb:
                # get rgb camera
                rgb_sensor_spec = obtain_sensor_spec("color", "color_sensor", [0.0, 0.0, 0.0])
                # add the rgb camera
                sensor_specs.append(rgb_sensor_spec)

            # set the depth camera
            if self.enable_depth:
                # get depth camera
                depth_sensor_spec = obtain_sensor_spec("depth", 'depth_sensor', [0.0, 0.0, 0.0])
                # add the depth camera
                sensor_specs.append(depth_sensor_spec)

            # set the semantic camera
            if self.enable_semantic:
                # get semantic camera
                semantic_sensor_spec = obtain_sensor_spec('semantic', 'semantic_sensor', [0.0, 0.0, 0.0])
                # add the semantic sensor
                sensor_specs.append(semantic_sensor_spec)

            # set the RGB-D camera
            if self.enable_rgb_depth:
                # get the RGB camera
                rgb_sensor_spec = obtain_sensor_spec('color', 'color_sensor', [0.0, 0.0, 0.0])
                # get the depth camera
                depth_sensor_spec = obtain_sensor_spec('depth', 'depth_sensor', [0.0, 0.0, 0.0])
                # add the RGB and depth cameras
                sensor_specs.append(rgb_sensor_spec)
                sensor_specs.append(depth_sensor_spec)
        else:
            spec_orientations = [[0.0, 0.0, 0.0], [0.0, np.pi, 0.0], [0.0, np.pi / 2, 0.0], [0.0, -1 * np.pi / 2, 0.0]]
            spec_uuids = ["sensor_front", "sensor_back", "sensor_left", "sensor_right"]
            if self.enable_rgb:
                for spec_ori, spec_uuid in zip(spec_orientations, spec_uuids):
                    sensor_specs.append(obtain_sensor_spec("color", "color_" + spec_uuid, spec_ori))

            if self.enable_depth:
                for spec_ori, spec_uuid in zip(spec_orientations, spec_uuids):
                    sensor_specs.append(obtain_sensor_spec("depth", "depth_" + spec_uuid, spec_ori))

            if self.enable_semantic:
                for spec_ori, spec_uuid in zip(spec_orientations, spec_uuids):
                    sensor_specs.append(obtain_sensor_spec("semantic", "semantic_" + spec_uuid, spec_ori))

            if self.enable_rgb_depth:
                for spec_ori, spec_uuid in zip(spec_orientations, spec_uuids):
                    sensor_specs.append(obtain_sensor_spec("color", "color_" + spec_uuid, spec_ori))
                    sensor_specs.append(obtain_sensor_spec("depth", "depth_" + spec_uuid, spec_ori))

        # set the sensor specifications
        self.agent_cfg.sensor_specifications = sensor_specs

    def embedded_agent_action_specs(self):
        if self.enable_act_noise:
            self.agent_cfg.action_space = dict(
                move_forward=habitat_sim.ActionSpec(
                    "move_forward",
                    habitat_sim.PyRobotNoisyActuationSpec(
                        amount=self.move_forward_amount,
                        robot="LoCoBot",
                        controller="Proportional",
                        noise_multiplier=1.0
                    ),
                ),
                turn_left=habitat_sim.ActionSpec(
                    "turn_left",
                    habitat_sim.PyRobotNoisyActuationSpec(
                        amount=self.turn_left_amount,
                        robot="LoCoBot",
                        controller="Proportional",
                        noise_multiplier=0.5
                    ),
                ),
                turn_right=habitat_sim.ActionSpec(
                    "turn_right",
                    habitat_sim.PyRobotNoisyActuationSpec(
                        amount=self.turn_right_amount,
                        robot="LoCoBot",
                        controller="Proportional",
                        noise_multiplier=0.5
                    ),
                )
            )
        else:
            self.agent_cfg.action_space = {
                "move_forward": habitat_sim.agent.ActionSpec(
                    "move_forward", habitat_sim.agent.ActuationSpec(amount=self.move_forward_amount)
                ),
                "turn_left": habitat_sim.agent.ActionSpec(
                    "turn_left", habitat_sim.agent.ActuationSpec(amount=self.turn_left_amount)
                ),
                "turn_right": habitat_sim.agent.ActionSpec(
                    "turn_right", habitat_sim.agent.ActuationSpec(amount=self.turn_right_amount)
                ),
            }

    # create the simulator and agent
    def create_simulator_and_agent(self):
        # create the simulator configurations
        self.sim_cfg = habitat_sim.SimulatorConfiguration()  # get the configuration object for the simulator
        self.sim_cfg.gpu_device_id = 0  # assign a GPU to the simulator
        self.sim_cfg.scene_id = self.habitat_settings["scene"]  # define the scene name with the ply files
        self.sim_cfg.enable_physics = self.habitat_settings['enable_physics']  # enable the physics

        # create the agent configurations
        self.agent_cfg = habitat_sim.agent.AgentConfiguration()  # get the configuration object for the agent

        # create the sensor configurations
        self.embedded_agent_sensor_specs()

        # create the action configurations
        self.embedded_agent_action_specs()

        # create the simulator
        self.sim_cfg = habitat_sim.Configuration(self.sim_cfg, [self.agent_cfg])
        simulator = habitat_sim.Simulator(self.sim_cfg)

        # disable the sliding behavior
        simulator.config.sim_cfg.allow_sliding = self.allow_sliding

        # create the agent
        agent = simulator.initialize_agent(0)
        # set the agent state
        agent_state = habitat_sim.AgentState()
        agent_state.position = np.array([0.0, 0.0, 0.0])  # the agent is set at [0, 0, 0] by default
        agent.set_state(agent_state)

        # create follower for optimal path planning
        follower = habitat_sim.nav.GreedyGeodesicFollower(
            pathfinder=simulator.pathfinder,
            agent=agent,
            goal_radius=self.dist_eps,
            forward_key="move_forward",
            left_key="turn_left",
            right_key="turn_right"
        )

        return simulator, agent, follower

    def is_on_map(self, loc):
        c = int((loc[0] - self.min_x) // self.meters_per_pixel)
        r = int((loc[2] - self.min_y) // self.meters_per_pixel)

        return not self.top_down_gray_map[r, c] == 1.0

    # sample navigable start and goal locations
    def sample_start_goal_locations(self):
        while True:
            # sample start and goal locations
            s_loc = self.simulator.pathfinder.get_random_navigable_point()
            g_loc = self.simulator.pathfinder.get_random_navigable_point()

            # exam whether the path exists
            path = habitat_sim.ShortestPath()
            path.requested_start = s_loc
            path.requested_end = g_loc
            found_path = self.simulator.pathfinder.find_path(path)
            geodesic_distance = path.geodesic_distance
            if found_path is True and self.is_on_map(s_loc) and self.is_on_map(g_loc):
                # return start, goal locations and geometry distance
                return s_loc, g_loc, geodesic_distance

    # set fixed start and goals
    def set_start_goal_locations(self):
        path = habitat_sim.ShortestPath()
        path.requested_start = self.start_loc
        path.requested_end = self.goal_loc
        self.simulator.pathfinder.find_path(path)
        geodesic_distance = path.geodesic_distance
        return geodesic_distance

    # compute the geometric ditance
    def compute_geo_distance(self, start_loc, goal_loc):
        path = habitat_sim.ShortestPath()
        path.requested_start = start_loc
        path.requested_end = goal_loc
        self.simulator.pathfinder.find_path(path)
        return path.geodesic_distance

    # set agent state
    def set_agent_state(self, loc=None, ori=None):
        agent_state = habitat_sim.AgentState()
        agent_state.position = self.start_loc if loc is None else loc
        ori = quat_from_angle_axis(ori, np.array([0, 1, 0]))  # pitch, yaw, roll
        agent_state.rotation = agent_state.rotation if ori is None else ori
        self.agent.set_state(agent_state)

    # render agent observations
    def render_agent_observations(self):
        # render from the simulator
        observations = self.simulator.get_sensor_observations()

        # save the observation in a dict
        return_obs = {}
        for name in self.sensor_names:
            if name == "top_down":  # render top down observation
                return_obs[name] = self.draw_agent_on_top_down_map()
            else:  # render sensor observations
                if "depth" in name and self.depth_clip_vmax:  # clip the depth image if depth_clip_vmax != 0
                    observations[name] = np.clip(observations[name], a_min=0, a_max=self.depth_clip_vmax)

                return_obs[name] = observations[name]

        return return_obs

    # render agent state
    def render_agent_state(self):
        return self.agent.state.position.tolist() + quat_to_coeffs(self.agent.state.rotation).tolist()

    # gym reset function
    def reset(self, start_loc=None, goal_loc=None):
        # reset the step counter
        self.step_counter = 0

        # randomly sample the start ang goal locations
        if start_loc is None or goal_loc is None:
            # randomly sample the start and goal locations
            self.start_loc, self.goal_loc, self.geo_dist = self.sample_start_goal_locations()

            # # todo: debug
            # self.start_loc = np.array([-0.15,  0.17,  1.55])
            # self.goal_loc = np.array([-3.67,  0.17, 0.83])

            # reset the top-down map
            self.top_down_map_traj = self.top_down_map.copy()
        else:
            # set the start and goal locations
            self.start_loc = np.array(start_loc).astype(np.float32)
            self.goal_loc = np.array(goal_loc).astype(np.float32)
            self.set_start_goal_locations()
            # query the shortest path
            self.query_shortest_path(self.start_loc, self.goal_loc)
            # draw the trajectory on the top-down map
            self.top_down_map_traj = self.display_shortest_path()

        # randomly sample the agent's orientation [0, np.pi / 2, np.pi, np.pi * 3 / 2]
        ori = random.sample([0, np.pi/2, np.pi, np.pi * 3 / 2], 1)[0]
        # set the agent's orientation
        self.set_agent_state(ori=ori)

        # render agent observation
        obs = self.render_agent_observations()

        # render agent state e.g. [x, y, z, rotation]
        obs['state'] = self.render_agent_state()
        return obs

    # gym step function
    def step(self, act):
        # step
        self.simulator.step(act)
        # render observation
        obs = self.render_agent_observations()
        # render state
        obs['state'] = self.render_agent_state()
        # increase the time step
        self.step_counter += 1
        # check the termination
        done = self.is_terminal(obs['state'])

        return obs, done

    # gym render function
    def render(self, observation, time_step):
        if self.enable_panorama:
            if self.enable_rgb:
                self.display_panorama(observation, time_step, "color_sensor")

            if self.enable_depth:
                self.display_panorama(observation, time_step, "depth_sensor")

            if self.enable_semantic:
                self.display_panorama(observation, time_step, "semantic_sensor")

            if self.enable_rgb_depth:
                self.display_panorama(observation, time_step, "color_sensor")
        else:
            self.display_observations(observation, time_step)

    # gym close function
    def close(self):
        self.simulator.close()

    def query_shortest_path(self, start_loc, goal_loc):
        # Use ShortestPath module to compute path between samples.
        self.shortest_path = habitat_sim.ShortestPath()
        # set the start and goal locations
        self.shortest_path.requested_start = start_loc
        self.shortest_path.requested_end = goal_loc
        # find the path use the built-in path finder
        self.simulator.pathfinder.find_path(self.shortest_path)

    def display_shortest_path(self):
        # render top down map
        top_down_map = self.top_down_map.copy()
        grid_dimensions = (top_down_map.shape[0], top_down_map.shape[1])
        # convert world trajectory points to maps module grid points
        trajectory = [
            maps.to_grid(
                path_point[2],
                path_point[0],
                grid_dimensions,
                pathfinder=self.simulator.pathfinder,
            )
            for path_point in self.shortest_path.points
        ]
        grid_tangent = mn.Vector2(
            trajectory[1][1] - trajectory[0][1], trajectory[1][0] - trajectory[0][0]
        )
        path_initial_tangent = grid_tangent / grid_tangent.length()
        initial_angle = math.atan2(path_initial_tangent[0], path_initial_tangent[1])
        # draw the agent and trajectory on the map
        maps.draw_path(top_down_map, trajectory)
        maps.draw_agent(
            top_down_map, trajectory[0], initial_angle, agent_radius_px=8
        )
        return top_down_map

    @staticmethod
    def crop_local_map(agent_loc, global_map, size):
        # get the size of the global map
        r, c, _ = global_map.shape

        # compute the boundary
        crop_from_r = agent_loc[0] - size if agent_loc[0] - size > 0 else 0
        crop_from_c = agent_loc[1] - size if agent_loc[1] - size > 0 else 0

        crop_to_r = agent_loc[0] + size if agent_loc[0] + size < r else r
        crop_to_c = agent_loc[1] + size if agent_loc[1] + size < c else c

        # crop the map
        local_map = global_map[crop_from_r:crop_to_r, crop_from_c:crop_to_c, :]

        return local_map

    def draw_agent_on_top_down_map(self):
        # get the boundary of the environment
        top_down_map = self.top_down_map_traj.copy()
        grid_dimensions = (top_down_map.shape[0], top_down_map.shape[1])

        # convert the world positions to map locations
        agent_map_pos = maps.to_grid(
            self.agent.state.position[2],
            self.agent.state.position[0],
            grid_dimensions,
            pathfinder=self.simulator.pathfinder,
        )

        # plot the agent's path in dashed red color
        if self.plot_traj:
            top_down_map[agent_map_pos[0] - 5: agent_map_pos[0] + 5,
                         agent_map_pos[1] - 5: agent_map_pos[1] + 5, 0] = 255
            top_down_map[agent_map_pos[0] - 5: agent_map_pos[0] + 5,
                         agent_map_pos[1] - 5: agent_map_pos[1] + 5, 1] = 100
            top_down_map[agent_map_pos[0] - 5: agent_map_pos[0] + 5,
                         agent_map_pos[1] - 5: agent_map_pos[1] + 5, 2] = 0

        # save the current trajectory
        self.top_down_map_traj = top_down_map.copy()

        # convert goal positions to map locations
        goal_map_pos = maps.to_grid(
            self.goal_loc[2],
            self.goal_loc[0],
            grid_dimensions,
            pathfinder=self.simulator.pathfinder
        )

        # get the orientation and reference axis
        agent_angle, refer_axis = quat_to_angle_axis(self.agent.state.rotation)

        # compute the direction vector
        head_vector = [np.cos(agent_angle), 0, np.sin(agent_angle)]

        if np.array_equal(refer_axis, np.array([0, 1, 0])):
            # rotate along x axis
            rot_mat_x = np.array([[1, 0, 0],
                                  [0, np.cos(-np.pi), -np.sin(-np.pi)],
                                  [0, np.sin(-np.pi), np.cos(-np.pi)]])
            head_vector = np.matmul(rot_mat_x, head_vector)

        # rotate along z axis
        rot_mat_z = np.array([[np.cos(np.pi), -np.sin(np.pi), 0],
                              [np.sin(np.pi), np.cos(np.pi), 0],
                              [0, 0, 1]])
        head_vector_map = np.matmul(rot_mat_z, head_vector)

        # compute the angle
        map_angle = np.arctan2(head_vector_map[2], head_vector_map[0])

        if self.map_show_agent:
            agent_radius = 15
            # draw the agent on the map
            maps.draw_agent(
                top_down_map, agent_map_pos, map_angle, agent_radius_px=agent_radius
            )  # the agent will be resize a region with radius = 5 pixelsex

            # draw the goal on the map
            if self.map_show_goal:
                goal_off_set = 15
                top_down_map[goal_map_pos[0]-goal_off_set:goal_map_pos[0]+goal_off_set,
                             goal_map_pos[1]-goal_off_set:goal_map_pos[1]+goal_off_set, :] = 0.7

        # crop the local map out if the local map flag is True
        if self.enable_local_map:
            top_down_map = self.crop_local_map(agent_loc=agent_map_pos,
                                               global_map=top_down_map,
                                               size=self.local_map_size)

            if self.enable_ego_local_map:  # if True, rotate the local map based on agent orientation
                # rotate the local map into egocentric view
                rot_control = int(np.round(map_angle / (np.pi / 2)))
                if rot_control == 0:
                    top_down_map = np.rot90(top_down_map, k=2)
                elif rot_control == 1:
                    top_down_map = np.rot90(top_down_map, k=1)
                elif rot_control == -1:
                    top_down_map = np.rot90(top_down_map, k=3)
                else:
                    pass

        return top_down_map

    def display_observations(self, obs, t):
        if t == 0:  # create display artists for all sensors
            view_num = len(self.sensor_names)
            self.fig, self.arr = plt.subplots(1, view_num, figsize=(12, 6))
            self.arr = [self.arr] if view_num == 1 else self.arr
            # create the plot artists
            for i, name in enumerate(self.sensor_names):
                # remove the axis labels
                self.arr[i].axis("off")
                # add title
                self.arr[i].set_title(name)
                if name == 'color_sensor':
                    self.artists.append(self.arr[i].imshow(obs[name][:, :, 0:3]))
                elif name == "depth_sensor":
                    if self.depth_clip_vmax:
                        self.artists.append(self.arr[i].imshow(obs[name]))
                    else:
                        self.artists.append(self.arr[i].imshow(obs[name]))
                elif name == "top_down":
                    self.artists.append(self.arr[i].imshow(obs[name]))
                elif name == "semantic_sensor":
                    semantic_img = Image.new("P", (obs[name].shape[1], obs[name].shape[0]))
                    semantic_img.putpalette(d3_40_colors_rgb.flatten())
                    semantic_img.putdata((obs[name].flatten() % 40).astype(np.uint8))
                    semantic_img = semantic_img.convert("RGBA")
                    self.artists.append(self.arr[i].imshow(semantic_img))
                else:
                    raise Exception(f"Invalid observation name {name}")
        else:
            for i, name in enumerate(self.sensor_names):
                if name == 'color_sensor':
                    self.artists[i].set_data(obs[name][:, :, 0:3])
                elif name == 'depth_sensor':
                    self.artists[i].set_data(obs[name])
                elif name == "top_down":
                    self.artists[i].set_data(obs[name])
                elif name == "semantic_sensor":
                    semantic_img = Image.new("P", (obs[name].shape[1], obs[name].shape[0]))
                    semantic_img.putpalette(d3_40_colors_rgb.flatten())
                    semantic_img.putdata((obs[name].flatten() % 40).astype(np.uint8))
                    semantic_img = semantic_img.convert("RGBA")
                    self.artists[i].set_data(semantic_img)

        self.fig.canvas.draw()
        plt.pause(0.1)

    def display_panorama(self, obs, t, obs_type):
        if t == 0:
            if not self.enable_rgb_depth:
                # create the figure
                self.fig, self.arr = plt.subplots(3, 3, figsize=(12, 12))
                # remove the axis labels
                for m in range(3):
                    for n in range(3):
                        self.arr[m, n].axis("off")

                # built-in function
                def create_artist(plot_arr, r, c, obs_name):
                    # set title of the plot
                    plot_arr[r, c].set_title(obs_name)
                    # create the artist for subplot
                    if obs_type == "color_sensor":
                        return plot_arr[r, c].imshow(obs[obs_name][:, :, 0:3])
                    elif obs_type == "depth_sensor":
                        if self.depth_clip_vmax:
                            return plot_arr[r, c].imshow(obs[obs_name])
                        else:
                            return plot_arr[r, c].imshow(obs[obs_name])
                    elif obs_type == "semantic_sensor":
                        _img = Image.new("P", (obs[obs_name].shape[1], obs[obs_name].shape[0]))
                        _img.putpalette(d3_40_colors_rgb.flatten())
                        _img.putdata((obs[obs_name].flatten() % 40).astype(np.uint8))
                        _img = _img.convert("RGBA")
                        return plot_arr[r, c].imshow(_img)
                    else:
                        raise Exception(f"Invalid observation name {obs_type}")

                # add title
                self.artists.append(create_artist(self.arr, 0, 1, obs_type + '_front'))
                self.artists.append(create_artist(self.arr, 1, 0, obs_type + '_left'))
                self.artists.append(create_artist(self.arr, 1, 2, obs_type + '_right'))
                self.artists.append(create_artist(self.arr, 2, 1, obs_type + '_back'))

                # add top down observation
                self.artists.append(self.arr[1, 1].imshow(obs["top_down"]))
            else:
                # create the figure
                self.fig, self.arr = plt.subplots(4, 3, figsize=(12, 12))
                # remove the axis labels
                for m in range(4):
                    for n in range(3):
                        self.arr[m, n].axis("off")

                # add title
                self.arr[0, 0].set_title("color_front")
                self.arr[0, 1].set_title("depth_front")
                self.artists.append(self.arr[0, 0].imshow(obs['color_sensor_front']))
                self.artists.append(self.arr[0, 1].imshow(obs['depth_sensor_front']))

                self.arr[1, 0].set_title("color_left")
                self.arr[1, 1].set_title("depth_left")
                self.artists.append(self.arr[1, 0].imshow(obs['color_sensor_left']))
                self.artists.append(self.arr[1, 1].imshow(obs['depth_sensor_left']))

                self.arr[2, 0].set_title("color_right")
                self.arr[2, 1].set_title("depth_right")
                self.artists.append(self.arr[2, 0].imshow(obs['color_sensor_right']))
                self.artists.append(self.arr[2, 1].imshow(obs['depth_sensor_right']))

                self.arr[3, 0].set_title("color_back")
                self.arr[3, 1].set_title("depth_back")
                self.artists.append(self.arr[3, 0].imshow(obs['color_sensor_back']))
                self.artists.append(self.arr[3, 1].imshow(obs['depth_sensor_back']))

                # add top down observation
                self.arr[1, 2].set_title("top_down")
                self.artists.append(self.arr[1, 2].imshow(obs["top_down"]))
        else:
            if not self.enable_rgb_depth:
                # update the artists
                def update_artist(artists, idx, obs_name):
                    if obs_type == "color_sensor":
                        artists[idx].set_data(obs[obs_name][:, :, 0:3])
                    elif obs_type == "depth_sensor":
                        artists[idx].set_data(obs[obs_name])
                    elif obs_type == "semantic_sensor":
                        _img = Image.new("P", (obs[obs_name].shape[1], obs[obs_name].shape[0]))
                        _img.putpalette(d3_40_colors_rgb.flatten())
                        _img.putdata((obs[obs_name].flatten() % 40).astype(np.uint8))
                        _img = _img.convert("RGBA")
                        artists[idx].set_data(_img)
                    else:
                        raise Exception(f"Invalid observation name {obs_type}")
                # update the plot with the latest offline_dataset
                update_artist(self.artists, 0, obs_type + "_front")
                update_artist(self.artists, 1, obs_type + "_left")
                update_artist(self.artists, 2, obs_type + "_right")
                update_artist(self.artists, 3, obs_type + "_back")

                # update the top down view
                self.artists[-1].set_data(obs['top_down'])
            else:
                self.artists[0].set_data(obs['color_sensor_front'])
                self.artists[1].set_data(obs['depth_sensor_front'])

                self.artists[2].set_data(obs['color_sensor_left'])
                self.artists[3].set_data(obs['depth_sensor_left'])

                self.artists[4].set_data(obs['color_sensor_right'])
                self.artists[5].set_data(obs['depth_sensor_right'])

                self.artists[6].set_data(obs['color_sensor_back'])
                self.artists[7].set_data(obs['depth_sensor_back'])

                # add top down observation
                self.artists[8].set_data(obs["top_down"])

        self.fig.canvas.draw()
        plt.pause(0.1)

    # display a top down map
    def display_top_down_map(self):
        plt.figure(figsize=(12, 8))
        ax = plt.subplot(1, 1, 1)
        ax.axis("off")
        if len(self.top_down_map.shape) != 3:
            rows, cols = self.top_down_map.shape
        else:
            rows, cols, _ = self.top_down_map.shape
        plt.title(f"Size {rows} x {cols}")
        plt.imshow(self.top_down_map)
        plt.show()

    # rgb2gray
    @staticmethod
    def rgb2gray(obs):
        return rgb2gray(obs)

    def is_terminal(self, loc):
        # convert location to [x, y]
        agent_loc = np.array([loc[0], loc[2]])
        goal_loc = np.array([self.goal_loc[0], self.goal_loc[2]])
        # compute the geometric distance
        self.agent_goal_dist = np.linalg.norm(agent_loc - goal_loc)

        # check termination
        if self.agent_goal_dist < self.dist_eps or self.step_counter == self.max_episode_length:
            done = True
        else:
            done = False

        # return termination flag
        return done

    @staticmethod
    def quaternion_to_angle(quaternion_array):
        quaternion = quat_from_coeffs(quaternion_array)
        # get the orientation and reference axis
        agent_angle, refer_axis = quat_to_angle_axis(quaternion)

        # compute the direction vector
        head_vector = [np.cos(agent_angle), 0, np.sin(agent_angle)]

        if np.array_equal(refer_axis, np.array([0, 1, 0])):
            # rotate along x axis
            rot_mat_x = np.array([[1, 0, 0],
                                  [0, np.cos(-np.pi), -np.sin(-np.pi)],
                                  [0, np.sin(-np.pi), np.cos(-np.pi)]])
            head_vector = np.matmul(rot_mat_x, head_vector)

        # rotate along z axis
        rot_mat_z = np.array([[np.cos(np.pi), -np.sin(np.pi), 0],
                              [np.sin(np.pi), np.cos(np.pi), 0],
                              [0, 0, 1]])
        head_vector_map = np.matmul(rot_mat_z, head_vector)

        # compute the angle
        map_angle = np.arctan2(head_vector_map[2], head_vector_map[0])

        return map_angle


# Abdelrahman M.
'''
Here I use the polyglot text extractor to extract the entities.
It's possible here to count the occurence of the entities within each article.
But for the time being I'm only extracting the entities.
'''

from polyglot.text import Text as PolyglotExtractor

def extract(text, language):
	"""
	Function that extracts tokens and entities from text.
	Args:
		text(str)
		language(str)
	Returns:
		words(list(str)): list containg entities
	"""

	tagged_text = PolyglotExtractor(text, hint_language_code=language)
	entities = tagged_text.entities
	tokens = tagged_text.tokens

	words = set()

	for entity in entities:
		for token in entity:
			words.add(token.lower())

	words = list(words)

	return words


import datetime as dt
import json
from terminaltables import SingleTable as tb

class c: r, g, w, x = '\033[1;31m', '\033[1;32m', '\033[1;37m', '\033[0m'
j = json.load(open('data.json'))
xt, yt, zt = j["p"][:]
bn, bd, bt, ba = j['t'][0]['n'], j['t'][0]['d'], j['t'][0]['t'], j['t'][0]['a']
n, d, s, x = len(ba), [], [], 0
ss, xs, ys, zs = [0] * 4

t = ['', c.w + 'All (100%)' + c.x, c.w + 'Saving (' + str(xt) + '%)' + c.x,
    c.w + 'Spending (' + str(yt) + '%)' + c.x,
    c.w + 'Emergency (' + str(zt) + '%)' + c.x]

for x in range(n):
    r = bd[x] + ' ' + c.w + bn[x] + c.x
    if bt[x] is 'D':
        xa, ya = ba[x] * (xt / 100), ba[x] * (yt / 100)
        za = ba[x] - xa - ya
        d.append([r, ba[x], xa, ya, za])
    else: d.append([r, -ba[x], 0, -ba[x], 0])
    ss += d[x][1]
    xs += d[x][2]
    ys += d[x][3]
    zs += d[x][4]
    if x is n - 1: s.extend([ss, xs, ys, zs])
    for v, w in enumerate(d[x]):
        if isinstance(w, float):
            d[x][v] = '$ {0:.2f}'.format(abs(w))
            if w > 0: d[x][v] = c.g + d[x][v] + c.x
            if w < 0: d[x][v] = c.r + d[x][v] + c.x
        if w is 0: d[x][v] = ''
    for v, w in enumerate(s):
        if isinstance(w, float): s[v] = c.w + '$ {0:.2f}'.format(w) + c.x
    x += 1

z = [dt.datetime.now().strftime('%Y-%m-%d') + ' ' + c.w + 'GRANDTOTAL' + c.x]
z.extend(s)
print(tb([t] + d + [z]).table)


#!/usr/bin/env python

#Each queen is represented by a 2 tuple indicating their
#(col, row) position
def check_conflicts(queen, queen_list):
    for other_queen in queen_list:
        #Are the queens in the same colunm
        if queen[0] == other_queen[0]:
            return True
        #Are the queens in the same row
        if queen[1] == other_queen[1]:
            return True
        #Are the queens in the same diagnal of each other
        delta_column = abs(queen[0]-other_queen[0])
        delta_row = abs(queen[1] - other_queen[1])
        if delta_column == delta_row:
            return True
    #All checks pass no conflict found
    return False


from __future__ import unicode_literals
from django.db import models
from django.utils import timezone
from simple_history.models import HistoricalRecords
from datetime import datetime
# from inventory.models import WareHouse, WareHouseItem
from basedata.const import MANUFACTURING_PRODUCT_TYPES, PROCESSED_PRODUCTS_STOCK_STATUS_CHOICES

class ProcessProduct(models.Model):

    name = models.CharField(max_length=255)
    description = models.TextField()
    type = models.PositiveSmallIntegerField(choices=MANUFACTURING_PRODUCT_TYPES)# main product, byproduct, waste,  wip
    unit = models.ForeignKey('inventory.UnitOfMeasure', on_delete=models.SET_NULL, null=True)
    created_on = models.DateTimeField(auto_now_add=True, editable=False, db_index=True, verbose_name=('created on'))
    finished_goods= models.BooleanField(default=False)
    reference_number = models.CharField(max_length=255, null=True, default=None)
    location = models.ForeignKey(
                        'inventory.WareHouse',
                        blank=True,
                        null=True,
                        on_delete=models.SET_NULL
                    )
    unit = models.ForeignKey(
                        'inventory.UnitOfMeasure',
                        on_delete=models.SET_NULL,
                        null=True,
                        blank=True,
                        default=1
                    )
    status = models.PositiveIntegerField(
                            default=0,
                            choices=PROCESSED_PRODUCTS_STOCK_STATUS_CHOICES,
                        )
    minimum_order_level = models.IntegerField( default=0, null=True, blank=True)
    maximum_stock_level = models.IntegerField(default=0, null=True, blank=True)
    history = HistoricalRecords()

    @property
    def quantity(self):
        from inventory.models import WareHouseItem

        #returns quantity from all warehouses
        processed = WareHouseItem.objects.filter(processed_item=self)
        return sum([i.quantity for i in processed])

    @property
    def unit_sales_price(self):
    	return self.unitpricing.group_pricing_unit_sales_price

    def processes(self):
        return self.processes.all()

    def production_orders(self):
        return self.production_orders.all()

    def save(self, *args, **kwargs):
        if not self.reference_number:
           prefix = 'PPD-{}'.format(timezone.now().strftime('%y%m%d'))
           prev_instances = self.__class__.objects.filter(reference_number__contains=prefix)
           if prev_instances.exists():
              last_instance_id = prev_instances.last().reference_number[-4:]
              self.reference_number = prefix+'{0:04d}'.format(int(last_instance_id)+1)
           else:
               self.reference_number = prefix+'{0:04d}'.format(1)
        super(ProcessProduct, self).save(*args, **kwargs)

    def __str__(self):
        return f'{self.name} {self.reference_number}'

class SalesGroupUnitPricing(models.Model):
    name = models.CharField(max_length=230)
    product = models.ForeignKey(
    					'ProcessProduct',
    					null =True,
    					on_delete = models.SET_NULL,
    					related_name = 'unitpricing'
    				)
    group_pricing_unit_sales_price = models.DecimalField(max_digits=16, default= 0, decimal_places=2)
    reference_number = models.CharField(max_length=255, null=True, default=None)

    def save(self, *args, **kwargs):
        if not self.reference_number:
            prefix = 'SGUP-{}'.format(timezone.now().strftime('%y%m%d'))
            prev_instances = self.__class__.objects.filter(reference_number__contains=prefix)
            if prev_instances.exists():
                last_instance_id = prev_instances.last().reference_number[-4:]
                self.reference_number = prefix+'{0:04d}'.format(int(last_instance_id)+1)
            else:
                self.reference_number = prefix+'{0:04d}'.format(1)
        super(SalesGroupUnitPricing, self).save(*args, **kwargs)

    def __str__(self):
        return f'{self.name} {self.reference_number}'


from collections import OrderedDict

from cloudshell.cli.command_template.command_template import CommandTemplate

DEFAULT_ERROR_MAP = OrderedDict((("error:", "Error happens while executing CLI command"),))

def prepare_error_map(error_map=None):
    """

    :param collections.OrderedDict error_map:
    :rtype: collections.OrderedDict
    """
    if error_map is None:
        error_map = OrderedDict()

    error_map.update(DEFAULT_ERROR_MAP)
    return error_map

SAVE_CONFIGURATION = CommandTemplate("save {destination_file_path}", error_map=prepare_error_map(
    error_map=OrderedDict((("[Ee]rror saving", "Failed to save configuration file"),))))

LOAD_CONFIGURATION = CommandTemplate("load {source_file_path}", error_map=prepare_error_map(
    error_map=OrderedDict((("[Cc]an not open", "Unable to open remote configuration file. "
                                               "Please check that config file link is correct"),
                           ("[Ii]nvalid url protocol", "Invalid protocol type in the configuration file link"),
                           ("[Hh][Tt][Tt][Pp] [Ee]rror", "Unable to retrieve configuration file via HTTP. "
                                                         "Please check that config file link is correct")))))

COMMIT = CommandTemplate("commit", error_map=prepare_error_map(
    error_map=OrderedDict((("[Cc]ommit failed", "Failed to commit changes. Please check your configuration file"),))))

SHOW_INTERFACES = CommandTemplate("show interfaces", error_map=prepare_error_map())


# ======================================================================
# Adapter Array
#   Advent of Code 2020 Day 10 -- Eric Wastl -- https://adventofcode.com
#
# Python implementation by Dr. Dean Earl Wright III
# ======================================================================

# ======================================================================
#                    t e s t _ j o l t s . p y
# ======================================================================
"Test solver for Advent of Code 2020 day 10, Adapter Array"

# ----------------------------------------------------------------------
#                                                                 import
# ----------------------------------------------------------------------
import unittest

import aoc_10
import jolts

# ----------------------------------------------------------------------
#                                                              constants
# ----------------------------------------------------------------------
EXAMPLE_7_5_TEXT = """
16
10
15
5
1
11
7
19
6
12
4
"""
EXAMPLE_22_10_TEXT = """
28
33
18
42
31
14
46
20
48
47
24
23
49
45
19
38
39
11
1
32
25
35
8
17
7
9
4
2
34
10
3
"""
PART_ONE_TEXT = EXAMPLE_22_10_TEXT
PART_TWO_TEXT = EXAMPLE_22_10_TEXT

PART_ONE_RESULT = 22 * 10
PART_TWO_RESULT = 19208

# ======================================================================
#                                                              TestJolts
# ======================================================================

class TestJolts(unittest.TestCase):  # pylint: disable=R0904
    "Test Jolts object"

    def test_empty_init(self):
        "Test the default Jolts creation"

        # 1. Create default Jolts object
        myobj = jolts.Jolts()

        # 2. Make sure it has the default values
        self.assertEqual(myobj.part2, False)
        self.assertEqual(myobj.text, None)
        self.assertEqual(len(myobj.adapters), 0)
        self.assertEqual(len(myobj.ordered), 0)
        self.assertEqual(myobj.start, 0)
        self.assertEqual(myobj.device, None)

    def test_text_init(self):
        "Test the Jolts object creation from text"

        # 1. Create Jolts object from text
        myobj = jolts.Jolts(text=aoc_10.from_text(EXAMPLE_7_5_TEXT))

        # 2. Make sure it has the expected values
        self.assertEqual(myobj.part2, False)
        self.assertEqual(len(myobj.text), 11)
        self.assertEqual(len(myobj.adapters), 11)
        self.assertEqual(len(myobj.ordered), 11)
        self.assertEqual(myobj.start, 0)
        self.assertEqual(myobj.device, 22)

        # 3. Test methods
        self.assertEqual(myobj.get_part_one_differences(), 7 * 5)

        self.assertEqual(myobj.how_many_ways(), 8)

    def test_part_one(self):
        "Test part one example of Jolts object"

        # 1. Create Jolts object from text
        myobj = jolts.Jolts(text=aoc_10.from_text(PART_ONE_TEXT))

        # 2. Check the part one result
        self.assertEqual(myobj.part_one(verbose=False), PART_ONE_RESULT)

    def test_part_two(self):
        "Test part two example of Jolts object"

        # 1. Create Jolts object from text
        myobj = jolts.Jolts(part2=True, text=aoc_10.from_text(PART_TWO_TEXT))

        # 2. Check the part two result
        self.assertEqual(myobj.part_two(verbose=False), PART_TWO_RESULT)

# ----------------------------------------------------------------------
#                                                  module initialization
# ----------------------------------------------------------------------
if __name__ == '__main__':
    pass

# ======================================================================
# end                    t e s t _ j o l t s . p y                   end
# ======================================================================


# for문
"""
for 변수 in iterable값:
    반복할 코드
"""

li_1 = ["one", "two", "three"]
for i in li_1:
    print(i)
# 첫 번째 요소부터 마지막 요소까지 변수에 대입하면서 반복

s1 = "Hello"
for i in s1:
    print(i)

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for number in numbers:
    print(number)

numbers.reverse()
for number in numbers:
    print(number)

# range()
# range(끝 정수)
# 0 ~ 끝 정수 - 1
# range(시작, 끝)
# 시작 ~ 끝 - 1
# range(시작, 끝, 스텝)
# 시작 ~ 끝 - 1 까지인데 스텝만큼 차이나게

for i in range(10):
    print (i)

for i in range(1, 11):
    print(i)

for i in range(1, 21, 2):
    print(i)

# for문을 사용하여 2부터 30까지 출력해보세요.
for i in range(2, 31):
    print(i)

# for문을 사용하여 2부터 30까지 숫자 중 짝수만 출력해보세요.
for i in range(2, 31, 2): # 2 ~ 30 2씩 차이
    print(i)

for i in range(2, 31):
    if i % 2 == 1: # 홀수
        #continue
        pass # 아무것도 안 하고 그냥 넘어갈 때
    else : # 짝수
        print(i)

for i in range(2, 31):
    if i % 2 == 0: # 짝수
        print(i)

# for문을 사용하여 10부터 1까지 출력해보세요
for i in range(10, 0, -1):
    print(i)

for i in reversed(range(1, 11)):
    print(i)

for i in range(1, 11)[::-1]: # 슬라이싱
    print(i)

# 슬라이싱
# [시작인덱스 : 끝인덱스 : 방향]

money = 2000
price = 1000
coffee = 5

for i in range(coffee): # 0 ~ 4
    print("커피를 구매했습니다.")
    money -= price

    print("남은 커피 :", coffee - 1 - i)
    if money < price:
        break

for i in range(1, coffee + 1): # 1 ~ 5
    print("남은 커피 :", coffee - i) # 4 ~ 0

for i in range(coffee):
    coffee -= 1
    print("남은 커피 :", coffee) # 4 ~ 0

prices = [500, 700, 930]
money = int(input("돈: "))
for i in range(len(prices)):
    price = prices[i]
    print(money // price)
    print(money % price)

for price in prices: # prices 안에 들어있는 내용을 price에 할당해 바로 사용
    print(money // price)
    print(money % price)

scores=[]
for i in range(5):
    score = int(input("시험점수 : "))
    scores.append(score)

# 이중 for문
for i in range(1, 10): # 1 ~ 9
    print("2 *", i,"=",2*i)

for i in range(2, 10): # 2 ~ 9 첫 번째 for문이 먼저 실행됨
    print(i,"단")
    for j in range (1, 10):
        print(i,"*",j,"=", i*j)
    print("-------------") # i가 바뀌기 전에 들어가야 한다


from threading import Thread
import logging.config

import seaborn as sns
import matplotlib.pyplot as plt
from pylsl import resolve_byprop, StreamInlet

from muse_server import outlet_helper
from muse_server.outlet_helper import STREAM_TYPE, CHANNELS_NAMES, find_stream
from muse_stream_info import MuseStreamInfo
from fig_info import FigInfo

sns.set_style("whitegrid", {'axes.grid': False})

logger = logging.getLogger(__name__)

# sns.despine(left=True)

class EegVisualizer:
    def __init__(self, timeout=1):
        self.timeout = timeout
        self.stream_details = None
        self.fig_info = None
        self.timestamps = None

    def stop(self):
        self.fig_info.is_running = False

    def start(self):
        self.stream_details = find_stream()
        self.fig_info = FigInfo(self.stream_details.frequency, self.stream_details.channels_count)
        self.lunch_plot()

    def plot_graph(self):
        self.fig_info.plot(self.stream_details)

    def lunch_plot(self):
        plotting_thread = Thread(target=self.plot_graph)
        plotting_thread.daemon = False
        plotting_thread.start()
        plt.show()


import sys

from dcim.models import PowerFeed, PowerPanel, Rack
from startup_script_utils import load_yaml, pop_custom_fields, set_custom_fields_values

power_feeds = load_yaml("/opt/netbox/initializers/power_feeds.yml")

if power_feeds is None:
    sys.exit()

required_assocs = {"power_panel": (PowerPanel, "name")}

optional_assocs = {"rack": (Rack, "name")}

for params in power_feeds:
    custom_field_data = pop_custom_fields(params)

    for assoc, details in required_assocs.items():
        model, field = details
        query = {field: params.pop(assoc)}

        params[assoc] = model.objects.get(**query)

    for assoc, details in optional_assocs.items():
        if assoc in params:
            model, field = details
            query = {field: params.pop(assoc)}

            params[assoc] = model.objects.get(**query)

    power_feed, created = PowerFeed.objects.get_or_create(**params)

    if created:
        set_custom_fields_values(power_feed, custom_field_data)

        print("⚡ Created Power Feed", power_feed.name)


import sys
import re
import random

import constants as constants_values

def key_gen(size=32):
    key = ''
    x = round(random.uniform(0, 1), 3)
    r = round(random.uniform(0, 4), 3)

    for i in range(size):
        x=r*x*(1-x) #logistic map
        key += convert_decimel_to_hexa(int((x*pow(10,16))%256)) #key=(x*10^16)%256
    return key

def normal_serpent_key_gen(size=32):
    key = ''
    x = round(random.uniform(0, 1), 3)
    r = round(random.uniform(0, 4), 3)

    for i in range(size):
        x=r*x*(1-x) #logistic map
        key += convert_decimel_to_hexa(int((x*pow(10,16))%256)) #key=(x*10^16)%256
    return key

def convert_decimel_to_hexa(decimalValue):
    return hex(decimalValue).replace('0x', '')

def convert_decimel_to_binary64(decimalValue):
    return str(dec_to_bin(decimalValue)).zfill(64)

def dec_to_bin(x):
    return int(bin(x)[2:])

def random_iv(length):
    iv = ""
    for i in range(length):
        iv +=  str(random.randint(0, 1))
    return iv

def reverse(toreverse):
    out = ""
    for i in range(int((len(toreverse)/2))):
        out += toreverse[len(toreverse)-i*2-2:len(toreverse)-i*2]
    return out

def S(box, input):
    """Apply S-box number 'box' to 4-bit bitstring 'input' and return a
    4-bit bitstring as the result."""

    return SBoxBitstring[box%8][input]
    # There used to be 32 different S-boxes in serpent-0. Now there are
    # only 8, each of which is used 4 times (Sboxes 8, 16, 24 are all
    # identical to Sbox 0, etc). Hence the %8.

def SInverse(box, output):
    """Apply S-box number 'box' in reverse to 4-bit bitstring 'output' and
    return a 4-bit bitstring (the input) as the result."""

    return SBoxBitstringInverse[box%8][output]

def SHat(box, input):
    """Apply a parallel array of 32 copies of S-box number 'box' to the
    128-bit bitstring 'input' and return a 128-bit bitstring as the
    result."""

    result = ""
    for i in range(32):
        result = result + S(box, input[4*i:4*(i+1)])
    return result

def SHatInverse(box, output):
    """Apply, in reverse, a parallel array of 32 copies of S-box number
    'box' to the 128-bit bitstring 'output' and return a 128-bit bitstring
    (the input) as the result."""

    result = ""
    for i in range(32):
        result = result + SInverse(box, output[4*i:4*(i+1)])
    return result

def SBitslice(box, words):
    """Take 'words', a list of 4 32-bit bitstrings, least significant word
    first. Return a similar list of 4 32-bit bitstrings obtained as
    follows. For each bit position from 0 to 31, apply S-box number 'box'
    to the 4 input bits coming from the current position in each of the
    items in 'words'; and put the 4 output bits in the corresponding
    positions in the output words."""

    result = ["", "", "", ""]
    for i in range(32): # ideally in parallel
        quad = S(box, words[0][i] + words[1][i] + words[2][i] + words[3][i])
        for j in range(4):
            result[j] = result[j] + quad[j]
    return result

def SBitsliceInverse(box, words):
    """Take 'words', a list of 4 32-bit bitstrings, least significant word
    first. Return a similar list of 4 32-bit bitstrings obtained as
    follows. For each bit position from 0 to 31, apply S-box number 'box'
    in reverse to the 4 output bits coming from the current position in
    each of the items in the supplied 'words'; and put the 4 input bits in
    the corresponding positions in the returned words."""

    result = ["", "", "", ""]
    for i in range(32): # ideally in parallel
        quad = SInverse(
            box, words[0][i] + words[1][i] + words[2][i] + words[3][i])
        for j in range(4):
            result[j] = result[j] + quad[j]
    return result

def LT(input):
    """Apply the table-based version of the linear transformation to the
    128-bit string 'input' and return a 128-bit string as the result."""

    if len(input) != 128:
        raise ValueError ("input to inverse LT is not 128 bit long")

    result = ""
    for i in range(len(constants_values.LTTable)):
        outputBit = "0"
        for j in constants_values.LTTable[i]:
            outputBit = xor(outputBit, input[j])
        result = result + outputBit
    return result

def LTInverse(output):
    """Apply the table-based version of the inverse of the linear
    transformation to the 128-bit string 'output' and return a 128-bit
    string (the input) as the result."""

    if len(output) != 128:
        raise ValueError ("input to inverse LT is not 128 bit long")

    result = ""
    for i in range(len(constants_values.LTTableInverse)):
        inputBit = "0"
        for j in constants_values.LTTableInverse[i]:
            inputBit = xor(inputBit, output[j])
        result = result + inputBit
    return result

def LTBitslice(X):
    """Apply the equations-based version of the linear transformation to
    'X', a list of 4 32-bit bitstrings, least significant bitstring first,
    and return another list of 4 32-bit bitstrings as the result."""

    X[0] = rotateLeft(X[0], 13)
    X[2] = rotateLeft(X[2], 3)
    X[1] = xor(X[1], X[0], X[2])
    X[3] = xor(X[3], X[2], shiftLeft(X[0], 3))
    X[1] = rotateLeft(X[1], 1)
    X[3] = rotateLeft(X[3], 7)
    X[0] = xor(X[0], X[1], X[3])
    X[2] = xor(X[2], X[3], shiftLeft(X[1], 7))
    X[0] = rotateLeft(X[0], 5)
    X[2] = rotateLeft(X[2], 22)

    return X

def LTBitsliceInverse(X):
    """Apply, in reverse, the equations-based version of the linear
    transformation to 'X', a list of 4 32-bit bitstrings, least significant
    bitstring first, and return another list of 4 32-bit bitstrings as the
    result."""

    X[2] = rotateRight(X[2], 22)
    X[0] = rotateRight(X[0], 5)
    X[2] = xor(X[2], X[3], shiftLeft(X[1], 7))
    X[0] = xor(X[0], X[1], X[3])
    X[3] = rotateRight(X[3], 7)
    X[1] = rotateRight(X[1], 1)
    X[3] = xor(X[3], X[2], shiftLeft(X[0], 3))
    X[1] = xor(X[1], X[0], X[2])
    X[2] = rotateRight(X[2], 3)
    X[0] = rotateRight(X[0], 13)

    return X

def IP(input):
    """Apply the Initial Permutation to the 128-bit bitstring 'input'
    and return a 128-bit bitstring as the result."""

    return applyPermutation(constants_values.IPTable, input)

def FP(input):
    """Apply the Final Permutation to the 128-bit bitstring 'input'
    and return a 128-bit bitstring as the result."""

    return applyPermutation(constants_values.FPTable, input)

def IPInverse(output):
    """Apply the Initial Permutation in reverse."""

    return FP(output)

def FPInverse(output):
    """Apply the Final Permutation in reverse."""

    return IP(output)

def applyPermutation(permutationTable, input):
    """Apply the permutation specified by the 128-element list
    'permutationTable' to the 128-bit bitstring 'input' and return a
    128-bit bitstring as the result."""

    if len(input) != len(permutationTable):
        raise ValueError ("input size (%d) doesn't match perm table size (%d)"% (len(input), len(permutationTable)))

    result = ""
    for i in range(len(permutationTable)):
        result = result + input[permutationTable[i]]
    return result

def R(i, BHati, KHat):
    """Apply round 'i' to the 128-bit bitstring 'BHati', returning another
    128-bit bitstring (conceptually BHatiPlus1). Do this using the
    appropriately numbered subkey(s) from the 'KHat' list of 33 128-bit
    bitstrings."""

    #O.show("BHati", BHati, "(i=%2d) BHati" % i)

    xored = xor(BHati, KHat[i])
    #O.show("xored", xored, "(i=%2d) xored" % i)

    SHati = SHat(i, xored)
    #O.show("SHati", SHati, "(i=%2d) SHati" % i)

    if 0 <= i <= constants_values.r-2:
        BHatiPlus1 = LT(SHati)
    elif i == constants_values.r-1:
        BHatiPlus1 = xor(SHati, KHat[constants_values.r])
    else:
        raise ValueError ( "round %d is out of 0..%d range" % (i, constants_values.r-1))
    #O.show("BHatiPlus1", BHatiPlus1, "(i=%2d) BHatiPlus1" % i)

    return BHatiPlus1

def RInverse(i, BHatiPlus1, KHat):
    """Apply round 'i' in reverse to the 128-bit bitstring 'BHatiPlus1',
    returning another 128-bit bitstring (conceptually BHati). Do this using
    the appropriately numbered subkey(s) from the 'KHat' list of 33 128-bit
    bitstrings."""

    #O.show("BHatiPlus1", BHatiPlus1, "(i=%2d) BHatiPlus1" % i)

    if 0 <= i <= constants_values.r-2:
        SHati = LTInverse(BHatiPlus1)
    elif i == constants_values.r-1:
        SHati = xor(BHatiPlus1, KHat[constants_values.r])
    else:
        raise ValueError("round %d is out of 0..%d range" % (i, constants_values.r-1))
    #O.show("SHati", SHati, "(i=%2d) SHati" % i)

    xored = SHatInverse(i, SHati)
    #O.show("xored", xored, "(i=%2d) xored" % i)

    BHati = xor(xored, KHat[i])
    #O.show("BHati", BHati, "(i=%2d) BHati" % i)

    return BHati

def RBitslice(i, Bi, K):
    """Apply round 'i' (bitslice version) to the 128-bit bitstring 'Bi' and
    return another 128-bit bitstring (conceptually B i+1). Use the
    appropriately numbered subkey(s) from the 'K' list of 33 128-bit
    bitstrings."""

    #O.show("Bi", Bi, "(i=%2d) Bi" % i)

    # 1. Key mixing
    xored = xor (Bi, K[i])
    #O.show("xored", xored, "(i=%2d) xored" % i)

    # 2. S Boxes
    Si = SBitslice(i, quadSplit(xored))
    # Input and output to SBitslice are both lists of 4 32-bit bitstrings
    #O.show("Si", Si, "(i=%2d) Si" % i, "tlb")

    # 3. Linear Transformation
    if i == constants_values.r-1:
        # In the last round, replaced by an additional key mixing
        BiPlus1 = xor(quadJoin(Si), K[constants_values.r])
    else:
        BiPlus1 = quadJoin(LTBitslice(Si))
    # BIPlus1 is a 128-bit bitstring
    #O.show("BiPlus1", BiPlus1, "(i=%2d) BiPlus1" % i)

    return BiPlus1

def RBitsliceInverse(i, BiPlus1, K):
    """Apply the inverse of round 'i' (bitslice version) to the 128-bit
    bitstring 'BiPlus1' and return another 128-bit bitstring (conceptually
    B i). Use the appropriately numbered subkey(s) from the 'K' list of 33
    128-bit bitstrings."""

    #O.show("BiPlus1", BiPlus1, "(i=%2d) BiPlus1" % i)

    # 3. Linear Transformation
    if i == constants_values.r-1:
        # In the last round, replaced by an additional key mixing
        Si = quadSplit(xor(BiPlus1, K[constants_values.r]))
    else:
        Si = LTBitsliceInverse(quadSplit(BiPlus1))
    # SOutput (same as LTInput) is a list of 4 32-bit bitstrings

    #O.show("Si", Si, "(i=%2d) Si" % i, "tlb")

    # 2. S Boxes
    xored = SBitsliceInverse(i, Si)
    # SInput and SOutput are both lists of 4 32-bit bitstrings

    #O.show("xored", xored, "(i=%2d) xored" % i)

    # 1. Key mixing
    Bi = xor (quadJoin(xored), K[i])

    #O.show("Bi", Bi, "(i=%2d) Bi" % i)

    return Bi

def makeSubkeys(userKey):
    """Given the 256-bit bitstring 'userKey' (shown as K in the paper, but
    we can't use that name because of a collision with K[i] used later for
    something else), return two lists (conceptually K and KHat) of 33
    128-bit bitstrings each."""

    # Because in Python I can't index a list from anything other than 0,
    # I use a dictionary instead to legibly represent the w_i that are
    # indexed from -8.

    # We write the key as 8 32-bit words w-8 ... w-1
    # ENOTE: w-8 is the least significant word

    w = {}

    for i in range(-8, 0):
        w[i] = userKey[(i+8)*32:(i+9)*32]
        #O.show("wi", w[i], "(i=%2d) wi" % i)

    # We expand these to a prekey w0 ... w131 with the affine recurrence
    for i in range(132):
        w[i] = rotateLeft(xor(w[i-8], w[i-5], w[i-3], w[i-1],bitstring(constants_values.phi, 32), bitstring(i,32)),11)
        #O.show("wi", w[i], "(i=%2d) wi" % i)

    # The round keys are now calculated from the prekeys using the S-boxes
    # in bitslice mode. Each k[i] is a 32-bit bitstring.
    k = {}
    for i in range(constants_values.r+1):
        whichS = (constants_values.r + 3 - i) % constants_values.r
        k[0+4*i] = ""
        k[1+4*i] = ""
        k[2+4*i] = ""
        k[3+4*i] = ""
        for j in range(32): # for every bit in the k and w words
            # ENOTE: w0 and k0 are the least significant words, w99 and k99
            # the most.
            input = w[0+4*i][j] + w[1+4*i][j] + w[2+4*i][j] + w[3+4*i][j]
            output = S(whichS, input)
            for l in range(4):
                k[l+4*i] = k[l+4*i] + output[l]

    # We then renumber the 32 bit values k_j as 128 bit subkeys K_i.
    K = []
    for i in range(33):
        # ENOTE: k4i is the least significant word, k4i+3 the most.
        K.append(k[4*i] + k[4*i+1] + k[4*i+2] + k[4*i+3])

    # We now apply IP to the round key in order to place the key bits in
    # the correct column
    KHat = []
    for i in range(33):
        KHat.append(IP(K[i]))

        #O.show("Ki", K[i], "(i=%2d) Ki" % i)
        #O.show("KHati", KHat[i], "(i=%2d) KHati" % i)

    return K, KHat

def makeLongKey(k):
    """Take a key k in bitstring format. Return the long version of that
    key."""

    l = len(k)
    if l % 32 != 0 or l < 64 or l > 256:
        raise ValueError("Invalid key length (%d bits)" % l)
    if l == 256:
        return k
    else:
        return k + "1" + "0"*(256 -l -1)

def bitstring(n, minlen=1):
    """Translate n from integer to bitstring, padding it with 0s as
    necessary to reach the minimum length 'minlen'. 'n' must be >= 0 since
    the bitstring format is undefined for negative integers.  Note that,
    while the bitstring format can represent arbitrarily large numbers,
    this is not so for Python's normal integer type: on a 32-bit machine,
    values of n >= 2^31 need to be expressed as python long integers or
    they will "look" negative and won't work. E.g. 0x80000000 needs to be
    passed in as 0x80000000L, or it will be taken as -2147483648 instead of
    +2147483648L.
    EXAMPLE: bitstring(10, 8) -> "01010000"
    """

    if minlen < 1:
        raise ValueError("a bitstring must have at least 1 char")
    if n < 0:
        raise ValueError("bitstring representation undefined for neg numbers")

    result = ""
    while n > 0:
        if n & 1:
            result = result + "1"
        else:
            result = result + "0"
        n = n >> 1
    if len(result) < minlen:
        result = result + "0" * (minlen - len(result))
    return result

def binaryXor(n1, n2):
    """Return the xor of two bitstrings of equal length as another
    bitstring of the same length.
    EXAMPLE: binaryXor("10010", "00011") -> "10001"
    """

    if len(n1) != len(n2):

        raise ValueError("can't xor bitstrings of different " + "lengths (%d and %d)" % (len(n1), len(n2)))
    # We assume that they are genuine bitstrings instead of just random
    # character strings.

    result = ""

    for i in range(len(n1)):
        if n1[i] == n2[i]:
            result = result + "0"
        else:
            result = result + "1"
    return result

def xor(*args):
    """Return the xor of an arbitrary number of bitstrings of the same
    length as another bitstring of the same length.
    EXAMPLE: xor("01", "11", "10") -> "00"
    """

    if args == []:
        raise ValueError("at least one argument needed")

    result = args[0]
    for arg in args[1:]:
        result = binaryXor(result, arg)
    return result

def rotateLeft(input, places):
    """Take a bitstring 'input' of arbitrary length. Rotate it left by
    'places' places. Left means that the 'places' most significant bits are
    taken out and reinserted as the least significant bits. Note that,
    because the bitstring representation is little-endian, the visual
    effect is actually that of rotating the string to the right.
    EXAMPLE: rotateLeft("000111", 2) -> "110001"
    """

    p = places % len(input)
    return input[-p:] + input[:-p]

def rotateRight(input, places):
    return rotateLeft(input, -places)

def shiftLeft(input, p):
    """Take a bitstring 'input' of arbitrary length. Shift it left by 'p'
    places. Left means that the 'p' most significant bits are shifted out
    and dropped, while 'p' 0s are inserted in the the least significant
    bits. Note that, because the bitstring representation is little-endian,
    the visual effect is actually that of shifting the string to the
    right. Negative values for 'p' are allowed, with the effect of shifting
    right instead (i.e. the 0s are inserted in the most significant bits).
    EXAMPLE: shiftLeft("000111", 2) -> "000001"
             shiftLeft("000111", -2) -> "011100"
    """

    if abs(p) >= len(input):
        # Everything gets shifted out anyway
        return "0" * len(input)
    if p < 0:
        # Shift right instead
        return  input[-p:] + "0" * len(input[:-p])
    elif p == 0:
        return input
    else: # p > 0, normal case
        return "0" * len(input[-p:]) + input[:-p]

def shiftRight(input, p):
    """Take a bitstring 'input' and shift it right by 'p' places. See the
    doc for shiftLeft for more details."""

    return shiftLeft(input, -p)

def keyLengthInBitsOf(k):
    """Take a string k in I/O format and return the number of bits in it."""

    return len(k) * 4

def bitstring2hexstring(b):
    """Take bitstring 'b' and return the corresponding hexstring."""

    result = ""
    l = len(b)
    if l % 4:
        b = b + "0" * (4-(l%4))
    for i in range(0, len(str(b)), 4):
        result = result + constants_values.bin2hex[b[i:i+4]]
    return reverseString(result)

def hexstring2bitstring(h):
    """Take hexstring 'h' and return the corresponding bitstring."""

    result = ""
    for c in reverseString(h):
        result = result + constants_values.hex2bin[c]

    return result

def reverseString(s):
    l = list(s)
    l.reverse()
    return "".join(l)

def quadSplit(b128):
    """Take a 128-bit bitstring and return it as a list of 4 32-bit
    bitstrings, least significant bitstring first."""

    if len(b128) != 128:
        raise ValueError("must be 128 bits long, not " + len(b128))
    result = []
    for i in range(4):
        result.append(b128[(i*32):(i+1)*32])
    return result

def quadJoin(l4x32):
    """Take a list of 4 32-bit bitstrings and return it as a single 128-bit
    bitstring obtained by concatenating the internal ones."""

    if len(l4x32) != 4:
        raise ValueError("need a list of 4 bitstrings, not " + len(l4x32))

    return l4x32[0] + l4x32[1] + l4x32[2] + l4x32[3]

def convertToBitstring(input, numBits):
    """Take a string 'input', theoretically in std I/O format, but in
    practice liable to contain any sort of crap since it's user supplied,
    and return its bitstring representation, normalised to numBits
    bits. Raise the appropriate variant of ValueError (with explanatory
    message) if anything can't be done (this includes the case where the
    'input', while otherwise syntactically correct, can't be represented in
    'numBits' bits)."""

    input = input.lower()

    if re.match("^[0-9a-f]+$", input):
        bitstring = hexstring2bitstring(input)
        #print('BitString: '+ bitstring) # Unknown = each number is 0000 bits for the key
    else:
        raise ValueError ("%s is not a valid hexstring" % input)

    # assert: bitstring now contains the bitstring version of the input

    #print('bitstring[numBits:]: '+ bitstring[numBits:])

    if len(bitstring) > numBits:
        # Last chance: maybe it's got some useless 0s...
        if re.match("^0+$", bitstring[numBits:]):
            bitstring = bitstring[:numBits]
        else:
            raise ValueError ("input too large to fit in %d bits" % numBits)
    else:
        bitstring = bitstring + "0" * (numBits-len(bitstring))

    return bitstring

def prepare(input):
    result = ""
    for c in reverseString(input.lower()):
        result = constants_values.ebin2hex[constants_values.hex2bin[c]] + result

    return reverseString(result)

SBoxBitstring = []
SBoxBitstringInverse = []
for line in constants_values.SBoxDecimalTable:
    dict = {}
    inverseDict = {}
    for i in range(len(line)):
        index = bitstring(i, 4)
        value = bitstring(line[i], 4)
        dict[index] = value
        inverseDict[value] = index
    SBoxBitstring.append(dict)
    SBoxBitstringInverse.append(inverseDict)

def helpExit(message = None):
    print (constants_values.help)
    if message:
        print ("ERROR:", message)
    sys.exit()


#Convolución Discreta con herramientas de conversión binaria
#Juice930
#artvel_0412@hotmail.com
import numpy as np
def C1(x): #Complemento a 1
    return list(map(lambda n:n^1,x))

def C2(x):
    if type(x[0])==list:   return list(map(lambda n:__C2(n),x))
    else:               return __C2(x)
def __C2(x): #Complemento a 2
    if not (1 in x):
        return [0]*len(x)
    x=C1(x)
    x.reverse()
    for i,j in enumerate(x):
        x[i]^=1
        if x[i]==1:
            break
    x.reverse()
    return x
def hexcon(x):
    if type(x[0])==list:   return list(map(lambda n:hex(int(__bincon(n)[2:],2)),x))
    else:               return hex(int(__bincon(x)[2:],2))
def bincon(x):
    if type(x[0])==list:   return list(map(lambda n:__bincon(n),x))
    else:               return __bincon(x)
def __bincon(x):
    res=str()
    for i in x:
        res+=str(i)
    return bin(int(res,2))
def IE3(x):
    if type(x)==list:   return list(map(lambda n:__IE3(n),x))
    else:               return __IE3(x)

def __IE3(num):
    if num==0 or abs(num)<2**-126:
        return [0]*32
    elif num>2**128-1:
        return [0]+[1 for i in range(31)]
    elif num<-2**128-1:
        return [1]+[1 for i in range(31)]
    s=0
    if num<0:
        s=1
        num=-num
    if 0<=num<2**64:
        L=int(np.log2(num)+1)
        exp=Qi(int(127+np.log2(num)),0,8)
    else:
        L=64+int(np.log2(num/(2**64))+1)
        exp=Qi(int(127+64+np.log2(num/2**64)),0,8)

    if L>=1:
        aux=Qi(num*2**-L,24,24)[1::]
    else:
        aux=Qi(num*2**(-L-1),24,24)[1::]
    return [s]+exp+aux

def InvIE3(arr):
    if type(arr[0])==list:  return list(map(lambda n:__InvIE3(n),arr))
    else:                   return __InvIE3(arr)

def __InvIE3(arr):
    exp=invQi(arr[1:9],0)-127
    mant=invQi([1]+arr[9::],23)
    return ((-1)**arr[0])*(2**exp)*mant

def Qi(x,i,L,signed=0): #Convertir número o números de decimal a arreglo binario
    if type(x)==list:   return list(map(lambda n:__Qi(n,i,L,signed),x))
    else:               return __Qi(x,i,L,signed=0)

def __Qi(x,i,L,signed=0):
    if abs(x)>2**(L-i) and L>i and i<0: return 'error'
    res=bin(int(x*2**i))
    Long=len(res[res.find('b')+1:])
    if res[0]=='-':
        return [1]*(L-Long)+C2([int(i) for i in res[res.find('b')+1:]])
    elif signed!=0:
        return [0]*(L-Long)+list([int(i) for i in res[res.find('b')+1:]])
    return [0]*(L-Long)+list([int(i) for i in res[res.find('b')+1:]])

def invQi(num,i,signed=0):  #Convierte de arreglo o arreglos binarios a decimal
    if type(num[0])==list: return list(map(lambda n:__invQi(n,i,signed),num))
    else:               return __invQi(num,i,signed)
def __invQi(num,i,signed=0):#Sirve para un solo arreglo binario a decimal
    if(type(num)!=list): return 'error'
    #TODO:Checar con el signado!!!
    if signed!=0:
        if num[0]==1:
            num=C2(num)
            return -sum([k*(2**(len(num)-i-j-1)) for j,k in enumerate(num)])
        else:
            return sum([k*(2**(len(num)-i-j-1)) for j,k in enumerate(num)])
    return sum([k*(2**(len(num)-i-j-1)) for j,k in enumerate(num)])

def convol(x,y):            #Convolución discreta de dos arreglos
    res=[0]*(len(x)+len(y)-1)
    for n in range(len(res)):
        for k in range(n+1):
            try:
                res[n]+=x[k]*y[n-k]
            except:
                res[n]+=0
    return res

def corr(x,y=[]):           #Correlación o Autocorrelación
    if y==[]:               #Si solo se dio un argumento se asume autocorrelación
        return convol(x,x[::-1])
    return convol(x,y[::-1])

def syntheticdivision(dividend, divisor,it):    #Código adaptado a nuestras necesidades
    '''Fast polynomial division by using Extended Synthetic Division. Also works with non-monic polynomials.'''
    # dividend and divisor are both polynomials, which are here simply lists of coefficients. Eg: x^2 + 3x + 5 will be represented as [1, 3, 5]
    h = []
    out = list(dividend) # Copy the dividend
    normalizer = divisor[0]
    for k in range(it-1):
        for i in range(len(dividend)-(len(divisor)-1)):
            out[i] /= normalizer
            coef = out[i]
            if coef != 0:
                for j in range(1, len(divisor)):
                    out[i + j] += -divisor[j] * coef
        separator = -(len(divisor)-1)
        h.append(out[:separator][0]*(-1)**k)
        out=list(map(lambda n:-n,out[separator:]))+[0]
    return np.array(h)

def getEcenDif(y):
    h=[y[0]]
    for i in range(1,len(y)):
        h.append(y[i]-sum([y[j]*h[-j] for j in range(1,i)]))
    return np.array(h)

def evaluate(it,a):
    h=[a[0]]
    for i in range(1,len(a)):
        h.append(sum([a[j]*h[-j] for j in range(1,i+1)]))
    for i in range(len(a),it):
        h.append(sum([a[j]*h[-j] for j in range(1,len(a))]))
    return np.array(h)

def Wkn(k,N=32):
    return np.exp(-2j*np.pi*k/N)

def rev(a):
    a.reverse()
    return a

def indix(N):
    L=int(np.log2(N)-1)
    index=[]
    for i in range(N//2):
        index.append(invQi(rev(Qi(i,0,L)),0))
    return index,L

def __fft(h,N,radix):
    y=h.copy()
    for i in range(0,N,2*radix):
        for j in range(radix):
            y[i+j]+=h[i+j+radix]*Wkn(j*N//(2*radix),N)
            y[i+j+radix]=h[i+j]-h[i+j+radix]*Wkn(j*N//(2*radix),N)
    return y

def fft(h):
    N=len(h)
    index,L=indix(N)
    y=h.copy()
    h=[]
    for i in index:
        h.append(y[i]+y[i+N//2])
        h.append(y[i]-y[i+N//2])
    print("Iteración número 0")
    for i,j in list(enumerate(h)):
        print(i,j)
    for i in range(1,L+1):
        h=__fft(h,N,2**i)
        print("Iteración número "+str(i))
        for j,k in list(enumerate(h)):
            print(j.k)

    return h


"""
You have been recruited by your friend, a linguistics enthusiast, to create a utility tool that can perform analysis on a given piece of text. Complete the class
'analysedText' with the following methods -

<ul>
    <li> Constructor - Takes argument 'text',makes it lower case and removes all punctuation. Assume only the following punctuation is used - period (.), exclamation mark (!), comma (,) and question mark (?). Store the argument in "fmtText"
    <li> freqAll - returns a dictionary of all unique words in the text along with the number of their occurences.
    <li> freqOf - returns the frequency of the word passed in argument.
</ul>
 """
class analysedText(object):
    def __init__(self, text):
         formattedText = text.replace('.','').replace('!','').replace('?','').replace(',','')
         formattedText = formattedText.lower()
         self.fmtText = formattedText

    def freqAll(self):
        wordList = self.fmtText.split(' ')

        freqMap = {}
        for word in set(wordList):
            freqMap[word] = wordList.count(word)

        print(freqMap)
        return freqMap

    def freqOf(self, word):
        freqDict = self.freqAll()

        if word in freqDict:
            print(freqDict[word])
            return freqDict[word]
        else:
            return 0

text = analysedText('Hello, what the point?! If you know that hello have to be a start. That why.')
print(text)


from django.conf.urls import patterns, include, url
from django.contrib import admin

from monitor import views

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'stockman.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),

    url(r'^$', views.get_index),

    url(r'^insert_symbol/$', views.insert_symbol),
    url(r'^insert_reminder/$', views.insert_reminder),

    url(r'^get_attrib_form', views.get_attrib_form),
    url(r'^get_triggered_reminders/$', views.get_triggered_reminders),

    # url(r'^scripts/monitor.js', provide_monitorjs),

    url(r'^print_request_info/$', views.print_request_info),
    url(r'^scratch/$', views.scratch),
    url(r'^get_form/$', views.get_form),

    url(r'^admin/', include(admin.site.urls)),

    url(r'^(?P<dname>[a-zA-Z]+)/(?P<fname>[a-zA-Z.]+)', views.provide_script),
)


"""
Day 17 Part 1

A bit of work to implement but worked 1st first time
"""
map_of_cores = []

# Create a list of lists to become an array of seats.
f = open("day17input.txt", "r")
for file_line in f:
    map_of_cores.append(list(file_line.rstrip()))
f.close()

max_x = len(map_of_cores[1])
max_y = len(map_of_cores)
max_z = 1
min_x = -1
min_y = -1
min_z = -1
active_cores = []

# Populate starting list of active cores.
for i in range(max_y):
    for j in range(max_x):
        if map_of_cores[i][j] == '#':
            active_cores.append([j, i, 0])

# Works out if the core is now active as a result of the previous set of active cores.
def cell_is_now_active(coords: list, _active_cores: list) -> bool:
    num_adj_active = 0
    for x in range(coords[0] - 1, coords[0] + 2):
        for y in range(coords[1] - 1, coords[1] + 2):
            for z in range(coords[2] - 1, coords[2] + 2):
                if x == coords[0] and y == coords[1] and z == coords[2]:
                    continue
                if [x, y, z] in _active_cores:
                    num_adj_active += 1

    if num_adj_active == 3:
        return True

    if coords in _active_cores and num_adj_active == 2:
        return True

    return False

# Activates/deactivates cores based on criteria. Dimensions of search area passed in.
def run_cycle(_dimensions: list, _active_cores: list) -> list:
    new_active_cores = []
    for x in range(_dimensions[0], _dimensions[1] + 1):
        for y in range(_dimensions[2], _dimensions[3] + 1):
            for z in range(_dimensions[4], _dimensions[5] + 1):
                if cell_is_now_active([x, y, z], _active_cores):
                    new_active_cores.append([x, y, z])

    return new_active_cores

itr = 0
while itr < 6:
    dimensions = [min_x, max_x, min_y, max_y, min_z, max_z]
    active_cores = run_cycle(dimensions, active_cores.copy())
    min_x -= 1
    min_y -= 1
    min_z -= 1
    max_x += 1
    max_y += 1
    max_z += 1
    itr += 1

print('No. active cores: ' + str(len(active_cores)))