import tempfile
import unittest

from brkga_mp_ipr.types import *
from brkga_mp_ipr.types_io import *
from tests.paths_constants import *

class Test(unittest.TestCase):
    """
    Test units for types I/O functions.
    """

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

    def setUp(self):
        """
        Set up some configurations.
        """

        Test.maxDiff = None

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

    def test_load_configuration(self):
        """
        Test load functions.
        """

        self.assertRaises(IsADirectoryError, load_configuration, ".")
        self.assertRaises(FileNotFoundError, load_configuration, "")

        filename = os.path.join(CONFIG_DIR, "empty.conf")
        with self.assertRaises(LoadError) as context:
            load_configuration(filename)
        self.assertEqual(str(context.exception).strip(),
                         f"Cannot read {filename}")

        filename = os.path.join(CONFIG_DIR, "unknown_param.conf")
        with self.assertRaises(LoadError) as context:
            load_configuration(filename)
        self.assertEqual(str(context.exception).strip(),
                         "Line 25: parameter 'population_sizee' unknown")

        filename = os.path.join(CONFIG_DIR, "missing_value.conf")
        with self.assertRaises(LoadError) as context:
            load_configuration(filename)
        self.assertEqual(str(context.exception).strip(),
                         "Line 25: missing parameter or value")

        filename = os.path.join(CONFIG_DIR, "wrong_type.conf")
        with self.assertRaises(LoadError) as context:
            load_configuration(filename)
        self.assertEqual(str(context.exception).strip(),
                         "Line 25: invalid value for 'population_size': 500.123")

        filename = os.path.join(CONFIG_DIR, "wrong_bias_function.conf")
        with self.assertRaises(LoadError) as context:
            load_configuration(filename)
        self.assertEqual(str(context.exception).strip(),
                         "Line 40: invalid value for 'bias_type': loginvrse")

        filename = os.path.join(CONFIG_DIR, "wrong_pr_selection.conf")
        with self.assertRaises(LoadError) as context:
            load_configuration(filename)
        self.assertEqual(str(context.exception).strip(),
                         "Line 55: invalid value for 'pr_selection': worseones")

        filename = os.path.join(CONFIG_DIR, "missing_param.conf")
        with self.assertRaises(LoadError) as context:
            load_configuration(filename)
        self.assertEqual(str(context.exception).strip(),
                         "Missing parameters: population_size, mutants_percentage, total_parents, bias_type")

        brkga_params, control_params = \
            load_configuration(os.path.join(CONFIG_DIR, "regular.conf"))

        self.assertEqual(brkga_params.population_size, 500)
        self.assertEqual(brkga_params.elite_percentage, 0.30)
        self.assertEqual(brkga_params.mutants_percentage, 0.15)
        self.assertEqual(brkga_params.num_elite_parents, 2)
        self.assertEqual(brkga_params.total_parents, 3)
        self.assertEqual(brkga_params.bias_type, BiasFunctionType.LOGINVERSE)
        self.assertEqual(brkga_params.num_independent_populations, 3)
        self.assertEqual(brkga_params.pr_number_pairs, 0)
        self.assertEqual(brkga_params.pr_minimum_distance, 0.15)
        self.assertEqual(brkga_params.pr_type, PathRelinkingType.PERMUTATION)
        self.assertEqual(brkga_params.pr_selection, PathRelinkingSelection.RANDOMELITE)
        self.assertEqual(brkga_params.alpha_block_size, 1.0)
        self.assertEqual(brkga_params.pr_percentage, 1.0)
        self.assertEqual(control_params.exchange_interval, 200)
        self.assertEqual(control_params.num_exchange_indivuduals, 2)
        self.assertEqual(control_params.reset_interval, 600)

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

    def test_write_configuration(self):
        """
        Test write functions.
        """

        #########################
        # From config file
        #########################

        brkga_params, control_params = \
            load_configuration(os.path.join(CONFIG_DIR, "regular.conf"))

        self.assertRaises(PermissionError, write_configuration,
                          "/invalid", brkga_params, control_params)

        self.assertRaises(IsADirectoryError, write_configuration,
                          ".", brkga_params, control_params)

        tmp = tempfile.NamedTemporaryFile(mode="r")
        write_configuration(tmp.name, brkga_params, control_params)

        tmp.seek(0)
        result = tmp.read().lower()
        tmp.close()

        standard = """population_size 500
elite_percentage 0.3
mutants_percentage 0.15
num_elite_parents 2
total_parents 3
bias_type loginverse
num_independent_populations 3
pr_number_pairs 0
pr_minimum_distance 0.15
pr_type permutation
pr_selection randomelite
alpha_block_size 1.0
pr_percentage 1.0
exchange_interval 200
num_exchange_indivuduals 2
reset_interval 600
"""
        self.assertEqual(result, standard)

        #########################
        # TODO: From direct building
        #########################

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

if __name__ == "__main__":
    unittest.main()


"""
@author     Arthur Allshire
@email      arthur.allshire@mail.utoronto.ca
@author     Mayank Mittal
@email      mittalma@ethz.ch

@brief Defines argparse utilities for RL-games adapter.
"""

# isaacgym
from isaacgym import gymapi
from isaacgym import gymutil
# leibizgym
from leibnizgym.utils.helpers import update_dict, get_resources_dir
from leibnizgym.utils.errors import InvalidTaskNameError
from leibnizgym.utils.message import *
# python
from typing import Dict
import argparse
import os
import yaml

def join_config_path(config_name: str, base_path: str = None) -> str:
    """Concatenates the configuration for RL games directory.

    Args
        config_name: The name of the configuration file to load.
        base_path: The path where config is stored (default: `resources/config`)

    Returns
        The joined path for RL games config file.
    """
    # check for base path: default 'resources/config'
    if base_path is None:
        base_path = os.path.join(get_resources_dir(), 'config')
    # config file name
    config_filename = os.path.join(base_path, config_name)
    # check if path exists
    if not os.path.exists(config_filename):
        msg = f"Configuration file not found: {config_filename}"
        print_error(msg)
        raise ValueError(msg)

    return config_filename

def retrieve_cfg_paths(args: argparse.Namespace) -> (str, str, str):
    """Returns the config paths for agent and environment based on the args.

    TODO (@mayank): Simplify the passing of args everywhere.

    Args:
        args: command line arguments
    Returns:
        (logdir path, train config dict, task config dict)
    """
    # get task configuration file.
    if args.task == "Trifinger":
        # print task related args input
        print_info(f"[Trifinger]: Task difficulty : {args.task_variant}")
        print_info(f"[Trifinger]: Training type   : {args.training_type}")
        # directory to save logs in (tensorboard>?)
        logdir = os.path.join(args.logdir, "trifinger")
        # path where gym config is stored
        trifinger_path = os.path.join(get_resources_dir(), 'config', 'trifinger')
        # complete file name for yaml config
        task_cfg_file = join_config_path(f"difficulty_{args.task_variant}.yaml",
                                         base_path=os.path.join(trifinger_path, 'gym'))
        # resolve training config for environment
        agent_cfg_file = join_config_path(f"{args.training_type}_ppo.yaml",
                                          base_path=os.path.join(trifinger_path, 'rlg'))
    else:
        raise InvalidTaskNameError(args.task)
    # print the files being loaded
    print_notify(f"Task config : {task_cfg_file}")
    print_notify(f"Agent config: {agent_cfg_file}")
    # return the paths
    return logdir, agent_cfg_file, task_cfg_file

def load_cfg(args: argparse.Namespace) -> (Dict, Dict, str):
    """Loads the config given the args

    Args:
        args: command line arguments
    Returns:
        (environment_config, rl_games_config, logdir)
    """
    # get paths to various logging and configurations
    logdir, cfg_train_pth, cfg_env_pth = retrieve_cfg_paths(args)
    # load task config dictionary
    with open(os.path.join(os.getcwd(), cfg_env_pth), 'r') as f:
        cfg = yaml.load(f, Loader=yaml.SafeLoader)
    # load agent config dictionary
    with open(os.path.join(os.getcwd(), cfg_train_pth), 'r') as f:
        cfg_train = yaml.load(f, Loader=yaml.SafeLoader)

    print(args)

    return update_cfg(cfg, cfg_train, logdir, args)

def update_cfg(cfg, cfg_train, logdir, args):
    # Override settings if passed by the command line
    # Override number of environments
    if args.num_envs > 0:
        cfg["num_instances"] = args.num_envs
    # Override episode length
    if args.episode_length > 0:
        cfg["episode_length"] = args.episode_length
    # Override the physics engine
    cfg["physics_engine"] = 'physx' if args.physics_engine == gymapi.SIM_PHYSX else 'flex'
    # Override the phyiscs settings
    # NOTE: All arg params are overriden if they are provided in the YAML config, except number of threads.
    args_sim_settings = {
        "dt": 1.0 / 60.0,
        "use_gpu_pipeline": args.device == "GPU",
        "num_client_threads": args.slices,
        "flex": {
            "shape_collision_margin": 0.01,
            "num_outer_iterations": 4,
            "num_inner_iterations": 10
        },
        "physx": {
            "solver_type": 1,
            "num_position_iterations": 4,
            "num_velocity_iterations": 0,
            "num_threads": 4,
            "use_gpu": args.use_gpu,
            "num_subscenes": args.subscenes,
            "max_gpu_contact_pairs": 8 * 1024 * 1024,
        }
    }
    # if yaml config has sim settings, override above args settings
    try:
        cfg["sim"] = update_dict(args_sim_settings, cfg["sim"])
    except AttributeError:
        cfg["sim"] = args_sim_settings
    # Override number of threads for physics if passed by CLI
    if args.physics_engine == gymapi.SIM_PHYSX and args.num_threads > 0:
        cfg["sim"]["physx"]["num_threads"] = args.num_threads
    # Override domain randomization
    # TODO (@arthur): DR for leibnizgym
    # if "task" in cfg:
    #     if "randomize" not in cfg["task"]:
    #         cfg["task"]["randomize"] = args.randomize
    #     else:
    #         cfg["task"]["randomize"] = args.randomize or cfg["task"]["randomize"]
    # else:
    #     cfg["task"] = {"randomize": False}

    # Set cfg to enable asymmetric training
    if "asym" in args.training_type:
        cfg["asymmetric_obs"] = True

    # %% RLG config
    exp_name = cfg_train["params"]["config"]['name']
    #  Override experiment name
    if args.experiment_name != 'Base':
        exp_name = f"{args.experiment_name}_{args.task_type}_{args.device}_{str(args.physics_engine).split('_')[-1]}"
    # if cfg["task"]["randomize"]:
    #     exp_name += "_DR"
    cfg_train["params"]["config"]['name'] = exp_name
    # Set number of environment instances
    if "num_instances" in cfg:
        cfg_train["params"]["config"]["minibatch_size"] = cfg["num_instances"]
        cfg_train["params"]["config"]["num_actors"] = cfg["num_instances"]
        # Set minibatch size for central value config
        if "central_value_config" in cfg_train["params"]["config"]:
            cfg_train["params"]["config"]["central_value_config"]["minibatch_size"] = cfg["num_instances"]
    else:
        msg = "Must provide num_instances for rl_games to work, either in config or via `num_envs` argument."
        raise ValueError(msg)
    # Check if continue training for loaded checkpoint
    if args.resume > 0:
        cfg_train["params"]["load_checkpoint"] = True
    # Set maximum number of training iterations (epochs)
    if args.max_iterations > 0:
        cfg_train["params"]["config"]['max_epochs'] = args.max_iterations

    # acquire seed from the agent configuration dict
    try:
        seed = cfg_train.get("params").get("seed", 42)
    except AttributeError:
        seed = cfg_train.get("seed", 42)
    # Override the seed for both agent and task
    if args.seed > 0:
        seed = args.seed
    cfg["seed"] = seed
    cfg_train["seed"] = seed

    return cfg, cfg_train, logdir

def get_args(benchmark: bool = False, use_rlg_config: bool = False) -> argparse.Namespace:
    """Defines the custom args for argparsing and parses them.

    Args:
        benchmark: Add additional params for benchmarking the environment.
        use_rlg_config: Add RL-games specfic params or not.

    Returns:
        Parsed CLI arguments.
    """
    custom_parameters = [
        # sets verbosity of the run
        {"name": "--verbose", "action": "store_true", "default": False,
         "help": "Set verbosity of the environment (useful for debugging)."},
        # sets whether to train/test
        {"name": "--test", "action": "store_true", "default": False,
         "help": "Run trained policy, no training"},
        # sets whether to train further or test with provided NN weights
        {"name": "--resume", "type": int, "default": 0,
         "help": "Resume training or start testing from a checkpoint"},
        # sets whether to run GUI for visualization or not.
        {"name": "--headless", "action": "store_true", "default": False,
         "help": "Force display off at all times"},
        # sets the name of the task
        {"name": "--task", "type": str, "default": "Trifinger",
         "help": "Task supported: ['Trifinger'] "},
        # sets the task variant to run
        {"name": "--task_variant", "type": str, "default": "1",
         "help": "Task-specific config, eg for Trifinger allows setting difficulty"},
        # sets the training type such as asymm, LSTM etc.
        {"name": "--training_type", "type": str, "default": "vanilla",
         "help": "choose type of training to be used, allows choosing eg. asymm, LSTM, etc."},
        # sets the task type: that is implementation language
        {"name": "--task_type", "type": str, "default": "Python",
         "help": "Choose Python or C++"},
        # sets the device for the environment
        {"name": "--device", "type": str, "default": "GPU",
         "help": "Choose CPU or GPU device for running physics"},
        # sets the device for the RL agent
        {"name": "--ppo_device", "type": str, "default": "GPU",
         "help": "Choose CPU or GPU device for inferencing PPO network"},
        # sets the directory to log data into
        {"name": "--logdir", "type": str, "default": "logs/"},
        # sets the experiment name
        {"name": "--experiment_name", "type": str, "default": "Base"},
        # sets the training config file
        {"name": "--cfg_train", "type": str, "default": "Base",
         "help": "Agent training config file path"},
        # sets the config environment file
        {"name": "--cfg_env", "type": str, "default": "Base",
         "help": "Environment config file path"},
        # sets the seed of the experiment
        {"name": "--seed", "type": int, "default": -1,
         "help": "Random seed"},
        # sets maximum number of training iterations
        {"name": "--max_iterations", "type": int, "default": 0,
         "help": "Set a maximum number of training iterations"},
        # sets the number of instances to run
        {"name": "--num_envs", "type": int, "default": 0,
         "help": "Number of environments to create - override config file"},
        # sets maximum number of steps in episode
        {"name": "--episode_length", "type": int, "default": 0,
         "help": "Episode length, by default is read from yaml config"},
        # checks applying of physics DR
        {"name": "--randomize", "action": "store_true", "default": False,
         "help": "Apply physics domain randomization"}]

    # configurations specfic for RL-games
    if use_rlg_config:
        # sets whether to train/test
        custom_parameters += [
            {"name": "--play", "action": "store_true", "default": False,
             "help": "Run trained policy, the same as test, can be used only by rl_games RL library"},
            # sets the checkpoint point path to load weights from
            {"name": "--checkpoint", "type": str, "default": "",
             "help": "Path to the saved weights, only for rl_games RL library"},
        ]

    # further config for benchmarking the running
    if benchmark:
        custom_parameters += [
            # number of processes to run
            {"name": "--num_proc", "type": int, "default": 1, "help": "Number of child processes to launch"},
            # whether to apply random actions or not
            {"name": "--random_actions", "action": "store_true",
             "help": "Run benchmark with random actions instead of inferencing"},
            # number of timing reports for benchmark
            {"name": "--bench_len", "type": int, "default": 10,
             "help": "Number of timing reports"},
            # name of the benchamrking file to dump results into
            {"name": "--bench_file", "action": "store", "help": "Filename to store benchmark results"}]

    # parse arguments
    args = gymutil.parse_arguments(description="RL Policy Training using Leibnizgym",
                                   custom_parameters=custom_parameters)
    # check if run is training/test/play
    if args.test:
        args.play = args.test
        args.train = False
    elif args.play:
        args.train = False
    else:
        args.train = True
    # return parsed arguments
    return args


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@author: Andrés Montoro Montarroso
@author: Pedro Manuel Gómez-Portillo
"""

import matplotlib.pyplot as plt
import sklearn.neighbors
import numpy
import sklearn.cluster
from sklearn import metrics

#Filtering inc2006.csv by accidents
def filter():
    with open('data/inc2006.csv', 'r') as f_in:
        with open('data/inc2006filt.csv', 'w') as f_out:
            lines = f_in.readlines()
            for i in range(len(lines)):
                if "Accidente" in lines[i]:
                    f_out.write(lines[i])
filter()

#Plottering data by clusters
def plotdata(data, labels, name):
    fig, ax = plt.subplots()
    plt.scatter([row[0] for row in data], [row[1] for row in data], c=labels)
    ax.grid(True)
    fig.tight_layout()
    plt.title(name)
    plt.show()

#Creating file only with latitude and longitude
X = []
with open ('data/inc2006filt.csv','r') as file_filter:
    for line in file_filter:
        cadena = line.split(";")
        data=[cadena[2],cadena[12]]
        X.append(data)

#Creating two vector, one with lat. and with long.
miX = []
miY=[]
for e in X:
    miX.append(e[0])
    miY.append(e[1])

plt.scatter(miX, miY)
plt.show()

#Creating the graph with the distribution in order to see de inflexion point
dist = sklearn.neighbors.DistanceMetric.get_metric('euclidean')
matsim = dist.pairwise(X)

minPts=5
"""
A = sklearn.neighbors.kneighbors_graph(X, minPts, include_self=False)
Ar = A.toarray()

seq = []
for i,s in enumerate(X):
    for j in range(len(X)):
        if Ar[i][j] != 0:
            seq.append(matsim[i][j])

seq.sort()
plt.plot(seq)
plt.show()
"""
#plotting the clusters
labels = sklearn.cluster.DBSCAN(eps=0.0075, min_samples=minPts).fit_predict(X)

# 3. Plot the results
plotdata(X,labels, 'dbscan')

print("Number of clusters: {}".format(len(set(labels)) - (1 if -1 in labels else 0)))

# 4. Validation
print("Silhouette Coefficient: %0.3f"
      % metrics.silhouette_score(numpy.asarray(X), labels))


import distutils.version
import logging
import re
import subprocess

# Pulls a version number from the first line of 'java -version'
# See http://java.sun.com/j2se/versioning_naming.html to learn more about the
# command's output format.
_VERSION_REGEX = re.compile('"([0-9][.0-9]*)')

def _GetJavaVersion():
  """Returns the string for the current version of Java installed."""
  proc = subprocess.Popen(['java', '-version'], stderr=subprocess.PIPE)
  unused_stdoutdata, stderrdata = proc.communicate()
  version_line = stderrdata.splitlines()[0]
  return _VERSION_REGEX.search(version_line.decode()).group(1)

def Compile(compiler_jar_path, source_paths, flags=None):
  """Prepares command-line call to Closure Compiler.

  Args:
    compiler_jar_path: Path to the Closure compiler .jar file.
    source_paths: Source paths to build, in order.
    flags: A list of additional flags to pass on to Closure Compiler.

  Returns:
    The compiled source, as a string, or None if compilation failed.
  """

  # User friendly version check.
  if not (distutils.version.LooseVersion(_GetJavaVersion()) >=
          distutils.version.LooseVersion('1.6')):
    logging.error('Closure Compiler requires Java 1.6 or higher. '
                  'Please visit http://www.java.com/getjava')
    return

  args = ['java', '-jar', compiler_jar_path]
  for path in source_paths:
    args += ['--js', path]

  if flags:
    args += flags

  logging.info('Compiling with the following command: %s', ' '.join(args))

  proc = subprocess.Popen(args, stdout=subprocess.PIPE)
  stdoutdata, unused_stderrdata = proc.communicate()

  if proc.returncode != 0:
    return

  return stdoutdata


from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_oauthlib.client import OAuth
from flask_wtf.csrf import CSRFProtect
from flask_user import UserManager, SQLAlchemyAdapter
from flask_login import LoginManager

from workers import UandusClient

CLIENT_ID = ""
CLIENT_SECRET = ""

db = SQLAlchemy()
csrf = CSRFProtect()
oauth = OAuth()

uandus_client = None
lm = LoginManager()

def create_app(extra_config_settings={}):
    """Create a Flask applicaction.
    """

    # Instantiate Flask
    app = Flask(__name__)

    # Load App Config settings
    app.config['JSON_AS_ASCII'] = False
    # Load common settings from 'app/settings.py' file
    app.config.from_object('app.settings')
    # Load local settings from 'app/local_settings.py'
    app.config.from_object('app.local_settings')
    # Load extra config settings from 'extra_config_settings' param
    app.config.update(extra_config_settings)

    oauth.init_app(app)
    # Setup Flask-SQLAlchemy
    db.init_app(app)

    # Setup WTForms CSRFProtect
    csrf.init_app(app)

    global CLIENT_ID
    global CLIENT_SECRET

    CLIENT_ID = app.config.setdefault('CLIENT_ID', '')
    CLIENT_SECRET = app.config.setdefault('CLIENT_SECRET', '')

    # Define bootstrap_is_hidden_field for flask-bootstrap's bootstrap_wtf.html
    from wtforms.fields import HiddenField

    def is_hidden_field_filter(field):
        return isinstance(field, HiddenField)

    app.jinja_env.globals['bootstrap_is_hidden_field'] = is_hidden_field_filter

    # Setup Flask-User to handle user account related forms
    from .models.user_models import User

    db_adapter = SQLAlchemyAdapter(db, User)  # Setup the SQLAlchemy DB Adapter
    user_manager = UserManager(db_adapter, app)  # Init Flask-User and bind to app

    app.app_context().push()

    # Applications
    global uandus_client

    uandus_client = UandusClient(client_id=CLIENT_ID, client_secret=CLIENT_SECRET)

    # Register blueprints
    from app.views.main_views import main_blueprint
    from app.views.oauth_views import oauth_blueprint

    app.register_blueprint(main_blueprint)
    app.register_blueprint(oauth_blueprint)

    return app


# -*- coding: utf-8 -*-
# **************************************************************************
# *
# * Authors:     Ruben Sanchez Garcia (ruben.sanchez-garcia@stats.ox.ac.uk
# *
# * University of Oxford, Dept. of Statistics
# *
# * This program is free software; you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation; either version 2 of the License, or
# * (at your option) any later version.
# *
# * This program is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with this program; if not, write to the Free Software
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# * 02111-1307  USA
# *
# *  All comments concerning this program package may be sent to the
# *  e-mail address 'you@yourinstitution.email'
# *
# **************************************************************************

"""
This protocol removes any metadata row for which the image file is not available.

"""
import glob
import os.path
import re
import sys

from pyworkflow.protocol import Protocol, params, Integer, MultiPointerParam, BooleanParam, StringParam
from pwem.protocols import ProtProcessParticles, ProtParticles, EMProtocol, ProtSets
from pyworkflow.utils import ProgressBar, getListFromRangeString

class RemoveUnlinkedImages(ProtSets):
    """ Protocol to remove items with missing binary files from a set. """
    _label = 'remove unlinked images'

    def _defineParams(self, form):
        form.addSection(label='Input')
        form.addParam('inputSet', params.PointerParam, pointerClass='EMSet',
                      label="Input Set", help="Select the set you want to clean.")

    def _insertAllSteps(self):
        self._insertFunctionStep('removeUnlinkedImagesStep')

    def removeUnlinkedImagesStep(self):
        inputFullSet = self.inputSet.get()
        inputClassName = self.inputSet.getClassName()

        nElements = len(inputFullSet.getIdSet())

        progress = ProgressBar(total=nElements, fmt=ProgressBar.NOBAR)
        progress.start()
        sys.stdout.flush()
        step = max(10000, nElements // 10000)

        try:
            outputSetFunction = getattr(self, "_create%s" % inputClassName)
            outputSet = outputSetFunction()
        except Exception:
            outputSet = inputFullSet.createCopy(self._getPath())

        outputSet.copyInfo(inputFullSet)

        for i, elem in enumerate(inputFullSet.iterItems()):
                if progress and i % step == 0:
                    progress.update(i+1)
                binary_file_path = elem.getFileName()  # Assuming the binary file path is accessible this way
                if os.path.exists(binary_file_path):
                    self._append(outputSet, elem)

        if outputSet.getSize():
            key = 'output' + inputClassName.replace('SetOf', '')
            self._defineOutputs(**{key: outputSet})
            self._defineTransformRelation(inputFullSet, outputSet)
        else:
            self.summaryVar.set('Output was not generated. Resulting set '
                                'was EMPTY!!!')

# class RemoveUnlinkedImages(EMProtocol):
#     """
#     This protocol allow you to run an arbitrary command on an input set of particles
#     (or several), and generates an starfile with one or more new metadata columns.
#     """
#     _label = 'Removed unlinked images'
#
#     def __init__(self, **kwargs):
#         super().__init__(**kwargs)
#         self.stepsExecutionMode = constants.STEPS_SERIAL
#
#     # -------------------------- DEFINE param functions ----------------------
#     def _defineParams(self, form):
#         form.addSection(label='Input')
#         form.addParam('inputSet', params.PointerParam, pointerClass='Set',
#                       label="Input Set")
#
#     def _getDefaultParallel(self):
#         """This protocol doesn't have mpi version"""
#         return (0, 0)
#
#     # --------------------------- STEPS functions ------------------------------
#     def _insertAllSteps(self):
#         # Insert processing steps
#
#         self._insertFunctionStep('createOutputStep')
#
#     def inputPartsStarFname(self, num):
#         return self._getExtraPath("particles%d.star"%num)
#
#
#     def createOutputStep(self):
#
#         input_set = self.inputSet.get()
#         output_set = Set.create(self._getPath("outputSet.sqlite"))
#
#         # Iterate through the items and check if the binary files exist
#         for item in input_set:
#             binary_file_path = item.getFileName()  # Assuming the binary file path is accessible this way
#             if os.path.exists(binary_file_path):
#                 output_set.append(item)
#
#         # Set the output
#         self._defineOutputs(outputSet=output_set)
#         self._defineTransformRelation(self.inputSet, output_set)
#
#     # --------------------------- INFO functions -----------------------------------
#
#     # def _msg(self):
#     #     return "You have run the command '"+self.command.get()+"'\n Env vars: %s"%self.envVars.get()
#     #
#     # def _summary(self):
#     #     """ Summarize what the protocol has done"""
#     #     summary = []
#     #
#     #     if self.isFinished():
#     #         summary.append(self._msg())
#     #     return summary
#     #
#     # def _methods(self):
#     #     methods = []
#     #
#     #     if self.isFinished():
#     #         methods.append(self._msg())
#     #     return methods


from tesserocr import PyTessBaseAPI, PSM, OEM
import tesserocr
from PIL import Image
import pandas as pd
import os
from wand.image import Image as Img

#Helper class to read text using ocr
#First analyse layout and rotate if needed and extract text

def ocr_from_file_path(file_path,language):
    print("Performing OCR")
    text=""
    try:
        image = Image.open(file_path)
        text = tesserocr.image_to_text(image,lang=language)
    except Exception as e:
        print(e)
        pass
    return text

def convert_pdf_to_png(file_path,file_name):
    print("Converting pdf to png image for OCR")
    name_to_save = file_name[0:len(file_name) - 4]
    with Img(filename=full_path, resolution=300) as img:
        img.compression_quality = 99
        temp_name = file_path+'/'+name_to_save+".jpg"
        img.save(filename=temp_name)


import numpy as np
import scipy.ndimage as ndimage

from wzk import np2, grid

# TODO Right now I am calculating to the grid centers. That’s the reason it looks kinda wrong by half the pixel size
#   Does not really matter for the pure simulation part. But There might be an offset compared to the Kinect Fusion Map

# Occupancy Image to Distance Image
def img2dist_img(img: np.ndarray, voxel_size: float, add_boundary: bool = True) -> np.ndarray:
    """
    Calculate the signed distance field from an 2D/3D image of the world.
    Obstacles are 1/True, free space is 0/False.
    The distance image is of the same shape as the input image and has positive values outside objects and negative
    values inside objects see 'CHOMP - signed distance field' (10.1177/0278364913488805)
    The voxel_size is used to scale the distance field correctly (the shape of a single pixel / voxel)
    """

    shape = np.array(img.shape)

    if not add_boundary:
        img_bool = img.astype(bool)
        img_int = img.astype(int)

        # Main function
        #                                         # EDT wants objects as 0, rest as 1
        dist_img = ndimage.distance_transform_edt(-img_int + 1, sampling=voxel_size)
        dist_img_complement = ndimage.distance_transform_edt(img_int, sampling=voxel_size)
        dist_img[img_bool] = - dist_img_complement[img_bool]  # Add interior information # noqa

    else:
        # Additional branch, to include boundary filled with obstacles
        img_wb = np.ones(shape + 2, dtype=bool)
        inner_image_idx = np2.slicen(start=np.ones(img.ndim, dtype=int), end=(shape + 1))
        img_wb[inner_image_idx] = img

        dist_img = img2dist_img(img=img_wb, voxel_size=voxel_size, add_boundary=False)
        dist_img = dist_img[inner_image_idx]  # noqa

    return dist_img

def img2dist_img_grad(limits,
                      dist_img=None,  # either
                      img=None, add_boundary=True,  # or
                      ):
    """
    Use Sobel-filter to get the derivative of the edt
    """
    dist_img = helper__dist_img(dist_img=dist_img, img=img, add_boundary=add_boundary, limits=limits)
    voxel_size = grid.limits2voxel_size(shape=dist_img.shape, limits=limits)
    return img2grad(img=dist_img, voxel_size=voxel_size)

def helper__dist_img(dist_img=None,
                     img=None, limits=None, add_boundary=True):
    if dist_img is None:
        voxel_size = grid.limits2voxel_size(shape=img.shape, limits=limits)
        dist_img = img2dist_img(img=img, voxel_size=voxel_size, add_boundary=add_boundary)

    return dist_img

def helper__dist_img_grad(dist_img_grad=None,
                          dist_img=None, add_boundary=True,
                          img=None, limits=None):
    if dist_img_grad is None:
        dist_img_grad = img2dist_img_grad(img=img, add_boundary=add_boundary,
                                          dist_img=dist_img, limits=limits)
    return dist_img_grad

# Image to Distance Function
def img2dist_fun(limits, interp_order=1,
                 img=None, add_boundary=True,  # A
                 dist_img=None,  # B
                 ):
    """
    Interpolate the distance field at each point (continuous).
    The optimizer is happier with the interpolated version, but it is hard to ensure that the interpolation is
    conservative, so the direct variant should be preferred. (actually)
    # DO NOT INTERPOLATE the EDT -> not conservative -> use order=0 / 'nearest'
    """
    dist_img = helper__dist_img(dist_img=dist_img, img=img, limits=limits, add_boundary=add_boundary)

    dist_fun = img2interpolation_fun(img=dist_img, order=interp_order, limits=limits)
    return dist_fun

def img2dist_grad(*,
                  interp_order=1, limits,
                  dist_img_grad=None,  # A
                  img=None, add_boundary=True,  # B 1
                  dist_img=None,  # B 2
                  ):
    dist_img_grad = helper__dist_img_grad(dist_img_grad=dist_img_grad, dist_img=dist_img,
                                          img=img, add_boundary=add_boundary, limits=limits)
    dist_grad = img_grad2interpolation_fun(img_grad=dist_img_grad, order=interp_order, limits=limits)
    return dist_grad

def img2fun_grad(*, dist_img=None, dist_img_grad=None,
                 img=None, add_boundary=True,
                 interp_order_dist, interp_order_grad,
                 limits):
    dist_img = helper__dist_img(dist_img=dist_img, img=img, limits=limits, add_boundary=add_boundary)
    dist_img_grad = helper__dist_img_grad(dist_img_grad=dist_img_grad, dist_img=dist_img,
                                          img=img, add_boundary=add_boundary, limits=limits)

    dist_fun = img2dist_fun(dist_img=dist_img, interp_order=interp_order_dist, limits=limits)
    dist_grad = img2dist_grad(dist_img_grad=dist_img_grad, interp_order=interp_order_grad, limits=limits)

    return dist_fun, dist_grad

# Helper
def __create_radius_temp(radius, shape):
    if np.size(radius) == 1:
        return radius
    d_spheres = np.nonzero(np.array(shape) == np.size(radius))[0][0]
    r_temp_shape = np.ones(len(shape) - 1, dtype=int)
    r_temp_shape[d_spheres] = np.size(radius)
    return radius.reshape(r_temp_shape)

def img2grad(img, voxel_size):
    """
    Calculate the derivative of an image in each direction of the image, using the sobel filter.
    """
    sobel = np.zeros((img.ndim,) + img.shape)
    for d in range(img.ndim):  # Treat image boundary like obstacle
        sobel[d, ...] = ndimage.sobel(img, axis=d, mode="constant", cval=0)

    # Check appropriate scaling of sobel filter, should be correct
    sobel /= 2 ** (2 * img.ndim - 1) * voxel_size  # 2D: 8, 3D: 32
    return sobel

# Image interpolation
def img2interpolation_fun(img, limits, order=1, mode="nearest"):
    """
    Return a function which interpolates between the pixel values of the image (regular spaced grid) by using
    'scipy.ndimage.map_coordinates'. The resulting function takes as input argument either a ndarray or a list of
    world coordinates (!= image coordinates)
    The 'order' keyword indicates which order of interpolation to use. Standard is linear interpolation (order=1).
    For order=0 no interpolation is performed and the value of the nearest grid cell is chosen. Here the values between
    the different cells jump and aren't continuous.

    """

    lower_left = limits[:, 0]
    voxel_size = grid.limits2voxel_size(shape=img.shape, limits=limits)
    factor = 1 / voxel_size

    def interp_fun(x):
        x2 = x.copy()
        if x2.ndim == 1:
            x2 = x2[np.newaxis, :]

        # Map physical coordinates to image indices
        x2 -= lower_left
        x2 *= factor
        x2 -= 0.5

        # print('voxel_size', voxel_size)
        return ndimage.map_coordinates(input=img, coordinates=x2.T, order=order, mode=mode).T

    return interp_fun

def img_grad2interpolation_fun(img_grad, limits, order=1, mode="nearest"):
    """
    Interpolate images representing derivatives (ie from Soble filter). For each dimension there is a derivative /
    layer in the image.
    Return the results combined as an (x, n_dim) array for the derivatives at each point for each dimension.
    """

    n_dim = img_grad.shape[0]

    fun_list = []
    for d in range(n_dim):
        fun_list.append(img2interpolation_fun(img=img_grad[d, ...], order=order, mode=mode, limits=limits))

    def fun_grad(x):
        res = np.empty_like(x)
        for _d in range(n_dim):
            res[..., _d] = fun_list[_d](x=x)

        return res

    return fun_grad

def test():
    limits = np.array([[-1, 2],
                       [-1, 2]])
    img = np.zeros((20, 20), dtype=bool)
    voxel_size = 3 / 20

    img[3:5, 5:8] = 1
    img[range(20), range(20)] = 1
    dist_img = img2dist_img(img=img, voxel_size=voxel_size, add_boundary=False)
    fun = img2interpolation_fun(img=dist_img, limits=limits, order=0)
    x = np.array(np.meshgrid(*[np.linspace(limits[i, 0], limits[i, 1], 201) for i in range(2)], indexing="ij"))
    x = x.reshape(2, -1).T
    d = fun(x)

    from wzk import mpl2
    fig, ax = mpl2.new_fig(aspect=1)
    eps = 0.01
    mpl2.imshow(ax=ax, limits=limits, img=img, mask=~img, cmap="k")
    ax.plot(*x[d < eps].T, marker="o", color="red", ls="", markersize=1)
    ax.plot(*x[d > eps].T, marker="o", color="blue", ls="", markersize=1)

    #
    dimg = img2dist_img(img=img, voxel_size=voxel_size, )
    dimg_grad = img2grad(img=dimg, voxel_size=voxel_size)
    fig, ax = mpl2.new_fig(aspect=1, n_cols=4)

    mpl2.imshow(ax=ax[0], limits=limits, img=img, cmap="Greys")
    mpl2.imshow(ax=ax[1], limits=limits, img=dimg, cmap="Greys")
    mpl2.imshow(ax=ax[2], limits=limits, img=dimg_grad[0, :, :], cmap="Greys")
    mpl2.imshow(ax=ax[3], limits=limits, img=dimg_grad[1, :, :], cmap="Greys")

if __name__ == "__main__":
    test()


import click
from typing import Dict, Any, Sequence
from .tnco_env_command import TNCOEnvironmentCommand
from .obj_utils import shallow_merge_objs
from .identifier import Identifier, determine_identifier, strip_identifiers
from .constraints import mutually_exclusive
from lmctl.cli.controller import get_global_controller
from lmctl.cli.arguments import FileInputOption, SetParamOption

__all__ = (
    'TNCOUpdateCommand',
)

class TNCOUpdateCommand(TNCOEnvironmentCommand):

    def __init__(self,
                type_display_name: str,
                *args,
                identifiers: Sequence[Identifier] = None,
                print_result: bool = True,
                result_prefix: str = 'Updated: ',
                additional_help: str = None,
                allow_patch: bool = True,
                **kwargs
            ):
        self.type_display_name = type_display_name
        self.identifiers = identifiers
        self.print_result = print_result
        self.result_prefix = result_prefix
        self.additional_help = additional_help
        self.allow_patch = allow_patch
        if 'help' not in kwargs or kwargs['help'] is None:
            kwargs['help'] = self._build_help()
        if 'short_help' not in kwargs or kwargs['short_help'] is None:
            kwargs['short_help'] = f'Update a {self.type_display_name}'
        super().__init__(*args, **kwargs)
        self.params.append(FileInputOption())
        self.params.append(SetParamOption())

        self.update_behaviour = self.callback
        self.callback = self._callback

        if len(self.identifiers) > 1:
            self.callback = mutually_exclusive(
                *[(i.param_name, i.get_cli_display_name()) for i in self.identifiers]
            )(self.callback)

    def _callback(self,
                    *args,
                    environment_name: str = None,
                    pwd: str = None,
                    client_secret: str = None,
                    token: str = None,
                    file_content: Dict[str, Any] = None,
                    set_values: Dict[str, Any] = None,
                    **kwargs):
        obj = shallow_merge_objs(file_content, set_values)
        identity = determine_identifier(self.identifiers, required=True, file_content=file_content, **kwargs)
        stripped_kwargs = strip_identifiers(self.identifiers, **kwargs)

        if self.allow_patch:
            # Patch update supported if file_content not specified
            stripped_kwargs['patchable'] = file_content is None

        tnco_client = self._get_tnco_client(environment_name, pwd, client_secret, token)
        result = self.update_behaviour(*args, tnco_client=tnco_client, obj=obj, identity=identity, **stripped_kwargs)

        if self.print_result:
            io = get_global_controller().io
            text = ''
            if self.result_prefix:
                text += str(self.result_prefix)
            text += str(result)
            io.print(text)

    def _build_help(self) -> str:
        help_msg = f'Update a {self.type_display_name}'
        help_msg += f'\n\nUse the "-f, --file" option to parse input data as a file in a supported format.'
        help_msg += f'\nOtherwise, use "--set" option to set attributes as key=value pairs.'
        if self.identifiers is not None and len(self.identifiers) > 0:
            help_msg += '\n\n'
            help_msg += self._produce_identifer_str()
        if self.additional_help:
            help_msg += f'\n\n{self.additional_help}'
        return help_msg

    def _produce_identifer_str(self) -> str:
        identifiers_str = f'Identify the {self.type_display_name} to be updated'

        if len(self.identifiers) == 1:
            identifiers_str += f' using the "{self.identifiers[0].get_cli_display_name()}" parameter'
        else:
            identifiers_str += ' using one paramter from [' + ', '.join([f'"{p.get_cli_display_name()}"' for p in self.identifiers]) + ']'

        attr_identifiers = [p for p in self.identifiers if p.obj_attribute is not None]
        if len(attr_identifiers) > 1:
            identifiers_str += f' or by including one of the following attributes'
            file_attr_str = ', '.join([f'"{p.obj_attribute}"' for p in attr_identifiers])
            identifiers_str += f' [{file_attr_str}] in the given object/file'
        elif len(attr_identifiers) == 1:
            identifiers_str += f' or by including the "{attr_identifiers[0].obj_attribute}" attribute in the given object/file'
        return identifiers_str


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Задание 5.2b

Преобразовать скрипт из задания 5.2a таким образом,
чтобы сеть/маска не запрашивались у пользователя,
а передавались как аргумент скрипту.

Ограничение: Все задания надо выполнять используя только пройденные темы.

"""
from sys import argv

# get user`s nonsense
user_data = argv[1] # input("Введите IP-адрес: ")

ip_and_mask = user_data.split('/')

# ---------start work with ip address-----
# retrieving an IP-address
ip_addr = ip_and_mask[0]

ap_addr_list = ip_addr.split('.')
# ---------end work with ip address-----

# ---------start work with net mask-----
# retrieving a net mask
short_net_mask = ip_and_mask[1]

# computing the number of full octets of net mask
full_octets_count = int(short_net_mask) // 8

# computing the number of bits in incomplete octet
incmplt_octet_bits = int(short_net_mask) % 8

# is octet incomplete or empty, 1 == incomplete, 0 == empty
incmplt_octet_count = int(incmplt_octet_bits > 0)

bits_value = [128, 64, 32, 16, 8, 4, 2, 1]

# computing incomplete octet value
incmplt_octet_value = str(sum(bits_value[:(incmplt_octet_bits)])) + '.'
nm_full_octet = '255.'
nm_empty_octet = '0.'

# computing the number of empty octets
empty_octets_count = 4 - full_octets_count - incmplt_octet_count

net_mask = (nm_full_octet * full_octets_count + incmplt_octet_value + nm_empty_octet * empty_octets_count).strip('.')
octets_list = net_mask.split('.')[:4]
# ---------end work with net mask-----

# computing network address from IP-address
ip_addr_bin = "{:08b}{:08b}{:08b}{:08b}".format(int(ap_addr_list[0]),int(ap_addr_list[1]),int(ap_addr_list[2]),int(ap_addr_list[3]))
net_mask_length = '0' * int(short_net_mask)
network_ip_addr = ip_addr_bin[:len(net_mask_length)] + '0' * (32 - len(net_mask_length))

# network address in list; values of list element must be an integer
network_addr_list = [int(network_ip_addr[:8], 2), int(network_ip_addr[8:16], 2), int(network_ip_addr[16:24], 2), int(network_ip_addr[24:], 2)]

# done with computing network address from IP-address

template = f'''
Network:
{network_addr_list[0]:<8}  {network_addr_list[1]:<8}  {network_addr_list[2]:<8}  {network_addr_list[3]:<8}
{network_addr_list[0]:08b}  {network_addr_list[1]:08b}  {network_addr_list[2]:08b}  {network_addr_list[3]:08b}

Mask:
/{short_net_mask}
{octets_list[0]:<8}  {octets_list[1]:<8}  {octets_list[2]:<8}  {octets_list[3]:<8}
{int(octets_list[0]):08b}  {int(octets_list[1]):08b}  {int(octets_list[2]):08b}  {int(octets_list[3]):08b}
'''

print(template)


from __future__ import division
from past.utils import old_div
import unittest
from nineml.abstraction import (
    Dynamics, Regime, Alias, Parameter, AnalogReceivePort, AnalogReducePort,
    OnCondition, AnalogSendPort, Constant, StateAssignment)
from nineml.abstraction.dynamics.visitors.modifiers import (
    DynamicsSubstituteAliases)
from nineml import units as un

# Testing Skeleton for class: DynamicsClonerPrefixNamespace
class DynamicsSubstituteAliasesTest(unittest.TestCase):

    def setUp(self):

        self.a = Dynamics(
            name='A',
            aliases=['A1:=P1 / P2', 'A2 := ARP2 + P3', 'A3 := A4 * P4 * P5',
                     'A4:=P6 ** 2 + ADP1', 'A5:=SV1 * SV2 * P8',
                     'A6:=SV1 * P1 / P8', 'A7:=A1 / P8'],
            regimes=[
                Regime('dSV1/dt = -A1 / A2',
                       'dSV2/dt = -ADP1 / P7',
                       'dSV3/dt = -A1 * A3 / (A2 * C1)',
                       transitions=[OnCondition('SV1 > 10',
                                                target_regime_name='R2')],
                       aliases=[Alias('A1', 'P1 / P2 * 2'),
                                Alias('A5', 'SV1 * SV2 * P8 * 2')],
                       name='R1'),
                Regime('dSV1/dt = -A1 / A2',
                       'dSV3/dt = -A1 / A2 * A4',
                       transitions=[OnCondition(
                           'C2 > A6',
                           state_assignments=[
                               StateAssignment('SV1', 'SV1 - A7')],
                           target_regime_name='R1')],
                       name='R2')],
            analog_ports=[AnalogReceivePort('ARP1', dimension=un.resistance),
                          AnalogReceivePort('ARP2', dimension=un.charge),
                          AnalogReducePort('ADP1',
                                           dimension=un.dimensionless),
                          AnalogSendPort('A5', dimension=un.current)],
            parameters=[Parameter('P1', dimension=un.voltage),
                        Parameter('P2', dimension=un.resistance),
                        Parameter('P3', dimension=un.charge),
                        Parameter('P4', dimension=old_div(un.length, un.current ** 2)),
                        Parameter('P5', dimension=old_div(un.current ** 2, un.length)),
                        Parameter('P6', dimension=un.dimensionless),
                        Parameter('P7', dimension=un.time),
                        Parameter('P8', dimension=un.current)],
            constants=[Constant('C1', value=10.0, units=un.unitless),
                       Constant('C2', value=1.0, units=un.ohm)])

        self.ref_substituted_a = Dynamics(
            name='substituted_A',
            aliases=['A5:=SV1 * SV2 * P8'],
            regimes=[
                Regime('dSV1/dt = -2 * (P1 / P2) / (ARP2 + P3)',
                       'dSV2/dt = -ADP1 / P7',
                       ('dSV3/dt = -2 * (P1 / P2) * ((P6 ** 2 + ADP1) * P4 * '
                        'P5) / ((ARP2 + P3) * C1)'),
                       transitions=[OnCondition('SV1 > 10',
                                                target_regime_name='R2')],
                       aliases=[Alias('A5', 'SV1 * SV2 * P8 * 2')],
                       name='R1'),
                Regime('dSV1/dt = -(P1 / P2) / (ARP2 + P3)',
                       'dSV3/dt = -(P1 / P2) / (ARP2 + P3) * (P6 ** 2 + ADP1)',
                       transitions=[OnCondition(
                           'C2 > (SV1 * P1 / P8)',
                           state_assignments=[
                               StateAssignment('SV1', 'SV1 - (P1 / P2) / P8')],
                           target_regime_name='R1')],
                       name='R2')],
            analog_ports=[AnalogReceivePort('ARP1', dimension=un.resistance),
                          AnalogReceivePort('ARP2', dimension=un.charge),
                          AnalogReducePort('ADP1',
                                           dimension=un.dimensionless),
                          AnalogSendPort('A5', dimension=un.current)],
            parameters=[Parameter('P1', dimension=un.voltage),
                        Parameter('P2', dimension=un.resistance),
                        Parameter('P3', dimension=un.charge),
                        Parameter('P4', dimension=old_div(un.length, un.current ** 2)),
                        Parameter('P5', dimension=old_div(un.current ** 2, un.length)),
                        Parameter('P6', dimension=un.dimensionless),
                        Parameter('P7', dimension=un.time),
                        Parameter('P8', dimension=un.current)],
            constants=[Constant('C1', value=10.0, units=un.unitless),
                       Constant('C2', value=1.0, units=un.ohm)]
        )

    def test_substitute_aliases(self):
        substituted_a = self.a.clone()
        substituted_a.name = 'substituted_A'
        DynamicsSubstituteAliases(substituted_a)
        self.assertEqual(substituted_a, self.ref_substituted_a,
                         substituted_a.find_mismatch(self.ref_substituted_a))


from django.db.models import fields
from salary.models import EmployeeSalary, SalaryLine, Vacation
from projectmanager.serializers import EmployeeSerializer
from .apps import APP_NAME
from rest_framework import serializers

class EmployeeSalarySerializer(serializers.ModelSerializer):
    employee=EmployeeSerializer()
    class Meta:
        model=EmployeeSalary
        fields=['id','employee','year','month','month_name','get_edit_url','get_absolute_url']
class SalaryLineSerializer(serializers.ModelSerializer):
    class Meta:
        model=SalaryLine
        fields=['id','amount','direction','title','description','get_edit_url','get_absolute_url']
class VacationSerializer(serializers.ModelSerializer):
    employee=EmployeeSerializer()
    class Meta:
        model=Vacation
        fields=['id','title','employee','persian_vacation_started','persian_vacation_ended','description','get_edit_url','get_absolute_url']


import math
import tkinter.filedialog
from copy import deepcopy

import numpy as np
import gym
from gym import spaces

class MyEnv(gym.Env):
  metadata = {'render.modes': ['console']}

  # Define constants for clearer code
  LEFT = 0
  RIGHT = 1
  UP = 2
  DOWN = 3

  def __init__(self):
      super(MyEnv, self).__init__()

      # Size of the 1D-grid
      self.columns = 7
      self.rows = 6
      self.start = [5, 0]
      self.objeto_state = [2, 3]
      # Initialize the agent at the right of the grid
      self.agent_pos = (5,0) #linha, coluna
      self.objeto = (2, 3) #linha, coluna
      self.paredes = [(1, 3), (4,0), (4, 1), (4, 3), (4, 4), (4, 5), (4, 6), (5, 6)]
      self.base = [(0, 2), (0, 3), (0, 4)]
      self.matriz_renderizacao = [["" for x in range(7)] for y in range(6)]
      self.capturou_objeto = False

      # Define action and observation space
      # They must be gym.spaces objects
      # Example when using discrete actions, we have two: left and right
      n_actions = 4
      self.action_space = spaces.Discrete(n_actions)

      self.current_state = None
      # The observation will be the coordinate of the agent
      # this can be described both by Discrete and Box space
      self.observation_space = spaces.Discrete(self.rows*self.columns)

  def observation(self, state):
      return state[0] * self.columns + state[1]

  def colidiu(self, x, y):
      if x < 0 or y < 0 or x >= self.columns or y >= self.rows:
          return True
      if (y, x) == self.objeto:
          return True
      if (y, x) in self.paredes:
          return True

      return False

  def pode_andar(self, x, y, action):
      colide = self.colidiu(x, y)
      if colide:
          return False
      if self.capturou_objeto:
          new_x, new_y = self.get_delta(self.objeto_state, action)
          colide = self.colidiu(new_x, new_y)
          if colide:
              return False
      return True

  def captura_objeto(self):
      y = self.current_state[0]
      x = self.current_state[1]
      if y == 2 and x in [2,4]:
          self.capturou_objeto = True

  def get_delta(self, state_array, action):
      new_x = state_array[1]
      new_y = state_array[0]

      if action == self.RIGHT:  # right
          new_x = new_x + 1
      elif action == self.DOWN:  # down
          new_y = new_y + 1
      elif action == self.LEFT:  # left
          new_x = new_x - 1
      elif action == self.UP:  # up
          new_y = new_y - 1
      else:
          raise Exception("Invalid action.")

      return new_x, new_y

  def step(self, action):
      new_state = deepcopy(self.current_state)
      new_x, new_y = self.get_delta(new_state, action)
      new_x_o, new_y_o = self.get_delta(self.objeto_state, action)

      andou = self.pode_andar(new_x, new_y, action)
      new_state = [new_y, new_x] if andou else new_state
      if self.capturou_objeto:
        self.objeto_state = [new_y_o, new_x_o] if andou else self.objeto_state

      self.current_state = new_state
      self.captura_objeto()

      reward = -1.0
      is_terminal = False

      if andou:
          if (self.objeto_state[0], self.objeto_state[1]) in self.base:
              if self.capturou_objeto: #se chegou na base sem o objeto
                  is_terminal = True
                  reward = 1
              else:
                  reward = -100.0
                  self.current_state = deepcopy(self.start)

      return self.observation(self.current_state), reward, is_terminal, {}

  def reset(self):
    self.agent_pos = (5,0)
    self.objeto = (2, 3)
    self.current_state = self.start
    self.objeto_state = [2, 3]
    self.capturou_objeto = False
    return self.observation(self.current_state)

  def render(self, mode='console'):
    if mode != 'console':
       raise NotImplementedError()
       # agent is represented as a cross, rest as a dot
    ay, ax = self.current_state[0], self.current_state[1]
    oy, ox = self.objeto_state[0], self.objeto_state[1]

    for y, x in self.paredes:
        self.matriz_renderizacao[y][x] = "X"
    for y, x in self.base:
        self.matriz_renderizacao[y][x] = "B"

    for y in range(self.rows):
        for x in range(self.columns):
            if not self.matriz_renderizacao[y][x] in ["X", "B"]:
                if ax == x and ay == y:
                    self.matriz_renderizacao[y][x] = "A"
                elif ox == x and oy == y:
                    self.matriz_renderizacao[y][x] = "O"
                else:
                    self.matriz_renderizacao[y][x] = " "

    for y in range(self.rows):
        print("-" * self.columns * 2)
        linha = "|"
        for x in range(self.columns):
            linha += f"{self.matriz_renderizacao[y][x]}|"
        print(linha)

  def print_infos(self, step, accumulated_reward):
      print(f"[{step}] = agente: {self.current_state} - objeto: {self.objeto_state} accumulated_reward: {accumulated_reward}")
      # print(f"objeto: {self.objeto_state}")

  def close(self):
    pass


import time
num = int(input('Digite um número para ver sua tabuada: '))
con = 1
print(' ', '=' * 16)
while con <= 10:
    res = num * con
    print('|| ', num, ' x {:2} = {:2}'.format(con, res), ' ||')
    con += 1
    time.sleep(1.5)
print(' ', '=' * 16)


from hanzi_chaizi import HanziChaizi

class ChaiZi(object):
    def __init__(self, params=None):
        self.params = params if params else {}
        self.hc = HanziChaizi(**self.params)

    def extract(self, char_seq):
        result = [self.hc.query(i) for i in char_seq]
        return result

if __name__ == "__main__":
    obj = ChaiZi()
    result = obj.extract('明天一定龖麣')

    print(result)


import scraper_helper
import scrapy
from bs4 import BeautifulSoup
import scraper_helper as sh
from requests import request
from lxml import html
import re

class qspider(scrapy.Spider):
    name = "quotes"
    allowed_domains = ["brainsensei.com"]

    start_urls = ["https://brainsensei.com/explore-courses/"]

    def parse(self, response):
        for href in response.css('.box-link::attr(href)'):
            url = response.urljoin(href.extract())
            yield scrapy.Request(url, callback = self.parse_dir_contents)

    def parse_dir_contents(self, response):

        #reviewer_name

        reviewer_name = response.xpath('//div[@class="slides"]//span[@class="testimonial-name"]/text()').extract()
        reviewer_name = [desc.strip() for desc in reviewer_name]
        reviewer_name = "|".join(reviewer_name)

        #reviewer_description

        reviewer_description = response.xpath('//blockquote//p/text()').extract()
        reviewer_description = [revv.strip() for revv in reviewer_description]
        reviewer_description = "|".join(reviewer_description)
        reviewer_description = reviewer_description.replace("||","|")
        reviewer_description = re.sub("$/|","",reviewer_description)

        #title

        title = response.xpath('//title/text()').extract()
        title = [tit.strip() for tit in title[:1]]
        title = "".join(title)

        #price

        price = response.xpath('//span[@class="woocommerce-Price-amount amount"]//bdi/text()').extract()
        price = [pri.strip() for pri in price]
        price = "".join(price)
        price = scraper_helper.cleanup(price)

        description = response.xpath('//div[@class="wpb_wrapper"]//p/text()').extract()
        description = [desc.strip() for desc in description[:1]]
        description = "".join(description)
        short = description.split(".")[0]
        description = "
"+description+"
"

        batch_date = response.xpath('//div[@class="simple-col simple-data-date"]/text()').extract()
        batch_date = [str.strip() for str in batch_date]
        batch_date = "|".join(batch_date)

        batch_time = response.xpath('//div[@class="simple-col simple-data-time"]/text()').extract()
        batch_time = [batch.strip() for batch in batch_time]
        batch_time = "|".join(batch_time)
        batch_time = batch_time.replace("to","-")
        batch_time = re.sub('\(.*?\)', '', batch_time).replace('||', '|')

        batch_price = response.css('.simple-data-time+ .simple-col::text').extract()
        batch_price = [batp.strip() for batp in batch_price]
        batch_price = "|".join(batch_price)
        batch_price = batch_price.replace("$","")

        what_will_learn = response.css('.open+ .open li::text , p+ ul li::text').getall()

        what_will_learn = [sho.strip() for sho in what_will_learn]
        what_will_learn = "|".join(what_will_learn)
        what_will_learn = what_will_learn.replace("||","|")
        if what_will_learn == "":
            what_will_learn = response.css('#capmfeatures > div.row_col_wrap_12.col.span_12.dark.left > div > div > div > div.toggles > div:nth-child(2) > div > div > div').extract()
            what_will_learn = what_will_learn[0]
            what_will_learn = what_will_learn.strip().replace('\n', '')
            what_will_learn = re.sub('
| div.row_col_wrap_12.col.span_12.dark.left > div > div > div > div.toggles > div:nth-child(2) > div > div > div').extract()
            content = content[0]
            content = content.strip().replace('\n', '')
            content = re.sub('
|<p.*?
', '', content)
            content = content.split('

')
        number = 1
        head = []
        for cont in content:
            if cont.strip() == "" or cont.strip() == "

": continue
            heading = f"
Module {number}: {cont.strip()}
"
            head.append(heading)
            number += 1
        heading = "".join(head)

        yield{
        'title' : title,
        'price' : price,
        'description' : description,
        'reviewer_description' : reviewer_description,
        'what_will_learn' : what_will_learn,
        'reviewer_name' : reviewer_name,
        'batch_date' : batch_date,
        'batch_time' : batch_time,
        'short' : short,
        'batch_price' : batch_price,
        'heading' : heading
        }


a = ['nicola','balentin','sasha','stas','uri']
b = 0
ss = ''
for i in a:
    if list(i)[0] == 's':
        i = list(i)
        i[0] = 'S'
        for iii in i:
            ss += iii
        a[b] = ss
    b+=1
    ss = ''
print(a)


import torch
import torch.nn.functional as F
from face_dataset import FaceDataset
import torchvision
import torch.nn as nn
from torch.utils.data import DataLoader
from multi_machine import MultiMachine

def train(device):
    batch_size = 500
    cid = FaceDataset(is_train=True)
    dataloader = DataLoader(cid, batch_size=batch_size, shuffle=True)
    model = MultiMachine()
    model.train()
    model.to(device)
    optimizer = torch.optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-5)
    criterion = torch.nn.MSELoss(reduction='mean')
    num_epochs = 10
    n_batches = int(len(cid)/batch_size) + 1
    batch_number = 0
    loss = None

    for epoch in range(num_epochs):
        batch_number = 0
        for (image, age, gender) in dataloader:
            image = image.to(device)
            age = age.to(device)
            gender = gender.to(device)
            optimizer.zero_grad()
            y_hat = model(image)
            age_hat = y_hat[:, 0]
            gender_hat = y_hat[:, 1:]
            age_hat = age_hat.reshape(-1)
            age_loss = criterion(age_hat, age)
            gender_loss = F.cross_entropy(gender_hat, gender)
            loss = age_loss + gender_loss
            loss.backward()
            optimizer.step()
            batch_number += 1
            print(f'Epoch:{epoch + 1} (of {num_epochs}), Batch: {batch_number} of {n_batches}, Loss:{loss.item():.4f}')

    print("Train done")
    torch.save(model, 'models/multi.h5')

if __name__ == "__main__":
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    train(device)


# I want the ingredients that are unique to each product so I can find
# where my allergies are coming from >:(
from arrayManipulation import removeCommonElements

# Get ingredients from file
shampoo1 = {
    "title": "",
    "ingredients": []
}

shampoo2 = {
    "title": "",
    "ingredients": []
}
with open('shampoo1_ingredients.csv', 'r', encoding="utf-8") as file:
    shampoo1["title"] = file.readline()
    shampoo1["ingredients"] = file.read().split(',')

with open('shampoo2_ingredients.csv', 'r', encoding="utf-8") as file:
    shampoo2["title"] = file.readline()
    shampoo2["ingredients"] = file.read().split(',')

removeCommonElements(shampoo1["ingredients"],shampoo2["ingredients"])
print(f"{shampoo1['title']}")
print(shampoo1["ingredients"])
print(f"{shampoo2['title']}")
print(shampoo2["ingredients"])


import click
from typing import Any, Sequence

__all__ = (
    'SetParamOption',
    'set_param_option'
)

default_param_decls = ['--set', 'set_values']

class SetParamOption(click.Option):

    def __init__(
            self,
            param_decls: Sequence[str] = default_param_decls,
            help: str = 'Set parameters on the object',
            **kwargs):
        param_decls = [p for p in param_decls]

        self.wrapped_callback = kwargs.pop('callback', None)
        super().__init__(
            param_decls,
            help=help,
            multiple=True,
            callback=self._callback,
            **kwargs
        )

    def _callback(self, ctx: click.Context, param: click.Parameter, value: Any):
        parse_result = {}
        if value is None:
            value = []
        for v in value:
            split = v.split('=')
            if len(split) != 2:
                raise click.BadParameter(f'value must use format <key>=<value>', ctx=ctx, param=param)
            parse_result[split[0]] = split[1]
        if self.wrapped_callback is not None:
            return self.wrapped_callback(parse_result)
        else:
            return parse_result

def set_param_option(*args, **kwargs):
    def decorator(f):
        param_decls = args
        if len(param_decls) == 0:
            param_decls = default_param_decls
        return click.option(*param_decls, cls=SetParamOption, **kwargs)(f)
    return decorator


# Задача 4. Задана натуральная степень k.
# Сформировать случайным образом список коэффициентов (от 0 до 10) многочлена,
# записать в файл полученный многочлен не менее 3-х раз.

# процедура задания рандомных коэффициентов многочлена
import random
def random_cof_polynomial(value: str, min_rand, max_rand):
    NO_VALUE = ''
    result_list = []
    result_out = NO_VALUE
    polynomial_string = value.replace('+','$+').replace('-','$-').replace('=','$=$').replace(' ', '')
    polynomial_list = polynomial_string.split('$')
    for i in range(len(polynomial_list)):
        if polynomial_list[i].find('^')>0:
            find_value_list = polynomial_list[i].split("*")
            type_polynomial = find_value_list[1]
            result_list.append(f'{random.randint(min_rand, max_rand)}*{type_polynomial}')
        else:
            if polynomial_list[i] != '=' and polynomial_list[i] != NO_VALUE:
                if len(polynomial_list)-1 == i:
                    result_list.append(f'{polynomial_list[i]}')
                else:
                    result_list.append(f'{random.randint(min_rand, max_rand)}')
            else:
                if polynomial_list[i] == '=':
                    result_list.append('=')

    for i in range(len(result_list)):
        if i == 0 or i>len(result_list)-3:
            result_out += (f'{result_list[i]}')
        else:
            if result_list[i][0] != '-':
                result_out += (f'+{result_list[i]}')
            else:
                result_out += (f'{result_list[i]}')

    result_out = (f'{result_out}')
    result_out = result_out.replace('+',' + ').replace('-',' - ').replace('=',' = ')
    return result_out

# список многочленов
polynomial_list = []
polynomial_list.append('3*x^9 + 3*x^8 - 2*x^6 + 1*x^5 - 3*x^4 - 3*x^2 + 3 + 2*x^2 + 2*x^1 + 2 = 0')
polynomial_list.append('6*x^9 + 6*x^8 - 4*x^6 + 2*x^5 - 6*x^4 - 2*x^2 + 4*x^1 + 33 = 0')
polynomial_list.append('-3*x^2 - 10 + 3*x^2 + 1*x^1 = 2')
polynomial_list.append('3*x^9 + 3*x^8 + 2 = -1')

with open('random_cof_poly.txt', 'w') as file:
    file.write('')

MIN_VALUE_RANDOM = 0
MAX_VALUE_RANDOM = 10
# случайным образом изменяем коэффициенты многочленов и записываем их в файл
for i in polynomial_list:
    print (f'old -> {i}')
    new_polynomial = random_cof_polynomial(i,MIN_VALUE_RANDOM,MAX_VALUE_RANDOM)
    print (f'new -> {new_polynomial}')
    print('')
    with open('random_cof_poly.txt', 'a') as file:
        file.write(new_polynomial + '\n')


# # looping in list
# numbers = [12,45,65,23,89,78,45,11]
# total = sum(numbers)
# total = 0
# for i in numbers:
#   total = total + i
#   print(i)
# print (total)

# # to get the index with while loop
# for num in enumerate(numbers):
#   print(num)

# looping in set

# nums = {12,45,65,23,89,78,45,11}

# set_total = 0
# for num in nums :
#   set_total += num
# print(set_total)

# # looping in tuples

# number_tuples = 12,45,65,23,89,78,11,45
# # if we just declare some values with commas than its a tuple

# tuples_total =0
# for num in number_tuples:
#   tuples_total +=num
# print(tuples_total)

# looping in dictionary
marks = { 'physics' : 12, 'chemistry' : 45 , 'math' : 56 }

# looping in dictionary only loop through the keys
for mark in marks:
  val = marks[mark]
  print(mark,val)

for subject,mark in marks.items():
  print(subject,mark)


from flask import Blueprint, render_template, request, jsonify

print(__name__)

views = Blueprint(__name__, "views")

@views.route("/")
def home():
    return render_template("index.html", name="Joe")

@views.route('/profile')
def profile(username):
    args = request.args
    print('args:', args)
    name = args.get('name')
    return render_template("index.html", name=name)

@views.route("/json")
def get_json():
    return jsonify({"name": "Joe", "age": 30})

@views.route("/data")
def get_data():
    data =request.json
    print('data:', data)
    return jsonify(data)


# %% S0. SETUP env
from skimage.restoration import denoise_tv_chambolle
import pywt
import MRzeroCore as mr0
import numpy as np
import pypulseq as pp
from matplotlib import pyplot as plt

# makes the ex folder your working directory
import os
os.chdir(os.path.abspath(os.path.dirname(__file__)))

experiment_id = 'exD01_bSSFP_2D'

# %% S4: SETUP SPIN SYSTEM/object on which we can run the MR sequence external.seq from above
sz = [64, 64]

# obj_p = mr0.VoxelGridPhantom.load_mat('../data/phantom2D.mat')
phantom = mr0.VoxelGridPhantom.load_mat('../data/numerical_brain_cropped.mat')
phantom = phantom.interpolate(sz[0], sz[1], 1)
phantom.T2dash[:] = 30e-3
phantom.D *= 0

space = np.fft.ifftshift(phantom.PD[:, :, 0])
kspace_adc = np.fft.ifft2(space)
# this is a kspace as it woudk come from an ADC, with low frequencies centered.
kspace_adc = np.fft.ifftshift(kspace_adc)

plt.imshow(np.log(np.abs(kspace_adc)))

# %% ##########################################################################
# S6: compressed sensing MR reconstruction of undersampled signal
# S6.1: function definitions

def shrink(coeff, epsilon):
    shrink_values = (abs(coeff) < epsilon)
    high_values = coeff >= epsilon
    low_values = coeff <= -epsilon
    coeff[shrink_values] = 0
    coeff[high_values] -= epsilon
    coeff[low_values] += epsilon

# help?
#  https://www2.isye.gatech.edu/~brani/wp/kidsA.pdf
for family in pywt.families():
    print("%s family: " % family + ', '.join(pywt.wavelist(family)))

print(pywt.Wavelet('haar'))

def waveletShrinkage(current, epsilon):
    # Compute Wavelet decomposition
    cA, (cH, cV, cD) = pywt.dwt2(current, 'haar')
    # Shrink
    shrink(cA, epsilon)
    shrink(cH, epsilon)
    shrink(cV, epsilon)
    shrink(cD, epsilon)
    wavelet = cA, (cH, cV, cD)
    # return inverse WT
    return pywt.idwt2(wavelet, 'haar')

def updateData(k_space, pattern, current, step, i):
    # go to k-space
    update = np.fft.ifft2(np.fft.fftshift(current))
    # compute difference
    update = k_space - (update * pattern)
    print("i: {}, consistency RMSEpc: {:3.6f}".format(
        i, np.abs(update[:]).sum() * 100))
    # return to image space
    update = np.fft.fftshift(np.fft.fft2(update))
    # improve current estimation by consitency
    update = current + (step * update)
    return update

# S6.2: preparation and conventional fully sampled reconstruction

# high  frequencies centered as FFT needs it
kspace_full = np.fft.ifftshift(kspace_adc)

kspace = kspace_full
# fully sampled recon
recon_nufft = (np.fft.fftshift(np.fft.fft2(kspace_full)))

# %% S6.3 undersampling and undersampled reconstruction
# space= space/ np.linalg.norm(space[:])   # normalization of the data somethimes helps

# parameters of iterative reconstructio using total variation denoising
denoising_strength = 10e-6
number_of_iterations = 8000

# parameters of random subsampling pattern
percent = 0.25        # this is the amount of data that is randomly measured
square_size = 16      # size of square in center of k-space

# generate a random subsampling pattern
np.random.seed(np.random.randint(100))
pattern = np.random.random_sample(kspace.shape)
pattern = pattern < percent  # random data

pattern[sz[0] // 2 - square_size // 2:sz[0] // 2 + square_size // 2,
        sz[0] // 2 - square_size // 2:sz[0] // 2 + square_size // 2] = 1   # square in center of k-space
# high  frequencies centered as kspace and as FFT needs it
pattern = np.fft.fftshift(pattern)

kspace = kspace_full * pattern  # apply the undersampling pattern

# calculate the actually measured data in percent
actual_measured_percent = np.count_nonzero(pattern) / pattern.size * 100

# actual iterative reconstruction algorithm
current = np.zeros(kspace.size).reshape(kspace.shape)
current_shrink = np.zeros(kspace.size).reshape(kspace.shape)
first = updateData(kspace, pattern, current, 1, 0)
current_shrink = first
all_iter = np.zeros((kspace.shape[0], kspace.shape[1], number_of_iterations))

for i in range(number_of_iterations):
    current = updateData(kspace, pattern, current_shrink, 0.1, i)

    current_shrink = denoise_tv_chambolle(abs(current), denoising_strength)
    # current_shrink = waveletShrinkage(abs(current), denoising_strength)

    all_iter[:, :, i] = current

# Plotting

pattern_vis = np.fft.fftshift(pattern * 256)

fig = plt.figure(dpi=90)
plt.subplot(321)
plt.set_cmap(plt.gray())
plt.imshow(abs(recon_nufft))
plt.ylabel('recon_full')
plt.subplot(322)
plt.set_cmap(plt.gray())
plt.imshow(abs(pattern_vis))
plt.ylabel("pattern_vis")
plt.title("{:.1f} % sampled".format(actual_measured_percent))
plt.subplot(323)
plt.set_cmap(plt.gray())
plt.imshow(abs(first))
plt.ylabel('first iter (=NUFFT)')
plt.subplot(325)
plt.set_cmap(plt.gray())
plt.imshow(abs(current_shrink))
plt.ylabel('final recon')
plt.subplot(324)
plt.set_cmap(plt.gray())
plt.imshow(np.log(abs(np.fft.fftshift(kspace_full))))
plt.ylabel('kspace_nufft')
plt.subplot(326)
plt.set_cmap(plt.gray())
plt.imshow(np.log(abs(np.fft.fftshift((kspace)))))
plt.ylabel('kspace*pattern')
plt.show()

# %% Plot all iter
# make 25 example iterations
idx = np.linspace(1, all_iter.shape[2], 25) - 1
# choose them from all iters
red_iter = all_iter[:, :, tuple(idx.astype(int))]
Tot = red_iter.shape[2]
Rows = Tot // 5
if Tot % 5 != 0:
    Rows += 1
Position = range(1, Tot + 1)  # Position index

fig = plt.figure()
for k in range(Tot):
    ax = fig.add_subplot(Rows, 5, Position[k])
    ax.imshow((abs((red_iter[:, :, k]))))
    plt.title('iter {}'.format(idx[k].astype(int)))
    print(k)
plt.show()


import sys
import re
import os
from Graph import *
from heuristic import *

if __name__ == '__main__':

    # Getting path to a text file, given as system argument
    # Default file - test1.txt
    path = "tests/test1.txt"
    if len(sys.argv) > 1:
        arg = sys.argv[1]
        if os.path.exists(arg):
            filename, file_extension = os.path.splitext(arg)
            if file_extension == '.txt':
                path = arg
            else:
                print("Wrong file extension. Using default file. ")
        else:
            print("No such a file. Using default file. ")

    file = open(path, 'r')

    # Getting info from file
    matrix_height = int(file.readline())
    matrix_width = int(file.readline())

    start_coordinates = re.findall(r'\d+', file.readline())
    start_position = (int(start_coordinates[0]), int(start_coordinates[1]))

    goal_coordinates = re.findall(r'\d+', file.readline())
    goal_position = (int(goal_coordinates[0]), int(goal_coordinates[1]))

    # reading matrix
    map = []
    for i in range(matrix_height):
        values = []
        line = file.readline().split()
        for value in line:
            values.append(int(value))
        map.append(values)
    matrix = Matrix(matrix_height, matrix_width, map)

    # Creating graph
    graph = Graph(matrix)
    heuristic = manhattan_distance
    path = graph.search(start_position, goal_position, heuristic)  # getting path

    # Handling result
    if path == None:
        print("No path was found.")
    else:
        # Printing info about solution
        print(graph.path_matrix(path))  # print matrix with directions and balls
        directions_dict = graph.directions(path)
        directions = ""
        for move in path:
            if directions_dict[move.position] != 'F':
                directions += directions_dict[move.position] + " -> "
            else:
                directions += directions_dict[move.position] + "."
        print("\n" + directions)
        print("\nPath length: " + str(len(path) - 1) + " steps.")


import gym
import os
import random
from mmdet3d.core.bbox import DepthInstance3DBoxes
import numpy as np
import torch
import open3d as o3d

class Active_3d(gym.Env):
    def __init__(self):
        self.data_root_path = '/home/zhl/project/Reinforcement Learning/R3AD/mmdetection3d/data/r3ad/data/'
        self.action_space = gym.spaces.Discrete(3)
        self.observation_space = gym.spaces.Box(shape=(5, 256, 259), low=-100, high=100)
        self.train_Home_list = ['Home_3', 'Home_4', 'Home_5', 'Home_6', 'Home_7']
        self.angle_list = ['0', '45', '90', '135', '180', '225', '270', '315']

        self.votenet_pre = torch.load('model_V.pkl')
        self.votenet_train = torch.load('model_V.pkl')
        self.meta = []
        for i in range(6688):
            self.meta.append({'box_type_3d':DepthInstance3DBoxes})

    def reset(self):
        Home = random.choice(self.train_Home_list)
        self.data_path = self.data_root_path + Home + '/'
        self.coors_list = os.listdir(self.data_path)
        self.coor_now = random.choice(self.coors_list)
        self.angle_now = random.choice(self.angle_list)
        self.obs_buffer = np.zeros((104, 256 * 259))
        self.step_num = 0
        self.done = 0
        cloud_path, _, _, _ = self.path()
        assert os.path.exists(cloud_path)
        points = []
        points.append(self.read_pc(cloud_path))
        self.bbox_results = self.votenet_train.simple_test(points, self.meta, None, True)
        obsret = self.votenet_train.backbone.fp_ret
        obs = torch.cat((obsret['fp_xyz'][0], obsret['fp_features'][0].permute(0, 2, 1)), axis=2)
        obs = obs.detach().cpu().squeeze().data.numpy()
        obs = obs.flatten()
        self.obs_buffer[4] = obs
        coor_space = self.coor_space()
        return {'observation': self.obs_buffer[:5], 'mask': coor_space}

    def step(self, action):
        coor_int = [int(i) for i in self.coor_now.split(' ')]
        action_coor = action[0]
        action_angle = action[1]

        self.coor_now = self.coor_now_cal(action_coor, coor_int)
        self.angle_now = self.angle_list[action_angle]

        cloud_path, _, _, _ = self.path()
        assert os.path.exists(cloud_path)
        reward, obs = self.reward_cal(cloud_path)
        obs = obs.detach().cpu().squeeze().data.numpy().flatten()
        self.obs_buffer[self.step_num + 5] = obs

        coor_space = self.coor_space()

        self.step_num += 1

        if self.step_num == 99:
            self.done = True

        return {'observation': self.obs_buffer[self.step_num : self.step_num + 5], 'mask': coor_space}, reward, self.done, {}

    def coor_space(self):
        coor_int = [int(i) for i in self.coor_now.split(' ')]
        coor_f = ' '.join([str(i) for i in [coor_int[0], coor_int[1] + 1]])
        coor_b = ' '.join([str(i) for i in [coor_int[0], coor_int[1] - 1]])
        coor_l = ' '.join([str(i) for i in [coor_int[0] - 1, coor_int[1]]])
        coor_r = ' '.join([str(i) for i in [coor_int[0] + 1, coor_int[1]]])
        coor_fl = ' '.join([str(i) for i in [coor_int[0] - 1, coor_int[1] + 1]])
        coor_fr = ' '.join([str(i) for i in [coor_int[0] + 1, coor_int[1] + 1]])
        coor_bl = ' '.join([str(i) for i in [coor_int[0] - 1, coor_int[1] - 1]])
        coor_br = ' '.join([str(i) for i in [coor_int[0] + 1, coor_int[1] - 1]])

        coor_space = [1, 0, 0, 0, 0, 0, 0, 0, 0]
        if coor_f in self.coors_list:
            coor_space[1] = 1
        if coor_b in self.coors_list:
            coor_space[2] = 1
        if coor_l in self.coors_list:
            coor_space[3] = 1
        if coor_r in self.coors_list:
            coor_space[4] = 1
        if coor_fl in self.coors_list:
            coor_space[5] = 1
        if coor_fr in self.coors_list:
            coor_space[6] = 1
        if coor_bl in self.coors_list:
            coor_space[7] = 1
        if coor_br in self.coors_list:
            coor_space[8] = 1

        return coor_space

    def coor_now_cal(self, action_coor, coor_int):
        coor_now = ' '.join([str(i) for i in [coor_int[0], coor_int[1]]])
        coor_f = ' '.join([str(i) for i in [coor_int[0], coor_int[1] + 1]])
        coor_b = ' '.join([str(i) for i in [coor_int[0], coor_int[1] - 1]])
        coor_l = ' '.join([str(i) for i in [coor_int[0] - 1, coor_int[1]]])
        coor_r = ' '.join([str(i) for i in [coor_int[0] + 1, coor_int[1]]])
        coor_fl = ' '.join([str(i) for i in [coor_int[0] - 1, coor_int[1] + 1]])
        coor_fr = ' '.join([str(i) for i in [coor_int[0] + 1, coor_int[1] + 1]])
        coor_bl = ' '.join([str(i) for i in [coor_int[0] - 1, coor_int[1] - 1]])
        coor_br = ' '.join([str(i) for i in [coor_int[0] + 1, coor_int[1] - 1]])
        while True:
            if action_coor == 0:
                return coor_now
            elif action_coor == 1:
                return coor_f
            elif action_coor == 2:
                return coor_b
            elif action_coor == 3:
                return coor_l
            elif action_coor == 4:
                return coor_r
            elif action_coor == 5:
                return coor_fl
            elif action_coor == 6:
                return coor_fr
            elif action_coor == 7:
                return coor_bl
            elif action_coor == 8:
                return coor_br
            else:
                print('action wrong!!!!')

    def path(self):
        cloud_path = ''.join([self.data_path, self.coor_now, '/', 'cloud ', self.angle_now, '.pcd'])
        color_path = ''.join([self.data_path, self.coor_now, '/', 'color ', self.angle_now, '.png'])
        depth_path = ''.join([self.data_path, self.coor_now, '/', 'depth ', self.angle_now, '.png'])
        anno_path = ''.join([self.data_path, self.coor_now, '/', 'anno ', self.angle_now, '.txt'])
        return cloud_path, color_path, depth_path, anno_path

    def read_pc(self, path):
        pcd = o3d.io.read_point_cloud(path)
        xyz = pcd.points
        # o3d format(yz-x) to depth format
        xyz = np.asarray(xyz)[:, [0, 2, 1]]
        xyz[:, 1] = -xyz[:, 1]
        xyz[:, 2] = xyz[:, 2] + 1.1

        RGB = pcd.colors
        RGB = np.asarray(RGB)

        pc = np.concatenate((xyz, RGB), axis=1)

        if pc.shape[0]<20000:
            Replace = True
        else:
            Replace=False
        choices = np.random.choice(pc.shape[0], 20000, replace=Replace)
        pc = pc[choices]

        floor_height = np.percentile(pc[:, 2], 0.99)
        height = pc[:, 2] - floor_height
        pc = np.concatenate([pc, np.expand_dims(height, 1)], 1)

        return torch.from_numpy(pc).float().cuda()

    def reward_cal(self, path):
        reward = 0
        points = []
        points.append(self.read_pc(path))
        self.bbox_results = self.votenet_train.simple_test(points, self.meta, None, True)
        obsret = self.votenet_train.backbone.fp_ret
        obs = torch.cat((obsret['fp_xyz'][0], obsret['fp_features'][0].permute(0, 2, 1)), axis=2)
        return reward, obs


import cv2
import pytesseract

pytesseract.pytesseract.tesseract_cmd = "C:\\Program Files\\Tesseract-OCR\\tesseract.exe"

def ocr_main(file):
    img = cv2.imread(file)

    img = cv2.resize(img, None, fx=0.25, fy=0.25)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    thresh_img = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 11)
    extracted_text = pytesseract.image_to_string(thresh_img)
    return extracted_text


import itertools as it
import more_itertools as mit
import functools as ft
import operator as op
import re
from collections import Counter

from time import sleep

def path(x1, y1, x2, y2):
    if x1 == x2:
        return map(lambda y: (x1, y), range(min(y1, y2), max(y1, y2) + 1))
    elif y1 == y2:
        return map(lambda x: (x, y1), range(min(x1, x2), max(x1, x2) + 1))

CLEAR_SCREEN = "\033[3J\033[H"

with open("input") as inf, open("part1.out", "w+") as outf:
    paths = [[tuple(map(int, j.split(',')))
              for j in i.split(" -> ")]
             for i in inf.read().splitlines()]

    rocks = set()
    sand = set()

    current_grain = (500, 0)

    for p in paths:
        for (x1, y1), (x2, y2) in it.pairwise(p):
            rocks.update(set(path(x1, y1, x2, y2)))

    min_x = min(map(op.itemgetter(0), rocks)) - 5
    max_x = max(map(op.itemgetter(0), rocks)) + 5

    min_y = 0
    max_y = max(map(op.itemgetter(1), rocks)) + 5

    while True:
        next_pos = (current_grain[0], current_grain[1] + 1)
        if next_pos in rocks | sand:
            next_pos = (next_pos[0] - 1, next_pos[1])
            if next_pos in rocks | sand:
                next_pos = (next_pos[0] + 2, next_pos[1])
                if next_pos in rocks | sand:
                    sand.add(current_grain)
                    next_pos = (500, 0)
        current_grain = next_pos

        if current_grain[1] > max_y:
            outf.write(str(len(sand)))
            exit()

        print(CLEAR_SCREEN, end='', flush=False)
        for y in range(current_grain[1] // 40 * 40,
                       current_grain[1] // 40 * 40 + 40):
            for x in range(min_x, max_x):
                print('█' if (x, y) in rocks else '░' if
                      (x, y) == current_grain else '▒' if
                      (x, y) in sand else ' ',
                      end='',
                      flush=False)

            print(flush=True)

        # sleep(0.01)


import csv
from pathlib import Path
import qrcode
import barcode
from barcode.writer import ImageWriter
from PIL import Image, ImageFont, ImageDraw

from user import User
from util_pil import add_margin, crop_square, crop_center, expand_square, concat_v, concat_h

# アイコン画像保存用ディレクトリ
ICON_DIR_PATH = str(Path(__name__).parent / 'icon')
# 名札画像生成用ディレクトリ
NAME_TAG_DIR_PATH = str(Path(__name__).parent / 'name_tag')
# 名札画像
CONCAT_DIR_PATH = str(Path(__name__).parent / 'concat')
Path(ICON_DIR_PATH).mkdir(exist_ok=True)
Path(NAME_TAG_DIR_PATH).mkdir(exist_ok=True)
Path(CONCAT_DIR_PATH).mkdir(exist_ok=True)

CSV_PATH = r'data.csv'
BASE_NAME_TAG_PATH = r'base.png'
DEFAULT_ICON_PATH = r'default_icon.png'
DUMMY_IMG_PATH = r'dummy.png'
FONT_PATH = r'NotoSansJP-Bold.otf'

def load_csv(csv_path):
    tmp_part_dict = {}

    # connpassからダウンロードできるcsvファイルはShift-JIS
    with open(csv_path, encoding='cp932') as f:
        reader = csv.reader(f)
        # 1行目のヘッダーをスキップ
        next(reader)

        # 1行ずつ読み込み
        for row in reader:
            user = User('')
            # ユーザー名
            user.user_name = row[1]
            # 表示名
            user.display_name = row[2]
            # 参加ステータス
            user.status_part = row[5]
            # 受付番号
            user.rcpt_number = row[10]

            # 参加ステータスがキャンセルの参加者は除外
            if 'キャンセル' in user.status_part:
                continue

            # リストに参加者を追加
            tmp_part_dict[user.user_name] = user

        return tmp_part_dict

def gen_name_tag(user, over_write=False):
    # 名札保存先のパス
    name_tag_path = Path(NAME_TAG_DIR_PATH) / '{}.png'.format(user.user_name)

    # 生成済みか否かを確認
    if Path(name_tag_path).is_file():
        print('Already generate name tag')
        # 上書きを許可していない場合
        if not over_write:
            print('Skip generate')
            return

    # ベース画像を読み込み
    # 横:91mm 縦:55mm
    base_img = Image.open(BASE_NAME_TAG_PATH).convert('RGBA')
    # ベース画像のサイズをすべての計算の基準とする
    base_img_size = base_img.size

    # 表示名
    dn_img = Image.new('RGBA', base_img_size)
    draw_dn_img = ImageDraw.Draw(dn_img)

    # 表示名のフォントサイズを計算
    # 横:64% 縦:10%に収まる
    i = 1
    bbox = draw_dn_img.textbbox((0, 0), user.display_name, font=ImageFont.truetype(FONT_PATH, i))
    while bbox[2] < base_img_size[0] * 0.64 and bbox[3] < base_img_size[1] * 0.12:
        i += 1
        bbox = draw_dn_img.textbbox((0, 0), user.display_name, font=ImageFont.truetype(FONT_PATH, i))

    # 表示名の文字を描画
    # 横: 中央 縦:中央 + 20%
    draw_dn_img.text(
        (base_img_size[0] * 0.50, base_img_size[1] * 0.70),
        user.display_name,
        fill=(255, 255, 255),
        font=ImageFont.truetype(FONT_PATH, i - 1),
        anchor='mm',
    )

    # 受付番号
    # rn_img = Image.new('RGBA', base_img_size)
    # draw_dn_img = ImageDraw.Draw(rn_img)

    # 受付番号の文字を描画
    # draw_dn_img.text(
    #     (30, base_img_size[1] - 20),
    #     user.rcpt_number,
    #     fill='black',
    #     font=ImageFont.truetype(FONT_PATH, 12),
    #     anchor='mm',
    # )

    # アイコン
    # サイズは256x256に角r30px
    if Path(user.icon_path).is_file():
        # ダウンロードしたアイコン画像
        icon_img = Image.open(user.icon_path).convert('RGBA')
    else:
        # デフォルトのアイコン画像
        icon_img = Image.open(DEFAULT_ICON_PATH).convert('RGBA')

    # 余白を足して正方形に
    # icon_img = expand2square(icon_img, (255, 255, 255, 0))
    # クロップして正方形に
    icon_img = crop_square(icon_img)
    # リサイズ 18.5x18.5mm
    icon_size = (
        round(base_img_size[0] / 91 * 18.5),
        round(base_img_size[0] / 91 * 18.5)
    )
    icon_img = icon_img.resize(icon_size)

    # 四隅のピクセルから角丸加工の有無を判定
    round_flag = True
    # 四隅のピクセルが透明か否か
    if icon_img.getpixel((0, 0))[3] == 0 or \
            icon_img.getpixel((icon_img.size[0] - 1, 0)) == 0 or \
            icon_img.getpixel((0, icon_img.size[1] - 1)) == 0 or \
            icon_img.getpixel((icon_img.size[0]-1, icon_img.size[1]-1)) == 0:
        round_flag = False

    # ベースと同じサイズに拡張
    # 横: 中央 縦:上から40%
    icon_img = add_margin(
        icon_img,
        round((base_img_size[1] - icon_img.size[1]) * 0.40),   # top
        round((base_img_size[0] - icon_img.size[0]) * 0.50),   # right
        round((base_img_size[1] - icon_img.size[1] - (base_img_size[1] - icon_img.size[1]) * 0.40)),   # bottom
        round((base_img_size[0] - icon_img.size[0] - (base_img_size[0] - icon_img.size[0]) * 0.50)),   # left
        (0, 0, 0, 0))

    # ベースと同じサイズに拡張した結果サイズが1pxオーバーした場合の処理
    if base_img_size[0] != icon_img.size[0] or base_img_size[1] != icon_img.size[1]:
        # ベースのサイズで中央をクロップ
        icon_img = crop_center(icon_img, base_img_size[0], base_img_size[1])

    if round_flag:
        # 角丸: 2.2mm
        radius = round(base_img_size[0] / 91 * 2.2)
        # 角丸用マスク
        icon_msk_img = Image.new('L', base_img_size, 255)
        draw_icon_msk_img = ImageDraw.Draw(icon_msk_img)
        draw_icon_msk_img.rounded_rectangle(
            (round((base_img_size[0] - icon_size[0]) * 0.50) + 1,
             round((base_img_size[1] - icon_size[1]) * 0.40) + 1,
             round((base_img_size[0] - icon_size[0]) * 0.50) + icon_size[0] - 1,
             round((base_img_size[1] - icon_size[1]) * 0.40) + icon_size[1] - 1),
            radius=radius,
            fill=0,
            outline=None,
            width=0
        )

    # QRコード
    # qr = qrcode.QRCode(box_size=2)
    # qr.add_data(user.rcpt_number)
    # qr.make()
    # qr_img = qr.make_image()
    # qr_img = qr_img.resize((200, 200))
    # qr_pos = (base_img_size[0] - qr_img.size[0], base_img_size[1] - qr_img.size[1])

    # バーコード
    # a = barcode.get_barcode_class('code128')
    # b = a(user.rcpt_number, writer=ImageWriter())
    # b.save('tmp_bc')
    # bc_img = Image.open('tmp_bc.png')
    # bc_img = bc_img.resize((400, 400))
    # bc_pos = (base_img_size[0] - bc_img.size[0], base_img_size[1] - bc_img.size[1])

    # 表示名をアルファブレンド
    res_img = Image.alpha_composite(base_img, dn_img)

    # 受付番号をアルファブレンド
    # res_img = Image.alpha_composite(res_img, rn_img)

    # アイコンをコンポジット
    if round_flag:
        # 角丸加工が必要な場合はマスクを使用してコンポ
        res_img = Image.composite(res_img, icon_img, icon_msk_img)
    else:
        # 角丸加工が不要な場合はアルファブレンド
        res_img = Image.alpha_composite(res_img, icon_img)

    # QRコードを貼り付け
    # res_img.paste(qr_img, qr_pos)

    # バーコードを貼り付け
    # res_img.paste(bc_img, bc_pos)

    # 保存
    res_img.convert('RGB').save(name_tag_path)
    print('Generate name tag: {}'.format(name_tag_path))

def concat_nametag(path_list, output_dir, prefix=''):
    # 書き出し画像用カウンタ
    cnt = 0
    # 余白用dummy画像
    dummy_im = Image.open(DUMMY_IMG_PATH)

    it = iter(path_list)
    while True:
        im0_path = im1_path = im2_path = im3_path = im4_path = None
        im5_path = im6_path = im7_path = im8_path = im9_path = None
        try:
            im0_path = next(it)
            im1_path = next(it)
            im2_path = next(it)
            im3_path = next(it)
            im4_path = next(it)
            im5_path = next(it)
            im6_path = next(it)
            im7_path = next(it)
            im8_path = next(it)
            im9_path = next(it)
        except StopIteration:
            break
        finally:
            im0 = Image.open(im0_path) if im0_path and Path(im0_path).is_file() else dummy_im
            im1 = Image.open(im1_path) if im1_path and Path(im1_path).is_file() else dummy_im
            im2 = Image.open(im2_path) if im2_path and Path(im2_path).is_file() else dummy_im
            im3 = Image.open(im3_path) if im3_path and Path(im3_path).is_file() else dummy_im
            im4 = Image.open(im4_path) if im4_path and Path(im4_path).is_file() else dummy_im
            im5 = Image.open(im5_path) if im5_path and Path(im5_path).is_file() else dummy_im
            im6 = Image.open(im6_path) if im6_path and Path(im6_path).is_file() else dummy_im
            im7 = Image.open(im7_path) if im7_path and Path(im7_path).is_file() else dummy_im
            im8 = Image.open(im8_path) if im8_path and Path(im8_path).is_file() else dummy_im
            im9 = Image.open(im9_path) if im9_path and Path(im9_path).is_file() else dummy_im

            # 各名札画像を詰め込み
            res = concat_v(concat_h(im0, im1), concat_h(im2, im3))
            res = concat_v(res, concat_h(im4, im5))
            res = concat_v(res, concat_h(im6, im7))
            res = concat_v(res, concat_h(im8, im9))

            # 余白を追加 左右14mm 上下11mmずつ -> 印刷時の余白が上下5mm発生するので4mm 1mmで計算
            # https://www.a-one.co.jp/product/search/detail.php?id=72110
            # concat後の画像は横182mm 縦275mm
            margin_x = round(res.size[0] / 182 * 4)
            margin_y = round(res.size[1] / 275 * 1)
            res = add_margin(res, margin_y, margin_x, margin_y, margin_x, (57, 57, 57))

            # 保存
            concat_path = str(Path(output_dir) / '{}{:0=3}.png'.format(prefix, cnt))
            res.save(concat_path)
            print('Concat name tag: {}'.format(concat_path))

            cnt += 1

if __name__ == '__main__':
    # CSVを読み込み
    part_dict = load_csv(CSV_PATH)

    for uid, user in part_dict.items():
        print(user.user_name)
        # アイコンをダウンロード
        user.download_icon(skip=True, over_write=False)
        # 名札を生成
        gen_name_tag(user, over_write=False)

    # 表示名順でソートしたリストに変換
    part_list = list(part_dict.values())
    part_list.sort(key=lambda x: x.display_name)
    # 表示名順でソートした名札画像のパスリスト
    nametag_path_list = [str(Path(NAME_TAG_DIR_PATH) / '{}.png'.format(p.user_name)) for p in part_list]
    # 生成した名札を10枚単位でconcat
    concat_nametag(nametag_path_list, CONCAT_DIR_PATH, 'general')

    # 以下ディレクトリに名札画像(全部同一サイズ)を入れると10枚単位でconcatされる
    # EX_NAME_TAG_DIR_PATH = r'ex_name_tag'
    # glob_p = r'*.png'
    # gr = list(Path(EX_NAME_TAG_DIR_PATH).glob(glob_p))
    # gr = [str(g) for g in gr]
    # concat_nametag(gr, CONCAT_DIR_PATH, 'ex')