"""
This module contains the implementation of the Classes: BaseEnvironment, BaseWrapper, BaseObservationWrapper, BaseActionWrapper,
BaseRewardWrapper, BaseGridWorld, BaseCarOnHill, BaseCartPole, BaseInvertedPendulum and LQG.

Then there are the Mujoco Environments Wrappers: BaseMujoco, BaseHalfCheetah, BaseAnt, BaseHopper, BaseHumanoid, BaseSwimmer,
BaseWalker2d

The Class BaseEnvironment inherits from the Class AbstractUnit and from ABC.

The Class BaseEnvironment is an abstract Class used as base class for all types of environments.

The Class BaseWrapper is used as generic wrapper Class. The Classes BaseObservationWrapper, BaseActionWrapper and
BaseRewardWrapper are abstract Classes, that when sub-classed can be used to wrap something specific of an environment.

The Classes BaseGridWorld, BaseCarOnHill, BaseCartPole, BaseInvertedPendulum simply wrap the corresponding Classes of MushroomRL
but they are changed so to inherit from the Class BaseEnvironment so that they can be used in this library.

The Class LQG is a re-adaptation of code copied from: https://github.com/T3p/potion/blob/master/potion/envs/lq.py

The Classes BaseHalfCheetah, BaseAnt, BaseHopper, BaseHumanoid, BaseSwimmer and BaseWalker2d inherit from the Class BaseMujoco
and are simply wrappers of the corresponding OpenAI gym Classes.
"""

from abc import ABC, abstractmethod
import numpy as np
import scipy
import math

from gym.envs.mujoco.half_cheetah_v3 import HalfCheetahEnv
from gym.envs.mujoco.ant_v3 import AntEnv
from gym.envs.mujoco.hopper_v3 import HopperEnv
from gym.envs.mujoco.humanoid_v3 import HumanoidEnv
from gym.envs.mujoco.swimmer_v3 import SwimmerEnv
from gym.envs.mujoco.walker2d_v3 import Walker2dEnv

from mushroom_rl.utils.spaces import Box
from mushroom_rl.core.environment import MDPInfo
from mushroom_rl.environments import GridWorld, CarOnHill, CartPole, InvertedPendulum

from ARLO.abstract_unit.abstract_unit import AbstractUnit

class BaseEnvironment(AbstractUnit, ABC):
    """
    This is the base environment Class based on the OpenAI Gym class. Part of this class is a re-adaptation of code copied from:
    -OpenAI gym:
    cf. https://github.com/openai/gym/blob/master/gym/core.py

    -MushroomRL:
    cf. https://github.com/MushroomRL/mushroom-rl/blob/dev/mushroom_rl/core/environment.py

    This can be sub-classed by the user to create their own specific environment.

    You must use environment spaces from  MushroomRL (e.g: Box, Discrete).

    This Class is an abstract Class and it inherits from the Class AbstractUnit.
    """

    def __init__(self, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3, n_jobs=1,
                 job_type='process'):
        """
        Non-Parameters Members
        ----------------------
        observation_space: This must be a space from MushroomRL like Box, Discrete.

        action_space: This must be a space from MushroomRL like Box, Discrete.

        gamma: This is the value of the gamma of the MDP, that is in this Class.

        horizon: This is the horizon of the MDP, that is in this Class.

        The other parameters and non-parameters members are described in the Class AbstractUnit.
        """

        super().__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode, checkpoint_log_path=checkpoint_log_path,
                         verbosity=verbosity, n_jobs=n_jobs, job_type=job_type)

        self.action_space = None
        self.observation_space = None
        self.gamma = None
        self.horizon = None

    def __repr__(self):
         return 'BaseEnvironment('+'observation_space='+str(self.observation_space)+', action_space='+str(self.action_space)\
                +', gamma='+str(self.gamma)+', horizon='+str(self.horizon)+', obj_name='+str(self.obj_name)\
                +', seeder='+str(self.seeder)+', local_prng='+str(self.local_prng)+', log_mode='+str(self.log_mode)\
                +', checkpoint_log_path='+str(self.checkpoint_log_path)+', verbosity='+str(self.verbosity)\
                +', n_jobs='+str(self.n_jobs)+', job_type='+str(self.job_type)+', logger='+str(self.logger)+')'

    @abstractmethod
    def step(self, action):
        """
        Method used to run one step of the environment dynamics.
        """

        raise NotImplementedError

    @abstractmethod
    def reset(self, state=None):
        """
        Method used to reset the environment.
        """

        raise NotImplementedError

    @abstractmethod
    def render(self, mode='human'):
        """
        Method used to render an environment.
        """

        raise NotImplementedError

    def close(self):
        """
        Method used to perform necessary cleanup.
        """

        pass

    def seed(self, seed=None):
        """
        Method used to seed the environment.
        """

        return

    def stop(self):
        """
        Method used to stop an MDP. This is needed for backward compatibility with MushroomRL.
        """

        pass

    def unwrapped(self):
        """
        This method completely unwraps the env contained in the class.

        Returns:
        ----------
        self: The base non-wrapped env instance
        """

        return self

    @property
    def info(self):
        """
        Property method that constructs an object of Class mushroom_rl.environment.MDPInfo
        """

        #each block must modify the observation_space and action_space according to the transformation they did
        return MDPInfo(observation_space=self.observation_space, action_space=self.action_space, gamma=self.gamma,
                       horizon=self.horizon)

    def _sample_from_box(self, space):
        """
        Parameters
        ----------
        space: The space to which to sample from. It must be an object of Class Box.

        This method was copied from OpenAI gym: cf. https://github.com/openai/gym/blob/master/gym/spaces/box.py

        Generates a single random sample inside of the Box. In creating a sample of the box, each coordinate is sampled according
        to the form of the interval:
        * [a, b] : uniform distribution
        * [a, inf) : shifted exponential distribution
        * (-inf, b] : shifted negative exponential distribution
        * (-inf, inf) : normal distribution
        """

        if(not isinstance(space, Box)):
            exc_msg = 'The method \'_sample_from_box\' can only be applied on \'Box\' spaces!'
            self.logger.exception(msg=exc_msg)
            raise TypeError(exc_msg)
        else:
            bounded_below = -np.inf < space.low
            bounded_above = np.inf > space.high

            if(space.high.dtype.kind == 'f'):
                high = space.high
            else:
                high = space.high.astype('int64') + 1

            sample = np.empty(space.shape)

            #Masking arrays which classify the coordinates according to interval type
            unbounded = ~bounded_below & ~bounded_above
            upp_bounded = ~bounded_below & bounded_above
            low_bounded = bounded_below & ~bounded_above
            bounded = bounded_below & bounded_above

            #Vectorized sampling by interval type
            sample[unbounded] = self.local_prng.normal(size=unbounded[unbounded].shape)

            sample[low_bounded] = self.local_prng.exponential(size=low_bounded[low_bounded].shape) + space.low[low_bounded]

            sample[upp_bounded] = -self.local_prng.exponential(size=upp_bounded[upp_bounded].shape) + space.high[upp_bounded]

            sample[bounded] = self.local_prng.uniform(low=space.low[bounded], high=high[bounded], size=bounded[bounded].shape)

            if space.high.dtype.kind == 'i':
                sample = np.floor(sample)

            sample = sample.astype(space.high.dtype)

            return sample

    def sample_from_box_action_space(self):
        """
        This method samples from a Box Action Space.
        """

        sample = self._sample_from_box(space=self.action_space)

        return sample

    def sample_from_box_observation_space(self):
        """
        This method samples from a Box Observation Space.
        """

        sample = self._sample_from_box(space=self.observation_space)

        return sample

    def set_params(self, params_dict):
        """
        Parameters
        ----------
        params_dict: This is a dictionary containing the parameters of the environment and their new value.
        """

        if(isinstance(params_dict, dict)):
            for tmp_key in list(params_dict.keys()):
                if(hasattr(self, tmp_key)):
                    setattr(self, tmp_key, params_dict[tmp_key])
                else:
                    exc_msg = 'The environment does not have the member \''+str(tmp_key)+'\'!'
                    self.logger.exception(msg=exc_msg)
                    raise AttributeError(exc_msg)
        else:
            exc_msg = '\'params_dict\' must be a dictionary!'
            self.logger.exception(msg=exc_msg)
            raise TypeError(exc_msg)

    def get_params(self, params_names):
        """
        Parameters
        ----------
        params_names: This is a list of strings and they represent the names of the parameters of which we want to get the value.

        Returns
        -------
        params_dict: This is a dictionary with as keys the strings in the list params_names and as values the current value of
                     such parameter.
        """

        params_dict = {}

        for tmp_key in params_names:
            if(hasattr(self, tmp_key)):
                params_dict.update({tmp_key: getattr(self, tmp_key)})
            else:
                exc_msg = 'The environment does not have the member \''+str(tmp_key)+'\'!'
                self.logger.exception(msg=exc_msg)
                raise AttributeError(exc_msg)

        return params_dict

class BaseWrapper(BaseEnvironment):
    """
    This is the base wrapper Class based on the OpenAI Wrapper Class. Part of this class is a re-adaptation of code copied from
    OpenAI gym: https://github.com/openai/gym/blob/master/gym/core.py

    This is used as base Class for observation wrappers, action wrappers and reward wrappers.

    Other kind of wrappers can be created inheriting from this Class.
    """

    def __init__(self, env, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3, n_jobs=1,
                 job_type='process'):
        """
        Parameters
        ----------
        env: This is the environment that needs to be wrapped. It must be an object of a Class inheriting from the Class
             BaseEnvironment.

        The other parameters and non-parameters members are described in the Class BaseEnvironment.
        """

        super().__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode, checkpoint_log_path=checkpoint_log_path,
                         verbosity=verbosity, n_jobs=n_jobs, job_type=job_type)

        self.env = env

        #The env must be an object of a Class inheriting from the Class BaseEnvironment
        if(not isinstance(self.env, BaseEnvironment)):
            exc_msg = 'The \'env\' must be an object of a Class inheriting from the Class BaseEnvironment!'
            self.logger.exception(msg=exc_msg)
            raise TypeError(exc_msg)

        self.action_space = self.env.action_space
        self.observation_space = self.env.observation_space
        self.gamma = self.env.gamma
        self.horizon = self.env.horizon

    def __repr__(self):
         return str(self.__class__.__name__)+'('+'env='+str(self.env)+', observation_space='+str(self.observation_space)\
                +', action_space='+str(self.action_space)+', gamma='+str(self.gamma)+', horizon='+str(self.horizon)\
                +', obj_name='+str(self.obj_name)+', seeder='+str(self.seeder)+', local_prng='+str(self.local_prng)\
                +', log_mode='+str(self.log_mode)+', checkpoint_log_path='+str(self.checkpoint_log_path)\
                +', verbosity='+str(self.verbosity)+', n_jobs='+str(self.n_jobs)+', job_type='+str(self.job_type)\
                +', logger='+str(self.logger)+')'

    def step(self, action):
        """
        Method used to run one step of the environment dynamics.
        """

        return self.env.step(action=action)

    def reset(self, state=None):
        """
        Method used to reset the environment.
        """

        return self.env.reset(state=state)

    def render(self, mode='human'):
        """
        Method used to render an environment.
        """

        return self.env.render(mode=mode)

    def close(self):
        """
        Method used to perform necessary cleanup.
        """

        return self.env.close()

    def seed(self, seed=None):
        """
        Method used to seed the environment.
        """

        return self.env.seed(seed=seed)

    def stop(self):
        return self.env.stop()

    def unwrapped(self):
        """
        Method to unwrap the environment.
        """

        return self.env.unwrapped()

class BaseObservationWrapper(BaseWrapper):
    """
    Part of this Class is a readaptation of code copied from OpenAI gym: https://github.com/openai/gym/blob/master/gym/core.py

    To create an observation wrapper you must create a new Class inheriting from this Class. You must override the observation
    method, and in the __init__ you must:
        -Call the __init__ of BaseWrapper via: super().__init__(env)
        -Properly modify the observation space.

    This is an abstract Class: it must be sub-classed.
    """

    def reset(self, state=None):
        """
        Method used to reset the environment.
        """

        observation = self.env.reset(state=state)
        return self.observation(observation=observation)

    def step(self, action):
        """
        Method used to run one step of the environment dynamics.
        """

        observation, reward, absorbing, info = self.env.step(action=action)
        return self.observation(observation=observation), reward, absorbing, {}

    @abstractmethod
    def observation(self, observation):
        """
        Method used to transform the observations.
        """

        raise NotImplementedError

class BaseActionWrapper(BaseWrapper):
    """
    Part of this Class is a readaptation of code copied from OpenAI gym: https://github.com/openai/gym/blob/master/gym/core.py

    To create an action wrapper you must create a new Class inheriting from this Class. You must override the action method and
    in the __init__ you must:
        -Call the __init__ of BaseWrapper via: super().__init__(env)
        -Properly modify the action space.

    This is an abstract Class: it must be sub-classed.
    """

    def step(self, action):
        """
        Method used to run one step of the environment dynamics.
        """

        return self.env.step(self.action(action=action))

    @abstractmethod
    def action(self, action):
        """
        Method used to transform the actions.
        """

        raise NotImplementedError

class BaseRewardWrapper(BaseWrapper):
    """
    Part of this Class is a readaptation of code copied from OpenAI gym: https://github.com/openai/gym/blob/master/gym/core.py

    To create a reward wrapper you must create a new Class inheriting from this Class. You must override the reward method, and
    in the __init__ you must:
        -Call the __init__ of BaseWrapper via: super().__init__(env)

    This is an abstract Class: it must be sub-classed.
    """

    def step(self, action):
        """
        Method used to run one step of the environment dynamics.
        """

        observation, reward, absorbing, info = self.env.step(action=action)
        return observation, self.reward(reward=reward), absorbing, {}

    @abstractmethod
    def reward(self, reward):
        """
        Method used to transform the rewards.
        """

        raise NotImplementedError

class BaseGridWorld(GridWorld, BaseEnvironment):
    """
    This Class wraps the GridWorld Class from MushroomRL: this is needed for the correct working of this library.
    """

    def __init__(self, height, width, goal, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3,
                 n_jobs=1, job_type='process', start=(0,0)):
        super().__init__(height=height, width=width, goal=goal, start=start)
        super(BaseEnvironment, self).__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode,
                                              checkpoint_log_path=checkpoint_log_path, verbosity=verbosity, n_jobs=n_jobs,
                                              job_type=job_type)
        self.horizon = super().info.horizon
        self.gamma = super().info.gamma

        self.observation_space   = super().info.observation_space
        self.action_space =  super().info.action_space

    def __repr__(self):
        return 'BaseGridWorld('+'observation_space='+str(self.observation_space)+', action_space='+str(self.action_space)\
                +', gamma='+str(self.gamma)+', horizon='+str(self.horizon)+', obj_name='+str(self.obj_name)\
                +', seeder='+str(self.seeder)+', local_prng='+str(self.local_prng)+', log_mode='+str(self.log_mode)\
                +', checkpoint_log_path='+str(self.checkpoint_log_path)+', verbosity='+str(self.verbosity)\
                +', n_jobs='+str(self.n_jobs)+', job_type='+str(self.job_type)+', logger='+str(self.logger)+')'

    def seed(self, seed=None):
        """
        Method used to seed the environment.
        """

        return

class BaseCarOnHill(CarOnHill, BaseEnvironment):
    """
    This Class wraps the CarOnHill Class from MushroomRL: this is needed for the correct working of this library.
    """

    def __init__(self, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3, n_jobs=1,
                 job_type='process', horizon=100, gamma=.95):
        super().__init__(horizon=horizon, gamma=gamma)
        super(BaseEnvironment, self).__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode,
                                              checkpoint_log_path=checkpoint_log_path, verbosity=verbosity, n_jobs=n_jobs,
                                              job_type=job_type)

        self.horizon = super().info.horizon
        self.gamma = super().info.gamma

        self.observation_space = super().info.observation_space
        self.action_space =  super().info.action_space

    def __repr__(self):
        return 'BaseCarOnHill('+'observation_space='+str(self.observation_space)+', action_space='+str(self.action_space)\
                +', gamma='+str(self.gamma)+', horizon='+str(self.horizon)+', obj_name='+str(self.obj_name)\
                +', seeder='+str(self.seeder)+', local_prng='+str(self.local_prng)+', log_mode='+str(self.log_mode)\
                +', checkpoint_log_path='+str(self.checkpoint_log_path)+', verbosity='+str(self.verbosity)\
                +', n_jobs='+str(self.n_jobs)+', job_type='+str(self.job_type)+', logger='+str(self.logger)+')'

    def seed(self, seed=None):
        """
        Method used to seed the environment.
        """

        return

class BaseCartPole(CartPole, BaseEnvironment):
    """
    This Class wraps the CartPole Class from MushroomRL: this is needed for the correct working of this library.
    """

    def __init__(self, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3, n_jobs=1,
                 job_type='process', m=2., M=8., l=.5, g=9.8, mu=1e-2, max_u=50., noise_u=10., horizon=3000, gamma=.95):
        super().__init__(m=m, M=M, l=l, g=g, mu=mu, max_u=max_u, noise_u=noise_u, horizon=horizon, gamma=gamma)
        super(BaseEnvironment, self).__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode,
                                              checkpoint_log_path=checkpoint_log_path, verbosity=verbosity, n_jobs=n_jobs,
                                              job_type=job_type)

        self.horizon = super().info.horizon
        self.gamma = super().info.gamma

        self.observation_space  = super().info.observation_space
        self.action_space  =  super().info.action_space

    def __repr__(self):
        return 'BaseCartPole('+'observation_space='+str(self.observation_space)+', action_space='+str(self.action_space)\
                +', gamma='+str(self.gamma)+', horizon='+str(self.horizon)+', obj_name='+str(self.obj_name)\
                +', seeder='+str(self.seeder)+', local_prng='+str(self.local_prng)+', log_mode='+str(self.log_mode)\
                +', checkpoint_log_path='+str(self.checkpoint_log_path)+', verbosity='+str(self.verbosity)\
                +', n_jobs='+str(self.n_jobs)+', job_type='+str(self.job_type)+', logger='+str(self.logger)+')'

    def seed(self, seed=None):
        """
        Method used to seed the environment.
        """

        return

class BaseInvertedPendulum(InvertedPendulum, BaseEnvironment):
    """
    This Class wraps the InvertedPendulum Class from MushroomRL: this is needed for the correct working of this library.
    """

    def __init__(self, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3, n_jobs=1,
                 job_type='process', random_start=False, m=1., l=1., g=9.8, mu=1e-2, max_u=5., horizon=5000, gamma=.99):
        super().__init__(random_start=random_start, m=m, l=l, g=g, mu=mu, max_u=max_u, horizon=horizon, gamma=gamma)
        super(BaseEnvironment, self).__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode,
                                              checkpoint_log_path=checkpoint_log_path, verbosity=verbosity, n_jobs=n_jobs,
                                              job_type=job_type)

        self.horizon = super().info.horizon
        self.gamma = super().info.gamma

        self.observation_space = super().info.observation_space
        self.action_space =  super().info.action_space

    def __repr__(self):
        return 'BaseInvertedPendulum('+'observation_space='+str(self.observation_space)\
                +', action_space='+str(self.action_space)+', gamma='+str(self.gamma)+', horizon='+str(self.horizon)\
                +', obj_name='+str(self.obj_name)+', seeder='+str(self.seeder)+', local_prng='+str(self.local_prng)\
                +', log_mode='+str(self.log_mode)+', checkpoint_log_path='+str(self.checkpoint_log_path)\
                +', verbosity='+str(self.verbosity)+', n_jobs='+str(self.n_jobs)+', job_type='+str(self.job_type)\
                +', logger='+str(self.logger)+')'

    def seed(self, seed=None):
        """
        Method used to seed the environment.
        """

        return

class LQG(BaseEnvironment):
    """
    Environment implementing a Linear-Quadratic Gaussian control (LQG) problem: s_{t+1} = A s_t + B a_t + env_noise

    The reward function is given by: r_{t+1} = - s_t^T Q s_t - a_t^T R a_t

    Note that there is also a noise on the controller: if you pick action a_t then you will be able to execute action:
    a_t + controller_noise. This only plays a role when rolling out the policy: we consider a gaussian policy with mean a_t and
    covariante matrix given by controller_noise.

    This is a re-adaptation of code copied from: https://github.com/T3p/potion/blob/master/potion/envs/lq.py
    """

    def __init__(self, obj_name, A=np.eye(1), B=np.eye(1), Q=np.eye(1), R=np.eye(1), max_pos=1.0, max_action=1.0,
                 env_noise=np.eye(1), controller_noise=np.eye(1), horizon=10, gamma=0.9, seeder=2, log_mode='console',
                 checkpoint_log_path=None, verbosity=3, n_jobs=1, job_type='process'):
        """
        Parameters
        ----------
        A: This is the state dynamics matrix.

           The default is np.eye(1).

        B: This is the action dynamics matrix.

           The default is np.eye(1).

        Q: This is the cost weight matrix for the state. It must be a positive-definite matrix (to always have a negative reward).

           The default is np.eye(1).

        R: This is the cost weight matrix for the action. It must be a positive-definite matrix (to always have a negative
           reward).

           The default is np.eye(1).

        max_pos: This is the maximum value that the state can reach.

                 The default is 1.0.

        max_action: This is the maximum value that the action can reach.

                    The default is 1.0.

        env_noise: This is the covariance matrix representing the environment noise.

                   The default is np.eye(1).

        controller_noise: This is the covariance matrix representing the controller noise.

                          The default is np.eye(1).

        horizon: This is the horizon of the MDP.

                 The default is 10.

        gamma: This is the discount factor of the MDP.

               The default is 0.9.

        Non-Parameters Members
        ----------------------
        is_eval_phase: This is True if the environment is used for evaluating a policy: what happens is that the controller_noise
                       is added to the action selected by the policy, and then fed to the simulator.

                       Otherwise it is False.

                       This is used to represent the fact that even if we have learnt a theoretically optimal policy, in practice
                       to execute it there is going to be some noise and so the resulting action taken in the real world will be
                       different from the one selected by the policy.

                       This parameter can be set automatically by the evaluation metric.

        The other parameters and non-parameters members are described in the Class BaseEnvironment.
        """

        super().__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode, checkpoint_log_path=checkpoint_log_path,
                         verbosity=verbosity, n_jobs=n_jobs, job_type=job_type)

        self.A = A
        self.B = B
        self.Q = Q
        self.R = R

        #state dimension
        self.ds = self.A.shape[1]

        #action dimension
        self.da = self.B.shape[1]

        if(self.da == 1):
            if(self.R < 0):
                exc_msg = 'The matrix \'R\' must be positive-definite so that the reward is always negative!'
                self.logger.exception(msg=exc_msg)
                raise ValueError(exc_msg)
        else:
            if(not np.all(np.linalg.eigvals(self.R) > 0)):
                exc_msg = 'The matrix \'R\' must be positive-definite so that the reward is always negative!'
                self.logger.exception(msg=exc_msg)
                raise ValueError(exc_msg)

        if(self.ds == 1):
            if(self.Q < 0):
                exc_msg = 'The matrix \'Q\' must be positive-definite so that the reward is always negative!'
                self.logger.exception(msg=exc_msg)
                raise ValueError(exc_msg)
        else:
            if(not np.all(np.linalg.eigvals(self.Q) > 0)):
                exc_msg = 'The matrix \'Q\' must be positive-definite so that the reward is always negative!'
                self.logger.exception(msg=exc_msg)
                raise ValueError(exc_msg)

        #task horizon
        self.horizon = horizon

        #discount factor
        self.gamma = gamma

        #max state for clipping
        self.max_pos = max_pos*np.ones(self.ds)

        #max action for clipping
        self.max_action = max_action*np.ones(self.da)

        #environment noise
        self.env_noise = env_noise
        #check that the env_noise has the right shape:
        if(self.env_noise.shape[1] != self.ds):
            exc_msg = 'The \'env_noise\' co-variance matrix is not of the right shape!'
            self.logger.exception(msg=exc_msg)
            raise ValueError(exc_msg)

        self.viewer = None

        self.action_space = Box(low=-self.max_action, high=self.max_action)

        self.observation_space = Box(low=-self.max_pos, high=self.max_pos)

        self.controller_noise = controller_noise
        #check that the controller_noise has the right shape:
        if(self.controller_noise.shape[1] != self.da):
            exc_msg = 'The \'controller_noise\' co-variance matrix is not of the right shape!'
            self.logger.exception(msg=exc_msg)
            raise ValueError(exc_msg)

        #when this is true the controller noise is added to the action that the policy originally picked.
        self.is_eval_phase = False

    def __repr__(self):
        return 'LQG('+'observation_space='+str(self.observation_space)+', action_space='+str(self.action_space)\
                +', gamma='+str(self.gamma)+', horizon='+str(self.horizon)+', A='+str(self.A)+', B='+str(self.B)\
                +', Q='+str(self.Q)+', R='+str(self.R)+', env_noise='+str(self.env_noise)\
                +', controller_noise='+str(self.controller_noise)+', is_eval_phase='+str(self.is_eval_phase)\
                +', obj_name='+str(self.obj_name)+', seeder='+str(self.seeder)+', local_prng='+str(self.local_prng)\
                +', log_mode='+str(self.log_mode)+', checkpoint_log_path='+str(self.checkpoint_log_path)\
                +', verbosity='+str(self.verbosity)+', n_jobs='+str(self.n_jobs)+', job_type='+str(self.job_type)\
                +', logger='+str(self.logger)+')'

    def step(self, action):
        """
        Method used to run one step of the environment dynamics.
        """

        if(self.is_eval_phase):
            action = action + self.local_prng.multivariate_normal(mean=np.zeros(self.da), cov=self.controller_noise)

        u = np.clip(np.ravel(np.atleast_1d(action)), -self.max_action, self.max_action)

        #makes the noise different at each step:
        env_noise = np.dot(self.env_noise, self.local_prng.standard_normal(self.ds))

        xn = np.clip(np.dot(self.A, self.state.T) + np.dot(self.B, u) + env_noise, -self.max_pos, self.max_pos)

        cost = np.dot(self.state, np.dot(self.Q, self.state)) + np.dot(u, np.dot(self.R, u))

        self.state = xn.ravel()

        self.timestep += 1

        return np.array(self.state), -np.asscalar(cost), self.timestep >= self.horizon, {'danger':0}

    def reset(self, state=None):
        """
        By default, random uniform initialization.
        """

        self.timestep = 0
        if state is None:
            self.state = np.array(self.local_prng.uniform(low=-self.max_pos, high=self.max_pos, size=self.ds))
        else:
            self.state = np.array(state)

        return np.array(self.state)

    def seed(self, seed=None):
        """
        Method used to seed the environment.
        """

        if(seed is None):
            self.set_local_prng(new_seeder=seed)

    def render(self, mode='human', close=False):
        """
        Method used to render the environment.
        """

        #this is here since it would otherwise open a plot window
        from gym.envs.classic_control import rendering

        if self.ds not in [1, 2]:
            return
        if close:
            if self.viewer is not None:
                self.viewer.close()
                self.viewer = None
            return

        screen_width = 600
        world_width = math.ceil((self.max_pos[0] * 2) * 1.5)
        xscale = screen_width / world_width
        ballradius = 3

        if self.ds == 1:
            screen_height = 400
        else:
            world_height = math.ceil((self.max_pos[1] * 2) * 1.5)
            screen_height = math.ceil(xscale * world_height)
            yscale = screen_height / world_height

        if self.viewer is None:
            clearance = 0  # y-offset
            self.viewer = rendering.Viewer(screen_width, screen_height)
            mass = rendering.make_circle(ballradius * 2)
            mass.set_color(.8, .3, .3)
            mass.add_attr(rendering.Transform(translation=(0, clearance)))
            self.masstrans = rendering.Transform()
            mass.add_attr(self.masstrans)
            self.viewer.add_geom(mass)
            if self.ds == 1:
                self.track = rendering.Line((0, 100), (screen_width, 100))
            else:
                self.track = rendering.Line((0, screen_height / 2), (screen_width, screen_height / 2))
            self.track.set_color(0.5, 0.5, 0.5)
            self.viewer.add_geom(self.track)
            zero_line = rendering.Line((screen_width / 2, 0), (screen_width / 2, screen_height))
            zero_line.set_color(0.5, 0.5, 0.5)
            self.viewer.add_geom(zero_line)

        x = self.state[0]
        ballx = x * xscale + screen_width / 2.0
        if self.ds == 1:
            bally = 100
        else:
            y = self.state[1]
            bally = y * yscale + screen_height / 2.0
        self.masstrans.set_translation(ballx, bally)

        return self.viewer.render(return_rgb_array=mode == 'rgb_array')

    def get_optimal_K(self):
        """
        Returns
        -------
        Computes the optimal parameters K and returns the optimal policy given by: -K*s where s is the state.

        Note that the addition of the controller noise is taken care of in the evaluation phase.
        """

        X = np.matrix(scipy.linalg.solve_discrete_are(self.A, self.B, self.Q, self.R))

        K = np.matrix(scipy.linalg.inv(self.B.T*X*self.B+self.R)*(self.B.T*X*self.A))

        return -K

class BaseMujoco(BaseEnvironment):
    """
    This Class wraps the Mujoco environments. Every Mujoco environment inherits from this Class.

    This is an abstract Class.
    """

    def __init__(self, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3, n_jobs=1,
                 job_type='process'):
        """
        Non-Parameters Members
        ----------------------
        mujoco_env: This is a Mujoco environment instance: an object of a Class inheriting from OpenAI gym Class:
                    gym.envs.mujoco.mujoco_env.MujocoEnv.

        n_steps: This is a counter for the horizon of the environment. It is the number of total steps that have happened so far.
        """

        super().__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode, checkpoint_log_path=checkpoint_log_path,
                         verbosity=verbosity)

        #this is set in the sub-Class:
        self.mujoco_env = None

        self.n_steps = 0

    def __repr__(self):
        return str(self.__class__.__name__)+'('+'observation_space='+str(self.observation_space)\
               +', action_space='+str(self.action_space)+', gamma='+str(self.gamma)+', horizon='+str(self.horizon)\
               +', obj_name='+str(self.obj_name)+', seeder='+str(self.seeder)+', local_prng='+str(self.local_prng)\
               +', log_mode='+str(self.log_mode)+', checkpoint_log_path='+str(self.checkpoint_log_path)\
               +', verbosity='+str(self.verbosity)+', n_jobs='+str(self.n_jobs)+', job_type='+str(self.job_type)\
               +', logger='+str(self.logger)+')'

    def _update_counter(self, out_step):
        """
        Parameters
        ----------
        out_step: The output from the mujoco_env object step() method.

        Returns
        -------
        tuple(out_step): The modified environment step() method output.

        Updates the n_steps and if the horizon is reached the output of the method step() from the environment is modified: done
        is set to True.
        """

        if(hasattr(self, 'n_steps')):
            out_step = list(out_step)

            self.n_steps += 1

            if(self.n_steps >= self.horizon):
                out_step[2] = True
                self.n_steps = 0

        return tuple(out_step)

    def step(self, action):
        """
        Method used to run one step of the environment dynamics.
        """

        out = self.mujoco_env.step(action=action)

        out = self._update_counter(out_step=out)

        return out

    def reset(self, state=None):
        """
        Method used to reset the environment.
        """

        obs = self.mujoco_env.reset()

        self.n_steps = 0

        return obs

    def seed(self, seed=None):
        """
        Method used to seed the environment.
        """

        return self.mujoco_env.seed(seed=seed)

    def render(self, mode='human'):
        """
        Method used to render the environment.
        """

        return self.mujoco_env.render(mode=mode)

    def set_local_prng(self, new_seeder):
        """
        Method used to adjust to the fact that OpenAI does not use my system of using local prng but have their own way of doing
        it. Without this method by calling the original method set_local_prng() implemented in the Class AbstractUnit there would
        be no effect on the environment.

        The method set_local_prng() is called in the Metric Classes and in some of the DataGeneration Classes so this method
        needs to work properly.
        """

        self.seed(seed=new_seeder)

    def _initialise_mdp_properties(self, gamma, horizon):
        """
        Parameters
        ----------
        gamma: This is the MDP discount factor. It must be a float.

        horizon: This is the MDP horizon. It must be an integer.
        """

        #no gamma, no horizon in Mujoco: i select them
        self.gamma = gamma
        self.horizon = horizon

        #I need to use the environment spaces from MushroomRL:
        self.action_space = Box(self.mujoco_env.action_space.low, self.mujoco_env.action_space.high)

        self.observation_space = Box(self.mujoco_env.observation_space.low, self.mujoco_env.observation_space.high)

class BaseHalfCheetah(BaseMujoco):
    """
    This Class wraps the Mujoco environment: HalfCheetahEnv.
    """

    def __init__(self, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3, n_jobs=1,
                 job_type='process', gamma=0.99, horizon=1000, xml_file='half_cheetah.xml', forward_reward_weight=1.0,
                 ctrl_cost_weight=0.1, reset_noise_scale=0.1, exclude_current_positions_from_observation=True):
        """
        Parameters
        ----------
        gamma: This is the MDP discount factor. It must be a float.

               The default is 0.99.

        horizon: This is the MDP horizon. It must be an integer.

                 The default is 1000.
        """

        super().__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode, checkpoint_log_path=checkpoint_log_path,
                         verbosity=verbosity)

        self.mujoco_env = HalfCheetahEnv(xml_file=xml_file, forward_reward_weight=forward_reward_weight,
                                         ctrl_cost_weight=ctrl_cost_weight, reset_noise_scale=reset_noise_scale,
                                         exclude_current_positions_from_observation=exclude_current_positions_from_observation)

        self._initialise_mdp_properties(gamma=gamma, horizon=horizon)

class BaseAnt(BaseMujoco):
    """
    This Class wraps the Mujoco environment: AntEnv.
    """

    def __init__(self, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3, n_jobs=1,
                 job_type='process', gamma=0.99, horizon=1000, xml_file='ant.xml', ctrl_cost_weight=0.5, contact_cost_weight=5e-4,
                 healthy_reward=1.0, terminate_when_unhealthy=True, healthy_z_range=(0.2, 1.0), contact_force_range=(-1.0, 1.0),
                 reset_noise_scale=0.1, exclude_current_positions_from_observation=True):
        """
        Parameters
        ----------
        gamma: This is the MDP discount factor. It must be a float.

               The default is 0.99.

        horizon: This is the MDP horizon. It must be an integer.

                 The default is 1000.
        """

        super().__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode, checkpoint_log_path=checkpoint_log_path,
                         verbosity=verbosity)

        self.mujoco_env = AntEnv(xml_file=xml_file, ctrl_cost_weight=ctrl_cost_weight, contact_cost_weight=contact_cost_weight,
                                 healthy_reward=healthy_reward, terminate_when_unhealthy=terminate_when_unhealthy,
                                 healthy_z_range=healthy_z_range, contact_force_range=contact_force_range,
                                 reset_noise_scale=reset_noise_scale,
                                 exclude_current_positions_from_observation=exclude_current_positions_from_observation)

        self._initialise_mdp_properties(gamma=gamma, horizon=horizon)

class BaseHopper(BaseMujoco):
    """
    This Class wraps the Mujoco environment: HopperEnv.
    """

    def __init__(self, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3, n_jobs=1,
                 job_type='process', gamma=0.99, horizon=1000, xml_file='hopper.xml', forward_reward_weight=1.0,
                 ctrl_cost_weight=1e-3, healthy_reward=1.0, terminate_when_unhealthy=True, healthy_state_range=(-100.0, 100.0),
                 healthy_z_range=(0.7, float('inf')), healthy_angle_range=(-0.2, 0.2), reset_noise_scale=5e-3,
                 exclude_current_positions_from_observation=True):
        """
        Parameters
        ----------
        gamma: This is the MDP discount factor. It must be a float.

               The default is 0.99.

        horizon: This is the MDP horizon. It must be an integer.

                 The default is 1000.
        """

        super().__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode, checkpoint_log_path=checkpoint_log_path,
                         verbosity=verbosity)

        self.mujoco_env = HopperEnv(xml_file=xml_file, forward_reward_weight=forward_reward_weight,
                                    ctrl_cost_weight=ctrl_cost_weight, healthy_reward=healthy_reward,
                                    terminate_when_unhealthy=terminate_when_unhealthy, healthy_state_range=healthy_state_range,
                                    healthy_z_range=healthy_z_range, healthy_angle_range=healthy_angle_range,
                                    reset_noise_scale=reset_noise_scale,
                                    exclude_current_positions_from_observation=exclude_current_positions_from_observation)

        self._initialise_mdp_properties(gamma=gamma, horizon=horizon)

class BaseHumanoid(BaseMujoco):
    """
    This Class wraps the Mujoco environment: HumanoidEnv.
    """

    def __init__(self, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3, n_jobs=1,
                 job_type='process', gamma=0.99, horizon=1000, xml_file='humanoid.xml', forward_reward_weight=1.25,
                 ctrl_cost_weight=0.1, contact_cost_weight=5e-7, contact_cost_range=(-np.inf, 10.0), healthy_reward=5.0,
                 terminate_when_unhealthy=True, healthy_z_range=(1.0, 2.0), reset_noise_scale=1e-2,
                 exclude_current_positions_from_observation=True):
        """
        Parameters
        ----------
        gamma: This is the MDP discount factor. It must be a float.

               The default is 0.99.

        horizon: This is the MDP horizon. It must be an integer.

                 The default is 1000.
        """

        super().__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode, checkpoint_log_path=checkpoint_log_path,
                         verbosity=verbosity)

        self.mujoco_env = HumanoidEnv(xml_file=xml_file, forward_reward_weight=forward_reward_weight,
                                      ctrl_cost_weight=ctrl_cost_weight, contact_cost_weight=contact_cost_weight,
                                      contact_cost_range=contact_cost_range, healthy_reward=healthy_reward,
                                      terminate_when_unhealthy=terminate_when_unhealthy, healthy_z_range=healthy_z_range,
                                      reset_noise_scale=reset_noise_scale,
                                      exclude_current_positions_from_observation=exclude_current_positions_from_observation)

        self._initialise_mdp_properties(gamma=gamma, horizon=horizon)

class BaseSwimmer(BaseMujoco):
    """
    This Class wraps the Mujoco environment: SwimmerEnv.
    """

    def __init__(self, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3, n_jobs=1,
                 job_type='process', gamma=0.99, horizon=1000, xml_file="swimmer.xml", forward_reward_weight=1.0,
                 ctrl_cost_weight=1e-4, reset_noise_scale=0.1, exclude_current_positions_from_observation=True):
        """
        Parameters
        ----------
        gamma: This is the MDP discount factor. It must be a float.

               The default is 0.99.

        horizon: This is the MDP horizon. It must be an integer.

                 The default is 1000.
        """

        super().__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode, checkpoint_log_path=checkpoint_log_path,
                         verbosity=verbosity)

        self.mujoco_env = SwimmerEnv(xml_file=xml_file, forward_reward_weight=forward_reward_weight,
                                     ctrl_cost_weight=ctrl_cost_weight, reset_noise_scale=reset_noise_scale,
                                     exclude_current_positions_from_observation=exclude_current_positions_from_observation)

        self._initialise_mdp_properties(gamma=gamma, horizon=horizon)

class BaseWalker2d(BaseMujoco):
    """
    This Class wraps the Mujoco environment: Walker2dEnv.
    """

    def __init__(self, obj_name, seeder=2, log_mode='console', checkpoint_log_path=None, verbosity=3, n_jobs=1,
                 job_type='process', gamma=0.99, horizon=1000, xml_file="walker2d.xml", forward_reward_weight=1.0,
                 ctrl_cost_weight=1e-3, healthy_reward=1.0, terminate_when_unhealthy=True, healthy_z_range=(0.8, 2.0),
                 healthy_angle_range=(-1.0, 1.0), reset_noise_scale=5e-3, exclude_current_positions_from_observation=True):
        """
        Parameters
        ----------
        gamma: This is the MDP discount factor. It must be a float.

               The default is 0.99.

        horizon: This is the MDP horizon. It must be an integer.

                 The default is 1000.
        """

        super().__init__(obj_name=obj_name, seeder=seeder, log_mode=log_mode, checkpoint_log_path=checkpoint_log_path,
                         verbosity=verbosity)

        self.mujoco_env = Walker2dEnv(xml_file=xml_file, forward_reward_weight=forward_reward_weight,
                                      ctrl_cost_weight=ctrl_cost_weight, healthy_reward=healthy_reward,
                                      terminate_when_unhealthy=terminate_when_unhealthy, healthy_z_range=healthy_z_range,
                                      healthy_angle_range=healthy_angle_range, reset_noise_scale=reset_noise_scale,
                                      exclude_current_positions_from_observation=exclude_current_positions_from_observation)

        self._initialise_mdp_properties(gamma=gamma, horizon=horizon)


#!/usr/bin/env python
# coding: utf-8

# #### 배열 안 단어에서 특정 글자들을 옮겨서 모두가 같은 단어가 되도록 만들기
#
# #### 가능하면 true return, 안되면 false return

# In[ ]:

words = ["abc","aabc","bc"] # true
words = ["ab","a"] # false

# #### words의 총 길이가 n일때, n의 배수 개수만큼 만큼 각 문자들이 존재한다면 이동으로 같아질 수 있음

# In[39]:

class Solution(object):
    def makeEqual(self, words):
        length = len(words)
        if length == 1: # 한 문자인 경우 -> True
            return True

        check = ''
        for i in words:
            check += i

        check2 = set(check) # 겹치는 거 모두 제외한 문자들
        if len(check2) == len(check): # a b c 이런 식으로만 존재하는 경우 같아질 수 x
            return False

        result = []
        for j in check2:
            result.append(check.count(j)) # check에서 unique한 문자들 개수 세기(a 몇개, b 몇개 ...)

        for k in result: # 각 문자들 개수가 words의 n의 배수만큼 존재하는가? (나머지 = 0)
            if k%length >= 1:
                return False # 특정 문자 하나라도 n의 배수 아닌 경우 False
        return True # 모든 문자들이 다 words의 n 배수인 경우 True

week9/1-1) LEET 1897 Redistribute Characters to Make All Strings Equal.py


from app import db

class Board(db.Model):
    __tablename__ = "board"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String)
    owner = db.Column(db.String)
    cards = db.relationship("Card", back_populates="board",
                            cascade="all, delete-orphan")

    def to_dict(self):
        return {
            "id": self.id,
            "title": self.title,
            "owner": self.owner,
        }

    @classmethod
    def from_dict(cls, board_data):
        new_board = Board(
            title=board_data["title"],
            owner=board_data["owner"]
        )
        return new_board


#! /usr/bin/env python
# -*- coding: utf-8 -*-

import logging

from src.ui.winsWidgetView import WinsWidgetView

logging.basicConfig(level=logging.DEBUG) # change to 'DEBUG' to see more

from PyQt5 import QtWidgets, QtGui

def setFontFamily(font):
    allFamillies = QtGui.QFontDatabase().families()
    familyName = font.defaultFamily()
    if "微软雅黑" in allFamillies:
        familyName = "微软雅黑"
    font.setFamily(familyName)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    font = QtGui.QFont()
    setFontFamily(font)
    font.setPixelSize(14)
    app.setFont(font)
    with open('qml\Main.qml', 'r') as qss:
        app.setStyleSheet(qss.read())
    mainview = WinsWidgetView()
    mainview.show()
    sys.exit(app.exec_())


__author__ = 'Médéric Ribreux'
__date__ = 'April 2016'
__copyright__ = '(C) 2016, Médéric Ribreux'

# This will get replaced with a git SHA1 when you do a git archive

__revision__ = '$Format:%H$'

from processing.core.parameters import ParameterRaster, getParameterFromString
from processing.tools.system import isWindows
from ..Grass7Utils import Grass7Utils
from os import path

def multipleOutputDir(alg, field, basename=None):
    """
    Handle multiple output of rasters into a
    directory.
    """
    # We need to know where is the output directory
    outputDir = alg.getOutputValue(field)

    # We need to grab the variable basename
    if basename:
        commands = ["for r in $(g.list type=rast pattern='{}*'); do".format(basename)]
    # Otherwise, export everything
    else:
        commands = ["for r in $(g.list type=rast); do".format(basename)]
    commands.append("  r.out.gdal -c -t -f input=${{r}} output={}/${{r}}.tif createopt=\"TFW=YES,COMPRESS=LZW\"".format(outputDir))
    commands.append("done")
    alg.commands.extend(commands)
    alg.outputCommands.extend(commands)

def orderedInput(alg, inputParameter, targetParameterDef, numSeq=None):
    """Inport multiple rasters in the order"""
    rasters = alg.getParameterValue(inputParameter).split(';')
    # TODO: make targetParameter
    inputParameter = getParameterFromString(targetParameterDef)
    rootFilename = '{}_'.format(alg.getTempFilename())
    inputParameter.value = rootFilename
    alg.addParameter(inputParameter)
    # Handle specific range
    if numSeq is None:
        numSeq = range(1, len(rasters) + 1)

    for idx in range(len(rasters)):
        layer = rasters[idx]
        if layer in alg.exportedLayers.keys():
            continue
        else:
            destFilename = '{}{}'.format(rootFilename, numSeq[idx])
            alg.setSessionProjectionFromLayer(layer, alg.commands)
            alg.exportedLayers[layer] = destFilename
            command = 'r.external input={} band=1 output={} --overwrite -o'.format(layer, destFilename)
            alg.commands.append(command)

    alg.setSessionProjectionFromProject(alg.commands)

    region = \
        unicode(alg.getParameterValue(alg.GRASS_REGION_EXTENT_PARAMETER))
    regionCoords = region.split(',')
    command = 'g.region'
    command += ' -a'
    command += ' n=' + unicode(regionCoords[3])
    command += ' s=' + unicode(regionCoords[2])
    command += ' e=' + unicode(regionCoords[1])
    command += ' w=' + unicode(regionCoords[0])
    cellsize = alg.getParameterValue(alg.GRASS_REGION_CELLSIZE_PARAMETER)
    if cellsize:
        command += ' res=' + unicode(cellsize)
    else:
        command += ' res=' + unicode(alg.getDefaultCellsize())
    alignToResolution = \
        alg.getParameterValue(alg.GRASS_REGION_ALIGN_TO_RESOLUTION)
    if alignToResolution:
        command += ' -a'
    alg.commands.append(command)
    return rootFilename

def regroupRasters(alg, field, groupField, subgroupField=None, extFile=None):
    """
    Group multiple input rasters into a group
    * If there is a subgroupField, a subgroup will automatically created.
    * When an external file is provided, the file is copied into the respective
      directory of the subgroup.
    * extFile is a dict of the form 'parameterName':'directory name'.
    """
    # List of rasters names
    rasters = alg.getParameterFromName(field)
    rastersList = rasters.value.split(';')
    alg.parameters.remove(rasters)

    # Insert a i.group command
    group = getParameterFromString("ParameterString|{}|group of rasters|None|False|False".format(groupField))
    group.value = alg.getTempFilename()
    alg.addParameter(group)

    if subgroupField:
        subgroup = getParameterFromString("ParameterString|{}|subgroup of rasters|None|False|False".format(subgroupField))
        subgroup.value = alg.getTempFilename()
        alg.addParameter(subgroup)

    command = 'i.group group={}{} input={}'.format(
        group.value,
        ' subgroup={}'.format(subgroup.value) if subgroupField else '',
        ','.join([alg.exportedLayers[f] for f in rastersList])
    )
    alg.commands.append(command)

    # Handle external files
    origExtParams = {}
    if subgroupField and extFile:
        for ext in extFile.keys():
            extFileName = alg.getParameterValue(ext)
            if extFileName:
                shortFileName = path.basename(extFileName)
                destPath = path.join(Grass7Utils.grassMapsetFolder(),
                                     'PERMANENT',
                                     'group', group.value,
                                     'subgroup', subgroup.value,
                                     extFile[ext], shortFileName)
            copyFile(alg, extFileName, destPath)
            origExtParams[ext] = extFileName
            alg.setParameterValue(ext, shortFileName)

    # modify parameters values
    alg.processCommand()

    # Re-add input rasters
    alg.addParameter(rasters)

    # replace external files value with original value
    for param in origExtParams.keys():
        alg.setParameterValue(param, origExtParams[param])

    # Delete group:
    alg.parameters.remove(group)
    if subgroupField:
        alg.parameters.remove(subgroup)
        return group.value, subgroup.value

    return group.value

def exportInputRasters(alg, rasterDic):
    """
    Export input rasters
    Use a dict to make input/output link:
    { 'inputName1': 'outputName1', 'inputName2': 'outputName2'}
    """
    # Get inputs and outputs
    for inputName, outputName in rasterDic.iteritems():
        inputRaster = alg.getParameterValue(inputName)
        outputRaster = alg.getOutputFromName(outputName)
        command = 'r.out.gdal -c -t -f --overwrite createopt="TFW=YES,COMPRESS=LZW" input={} output=\"{}\"'.format(
            alg.exportedLayers[inputRaster],
            outputRaster.value
        )
        alg.commands.append(command)
        alg.outputCommands.append(command)

def verifyRasterNum(alg, rasters, mini, maxi=None):
    """Verify if we have at least n rasters in multipleInput"""
    num = len(alg.getParameterValue(rasters).split(';'))
    if num < mini:
        return 'You need to set at least {} input rasters for this algorithm!'.format(mini)
    if maxi and num > maxi:
        return 'You need to set a maximum of {} input rasters for this algorithm!'.format(maxi)
    return None

def file2Output(alg, output):
    """Transform an OutputFile to a parameter"""
    # Get the outputFile
    outputFile = alg.getOutputFromName(output)
    alg.removeOutputFromName(output)

    # Create output parameter
    param = getParameterFromString("ParameterString|{}|output file|None|False|False".format(output))
    param.value = outputFile.value
    alg.addParameter(param)

    return outputFile

def createDestDir(alg, toFile):
    """ Generates an mkdir command for GRASS7 script """
    # Creates the destination directory
    command = "{} {}".format(
        "MD" if isWindows() else "mkdir -p",
        path.dirname(toFile)
    )
    alg.commands.append(command)

def moveFile(alg, fromFile, toFile):
    """ Generates a move command for GRASS7 script """
    createDestDir(alg, toFile)
    command = "{} {} {}".format(
        "MOVE /Y" if isWindows() else "mv -f",
        fromFile,
        toFile
    )
    alg.commands.append(command)

def copyFile(alg, fromFile, toFile):
    """ Generates a copy command for GRASS7 script """
    createDestDir(alg, toFile)
    command = "{} {} {}".format(
        "COPY /Y" if isWindows() else "cp -f",
        fromFile,
        toFile)
    alg.commands.append(command)


from .post_manager import PostManager
from app.data import post_response, posts_response, new_post_request

class NaiivePostManager(PostManager):
    def __init__(self):
        self.posts = []

    def list_posts(self):
        return posts_response.dump(self.posts)

    def get_post_by_id(self, id):
        p = next((p for p in self.posts if p["id"] == id), None)
        if not p:
            return "Not Found", 404
        else:
            return post_response.dump(p)

    def create_post(self, req):
        post = new_post_request.load(req)
        ids = [p.id for p in self.posts]
        if len(ids) == 0:
            ids = [-1]
        new_post = {
            **post,
            **{"id": max(ids) + 1, "slug": post["title"].replace(" ", "-").lower()},
        }
        self.posts.append(new_post)
        return new_post, 201

    def get_post_by_slug(self, slug: str):
        p = next((p for p in self.posts if p.get("slug", "") == slug), None)
        if not p:
            return "Not Found", 404
        else:
            return post_response.dump(p)


cu=[]
def fn(a,y):
    x=a+y
    cu.append(a)
    if x<100:
        return fn(y,x)
print(fn(0,1))
print(cu)
print()

#第二种：循环的方法
a=0
b=1
i=1
cu2 = []
while i<10:
    c=a+b
    # print(c)
    cu2.append(c)
    a=b
    b=c
    i += 1
print(cu2)
print()

#第三种：递归函数
def fi(n):
    if n<=1:
        return n
    else:
        return fi(n-1)+fi(n-2)
d=9
for i in range(d):
    print(fi(i))

函数编程函数练习10递归.py

函数编程函数练习10递归.py


import re
import os

def readFile():
    path = os.path.join(os.path.expanduser('~'), 'listaSadow', 'listaSadow.txt')
    with open(path,"r") as file:
        for line in file.readlines():
            yield line

def writeMongoCommand(listaCommand):
    path = os.path.join(os.path.expanduser('~'), 'listaSadow', 'dbPopulate.txt')
    with open(path,"w") as file:
        for i in listaCommand:
            file.write(i)
            file.write("\n")

court_name = "TT"
s = "Sąd Rejonowy w Wysokiem Mazowieckiem dla miasta Skarżysko-Kamienna oraz gmin: Bliżyn, Łączna, Skarżysko Kościelne i Suchedniów"

def takeBiggerIndex(index, list_of_indexes):
    for item in list_of_indexes:
        if index < item:
            return item
    return None

def takeString(s,start,stop):
    if stop:
        return s[start:stop]
    else:
        return s[start:]

def getCourtName(s:str):
    index_for = s.find("dla")
    court_name = takeString(s, 0,index_for)
    return court_name

def separate(s:str):
    index_city = s.find("miasta")
    index_region = s.find("gmina")
    index_city_part = s.find("dzielnic")
    indexes = [index_city,index_region,index_city_part]
    city = takeString(s,index_city,takeBiggerIndex(index_city,indexes))
    region = takeString(s,index_region,takeBiggerIndex(index_region,indexes))
    city_parts = takeString(s,index_city_part,takeBiggerIndex(index_city_part,indexes))
    # for item in twoString:
    #     if item.find("miast")>0:
    #         city=item
    #     elif item.find("dzielnic")>0:
    #         region = item
    #     else:
    #         dzielnic = item
    #     print(dzielnica)
    return {"city":city,"region":region, "city_parts": city_parts}

def generateListOfResults(s:str):
    strings= separate(s)
    citys = regexCreateArray(strings["city"])
    regions = regexCreateArray(strings["region"])
    city_parts = regexCreateArray(strings["city_parts"])
    return {"citys":citys,"regions":regions, "city_parts":city_parts}

def regexCreateArray(s):
    return re.findall(r"\b[A-ZŚĆĘŻŹ]\w+",s)

def createMongoCommand(s):
    name = getCourtName(s)
    generatedResults=generateListOfResults(s)
    citys = generatedResults["citys"]
    regions = generatedResults["regions"]
    city_parts = generatedResults["city_parts"]
    template = 'db.courtCollection.insert({{name:"{}", level:"rejonowy", coverCitys:{} coverRegions:{}, coverCityParts:{}}})'.format(name,citys,regions,city_parts)
    return template

def createObjToInsert(s):
    name = getCourtName(s)[0:-1]
    generatedResults=generateListOfResults(s)
    citys = generatedResults["citys"]
    regions = generatedResults["regions"]
    city_parts = generatedResults["city_parts"]
    obj = {"name":name, "level":"rejonowy", "coverCitys":citys, "coverRegions":regions, "coverCityParts":city_parts}
    return obj

# createMongoCommand(s)

# separate(s)

# readFile()
from random import randint
from pymongo import MongoClient

client = MongoClient("192.168.1.143", 27017)

db = client.dbs
def createInputToMongoDb():
    arrayWithCommands = []
    for line in readFile():
        comand = createMongoCommand(line)
        arrayWithCommands.append(comand)
        obj=createObjToInsert(line)
        print(obj)
        db.courtCollection.insert_one(obj)
    writeMongoCommand(arrayWithCommands)
    pass

# createInputToMongoDb()
# print(createObjToInsert(s))

def createCourtCollection():
    for i,line in enumerate(readFile()):
        # print(line)
        index = line.find(";")
        court_name = line[:index-1]
        wlasciwosc = line[index+5:]
        print(court_name)
        print(wlasciwosc)
        db.court.update_one({"name":court_name},{"$set":{"coverArea":wlasciwosc}})

        # if(i>10):
        #     return "koniec"
    pass

createCourtCollection()


import Pyro4
import Pyro4.naming
from xbmcjson import XBMC
import _thread as thread
from subprocess import run, PIPE
from evdev import UInput, InputEvent, ecodes as e
from time import sleep
import logging as log

from pulse_mute import Pulse

@Pyro4.expose
class RemoteServer(object):
    def __init__(self):
        self.ui = UInput()
        cap = {e.EV_REL: [e.REL_X, e.REL_Y]}
        cap = {
            e.EV_REL : (e.REL_X, e.REL_Y),
            e.EV_KEY : (e.BTN_MOUSE,),
        }
        self.mouse = UInput(cap)

    def run(self, args):
        proc = run(args, check=False, stdout=PIPE, stderr=PIPE)
        return (args, proc.returncode, proc.stderr,proc.stdout)

    def handshake(self):
        return

    @Pyro4.oneway
    def sleep(self):
        log.debug("Putting system to sleep")
        proc = run(["sudo","systemctl","suspend"], check=False)

    def keycombo(self,keys):
        for key in keys:
            self.ui.write(e.EV_KEY, key, 1)
        for key in keys:
            self.ui.write(e.EV_KEY, key, 0)
        self.ui.syn()

    def mouseaction(self, events):
        for ev in events:
            self.mouse.write(ev['type'],ev['code'],ev['value'])
        self.mouse.syn()

    def pause(self,appname):
        if appname == "spotify":
            return self.pause_spotify()
        elif appname == "kodi":
            return self.pause_kodi()

    def pause_spotify(self):
        log.debug("Pausing spotify")
        args = ["dbus-send", "--print-reply",
                "--dest=org.mpris.MediaPlayer2.spotify",
                "/org/mpris/MediaPlayer2",
                "org.mpris.MediaPlayer2.Player.Pause"]
        return self.run(args)

    def pause_kodi(self):
        log.debug("Pausing Kodi")
        kodi = XBMC("http://192.168.1.69:8080/jsonrpc")
        playerid_result = kodi.Player.GetActivePlayers()['result']
        if playerid_result:
            playerid = playerid_result[0]['playerid']
        else:
            return
        speed = kodi.Player.GetProperties(
            {'playerid':playerid,'properties':['speed']}
                )['result']['speed']
        if speed != 0:
            kodi.Player.PlayPause({'playerid': playerid})

    def mute_app(self, appname):
        Pulse.mute_input(appname)

    def unmute_app(self, appname):
        Pulse.unmute_input(appname)

    def pause_service(self,appname):
        log.debug("Suspending service: %s" % appname)
        args = ["systemctl","--user","kill","-s","STOP","%s.service" %appname]
        result = self.run(args)
        return result

    def continue_service(self,appname):
        log.debug("Resuming_ service: %s" % appname)
        args = ["systemctl","--user","kill","-s","CONT","%s.service" %appname]
        return self.run(args)

def init_log():
    log_format = '%(levelname)s:%(message)s'
    log_file = '/home/zteifel/remote/server.log'
    log.basicConfig(format=log_format, level=log.DEBUG,filename=log_file)

def start_nameserver():
    Pyro4.naming.startNSloop(host,port)

init_log()
log.info('Starting remote server')
host = "192.168.1.69"
port = 9093
thread.start_new_thread(start_nameserver,())
rs = RemoteServer()
daemon = Pyro4.Daemon(host)
rs_uri = daemon.register(rs)
ns = Pyro4.locateNS(host,port)
ns.register("zteifel.remoteserver", rs_uri)
daemon.requestLoop()


from __future__ import annotations

from typing import TypedDict

from movielog.reviews import serializer
from movielog.utils import export_tools, list_tools
from movielog.utils.logging import logger

StatGroup = TypedDict("StatGroup", {"reviewYear": str, "reviewsCreated": int})

def export() -> None:  # noqa: WPS210
    logger.log("==== Begin exporting {}...", "review stats")

    all_reviews = serializer.deserialize_all()

    stat_groups = [
        StatGroup(
            reviewYear="all",
            reviewsCreated=len(all_reviews),
        )
    ]

    reviews_by_year = list_tools.group_list_by_key(
        all_reviews, lambda review: str(review.date.year)
    )
    for year, reviews_for_year in reviews_by_year.items():
        stat_groups.append(
            StatGroup(
                reviewYear=str(year),
                reviewsCreated=len(reviews_for_year),
            )
        )

    export_tools.serialize_dicts_to_folder(
        dicts=stat_groups,
        folder_name="review_stats",
        filename_key=lambda stat_file: stat_file["reviewYear"],
    )


# Python3 program to illustrate deletion in a Binary Tree

# class to create a node with data, left child and right child.
class Node:
	def __init__(self,data):
		self.data = data
		self.left = None
		self.right = None

# Inorder traversal of a binary tree
def inorder(temp):
	if(not temp):
		return
	inorder(temp.left)
	print(temp.data, end = " ")
	inorder(temp.right)

# function to delete the given deepest node (d_node) in binary tree
def deleteDeepest(root,d_node):
	q = []
	q.append(root)
	while(len(q)):
		temp = q.pop(0)
		if temp is d_node:
			temp = None
			return
		if temp.right:
			if temp.right is d_node:
				temp.right = None
				return
			else:
				q.append(temp.right)
		if temp.left:
			if temp.left is d_node:
				temp.left = None
				return
			else:
				q.append(temp.left)

# function to delete element in binary tree
def deletion(root, key):
	if root == None :
		return None
	if root.left == None and root.right == None:
		if root.key == key :
			return None
		else :
			return root
	key_node = None
	q = []
	q.append(root)
	temp = None
	while(len(q)):
		temp = q.pop(0)
		if temp.data == key:
			key_node = temp
		if temp.left:
			q.append(temp.left)
		if temp.right:
			q.append(temp.right)
	if key_node :
		x = temp.data
		deleteDeepest(root,temp)
		key_node.data = x
	return root

# Driver code
if __name__=='__main__':
	root = Node(10)
	root.left = Node(11)
	root.left.left = Node(7)
	root.left.right = Node(12)
	root.right = Node(9)
	root.right.left = Node(15)
	root.right.right = Node(8)
	print("The tree before the deletion:")
	inorder(root)
	key = 8
	root = deletion(root, key)
	print()
	print("The tree after the deletion;")
	inorder(root)

# This code is contributed by Monika Anandan

Python3 program to illustrate deletion.py


import logging
import sys
import os

LOG_CONFIG = {
    'name': 'event-tracker',
    'level': logging.DEBUG,
    'stream_handler': logging.StreamHandler(sys.stdout),
    'format': '%(asctime)s: %(module)s: %(levelname)s: %(message)s'
}

TWITTER_CONFIG = {
    'api_key': os.environ["TWITTER_API_KEY"],
    'api_secret': os.environ["TWITTER_API_KEY_SECRET"],
    'bearer_token': os.environ["TWITTER_BEARER_TOKEN"],
}

REDDIT_CONFIG = {
    'client_id': os.environ["REDDIT_CLIENT_ID"],
    'client_secret': os.environ["REDDIT_CLIENT_SECRET"],
    'user_agent': os.environ["REDDIT_USER_AGENT"]
}

TELEGRAM_CONFIG = {
    'bot_token': os.environ["TELEGRAM_BOT_TOKEN"]
}


from random import randint
from time import sleep

def maior(*arg):
	arg = list(arg)
	if len(arg) == 0:
		arg.append(0)

	print('-=' * 30)
	print(f'Analisando valores passados...')
	for c in arg:
		print(c, flush=True, end=' ')
		sleep(0.07)
	print(f'Foram informados {len(arg)} valores ao todo.')

	maior = arg[0]
	for c in arg:
		if c >= maior:
			maior = c
	print(f'O maior valor informado foi {maior}')

if __name__ == "__main__":
	maior(2, 9, 4, 5, 7, 1)
	maior(4, 7, 0)
	maior(1, 2)
	maior(6)
	maior()


import sys
import rdkit
from argparse import ArgumentParser
from rdkit import Chem, DataStructs
from rdkit.Chem import AllChem

import pandas as pd

pred_mols = pd.read_csv('',
                        header=None).values.reshape(-1)

ref_path = 'actives.txt'

with open(ref_path) as f:
    next(f)
    true_mols = [line.split(',')[0] for line in f]
print('number of active reference', len(true_mols))

true_mols = [Chem.MolFromSmiles(s) for s in true_mols]
true_mols = [x for x in true_mols if x is not None]
true_fps = [AllChem.GetMorganFingerprintAsBitVect(x, 3, 2048) for x in true_mols]

pred_mols = [Chem.MolFromSmiles(s) for s in pred_mols]
pred_mols = [x for x in pred_mols if x is not None]
pred_fps = [AllChem.GetMorganFingerprintAsBitVect(x, 3, 2048) for x in pred_mols]

fraction_similar = 0

sim_distribution = []
for i in range(len(pred_fps)):
    sims = DataStructs.BulkTanimotoSimilarity(pred_fps[i], true_fps)

    if max(sims) >= 0.4:
        fraction_similar += 1
    sim_distribution.append(max(sims))

print('novelty:', 1 - fraction_similar / len(pred_mols))

similarity = 0
for i in range(len(pred_fps)):
    sims = DataStructs.BulkTanimotoSimilarity(pred_fps[i], pred_fps[:i])
    similarity += sum(sims)

n = len(pred_fps)
n_pairs = n * (n - 1) / 2
diversity = 1 - similarity / n_pairs
print('diversity:', diversity)


# -*- coding: utf-8 -*-
"""
Created on Wed Sep 29 13:12:03 2021

@author: thuang

Plots the sensitivity delta = master_branch - my_branch
for 1e3 and 1e4.
"""

from matplotlib import pyplot as plt
import numpy as np

class delta_bars:

    def __init__(self, data_dict, tolerance):
        """
        Parameters
        ----------

        data_dict : dictionary
            A dictionary containing the data to write to the Excel file.
            Dictionary shall contain: {'names':[name1, name2], mode_id:{t1_blf:{'T1': t1, 'BLF': blf, 'name1':[1e3, 1e4], 'name2':[1e3, 1e4], 'delta':[1e3, 1e4]}}}

        Returns
        -------
        None.

        """
        self.data_dict = data_dict.copy()
        self.tolerance = tolerance

    def plot_delta(self):
        """
        Plots the delta for each scenario of each mode as a bar graph.
        """

        self.data_dict.pop('names', None)

        num_modes = len(self.data_dict) #number of modes
        num_cols = int(np.ceil(np.sqrt(num_modes))) #make the plot grid as square as possible to save space
        num_rows = num_cols
        fig1, *ax = plt.subplots(num_rows, num_cols)
        fig1.tight_layout()

        if num_cols*num_rows>1: #if only one axis, then can't flatten
            ax = ax[0].flatten('F')

        if num_modes < len(ax): #remove excess axes exceeding the number of plots
            for this_ax in ax[num_modes:]:
                this_ax.remove()

        for n, mode_id in enumerate(self.data_dict.keys()):
            labels = []
            delta_e3 = []
            delta_e4 = []
            for t1_blf in self.data_dict[mode_id].keys():
                labels += [self.data_dict[mode_id][t1_blf]['T1'] + ',' + self.data_dict[mode_id][t1_blf]['BLF']]
                delta_e3 += [self.data_dict[mode_id][t1_blf]['delta'][0]]
                delta_e4 += [self.data_dict[mode_id][t1_blf]['delta'][1]]
            ax[n].bar(np.arange(len(labels)), delta_e3, tick_label=labels, color='tab:blue', width=.25)
            ax[n].bar(np.arange(len(labels))+.25, delta_e4, tick_label=labels, color='tab:red', width=.25)
            ax[n].legend(['1e-3', '1e-4'], fontsize='xx-large')
            ax[n].grid(True, which='both', axis='both')
            ax[n].set_xlabel('T1, BLF', fontsize='xx-large')
            ax[n].set_ylabel(chr(916)+'sensitivity (dBm)', fontsize='xx-large')
            if (np.array(delta_e3) < -self.tolerance).any():
                ax[n].set_title(f'Mode {mode_id}', fontsize='xx-large', color='red')
            else:
                ax[n].set_title(f'Mode {mode_id}', fontsize='xx-large', color='green')
            ax[n].tick_params(axis='both', labelsize='xx-large')
            ax[n].minorticks_on()


# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""
Utility methods for serializing responses
"""

import datetime

from oslo_config import cfg
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import encodeutils
import webob

from senlin.common import exception
from senlin.common.i18n import _

LOG = logging.getLogger(__name__)

def is_json_content_type(request):

    content_type = request.content_type
    if not content_type or content_type.startswith('text/plain'):
        content_type = 'application/json'

    if (content_type in ('JSON', 'application/json') and
            request.body.startswith(b'{')):
        return True
    return False

class JSONRequestDeserializer(object):

    def has_body(self, request):
        """Return whether a Webob.Request object will possess an entity body.

        :param request: A Webob.Request object
        """
        if request is None or request.content_length is None:
            return False

        if request.content_length > 0 and is_json_content_type(request):
            return True

        return False

    def from_json(self, datastring):
        try:
            if len(datastring) > cfg.CONF.senlin_api.max_json_body_size:
                msg = _('JSON body size (%(len)s bytes) exceeds maximum '
                        'allowed size (%(limit)s bytes).'
                        ) % {'len': len(datastring),
                             'limit': cfg.CONF.senlin_api.max_json_body_size}
                raise exception.RequestLimitExceeded(message=msg)
            return jsonutils.loads(datastring)
        except ValueError as ex:
            raise webob.exc.HTTPBadRequest(str(ex))

    def default(self, request):
        if self.has_body(request):
            return {'body': self.from_json(request.body)}
        else:
            return {}

class JSONResponseSerializer(object):

    def to_json(self, data):
        def sanitizer(obj):
            if isinstance(obj, datetime.datetime):
                return obj.isoformat()
            return str(obj)

        response = jsonutils.dumps(data, default=sanitizer, sort_keys=True)
        LOG.debug("JSON response : %s", response)
        return response

    def default(self, response, result):
        response.content_type = 'application/json'
        response.body = encodeutils.safe_encode(self.to_json(result))


import time
import pyupm_grove as grove
import mraa

def AirRead():
    air = mraa.Aio(2)
    airValue = air.read()
    return airValue

# Create the temperature sensor object using AIO pin 0
def TemperatureRead():
    temp = grove.GroveTemp(0)
    celsius = temp.value()
    fahrenheit = celsius * 9.0/5.0 + 32.0;
    return celsius,fahrenheit
# Read the temperature ten times, printing both the Celsius and
# equivalent Fahrenheit temperature, waiting one second between readings

def ControlRelay(flag):
    relay = mraa.Gpio(62) # GPIO_51
    relay.dir(mraa.DIR_OUT)
    if flag == 1:
        relay.write(1)
    else:
        relay.write(0)

if __name__ == "__main__":
    while True:
        print(AirRead())
        print(TemperatureRead())
        ControlRelay(1)
        time.sleep(1)
        ControlRelay(0)
        time.sleep(1)


import os
import numpy as np
import pickle
import open3d as o3d
from absl import app
from absl import flags

flags.DEFINE_string('task', 'stack-block-pyramid', '')
flags.DEFINE_string('data_dir', './training_datasets/voxel_grids', '')
flags.DEFINE_string('data_source', './training_datasets/rgbd', '')
flags.DEFINE_integer('num_per_class', '100', '')

FLAGS = flags.FLAGS

def normalize(arr):
    """
    normalize an array to [0, 1]
    """
    arr_min = arr.min()
    arr_max = arr.max()
    return (arr - arr_min) / (arr_max - arr_min)

def load_rgb_segm_depth(path, num):

  rgb_image_batches = []
  # segm_image_batches = []
  depth_image_batches = []
  class_paths = []
  file_name_batches = []

  sub_paths = os.listdir(path)

  data_types = ['positive', 'negative']

  img_types = ['color', 'depth']

  for sub_path in sub_paths:
    for data_type in data_types:

      rgb_images = []
      # segm_images = []
      depth_images = []
      file_names = []
      class_path = os.path.join(path, sub_path, data_type)
      print(class_path)

      for img_type in img_types:

        img_path = os.path.join(class_path, img_type)
        images = os.listdir(img_path)
        for i ,img_name in enumerate(images):
          if i == num:
            break

          with open(os.path.join(img_path, img_name), 'rb') as f:
            file_names.append(img_name[:img_name.find('.')])
            img = pickle.load(f)

          if img_type == 'color':
            rgb_images.append(img)
          # elif img_type == 'segm':
          #   segm_images.append(img)
          elif img_type == 'depth':
            depth_images.append(img)

      rgb_image_batches.append(rgb_images)
      # segm_image_batches.append(segm_images)
      depth_image_batches.append(depth_images)
      file_name_batches.append(file_names)
      class_paths.append(class_path)

  return rgb_image_batches, depth_image_batches, file_name_batches, class_paths

def rgbd_to_voxel_grids(rgb_img, depth_img):

  rgbd_img = o3d.geometry.RGBDImage.create_from_color_and_depth(
    o3d.geometry.Image(rgb_img),
    o3d.geometry.Image(depth_img),
    convert_rgb_to_intensity=False)

  # x_dim = 50
  # y_dim = 45
  # z_dim = 100

  x_dim = 35
  y_dim = 30
  z_dim = 70

  # # xyz
  # camera_pose = np.array([[-6.12323400e-17, -1.00000000e+00,  1.22464680e-16, 1],
  #       [-7.07106781e-01,  1.29893408e-16,  7.07106781e-01, 0],
  #       [-7.07106781e-01, -4.32978028e-17, -7.07106781e-01, 0.75],
  #       [0,0,0,1]])

  #xzy
  camera_pose = np.array([[-6.12323400e-17, -1.22464680e-16,  1.00000000e+00,1 ],
  [-7.07106781e-01, -7.07106781e-01, -1.29893408e-16,0],
  [ 7.07106781e-01, -7.07106781e-01, -4.32978028e-17,0.75],
  [0,0,0,1]])

  intrinsic_matrix = np.array([[450., 0, 320.],
                                    [0, 450., 240.],
                                    [0, 0, 1]])
  camera_intrinsic = o3d.camera.PinholeCameraIntrinsic(640, 480, intrinsic_matrix)

  pcd = o3d.geometry.PointCloud.create_from_rgbd_image(
      rgbd_img, camera_intrinsic, camera_pose)

  # o3d.visualization.draw_geometries([pcd])
  min_bound = pcd.get_min_bound()
  max_bound = pcd.get_max_bound()

  min_bound[0] += 0.000
  max_bound[0] -= 0.0018

  min_bound[1] += 0.00000105
  max_bound[1] -= 0.000275

  min_bound[2] += 0.0011
  max_bound[2] -= 0.0011

  cropping_bound = o3d.geometry.AxisAlignedBoundingBox(min_bound, max_bound)

  # Crop the point cloud using the bounding box
  cropped_point_cloud = pcd.crop(cropping_bound)

  # o3d.visualization.draw_geometries([cropped_point_cloud])

  # Get point cloud coordinates
  points = np.asarray(cropped_point_cloud.points)

  # Get point cloud colors
  colors = np.asarray(cropped_point_cloud.colors)

  # Define voxel size
  # voxel_size = 0.0000105
  voxel_size = 0.000015

  # Calculate voxel grid dimensions
  max_bound = np.max(points, axis=0)
  min_bound = np.min(points, axis=0)
  dimensions = np.ceil((max_bound - min_bound) / voxel_size)

  print(f'dimentsions: {dimensions}')
  # Calculate voxel grid indices for each point
  indices = np.floor((points - min_bound) / voxel_size)

  # Initialize voxel grid with zeros
  voxel_grid = np.zeros((int(dimensions[0]), int(dimensions[1]), int(dimensions[2]), 3))

  # Fill voxel grid with colors
  for i in range(points.shape[0]):
      voxel_grid[int(indices[i][0]), int(indices[i][1]), int(indices[i][2])] = colors[i]

  # Convert voxel grid to 3D numpy array
  voxel_grid = np.asarray(voxel_grid)
  voxel_grid = np.pad(voxel_grid, ((0, x_dim-voxel_grid.shape[0]), (0, y_dim-voxel_grid.shape[1]), (0, z_dim-voxel_grid.shape[2]), (0, 0)), mode='constant')

  return voxel_grid

def main(unused_argv):
  rgb_image_batches, depth_image_batches, file_name_batches, class_paths = load_rgb_segm_depth(os.path.join(FLAGS.data_source, FLAGS.task), FLAGS.num_per_class)

  for idx, class_path in enumerate(class_paths):
    for n in range(FLAGS.num_per_class):
      print(f'Processing {class_path}...')

      voxel_grid = rgbd_to_voxel_grids(rgb_image_batches[idx][n], depth_image_batches[idx][n])

      voxel_grid = np.mean(voxel_grid, axis=-1, keepdims=True)
      # voxel_grid = voxel_grid.reshape(25, 20, 50)

      save_path = os.path.join(FLAGS.data_dir, class_path)
      if not os.path.exists(save_path):
          os.makedirs(save_path)

      # save_path = os.path.join(file_path, file_name[:file_name.find('.')] + '.npy')
      # voxel_grid = np.mean(voxel_grid, axis=-1, keepdims=True)
      np.save(os.path.join(save_path, file_name_batches[idx][n] + '.npy'), voxel_grid)

if __name__ == '__main__':
  app.run(main)


from typing import List

class AES:

    def __init__(self, plainText:str, key:str) -> None:
        self.plainText = plainText
        self.key = key
        self.keyBytes = b''

    def __pad(self, input:bytes) -> bytes:
        length = 16 - (len(input) % 16)
        paddedInput = input
        paddedInput += bytes([length])*length
        return paddedInput

    def __unpad(self, input:bytes) -> bytes:
        unpadInput = input[:-input[-1]]
        return unpadInput

    def __leftRotate(self, arr:bytes, n) -> bytes:
        n = n % len(arr)
        return arr[n:] + arr[:n]

    def __g(self, word:bytes) -> bytes:
        result = b''
        rotatedWord = self.__leftRotate(word,1)
        return result

    def __generateRoundKeys(self) -> None:
        # 16 byte key divided into 4 words
        w0 = self.key[:4]
        w1 = self.key[4:8]
        w2 = self.key[8:12]
        w3 = self.key[12:16]

    def encrypt(self) -> None:
        pt = self.plainText.encode()
        if len(pt) > 16:
            print("Plaintext should be less than 16 bytes")
            return
        bytesKey = self.key.encode()
        self.keyBytes = bytesKey
        if len(bytesKey) != 16:
            print("Key should be exactly 16 bytes")
            return
        paddedByteText = self.__pad(pt)
        self.__generateRoundKeys()

    def decrypt(self) -> None:
        pass


"""
This script is meant to be iterated many times to replicate the spawning of many error popups.
"""

from PySide2 import QtWidgets
import random
from PySide2.QtWidgets import QMainWindow, QApplication
from PySide2.QtGui import QIcon
from configparser import ConfigParser
import sys
app = QApplication(sys.argv)
appcfg = ConfigParser()
appcfg.read('configs/appsettings.ini')

if appcfg.getint('popup_properties', 'popup_style_index') == 0:
    app.setStyle('windowsvista')
elif appcfg.getint('popup_properties', 'popup_style_index') == 1:
    app.setStyle('Fusion')
elif appcfg.getint('popup_properties', 'popup_style_index') == 2:
    app.setStyle('Windows')

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.msg = QtWidgets.QMessageBox(self)
        self.msg.setWindowTitle(appcfg.get('popup_strings', 'popup_win_title'))
        self.msg.setText(appcfg.get('popup_strings', 'popup_message'))
        self.msg.move(random.randint(0, 1000), random.randint(0, 600))
        if appcfg.getint('popup_properties', 'popup_type_index') == 0:
            self.msg.setIcon(QtWidgets.QMessageBox.Information)
        elif appcfg.getint('popup_properties', 'popup_type_index') == 1:
            self.msg.setIcon(QtWidgets.QMessageBox.Question)
        elif appcfg.getint('popup_properties', 'popup_type_index') == 2:
            self.msg.setIcon(QtWidgets.QMessageBox.Warning)
        elif appcfg.getint('popup_properties', 'popup_type_index') == 3:
            self.msg.setIcon(QtWidgets.QMessageBox.Critical)
        self.setWindowIcon(QIcon(appcfg.get('popup_properties', 'popup_icon_path')))
        self.msg.exec_()
        sys.exit()

def window():
    global app
    MainWindow()

    sys.exit(app.exec_())

window()


'''
72. 두 정수의 합

두 정수 a와 b의 합을 구하라. + 또는 - 연산자는 사용할 수 없다.

'''

class Solution:
    def getSum(self, a: int, b: int) -> int:

        mask = 0xffffffff

        while (b & mask) > 0:

            carry = ( a & b ) << 1

            a = (a ^ b) # XOR 연산
            b = carry

        return (a & mask) if b > 0 else a
    # 28 ms

# 납득이 잘 가지 않는다...