from models import mnist_models as mnist
import training_runner as base_runner
import callback_utilities
import utilities as util
import tarantella as tnt

import tensorflow as tf
import enum
import pytest

setup_save_path = callback_utilities.setup_save_path

class CallbackWrapper(enum.Enum):
  NONE = 0,
  DEFAULT = 1,  # behaves similar to a normal keras callback - runs only once (on a single rank)
  ONE_RANK = 2,
  MULTI_RANK = 3

class PrintingCallback(tf.keras.callbacks.Callback):
  def on_batch_end(self, batch, logs = None):
    if batch % 4 == 0:
      print(f"[rank {tnt.get_rank()}] Batch {batch} done")

  def on_epoch_end(self, epoch, logs = None):
    print(f"[rank {tnt.get_rank()}] Epoch {epoch} done")

def is_callback_running_on_one_rank(model_config, wrapper_type):
  if wrapper_type in [CallbackWrapper.NONE]:
    if model_config.parallel_strategy == tnt.ParallelStrategy.DATA:
      return False
  elif wrapper_type in [CallbackWrapper.MULTI_RANK]:
    return False
  return True

@pytest.mark.parametrize("model_config", [base_runner.ModelConfig(mnist.subclassed_model_generator),
                                          pytest.param(base_runner.ModelConfig(mnist.fc_model_generator_four_partitions,
                                                                               tnt.ParallelStrategy.PIPELINING),
                                                       marks=pytest.mark.skipif(tnt.get_size() != 4,
                                                                                reason="Can only run on 4 ranks, model has 4 partitions")),
                                          pytest.param(base_runner.ModelConfig(mnist.fc_model_generator,
                                                                               tnt.ParallelStrategy.PIPELINING),
                                                       marks=pytest.mark.skipif(tnt.get_size() != 1,
                                                                                reason="Cannot run multi-rank, model has only one partition")),
                                          ])
class TestUserDefinedCallbacks:
  @pytest.mark.parametrize("number_epochs", [2])
  @pytest.mark.parametrize("wrapper_type", [CallbackWrapper.NONE,
                                            CallbackWrapper.DEFAULT,
                                            CallbackWrapper.ONE_RANK])
  def test_custom_callback_one_rank(self, model_config, number_epochs, wrapper_type, capsys):
    if not is_callback_running_on_one_rank(model_config, wrapper_type):
      pytest.skip("test configuration for multi-rank callback")

    ref_callback = PrintingCallback()
    tnt_callback = PrintingCallback()
    if wrapper_type == CallbackWrapper.DEFAULT:
      tnt_callback = tnt.keras.callbacks.Callback(tnt_callback)
    elif wrapper_type == CallbackWrapper.ONE_RANK:
      tnt_callback = tnt.keras.callbacks.Callback(tnt_callback, run_on_all_ranks = False)

    train_dataset, _ = callback_utilities.train_val_dataset_generator()
    ref_train_dataset, _ = callback_utilities.train_val_dataset_generator()
    tnt_model_runner, reference_model_runner = callback_utilities.gen_model_runners(model_config)

    param_dict = {'epochs' : number_epochs,
                  'verbose' : 0,
                  'shuffle' : False}
    tnt_history = tnt_model_runner.model.fit(train_dataset,
                                             callbacks = [tnt_callback],
                                             **param_dict)
    tnt_captured = capsys.readouterr()
    ref_history = reference_model_runner.model.fit(ref_train_dataset,
                                                   callbacks = [ref_callback],
                                                   **param_dict)
    ref_captured = capsys.readouterr()

    callback_utilities.assert_identical_tnt_and_ref_history(tnt_history, ref_history)
    if tnt.is_master_rank():
      result = (tnt_captured.out == ref_captured.out)
    else:
      result = all([tnt_captured.out == "", tnt_captured.err == ""])
    util.assert_on_all_ranks(result)

  @pytest.mark.parametrize("number_epochs", [3])
  @pytest.mark.parametrize("wrapper_type", [CallbackWrapper.NONE,
                                            CallbackWrapper.MULTI_RANK])
  def test_custom_callback_multi_rank(self, model_config, number_epochs, wrapper_type, capsys):
    if is_callback_running_on_one_rank(model_config, wrapper_type):
      pytest.skip("test configuration for single-rank callback")

    ref_callback = PrintingCallback()
    tnt_callback = PrintingCallback()
    if wrapper_type == CallbackWrapper.MULTI_RANK:
      tnt_callback = tnt.keras.callbacks.Callback(tnt_callback, run_on_all_ranks = True)

    train_dataset, _ = callback_utilities.train_val_dataset_generator()
    ref_train_dataset, _ = callback_utilities.train_val_dataset_generator()
    tnt_model_runner, reference_model_runner = callback_utilities.gen_model_runners(model_config)

    param_dict = {'epochs' : number_epochs,
                  'verbose' : 0,
                  'shuffle' : False}
    tnt_history = tnt_model_runner.model.fit(train_dataset,
                                             callbacks = [tnt_callback],
                                             **param_dict)
    tnt_captured = capsys.readouterr()
    ref_history = reference_model_runner.model.fit(ref_train_dataset,
                                                   callbacks = [ref_callback],
                                                   **param_dict)
    ref_captured = capsys.readouterr()

    callback_utilities.assert_identical_tnt_and_ref_history(tnt_history, ref_history)
    util.assert_on_all_ranks(tnt_captured.out == ref_captured.out)


from django.db import models

# Create your models here.

# Un destino es un lugar al que se puede viajar, pero sin incluir los datos respecto al viaje, como precio, etc...
class Destino(models.Model):
	lugar = models.CharField(max_length=100)
	descripcion = models.TextField()
	distancia = models.IntegerField()

	def __unicode__(self):
        	return self.lugar

class Viaje(models.Model):
	destino = models.ForeignKey(Destino, related_name="viajes")
	dias = models.IntegerField()
	coste = models.IntegerField()

	OPCIONES = (
	('Tren','Tren'),
	('Avion','Avion'),
	('Barco','Barco'),
	('Autobus','Autobus'),
	)

	desplazamiento = models.CharField(max_length=10, choices = OPCIONES)

	def __str__(self):
		return self.destino

class Ruta(models.Model):
	nombre = models.CharField(max_length=200)
	destinos = models.ManyToManyField(Destino)

	def __str__(self):
		return self.nombre

	def getDias(self):
		dias=0
		for destino in self.destinos.all():
			for viaje in destino.viajes.all():
				dias+=viaje.dias
		return dias

	def getCoste(self):
		coste=0
		for destino in self.destinos.all():
			for viaje in destino.viajes.all():
				coste+=viaje.coste
		return coste


import navis
import requests
import warnings

import cloudvolume as cv
import numpy as np
import pandas as pd
import trimesh as tm

from abc import ABC
from io import StringIO, BytesIO

from ..utils import make_iterable

use_pbars = True

class OnDemandDict(dict):
    """Initialized with a just a URL.

    Will fetch data from given URL on first request.

    """

    def __init__(self, url):
        """Initialize with just a URL."""
        self.url = url
        self.fetched = False
        super().__init__()

    def __getitem__(self, key):
        if not self.fetched:
            self.update_from_url()
        return super().__getitem__(key)

    def __contains__(self, key):
        if not self.fetched:
            self.update_from_url()
        return super().__contains__(key)

    def get(self, *args, **kwargs):
        if not self.fetched:
            self.update_from_url()
        return super().get(*args, **kwargs)

    def update_from_url(self):
        """Update content from URL."""
        resp = requests.get(self.url)
        resp.raise_for_status()
        self.update(resp.json())
        self.fetched = True

TRANSFORM_SERVICE_URL = 'https://services.itanna.io/app/transform-service'
SYNAPSE_SERVICE_URL = 'https://services.itanna.io/app/synapse-service'

TRANSFORM_SERVICE_INFO = OnDemandDict(f'{TRANSFORM_SERVICE_URL}/info')
SYNAPSE_SERVICE_INFO = OnDemandDict(f'{SYNAPSE_SERVICE_URL}/info')

def spine_transform_datasets():
    """Fetch datasets available on spine's transform service.

    Returns
    -------
    dict

    """
    resp = requests.get(f'{TRANSFORM_SERVICE_URL}/info')
    resp.raise_for_status()
    return resp.json()

class SpineService(ABC):
    """Abstract base class for spine services."""

    @property
    def info(self):
        """Return general info on given service."""
        if not hasattr(self, '_info'):
            url = self.makeurl('info')
            resp = self.session.get(url)
            resp.raise_for_status()
            self._info = resp.json()
        return self._info

    def urljoin(self, *args):
        """Join arguments into an url.

        Trailing but not leading slashes are stripped for each argument.

        """
        return "/".join(map(lambda x: str(x).rstrip('/'), args))

    def makeurl(self, *args):
        """Generate URL from base URL and args."""
        return self.urljoin(self.base_url, *args)

class FlyCacheService(SpineService):
    """Interface with cache services."""

    def __init__(self,
                 base_url='https://services.itanna.io/app/flycache-dev'):
        """Init class."""
        self.base_url = base_url

    def get_L2_centroids(self, ids, token, as_array=False, chunksize=50,
                         progress=True):
        """Fetch centroids of given l2 chunks.

        Coordinates are in nm.

        Parameter
        ---------
        ids :           iterable
                        Iterable with L2 IDs.
        token :         str
                        A ChunkedGraph/CAVE auth token.
        as_array :      bool
                        Determines output (see Returns).
        chunksize :     int
                        Query L2 IDs in chunks of this size.
        progress :      bool
                        Whether to show a progress bar or not.

        Returns
        -------
        array
                        If `as_array=True`: array in same order as queried `ids`.
                        Missing centroids are returns with coordinate (0, 0, 0).
        dict
                        If `as_array=False`: dictionary mapping ID to
                        centroid `{L2_ID: [x, y, z], ..}`.

        """
        url = self.makeurl('mesh/l2_centroid/flywire_fafb_production/')

        # Make sure we have an array of integers
        ids = make_iterable(ids, force_type=np.int64)

        with navis.config.tqdm(total=len(ids), desc='Fetching centroids',
                               leave=False, disable=not progress) as pbar:

            # First we will get everything that's cached in a single big query
            post = {
                      "token": token,
                      "query_ids": ids.tolist()
                    }
            resp = self.session.post(url + '?cache_only=1', json=post)
            resp.raise_for_status()

            # Parse response
            centroids = {np.int64(k): v for k, v in resp.json().items()}

            # Filter to remaining IDs
            to_fetch = ids[~np.isin(ids, list(centroids))]

            # Update progress bar
            pbar.update(len(centroids))

            # Now go over the remaining indices in chunks
            for i in range(0, len(to_fetch), int(chunksize)):
                this_chunk = to_fetch[i:i+chunksize]
                post = {
                          "token": token,
                          "query_ids": this_chunk.tolist()
                        }

                resp = self.session.post(url, json=post)
                resp.raise_for_status()

                # Parse response
                data = resp.json()

                # IDs will have been returned as strings
                centroids.update({np.int64(k): v for k, v in data.items()})

                pbar.update(len(this_chunk))

        if not as_array:
            return centroids

        centroids = np.array([centroids.get(i, [0, 0, 0]) for i in ids])

        return centroids

class SynapseService(SpineService):
    """Interface with synapse service on `services.itanna.io`.

    Kindly hosted by Eric Perlman and Davi Bock! Check out the online docs for
    available API endpoints:
    https://services.itanna.io/app/synapse-service/docs

    Parameters
    ----------
    base_url :      str
                    Base URL for the service on spine.

    """

    def __init__(self,
                 base_url='https://services.itanna.io/app/synapse-service'):
        """Init class."""
        self.base_url = base_url
        self.session = requests.Session()

    @property
    def alignments(self):
        """Return available alignments of synapse data."""
        if not hasattr(self, '_alignments'):
            url = self.makeurl('alignments')
            resp = self.session.get(url)
            resp.raise_for_status()
            self._alignments = resp.json()
        return self._alignments

    @property
    def collections(self):
        """Return available collections of synapse data."""
        if not hasattr(self, '_collections'):
            url = self.makeurl('collections')
            resp = self.session.get(url)
            resp.raise_for_status()
            self._collections = resp.json()
        return self._collections

    @property
    def segmentations(self):
        """Return available segmentations the synapse data is mapped to."""
        if not hasattr(self, '_segmentations'):
            url = self.makeurl('segmentations')
            resp = self.session.get(url)
            resp.raise_for_status()
            self._segmentations = resp.json()
        return self._segmentations

    def validate_alignment(self, alignment):
        """Check if alignment exists."""
        available = [c.get('name', 'NA') for c in self.alignments]
        if alignment not in available:
            raise ValueError(f'{alignment} not among available alignments: '
                             f'{",".join(available)}')

    def validate_collection(self, collection):
        """Check if collection exists."""
        available = [c.get('name', 'NA') for c in self.collections]
        if collection not in available:
            raise ValueError(f'{collection} not among available collections: '
                             f'{",".join(available)}')

    def validate_segmentation(self, segmentation):
        """Check if alignment exists."""
        available = [c.get('name', 'NA') for c in self.segmentations]
        if segmentation not in available:
            raise ValueError(f'{segmentation} not among available segmentations: '
                             f'{",".join(available)}')

    def get_synapse(self, synapse_id, collection):
        """Return all available info (pre/post IDs, location) for single synapse.

        Parameter
        ---------
        synapse_id :    int
                        ID of synapse to query.
        collection :    str
                        Collection to query for the synapse. See ``.collections``
                        for a list of available collections. Currently available:

                          - "buhmann2019": Buhmann synapses

        Returns
        -------
        dict

        """
        assert isinstance(synapse_id, (int, np.integer, str))

        self.validate_collection(collection)

        url = self.makeurl('collection', collection, 'synapse', synapse_id, 'info')
        resp = self.session.get(url)
        resp.raise_for_status()
        return resp.json()

    def get_connectivity(self, segmentation_ids, segmentation, locations=False,
                         nt_predictions=False):
        """Fetch all connections from/to given segmentation ID(s).

        Parameters
        ----------
        segmentation_ids :  int | list thereof
                            Segmentation/root IDs to query.
        segmentation :      str
                            Which segmentation to search. Currently available:

                              - "fafb-ffn1-20190805" (segment IDs)
                              - "fafb-ffn1-20200412" (segment IDs)
                              - "flywire_supervoxels" (supervoxel IDs)
        locations :         bool
                            Whether to also fetch x/y/z locations for each
                            synapse.
        nt_predictions :    bool
                            Whether to also fetch neurotransmitter predictions
                            for each synapses.

        Returns
        -------
        pandas.DataFrame

        """
        # This always returns a numpy array
        segmentation_ids = navis.utils.make_iterable(segmentation_ids)

        # Check if segmentation actually exists
        self.validate_segmentation(segmentation)

        url = self.makeurl('segmentation', segmentation, 'feather')

        param = []
        if locations:
            param.append("locations=true")
        if nt_predictions:
            param.append("nt=eckstein2020")

        if param:
            url += f'?{"&".join(param)}'

        post = {"query_ids": segmentation_ids.tolist()}

        resp = self.session.post(url, json=post)
        resp.raise_for_status()

        # Read into DataFrame
        return pd.read_feather(BytesIO(resp.content))

class TransformService(SpineService):
    """Interface with transform service on `services.itanna.io`.

    Kindly hosted by Eric Perlman and Davi Bock! Check out the online docs for
    available API endpoints:
    https://services.itanna.io/app/transform-service/docs

    Parameters
    ----------
    base_url :      str
                    Base URL for the service on spine.

    """

    # Hard-coded data types for now. From:
    # https://github.com/bocklab/transform_service/blob/master/app/config.py
    DTYPES = {
              'test': np.float32,
              'flywire_v1': np.float32,
              'flywire_v1_inverse': np.float32,
              'fanc_v4_to_v3': np.float32,
              'fafb-ffn1-20200412': np.uint64,
              'fafb-ffn1-20200412-gcs': np.uint64,
              'fafb-ffn1-20200412-zarr': np.uint64,
              'flywire_190410': np.uint64
              }

    def __init__(self,
                 base_url='https://services.itanna.io/app/transform-service'):
        """Init class."""
        self.base_url = base_url
        self.session = requests.Session()

    def validate_dataset(self, dataset):
        """Check if dataset exists for given service."""
        if dataset not in self.info:
            ds_str = ", ".join(self.info.keys())
            raise ValueError(f'"{dataset}" not among listed datasets: {ds_str}')

    def validate_mip(self, mip, dataset):
        """Validate mip for given dataset."""
        assert isinstance(mip, (int, np.integer))
        if mip < 0:
            available_scales = sorted(self.info[dataset]['scales'])
            mip = available_scales[-mip - 1]
        elif mip not in self.info[dataset]['scales']:
            raise ValueError(f'mip {mip} not available for dataset "{dataset}". '
                             f'Available scales: {self.info["scales"]}')
        return mip

    def validate_output(self, x, on_fail='ignore'):
        """Validate output."""
        # If mapping failed will contain NaNs
        if on_fail != 'ignore':
            is_nan = np.any(np.isnan(x),
                            axis=1 if x.ndim == 2 else 0)
            if np.any(is_nan):
                msg = f'{is_nan.sum()} points failed to transform.'
                if on_fail == 'warn':
                    warnings.warn(msg)
                elif on_fail == 'raise':
                    raise ValueError(msg)

    def to_voxels(self, x, dataset, coordinates='nm'):
        """Parse spatial data into voxels coordinates.

        Parameters
        ----------
        x :             np.ndarray (N, 3) | Neuron/List | mesh
                        Data to transform.
        coordinates :   "nm" | "voxel"
                        Units of the coordinates in ``x``.

        Returns
        -------
        vxl :           np.ndarray (N, 3)
                        x/y/z coordinates extracted from x and converted to
                        voxels.

        """
        assert coordinates in ['nm',
                               'nanometer', 'nanometers',
                               'nanometre', 'nanometres',
                               'vxl', 'voxel', 'voxels']

        if isinstance(x, (navis.NeuronList, navis.TreeNeuron)):
            x = x.nodes[['x', 'y', 'z']].values
        elif isinstance(x, (navis.Volume, navis.MeshNeuron, tm.Trimesh)):
            x = np.asarray(x.vertices)

        # At this point we are expecting a numpy array
        vxl = np.asarray(x)

        # Make sure data is now in the correct format
        if vxl.ndim != 2 or vxl.shape[1] != 3:
            raise TypeError(f'Expected (N, 3) array, got {x.shape}')

        # We need to convert to voxel coordinates
        # Note that we are rounding here to get to voxels.
        # This will have the most impact on the Z section.
        if coordinates not in ['vxl', 'voxel', 'voxels']:
            # Make sure we are working with numbers
            # -> if dtype is "object" we will get errors from np.round
            if not np.issubdtype(vxl.dtype, np.number):
                vxl = vxl.astype(np.float64)

            # Convert to voxels
            vxl_size = self.info[dataset]['voxel_size']
            vxl = np.round(vxl / vxl_size).astype(np.int64)

        return vxl

    def get_offsets(self, x, transform, coordinates='nm', mip=-1, limit_request=10e9,
                    on_fail='warn'):
        """Transform coordinates.

        Parameters
        ----------
        x :             np.ndarray (N, 3) | Neuron/List | mesh
                        Data to transform.
        transform :     str
                        Dataset to use for transform. Currently available:

                         - 'flywire_v1': flywire to FAFB
                         - 'flywire_v1_inverse': FAFB to flywire
                         - 'fanc_v4_to_v3': FANC v4 to v3

                        See also ``.info`` for up-to-date info.
        mip :           int
                        Resolution of mapping. Lower = more precise but much slower.
                        Negative values start counting from the highest possible
                        resolution: -1 = highest, -2 = second highest, etc.
        coordinates :   "nm" | "voxel"
                        Units of the coordinates in ``x``.
        on_fail :       "warn" | "ignore" | "raise"
                        What to do if points failed to xform.

        Returns
        -------
        response :      np.ndarray
                        (N, 2) of dx and dy offsets.

        """
        assert on_fail in ['warn', 'raise', 'ignore']

        # Check if dataset exists
        self.validate_dataset(transform)

        # Parse mip
        mip = self.validate_mip(mip, dataset=transform)

        # Extract voxels from x
        vxl = self.to_voxels(x, transform, coordinates=coordinates)

        # Generate URL
        url = self.makeurl('transform/dataset', transform, 's', mip,
                           'values_binary/format/array_float_Nx3')

        # Make sure we don't exceed the maximum size for each request
        stack = []
        limit_request = int(limit_request)
        for ix in np.arange(0, vxl.shape[0], limit_request):
            this_vxl = vxl[ix: ix + limit_request]

            # Make request
            resp = self.session.post(url,
                                 data=this_vxl.astype(np.single).tobytes(order='C'))

            # Check for errors
            resp.raise_for_status()

            # Extract data
            data = np.frombuffer(resp.content, dtype=self.DTYPES[transform])

            # Reshape to [[dx1, dy1], [dx2, dy2], ...]
            data = data.reshape(this_vxl.shape[0], 2)
            stack.append(data)

        stack = np.concatenate(stack, axis=0)

        # See if any points failed to xform, and raise/warn if requested
        self.validate_output(stack, on_fail=on_fail)

        return stack

    def get_segids(self, x, segmentation, coordinates='nm', mip=-1,
                   limit_request=10e9, on_fail='warn'):
        """Fetch segmentation/supervoxel IDs.

        Parameters
        ----------
        x :             np.ndarray (N, 3) | Neuron/List | mesh
                        Coordinates to query segmentation IDs for.
        segmentation :  str
                        Segmentation to query. Currently available:

                         - 'fafb-ffn1-20200412'
                         - 'fafb-ffn1-20200412-gcs'
                         - 'fafb-ffn1-20200412-zarr'
                         - 'flywire_190410' (supervoxels)

        mip :           int
                        Resolution of mapping. Lower = more precise but much slower.
                        Negative values start counting from the highest possible
                        resolution: -1 = highest, -2 = second highest, etc.
        coordinates :   "nm" | "voxel"
                        Units of the coordinates in ``x``.
        limit_request : int
                        Max number of locations to query per request.
        on_fail :       "warn" | "ignore" | "raise"
                        What to do if points fail to return segmentation IDs.

        Returns
        -------
        response :      np.ndarray
                        (N, 2) of dx and dy offsets.

        """
        assert on_fail in ['warn', 'raise', 'ignore']

        # Check if dataset exists
        self.validate_dataset(segmentation)

        # Parse mip
        mip = self.validate_mip(mip, dataset=segmentation)

        # Extract voxels from x
        vxl = self.to_voxels(x, segmentation, coordinates=coordinates)

        # Generate URL
        url = self.makeurl('query/dataset', segmentation, 's', mip,
                           'values_binary/format/array_float_Nx3')

        # Make sure we don't exceed the maximum size for each request
        stack = []
        limit_request = int(limit_request)
        for ix in np.arange(0, vxl.shape[0], limit_request):
            this_vxl = vxl[ix: ix + limit_request]

            # Make request
            resp = self.session.post(url,
                                 data=this_vxl.astype(np.single).tobytes(order='C'))

            # Check for errors
            resp.raise_for_status()

            # Extract data
            data = np.frombuffer(resp.content, dtype=self.DTYPES[segmentation])

            stack.append(data)

        stack = np.concatenate(stack, axis=0)

        # See if any points failed to xform, and raise/warn if requested
        self.validate_output(stack, on_fail=on_fail)

        return stack

def query_spine_transform(x, dataset, query, coordinates='nm', mip=2,
                          limit_request=10e9, on_fail='warn'):
    """Fetch data via the transform service on spine.

    DEPCREATED! Use `spine.transform` or `spine.synapses` instead.

    Kindly hosted by Eric Perlman and Davi Bock! Check out
    https://services.itanna.io/app/transform-service/docs for available
    API endpoints.

    Parameters
    ----------
    x :             np.ndarray (N, 3) | Neuron/List | mesh
                    Data to transform.
    dataset :       str
                    Dataset to use for transform. Currently available:

                     - 'flywire_v1' (transformation)
                     - 'flywire_v1_inverse' (transformation)
                     - 'fanc_v4_to_v3' (transformation)
                     - 'fafb-ffn1-20200412' (query)
                     - 'fafb-ffn1-20200412-gcs' (query)
                     - 'fafb-ffn1-20200412-zarr' (query)
                     - 'flywire_190410' (query)

                    See also ``spine_transform_datasets()`` for up-to-date info.
    query :         "query" | "transform"
                    Whether we "query" segmentation IDs at given location(s) or
                    we want to "transform" locations into a different space.
    mip :           int
                    Resolution of mapping. Lower = more precise but much slower.
                    Negative values start counting from the highest possible
                    resolution: -1 = highest, -2 = second highest, etc.
    coordinates :   "nm" | "voxel"
                    Units of the provided coordinates in ``x``.
    on_fail :       "warn" | "ignore" | "raise"
                    What to do if points failed to xform.

    Returns
    -------
    response :      np.ndarray
                    (N, 2) of dx and dy coordinates for "transform"
                    (N, ) of IDs for "query"

    """
    # Hard-coded data types for now. From:
    # https://github.com/bocklab/transform_service/blob/master/app/config.py
    dtypes = {
              'test': np.float32,
              'flywire_v1': np.float32,
              'flywire_v1_inverse': np.float32,
              'fanc_v4_to_v3': np.float32,
              'fafb-ffn1-20200412': np.uint64,
              'fafb-ffn1-20200412-gcs': np.uint64,
              'fafb-ffn1-20200412-zarr': np.uint64,
              'flywire_190410': np.uint64
              }

    assert on_fail in ['warn', 'raise', 'ignore']
    assert query in ['query', 'transform']
    assert coordinates in ['nm',
                           'nanometer', 'nanometers',
                           'nanometre', 'nanometres',
                           'vxl', 'voxel', 'voxels']
    assert isinstance(mip, (int, np.integer))

    if mip < 0:
        available_scales = sorted(TRANSFORM_SERVICE_INFO[dataset]['scales'])
        mip = available_scales[-mip - 1]

    if dataset not in TRANSFORM_SERVICE_INFO:
        ds_str = ", ".join(TRANSFORM_SERVICE_INFO.keys())
        raise ValueError(f'"{dataset}" not among listed datasets: {ds_str}')

    if mip not in TRANSFORM_SERVICE_INFO[dataset]['scales']:
        raise ValueError(f'mip {mip} not available for dataset "{dataset}". '
                         f'Available scales: {TRANSFORM_SERVICE_INFO[dataset]["scales"]}')

    if isinstance(x, (navis.NeuronList, navis.TreeNeuron)):
        x = x.nodes[['x', 'y', 'z']].values
    elif isinstance(x, (navis.Volume, navis.MeshNeuron, tm.Trimesh)):
        x = np.asarray(x.vertices)

    # At this point we are expecting a numpy array
    x = np.asarray(x)

    # Make sure data is now in the correct format
    if x.ndim != 2 or x.shape[1] != 3:
        raise TypeError('Expected (N, 3) array, got {}'.format(x.shape))

    # We need to convert to voxel coordinates
    # Note that we are rounding here to get to voxels.
    # This will have the most impact on the Z section.
    if coordinates not in ['vxl', 'voxel', 'voxels']:
        x = np.round(x / [4, 4, 40]).astype(np.int64)

    # Generate URL
    url = f'{TRANSFORM_SERVICE_URL}/{query}/dataset/{dataset}/s/{mip}/values_binary/format/array_float_Nx3'

    # Make sure we don't exceed the maximum size for each request
    stack = []
    limit_request = int(limit_request)
    for ix in np.arange(0, x.shape[0], limit_request):
        this_x = x[ix: ix + limit_request]

        # Make request
        resp = requests.post(url,
                             data=this_x.astype(np.single).tobytes(order='C'))

        # Check for errors
        resp.raise_for_status()

        # Extract data
        data = np.frombuffer(resp.content, dtype=dtypes[dataset])
        if query == 'transform':
            data = data.reshape(this_x.shape[0], 2)
        stack.append(data)

    stack = np.concatenate(stack, axis=0)

    # If mapping failed will contain NaNs
    if on_fail != 'ignore':
        is_nan = np.any(np.isnan(stack),
                        axis=1 if stack.ndim == 2 else 0)
        if np.any(is_nan):
            msg = f'{is_nan.sum()} points failed to transform.'
            if on_fail == 'warn':
                warnings.warn(msg)
            elif on_fail == 'raise':
                raise ValueError(msg)

    return stack

synapses = SynapseService()
transform = TransformService()
flycache = FlyCacheService()


def greedy(tsp):
    sum = 0 # O(1)
    counter = 0 # O(1)
    i = 0 # O(1)
    j = 0 # O(1)
    mn = 999999999 # O(1)
    visitedRouteList = {} # O(1)
    visitedRouteList[0] = 1 # O(1)
    route = [0] *len(tsp) # O(1)
    while i < len(tsp) and j < len(tsp[i]): # O(N)
        if counter >= len(tsp[i]) - 1:# O(1)
            break
        if j!=i and j not in visitedRouteList: # O(N)
            if tsp[i][j] < mn:
                mn = tsp[i][j]
                route[counter] = j + 1
        j += 1
        if j == len(tsp[i]):
            sum += mn
            mn = 999999999
            visitedRouteList[route[counter] - 1] = 1
            j = 0
            i = route[counter] - 1
            counter += 1

    i = route[counter - 1] - 1
    for  j in range(0, len(tsp)): # O(N)
        if i != j and tsp[i][j] < mn: # O(1)
            mn = tsp[i][j] # O(1)
            route[counter] = j + 1 # O(1)

    sum += mn # O(1)
    return sum


from pygame import *
from random import randint
from time import sleep
font.init()
font1 = font.SysFont('Arial', 70)
font2 = font.SysFont('Arial', 20)
lose1 = font1.render('Player 1 lose!', True, (0, 0, 0))
lose2 = font1.render('Player 2 lose!', True, (0, 0, 0))
#__________________________________________________________________________________________________________________________________
bul = sprite.Group()
lose_ball1 = 0
lose_ball2 = 0
win_width = 700
win_height = 500
window = display.set_mode((win_width, win_height))
display.set_caption("Ping-pong")
bg = transform.scale(image.load("bg.png"), (win_width, win_height))

class GameSprite(sprite.Sprite):
    def __init__(self, player_image, player_x, player_y, player_speed, width, height):
        super().__init__()
        self.image = transform.scale(image.load(player_image), (width, height))
        self.speed = player_speed
        self.natural_speed = player_speed
        self.rect = self.image.get_rect()
        self.rect.x = player_x
        self.rect.y = player_y
        self.player_y = player_y
        self.width = width
        self.height = height
    def reset(self):
        window.blit(self.image, (self.rect.x, self.rect.y))
class Player(GameSprite):
    def update2(self):
        window.blit(self.image, (self.rect.x, self.rect.y))
        keys = key.get_pressed()
        if keys[K_UP] and self.rect.y > 0:
            self.rect.y -= self.speed
        if keys[K_DOWN] and self.rect.y < win_height - 110:
            self.rect.y += self.speed
    def update1(self):
        window.blit(self.image, (self.rect.x, self.rect.y))
        keys = key.get_pressed()
        if keys[K_w] and self.rect.y > 0:
            self.rect.y -= self.speed
        if keys[K_s] and self.rect.y < win_height - 110:
            self.rect.y += self.speed
play1 = Player('racket.png', 20, 0, 5, 20, 100)
play2 = Player('racket.png', win_width - 40, 0, 5, 20, 100)
ball = GameSprite('ball.png', win_width / 2, win_height / 2, 0, 40, 40)
game = True
clock = time.Clock()
FPS = 120
finish = False

speed_y = 2
speed_x = 2

while game:
    for e in event.get():
        if e.type == QUIT:
            game = False
    if finish != True:
        window.blit(bg, (0, 0))
        play1.update1()
        play2.update2()
        ball.reset()
        ball.rect.x += speed_x
        ball.rect.y += speed_y

        if sprite.collide_rect(play1, ball) or sprite.collide_rect(play2, ball):
            speed_x *= -1
            speed_y *= 1
        if ball.rect.y > win_height - 40 or ball.rect.y <= 0:
            speed_y *= -1
        if ball.rect.x <= 0:
            lose_ball1 += 1
            ball.rect.x = 340
            ball.rect.y = 240
            sleep(1)
            speed_x *= -1
            speed_y *= 1
        if ball.rect.x >= win_width - 40:
            lose_ball2 += 1
            ball.rect.x = 340
            ball.rect.y = 240
            sleep(1)
            speed_x *= -1
            speed_y *= 1
        score1 = font2.render(f'Счет 1: {lose_ball2}', True, (0, 0, 0))
        window.blit(score1,(0, 0))
        score2 = font2.render(f'Счет 2: {lose_ball1}', True, (0, 0, 0))
        window.blit(score2,(0, 20))
        if lose_ball1 >= 5:
            window.blit(lose1, (200, 200))
            finish = True
        if lose_ball2 >= 5:
            window.blit(lose2, (200, 200))
            finish = True
    display.update()
    clock.tick(FPS)


# is statements with comparisons
# can compare numbers or strings or booleans

# >= greater than or equal to - is a comparison operator
# other comparison operators : ==, != not equal, <, >, >=, <=
def max_num(num1, num2, num3):
    # comparing num1 to num2 and num3
    if num1 >= num2 and num1 >= num3:
        return num1
    # comparing num2 to num1 and num3
    elif num2 >= num1 and num2 >= num3:
        return num2
    # num 3 is the biggest
    else:
        return num3

print(max_num(3456, 40, 5))


import unittest
from pathlib import Path
import project1
from IO_file import read_instructions_from_file
from InstructionsProcess import *
from ElemetsInstance import *
import io
from contextlib import redirect_stdout

class MyTestCase(unittest.TestCase):
    def test_file(self):
        """Test the opening and reading of the given files."""
        path = Path('test.txt')
        self.assertEqual(read_instructions_from_file(path), ['PROPAGATE 1 2 750','PROPAGATE 2 3 1250'])
        path = Path('nothing.txt')
        self.assertEqual(str(read_instructions_from_file(path)),"[Errno 2] No such file or directory: 'nothing.txt'")

    def test_the_conflicts(self):
        """Test the function of finding conflicts instructions."""
        text_input = [
            'ALERT 2 Trouble 100',
            'ALERT 3 Trouble 100',
            'CANCEL 1 OH 10'
        ]
        text_output = {
            '100': ['ALERT 2 Trouble 100','ALERT 3 Trouble 100'],
            '10':['CANCEL 1 OH 10']
        }
        self.assertEqual(find_conflict(text_input), text_output)

    def test_situation_object(self):
        """Test for the function of Situation."""
        inst = project1.Situation('CANCEL', 'Trouble')
        self.assertEqual(inst.type, 'CANCEL')
        self.assertEqual(inst.msg, 'Trouble')

    def test_DEVICE(self):
        """Test device instance created as expected."""
        device_1 = Device(1)
        self.assertEqual(device_1.show_id(), 1)
        self.assertEqual(device_1.situation, [])
        sit = Situation('ALERT', 'Trouble')
        device_1.add_situation(sit)
        self.assertEqual(device_1.situation[0].type, 'ALERT')
        self.assertEqual(device_1.situation[0].msg, 'Trouble')
        sit = Situation('ALERT', 'Trouble')
        try:
            device_1.add_situation(sit)
        except Exception as e:
            self.assertEqual(str(e), 'Duplicate Alerts with same message')
        device_1.handle_cancel('Trouble')
        self.assertEqual(device_1.situation, [])
        sit = Situation('ALERT', 'Trouble')
        device_1.add_situation(sit)
        sit = Situation('CANCEL', 'Trouble')
        device_1.add_situation(sit)
        self.assertEqual(device_1.situation, [])
        sit = Situation('CANCEL', 'Trouble')
        device_1.add_situation(sit)
        sit = Situation('ALERT', 'Trouble')
        device_1.add_situation(sit)
        self.assertEqual(device_1.situation, [])

    def test_PRO(self):
        """Test the propagate instance created."""
        pro = Propagate(0, 'ALERT', 1, 2)
        self.assertEqual(pro.type, 'ALERT')
        self.assertEqual(pro.time, 0)
        self.assertEqual(pro.from_ID, 1)
        self.assertEqual(pro.to_ID, 2)

    def test_alert_cancel(self):
        """Testing the device can handle the instructions"""
        pro = project1.Device(1)
        alert = project1.Situation('ALERT', 'HELP')
        pro.add_situation(alert)
        self.assertEqual(pro.situation[0].type, 'ALERT')
        self.assertEqual(pro.situation[0].msg, 'HELP')
        pro.handle_cancel('HELP')
        self.assertEqual(pro.situation, [])
        pro.handle_cancel('ANOTHER HELP')
        #Testing if program can store the cancel instruction
        self.assertEqual(pro.situation[0].type, 'CANCEL')
        self.assertEqual(pro.situation[0].msg, 'ANOTHER HELP')
    def test_File(self):
        b = read_instructions_from_file('ABC')
        self.assertEqual(str(b), "[Errno 2] No such file or directory: 'ABC'")

    def test_creation_devices(self):
        """Testing the device created successfully"""
        text_input=[
            'DEVICE 1',
            'DEVICE 22'
        ]
        out = project1.create_device(text_input)
        self.assertEqual(2, out[-1])
        self.assertEqual(1, out[0][0]._id)
        self.assertEqual(22, out[0][1]._id)

    def test_propagate(self):
        """Testing for receiving propagate"""
        device_1 = project1.Device(1)
        can = project1.Situation('CANCEL', 'HELP')
        device_1.add_situation(can)
        device_input = [project1.Device(2), device_1]
        time_input = 10
        temp_input = [project1.Propagate(10, [can], 1, 2)]
        try:
            out,b = project1.check_if_propagate(temp_input, time_input, device_input)
            self.assertEqual(out[0].situation[0].msg, 'HELP')
            self.assertEqual(out[0].situation[0].type, 'CANCEL')
        except SystemExit:
            pass

    def test_only_one(self):
        to_do_input = ['ALERT 1 ABC 100']
        device_1 = project1.Device(1)
        out = project1.only_one_instruction(to_do_input, [device_1])
        situation_out = out[0].situation[0]
        self.assertEqual(out[0].situation[0].msg, 'ABC')
        self.assertEqual(out[0].situation[0].type, 'ALERT')
        to_do_input = ['CANCEL 1 ABC 100']
        device_1 = project1.Device(1)
        out = project1.only_one_instruction(to_do_input, [device_1])
        situation_out = out[0].situation[0]
        self.assertEqual(out[0].situation[0].msg, 'ABC')
        self.assertEqual(out[0].situation[0].type, 'CANCEL')

    def test_single_alert_time(self):
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'ALERT 1 Trouble 200',
        ]
        a, b = create_device(text_input)
        with self.assertRaises(SystemExit) as c:
            project1.running_program(text_input, a, b)
        self.assertEqual(c.exception.code, None)

    def test_two_alerts(self):
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'ALERT 1 Trouble 200',
            'ALERT 2 AnotherOne 200',
        ]
        a,b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[0].situation[0].type, 'ALERT')
            self.assertEqual(a[0].situation[0].msg, 'Trouble')
            self.assertEqual(a[1].situation[0].type, 'ALERT')
            self.assertEqual(a[1].situation[0].msg, 'AnotherOne')

    def test_two_alerts_greater(self):
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'ALERT 2 Trouble 200',
            'ALERT 1 AnotherOne 200',
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[0].situation[0].type, 'ALERT')
            self.assertEqual(a[0].situation[0].msg, 'AnotherOne')
            self.assertEqual(a[1].situation[0].type, 'ALERT')
            self.assertEqual(a[1].situation[0].msg, 'Trouble')

    def test_two_same(self):
        text_input = ['DEVICE 8']
        inst_input = ['ALERT 8 ABC 10', 'CANCEL 8 NC 10']
        a, b = create_device(text_input)
        de_li = project1.two_at_same_time(inst_input, a, True)
        self.assertEqual(de_li[0].situation[0].type, 'CANCEL')
        self.assertEqual(de_li[0].situation[1].type, 'ALERT')
        text_input = ['DEVICE 8']
        inst_input = ['ALERT 8 NC 10', 'CANCEL 8 NC 10']
        a, b = create_device(text_input)
        de_li = project1.two_at_same_time(inst_input, a, True)
        self.assertEqual(de_li[0].situation, [])

    def test_two_at_same_time_differnt_cotnent(self):
        text_input = ['DEVICE 8', 'DEVICE 10']
        a, b = create_device(text_input)
        inst_input = ['ALERT 8 ABC 10', 'CANCEL 10 NC 10']
        de_li = project1.two_at_same_time(inst_input, a, False)
        a, b = create_device(text_input)
        self.assertEqual(de_li[0].situation[0].msg, 'ABC')
        self.assertEqual(de_li[1].situation[0].msg, 'NC')
        self.assertEqual(de_li[0].situation[0].type, 'ALERT')
        self.assertEqual(de_li[1].situation[0].type, 'CANCEL')
        inst_input = ['CANCEL 10 NC 10', 'ALERT 8 ABC 10']
        de_li = project1.two_at_same_time(inst_input, a, True)
        self.assertEqual(de_li[0].situation[0].msg, 'ABC')

    def test_running(self):
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'ALERT 1 Trouble 200',
            'ALERT 2 AnotherOne 500',
            'CANCEL 2 AnotherOne 600'
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit as e:
            self.assertEqual(a[1].situation,[])

    def test_running_same_device_same_msg(self):
        text_input = [
            'DEVICE 2',
            'ALERT 2 AnotherOne 500',
            'CANCEL 2 AnotherOne 500'
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[0].situation, [])

    def test_running_diff_device_same_time(self):
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'ALERT 1 Trouble 200',
            'ALERT 2 AnotherOne 200'
        ]
        # Two alerts first smaller
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[0].situation[0].msg, 'Trouble')
            self.assertEqual(a[1].situation[0].msg, 'AnotherOne')
    def test_same_time_first_greater(self):
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'ALERT 2 Trouble 200',
            'ALERT 1 AnotherOne 200'
        ]
        # Two Alerts first greater
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[0].situation[0].msg, 'AnotherOne')
            self.assertEqual(a[1].situation[0].msg, 'Trouble')
    def test_same_device_alerts(self):
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'ALERT 1 Trouble 200',
            'ALERT 1 AnotherOne 200',
            'CANCEL 2 AnotherOne 400',
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[1].situation[0].type, 'CANCEL')
    def test_two_cancel_dif_device(self):
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'CANCEL 1 Trouble 200',
            'CANCEL 2 AnotherOne 200',
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[0].situation[0].msg, 'Trouble')
            self.assertEqual(a[1].situation[0].msg, 'AnotherOne')
    def test_same_device_first_greater(self):
        text_input = [
            'DEVICE 1',
            'CANCEL 1 BAJFIOQEO 200',
            'CANCEL 1 A 200',
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[0].situation[0].msg, 'A')

    def test_running_propagate(self):
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'ALERT 1 Trouble 200',
            'PROPAGATE 1 2 500'
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[1].situation[0].msg, 'Trouble')

    def test_propagate_alert(self):
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'ALERT 1 Trouble 200',
            'PROPAGATE 1 2 500'
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[1].situation[0].msg, 'Trouble')

    def test_propagate_cancel(self):
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'CANCEL 1 Trouble 200',
            'PROPAGATE 1 2 500'
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[1].situation[0].msg, 'Trouble')

    def test_two_cancel_dif(self):
        text_input = [
            'DEVICE 1',
            'CANCEL 1 A 200',
            'CANCEL 1 AoooA 200'
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[0].situation[0].msg, 'A')
            self.assertEqual(a[0].situation[1].msg, 'AoooA')

    def test_cancel_alert(self):
        text_input = [
            'DEVICE 1',
            'CANCEL 1 First 200',
            'ALERT 1 Second 200'
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[0].situation[0].msg, 'First')
            self.assertEqual(a[0].situation[1].msg, 'Second')
    def test_two_alerts_same_time(self):
        text_input = [
            'DEVICE 1',
            'ALERT 1 First 200',
            'ALERT 1 Second 200'
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[0].situation[0].msg, 'First')
            self.assertEqual(a[0].situation[1].msg, 'Second')

    def test_string_out(self):
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'ALERT 1 Random 100',
            'PROPAGATE 1 2 Random 10',
            'CANCEL 1 Random 20'
        ]
        a, b = create_device(text_input)
        try:
            project1.running_program(text_input, a, b)
        except SystemExit:
            self.assertEqual(a[1].situation[0].msg, 'Random')
            self.assertEqual(a[0].situation, [])

    def test_standard_output(self):
        f = io.StringIO()
        text_input = [
            'DEVICE 1',
            'DEVICE 2',
            'ALERT 1 AnAlert 10',
            'PROPAGATE 1 2 AnAlert 10'
        ]
        a, b = create_device(text_input)
        with redirect_stdout(f):
            try:
                project1.running_program(text_input, a, b)
            except SystemExit:
                pass
        output = f.getvalue()
        self.assertEqual(output, '@11 #1: SENT ALERT TO #2: AnAlert\n@21 #2: RECEIVED ALERT FROM #1: AnAlert\n')

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


# Si el MCD(a,b) = 1 si y solo si existen enteros m,n tales que
# 1 = ma +nb, haz un script en python para encontrar m y n

def MCD(a, b):
    while b != 0:
        a, b = b, a % b
    return a

def encontrar_mn(a, b):
    if MCD(a, b) != 1:
        return None, None
    else:
        x, y = Euclides(a, b)
        return x, y

def Euclides(a, b):
    if b == 0:
        return 1, 0
    else:
        x, y = Euclides(b, a % b)
        return y, x - y * (a // b)

a = [2, 2, 2]
b = [3, 7, 0]
for i in range(0, len(a)):
    m, n = encontrar_mn(a[i], b[i])
    print(f"m = {m}, n = {n}")
    print(f"1 = {a[i]} * {m} + {b[i]} * {n}\n")


from math import sqrt
def prime():
    yield 2
    i = 3
    while True:
        has_div = False
        for d in range(2, int(sqrt(i)) + 1):
            if i % d == 0:
                has_div = True
                break
        if not has_div:
            yield i
        i += 2

n = int(input("n = "))

for i, v in enumerate(prime()):
    print (v)
    if i == n - 1:
        break


import numpy as np
from dislib.data.array import Array

from pycompss.api.api import compss_wait_on

try:
    import cbor2
except ImportError:
    cbor2 = None

def encoder_helper(obj):
    if isinstance(obj, np.generic):
        return obj.item()
    elif isinstance(obj, np.ndarray):
        return {
            "class_name": "ndarray",
            "dtype_list": len(obj.dtype.descr) > 1,
            "dtype": str(obj.dtype),
            "items": obj.tolist(),
        }
    elif isinstance(obj, Array):
        return {"class_name": "dsarray", **obj.__dict__}
    elif isinstance(obj, np.random.RandomState):
        return {"class_name": "RandomState", "items": obj.get_state()}
    return None

def decoder_helper(class_name, obj):
    if class_name == "ndarray":
        if obj["dtype_list"]:
            items = list(map(tuple, obj["items"]))
            return np.rec.fromrecords(items, dtype=eval(obj["dtype"]))
        else:
            return np.array(obj["items"], dtype=obj["dtype"])
    elif class_name == "dsarray":
        return Array(
            blocks=obj["_blocks"],
            top_left_shape=obj["_top_left_shape"],
            reg_shape=obj["_reg_shape"],
            shape=obj["_shape"],
            sparse=obj["_sparse"],
            delete=obj["_delete"],
        )
    return None

def sync_obj(obj):
    """Recursively synchronizes the Future objects of a list or dictionary
    by using `compss_wait_on(obj)`.
        """
    if isinstance(obj, dict):
        iterator = iter(obj.items())
    elif isinstance(obj, list):
        iterator = iter(enumerate(obj))
    else:
        raise TypeError("Expected dict or list and received %s." % type(obj))

    for key, val in iterator:
        if isinstance(val, (dict, list)):
            sync_obj(obj[key])
        else:
            obj[key] = compss_wait_on(val)
            if isinstance(getattr(obj[key], "__dict__", None), dict):
                sync_obj(obj[key].__dict__)


import logging
logger = logging.getLogger(__name__)
import sys
import os
import json
import requests
from requests.exceptions import Timeout, ReadTimeout, ConnectionError
import time
import threading
import concurrent.futures
import collections
import binascii
import hashlib

from dogepartylib.lib import config, script, util

raw_transactions_cache = util.DictCache(size=config.BACKEND_RAW_TRANSACTIONS_CACHE_SIZE) #used in getrawtransaction_batch()
unconfirmed_transactions_cache = None

class BackendRPCError(Exception):
    pass

def rpc_call(payload):
    url = config.BACKEND_URL
    response = None
    TRIES = 12

    for i in range(TRIES):
        try:
            response = requests.post(url, data=json.dumps(payload), headers={'content-type': 'application/json'},
                verify=(not config.BACKEND_SSL_NO_VERIFY), timeout=config.REQUESTS_TIMEOUT)
            if i > 0:
                logger.debug('Successfully connected.')
            break
        except (Timeout, ReadTimeout, ConnectionError):
            logger.debug('Could not connect to backend at `{}`. (Try {}/{})'.format(url, i+1, TRIES))
            time.sleep(5)

    if response == None:
        if config.TESTNET:
            network = 'testnet'
        else:
            network = 'mainnet'
        raise BackendRPCError('Cannot communicate with backend at `{}`. (server is set to run on {}, is backend?)'.format(url, network))
    elif response.status_code not in (200, 500):
        raise BackendRPCError(str(response.status_code) + ' ' + response.reason)

    # Return result, with error handling.
    response_json = response.json()
    # Batch query returns a list
    if isinstance(response_json, list):
        return response_json
    if 'error' not in response_json.keys() or response_json['error'] == None:
        return response_json['result']
    elif response_json['error']['code'] == -5:   # RPC_INVALID_ADDRESS_OR_KEY
        raise BackendRPCError('{} Is `txindex` enabled in {} Core?'.format(response_json['error'], config.BTC_NAME))
    elif response_json['error']['code'] in [-28, -8, -2]:
        # “Verifying blocks...” or “Block height out of range” or “The network does not appear to fully agree!“
        logger.debug('Backend not ready. Sleeping for ten seconds.')
        # If Bitcoin Core takes more than `sys.getrecursionlimit() * 10 = 9970`
        # seconds to start, this’ll hit the maximum recursion depth limit.
        time.sleep(10)
        return rpc_call(payload)
    else:
        raise BackendRPCError('{}'.format(response_json['error']))

def rpc(method, params):
    payload = {
        "method": method,
        "params": params,
        "jsonrpc": "2.0",
        "id": 0,
    }
    return rpc_call(payload)

def rpc_batch(request_list):
    responses = collections.deque()

    def make_call(chunk):
        #send a list of requests to bitcoind to be executed
        #note that this is list executed serially, in the same thread in bitcoind
        #e.g. see: https://github.com/bitcoin/bitcoin/blob/master/src/rpcserver.cpp#L939
        responses.extend(rpc_call(chunk))

    chunks = util.chunkify(request_list, config.RPC_BATCH_SIZE)
    with concurrent.futures.ThreadPoolExecutor(max_workers=config.BACKEND_RPC_BATCH_NUM_WORKERS) as executor:
        for chunk in chunks:
            executor.submit(make_call, chunk)
    return list(responses)

def extract_addresses(txhash_list):
    tx_hashes_tx = getrawtransaction_batch(txhash_list, verbose=True)
    tx_hashes_addresses = {}
    tx_inputs_hashes = set() #use set to avoid duplicates

    for tx_hash, tx in tx_hashes_tx.items():
        tx_hashes_addresses[tx_hash] = set()
        for vout in tx['vout']:
            if 'addresses' in vout['scriptPubKey']:
                tx_hashes_addresses[tx_hash].update(tuple(vout['scriptPubKey']['addresses']))
        tx_inputs_hashes.update([vin['txid'] for vin in tx['vin']])

    raw_transactions = getrawtransaction_batch(list(tx_inputs_hashes), verbose=True)
    for tx_hash, tx in tx_hashes_tx.items():
        for vin in tx['vin']:
            vin_tx = raw_transactions[vin['txid']]
            if vin_tx is None: #bogus transaction
                continue
            vout = vin_tx['vout'][vin['vout']]
            if 'addresses' in vout['scriptPubKey']:
                tx_hashes_addresses[tx_hash].update(tuple(vout['scriptPubKey']['addresses']))

    return tx_hashes_addresses, tx_hashes_tx

def unconfirmed_transactions(address):
    logger.debug("unconfirmed_transactions called: %s" % address)
    if unconfirmed_transactions_cache is None:
        raise Exception("Unconfirmed transactions cache is not initialized")
    return unconfirmed_transactions_cache.get(address, [])

def refresh_unconfirmed_transactions_cache(mempool_txhash_list):
    # NOTE: This operation can be very slow.
    global unconfirmed_transactions_cache

    unconfirmed_txes = {}
    tx_hashes_addresses, tx_hashes_tx = extract_addresses(mempool_txhash_list)
    for tx_hash, addresses in tx_hashes_addresses.items():
        for address in addresses:
            if address not in unconfirmed_txes:
                unconfirmed_txes[address] = []
            unconfirmed_txes[address].append(tx_hashes_tx[tx_hash])
    unconfirmed_transactions_cache = unconfirmed_txes
    logger.debug('Unconfirmed transactions cache refreshed ({} entries, from {} supported mempool txes)'.format(
        len(unconfirmed_transactions_cache), len(mempool_txhash_list)))

def searchrawtransactions(address, unconfirmed=False):
    # Get unconfirmed transactions.
    if unconfirmed:
        logger.debug('searchrawtransactions: Getting unconfirmed transactions.')
        unconfirmed = unconfirmed_transactions(address)
    else:
        unconfirmed = []

    # Get confirmed transactions.
    try:
        logger.debug('Searching raw transactions.')
        rawtransactions = rpc('searchrawtransactions', [address, 1, 0, 9999999])
    except BackendRPCError as e:
        if str(e) == '404 Not Found':
            raise BackendRPCError('Unknown RPC command: `searchrawtransactions`. Please use a version of {} Core which supports an address index.'.format(config.BTC_NAME))
        else:
            raise BackendRPCError(str(e))
    confirmed = [tx for tx in rawtransactions if 'confirmations' in tx and tx['confirmations'] > 0]

    return unconfirmed + confirmed

def getblockcount():
    return rpc('getblockcount', [])

def getblockhash(blockcount):
    return rpc('getblockhash', [blockcount])

def getblock(block_hash):
    return rpc('getblock', [block_hash, False])

def getrawtransaction(tx_hash, verbose=False):
    return getrawtransaction_batch([tx_hash], verbose=verbose)[tx_hash]

def getrawmempool():
    return rpc('getrawmempool', [])

def sendrawtransaction(tx_hex):
    return rpc('sendrawtransaction', [tx_hex])

def getrawtransaction_batch(txhash_list, verbose=False, _recursing=False):
    if len(txhash_list) > config.BACKEND_RAW_TRANSACTIONS_CACHE_SIZE:
        #don't try to load in more than BACKEND_RAW_TRANSACTIONS_CACHE_SIZE entries in a single call
        txhash_list_chunks = util.chunkify(txhash_list, config.BACKEND_RAW_TRANSACTIONS_CACHE_SIZE)
        txes = {}
        for txhash_list_chunk in txhash_list_chunks:
            txes.update(getrawtransaction_batch(txhash_list_chunk, verbose=verbose))
        return txes

    tx_hash_call_id = {}
    payload = []
    noncached_txhashes = set()

    txhash_list = set(txhash_list)

    # payload for transactions not in cache
    for tx_hash in txhash_list:
        if tx_hash not in raw_transactions_cache:
            call_id = binascii.hexlify(os.urandom(5)).decode('utf8')
            payload.append({
                "method": 'getrawtransaction',
                "params": [tx_hash, 1],
                "jsonrpc": "2.0",
                "id": call_id
            })
            noncached_txhashes.add(tx_hash)
            tx_hash_call_id[call_id] = tx_hash
    #refresh any/all cache entries that already exist in the cache,
    # so they're not inadvertently removed by another thread before we can consult them
    #(this assumes that the size of the working set for any given workload doesn't exceed the max size of the cache)
    for tx_hash in txhash_list.difference(noncached_txhashes):
        raw_transactions_cache.refresh(tx_hash)

    logger.debug("getrawtransaction_batch: txhash_list size: {} / raw_transactions_cache size: {} / # getrawtransaction calls: {}".format(
        len(txhash_list), len(raw_transactions_cache), len(payload)))

    # populate cache
    added_entries_to_cache = []
    if len(payload) > 0:
        batch_responses = rpc_batch(payload)
        for response in batch_responses:
            if 'error' not in response or response['error'] is None:
                tx_hex = response['result']
                tx_hash = tx_hash_call_id[response['id']]
                raw_transactions_cache[tx_hash] = tx_hex
                added_entries_to_cache.append(tx_hash) #for debugging
            else:
                #TODO: this seems to happen for bogus transactions? Maybe handle it more gracefully than just erroring out?
                raise BackendRPCError('{} (txhash:: {})'.format(response['error'], tx_hash_call_id.get(response.get('id', '??'), '??')))

    # get transactions from cache
    result = {}
    for tx_hash in txhash_list:
        try:
            if verbose:
                result[tx_hash] = raw_transactions_cache[tx_hash]
            else:
                result[tx_hash] = raw_transactions_cache[tx_hash]['hex']
        except KeyError: #shows up most likely due to finickyness with addrindex not always returning results that we need...
            logger.debug("tx missing in rawtx cache: {} -- txhash_list size: {}, hash: {} / raw_transactions_cache size: {} / # rpc_batch calls: {} / txhash in noncached_txhashes: {} / txhash in txhash_list: {} -- list {}".format(
                e, len(txhash_list), hashlib.md5(json.dumps(list(txhash_list)).encode()).hexdigest(), len(raw_transactions_cache), len(payload),
                tx_hash in noncached_txhashes, tx_hash in txhash_list, list(txhash_list.difference(noncached_txhashes)) ))
            if not _recursing: #try again
                r = getrawtransaction_batch([tx_hash], verbose=verbose, _recursing=True)
                result[tx_hash] = r[tx_hash]
            else:
                raise #already tried again, give up

    return result

# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4


# https://leetcode.com/problems/maximum-depth-of-binary-tree/
# runtime beats 78.83%
# memory usage beats 11.11%

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def measure_depth(self, tree):
        rc = 0
        lc = 0
        if tree.right:
            rc += 1
            rc += self.measure_depth(tree.right)
        if tree.left:
            lc += 1
            lc += self.measure_depth(tree.left)
        return max(rc, lc)

    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        return self.measure_depth(root) + 1


"""
Handles all thing config
"""

from discord.commands import slash_command
from discord.ext import commands
import discord
import guildreader

def isauthor(author):
    """Makes sure they're the command invoker"""
    def check(message) -> bool:
        return message.author == author
    return check

class Config(discord.ext.commands.Cog):
    """
    Guild-Specific Config
    """
    def __init__(self, bot):
        self.bot = bot

    async def on_slash_command_error(self, ctx, error):
        if isinstance(error, discord.ext.commands.errors.MissingPermissions):
            return await ctx.respond(error.message)

    @slash_command()
    @commands.has_permissions(administrator=True)
    async def djmode(self, ctx, djrole: discord.Role = None):
        """
        Limits playback modification to people with specified role

            Parameters:
                ctx (commands.Context): Context Reference
                djrole (discord.Role): Role to enable for
        """
        if djrole is None:
            self.bot.reader.write_file(ctx.guild.id, 'djmode', djrole)
            return await ctx.respond('Disabling DJ-Mode')

        self.bot.reader.write_file(ctx.guild.id, 'djmode', str(djrole.id))
        await ctx.respond(f'Enabling DJ-Config for role: {djrole.name}')

    @slash_command()
    @commands.has_permissions(administrator=True)
    async def errors(self, ctx):
        """
        Shows or unshows commands not found error

            Parameters:
                ctx (commands.Context): Context Reference
        """
        toggle = self.bot.reader.read_file(ctx.guild.id, 'settings')
        toggle['errors'] = not toggle['errors']
        self.bot.reader.write_file(ctx.guild.id, 'settings', toggle)
        if not toggle:
            return await ctx.respond("Disabling showing of command not found")
        return await ctx.respond("Enabling showing of command not found")

    @slash_command()
    @commands.has_permissions(administrator=True)
    async def addword(self, ctx, word: str):
        """
        Add tracked words

            Parameters:
                ctx (commands.Context): Context Reference
                word (string): Word to track
        """
        wordjson: dict = self.bot.reader.read_file(ctx.guild.id, 'wordcount')
        try:
            wordjson[word]
            return await ctx.respond(f'{word} is already tracked')
        except KeyError:
            wordjson.setdefault(word, {})
            self.bot.reader.write_file(ctx.guild.id, "wordcount", wordjson)
            return await ctx.respond(f'Added {word} to tracked word list')

    @slash_command()
    @commands.has_permissions(administrator=True)
    async def removeword(self, ctx, word: str):
        """
        remove tracked words

            Parameters:
                ctx (commands.Context): Context Reference
                word (string): Word to track
        """
        wordjson: dict = self.bot.reader.read_file(ctx.guild.id, 'wordcount')
        try:
            del wordjson[word]
            self.bot.reader.write_file(ctx.guild.id, "wordcount", wordjson)
            return await ctx.respond(f'Removed {word} from tracking')
        except KeyError:
            return await ctx.respond(f'{word} isnt tracked')

def setup(bot):
    """
    Add Config Cog
    """
    bot.add_cog(Config(bot))


#!/usr/bin/python3
'''
This started out life as a practical example of setting up an AWS SSM Automation task, but this doesn't do that anymore.
Convert all GP2 volumes to GP3 volumes
'''

import boto3
from botocore.exceptions import ClientError

def tags_to_dict(resource):
    '''Convert the Tags structure into a python dict - because I'm lazy'''

    ObjTags = {}
    try:
        for tag_key in resource['Tags']:
            ObjTags[tag_key['Key']] = tag_key['Value']
    except:
        pass

    return ObjTags

def get_gp2_volumes():
    '''Get a list of all of the GP2 volumes'''

    client = boto3.client('ec2')
    response = client.describe_volumes(
    Filters=[
        {
            'Name': 'volume-type',
            'Values': [
                'gp2',
            ]
        },
    ])

    return response

def gp2_to_gp3(volumes):
    '''Convert the list of GP2 volumes to GP3'''

    results = []

    client = boto3.client('ec2')
    for volume in volumes['Volumes']:
        try:
            response = client.modify_volume(
                DryRun=True,
                VolumeId=volume['VolumeId'],
                VolumeType='gp3')
            results['succeeded'].append("{} {}".format(volume['VolumeId'], tags_to_dict(volume['Tags']).get('Name', volume['VolumeId'])))
        except BaseException as e:
            results['failed'].append("{} {}: {}".format(volume['VolumeId'], tags_to_dict(volume['Tags']).get('Name', volume['VolumeId']), e.message))
            continue

    return results

def display_results(results):
    '''Show me how the converions went'''
    for status in results:
        print("Volume conversions {}".status)
        for volume in status:
            print(volume)

def main():
    volumes = get_gp2_volumes()
    conv_results = gp2_to_gp3(volumes)
    display_results(conv_results)

if __name__ == '__main__':
    main()


def solution():
    n = int(input())
    num = [list(map(int, input().split())) for _ in range(2)]
    dp = [[0]*(n+1) for _ in range(2)]

    dp[0][1], dp[1][1] = num[0][0], num[1][0]

    for j in range(2, n+1):
        for i in range(2):
            dp[i][j] = max(dp[i-1][j-1], dp[i][j-2], dp[i-1][j-2])+num[i][j-1]

    return max(dp[0]+dp[1])

t = int(input())
for i in range(t):
    print(solution())


from __future__ import annotations

# TODO: RF and move all paths related functions from datalad.utils in here
import os
import os.path as op
# to not pollute API importing as _
from collections import defaultdict as _defaultdict
from collections.abc import (
    Iterable,
    Iterator,
)
from functools import wraps
from itertools import dropwhile
from pathlib import (
    Path,
    PurePosixPath,
)

from ..utils import (
    ensure_bytes,
    getpwd,
)

def _get_unicode_robust_version(f):

    @wraps(f)
    def wrapped(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except UnicodeEncodeError:
            return f(ensure_bytes(*args, **kwargs))
    doc = getattr(f, '__doc__', None)
    # adjust only if __doc__ is not completely absent (None)
    if doc is not None:
        wrapped.__doc__ = doc + \
            "\n\nThis wrapper around original function would encode forcefully " \
            "to utf-8 if initial invocation fails"
    return wrapped

abspath = op.abspath
basename = op.basename
curdir = op.curdir
dirname = op.dirname
exists = _get_unicode_robust_version(op.exists)
isdir = _get_unicode_robust_version(op.isdir)
isabs = _get_unicode_robust_version(op.isabs)
join = op.join
lexists = _get_unicode_robust_version(op.lexists)
normpath = op.normpath
pardir = op.pardir
pathsep = op.pathsep
relpath = op.relpath
realpath = _get_unicode_robust_version(op.realpath)
sep = op.sep

def robust_abspath(p: str | Path) -> str:
    """A helper which would not fail if p is relative and we are in non-existing directory

    It will rely on getpwd, which would rely on $PWD env variable to report
    the path.  Desired for improved resilience during e.g. reporting as in
    https://github.com/datalad/datalad/issues/2787
    """
    try:
        return abspath(p)
    except OSError:
        if not isabs(p):
            try:
                os.getcwd()
            except Exception:
                return normpath(join(getpwd(), p))
        # if no exception raised it was not the reason, raise original
        raise

def split_ext(filename: str) -> tuple[str, str]:
    """Use git-annex's splitShortExtensions rule for splitting extensions.

    Parameters
    ----------
    filename : str

    Returns
    -------
    A tuple with (root, extension)

    Examples
    --------
    >>> from datalad.local.addurls import split_ext
    >>> split_ext("filename.py")
    ('filename', '.py')

    >>> split_ext("filename.tar.gz")
    ('filename', '.tar.gz')

    >>> split_ext("filename.above4chars.ext")
    ('filename.above4chars', '.ext')
    """
    parts = filename.split(".")
    if len(parts) == 1:
        return filename, ""

    tail = list(dropwhile(lambda x: len(x) < 5,
                          reversed(parts[1:])))

    file_parts = parts[:1] + tail[::-1]
    ext_parts = parts[1+len(tail):]
    return ".".join(file_parts), "." + ".".join(ext_parts)

def get_parent_paths(paths: list[str], parents: list[str], only_with_parents: bool = False, *, sep: str = '/') -> list[str]:
    """Given a list of children paths, return their parent paths among parents
    or their own path if there is no known parent. A path is also considered its
    own parent (haven't you watched Predestination?) ;)

    All paths should be relative, not pointing outside (not starting
    with ../), and normalized (no // or dir/../dir and alike). Only minimal
    sanity checking of values is done.  By default paths are considered to be
    POSIX. Use 'sep' kwarg to set to `os.sep` to provide OS specific handling.

    Accent is made on performance to avoid O(len(paths) * len(parents))
    runtime.  ATM should be typically less than O(len(paths) * len(log(parents)))

    Initial intended use - for a list of paths in the repository
    to provide their paths as files/submodules known to that repository, to
    overcome difference in ls-tree and ls-files, where ls-files outputs nothing
    for paths within submodules.
    It is coded, so it could later be applied even whenever there are nested
    parents, e.g. parents = ['sub', 'sub/sub'] and then the "deepest" parent
    is selected

    Parameters
    ----------
    parents: list of str
    paths: list of str
    only_with_parents: bool, optional
      If set to True, return a list of only parent paths where that path had
      a parent
    sep: str, optional
      Path separator.  By default - '/' and thus treating paths as POSIX.
      If you are processing OS-specific paths (for both `parents` and `paths`),
      specify `sep=os.sep`.

    Returns
    -------
    A list of paths (without duplicates), where some entries replaced with
    their "parents" without duplicates.  So for 'a/b' and 'a/c' with a being
    among parents, there will be a single 'a'
    """
    # Let's do an early check even though then we would skip the checks on paths
    # being relative etc
    if not parents:
        return [] if only_with_parents else paths

    # We will create a lookup for known parent lengths
    parent_set = set(parents)  # O(log(len(parents))) lookup

    # Will be used in sanity checking that we got consistently used separators, i.e.
    # not mixing non-POSIX paths and POSIX parents
    asep = {'/': '\\', '\\': '/'}[sep]

    # rely on path[:n] be quick, and len(parent_lengths) << len(parent_set)
    # when len(parent_set) is large.  We will also bail checking any parent of
    # the length if at that length path has no directory boundary ('/').
    #
    # Create mapping for each length of
    # parent path to list of parents with that length
    parent_lengths_map: dict[int, set[str]] = _defaultdict(set)
    for parent in parent_set:
        _get_parent_paths_check(parent, sep, asep)
        parent_lengths_map[len(parent)].add(parent)

    # Make it ordered in the descending order so we select the deepest/longest parent
    # and store them as sets for faster lookup.
    # Could be an ordered dict but no need
    parent_lengths = [(l, parent_lengths_map[l]) for l in sorted(parent_lengths_map, reverse=True)]

    res = []
    seen = set()

    for path in paths:  # O(len(paths)) - unavoidable but could be parallelized!
        # Sanity check -- should not be too expensive
        _get_parent_paths_check(path, sep, asep)
        for parent_length, parents_ in parent_lengths:  # O(len(parent_lengths))
            if (len(path) < parent_length) or (len(path) > parent_length and path[parent_length] != sep):
                continue  # no directory deep enough
            candidate_parent = path[:parent_length]
            if candidate_parent in parents_:  # O(log(len(parent_set))) but expected one less due to per length handling
                if candidate_parent not in seen:
                    res.append(candidate_parent)
                    seen.add(candidate_parent)
                break  # it is!
        else:  # no hits
            if not only_with_parents:
                if path not in seen:
                    res.append(path)
                    seen.add(path)

    return res

def get_filtered_paths_(paths: Iterable[str|Path], filter_paths: Iterable[str | Path],
                        *, include_within_path: bool = False) \
        -> Iterator[str]:
    """Among paths (or Path objects) select the ones within filter_paths.

    All `paths` and `filter_paths` must be relative and POSIX.

    In case of `include_with_path=True`, if a `filter_path` points to some path
    under a `path` within `paths`, that path would be returned as well, e.g.
    `path` 'submod' would be returned if there is a `filter_path` 'submod/subsub/file'.

    Complexity is O(N*log(N)), where N is the largest of the lengths of `paths`
    or `filter_paths`.

    Yields
    ------
    paths, sorted (so order is not preserved), which reside under 'filter_paths' or
    path within 'filter_paths' is under that path.
    """
    # do conversion and sanity checks, O(N)
    def _harmonize_paths(l: Iterable[str | Path]) -> list[tuple[str, ...]]:
        ps = []
        for p in l:
            pp = PurePosixPath(p)
            if pp.is_absolute():
                raise ValueError(f"Got absolute path {p}, expected relative")
            if pp.parts and pp.parts[0] == '..':
                raise ValueError(f"Path {p} leads outside")
            ps.append(pp.parts)  # store parts
        return sorted(ps)  # O(N * log(N))

    paths_parts = _harmonize_paths(paths)
    filter_paths_parts = _harmonize_paths(filter_paths)

    # we will pretty much "scroll" through sorted paths and filter_paths at the same time
    for path_parts in paths_parts:
        while filter_paths_parts:
            filter_path_parts = filter_paths_parts[0]
            l = min(len(path_parts), len(filter_path_parts))
            # if common part is "greater" in the path -- we can go to the next "filter"
            if filter_path_parts[:l] < path_parts[:l]:
                # get to the next one
                filter_paths_parts = filter_paths_parts[1:]
            else:
                break  # otherwise -- consider this one!
        else:
            # no filter path left - the other paths cannot be the selected ones
            break
        if include_within_path:
            # if one identical or subpath of another one -- their parts match in the beginning
            # and we will just reuse that 'l'
            pass
        else:
            # if all components of the filter match, for that we also add len(path_parts) check below
            l = len(filter_path_parts)
        if len(path_parts) >= l and (path_parts[:l] == filter_path_parts[:l]):
            yield '/'.join(path_parts)

def _get_parent_paths_check(path: str, sep: str, asep: str) -> None:
    """A little helper for get_parent_paths"""
    if isabs(path) or path.startswith(pardir + sep) or path.startswith(curdir + sep):
        raise ValueError("Expected relative within directory paths, got %r" % path)
    if sep+sep in path:
        raise ValueError(f"Expected normalized paths, got {path} containing '{sep+sep}'")
    if asep in path:
        raise ValueError(f"Expected paths with {sep} as separator, got {path} containing '{asep}'")


import os
import platform

import logging

logging.basicConfig(level=os.getenv("LOG_LEVEL", logging.INFO))
LOGGER = logging.getLogger(__name__)

def get_genesis_path():
    if platform.system() == "Windows":
        txn_path = os.path.realpath("./genesis")
    else:
        txn_path = "/home/indy/genesis"
    txn_path = os.getenv("INDY_GENESIS_PATH", txn_path)
    return txn_path

def get_wallet_config(wallet_seed, wallet_id=None, access_creds=None, wallet_name="personal-agent-wallet"):
    return {
        "id": wallet_id,
        "name": wallet_name,
        "seed": wallet_seed,
        "access_creds": access_creds,

    }


class Song:

    def __init__(self, title="", artist="", album="", requested = False):
        self.title = title
        self.artist = artist
        self.album = album
        self.ID = None

        #Number of total votes and total thumbsUp feedbacks
        self.votes = 0
        self.thumbsUp = 0

        self.isFuture = 0
        self.requested = requested
        self.requests = 0

    def __getitem__(self, key):

        if key == 0:
            return self.title
        elif key == 1:
            return self.artist
        elif key == 2 and not self.requested:
            return self.votes
        elif key == 2 and self.requested:
            return self.requests

    def __cmp__(self, other):

        if self.title == other.title and self.artist == other.artist:
            return 0
        else:
            return cmp(self.title, other.title)

    def upThumbsUp(self):
        self.thumbsUp +=1

    def upThumpsDown(self):
        self.thumbsUp -=1

    def upVote(self):
        self.votes +=1


# Задача 2. Даны два случайных пятизначных числа.
# Определить, состоят ли они из одних и тех же цифр.

def Check(num1, num2):
    num1 = str(num1)
    num2 = str(num2)
    num1 = set(num1)
    num2 = set(num2)
    return num1 == num2

num1 = int(input("Введите первое пятизначное число: "))
num2 = int(input("Введите второе пятизначное число: "))
print(f"Ответ: {Check(num1, num2)}")


from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QSpacerItem, QSizePolicy, QPushButton, \
    QMessageBox, QGridLayout

#####################################################################
###   QUESTA CLASSE SERVE PER MOSTRARE ALL'UTENTE L'INTERFACCIA   ###
###            DI SCARICO DI UN ARTICOLO DEL MAGAZZINO            ###
#####################################################################
class Vista_scarico_articolo(QWidget):
    def __init__(self, controller, callback):
        super(Vista_scarico_articolo, self).__init__()

        self.controller = controller
        self.callback = callback
        self.info = {}
        self.labels = ["Codice a barre:", "Quantità da decrementare:"]

        self.v_layout = QVBoxLayout()
        self.grid_layout = QGridLayout()

        self.unload_item_view()

        self.v_layout.addLayout(self.grid_layout)

        self.v_layout.addItem(QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding))

        btn_ok = QPushButton("Scarica articolo")
        btn_ok.clicked.connect(self.unload_articolo)

        self.v_layout.addWidget(btn_ok)

        self.setLayout(self.v_layout)
        self.resize(400, 150)
        self.setFixedSize(self.size())
        self.setWindowTitle("Scarico articolo")

    ########################################################
    ###  METODO USATO PER MOSTRARE GLI ELEMENTI GRAFICI  ###
    ###      ALL'INTERNO DELL'INTERFACCIA DI SCARICO     ###
    ########################################################
    def unload_item_view(self):
        i=0
        for name in self.labels:
            self.grid_layout.addWidget(QLabel(name), i, 0)
            self.current_text_edit = QLineEdit(self)
            self.current_text_edit.returnPressed.connect(self.unload_articolo)
            self.grid_layout.addWidget(self.current_text_edit, i, 1)
            self.info[name] = self.current_text_edit
            i = i+1

    ################################################
    ###  METODO USATO PER AGGIUNGERE LO SCARICO  ###
    ###        DELL' ARTICOLO NEL SISTEMA        ###
    ################################################
    def unload_articolo(self):
        codice_immesso = self.info["Codice a barre:"].text()
        stock = self.info["Quantità da decrementare:"].text()

        if codice_immesso == "" or stock == "":
            QMessageBox.critical(self, 'Errore di compilazione!', 'Per favore, inserisci tutte le informazioni richieste.',
                                 QMessageBox.Ok, QMessageBox.Ok)
            return
        elif self.is_int(stock) and int(stock)>0:
            articolo_trovato = self.controller.scarico(codice_immesso, stock)
            if articolo_trovato == True:
                self.callback()
                self.close()
            else:
                QMessageBox.critical(self, 'Errore',
                                     'I dati inseriti sono errati!  \n Articolo non presente in anagrafica articolo oppure \n quantità richiesta non disponibile in magazzino.',
                                     QMessageBox.Ok, QMessageBox.Ok)
                return

        else:
            QMessageBox.critical(self, 'Errore',
                                 'Per favore, inserisci un valore numerico, intero e positivo per decrementare la quantità.',
                                 QMessageBox.Ok, QMessageBox.Ok)
            return

    ##########################################################
    ###           METODO USATO PER VERIFICARE SE           ###
    ###  UNA STRINGA PUÒ ESSERE CASTATA A VARIABILE FLOAT  ###
    ##########################################################
    def is_float(self, val):

        try:
            num = float(val)
        except ValueError:
            return False
        return True

    ##################################################
    ###       METODO USATO PER VERIFICARE SE       ###
    ###  UNA STRINGA PUÒ ESSERE CASTATA AD INTERO  ###
    ##################################################
    def is_int(self, val):
        try:
            num = int(val)
        except ValueError:
            return False
        return True


# File: X (Python 1.5)

import App
import BridgeUtils

def CreateMenus():
	pTopWindow = App.TopWindow_GetTopWindow()
	pTacticalControlWindow = App.TacticalControlWindow_GetTacticalControlWindow()
	LCARS = __import__(App.GraphicsModeInfo_GetCurrentMode().GetLcarsModule())
	pDatabase = App.g_kLocalizationManager.Load('data/TGL/Bridge Menus.tgl')
	pXOMenu = App.STTopLevelMenu_CreateW(pDatabase.GetString('Commander'))
	pXOPane = App.STStylizedWindow_CreateW('StylizedWindow', 'NoMinimize', pDatabase.GetString('Commander'), 0.0, 0.0)
	pXOPane.AddChild(pXOMenu, 0.0, 0.0, 0)
	pXOMenu.AddPythonFuncHandlerForInstance(App.ET_ST_BUTTON_CLICKED, 'Bridge.BridgeMenus.ButtonClicked')
	import BridgeMenus
	pCommunicate = BridgeMenus.CreateCommunicateButton('XO', pXOMenu)
	pXOMenu.AddChild(pCommunicate, 0.0, 0.0, 0)
	pReport = BridgeUtils.CreateBridgeMenuButton(pDatabase.GetString('Damage Report'), App.ET_REPORT, 0, pXOMenu)
	pXOMenu.AddChild(pReport, 0.0, 0.0, 0)
	pXOMenu.AddChild(BridgeUtils.CreateBridgeMenuButton(pDatabase.GetString('Green Alert'), App.ET_SET_ALERT_LEVEL, App.CharacterClass.EST_ALERT_GREEN, pXOMenu), 0.0, 0.0, 0)
	pXOMenu.AddChild(BridgeUtils.CreateBridgeMenuButton(pDatabase.GetString('Yellow Alert'), App.ET_SET_ALERT_LEVEL, App.CharacterClass.EST_ALERT_YELLOW, pXOMenu), 0.0, 0.0, 0)
	pXOMenu.AddChild(BridgeUtils.CreateBridgeMenuButton(pDatabase.GetString('Red Alert'), App.ET_SET_ALERT_LEVEL, App.CharacterClass.EST_ALERT_RED, pXOMenu), 0.0, 0.0, 0)
	pObjectives = App.STCharacterMenu_CreateW(pDatabase.GetString('Objectives'))
	pXOMenu.AddChild(pObjectives, 0.0, 0.0, 0)
	pShowLog = BridgeUtils.CreateBridgeMenuButton(pDatabase.GetString('Show Mission Log'), App.ET_SHOW_MISSION_LOG, 0, pXOMenu)
	pXOMenu.AddChild(pShowLog, 0.0, 0.0, 0)
	pContactStarfleet = BridgeUtils.CreateBridgeMenuButton(pDatabase.GetString('Contact Starfleet'), App.ET_CONTACT_STARFLEET, 0, pXOMenu)
	pXOMenu.AddChild(pContactStarfleet, 0.0, 0.0, 0)
	pContactEngineering = BridgeUtils.CreateBridgeMenuButton(pDatabase.GetString('Contact Engineering'), App.ET_CONTACT_ENGINEERING, 0, pXOMenu)
	pXOMenu.AddChild(pContactEngineering, 0.0, 0.0, 0)
	pContactEngineering.SetDisabled()
	if App.g_kUtopiaModule.IsMultiplayer():
		pReport.SetDisabled()
		pCommunicate.SetDisabled()
		pObjectives.SetDisabled()
		pShowLog.SetDisabled()
		pContactStarfleet.SetDisabled()
		pContactEngineering.SetDisabled()

	App.g_kLocalizationManager.Unload(pDatabase)
	pXOPane.SetNotVisible()
	pXOMenu.SetNotVisible()
	pXOMenu.SetNoSkipParent()
	pTacticalControlWindow.AddChild(pXOPane, 0.0, 0.0, 0)
	pTacticalControlWindow.AddMenuToList(pXOMenu)
	pXOMenu.AddPythonFuncHandlerForInstance(App.ET_SET_ALERT_LEVEL, __name__ + '.SetAlertLevel')
	pXOMenu.AddPythonFuncHandlerForInstance(App.ET_OBJECTIVES, __name__ + '.Objectives')
	pXOMenu.AddPythonFuncHandlerForInstance(App.ET_CONTACT_ENGINEERING, 'Bridge.EngineerCharacterHandlers.ContactEngineering')
	pXOMenu.AddPythonFuncHandlerForInstance(App.ET_COMMUNICATE, 'Bridge.Characters.CommonAnimations.NothingToAdd')
	pXOMenu.AddPythonFuncHandlerForInstance(App.ET_SHOW_MISSION_LOG, __name__ + '.ShowLog')
	return pXOMenu

def SetAlertLevel(pObject, pEvent):
	iType = pEvent.GetInt()
	pGame = App.Game_GetCurrentGame()
	pPlayer = App.ShipClass_Cast(pGame.GetPlayer())
	if App.IsNull(pPlayer):
		pObject.CallNextHandler(pEvent)
		return None

	iLevel = 0
	if iType == App.CharacterClass.EST_ALERT_GREEN:
		iLevel = pPlayer.GREEN_ALERT

	if iType == App.CharacterClass.EST_ALERT_YELLOW:
		iLevel = pPlayer.YELLOW_ALERT

	if iType == App.CharacterClass.EST_ALERT_RED:
		iLevel = pPlayer.RED_ALERT

	if iLevel != pPlayer.GetAlertLevel():
		if iType == App.CharacterClass.EST_ALERT_GREEN:
			App.TGSoundAction_Create('GreenAlertSound').Play()

		if iType == App.CharacterClass.EST_ALERT_YELLOW:
			App.TGSoundAction_Create('YellowAlertSound').Play()

		if iType == App.CharacterClass.EST_ALERT_RED:
			App.TGSoundAction_Create('RedAlertSound').Play()

		pAlertEvent = App.TGIntEvent_Create()
		pAlertEvent.SetSource(pObject)
		pAlertEvent.SetDestination(pPlayer)
		pAlertEvent.SetEventType(App.ET_SET_ALERT_LEVEL)
		pAlertEvent.SetInt(iLevel)
		App.g_kEventManager.AddEvent(pAlertEvent)

	pObject.CallNextHandler(pEvent)

def Objectives(pObject, pEvent):
	pObject.CallNextHandler(pEvent)

def SetContactEngineeringEnabled(bEnabled):
	pBridge = App.g_kSetManager.GetSet('bridge')
	pXO = App.CharacterClass_GetObject(pBridge, 'XO')
	pMenu = pXO.GetMenu()
	pDatabase = App.g_kLocalizationManager.Load('data/TGL/Bridge Menus.tgl')
	pButton = pMenu.GetButtonW(pDatabase.GetString('Contact Engineering'))
	if pButton:
		if bEnabled:
			pButton.SetEnabled()
		else:
			pButton.SetDisabled()

	App.g_kLocalizationManager.Unload(pDatabase)

def ShowLog(pObject, pEvent):
	pLog = App.STMissionLog_GetMissionLog()
	pTopWindow = App.TopWindow_GetTopWindow()
	App.g_kUtopiaModule.Pause(1)
	pWindow = App.STStylizedWindow_Cast(pLog.GetFirstChild())
	if pWindow != None:
		pWindow.ScrollToBottom()

	pTopWindow.MoveToFront(pLog)
	pLog.SetVisible()
	pTopWindow.SetFocus(pLog)
	pObject.CallNextHandler(pEvent)


import asyncio
import grpc
import logging
import time

from bidding_pb2 import (
    BidRequest,
    BidReply,
    HighestBidRequest,
    HighestBidReply,
    Bid,
    BidHistoryRequest,
    BidHistoryReply,
)
from bidding_pb2_grpc import (
    BiddingService,
    add_BiddingServiceServicer_to_server,
)
from tasks import place_bid
from query import QueryExecutor

class BiddingServer(BiddingService):

    async def PlaceBid(
        self,
        request: BidRequest,
        context: grpc.aio.ServicerContext,
    ) -> BidReply:
        logging.info("[PlaceBid] Serving request %s", request)
        bid_at = time.strftime('%Y-%m-%d %H:%M:%S')
        task = place_bid.s(
            request.auction_id, request.bidder_id, request.price, bid_at
        ).apply_async()
        result = task.get()
        return BidReply(
            message=f"[placeBid] Reply from celery-worker: {result}"
        )

    async def GetHighestBid(
        self,
        request: HighestBidRequest,
        context: grpc.aio.ServicerContext,
    ) -> HighestBidReply:
        logging.info("[GetHighestBid] Serving request %s", request)
        result = QueryExecutor.get_highest_bid(
            request.auction_ids_filter,
            request.read_from_leader,
        )
        bids = [
            Bid(
                bid_id=item.bid_id,
                auction_id=item.auction_id,
                bidder_id=item.bidder_id,
                bid_price=item.bid_price,
                bid_at=item.bid_at,
            ) for item in result
        ]
        return HighestBidReply(bids=bids)

    async def GetBidHistory(
        self,
        request: BidHistoryRequest,
        context: grpc.aio.ServicerContext,
    ) -> BidHistoryReply:
        logging.info("[GetBidHistory] Serving request %s", request)
        result = QueryExecutor.get_bid_history(
            request.auction_id_filter,
            request.next_bid_id,
            request.limit,
        )
        bids = [
            Bid(
                bid_id=item.bid_id,
                auction_id=item.auction_id,
                bidder_id=item.bidder_id,
                bid_price=item.bid_price,
                bid_at=item.bid_at,
            ) for item in result
        ]
        next_bid_id = (
            -1 if len(bids) < request.limit
            else bids[-1].bid_id + 1
        )
        return BidHistoryReply(bids=bids, next_bid_id=next_bid_id)

SERVER_PORT = 50051

async def serve() -> None:
    server = grpc.aio.server()
    add_BiddingServiceServicer_to_server(BiddingServer(), server)
    listen_addr = f"[::]:{SERVER_PORT}"
    server.add_insecure_port(listen_addr)
    logging.info("Starting server on %s", listen_addr)
    await server.start()
    await server.wait_for_termination()

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    asyncio.run(serve())


from django.views.generic import ListView
from .models import Menu, MenuItem

class MenuItemListView(ListView):
    model = Menu
    template_name = "templates/base.html"

class MenuByMenuItemView(ListView):
    context_object_name = 'menu_items'
    template_name = 'templates/menu.html'

    def get_queryset(self):
        self.menu_item = MenuItem.objects.get(slug=self.kwargs['slug'])
        self.menu_item_values = MenuItem.objects.filter(name=self.menu_item).values()
        self.menu_item_level = self.menu_item_values[0]['level']
        self.family = [str(x) for x in self.menu_item.get_family()]

        menu_name_id = self.menu_item_values[0]['menu_name_id']
        queryset = MenuItem.objects.filter(
            menu_name_id=menu_name_id,
        )
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['level'] = self.menu_item_level
        context['name'] = str(self.menu_item)
        context['family'] = self.family
        return context


"""
Faça um programa que leia um número inteiro
e diga se ele é ou não um número primo.
"""
num = input("Informe um número: ")

if num.isnumeric():
    num = int(num)
    count = 0

    for x in range(1, num+1):
        if num % x == 0:
            count += 1
            print(f"{x}", end=' - ')

    if count == 2:
        print(f"\nO número {num} é um número primo")
    else:
        print(f"\nO númerno {num} não é primo, ele é divisível {count} vezes")

else:
    print("Não é um número válido")


'''
This module defines backends, which are provider-specific functions,
returning url to user avatar by uid.
'''
import urllib2
import json

import gevent
from gevent.coros import Semaphore

from cache import enable_cache
from log import enable_logging

@enable_cache('twitter')
@enable_logging
def twitter(uid):
    ' Twitter backend '
    twi_data = urllib2.urlopen('http://api.twitter.com/1/users/show.json?user_id=%s' % uid).read()
    avatar = json.loads(twi_data).get('profile_image_url', None)
    return avatar

# There must be not more than 3 requests to vkontakte per second,
# that is why we use Semaphore and gevent.sleep
vkontakte_semaphore = Semaphore(1)

@enable_cache('vkontakte')
@enable_logging
def vkontakte(uid):
    ' Vkontakte backend '
    vkontakte_semaphore.acquire()
    try:
        vk_data = urllib2.urlopen('https://api.vkontakte.ru/method/getProfiles?uids=%s&fields=photo' % uid).read()
        avatar = json.loads(vk_data).get('response', [{}])[0]['photo']
        gevent.sleep(0.34)  # we shouldn't make more than 3 requests per second!
        return avatar
    finally:
        vkontakte_semaphore.release()

@enable_logging
def facebook(uid):
    ' Facebook backend '
    return 'http://graph.facebook.com/%s/picture' % uid


#!/usr/bin/env python
# Written by gpt-4, fixed by Deniz Yuret
# See https://huggingface.co/docs/datasets/load_hub for documentation

from datasets import list_datasets
import requests

# Get the list of datasets
dataset_list = list_datasets()
print(f"{len(dataset_list)} datasets:")

# Function to get the size of a dataset
def get_dataset_size(dataset_name):
    url = f"https://huggingface.co/datasets/{dataset_name}/resolve/main/dataset_infos.json"
    try:
        dataset_info = requests.get(url).json()
        dataset_info1 = next(iter(dataset_info.values()))
        #print(dataset_info)
        dataset_size = dataset_info1["download_size"]
        return dataset_size
    except:
        return 0

# Sort the datasets by size (in descending order)
# sorted_datasets = sorted(dataset_list, key=get_dataset_size, reverse=True)

# Print the sorted list of datasets with their sizes
for dataset in dataset_list:
    size = get_dataset_size(dataset)
    print(f"{size}\t{dataset}")